From 2fd2cdfb6d2f3c3d18f2e47f41679a7bde9bcbf3 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 10 Dec 2012 15:30:25 +0100 Subject: ath9k: move duplicated debug message to 'ath9k_hw_nvram_read' The fill_eeprom functions are printing the same debug message in case the 'ath9k_hw_nvram_read' function fails. Remove the duplicated code from fill_eeprom functions and add the ath_dbg call directly into 'ath9k_hw_nvram_read'. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k/eeprom.c') diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 0512397a293c..4b6a9350adcf 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -115,7 +115,13 @@ void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data, bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data) { - return common->bus_ops->eeprom_read(common, off, data); + bool ret; + + ret = common->bus_ops->eeprom_read(common, off, data); + if (!ret) + ath_dbg(common, EEPROM, "Unable to read eeprom region\n"); + + return ret; } void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, -- cgit v1.2.3-55-g7522 From 7177d8f998c452701ad5352cca12408e26f80b07 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 10 Dec 2012 15:30:26 +0100 Subject: ath9k: add EEPROM offset to debug message Show the EEPROM offset of the failed read operation in 'ath9k_hw_nvram_read'. The debug message is more informative this way. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k/eeprom.c') diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 4b6a9350adcf..bf52ae1fdfff 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -119,7 +119,8 @@ bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data) ret = common->bus_ops->eeprom_read(common, off, data); if (!ret) - ath_dbg(common, EEPROM, "Unable to read eeprom region\n"); + ath_dbg(common, EEPROM, + "unable to read eeprom region at offset %u\n", off); return ret; } -- cgit v1.2.3-55-g7522 From 0e4b9f2f12e94686855605eda64ea534a95d77f2 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 10 Dec 2012 15:30:27 +0100 Subject: ath9k: use 'struct ath_hw *' as the first argument for 'ath9k_hw_nvram_read' The 'ath9k_hw_nvram_read' function takes a 'struct ath_common *' as its first argument. Almost each of its caller has a 'struct ath_hw *' parameter in their argument list, and that is dereferenced in order to get the 'struct ath_common' pointer. Change the first argument of 'ath9k_hw_nvram_read' to be a 'struct ath_hw *', and remove the dereference calls from the callers. Also change the type of the first argument of the ar9300_eeprom_read_{byte,word} functions. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 17 ++++++++--------- drivers/net/wireless/ath/ath9k/eeprom.c | 3 ++- drivers/net/wireless/ath/ath9k/eeprom.h | 2 +- drivers/net/wireless/ath/ath9k/eeprom_4k.c | 6 ++---- drivers/net/wireless/ath/ath9k/eeprom_9287.c | 6 ++---- drivers/net/wireless/ath/ath9k/eeprom_def.c | 5 ++--- 6 files changed, 17 insertions(+), 22 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k/eeprom.c') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 11082b417d24..562186ca9b52 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3001,24 +3001,24 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, } } -static bool ar9300_eeprom_read_byte(struct ath_common *common, int address, +static bool ar9300_eeprom_read_byte(struct ath_hw *ah, int address, u8 *buffer) { u16 val; - if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val))) + if (unlikely(!ath9k_hw_nvram_read(ah, address / 2, &val))) return false; *buffer = (val >> (8 * (address % 2))) & 0xff; return true; } -static bool ar9300_eeprom_read_word(struct ath_common *common, int address, +static bool ar9300_eeprom_read_word(struct ath_hw *ah, int address, u8 *buffer) { u16 val; - if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val))) + if (unlikely(!ath9k_hw_nvram_read(ah, address / 2, &val))) return false; buffer[0] = val >> 8; @@ -3044,14 +3044,14 @@ static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer, * the 16-bit word at that address */ if (address % 2 == 0) { - if (!ar9300_eeprom_read_byte(common, address--, buffer++)) + if (!ar9300_eeprom_read_byte(ah, address--, buffer++)) goto error; count--; } for (i = 0; i < count / 2; i++) { - if (!ar9300_eeprom_read_word(common, address, buffer)) + if (!ar9300_eeprom_read_word(ah, address, buffer)) goto error; address -= 2; @@ -3059,7 +3059,7 @@ static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer, } if (count % 2) - if (!ar9300_eeprom_read_byte(common, address, buffer)) + if (!ar9300_eeprom_read_byte(ah, address, buffer)) goto error; return true; @@ -3236,12 +3236,11 @@ static bool ar9300_check_eeprom_header(struct ath_hw *ah, eeprom_read_op read, static int ar9300_eeprom_restore_flash(struct ath_hw *ah, u8 *mptr, int mdata_size) { - struct ath_common *common = ath9k_hw_common(ah); u16 *data = (u16 *) mptr; int i; for (i = 0; i < mdata_size / 2; i++, data++) - ath9k_hw_nvram_read(common, i, data); + ath9k_hw_nvram_read(ah, i, data); return 0; } diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index bf52ae1fdfff..eb9ac5ea6180 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -113,8 +113,9 @@ void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data, } } -bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data) +bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) { + struct ath_common *common = ath9k_hw_common(ah); bool ret; ret = common->bus_ops->eeprom_read(common, off, data); diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 319c651fa6c5..40d4f62d0f16 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -663,7 +663,7 @@ int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, int16_t targetRight); bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, u16 *indexL, u16 *indexR); -bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data); +bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data); void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data, int eep_start_loc, int size); void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 17c843d37210..c2bfd748eed8 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -32,13 +32,11 @@ static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) static bool __ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) { - struct ath_common *common = ath9k_hw_common(ah); u16 *eep_data = (u16 *)&ah->eeprom.map4k; int addr, eep_start_loc = 64; for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { - if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, - eep_data)) + if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) return false; eep_data++; } @@ -194,7 +192,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) if (!ath9k_hw_use_flash(ah)) { - if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, + if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { ath_err(common, "Reading Magic # failed\n"); return false; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index f2c32bc36f1c..3ae1f3df0637 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -33,14 +33,12 @@ static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah) static bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) { struct ar9287_eeprom *eep = &ah->eeprom.map9287; - struct ath_common *common = ath9k_hw_common(ah); u16 *eep_data; int addr, eep_start_loc = AR9287_EEP_START_LOC; eep_data = (u16 *)eep; for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) { - if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, - eep_data)) + if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) return false; eep_data++; } @@ -187,7 +185,7 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); if (!ath9k_hw_use_flash(ah)) { - if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, + if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { ath_err(common, "Reading Magic # failed\n"); return false; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 2654f741b8bf..1c25368b3836 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -91,12 +91,11 @@ static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) static bool __ath9k_hw_def_fill_eeprom(struct ath_hw *ah) { - struct ath_common *common = ath9k_hw_common(ah); u16 *eep_data = (u16 *)&ah->eeprom.def; int addr, ar5416_eep_start_loc = 0x100; for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { - if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc, + if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc, eep_data)) return false; eep_data++; @@ -268,7 +267,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) bool need_swap = false; int i, addr, size; - if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { + if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { ath_err(common, "Reading Magic # failed\n"); return false; } -- cgit v1.2.3-55-g7522 From ab5c4f71d8c7add173a2d32e5beefdaaf1b7cbbc Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 10 Dec 2012 15:30:28 +0100 Subject: ath9k: allow to load EEPROM content via firmware API The calibration data for devices w/o a separate EEPROM chip can be specified via the 'eeprom_data' field of 'ath9k_platform_data'. The 'eeprom_data' is usually filled from board specific setup functions. It is easy if the EEPROM data is mapped to the memory, but it can be complicated if it is stored elsewhere. The patch adds support for loading of the EEPROM data via the firmware API to avoid this limitation. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/eeprom.c | 19 ++++++++++- drivers/net/wireless/ath/ath9k/hw.h | 3 ++ drivers/net/wireless/ath/ath9k/init.c | 60 ++++++++++++++++++++++++++++++++- include/linux/ath9k_platform.h | 2 ++ 4 files changed, 82 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k/eeprom.c') diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index eb9ac5ea6180..971d770722cf 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -113,12 +113,29 @@ void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data, } } +static bool ath9k_hw_nvram_read_blob(struct ath_hw *ah, u32 off, + u16 *data) +{ + u16 *blob_data; + + if (off * sizeof(u16) > ah->eeprom_blob->size) + return false; + + blob_data = (u16 *)ah->eeprom_blob->data; + *data = blob_data[off]; + return true; +} + bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) { struct ath_common *common = ath9k_hw_common(ah); bool ret; - ret = common->bus_ops->eeprom_read(common, off, data); + if (ah->eeprom_blob) + ret = ath9k_hw_nvram_read_blob(ah, off, data); + else + ret = common->bus_ops->eeprom_read(common, off, data); + if (!ret) ath_dbg(common, EEPROM, "unable to read eeprom region at offset %u\n", off); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index eff67592db18..7f1a8e91c908 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "mac.h" #include "ani.h" @@ -921,6 +922,8 @@ struct ath_hw { bool is_clk_25mhz; int (*get_mac_revision)(void); int (*external_reset)(void); + + const struct firmware *eeprom_blob; }; struct ath_bus_ops { diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 80cae53a33e5..27703a5e48d6 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -23,6 +23,11 @@ #include "ath9k.h" +struct ath9k_eeprom_ctx { + struct completion complete; + struct ath_hw *ah; +}; + static char *dev_info = "ath9k"; MODULE_AUTHOR("Atheros Communications"); @@ -506,6 +511,51 @@ static void ath9k_init_misc(struct ath_softc *sc) sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; } +static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob, + void *ctx) +{ + struct ath9k_eeprom_ctx *ec = ctx; + + if (eeprom_blob) + ec->ah->eeprom_blob = eeprom_blob; + + complete(&ec->complete); +} + +static int ath9k_eeprom_request(struct ath_softc *sc, const char *name) +{ + struct ath9k_eeprom_ctx ec; + struct ath_hw *ah = ah = sc->sc_ah; + int err; + + /* try to load the EEPROM content asynchronously */ + init_completion(&ec.complete); + ec.ah = sc->sc_ah; + + err = request_firmware_nowait(THIS_MODULE, 1, name, sc->dev, GFP_KERNEL, + &ec, ath9k_eeprom_request_cb); + if (err < 0) { + ath_err(ath9k_hw_common(ah), + "EEPROM request failed\n"); + return err; + } + + wait_for_completion(&ec.complete); + + if (!ah->eeprom_blob) { + ath_err(ath9k_hw_common(ah), + "Unable to load EEPROM file %s\n", name); + return -EINVAL; + } + + return 0; +} + +static void ath9k_eeprom_release(struct ath_softc *sc) +{ + release_firmware(sc->sc_ah->eeprom_blob); +} + static int ath9k_init_softc(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { @@ -583,6 +633,12 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, ath_read_cachesize(common, &csz); common->cachelsz = csz << 2; /* convert to bytes */ + if (pdata->eeprom_name) { + ret = ath9k_eeprom_request(sc, pdata->eeprom_name); + if (ret) + goto err_eeprom; + } + /* Initializes the hardware for all supported chipsets */ ret = ath9k_hw_init(ah); if (ret) @@ -619,7 +675,8 @@ err_btcoex: err_queues: ath9k_hw_deinit(ah); err_hw: - + ath9k_eeprom_release(sc); +err_eeprom: kfree(ah); sc->sc_ah = NULL; @@ -882,6 +939,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc) if (sc->dfs_detector != NULL) sc->dfs_detector->exit(sc->dfs_detector); + ath9k_eeprom_release(sc); kfree(sc->sc_ah); sc->sc_ah = NULL; } diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h index 6e3f54f37844..fcdd81bd5314 100644 --- a/include/linux/ath9k_platform.h +++ b/include/linux/ath9k_platform.h @@ -22,6 +22,8 @@ #define ATH9K_PLAT_EEP_MAX_WORDS 2048 struct ath9k_platform_data { + const char *eeprom_name; + u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS]; u8 *macaddr; -- cgit v1.2.3-55-g7522