aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2013-05-17 20:50:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-05-22 15:08:49 -0400
commit75ab753d7704f0bd34e09d5e4081bc73fdddd775 (patch)
tree834f7906f5eff6acfc31568d3930b87e3487798b /drivers/net/wireless/mwifiex
parent06041118ef0908b9cae7657a7b734699bcf61a6c (diff)
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>
Diffstat (limited to 'drivers/net/wireless/mwifiex')
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c31
-rw-r--r--drivers/net/wireless/mwifiex/init.c20
-rw-r--r--drivers/net/wireless/mwifiex/main.c1
-rw-r--r--drivers/net/wireless/mwifiex/main.h2
-rw-r--r--drivers/net/wireless/mwifiex/scan.c22
5 files changed, 34 insertions, 42 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index d3c8ece980d8..fcd293c64118 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1859,6 +1859,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
1859 int i, offset, ret; 1859 int i, offset, ret;
1860 struct ieee80211_channel *chan; 1860 struct ieee80211_channel *chan;
1861 struct ieee_types_header *ie; 1861 struct ieee_types_header *ie;
1862 struct mwifiex_user_scan_cfg *user_scan_cfg;
1862 1863
1863 wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); 1864 wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);
1864 1865
@@ -1869,20 +1870,22 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
1869 return -EBUSY; 1870 return -EBUSY;
1870 } 1871 }
1871 1872
1872 if (priv->user_scan_cfg) { 1873 /* Block scan request if scan operation or scan cleanup when interface
1874 * is disabled is in process
1875 */
1876 if (priv->scan_request || priv->scan_aborting) {
1873 dev_err(priv->adapter->dev, "cmd: Scan already in process..\n"); 1877 dev_err(priv->adapter->dev, "cmd: Scan already in process..\n");
1874 return -EBUSY; 1878 return -EBUSY;
1875 } 1879 }
1876 1880
1877 priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), 1881 user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
1878 GFP_KERNEL); 1882 if (!user_scan_cfg)
1879 if (!priv->user_scan_cfg)
1880 return -ENOMEM; 1883 return -ENOMEM;
1881 1884
1882 priv->scan_request = request; 1885 priv->scan_request = request;
1883 1886
1884 priv->user_scan_cfg->num_ssids = request->n_ssids; 1887 user_scan_cfg->num_ssids = request->n_ssids;
1885 priv->user_scan_cfg->ssid_list = request->ssids; 1888 user_scan_cfg->ssid_list = request->ssids;
1886 1889
1887 if (request->ie && request->ie_len) { 1890 if (request->ie && request->ie_len) {
1888 offset = 0; 1891 offset = 0;
@@ -1902,25 +1905,25 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
1902 for (i = 0; i < min_t(u32, request->n_channels, 1905 for (i = 0; i < min_t(u32, request->n_channels,
1903 MWIFIEX_USER_SCAN_CHAN_MAX); i++) { 1906 MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
1904 chan = request->channels[i]; 1907 chan = request->channels[i];
1905 priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value; 1908 user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
1906 priv->user_scan_cfg->chan_list[i].radio_type = chan->band; 1909 user_scan_cfg->chan_list[i].radio_type = chan->band;
1907 1910
1908 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) 1911 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
1909 priv->user_scan_cfg->chan_list[i].scan_type = 1912 user_scan_cfg->chan_list[i].scan_type =
1910 MWIFIEX_SCAN_TYPE_PASSIVE; 1913 MWIFIEX_SCAN_TYPE_PASSIVE;
1911 else 1914 else
1912 priv->user_scan_cfg->chan_list[i].scan_type = 1915 user_scan_cfg->chan_list[i].scan_type =
1913 MWIFIEX_SCAN_TYPE_ACTIVE; 1916 MWIFIEX_SCAN_TYPE_ACTIVE;
1914 1917
1915 priv->user_scan_cfg->chan_list[i].scan_time = 0; 1918 user_scan_cfg->chan_list[i].scan_time = 0;
1916 } 1919 }
1917 1920
1918 ret = mwifiex_scan_networks(priv, priv->user_scan_cfg); 1921 ret = mwifiex_scan_networks(priv, user_scan_cfg);
1922 kfree(user_scan_cfg);
1919 if (ret) { 1923 if (ret) {
1920 dev_err(priv->adapter->dev, "scan failed: %d\n", ret); 1924 dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
1925 priv->scan_aborting = false;
1921 priv->scan_request = NULL; 1926 priv->scan_request = NULL;
1922 kfree(priv->user_scan_cfg);
1923 priv->user_scan_cfg = NULL;
1924 return ret; 1927 return ret;
1925 } 1928 }
1926 1929
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 71bbf1204685..1343725f8c4c 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -81,19 +81,13 @@ static void scan_delay_timer_fn(unsigned long data)
81 adapter->empty_tx_q_cnt = 0; 81 adapter->empty_tx_q_cnt = 0;
82 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); 82 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
83 83
84 if (priv->user_scan_cfg) { 84 if (priv->scan_request) {
85 if (priv->scan_request) { 85 dev_dbg(adapter->dev, "info: aborting scan\n");
86 dev_dbg(priv->adapter->dev, 86 cfg80211_scan_done(priv->scan_request, 1);
87 "info: aborting scan\n"); 87 priv->scan_request = NULL;
88 cfg80211_scan_done(priv->scan_request, 1); 88 } else {
89 priv->scan_request = NULL; 89 priv->scan_aborting = false;
90 } else { 90 dev_dbg(adapter->dev, "info: scan already aborted\n");
91 dev_dbg(priv->adapter->dev,
92 "info: scan already aborted\n");
93 }
94
95 kfree(priv->user_scan_cfg);
96 priv->user_scan_cfg = NULL;
97 } 91 }
98 goto done; 92 goto done;
99 } 93 }
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 121443a0f2a1..eb8518618622 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -436,6 +436,7 @@ mwifiex_close(struct net_device *dev)
436 dev_dbg(priv->adapter->dev, "aborting scan on ndo_stop\n"); 436 dev_dbg(priv->adapter->dev, "aborting scan on ndo_stop\n");
437 cfg80211_scan_done(priv->scan_request, 1); 437 cfg80211_scan_done(priv->scan_request, 1);
438 priv->scan_request = NULL; 438 priv->scan_request = NULL;
439 priv->scan_aborting = true;
439 } 440 }
440 441
441 return 0; 442 return 0;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 4ef67fca06d3..81251d91491c 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -492,7 +492,6 @@ struct mwifiex_private {
492 struct semaphore async_sem; 492 struct semaphore async_sem;
493 u8 report_scan_result; 493 u8 report_scan_result;
494 struct cfg80211_scan_request *scan_request; 494 struct cfg80211_scan_request *scan_request;
495 struct mwifiex_user_scan_cfg *user_scan_cfg;
496 u8 cfg_bssid[6]; 495 u8 cfg_bssid[6];
497 struct wps wps; 496 struct wps wps;
498 u8 scan_block; 497 u8 scan_block;
@@ -510,6 +509,7 @@ struct mwifiex_private {
510 u8 ap_11ac_enabled; 509 u8 ap_11ac_enabled;
511 u32 mgmt_frame_mask; 510 u32 mgmt_frame_mask;
512 struct mwifiex_roc_cfg roc_cfg; 511 struct mwifiex_roc_cfg roc_cfg;
512 bool scan_aborting;
513}; 513};
514 514
515enum mwifiex_ba_status { 515enum mwifiex_ba_status {
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 9cf5d8f07df8..7b2566b308c3 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1784,22 +1784,16 @@ check_next_scan:
1784 if (priv->report_scan_result) 1784 if (priv->report_scan_result)
1785 priv->report_scan_result = false; 1785 priv->report_scan_result = false;
1786 1786
1787 if (priv->user_scan_cfg) { 1787 if (priv->scan_request) {
1788 if (priv->scan_request) { 1788 dev_dbg(adapter->dev, "info: notifying scan done\n");
1789 dev_dbg(priv->adapter->dev, 1789 cfg80211_scan_done(priv->scan_request, 0);
1790 "info: notifying scan done\n"); 1790 priv->scan_request = NULL;
1791 cfg80211_scan_done(priv->scan_request, 0); 1791 } else {
1792 priv->scan_request = NULL; 1792 priv->scan_aborting = false;
1793 } else { 1793 dev_dbg(adapter->dev, "info: scan already aborted\n");
1794 dev_dbg(priv->adapter->dev,
1795 "info: scan already aborted\n");
1796 }
1797
1798 kfree(priv->user_scan_cfg);
1799 priv->user_scan_cfg = NULL;
1800 } 1794 }
1801 } else { 1795 } else {
1802 if (priv->user_scan_cfg && !priv->scan_request) { 1796 if (priv->scan_aborting && !priv->scan_request) {
1803 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, 1797 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1804 flags); 1798 flags);
1805 adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT; 1799 adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT;