|
@@ -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;
|
|
|
}
|