aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211_sta.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/ieee80211_sta.c')
-rw-r--r--net/mac80211/ieee80211_sta.c66
1 files changed, 44 insertions, 22 deletions
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
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;