Commit 4bda7faf authored by Pontus Fuchs's avatar Pontus Fuchs Committed by John W. Linville

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: default avatarPontus Fuchs <pontus.fuchs@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 546c505b
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h> #include <linux/module.h>
#include <linux/firmware.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "wcn36xx.h" #include "wcn36xx.h"
...@@ -992,6 +993,7 @@ static int wcn36xx_remove(struct platform_device *pdev) ...@@ -992,6 +993,7 @@ static int wcn36xx_remove(struct platform_device *pdev)
struct wcn36xx *wcn = hw->priv; struct wcn36xx *wcn = hw->priv;
wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n"); wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
release_firmware(wcn->nv);
mutex_destroy(&wcn->hal_mutex); mutex_destroy(&wcn->hal_mutex);
ieee80211_unregister_hw(hw); ieee80211_unregister_hw(hw);
......
...@@ -251,21 +251,22 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len) ...@@ -251,21 +251,22 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
int wcn36xx_smd_load_nv(struct wcn36xx *wcn) int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
{ {
const struct firmware *nv;
struct nv_data *nv_d; struct nv_data *nv_d;
struct wcn36xx_hal_nv_img_download_req_msg msg_body; struct wcn36xx_hal_nv_img_download_req_msg msg_body;
int fw_bytes_left; int fw_bytes_left;
int ret; int ret;
u16 fm_offset = 0; u16 fm_offset = 0;
ret = request_firmware(&nv, WLAN_NV_FILE, wcn->dev); if (!wcn->nv) {
if (ret) { ret = request_firmware(&wcn->nv, WLAN_NV_FILE, wcn->dev);
wcn36xx_err("Failed to load nv file %s: %d\n", if (ret) {
WLAN_NV_FILE, ret); wcn36xx_err("Failed to load nv file %s: %d\n",
goto out_free_nv; 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); INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE; msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
...@@ -275,7 +276,7 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn) ...@@ -275,7 +276,7 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
mutex_lock(&wcn->hal_mutex); mutex_lock(&wcn->hal_mutex);
do { 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) { if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
msg_body.last_fragment = 0; msg_body.last_fragment = 0;
msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE; msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
...@@ -313,10 +314,7 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn) ...@@ -313,10 +314,7 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
out_unlock: out_unlock:
mutex_unlock(&wcn->hal_mutex); mutex_unlock(&wcn->hal_mutex);
out_free_nv: out: return ret;
release_firmware(nv);
return ret;
} }
static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len) static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
......
...@@ -171,6 +171,8 @@ struct wcn36xx { ...@@ -171,6 +171,8 @@ struct wcn36xx {
struct device *dev; struct device *dev;
struct list_head vif_list; struct list_head vif_list;
const struct firmware *nv;
u8 fw_revision; u8 fw_revision;
u8 fw_version; u8 fw_version;
u8 fw_minor; u8 fw_minor;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment