diff options
-rw-r--r-- | net/mac80211/ieee80211.c | 13 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 6 | ||||
-rw-r--r-- | net/mac80211/ieee80211_ioctl.c | 6 | ||||
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 66 | ||||
-rw-r--r-- | net/mac80211/rx.c | 12 | ||||
-rw-r--r-- | net/mac80211/tx.c | 2 |
6 files changed, 70 insertions, 35 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 6378850d8580..4f8b6653e364 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 2be7fcebac48..e9109443cb10 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); | |||
745 | void ieee80211_sta_req_auth(struct net_device *dev, | 746 | void ieee80211_sta_req_auth(struct net_device *dev, |
746 | struct ieee80211_if_sta *ifsta); | 747 | struct ieee80211_if_sta *ifsta); |
747 | int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len); | 748 | int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len); |
748 | void ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, | 749 | ieee80211_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); |
750 | void ieee80211_rx_bss_list_init(struct net_device *dev); | 752 | void ieee80211_rx_bss_list_init(struct net_device *dev); |
751 | void ieee80211_rx_bss_list_deinit(struct net_device *dev); | 753 | void ieee80211_rx_bss_list_deinit(struct net_device *dev); |
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index bbd9bc572a54..dc03bd796fee 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 4f9be2fb2bfc..231a663ad914 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 | ||
1870 | void ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, | 1880 | ieee80211_txrx_result |
1871 | struct ieee80211_rx_status *rx_status) | 1881 | ieee80211_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 | ||
2701 | done: | ||
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 a7263fc476bd..a26aa7f50495 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 9ccf4b5a9aad..50ab4b2de1e9 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; |