]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/mac80211/scan.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[mv-sheeva.git] / net / mac80211 / scan.c
index 086d21645cbc2ab03e93f418f7b236e86db869a5..2a8d09ad17ff8829cc777143d0cff77dff6052c3 100644 (file)
@@ -21,6 +21,7 @@
 #include <net/iw_handler.h>
 
 #include "ieee80211_i.h"
+#include "driver-ops.h"
 #include "mesh.h"
 
 #define IEEE80211_PROBE_DELAY (HZ / 33)
@@ -297,36 +298,27 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
        was_hw_scan = local->hw_scanning;
        local->hw_scanning = false;
        local->sw_scanning = false;
+       local->scan_channel = NULL;
 
        /* we only have to protect scan_req and hw/sw scan */
        mutex_unlock(&local->scan_mtx);
 
-       if (was_hw_scan) {
-               /*
-                * Somebody might have requested channel change during scan
-                * that we won't have acted upon, try now. ieee80211_hw_config
-                * will set the flag based on actual changes.
-                */
-               ieee80211_hw_config(local, 0);
-               goto done;
-       }
-
        ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+       if (was_hw_scan)
+               goto done;
 
        netif_tx_lock_bh(local->mdev);
        netif_addr_lock(local->mdev);
        local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
-       local->ops->configure_filter(local_to_hw(local),
-                                    FIF_BCN_PRBRESP_PROMISC,
-                                    &local->filter_flags,
-                                    local->mdev->mc_count,
-                                    local->mdev->mc_list);
+       drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC,
+                            &local->filter_flags,
+                            local->mdev->mc_count,
+                            local->mdev->mc_list);
 
        netif_addr_unlock(local->mdev);
        netif_tx_unlock_bh(local->mdev);
 
-       if (local->ops->sw_scan_complete)
-               local->ops->sw_scan_complete(local_to_hw(local));
+       drv_sw_scan_complete(local);
 
        mutex_lock(&local->iflist_mtx);
        list_for_each_entry(sdata, &local->interfaces, list) {
@@ -346,12 +338,13 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
                if (sdata->vif.type == NL80211_IFTYPE_AP ||
                    sdata->vif.type == NL80211_IFTYPE_ADHOC ||
                    sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
-                       ieee80211_if_config(sdata,
-                                           IEEE80211_IFCC_BEACON_ENABLED);
+                       ieee80211_bss_info_change_notify(
+                               sdata, BSS_CHANGED_BEACON_ENABLED);
        }
        mutex_unlock(&local->iflist_mtx);
 
  done:
+       ieee80211_recalc_idle(local);
        ieee80211_mlme_notify_scan_completed(local);
        ieee80211_ibss_notify_scan_completed(local);
        ieee80211_mesh_notify_scan_completed(local);
@@ -375,8 +368,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
         * nullfunc frames and probe requests will be dropped in
         * ieee80211_tx_h_check_assoc().
         */
-       if (local->ops->sw_scan_start)
-               local->ops->sw_scan_start(local_to_hw(local));
+       drv_sw_scan_start(local);
 
        mutex_lock(&local->iflist_mtx);
        list_for_each_entry(sdata, &local->interfaces, list) {
@@ -387,8 +379,8 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
                if (sdata->vif.type == NL80211_IFTYPE_AP ||
                    sdata->vif.type == NL80211_IFTYPE_ADHOC ||
                    sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
-                       ieee80211_if_config(sdata,
-                                           IEEE80211_IFCC_BEACON_ENABLED);
+                       ieee80211_bss_info_change_notify(
+                               sdata, BSS_CHANGED_BEACON_ENABLED);
 
                if (sdata->vif.type == NL80211_IFTYPE_STATION) {
                        if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) {
@@ -405,11 +397,10 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
 
        netif_addr_lock_bh(local->mdev);
        local->filter_flags |= FIF_BCN_PRBRESP_PROMISC;
-       local->ops->configure_filter(local_to_hw(local),
-                                    FIF_BCN_PRBRESP_PROMISC,
-                                    &local->filter_flags,
-                                    local->mdev->mc_count,
-                                    local->mdev->mc_list);
+       drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC,
+                            &local->filter_flags,
+                            local->mdev->mc_count,
+                            local->mdev->mc_list);
        netif_addr_unlock_bh(local->mdev);
 
        /* TODO: start scan as soon as all nullfunc frames are ACKed */
@@ -474,11 +465,12 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
         * dependency, so that the scan completed calls
         * have more locking freedom.
         */
+
+       ieee80211_recalc_idle(local);
        mutex_unlock(&local->scan_mtx);
 
        if (local->ops->hw_scan)
-               rc = local->ops->hw_scan(local_to_hw(local),
-                                        local->scan_req);
+               rc = drv_hw_scan(local, local->scan_req);
        else
                rc = ieee80211_start_sw_scan(local);
 
@@ -491,6 +483,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
                } else
                        local->sw_scanning = false;
 
+               ieee80211_recalc_idle(local);
+
                local->scan_req = NULL;
                local->scan_sdata = NULL;
        }
@@ -565,24 +559,39 @@ void ieee80211_scan_work(struct work_struct *work)
                if (skip)
                        break;
 
-               next_delay = IEEE80211_PROBE_DELAY +
-                            usecs_to_jiffies(local->hw.channel_change_time);
+               /*
+                * Probe delay is used to update the NAV, cf. 11.1.3.2.2
+                * (which unfortunately doesn't say _why_ step a) is done,
+                * but it waits for the probe delay or until a frame is
+                * received - and the received frame would update the NAV).
+                * For now, we do not support waiting until a frame is
+                * received.
+                *
+                * In any case, it is not necessary for a passive scan.
+                */
+               if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
+                   !local->scan_req->n_ssids) {
+                       next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+                       break;
+               }
+
+               next_delay = IEEE80211_PROBE_DELAY;
                local->scan_state = SCAN_SEND_PROBE;
                break;
        case SCAN_SEND_PROBE:
-               next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
-               local->scan_state = SCAN_SET_CHANNEL;
-
-               if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
-                   !local->scan_req->n_ssids)
-                       break;
                for (i = 0; i < local->scan_req->n_ssids; i++)
                        ieee80211_send_probe_req(
                                sdata, NULL,
                                local->scan_req->ssids[i].ssid,
                                local->scan_req->ssids[i].ssid_len,
                                local->scan_req->ie, local->scan_req->ie_len);
+
+               /*
+                * After sending probe requests, wait for probe responses
+                * on the channel.
+                */
                next_delay = IEEE80211_CHANNEL_TIME;
+               local->scan_state = SCAN_SET_CHANNEL;
                break;
        }
 
@@ -622,3 +631,21 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
        mutex_unlock(&local->scan_mtx);
        return ret;
 }
+
+void ieee80211_scan_cancel(struct ieee80211_local *local)
+{
+       bool swscan;
+
+       cancel_delayed_work_sync(&local->scan_work);
+
+       /*
+        * Only call this function when a scan can't be
+        * queued -- mostly at suspend under RTNL.
+        */
+       mutex_lock(&local->scan_mtx);
+       swscan = local->sw_scanning;
+       mutex_unlock(&local->scan_mtx);
+
+       if (swscan)
+               ieee80211_scan_completed(&local->hw, true);
+}