summaryrefslogtreecommitdiff
path: root/package/mac80211/patches/305-pending-ath9k-allow-to-load-EEPROM-content-via-firmware-API.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/mac80211/patches/305-pending-ath9k-allow-to-load-EEPROM-content-via-firmware-API.patch')
-rw-r--r--package/mac80211/patches/305-pending-ath9k-allow-to-load-EEPROM-content-via-firmware-API.patch184
1 files changed, 184 insertions, 0 deletions
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 <juhosg@openwrt.org>
+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 <juhosg@openwrt.org>
+---
+ 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 <linux/if_ether.h>
+ #include <linux/delay.h>
+ #include <linux/io.h>
++#include <linux/firmware.h>
+
+ #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;
+