|
@@ -744,32 +744,6 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static void wl1271_fetch_nvs(struct wl1271 *wl)
|
|
|
-{
|
|
|
- const struct firmware *fw;
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = request_firmware(&fw, WL12XX_NVS_NAME, wl->dev);
|
|
|
-
|
|
|
- if (ret < 0) {
|
|
|
- wl1271_debug(DEBUG_BOOT, "could not get nvs file %s: %d",
|
|
|
- WL12XX_NVS_NAME, ret);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL);
|
|
|
-
|
|
|
- if (!wl->nvs) {
|
|
|
- wl1271_error("could not allocate memory for the nvs file");
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- wl->nvs_len = fw->size;
|
|
|
-
|
|
|
-out:
|
|
|
- release_firmware(fw);
|
|
|
-}
|
|
|
-
|
|
|
void wl12xx_queue_recovery_work(struct wl1271 *wl)
|
|
|
{
|
|
|
WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
|
|
@@ -5153,8 +5127,7 @@ static int wl1271_register_hw(struct wl1271 *wl)
|
|
|
if (wl->mac80211_registered)
|
|
|
return 0;
|
|
|
|
|
|
- wl1271_fetch_nvs(wl);
|
|
|
- if (wl->nvs != NULL) {
|
|
|
+ if (wl->nvs_len >= 12) {
|
|
|
/* NOTE: The wl->nvs->nvs element must be first, in
|
|
|
* order to simplify the casting, we assume it is at
|
|
|
* the beginning of the wl->nvs structure.
|
|
@@ -5419,6 +5392,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size)
|
|
|
wl->fw_type = WL12XX_FW_TYPE_NONE;
|
|
|
mutex_init(&wl->mutex);
|
|
|
mutex_init(&wl->flush_mutex);
|
|
|
+ init_completion(&wl->nvs_loading_complete);
|
|
|
|
|
|
order = get_order(aggr_buf_size);
|
|
|
wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
|
|
@@ -5539,24 +5513,31 @@ static irqreturn_t wl12xx_hardirq(int irq, void *cookie)
|
|
|
return IRQ_WAKE_THREAD;
|
|
|
}
|
|
|
|
|
|
-int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
|
|
|
+static void wlcore_nvs_cb(const struct firmware *fw, void *context)
|
|
|
{
|
|
|
+ struct wl1271 *wl = context;
|
|
|
+ struct platform_device *pdev = wl->pdev;
|
|
|
struct wl12xx_platform_data *pdata = pdev->dev.platform_data;
|
|
|
unsigned long irqflags;
|
|
|
int ret;
|
|
|
|
|
|
- if (!wl->ops || !wl->ptable) {
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ if (fw) {
|
|
|
+ wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL);
|
|
|
+ if (!wl->nvs) {
|
|
|
+ wl1271_error("Could not allocate nvs data");
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ wl->nvs_len = fw->size;
|
|
|
+ } else {
|
|
|
+ wl1271_debug(DEBUG_BOOT, "Could not get nvs file %s",
|
|
|
+ WL12XX_NVS_NAME);
|
|
|
+ wl->nvs = NULL;
|
|
|
+ wl->nvs_len = 0;
|
|
|
}
|
|
|
|
|
|
- wl->dev = &pdev->dev;
|
|
|
- wl->pdev = pdev;
|
|
|
- platform_set_drvdata(pdev, wl);
|
|
|
-
|
|
|
ret = wl->ops->setup(wl);
|
|
|
if (ret < 0)
|
|
|
- goto out;
|
|
|
+ goto out_free_nvs;
|
|
|
|
|
|
BUG_ON(wl->num_tx_desc > WLCORE_MAX_TX_DESCRIPTORS);
|
|
|
|
|
@@ -5578,7 +5559,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
|
|
|
pdev->name, wl);
|
|
|
if (ret < 0) {
|
|
|
wl1271_error("request_irq() failed: %d", ret);
|
|
|
- goto out;
|
|
|
+ goto out_free_nvs;
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_PM
|
|
@@ -5637,6 +5618,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
|
|
|
goto out_hw_pg_ver;
|
|
|
}
|
|
|
|
|
|
+ wl->initialized = true;
|
|
|
goto out;
|
|
|
|
|
|
out_hw_pg_ver:
|
|
@@ -5651,7 +5633,33 @@ out_unreg:
|
|
|
out_irq:
|
|
|
free_irq(wl->irq, wl);
|
|
|
|
|
|
+out_free_nvs:
|
|
|
+ kfree(wl->nvs);
|
|
|
+
|
|
|
out:
|
|
|
+ release_firmware(fw);
|
|
|
+ complete_all(&wl->nvs_loading_complete);
|
|
|
+}
|
|
|
+
|
|
|
+int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!wl->ops || !wl->ptable)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ wl->dev = &pdev->dev;
|
|
|
+ wl->pdev = pdev;
|
|
|
+ platform_set_drvdata(pdev, wl);
|
|
|
+
|
|
|
+ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
|
|
|
+ WL12XX_NVS_NAME, &pdev->dev, GFP_KERNEL,
|
|
|
+ wl, wlcore_nvs_cb);
|
|
|
+ if (ret < 0) {
|
|
|
+ wl1271_error("request_firmware_nowait failed: %d", ret);
|
|
|
+ complete_all(&wl->nvs_loading_complete);
|
|
|
+ }
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(wlcore_probe);
|
|
@@ -5660,6 +5668,10 @@ int __devexit wlcore_remove(struct platform_device *pdev)
|
|
|
{
|
|
|
struct wl1271 *wl = platform_get_drvdata(pdev);
|
|
|
|
|
|
+ wait_for_completion(&wl->nvs_loading_complete);
|
|
|
+ if (!wl->initialized)
|
|
|
+ return 0;
|
|
|
+
|
|
|
if (wl->irq_wake_enabled) {
|
|
|
device_init_wakeup(wl->dev, 0);
|
|
|
disable_irq_wake(wl->irq);
|