diff options
author | Amitkumar Karwar <akarwar@marvell.com> | 2013-05-17 20:50:20 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-05-22 15:08:49 -0400 |
commit | 75ab753d7704f0bd34e09d5e4081bc73fdddd775 (patch) | |
tree | 834f7906f5eff6acfc31568d3930b87e3487798b /drivers/net/wireless/mwifiex/cfg80211.c | |
parent | 06041118ef0908b9cae7657a7b734699bcf61a6c (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/cfg80211.c')
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 31 |
1 files changed, 17 insertions, 14 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 | ||