aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c8
-rw-r--r--drivers/net/wireless/ath/ath5k/pci.c7
-rw-r--r--drivers/net/wireless/ath/ath5k/sysfs.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c3
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/sw.c1
-rw-r--r--drivers/ssb/driver_pcicore.c18
-rw-r--r--net/bluetooth/hci_conn.c3
-rw-r--r--net/bluetooth/hidp/core.c18
-rw-r--r--net/bluetooth/hidp/hidp.h1
-rw-r--r--net/bluetooth/l2cap_core.c5
-rw-r--r--net/mac80211/scan.c3
-rw-r--r--net/wireless/core.c12
-rw-r--r--net/wireless/core.h2
-rw-r--r--net/wireless/nl80211.c24
-rw-r--r--net/wireless/scan.c10
17 files changed, 88 insertions, 44 deletions
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index f2657bf34fea..f97a540e2199 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -693,14 +693,12 @@ ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
693 if (!chinfo[pier].pd_curves) 693 if (!chinfo[pier].pd_curves)
694 continue; 694 continue;
695 695
696 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { 696 for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) {
697 struct ath5k_pdgain_info *pd = 697 struct ath5k_pdgain_info *pd =
698 &chinfo[pier].pd_curves[pdg]; 698 &chinfo[pier].pd_curves[pdg];
699 699
700 if (pd != NULL) { 700 kfree(pd->pd_step);
701 kfree(pd->pd_step); 701 kfree(pd->pd_pwr);
702 kfree(pd->pd_pwr);
703 }
704 } 702 }
705 703
706 kfree(chinfo[pier].pd_curves); 704 kfree(chinfo[pier].pd_curves);
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index bb93796bfaf1..cd60f0a2f0ea 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -297,7 +297,9 @@ ath5k_pci_remove(struct pci_dev *pdev)
297#ifdef CONFIG_PM_SLEEP 297#ifdef CONFIG_PM_SLEEP
298static int ath5k_pci_suspend(struct device *dev) 298static int ath5k_pci_suspend(struct device *dev)
299{ 299{
300 struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); 300 struct pci_dev *pdev = to_pci_dev(dev);
301 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
302 struct ath5k_softc *sc = hw->priv;
301 303
302 ath5k_led_off(sc); 304 ath5k_led_off(sc);
303 return 0; 305 return 0;
@@ -306,7 +308,8 @@ static int ath5k_pci_suspend(struct device *dev)
306static int ath5k_pci_resume(struct device *dev) 308static int ath5k_pci_resume(struct device *dev)
307{ 309{
308 struct pci_dev *pdev = to_pci_dev(dev); 310 struct pci_dev *pdev = to_pci_dev(dev);
309 struct ath5k_softc *sc = pci_get_drvdata(pdev); 311 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
312 struct ath5k_softc *sc = hw->priv;
310 313
311 /* 314 /*
312 * Suspend/Resume resets the PCI configuration space, so we have to 315 * Suspend/Resume resets the PCI configuration space, so we have to
diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c
index 5406f44309c8..d8ad0e45e1c4 100644
--- a/drivers/net/wireless/ath/ath5k/sysfs.c
+++ b/drivers/net/wireless/ath/ath5k/sysfs.c
@@ -10,7 +10,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \
10 struct device_attribute *attr, \ 10 struct device_attribute *attr, \
11 char *buf) \ 11 char *buf) \
12{ \ 12{ \
13 struct ath5k_softc *sc = dev_get_drvdata(dev); \ 13 struct ieee80211_hw *hw = dev_get_drvdata(dev); \
14 struct ath5k_softc *sc = hw->priv; \
14 return snprintf(buf, PAGE_SIZE, "%d\n", get); \ 15 return snprintf(buf, PAGE_SIZE, "%d\n", get); \
15} \ 16} \
16 \ 17 \
@@ -18,7 +19,8 @@ static ssize_t ath5k_attr_store_##name(struct device *dev, \
18 struct device_attribute *attr, \ 19 struct device_attribute *attr, \
19 const char *buf, size_t count) \ 20 const char *buf, size_t count) \
20{ \ 21{ \
21 struct ath5k_softc *sc = dev_get_drvdata(dev); \ 22 struct ieee80211_hw *hw = dev_get_drvdata(dev); \
23 struct ath5k_softc *sc = hw->priv; \
22 int val, ret; \ 24 int val, ret; \
23 \ 25 \
24 ret = kstrtoint(buf, 10, &val); \ 26 ret = kstrtoint(buf, 10, &val); \
@@ -35,7 +37,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \
35 struct device_attribute *attr, \ 37 struct device_attribute *attr, \
36 char *buf) \ 38 char *buf) \
37{ \ 39{ \
38 struct ath5k_softc *sc = dev_get_drvdata(dev); \ 40 struct ieee80211_hw *hw = dev_get_drvdata(dev); \
41 struct ath5k_softc *sc = hw->priv; \
39 return snprintf(buf, PAGE_SIZE, "%d\n", get); \ 42 return snprintf(buf, PAGE_SIZE, "%d\n", get); \
40} \ 43} \
41static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL) 44static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL)
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index b8cbfc707213..3bad0b2cf9a3 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -278,6 +278,12 @@ static int ath_pci_suspend(struct device *device)
278 278
279 ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); 279 ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
280 280
281 /* The device has to be moved to FULLSLEEP forcibly.
282 * Otherwise the chip never moved to full sleep,
283 * when no interface is up.
284 */
285 ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
286
281 return 0; 287 return 0;
282} 288}
283 289
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index a1fed6c8ff95..9283440a0210 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -661,7 +661,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
661 * TODO - this could be improved to be dependent on the rate. 661 * TODO - this could be improved to be dependent on the rate.
662 * The hardware can keep up at lower rates, but not higher rates 662 * The hardware can keep up at lower rates, but not higher rates
663 */ 663 */
664 if (fi->keyix != ATH9K_TXKEYIX_INVALID) 664 if ((fi->keyix != ATH9K_TXKEYIX_INVALID) &&
665 !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))
665 ndelim += ATH_AGGR_ENCRYPTDELIM; 666 ndelim += ATH_AGGR_ENCRYPTDELIM;
666 667
667 /* 668 /*
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index 2fb53d067512..333b69ef2ae2 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -112,6 +112,8 @@ static struct usb_device_id carl9170_usb_ids[] = {
112 { USB_DEVICE(0x04bb, 0x093f) }, 112 { USB_DEVICE(0x04bb, 0x093f) },
113 /* NEC WL300NU-G */ 113 /* NEC WL300NU-G */
114 { USB_DEVICE(0x0409, 0x0249) }, 114 { USB_DEVICE(0x0409, 0x0249) },
115 /* NEC WL300NU-AG */
116 { USB_DEVICE(0x0409, 0x02b4) },
115 /* AVM FRITZ!WLAN USB Stick N */ 117 /* AVM FRITZ!WLAN USB Stick N */
116 { USB_DEVICE(0x057c, 0x8401) }, 118 { USB_DEVICE(0x057c, 0x8401) },
117 /* AVM FRITZ!WLAN USB Stick N 2.4 */ 119 /* AVM FRITZ!WLAN USB Stick N 2.4 */
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index 092e342c19df..942f7a3969a7 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -298,6 +298,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
298 {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ 298 {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/
299 {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ 299 {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
300 {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ 300 {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
301 {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/
301 {RTL_USB_DEVICE(0x0Df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ 302 {RTL_USB_DEVICE(0x0Df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
302 {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/ 303 {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
303 /* HP - Lite-On ,8188CUS Slim Combo */ 304 /* HP - Lite-On ,8188CUS Slim Combo */
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index 21b9465f71ad..11d85bfd774e 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -516,8 +516,17 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc)
516 516
517static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) 517static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
518{ 518{
519 ssb_pcicore_fix_sprom_core_index(pc);
520
519 /* Disable PCI interrupts. */ 521 /* Disable PCI interrupts. */
520 ssb_write32(pc->dev, SSB_INTVEC, 0); 522 ssb_write32(pc->dev, SSB_INTVEC, 0);
523
524 /* Additional PCIe always once-executed workarounds */
525 if (pc->dev->id.coreid == SSB_DEV_PCIE) {
526 ssb_pcicore_serdes_workaround(pc);
527 /* TODO: ASPM */
528 /* TODO: Clock Request Update */
529 }
521} 530}
522 531
523void __devinit ssb_pcicore_init(struct ssb_pcicore *pc) 532void __devinit ssb_pcicore_init(struct ssb_pcicore *pc)
@@ -529,8 +538,6 @@ void __devinit ssb_pcicore_init(struct ssb_pcicore *pc)
529 if (!ssb_device_is_enabled(dev)) 538 if (!ssb_device_is_enabled(dev))
530 ssb_device_enable(dev, 0); 539 ssb_device_enable(dev, 0);
531 540
532 ssb_pcicore_fix_sprom_core_index(pc);
533
534#ifdef CONFIG_SSB_PCICORE_HOSTMODE 541#ifdef CONFIG_SSB_PCICORE_HOSTMODE
535 pc->hostmode = pcicore_is_in_hostmode(pc); 542 pc->hostmode = pcicore_is_in_hostmode(pc);
536 if (pc->hostmode) 543 if (pc->hostmode)
@@ -538,13 +545,6 @@ void __devinit ssb_pcicore_init(struct ssb_pcicore *pc)
538#endif /* CONFIG_SSB_PCICORE_HOSTMODE */ 545#endif /* CONFIG_SSB_PCICORE_HOSTMODE */
539 if (!pc->hostmode) 546 if (!pc->hostmode)
540 ssb_pcicore_init_clientmode(pc); 547 ssb_pcicore_init_clientmode(pc);
541
542 /* Additional PCIe always once-executed workarounds */
543 if (dev->id.coreid == SSB_DEV_PCIE) {
544 ssb_pcicore_serdes_workaround(pc);
545 /* TODO: ASPM */
546 /* TODO: Clock Request Update */
547 }
548} 548}
549 549
550static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) 550static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index fa48c0b3d93c..ea7f031f3b04 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -444,6 +444,9 @@ int hci_conn_del(struct hci_conn *conn)
444 444
445 hci_dev_put(hdev); 445 hci_dev_put(hdev);
446 446
447 if (conn->handle == 0)
448 kfree(conn);
449
447 return 0; 450 return 0;
448} 451}
449 452
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index c405a954a603..43b4c2deb7cc 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -464,7 +464,8 @@ static void hidp_idle_timeout(unsigned long arg)
464{ 464{
465 struct hidp_session *session = (struct hidp_session *) arg; 465 struct hidp_session *session = (struct hidp_session *) arg;
466 466
467 kthread_stop(session->task); 467 atomic_inc(&session->terminate);
468 wake_up_process(session->task);
468} 469}
469 470
470static void hidp_set_timer(struct hidp_session *session) 471static void hidp_set_timer(struct hidp_session *session)
@@ -535,7 +536,8 @@ static void hidp_process_hid_control(struct hidp_session *session,
535 skb_queue_purge(&session->ctrl_transmit); 536 skb_queue_purge(&session->ctrl_transmit);
536 skb_queue_purge(&session->intr_transmit); 537 skb_queue_purge(&session->intr_transmit);
537 538
538 kthread_stop(session->task); 539 atomic_inc(&session->terminate);
540 wake_up_process(current);
539 } 541 }
540} 542}
541 543
@@ -706,9 +708,8 @@ static int hidp_session(void *arg)
706 add_wait_queue(sk_sleep(intr_sk), &intr_wait); 708 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
707 session->waiting_for_startup = 0; 709 session->waiting_for_startup = 0;
708 wake_up_interruptible(&session->startup_queue); 710 wake_up_interruptible(&session->startup_queue);
709 while (!kthread_should_stop()) { 711 set_current_state(TASK_INTERRUPTIBLE);
710 set_current_state(TASK_INTERRUPTIBLE); 712 while (!atomic_read(&session->terminate)) {
711
712 if (ctrl_sk->sk_state != BT_CONNECTED || 713 if (ctrl_sk->sk_state != BT_CONNECTED ||
713 intr_sk->sk_state != BT_CONNECTED) 714 intr_sk->sk_state != BT_CONNECTED)
714 break; 715 break;
@@ -726,6 +727,7 @@ static int hidp_session(void *arg)
726 hidp_process_transmit(session); 727 hidp_process_transmit(session);
727 728
728 schedule(); 729 schedule();
730 set_current_state(TASK_INTERRUPTIBLE);
729 } 731 }
730 set_current_state(TASK_RUNNING); 732 set_current_state(TASK_RUNNING);
731 remove_wait_queue(sk_sleep(intr_sk), &intr_wait); 733 remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
@@ -1060,7 +1062,8 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
1060err_add_device: 1062err_add_device:
1061 hid_destroy_device(session->hid); 1063 hid_destroy_device(session->hid);
1062 session->hid = NULL; 1064 session->hid = NULL;
1063 kthread_stop(session->task); 1065 atomic_inc(&session->terminate);
1066 wake_up_process(session->task);
1064 1067
1065unlink: 1068unlink:
1066 hidp_del_timer(session); 1069 hidp_del_timer(session);
@@ -1111,7 +1114,8 @@ int hidp_del_connection(struct hidp_conndel_req *req)
1111 skb_queue_purge(&session->ctrl_transmit); 1114 skb_queue_purge(&session->ctrl_transmit);
1112 skb_queue_purge(&session->intr_transmit); 1115 skb_queue_purge(&session->intr_transmit);
1113 1116
1114 kthread_stop(session->task); 1117 atomic_inc(&session->terminate);
1118 wake_up_process(session->task);
1115 } 1119 }
1116 } else 1120 } else
1117 err = -ENOENT; 1121 err = -ENOENT;
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index 19e95004b286..af1bcc823f26 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -142,6 +142,7 @@ struct hidp_session {
142 uint ctrl_mtu; 142 uint ctrl_mtu;
143 uint intr_mtu; 143 uint intr_mtu;
144 144
145 atomic_t terminate;
145 struct task_struct *task; 146 struct task_struct *task;
146 147
147 unsigned char keys[8]; 148 unsigned char keys[8];
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9ec9c8c5eb5e..fc219ec28711 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -2530,7 +2530,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
2530 2530
2531 sk = chan->sk; 2531 sk = chan->sk;
2532 2532
2533 if (chan->state != BT_CONFIG) { 2533 if ((bt_sk(sk)->defer_setup && chan->state != BT_CONNECT2) ||
2534 (!bt_sk(sk)->defer_setup && chan->state != BT_CONFIG)) {
2534 struct l2cap_cmd_rej rej; 2535 struct l2cap_cmd_rej rej;
2535 2536
2536 rej.reason = cpu_to_le16(0x0002); 2537 rej.reason = cpu_to_le16(0x0002);
@@ -2541,7 +2542,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
2541 2542
2542 /* Reject if config buffer is too small. */ 2543 /* Reject if config buffer is too small. */
2543 len = cmd_len - sizeof(*req); 2544 len = cmd_len - sizeof(*req);
2544 if (chan->conf_len + len > sizeof(chan->conf_req)) { 2545 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
2545 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, 2546 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2546 l2cap_build_conf_rsp(chan, rsp, 2547 l2cap_build_conf_rsp(chan, rsp,
2547 L2CAP_CONF_REJECT, flags), rsp); 2548 L2CAP_CONF_REJECT, flags), rsp);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index e5a6ea4a94ea..08a45ac3d6f8 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -884,7 +884,8 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
884 for (i = 0; i < IEEE80211_NUM_BANDS; i++) { 884 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
885 local->sched_scan_ies.ie[i] = kzalloc(2 + 885 local->sched_scan_ies.ie[i] = kzalloc(2 +
886 IEEE80211_MAX_SSID_LEN + 886 IEEE80211_MAX_SSID_LEN +
887 local->scan_ies_len, 887 local->scan_ies_len +
888 req->ie_len,
888 GFP_KERNEL); 889 GFP_KERNEL);
889 if (!local->sched_scan_ies.ie[i]) { 890 if (!local->sched_scan_ies.ie[i]) {
890 ret = -ENOMEM; 891 ret = -ENOMEM;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index c22ef3492ee6..880dbe2e6f94 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -366,6 +366,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
366 366
367 mutex_init(&rdev->mtx); 367 mutex_init(&rdev->mtx);
368 mutex_init(&rdev->devlist_mtx); 368 mutex_init(&rdev->devlist_mtx);
369 mutex_init(&rdev->sched_scan_mtx);
369 INIT_LIST_HEAD(&rdev->netdev_list); 370 INIT_LIST_HEAD(&rdev->netdev_list);
370 spin_lock_init(&rdev->bss_lock); 371 spin_lock_init(&rdev->bss_lock);
371 INIT_LIST_HEAD(&rdev->bss_list); 372 INIT_LIST_HEAD(&rdev->bss_list);
@@ -701,6 +702,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
701 rfkill_destroy(rdev->rfkill); 702 rfkill_destroy(rdev->rfkill);
702 mutex_destroy(&rdev->mtx); 703 mutex_destroy(&rdev->mtx);
703 mutex_destroy(&rdev->devlist_mtx); 704 mutex_destroy(&rdev->devlist_mtx);
705 mutex_destroy(&rdev->sched_scan_mtx);
704 list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) 706 list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
705 cfg80211_put_bss(&scan->pub); 707 cfg80211_put_bss(&scan->pub);
706 cfg80211_rdev_free_wowlan(rdev); 708 cfg80211_rdev_free_wowlan(rdev);
@@ -737,12 +739,16 @@ static void wdev_cleanup_work(struct work_struct *work)
737 ___cfg80211_scan_done(rdev, true); 739 ___cfg80211_scan_done(rdev, true);
738 } 740 }
739 741
742 cfg80211_unlock_rdev(rdev);
743
744 mutex_lock(&rdev->sched_scan_mtx);
745
740 if (WARN_ON(rdev->sched_scan_req && 746 if (WARN_ON(rdev->sched_scan_req &&
741 rdev->sched_scan_req->dev == wdev->netdev)) { 747 rdev->sched_scan_req->dev == wdev->netdev)) {
742 __cfg80211_stop_sched_scan(rdev, false); 748 __cfg80211_stop_sched_scan(rdev, false);
743 } 749 }
744 750
745 cfg80211_unlock_rdev(rdev); 751 mutex_unlock(&rdev->sched_scan_mtx);
746 752
747 mutex_lock(&rdev->devlist_mtx); 753 mutex_lock(&rdev->devlist_mtx);
748 rdev->opencount--; 754 rdev->opencount--;
@@ -830,9 +836,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
830 break; 836 break;
831 case NL80211_IFTYPE_P2P_CLIENT: 837 case NL80211_IFTYPE_P2P_CLIENT:
832 case NL80211_IFTYPE_STATION: 838 case NL80211_IFTYPE_STATION:
833 cfg80211_lock_rdev(rdev); 839 mutex_lock(&rdev->sched_scan_mtx);
834 __cfg80211_stop_sched_scan(rdev, false); 840 __cfg80211_stop_sched_scan(rdev, false);
835 cfg80211_unlock_rdev(rdev); 841 mutex_unlock(&rdev->sched_scan_mtx);
836 842
837 wdev_lock(wdev); 843 wdev_lock(wdev);
838#ifdef CONFIG_CFG80211_WEXT 844#ifdef CONFIG_CFG80211_WEXT
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 3dce1f167eba..a570ff9214ec 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -65,6 +65,8 @@ struct cfg80211_registered_device {
65 struct work_struct scan_done_wk; 65 struct work_struct scan_done_wk;
66 struct work_struct sched_scan_results_wk; 66 struct work_struct sched_scan_results_wk;
67 67
68 struct mutex sched_scan_mtx;
69
68#ifdef CONFIG_NL80211_TESTMODE 70#ifdef CONFIG_NL80211_TESTMODE
69 struct genl_info *testmode_info; 71 struct genl_info *testmode_info;
70#endif 72#endif
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 491b0ba40c43..6a82c898f831 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3470,9 +3470,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3470 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 3470 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
3471 return -EINVAL; 3471 return -EINVAL;
3472 3472
3473 if (rdev->sched_scan_req)
3474 return -EINPROGRESS;
3475
3476 if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) 3473 if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
3477 return -EINVAL; 3474 return -EINVAL;
3478 3475
@@ -3511,12 +3508,21 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3511 if (ie_len > wiphy->max_scan_ie_len) 3508 if (ie_len > wiphy->max_scan_ie_len)
3512 return -EINVAL; 3509 return -EINVAL;
3513 3510
3511 mutex_lock(&rdev->sched_scan_mtx);
3512
3513 if (rdev->sched_scan_req) {
3514 err = -EINPROGRESS;
3515 goto out;
3516 }
3517
3514 request = kzalloc(sizeof(*request) 3518 request = kzalloc(sizeof(*request)
3515 + sizeof(*request->ssids) * n_ssids 3519 + sizeof(*request->ssids) * n_ssids
3516 + sizeof(*request->channels) * n_channels 3520 + sizeof(*request->channels) * n_channels
3517 + ie_len, GFP_KERNEL); 3521 + ie_len, GFP_KERNEL);
3518 if (!request) 3522 if (!request) {
3519 return -ENOMEM; 3523 err = -ENOMEM;
3524 goto out;
3525 }
3520 3526
3521 if (n_ssids) 3527 if (n_ssids)
3522 request->ssids = (void *)&request->channels[n_channels]; 3528 request->ssids = (void *)&request->channels[n_channels];
@@ -3614,6 +3620,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
3614out_free: 3620out_free:
3615 kfree(request); 3621 kfree(request);
3616out: 3622out:
3623 mutex_unlock(&rdev->sched_scan_mtx);
3617 return err; 3624 return err;
3618} 3625}
3619 3626
@@ -3621,12 +3628,17 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
3621 struct genl_info *info) 3628 struct genl_info *info)
3622{ 3629{
3623 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 3630 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3631 int err;
3624 3632
3625 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || 3633 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
3626 !rdev->ops->sched_scan_stop) 3634 !rdev->ops->sched_scan_stop)
3627 return -EOPNOTSUPP; 3635 return -EOPNOTSUPP;
3628 3636
3629 return __cfg80211_stop_sched_scan(rdev, false); 3637 mutex_lock(&rdev->sched_scan_mtx);
3638 err = __cfg80211_stop_sched_scan(rdev, false);
3639 mutex_unlock(&rdev->sched_scan_mtx);
3640
3641 return err;
3630} 3642}
3631 3643
3632static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, 3644static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ce04566a2ecc..1c4672e35144 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -100,14 +100,14 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
100 rdev = container_of(wk, struct cfg80211_registered_device, 100 rdev = container_of(wk, struct cfg80211_registered_device,
101 sched_scan_results_wk); 101 sched_scan_results_wk);
102 102
103 cfg80211_lock_rdev(rdev); 103 mutex_lock(&rdev->sched_scan_mtx);
104 104
105 /* we don't have sched_scan_req anymore if the scan is stopping */ 105 /* we don't have sched_scan_req anymore if the scan is stopping */
106 if (rdev->sched_scan_req) 106 if (rdev->sched_scan_req)
107 nl80211_send_sched_scan_results(rdev, 107 nl80211_send_sched_scan_results(rdev,
108 rdev->sched_scan_req->dev); 108 rdev->sched_scan_req->dev);
109 109
110 cfg80211_unlock_rdev(rdev); 110 mutex_unlock(&rdev->sched_scan_mtx);
111} 111}
112 112
113void cfg80211_sched_scan_results(struct wiphy *wiphy) 113void cfg80211_sched_scan_results(struct wiphy *wiphy)
@@ -123,9 +123,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
123{ 123{
124 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 124 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
125 125
126 cfg80211_lock_rdev(rdev); 126 mutex_lock(&rdev->sched_scan_mtx);
127 __cfg80211_stop_sched_scan(rdev, true); 127 __cfg80211_stop_sched_scan(rdev, true);
128 cfg80211_unlock_rdev(rdev); 128 mutex_unlock(&rdev->sched_scan_mtx);
129} 129}
130EXPORT_SYMBOL(cfg80211_sched_scan_stopped); 130EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
131 131
@@ -134,7 +134,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
134{ 134{
135 struct net_device *dev; 135 struct net_device *dev;
136 136
137 ASSERT_RDEV_LOCK(rdev); 137 lockdep_assert_held(&rdev->sched_scan_mtx);
138 138
139 if (!rdev->sched_scan_req) 139 if (!rdev->sched_scan_req)
140 return -ENOENT; 140 return -ENOENT;