aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/ieee80211.c13
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/ieee80211_ioctl.c6
-rw-r--r--net/mac80211/ieee80211_sta.c66
-rw-r--r--net/mac80211/rx.c12
-rw-r--r--net/mac80211/tx.c2
6 files changed, 70 insertions, 35 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 6378850d858..4f8b6653e36 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -350,11 +350,14 @@ static int ieee80211_stop(struct net_device *dev)
350 synchronize_rcu(); 350 synchronize_rcu();
351 skb_queue_purge(&sdata->u.sta.skb_queue); 351 skb_queue_purge(&sdata->u.sta.skb_queue);
352 352
353 if (!local->ops->hw_scan && 353 if (local->scan_dev == sdata->dev) {
354 local->scan_dev == sdata->dev) { 354 if (!local->ops->hw_scan) {
355 local->sta_scanning = 0; 355 local->sta_sw_scanning = 0;
356 cancel_delayed_work(&local->scan_work); 356 cancel_delayed_work(&local->scan_work);
357 } else
358 local->sta_hw_scanning = 0;
357 } 359 }
360
358 flush_workqueue(local->hw.workqueue); 361 flush_workqueue(local->hw.workqueue);
359 362
360 sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; 363 sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
@@ -526,7 +529,7 @@ int ieee80211_hw_config(struct ieee80211_local *local)
526 struct ieee80211_channel *chan; 529 struct ieee80211_channel *chan;
527 int ret = 0; 530 int ret = 0;
528 531
529 if (local->sta_scanning) { 532 if (local->sta_sw_scanning) {
530 chan = local->scan_channel; 533 chan = local->scan_channel;
531 mode = local->scan_hw_mode; 534 mode = local->scan_hw_mode;
532 } else { 535 } else {
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 2be7fcebac4..e9109443cb1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -470,7 +470,8 @@ struct ieee80211_local {
470 470
471 struct list_head interfaces; 471 struct list_head interfaces;
472 472
473 int sta_scanning; 473 bool sta_sw_scanning;
474 bool sta_hw_scanning;
474 int scan_channel_idx; 475 int scan_channel_idx;
475 enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; 476 enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
476 unsigned long last_scan_completed; 477 unsigned long last_scan_completed;
@@ -745,7 +746,8 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len);
745void ieee80211_sta_req_auth(struct net_device *dev, 746void ieee80211_sta_req_auth(struct net_device *dev,
746 struct ieee80211_if_sta *ifsta); 747 struct ieee80211_if_sta *ifsta);
747int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len); 748int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len);
748void ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, 749ieee80211_txrx_result ieee80211_sta_rx_scan(struct net_device *dev,
750 struct sk_buff *skb,
749 struct ieee80211_rx_status *rx_status); 751 struct ieee80211_rx_status *rx_status);
750void ieee80211_rx_bss_list_init(struct net_device *dev); 752void ieee80211_rx_bss_list_init(struct net_device *dev);
751void ieee80211_rx_bss_list_deinit(struct net_device *dev); 753void ieee80211_rx_bss_list_deinit(struct net_device *dev);
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index bbd9bc572a5..dc03bd796fe 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -315,7 +315,7 @@ int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq)
315 } 315 }
316 316
317 if (set) { 317 if (set) {
318 if (local->sta_scanning) 318 if (local->sta_sw_scanning)
319 ret = 0; 319 ret = 0;
320 else 320 else
321 ret = ieee80211_hw_config(local); 321 ret = ieee80211_hw_config(local);
@@ -545,8 +545,10 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev,
545{ 545{
546 int res; 546 int res;
547 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 547 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
548 if (local->sta_scanning) 548
549 if (local->sta_sw_scanning || local->sta_hw_scanning)
549 return -EAGAIN; 550 return -EAGAIN;
551
550 res = ieee80211_sta_scan_results(dev, extra, data->length); 552 res = ieee80211_sta_scan_results(dev, extra, data->length);
551 if (res >= 0) { 553 if (res >= 0) {
552 data->length = res; 554 data->length = res;
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 4f9be2fb2bf..231a663ad91 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -1483,8 +1483,18 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
1483 u32 supp_rates, prev_rates; 1483 u32 supp_rates, prev_rates;
1484 int i, j; 1484 int i, j;
1485 1485
1486 mode = local->sta_scanning ? 1486 mode = local->sta_sw_scanning ?
1487 local->scan_hw_mode : local->oper_hw_mode; 1487 local->scan_hw_mode : local->oper_hw_mode;
1488
1489 if (local->sta_hw_scanning) {
1490 /* search for the correct mode matches the beacon */
1491 list_for_each_entry(mode, &local->modes_list, list)
1492 if (mode->mode == rx_status->phymode)
1493 break;
1494
1495 if (mode == NULL)
1496 mode = local->oper_hw_mode;
1497 }
1488 rates = mode->rates; 1498 rates = mode->rates;
1489 num_rates = mode->num_rates; 1499 num_rates = mode->num_rates;
1490 1500
@@ -1867,31 +1877,39 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,
1867} 1877}
1868 1878
1869 1879
1870void ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, 1880ieee80211_txrx_result
1871 struct ieee80211_rx_status *rx_status) 1881ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,
1882 struct ieee80211_rx_status *rx_status)
1872{ 1883{
1873 struct ieee80211_mgmt *mgmt; 1884 struct ieee80211_mgmt *mgmt;
1874 u16 fc; 1885 u16 fc;
1875 1886
1876 if (skb->len < 24) { 1887 if (skb->len < 2)
1877 dev_kfree_skb(skb); 1888 return TXRX_DROP;
1878 return;
1879 }
1880 1889
1881 mgmt = (struct ieee80211_mgmt *) skb->data; 1890 mgmt = (struct ieee80211_mgmt *) skb->data;
1882 fc = le16_to_cpu(mgmt->frame_control); 1891 fc = le16_to_cpu(mgmt->frame_control);
1883 1892
1893 if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL)
1894 return TXRX_CONTINUE;
1895
1896 if (skb->len < 24)
1897 return TXRX_DROP;
1898
1884 if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) { 1899 if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
1885 if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) { 1900 if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) {
1886 ieee80211_rx_mgmt_probe_resp(dev, mgmt, 1901 ieee80211_rx_mgmt_probe_resp(dev, mgmt,
1887 skb->len, rx_status); 1902 skb->len, rx_status);
1903 dev_kfree_skb(skb);
1904 return TXRX_QUEUED;
1888 } else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) { 1905 } else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) {
1889 ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, 1906 ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len,
1890 rx_status); 1907 rx_status);
1908 dev_kfree_skb(skb);
1909 return TXRX_QUEUED;
1891 } 1910 }
1892 } 1911 }
1893 1912 return TXRX_CONTINUE;
1894 dev_kfree_skb(skb);
1895} 1913}
1896 1914
1897 1915
@@ -1981,7 +1999,7 @@ void ieee80211_sta_work(struct work_struct *work)
1981 if (!netif_running(dev)) 1999 if (!netif_running(dev))
1982 return; 2000 return;
1983 2001
1984 if (local->sta_scanning) 2002 if (local->sta_sw_scanning || local->sta_hw_scanning)
1985 return; 2003 return;
1986 2004
1987 if (sdata->type != IEEE80211_IF_TYPE_STA && 2005 if (sdata->type != IEEE80211_IF_TYPE_STA &&
@@ -2639,9 +2657,15 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
2639 union iwreq_data wrqu; 2657 union iwreq_data wrqu;
2640 2658
2641 local->last_scan_completed = jiffies; 2659 local->last_scan_completed = jiffies;
2642 wmb(); 2660 memset(&wrqu, 0, sizeof(wrqu));
2643 local->sta_scanning = 0; 2661 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
2644 2662
2663 if (local->sta_hw_scanning) {
2664 local->sta_hw_scanning = 0;
2665 goto done;
2666 }
2667
2668 local->sta_sw_scanning = 0;
2645 if (ieee80211_hw_config(local)) 2669 if (ieee80211_hw_config(local))
2646 printk(KERN_DEBUG "%s: failed to restore operational " 2670 printk(KERN_DEBUG "%s: failed to restore operational "
2647 "channel after scan\n", dev->name); 2671 "channel after scan\n", dev->name);
@@ -2657,9 +2681,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
2657 2681
2658 netif_tx_unlock_bh(local->mdev); 2682 netif_tx_unlock_bh(local->mdev);
2659 2683
2660 memset(&wrqu, 0, sizeof(wrqu));
2661 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
2662
2663 rcu_read_lock(); 2684 rcu_read_lock();
2664 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 2685 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
2665 2686
@@ -2677,6 +2698,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
2677 } 2698 }
2678 rcu_read_unlock(); 2699 rcu_read_unlock();
2679 2700
2701done:
2680 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 2702 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2681 if (sdata->type == IEEE80211_IF_TYPE_IBSS) { 2703 if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
2682 struct ieee80211_if_sta *ifsta = &sdata->u.sta; 2704 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
@@ -2699,7 +2721,7 @@ void ieee80211_sta_scan_work(struct work_struct *work)
2699 int skip; 2721 int skip;
2700 unsigned long next_delay = 0; 2722 unsigned long next_delay = 0;
2701 2723
2702 if (!local->sta_scanning) 2724 if (!local->sta_sw_scanning)
2703 return; 2725 return;
2704 2726
2705 switch (local->scan_state) { 2727 switch (local->scan_state) {
@@ -2762,7 +2784,7 @@ void ieee80211_sta_scan_work(struct work_struct *work)
2762 break; 2784 break;
2763 } 2785 }
2764 2786
2765 if (local->sta_scanning) 2787 if (local->sta_sw_scanning)
2766 queue_delayed_work(local->hw.workqueue, &local->scan_work, 2788 queue_delayed_work(local->hw.workqueue, &local->scan_work,
2767 next_delay); 2789 next_delay);
2768} 2790}
@@ -2794,7 +2816,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev,
2794 * ResultCode: SUCCESS, INVALID_PARAMETERS 2816 * ResultCode: SUCCESS, INVALID_PARAMETERS
2795 */ 2817 */
2796 2818
2797 if (local->sta_scanning) { 2819 if (local->sta_sw_scanning || local->sta_hw_scanning) {
2798 if (local->scan_dev == dev) 2820 if (local->scan_dev == dev)
2799 return 0; 2821 return 0;
2800 return -EBUSY; 2822 return -EBUSY;
@@ -2802,15 +2824,15 @@ static int ieee80211_sta_start_scan(struct net_device *dev,
2802 2824
2803 if (local->ops->hw_scan) { 2825 if (local->ops->hw_scan) {
2804 int rc = local->ops->hw_scan(local_to_hw(local), 2826 int rc = local->ops->hw_scan(local_to_hw(local),
2805 ssid, ssid_len); 2827 ssid, ssid_len);
2806 if (!rc) { 2828 if (!rc) {
2807 local->sta_scanning = 1; 2829 local->sta_hw_scanning = 1;
2808 local->scan_dev = dev; 2830 local->scan_dev = dev;
2809 } 2831 }
2810 return rc; 2832 return rc;
2811 } 2833 }
2812 2834
2813 local->sta_scanning = 1; 2835 local->sta_sw_scanning = 1;
2814 2836
2815 rcu_read_lock(); 2837 rcu_read_lock();
2816 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 2838 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
@@ -2865,7 +2887,7 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len)
2865 if (sdata->type != IEEE80211_IF_TYPE_STA) 2887 if (sdata->type != IEEE80211_IF_TYPE_STA)
2866 return ieee80211_sta_start_scan(dev, ssid, ssid_len); 2888 return ieee80211_sta_start_scan(dev, ssid, ssid_len);
2867 2889
2868 if (local->sta_scanning) { 2890 if (local->sta_sw_scanning || local->sta_hw_scanning) {
2869 if (local->scan_dev == dev) 2891 if (local->scan_dev == dev)
2870 return 0; 2892 return 0;
2871 return -EBUSY; 2893 return -EBUSY;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a7263fc476b..a26aa7f5049 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -338,8 +338,14 @@ ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx)
338 struct ieee80211_local *local = rx->local; 338 struct ieee80211_local *local = rx->local;
339 struct sk_buff *skb = rx->skb; 339 struct sk_buff *skb = rx->skb;
340 340
341 if (unlikely(local->sta_scanning != 0)) { 341 if (unlikely(local->sta_hw_scanning))
342 ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status); 342 return ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status);
343
344 if (unlikely(local->sta_sw_scanning)) {
345 /* drop all the other packets during a software scan anyway */
346 if (ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status)
347 != TXRX_QUEUED)
348 dev_kfree_skb(skb);
343 return TXRX_QUEUED; 349 return TXRX_QUEUED;
344 } 350 }
345 351
@@ -1499,7 +1505,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
1499 goto end; 1505 goto end;
1500 } 1506 }
1501 1507
1502 if (unlikely(local->sta_scanning)) 1508 if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning))
1503 rx.flags |= IEEE80211_TXRXD_RXIN_SCAN; 1509 rx.flags |= IEEE80211_TXRXD_RXIN_SCAN;
1504 1510
1505 if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx, 1511 if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 9ccf4b5a9aa..50ab4b2de1e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -225,7 +225,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
225 if (unlikely(tx->flags & IEEE80211_TXRXD_TX_INJECTED)) 225 if (unlikely(tx->flags & IEEE80211_TXRXD_TX_INJECTED))
226 return TXRX_CONTINUE; 226 return TXRX_CONTINUE;
227 227
228 if (unlikely(tx->local->sta_scanning != 0) && 228 if (unlikely(tx->local->sta_sw_scanning) &&
229 ((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || 229 ((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
230 (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ)) 230 (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ))
231 return TXRX_DROP; 231 return TXRX_DROP;