2019-06-02 10:22:23

by Christian Lamparter

[permalink] [raw]
Subject: [RFC PATCH] ath9k: integrate AR92XX pci fixup code

Some devices (like the Cisco Meraki Z1 Cloud Managed Teleworker Gateway)
need to be able to initialize the PCIe wifi device. Normally, this is done
during the early stages of booting linux, because the necessary init code
is read from the memory mapped SPI and passed to pci_enable_ath9k_fixup.
However, this isn't possible for devices which have the init code for the
Atheros chip stored on NAND in an UBI volume. Hence, this module can be
used to initialize the chip when the user-space is ready to extract the
init code.

Martin Blumenstingl prodived the following fixes:
owl-loader: add support for OWL emulation PCI devices
owl-loader: don't re-scan the bus when ath9k_pci_fixup failed
owl-loader: use dev_* instead of pr_* logging functions
owl-loader: auto-generate the eeprom filename as fallback
owl-loader: add a debug message when swapping the eeprom data
owl-loader: add missing newlines in log messages

Signed-off-by: Christian Lamparter <[email protected]>
Signed-off-by: Martin Blumenstingl <[email protected]>
---
drivers/net/wireless/ath/ath9k/Kconfig | 15 ++
drivers/net/wireless/ath/ath9k/ath9k.h | 1 +
drivers/net/wireless/ath/ath9k/pci.c | 252 ++++++++++++++++++++++++-
3 files changed, 266 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index a1ef8769983a..25b791389816 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -157,6 +157,21 @@ config ATH9K_PCOEM
depends on ATH9K
default y

+config ATH9K_PCI_NO_EEPROM
+ bool "Atheros ath9k support for EEPROM-less chips"
+ depends on ATH9K_PCI
+ default n
+ help
+ Say Y to support AR92XX-generation of ath9k PCI(e) WiFi chips, which
+ have their initialization data (which contains the PCI Device ID!)
+ stored together with the calibration data out of reach for the ath9k
+ chip.
+
+ These devices are usually various network appliances, routers or
+ access Points and such.
+
+ If unsure say N.
+
config ATH9K_HTC
tristate "Atheros HTC based wireless cards support"
depends on USB && MAC80211
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index a412b352182c..ec649446421b 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -959,6 +959,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
#define ATH9K_PCI_NO_PLL_PWRSAVE 0x0200
#define ATH9K_PCI_KILLER 0x0400
#define ATH9K_PCI_LED_ACT_HI 0x0800
+#define ATH9K_PCI_NO_EEPROM 0x1000

/*
* Default cache line size, in bytes.
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 92b2dd396436..53a16e961055 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -19,7 +19,11 @@
#include <linux/nl80211.h>
#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/completion.h>
+#include <linux/ath9k_platform.h>
#include "ath9k.h"
+#include "eeprom.h"

extern int ath9k_use_msi;

@@ -774,6 +778,17 @@ static const struct pci_device_id ath_pci_id_table[] = {
.driver_data = ATH9K_PCI_BT_ANT_DIV },
#endif

+#ifdef CONFIG_ATH9K_PCI_NO_EEPROM
+ /* If a physical EEPROM or OTP is not used (such as for an integrated
+ * access point), the device responds to bus probing with default
+ * hardware deviceID and subvendorDeviceID information.
+ */
+ { PCI_VDEVICE(ATHEROS, 0xff1c),
+ .driver_data = ATH9K_PCI_NO_EEPROM }, /* PCIe */
+ { PCI_VDEVICE(ATHEROS, 0xff1d),
+ .driver_data = ATH9K_PCI_NO_EEPROM }, /* PCI */
+#endif /* CONFIG_ATH9K_PCI_NO_EEPROM */
+
{ 0 }
};

@@ -882,6 +897,228 @@ static const struct ath_bus_ops ath_pci_bus_ops = {
.aspm_init = ath_pci_aspm_init,
};

+#ifdef CONFIG_ATH9K_PCI_NO_EEPROM
+
+struct ath_pci_fixup_ctx {
+ struct completion eeprom_load;
+};
+
+#define EEPROM_FILENAME_LEN 100
+/* AR5416_EEPROM_MAGIC changes depending on target endian */
+#define ATH_PCI_FIXUP_MAGIC 0xa55a
+
+static int ath_pci_fixup(struct pci_dev *pdev, const u16 *cal_data,
+ size_t cal_len)
+{
+ void __iomem *mem;
+ const void *cal_end = (void *)cal_data + cal_len;
+ const struct {
+ u16 reg;
+ u16 low_val;
+ u16 high_val;
+ } __packed * data;
+ u16 cmd;
+ u32 bar0;
+ bool swap_needed = false;
+
+ if (*cal_data != ATH_PCI_FIXUP_MAGIC) {
+ if (*cal_data != swab16(ATH_PCI_FIXUP_MAGIC)) {
+ dev_err(&pdev->dev, "invalid calibration data\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(&pdev->dev, "calibration data needs swapping\n");
+ swap_needed = true;
+ }
+
+ dev_info(&pdev->dev, "fixup device configuration\n");
+
+ mem = pcim_iomap(pdev, 0, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "ioremap error\n");
+ return -EINVAL;
+ }
+
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &bar0);
+ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0,
+ pci_resource_start(pdev, 0));
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+
+ /* set pointer to first reg address */
+ for (data = (const void *)(cal_data + 3);
+ (const void *)data <= cal_end && data->reg != (u16)~0;
+ data++) {
+ u32 val;
+ u16 reg;
+
+ reg = data->reg;
+ val = data->low_val;
+ val |= ((u32)data->high_val) << 16;
+
+ if (swap_needed) {
+ reg = swab16(reg);
+ val = swahb32(val);
+ }
+
+ __raw_writel(val, mem + reg);
+ usleep_range(100, 120);
+ }
+
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+
+ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, bar0);
+ pcim_iounmap(pdev, mem);
+
+ pci_disable_device(pdev);
+
+ return 0;
+}
+
+static void ath_pci_fixup_fw_cb(const struct firmware *fw, void *context)
+{
+ struct pci_dev *pdev = (struct pci_dev *)context;
+ struct ath_pci_fixup_ctx *ctx;
+ struct ath9k_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct pci_bus *bus;
+
+ ctx = (struct ath_pci_fixup_ctx *)pci_get_drvdata(pdev);
+ complete(&ctx->eeprom_load);
+
+ if (!fw) {
+ dev_err(&pdev->dev, "no eeprom data received.\n");
+ goto release;
+ }
+
+ /* also note that we are doing *u16 operations on the file */
+ if (fw->size > sizeof(pdata->eeprom_data) || fw->size < 0x200 ||
+ (fw->size & 1) == 1) {
+ dev_err(&pdev->dev, "eeprom file has an invalid size.\n");
+ goto release;
+ }
+
+ if (pdata) {
+ memcpy(pdata->eeprom_data, fw->data, fw->size);
+
+ /* eeprom has been successfully loaded - pass the data to ath9k
+ * but remove the eeprom_name, so it doesn't try to load it too.
+ */
+ pdata->eeprom_name = NULL;
+ }
+
+ if (ath_pci_fixup(pdev, (const u16 *)fw->data, fw->size))
+ goto release;
+
+ pci_lock_rescan_remove();
+ bus = pdev->bus;
+ pci_stop_and_remove_bus_device(pdev);
+ /* the device should come back with the proper
+ * ProductId. But we have to initiate a rescan.
+ */
+ pci_rescan_bus(bus);
+ pci_unlock_rescan_remove();
+
+release:
+ release_firmware(fw);
+}
+
+static const char *ath_pci_fixup_get_eeprom_name(struct pci_dev *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ath9k_platform_data *pdata;
+ char *eeprom_name;
+
+ /* try the existing platform data first */
+ pdata = dev_get_platdata(dev);
+ if (pdata && pdata->eeprom_name)
+ return pdata->eeprom_name;
+
+ dev_dbg(dev, "using auto-generated eeprom filename\n");
+
+ eeprom_name = devm_kzalloc(dev, EEPROM_FILENAME_LEN, GFP_KERNEL);
+ if (!eeprom_name)
+ return NULL;
+
+ /* this should match the pattern used in init.c */
+ scnprintf(eeprom_name, EEPROM_FILENAME_LEN, "ath9k-eeprom-pci-%s.bin",
+ dev_name(dev));
+
+ return eeprom_name;
+}
+
+static int ath_pci_fixup_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct ath_pci_fixup_ctx *ctx;
+ const char *eeprom_name;
+ int err = 0;
+
+ /* only handle devices that do not have a support EEPROM */
+ if (!(id->driver_data & ATH9K_PCI_NO_EEPROM))
+ return 0;
+
+ pcim_pin_device(pdev);
+
+ eeprom_name = ath_pci_fixup_get_eeprom_name(pdev);
+ if (!eeprom_name) {
+ dev_err(&pdev->dev, "no eeprom filename found.\n");
+ return -ENODEV;
+ }
+
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ init_completion(&ctx->eeprom_load);
+
+ pci_set_drvdata(pdev, ctx);
+ err = request_firmware_nowait(THIS_MODULE, true, eeprom_name,
+ &pdev->dev, GFP_KERNEL, pdev,
+ ath_pci_fixup_fw_cb);
+ if (err)
+ dev_err(&pdev->dev, "failed to request caldata (%d).\n", err);
+
+ /* Use the return code "1" as a way to tell the ath_pci_probe()
+ * function that we will be taking an alternative code-path from
+ * now on. Once the device has the proper ProductIDs it will
+ * go through ath_pci_probe() again.
+ */
+ return err < 0 ? err : 1;
+}
+
+static bool ath_pci_fixup_remove(struct pci_dev *pdev)
+{
+ const struct pci_device_id *id;
+ struct ath_pci_fixup_ctx *ctx;
+
+ id = pci_match_id(ath_pci_id_table, pdev);
+ if (!id || !(id->driver_data & ATH9K_PCI_NO_EEPROM))
+ return false;
+
+ ctx = pci_get_drvdata(pdev);
+ if (ctx) {
+ wait_for_completion(&ctx->eeprom_load);
+ pci_set_drvdata(pdev, NULL);
+ }
+
+ return true;
+}
+#else
+static int ath_pci_fixup_probe(struct pci_dev __maybe_unused *pdev,
+ const struct pci_device_id __maybe_unused *id)
+{
+ return 0;
+}
+
+static bool ath_pci_fixup_remove(struct pci_dev __maybe_unused *pdev)
+{
+ return false;
+}
+#endif /* CONFIG_ATH9K_PCI_NO_EEPROM */
+
static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct ath_softc *sc;
@@ -895,6 +1132,12 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (pcim_enable_device(pdev))
return -EIO;

+ ret = ath_pci_fixup_probe(pdev, id);
+ if (ret < 0)
+ return ret;
+ if (ret == 1)
+ return 0; /* ath_pci_fixup_probe took over */
+
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (ret) {
pr_err("32-bit DMA not available\n");
@@ -1007,9 +1250,14 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)

static void ath_pci_remove(struct pci_dev *pdev)
{
- struct ieee80211_hw *hw = pci_get_drvdata(pdev);
- struct ath_softc *sc = hw->priv;
+ struct ieee80211_hw *hw;
+ struct ath_softc *sc;

+ if (ath_pci_fixup_remove(pdev))
+ return;
+
+ hw = pci_get_drvdata(pdev);
+ sc = hw->priv;
if (!is_ath9k_unloaded)
sc->sc_ah->ah_flags |= AH_UNPLUGGED;
ath9k_deinit_device(sc);
--
2.20.1


2019-06-02 11:47:11

by Julian Calaby

[permalink] [raw]
Subject: Re: [RFC PATCH] ath9k: integrate AR92XX pci fixup code

Hi Christian,

On Sun, Jun 2, 2019 at 8:24 PM Christian Lamparter <[email protected]> wrote:
>
> Some devices (like the Cisco Meraki Z1 Cloud Managed Teleworker Gateway)
> need to be able to initialize the PCIe wifi device. Normally, this is done
> during the early stages of booting linux, because the necessary init code
> is read from the memory mapped SPI and passed to pci_enable_ath9k_fixup.
> However, this isn't possible for devices which have the init code for the
> Atheros chip stored on NAND in an UBI volume. Hence, this module can be
> used to initialize the chip when the user-space is ready to extract the
> init code.
>
> Martin Blumenstingl prodived the following fixes:
> owl-loader: add support for OWL emulation PCI devices
> owl-loader: don't re-scan the bus when ath9k_pci_fixup failed
> owl-loader: use dev_* instead of pr_* logging functions
> owl-loader: auto-generate the eeprom filename as fallback
> owl-loader: add a debug message when swapping the eeprom data
> owl-loader: add missing newlines in log messages
>
> Signed-off-by: Christian Lamparter <[email protected]>
> Signed-off-by: Martin Blumenstingl <[email protected]>

Two questions:

1. This seems complicated enough that the functions introduced should
probably go into a separate .c file, maybe "noeeprom.c", with a header
file with all the ifdef / config magic in it.
2. This smells almost like a completely separate PCI(e) driver for
cards in a "weird" state. Is there anything you're using from ath9k
other than the eeprom file naming? and is that really useful? Won't
the eeprom files be device specific and therefore could always use the
device name fallback?

Thanks,

--
Julian Calaby

Email: [email protected]
Profile: http://www.google.com/profiles/julian.calaby/

2019-06-02 13:19:48

by Christian Lamparter

[permalink] [raw]
Subject: Re: [RFC PATCH] ath9k: integrate AR92XX pci fixup code

Hello Julian,

On Sunday, June 2, 2019 1:43:52 PM CEST Julian Calaby wrote:
> On Sun, Jun 2, 2019 at 8:24 PM Christian Lamparter <[email protected]> wrote:
> >
> > Some devices (like the Cisco Meraki Z1 Cloud Managed Teleworker Gateway)
> > need to be able to initialize the PCIe wifi device. Normally, this is done
> > during the early stages of booting linux, because the necessary init code
> > is read from the memory mapped SPI and passed to pci_enable_ath9k_fixup.
> > However, this isn't possible for devices which have the init code for the
> > Atheros chip stored on NAND in an UBI volume. Hence, this module can be
> > used to initialize the chip when the user-space is ready to extract the
> > init code.
> >
> > Martin Blumenstingl prodived the following fixes:
> > owl-loader: add support for OWL emulation PCI devices
> > owl-loader: don't re-scan the bus when ath9k_pci_fixup failed
> > owl-loader: use dev_* instead of pr_* logging functions
> > owl-loader: auto-generate the eeprom filename as fallback
> > owl-loader: add a debug message when swapping the eeprom data
> > owl-loader: add missing newlines in log messages
> >
> > Signed-off-by: Christian Lamparter <[email protected]>
> > Signed-off-by: Martin Blumenstingl <[email protected]>
>
> Two questions:
>
> 1. This seems complicated enough that the functions introduced should
> probably go into a separate .c file, maybe "noeeprom.c", with a header
> file with all the ifdef / config magic in it.

In openwrt we called it owl-loader.c and it's a separate module there.
But I don't think that noeeprom.c is that great since ath9k also supports
AHB and htc_usb, so from this perspective it would mean:
pci_init_noeeprom.c ? (As AR5008, AR9160 and AR92XX seem to be affected).

> 2. This smells almost like a completely separate PCI(e) driver for
> cards in a "weird" state.
It's in the Datasheet that the device initializes into this state. See
AR9280 6.1.2 DEVICE_ID. "... if the EEPROM content is not valid, a
value of 0XFF1C returns when read from the register". This would also
mean that this routine can be used to resurrect aging AR9280 cards
that have a failed eeprom or are from APPLE, see this thread:

<https://www.mail-archive.com/[email protected]/msg03918.html>

"does anyone know whether 168c:ff1c can be supported by the current ath9k
driver? It isn't listed with the PCI IDs in the source. I bought it off
eBay as "Apple" AR5008. It is a PCI Express card with 3 Antenna
connectors and lots of Apple stampings on it. lspci says:"

> Is there anything you're using from ath9k
> other than the eeprom file naming? and is that really useful? Won't
> the eeprom files be device specific and therefore could always use the
> device name fallback?
Please take a look at the commit message. Unfortunately the Z1 stores
its calibration data in a ubi volume, these can't be easily read
without interfacing with either ubi or the vfs. In the future, simpler
devices that have it on SPI-NOR in a mtd partition can setup a nvmem
provider and the code can have a nvmem-consumer. (see attached patch).

Note: There are also devices with mutliple ath9k pci(e) chips
(usually one 2.4Ghz and one 5GHz), so a generic "ath9k" name is too
short and the pciids of both are the same. That's why the pci-bus
location is currently used for the eeprom name identifier.

Regards,
Christian

---

Note: nvmem dts is not finalized. See

commit 517f14d9cf3533d5ab4fded195ab6f80a92e378f
Author: Bartosz Golaszewski <[email protected]>
Date: Fri Nov 30 11:53:25 2018 +0000

nvmem: add new config option

for details why adding something like this unfinished patch
just does not makes sense (yet).

--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -21,6 +21,7 @@
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/completion.h>
+#include <linux/nvmem-consumer.h>
#include <linux/ath9k_platform.h>
#include "ath9k.h"
#include "eeprom.h"
@@ -1053,6 +1054,7 @@ static int ath_pci_fixup_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct ath_pci_fixup_ctx *ctx;
+ struct nvmem_cell *cell;
const char *eeprom_name;
int err = 0;

@@ -1062,6 +1064,21 @@ static int ath_pci_fixup_probe(struct pci_dev *pdev,

pcim_pin_device(pdev);

+ cell = nvmem_cell_get(&pdev->dev, "caldata");
+ if (!IS_ERR(cell)) {
+ void *value;
+ size_t len;
+
+ value = nvmem_cell_read(cell, &len);
+ if (!IS_ERR(value)) {
+ err = ath_pci_fixup(pdev, value, len);
+ kfree(value);
+ } else
+ err = -EINVAL;
+ nvmem_cell_put(cell);
+ return err;
+ }
+
eeprom_name = ath_pci_fixup_get_eeprom_name(pdev);
if (!eeprom_name) {
dev_err(&pdev->dev, "no eeprom filename found.\n");




2019-06-02 14:13:47

by Julian Calaby

[permalink] [raw]
Subject: Re: [RFC PATCH] ath9k: integrate AR92XX pci fixup code

Hi Christian,

On Sun, Jun 2, 2019 at 11:14 PM Christian Lamparter <[email protected]> wrote:
>
> Hello Julian,
>
> On Sunday, June 2, 2019 1:43:52 PM CEST Julian Calaby wrote:
> > On Sun, Jun 2, 2019 at 8:24 PM Christian Lamparter <[email protected]> wrote:
> > >
> > > Some devices (like the Cisco Meraki Z1 Cloud Managed Teleworker Gateway)
> > > need to be able to initialize the PCIe wifi device. Normally, this is done
> > > during the early stages of booting linux, because the necessary init code
> > > is read from the memory mapped SPI and passed to pci_enable_ath9k_fixup.
> > > However, this isn't possible for devices which have the init code for the
> > > Atheros chip stored on NAND in an UBI volume. Hence, this module can be
> > > used to initialize the chip when the user-space is ready to extract the
> > > init code.
> > >
> > > Martin Blumenstingl prodived the following fixes:
> > > owl-loader: add support for OWL emulation PCI devices
> > > owl-loader: don't re-scan the bus when ath9k_pci_fixup failed
> > > owl-loader: use dev_* instead of pr_* logging functions
> > > owl-loader: auto-generate the eeprom filename as fallback
> > > owl-loader: add a debug message when swapping the eeprom data
> > > owl-loader: add missing newlines in log messages
> > >
> > > Signed-off-by: Christian Lamparter <[email protected]>
> > > Signed-off-by: Martin Blumenstingl <[email protected]>
> >
> > Two questions:
> >
> > 1. This seems complicated enough that the functions introduced should
> > probably go into a separate .c file, maybe "noeeprom.c", with a header
> > file with all the ifdef / config magic in it.
>
> In openwrt we called it owl-loader.c and it's a separate module there.
> But I don't think that noeeprom.c is that great since ath9k also supports
> AHB and htc_usb, so from this perspective it would mean:
> pci_init_noeeprom.c ? (As AR5008, AR9160 and AR92XX seem to be affected).

Fair enough, I hadn't thought of the other buses.

> > 2. This smells almost like a completely separate PCI(e) driver for
> > cards in a "weird" state.
> It's in the Datasheet that the device initializes into this state. See
> AR9280 6.1.2 DEVICE_ID. "... if the EEPROM content is not valid, a
> value of 0XFF1C returns when read from the register". This would also
> mean that this routine can be used to resurrect aging AR9280 cards
> that have a failed eeprom or are from APPLE, see this thread:
>
> <https://www.mail-archive.com/[email protected]/msg03918.html>
>
> "does anyone know whether 168c:ff1c can be supported by the current ath9k
> driver? It isn't listed with the PCI IDs in the source. I bought it off
> eBay as "Apple" AR5008. It is a PCI Express card with 3 Antenna
> connectors and lots of Apple stampings on it. lspci says:"

I'm asking because (I think) Ath3k Bluetooth devices initialise with
one device ID when they don't have firmware, then initialise with a
different one once they do. These two states are handled using
different drivers. This seems like almost identical behaviour and
looks like it could be handled the same way. The code here looks like
it's just using the common boilerplate pci device initialisation code
from ath9k before doing it's own completely separate thing including
having PCI driver data in a different format to the rest of the ath9k
driver.

> > Is there anything you're using from ath9k
> > other than the eeprom file naming? and is that really useful? Won't
> > the eeprom files be device specific and therefore could always use the
> > device name fallback?
> Please take a look at the commit message. Unfortunately the Z1 stores
> its calibration data in a ubi volume, these can't be easily read
> without interfacing with either ubi or the vfs. In the future, simpler
> devices that have it on SPI-NOR in a mtd partition can setup a nvmem
> provider and the code can have a nvmem-consumer. (see attached patch).

Fair enough, I was reading the code as-is, not looking forward to
other possibilities.

> Note: There are also devices with mutliple ath9k pci(e) chips
> (usually one 2.4Ghz and one 5GHz), so a generic "ath9k" name is too
> short and the pciids of both are the same. That's why the pci-bus
> location is currently used for the eeprom name identifier.

I've finally worked out what was bothering me about the code: you look
at the platform data expecting it to be in the ath9k_platform_data
structure, however as far as I can tell, the platform data is only
ever set by reading the eeprom, which doesn't happen when there isn't
one, therefore the eeprom name retrieval will always fall back to
dev_name(). I'm assuming that dev_name() returns something
sufficiently unique to identify multiple different cards in a system.

Thanks,

--
Julian Calaby

Email: [email protected]
Profile: http://www.google.com/profiles/julian.calaby/