diff options
author | Pontus Fuchs <pontus.fuchs@gmail.com> | 2014-02-12 14:04:43 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-02-13 15:20:17 -0500 |
commit | 4bda7faf619a609534bb99c860a0a32ec40b8fb6 (patch) | |
tree | 14a6dd93dbac13b9c166dfa1aac78942077e2f1b | |
parent | 546c505bdc64c471be33a5ab525458431d718f5e (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.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/smd.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 2 |
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 | ||
252 | int wcn36xx_smd_load_nv(struct wcn36xx *wcn) | 252 | int 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 | ||
314 | out_unlock: | 315 | out_unlock: |
315 | mutex_unlock(&wcn->hal_mutex); | 316 | mutex_unlock(&wcn->hal_mutex); |
316 | out_free_nv: | 317 | out: return ret; |
317 | release_firmware(nv); | ||
318 | |||
319 | return ret; | ||
320 | } | 318 | } |
321 | 319 | ||
322 | static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len) | 320 | static 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; |