wcn36xx: Cache nv to avoid request_firmware on resume path
authorPontus Fuchs <pontus.fuchs@gmail.com>
Wed, 12 Feb 2014 19:04:43 +0000 (19:04 +0000)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 13 Feb 2014 20:20:17 +0000 (15:20 -0500)
If wowlan if off mac80211 will stop / start the driver on suspend /
resume. This causes problems on resume since request_firmware is called
from start. Fix this by caching the nv.

Signed-off-by: Pontus Fuchs <pontus.fuchs@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/wcn36xx/main.c
drivers/net/wireless/ath/wcn36xx/smd.c
drivers/net/wireless/ath/wcn36xx/wcn36xx.h

index e64a6784079e20446ad57078f607e0f01b7565a1..a801aaa760379ec211aac264bd1eb3d01b4d969c 100644 (file)
@@ -17,6 +17,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
+#include <linux/firmware.h>
 #include <linux/platform_device.h>
 #include "wcn36xx.h"
 
@@ -992,6 +993,7 @@ static int wcn36xx_remove(struct platform_device *pdev)
        struct wcn36xx *wcn = hw->priv;
        wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
 
+       release_firmware(wcn->nv);
        mutex_destroy(&wcn->hal_mutex);
 
        ieee80211_unregister_hw(hw);
index ad93cc791110847712331d22d218c17df10bd658..d5e90c45a482289ac10f887df513cff2b76bbf93 100644 (file)
@@ -251,21 +251,22 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
 
 int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
 {
-       const struct firmware *nv;
        struct nv_data *nv_d;
        struct wcn36xx_hal_nv_img_download_req_msg msg_body;
        int fw_bytes_left;
        int ret;
        u16 fm_offset = 0;
 
-       ret = request_firmware(&nv, WLAN_NV_FILE, wcn->dev);
-       if (ret) {
-               wcn36xx_err("Failed to load nv file %s: %d\n",
-                             WLAN_NV_FILE, ret);
-               goto out_free_nv;
+       if (!wcn->nv) {
+               ret = request_firmware(&wcn->nv, WLAN_NV_FILE, wcn->dev);
+               if (ret) {
+                       wcn36xx_err("Failed to load nv file %s: %d\n",
+                                     WLAN_NV_FILE, ret);
+                       goto out;
+               }
        }
 
-       nv_d = (struct nv_data *)nv->data;
+       nv_d = (struct nv_data *)wcn->nv->data;
        INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
 
        msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
@@ -275,7 +276,7 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
        mutex_lock(&wcn->hal_mutex);
 
        do {
-               fw_bytes_left = nv->size - fm_offset - 4;
+               fw_bytes_left = wcn->nv->size - fm_offset - 4;
                if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
                        msg_body.last_fragment = 0;
                        msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
@@ -313,10 +314,7 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
 
 out_unlock:
        mutex_unlock(&wcn->hal_mutex);
-out_free_nv:
-       release_firmware(nv);
-
-       return ret;
+out:   return ret;
 }
 
 static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
index c5bd61cffc9e0dc041bd1bbd64ee3d1a0d085bfd..0c5413f2c2e0385be9b9960b506948fb6566b5fa 100644 (file)
@@ -171,6 +171,8 @@ struct wcn36xx {
        struct device           *dev;
        struct list_head        vif_list;
 
+       const struct firmware   *nv;
+
        u8                      fw_revision;
        u8                      fw_version;
        u8                      fw_minor;