mac80211: Generalize off-channel operation helpers from scan code
[safe/jmp/linux-2.6] / net / mac80211 / ieee80211_i.h
index 88b0ba6..fd912eb 100644 (file)
@@ -71,9 +71,6 @@ struct ieee80211_fragment_entry {
 
 
 struct ieee80211_bss {
-       /* Yes, this is a hack */
-       struct cfg80211_bss cbss;
-
        /* don't want to look up all the time */
        size_t ssid_len;
        u8 ssid[IEEE80211_MAX_SSID_LEN];
@@ -227,31 +224,70 @@ struct mesh_preq_queue {
        u8 flags;
 };
 
-enum ieee80211_mgd_state {
-       IEEE80211_MGD_STATE_IDLE,
-       IEEE80211_MGD_STATE_PROBE,
-       IEEE80211_MGD_STATE_AUTH,
-       IEEE80211_MGD_STATE_ASSOC,
+enum ieee80211_work_type {
+       IEEE80211_WORK_DIRECT_PROBE,
+       IEEE80211_WORK_AUTH,
+       IEEE80211_WORK_ASSOC,
+};
+
+/**
+ * enum work_done_result - indicates what to do after work was done
+ *
+ * @WORK_DONE_DESTROY: This work item is no longer needed, destroy.
+ * @WORK_DONE_REQUEUE: This work item was reset to be reused, and
+ *     should be requeued.
+ */
+enum work_done_result {
+       WORK_DONE_DESTROY,
+       WORK_DONE_REQUEUE,
 };
 
-struct ieee80211_mgd_work {
+struct ieee80211_work {
        struct list_head list;
-       struct ieee80211_bss *bss;
-       int ie_len;
-       u8 prev_bssid[ETH_ALEN];
-       u8 ssid[IEEE80211_MAX_SSID_LEN];
-       u8 ssid_len;
+
+       struct rcu_head rcu_head;
+
+       struct ieee80211_sub_if_data *sdata;
+
+       enum work_done_result (*done)(struct ieee80211_work *wk,
+                                     struct sk_buff *skb);
+
+       struct ieee80211_channel *chan;
+       /* XXX: chan type? -- right now not really needed */
+
        unsigned long timeout;
-       enum ieee80211_mgd_state state;
-       u16 auth_alg, auth_transaction;
+       enum ieee80211_work_type type;
 
-       int tries;
+       u8 filter_ta[ETH_ALEN];
 
-       u8 key[WLAN_KEY_LEN_WEP104];
-       u8 key_len, key_idx;
+       union {
+               struct {
+                       int tries;
+                       u16 algorithm, transaction;
+                       u8 ssid[IEEE80211_MAX_SSID_LEN];
+                       u8 ssid_len;
+                       u8 key[WLAN_KEY_LEN_WEP104];
+                       u8 key_len, key_idx;
+                       bool privacy;
+               } probe_auth;
+               struct {
+                       struct cfg80211_bss *bss;
+                       const u8 *supp_rates;
+                       const u8 *ht_information_ie;
+                       enum ieee80211_smps_mode smps;
+                       int tries;
+                       u16 capability;
+                       u8 prev_bssid[ETH_ALEN];
+                       u8 ssid[IEEE80211_MAX_SSID_LEN];
+                       u8 ssid_len;
+                       u8 supp_rates_len;
+                       bool wmm_used, use_11n;
+               } assoc;
+       };
 
+       int ie_len;
        /* must be last */
-       u8 ie[0]; /* for auth or assoc frame, not probe */
+       u8 ie[0];
 };
 
 /* flags used in struct ieee80211_if_managed.flags */
@@ -259,17 +295,11 @@ enum ieee80211_sta_flags {
        IEEE80211_STA_BEACON_POLL       = BIT(0),
        IEEE80211_STA_CONNECTION_POLL   = BIT(1),
        IEEE80211_STA_CONTROL_PORT      = BIT(2),
-       IEEE80211_STA_WMM_ENABLED       = BIT(3),
        IEEE80211_STA_DISABLE_11N       = BIT(4),
        IEEE80211_STA_CSA_RECEIVED      = BIT(5),
        IEEE80211_STA_MFP_ENABLED       = BIT(6),
 };
 
-/* flags for MLME request */
-enum ieee80211_sta_request {
-       IEEE80211_STA_REQ_SCAN,
-};
-
 struct ieee80211_if_managed {
        struct timer_list timer;
        struct timer_list conn_mon_timer;
@@ -284,14 +314,11 @@ struct ieee80211_if_managed {
        int probe_send_count;
 
        struct mutex mtx;
-       struct ieee80211_bss *associated;
-       struct ieee80211_mgd_work *old_associate_work;
-       struct list_head work_list;
+       struct cfg80211_bss *associated;
 
        u8 bssid[ETH_ALEN];
 
        u16 aid;
-       u16 capab;
 
        struct sk_buff_head skb_queue;
 
@@ -300,8 +327,6 @@ struct ieee80211_if_managed {
        enum ieee80211_smps_mode req_smps, /* requested smps mode */
                                 ap_smps; /* smps mode AP thinks we're in */
 
-       unsigned long request;
-
        unsigned int flags;
 
        u32 beacon_crc;
@@ -568,6 +593,15 @@ struct ieee80211_local {
        const struct ieee80211_ops *ops;
 
        /*
+        * work stuff, potentially off-channel (in the future)
+        */
+       struct mutex work_mtx;
+       struct list_head work_list;
+       struct timer_list work_timer;
+       struct work_struct work_work;
+       struct sk_buff_head work_skb_queue;
+
+       /*
         * private workqueue to mac80211. mac80211 makes this accessible
         * via ieee80211_queue_work()
         */
@@ -752,7 +786,7 @@ struct ieee80211_local {
        unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
 
        bool pspolling;
-       bool scan_ps_enabled;
+       bool offchannel_ps_enabled;
        /*
         * PS can only be enabled when we have exactly one managed
         * interface (and monitors) in PS, this then points there.
@@ -947,6 +981,12 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
 void ieee80211_rx_bss_put(struct ieee80211_local *local,
                          struct ieee80211_bss *bss);
 
+/* off-channel helpers */
+void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local);
+void ieee80211_offchannel_stop_station(struct ieee80211_local *local);
+void ieee80211_offchannel_return(struct ieee80211_local *local,
+                                bool enable_beaconing);
+
 /* interface handling */
 int ieee80211_iface_init(void);
 void ieee80211_iface_exit(void);
@@ -960,6 +1000,11 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local);
 u32 __ieee80211_recalc_idle(struct ieee80211_local *local);
 void ieee80211_recalc_idle(struct ieee80211_local *local);
 
+static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
+{
+       return netif_running(sdata->dev);
+}
+
 /* tx handling */
 void ieee80211_clear_tx_pending(struct ieee80211_local *local);
 void ieee80211_tx_pending(unsigned long data);
@@ -1106,6 +1151,18 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
 void ieee80211_recalc_smps(struct ieee80211_local *local,
                           struct ieee80211_sub_if_data *forsdata);
 
+size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
+                         const u8 *ids, int n_ids, size_t offset);
+size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
+
+/* internal work items */
+void ieee80211_work_init(struct ieee80211_local *local);
+void ieee80211_add_work(struct ieee80211_work *wk);
+void free_work(struct ieee80211_work *wk);
+void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata);
+ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
+                                          struct sk_buff *skb);
+
 #ifdef CONFIG_MAC80211_NOINLINE
 #define debug_noinline noinline
 #else