From 23fe7d4e4f141228f550ebb73d9f206f2207bdfe Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 10 Dec 2012 15:46:15 +0000 Subject: mac80211: ath9k: allow to load EEPROM data via firmware API Signed-off-by: Gabor Juhos git-svn-id: svn://svn.openwrt.org/openwrt/trunk@34606 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- ...w-to-load-EEPROM-content-via-firmware-API.patch | 184 +++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 package/mac80211/patches/305-pending-ath9k-allow-to-load-EEPROM-content-via-firmware-API.patch (limited to 'package/mac80211/patches/305-pending-ath9k-allow-to-load-EEPROM-content-via-firmware-API.patch') diff --git a/package/mac80211/patches/305-pending-ath9k-allow-to-load-EEPROM-content-via-firmware-API.patch b/package/mac80211/patches/305-pending-ath9k-allow-to-load-EEPROM-content-via-firmware-API.patch new file mode 100644 index 0000000000..78efdc4e37 --- /dev/null +++ b/package/mac80211/patches/305-pending-ath9k-allow-to-load-EEPROM-content-via-firmware-API.patch @@ -0,0 +1,184 @@ +From ee4581f2f024c601a5e247ec6acab3e7df538f88 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 9 Dec 2012 17:31:54 +0100 +Subject: [PATCH 4/4] 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 +--- + 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(-) + +--- 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 + } + } + ++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); +--- 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" +@@ -920,6 +921,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 { +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -25,6 +25,11 @@ + + #include "ath9k.h" + ++struct ath9k_eeprom_ctx { ++ struct completion complete; ++ struct ath_hw *ah; ++}; ++ + static char *dev_info = "ath9k"; + + MODULE_AUTHOR("Atheros Communications"); +@@ -508,6 +513,51 @@ static void ath9k_init_misc(struct ath_s + 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) + { +@@ -585,6 +635,12 @@ static int ath9k_init_softc(u16 devid, s + 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) +@@ -621,7 +677,8 @@ err_btcoex: + err_queues: + ath9k_hw_deinit(ah); + err_hw: +- ++ ath9k_eeprom_release(sc); ++err_eeprom: + kfree(ah); + sc->sc_ah = NULL; + +@@ -884,6 +941,7 @@ static void ath9k_deinit_softc(struct at + if (sc->dfs_detector != NULL) + sc->dfs_detector->exit(sc->dfs_detector); + ++ ath9k_eeprom_release(sc); + kfree(sc->sc_ah); + sc->sc_ah = NULL; + } +--- 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