aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPontus Fuchs <pontus.fuchs@gmail.com>2014-02-12 14:04:43 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-02-13 15:20:17 -0500
commit4bda7faf619a609534bb99c860a0a32ec40b8fb6 (patch)
tree14a6dd93dbac13b9c166dfa1aac78942077e2f1b
parent546c505bdc64c471be33a5ab525458431d718f5e (diff)
wcn36xx: Cache nv to avoid request_firmware on resume path
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>
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c2
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.c22
-rw-r--r--drivers/net/wireless/ath/wcn36xx/wcn36xx.h2
3 files changed, 14 insertions, 12 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index e64a6784079e..a801aaa76037 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -17,6 +17,7 @@
17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18 18
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/firmware.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
21#include "wcn36xx.h" 22#include "wcn36xx.h"
22 23
@@ -992,6 +993,7 @@ static int wcn36xx_remove(struct platform_device *pdev)
992 struct wcn36xx *wcn = hw->priv; 993 struct wcn36xx *wcn = hw->priv;
993 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n"); 994 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
994 995
996 release_firmware(wcn->nv);
995 mutex_destroy(&wcn->hal_mutex); 997 mutex_destroy(&wcn->hal_mutex);
996 998
997 ieee80211_unregister_hw(hw); 999 ieee80211_unregister_hw(hw);
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index ad93cc791110..d5e90c45a482 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -251,21 +251,22 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
251 251
252int wcn36xx_smd_load_nv(struct wcn36xx *wcn) 252int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
253{ 253{
254 const struct firmware *nv;
255 struct nv_data *nv_d; 254 struct nv_data *nv_d;
256 struct wcn36xx_hal_nv_img_download_req_msg msg_body; 255 struct wcn36xx_hal_nv_img_download_req_msg msg_body;
257 int fw_bytes_left; 256 int fw_bytes_left;
258 int ret; 257 int ret;
259 u16 fm_offset = 0; 258 u16 fm_offset = 0;
260 259
261 ret = request_firmware(&nv, WLAN_NV_FILE, wcn->dev); 260 if (!wcn->nv) {
262 if (ret) { 261 ret = request_firmware(&wcn->nv, WLAN_NV_FILE, wcn->dev);
263 wcn36xx_err("Failed to load nv file %s: %d\n", 262 if (ret) {
264 WLAN_NV_FILE, ret); 263 wcn36xx_err("Failed to load nv file %s: %d\n",
265 goto out_free_nv; 264 WLAN_NV_FILE, ret);
265 goto out;
266 }
266 } 267 }
267 268
268 nv_d = (struct nv_data *)nv->data; 269 nv_d = (struct nv_data *)wcn->nv->data;
269 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ); 270 INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
270 271
271 msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE; 272 msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
@@ -275,7 +276,7 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
275 mutex_lock(&wcn->hal_mutex); 276 mutex_lock(&wcn->hal_mutex);
276 277
277 do { 278 do {
278 fw_bytes_left = nv->size - fm_offset - 4; 279 fw_bytes_left = wcn->nv->size - fm_offset - 4;
279 if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) { 280 if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
280 msg_body.last_fragment = 0; 281 msg_body.last_fragment = 0;
281 msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE; 282 msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
@@ -313,10 +314,7 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
313 314
314out_unlock: 315out_unlock:
315 mutex_unlock(&wcn->hal_mutex); 316 mutex_unlock(&wcn->hal_mutex);
316out_free_nv: 317out: return ret;
317 release_firmware(nv);
318
319 return ret;
320} 318}
321 319
322static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len) 320static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index c5bd61cffc9e..0c5413f2c2e0 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -171,6 +171,8 @@ struct wcn36xx {
171 struct device *dev; 171 struct device *dev;
172 struct list_head vif_list; 172 struct list_head vif_list;
173 173
174 const struct firmware *nv;
175
174 u8 fw_revision; 176 u8 fw_revision;
175 u8 fw_version; 177 u8 fw_version;
176 u8 fw_minor; 178 u8 fw_minor;