--- /dev/null
+From cd3d888d569f5908c4345f7c99018f574c80a32b Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 9 Dec 2012 14:58:56 +0100
+Subject: [PATCH 1/4] 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 <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ath/ath9k/eeprom.c | 8 +++++++-
+ drivers/net/wireless/ath/ath9k/eeprom_4k.c | 6 ++----
+ drivers/net/wireless/ath/ath9k/eeprom_9287.c | 5 +----
+ drivers/net/wireless/ath/ath9k/eeprom_def.c | 5 +----
+ 4 files changed, 11 insertions(+), 13 deletions(-)
+
+--- 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
+
+ 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,
+--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+@@ -37,11 +37,9 @@ static bool __ath9k_hw_4k_fill_eeprom(st
+ 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)) {
+- ath_dbg(common, EEPROM,
+- "Unable to read eeprom region\n");
++ if (!ath9k_hw_nvram_read(common, addr + eep_start_loc,
++ eep_data))
+ return false;
+- }
+ eep_data++;
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -40,11 +40,8 @@ static bool __ath9k_hw_ar9287_fill_eepro
+
+ for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
+ if (!ath9k_hw_nvram_read(common, addr + eep_start_loc,
+- eep_data)) {
+- ath_dbg(common, EEPROM,
+- "Unable to read eeprom region\n");
++ eep_data))
+ return false;
+- }
+ eep_data++;
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
+@@ -97,11 +97,8 @@ static bool __ath9k_hw_def_fill_eeprom(s
+
+ for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
+ if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc,
+- eep_data)) {
+- ath_err(ath9k_hw_common(ah),
+- "Unable to read eeprom region\n");
++ eep_data))
+ return false;
+- }
+ eep_data++;
+ }
+ return true;
--- /dev/null
+From 910b74fb0e0369b18aa689ab02c9413235c18f98 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 9 Dec 2012 16:47:35 +0100
+Subject: [PATCH 2/4] 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 <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ath/ath9k/eeprom.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- 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_comm
+
+ 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;
+ }
--- /dev/null
+From 26c22324cca2db37fa294156fd875100d95438f4 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 9 Dec 2012 15:19:01 +0100
+Subject: [PATCH 3/4] 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 <juhosg@openwrt.org>
+---
+ 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(-)
+
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -3005,24 +3005,24 @@ static u32 ath9k_hw_ar9300_get_eeprom(st
+ }
+ }
+
+-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;
+@@ -3048,14 +3048,14 @@ static bool ar9300_read_eeprom(struct at
+ * 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;
+@@ -3063,7 +3063,7 @@ static bool ar9300_read_eeprom(struct at
+ }
+
+ if (count % 2)
+- if (!ar9300_eeprom_read_byte(common, address, buffer))
++ if (!ar9300_eeprom_read_byte(ah, address, buffer))
+ goto error;
+
+ return true;
+@@ -3240,12 +3240,11 @@ static bool ar9300_check_eeprom_header(s
+ 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;
+ }
+--- 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
+ }
+ }
+
+-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);
+--- 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,
+ 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,
+--- 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(st
+
+ 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(stru
+
+
+ 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;
+--- 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_re
+ 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_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;
+--- 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(s
+
+ 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(str
+ 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;
+ }
--- /dev/null
+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;
+
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -40,7 +40,7 @@ int ath9k_modparam_nohwcrypt;
+@@ -45,7 +45,7 @@ int ath9k_modparam_nohwcrypt;
module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -678,6 +678,7 @@ static const struct ieee80211_iface_limi
+@@ -735,6 +735,7 @@ static const struct ieee80211_iface_limi
#endif
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO) },
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
-@@ -266,7 +266,7 @@ static int ath9k_hw_def_check_eeprom(str
+@@ -262,7 +262,7 @@ static int ath9k_hw_def_check_eeprom(str
{
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
struct ath_common *common = ath9k_hw_common(ah);
u32 sum = 0, el;
bool need_swap = false;
int i, addr, size;
-@@ -276,27 +276,16 @@ static int ath9k_hw_def_check_eeprom(str
+@@ -272,27 +272,16 @@ static int ath9k_hw_def_check_eeprom(str
return false;
}
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-@@ -195,7 +195,7 @@ static int ath9k_hw_4k_check_eeprom(stru
- int i, addr;
-
+@@ -57,7 +57,7 @@ static bool ath9k_hw_4k_fill_eeprom(stru
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
- if (!ath9k_hw_use_flash(ah)) {
+ if (!(ah->ah_flags & AH_NO_EEP_SWAP)) {
- if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
- &magic)) {
- ath_err(common, "Reading Magic # failed\n");
+ ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
+ }
+
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-@@ -189,7 +189,7 @@ static int ath9k_hw_ar9287_check_eeprom(
- struct ar9287_eeprom *eep = &ah->eeprom.map9287;
+@@ -60,7 +60,7 @@ static bool ath9k_hw_ar9287_fill_eeprom(
+ {
struct ath_common *common = ath9k_hw_common(ah);
- if (!ath9k_hw_use_flash(ah)) {
+ if (!(ah->ah_flags & AH_NO_EEP_SWAP)) {
- if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
- &magic)) {
- ath_err(common, "Reading Magic # failed\n");
+ ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
+ }
+
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -704,6 +704,7 @@ enum ath_cal_list {
+@@ -705,6 +705,7 @@ enum ath_cal_list {
#define AH_USE_EEPROM 0x1
#define AH_UNPLUGGED 0x2 /* The card has been physically removed. */
#define AH_FASTCC 0x4
struct ath_ops reg_ops;
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -541,6 +541,8 @@ static int ath9k_init_softc(u16 devid, s
+@@ -591,6 +591,8 @@ static int ath9k_init_softc(u16 devid, s
ah->is_clk_25mhz = pdata->is_clk_25mhz;
ah->get_mac_revision = pdata->get_mac_revision;
ah->external_reset = pdata->external_reset;
common = ath9k_hw_common(ah);
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
-@@ -29,6 +29,7 @@ struct ath9k_platform_data {
+@@ -31,6 +31,7 @@ struct ath9k_platform_data {
u32 gpio_mask;
u32 gpio_val;
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -936,23 +936,23 @@ static int __init ath9k_init(void)
+@@ -994,23 +994,23 @@ static int __init ath9k_init(void)
goto err_out;
}
};
/* policy for the key attributes */
-@@ -1652,6 +1653,22 @@ static int nl80211_set_wiphy(struct sk_b
+@@ -1651,6 +1652,22 @@ static int nl80211_set_wiphy(struct sk_b
+ if (result)
goto bad_res;
}
-
++
+ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
+ int idx, dbi = 0;
+
+ if (result)
+ goto bad_res;
+ }
-+
+
if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
- u32 tx_ant, rx_ant;
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2118,6 +2118,19 @@ static int ieee80211_get_tx_power(struct
static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
const u8 *addr)
{
-@@ -3241,6 +3254,7 @@ struct cfg80211_ops mac80211_config_ops
+@@ -3241,6 +3254,7 @@ struct cfg80211_ops mac80211_config_ops
.set_wiphy_params = ieee80211_set_wiphy_params,
.set_tx_power = ieee80211_set_tx_power,
.get_tx_power = ieee80211_get_tx_power,
void ath_fill_led_pin(struct ath_softc *sc)
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -821,7 +821,7 @@ int ath9k_init_device(u16 devid, struct
+@@ -878,7 +878,7 @@ int ath9k_init_device(u16 devid, struct
#ifdef CONFIG_MAC80211_LEDS
/* must be initialized before ieee80211_register_hw */
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
-@@ -33,6 +33,9 @@ struct ath9k_platform_data {
+@@ -35,6 +35,9 @@ struct ath9k_platform_data {
bool is_clk_25mhz;
int (*get_mac_revision)(void);
int (*external_reset)(void);
debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -497,6 +497,12 @@ enum {
+@@ -498,6 +498,12 @@ enum {
ATH9K_RESET_COLD,
};
struct ath9k_hw_version {
u32 magic;
u16 devid;
-@@ -741,6 +747,8 @@ struct ath_hw {
+@@ -742,6 +748,8 @@ struct ath_hw {
u32 rfkill_polarity;
u32 ah_flags;
bool reset_power_on;
bool htc_reset_init;
-@@ -1007,6 +1015,7 @@ void ath9k_hw_set_sta_beacon_timers(stru
+@@ -1010,6 +1018,7 @@ void ath9k_hw_set_sta_beacon_timers(stru
bool ath9k_hw_check_alive(struct ath_hw *ah);
bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
-@@ -31,6 +31,9 @@ struct ath9k_platform_data {
+@@ -33,6 +33,9 @@ struct ath9k_platform_data {
bool endian_check;
bool is_clk_25mhz;
AR_SREV_9285(ah) ||
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -929,6 +929,8 @@ struct ath_hw {
+@@ -930,6 +930,8 @@ struct ath_hw {
bool is_clk_25mhz;
int (*get_mac_revision)(void);
int (*external_reset)(void);
+ bool disable_2ghz;
+ bool disable_5ghz;
- };
- struct ath_bus_ops {
+ const struct firmware *eeprom_blob;
+ };
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -541,6 +541,8 @@ static int ath9k_init_softc(u16 devid, s
+@@ -591,6 +591,8 @@ static int ath9k_init_softc(u16 devid, s
ah->is_clk_25mhz = pdata->is_clk_25mhz;
ah->get_mac_revision = pdata->get_mac_revision;
ah->external_reset = pdata->external_reset;
#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;