mwifiex: remove global user_scan_cfg variable
As the variable is used only for preparation of internal scan commands, we don't need to keep it allocated until the entire scan completes. We will define it as a local variable and free immediately after it's use. New flag 'scan_aborting' is added to handle race between mwifiex_close() and scan handler. Previously user_scan_cfg pointer used to take care of this. This patch fixes a memory leak in mwifiex_cfg80211_scan after running "iwlist mlan0 scan & sleep 1; rmmod mwifiex_sdio". Reported-by: Daniel Drake <dsd@laptop.org> Tested-by: Daniel Drake <dsd@laptop.org> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
06041118ef
commit
75ab753d77
|
@ -1859,6 +1859,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
|
|||
int i, offset, ret;
|
||||
struct ieee80211_channel *chan;
|
||||
struct ieee_types_header *ie;
|
||||
struct mwifiex_user_scan_cfg *user_scan_cfg;
|
||||
|
||||
wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);
|
||||
|
||||
|
@ -1869,20 +1870,22 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (priv->user_scan_cfg) {
|
||||
/* Block scan request if scan operation or scan cleanup when interface
|
||||
* is disabled is in process
|
||||
*/
|
||||
if (priv->scan_request || priv->scan_aborting) {
|
||||
dev_err(priv->adapter->dev, "cmd: Scan already in process..\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
|
||||
GFP_KERNEL);
|
||||
if (!priv->user_scan_cfg)
|
||||
user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
|
||||
if (!user_scan_cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->scan_request = request;
|
||||
|
||||
priv->user_scan_cfg->num_ssids = request->n_ssids;
|
||||
priv->user_scan_cfg->ssid_list = request->ssids;
|
||||
user_scan_cfg->num_ssids = request->n_ssids;
|
||||
user_scan_cfg->ssid_list = request->ssids;
|
||||
|
||||
if (request->ie && request->ie_len) {
|
||||
offset = 0;
|
||||
|
@ -1902,25 +1905,25 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
|
|||
for (i = 0; i < min_t(u32, request->n_channels,
|
||||
MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
|
||||
chan = request->channels[i];
|
||||
priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
|
||||
priv->user_scan_cfg->chan_list[i].radio_type = chan->band;
|
||||
user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
|
||||
user_scan_cfg->chan_list[i].radio_type = chan->band;
|
||||
|
||||
if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
||||
priv->user_scan_cfg->chan_list[i].scan_type =
|
||||
user_scan_cfg->chan_list[i].scan_type =
|
||||
MWIFIEX_SCAN_TYPE_PASSIVE;
|
||||
else
|
||||
priv->user_scan_cfg->chan_list[i].scan_type =
|
||||
user_scan_cfg->chan_list[i].scan_type =
|
||||
MWIFIEX_SCAN_TYPE_ACTIVE;
|
||||
|
||||
priv->user_scan_cfg->chan_list[i].scan_time = 0;
|
||||
user_scan_cfg->chan_list[i].scan_time = 0;
|
||||
}
|
||||
|
||||
ret = mwifiex_scan_networks(priv, priv->user_scan_cfg);
|
||||
ret = mwifiex_scan_networks(priv, user_scan_cfg);
|
||||
kfree(user_scan_cfg);
|
||||
if (ret) {
|
||||
dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
|
||||
priv->scan_aborting = false;
|
||||
priv->scan_request = NULL;
|
||||
kfree(priv->user_scan_cfg);
|
||||
priv->user_scan_cfg = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,19 +81,13 @@ static void scan_delay_timer_fn(unsigned long data)
|
|||
adapter->empty_tx_q_cnt = 0;
|
||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
|
||||
if (priv->user_scan_cfg) {
|
||||
if (priv->scan_request) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: aborting scan\n");
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
priv->scan_request = NULL;
|
||||
} else {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: scan already aborted\n");
|
||||
}
|
||||
|
||||
kfree(priv->user_scan_cfg);
|
||||
priv->user_scan_cfg = NULL;
|
||||
if (priv->scan_request) {
|
||||
dev_dbg(adapter->dev, "info: aborting scan\n");
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
priv->scan_request = NULL;
|
||||
} else {
|
||||
priv->scan_aborting = false;
|
||||
dev_dbg(adapter->dev, "info: scan already aborted\n");
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
|
|
@ -436,6 +436,7 @@ mwifiex_close(struct net_device *dev)
|
|||
dev_dbg(priv->adapter->dev, "aborting scan on ndo_stop\n");
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
priv->scan_request = NULL;
|
||||
priv->scan_aborting = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -492,7 +492,6 @@ struct mwifiex_private {
|
|||
struct semaphore async_sem;
|
||||
u8 report_scan_result;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
struct mwifiex_user_scan_cfg *user_scan_cfg;
|
||||
u8 cfg_bssid[6];
|
||||
struct wps wps;
|
||||
u8 scan_block;
|
||||
|
@ -510,6 +509,7 @@ struct mwifiex_private {
|
|||
u8 ap_11ac_enabled;
|
||||
u32 mgmt_frame_mask;
|
||||
struct mwifiex_roc_cfg roc_cfg;
|
||||
bool scan_aborting;
|
||||
};
|
||||
|
||||
enum mwifiex_ba_status {
|
||||
|
|
|
@ -1784,22 +1784,16 @@ check_next_scan:
|
|||
if (priv->report_scan_result)
|
||||
priv->report_scan_result = false;
|
||||
|
||||
if (priv->user_scan_cfg) {
|
||||
if (priv->scan_request) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: notifying scan done\n");
|
||||
cfg80211_scan_done(priv->scan_request, 0);
|
||||
priv->scan_request = NULL;
|
||||
} else {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: scan already aborted\n");
|
||||
}
|
||||
|
||||
kfree(priv->user_scan_cfg);
|
||||
priv->user_scan_cfg = NULL;
|
||||
if (priv->scan_request) {
|
||||
dev_dbg(adapter->dev, "info: notifying scan done\n");
|
||||
cfg80211_scan_done(priv->scan_request, 0);
|
||||
priv->scan_request = NULL;
|
||||
} else {
|
||||
priv->scan_aborting = false;
|
||||
dev_dbg(adapter->dev, "info: scan already aborted\n");
|
||||
}
|
||||
} else {
|
||||
if (priv->user_scan_cfg && !priv->scan_request) {
|
||||
if (priv->scan_aborting && !priv->scan_request) {
|
||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||
flags);
|
||||
adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT;
|
||||
|
|
Loading…
Reference in New Issue