Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth
[pandora-kernel.git] / net / mac80211 / sta_info.h
index 28beb78..8c8ce05 100644 (file)
@@ -19,7 +19,8 @@
 /**
  * enum ieee80211_sta_info_flags - Stations flags
  *
- * These flags are used with &struct sta_info's @flags member.
+ * These flags are used with &struct sta_info's @flags member, but
+ * only indirectly with set_sta_flag() and friends.
  *
  * @WLAN_STA_AUTH: Station is authenticated.
  * @WLAN_STA_ASSOC: Station is associated.
  *     be in the queues
  * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping
  *     station in power-save mode, reply when the driver unblocks.
- * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal
- *     buffers. Automatically cleared on station wake-up.
+ * @WLAN_STA_TDLS_PEER: Station is a TDLS peer.
+ * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct
+ *     packets. This means the link is enabled.
+ * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was
+ *     keeping station in power-save mode, reply when the driver
+ *     unblocks the station.
+ * @WLAN_STA_SP: Station is in a service period, so don't try to
+ *     reply to other uAPSD trigger frames or PS-Poll.
  */
 enum ieee80211_sta_info_flags {
-       WLAN_STA_AUTH           = 1<<0,
-       WLAN_STA_ASSOC          = 1<<1,
-       WLAN_STA_PS_STA         = 1<<2,
-       WLAN_STA_AUTHORIZED     = 1<<3,
-       WLAN_STA_SHORT_PREAMBLE = 1<<4,
-       WLAN_STA_ASSOC_AP       = 1<<5,
-       WLAN_STA_WME            = 1<<6,
-       WLAN_STA_WDS            = 1<<7,
-       WLAN_STA_CLEAR_PS_FILT  = 1<<9,
-       WLAN_STA_MFP            = 1<<10,
-       WLAN_STA_BLOCK_BA       = 1<<11,
-       WLAN_STA_PS_DRIVER      = 1<<12,
-       WLAN_STA_PSPOLL         = 1<<13,
-       WLAN_STA_PS_DRIVER_BUF  = 1<<14,
+       WLAN_STA_AUTH,
+       WLAN_STA_ASSOC,
+       WLAN_STA_PS_STA,
+       WLAN_STA_AUTHORIZED,
+       WLAN_STA_SHORT_PREAMBLE,
+       WLAN_STA_ASSOC_AP,
+       WLAN_STA_WME,
+       WLAN_STA_WDS,
+       WLAN_STA_CLEAR_PS_FILT,
+       WLAN_STA_MFP,
+       WLAN_STA_BLOCK_BA,
+       WLAN_STA_PS_DRIVER,
+       WLAN_STA_PSPOLL,
+       WLAN_STA_TDLS_PEER,
+       WLAN_STA_TDLS_PEER_AUTH,
+       WLAN_STA_UAPSD,
+       WLAN_STA_SP,
 };
 
 #define STA_TID_NUM 16
@@ -86,6 +96,8 @@ enum ieee80211_sta_info_flags {
  * @stop_initiator: initiator of a session stop
  * @tx_stop: TX DelBA frame when stopping
  * @buf_size: reorder buffer size at receiver
+ * @failed_bar_ssn: ssn of the last failed BAR tx attempt
+ * @bar_pending: BAR needs to be re-sent
  *
  * This structure's lifetime is managed by RCU, assignments to
  * the array holding it must hold the aggregation mutex.
@@ -106,6 +118,9 @@ struct tid_ampdu_tx {
        u8 stop_initiator;
        bool tx_stop;
        u8 buf_size;
+
+       u16 failed_bar_ssn;
+       bool bar_pending;
 };
 
 /**
@@ -198,15 +213,16 @@ struct sta_ampdu_mlme {
  * @last_rx_rate_flag: rx status flag of the last data packet
  * @lock: used for locking all fields that require locking, see comments
  *     in the header file.
- * @flaglock: spinlock for flags accesses
  * @drv_unblock_wk: used for driver PS unblocking
  * @listen_interval: listen interval of this station, when we're acting as AP
- * @flags: STA flags, see &enum ieee80211_sta_info_flags
- * @ps_tx_buf: buffer of frames to transmit to this station
- *     when it leaves power saving state
- * @tx_filtered: buffer of frames we already tried to transmit
- *     but were filtered by hardware due to STA having entered
- *     power saving state
+ * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
+ * @ps_tx_buf: buffers (per AC) of frames to transmit to this station
+ *     when it leaves power saving state or polls
+ * @tx_filtered: buffers (per AC) of frames we already tried to
+ *     transmit but were filtered by hardware due to STA having
+ *     entered power saving state, these are also delivered to
+ *     the station when it leaves powersave or polls for frames
+ * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on
  * @rx_packets: Number of MSDUs received from this STA
  * @rx_bytes: Number of bytes received from this STA
  * @wep_weak_iv_count: number of weak WEP IVs received from this station
@@ -238,10 +254,12 @@ struct sta_ampdu_mlme {
  * @plink_timer: peer link watch timer
  * @plink_timer_was_running: used by suspend/resume to restore timers
  * @debugfs: debug filesystem info
- * @sta: station information we share with the driver
  * @dead: set to true when sta is unlinked
  * @uploaded: set to true when sta is uploaded to the driver
  * @lost_packets: number of consecutive lost packets
+ * @dummy: indicate a dummy station created for receiving
+ *     EAP frames before association
+ * @sta: station information we share with the driver
  */
 struct sta_info {
        /* General information, mostly static */
@@ -254,7 +272,6 @@ struct sta_info {
        struct rate_control_ref *rate_ctrl;
        void *rate_ctrl_priv;
        spinlock_t lock;
-       spinlock_t flaglock;
 
        struct work_struct drv_unblock_wk;
 
@@ -264,18 +281,16 @@ struct sta_info {
 
        bool uploaded;
 
-       /*
-        * frequently updated, locked with own spinlock (flaglock),
-        * use the accessors defined below
-        */
-       u32 flags;
+       /* use the accessors defined below */
+       unsigned long _flags;
 
        /*
         * STA powersave frame queues, no more than the internal
         * locking required.
         */
-       struct sk_buff_head ps_tx_buf;
-       struct sk_buff_head tx_filtered;
+       struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
+       struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
+       unsigned long driver_buffered_tids;
 
        /* Updated from RX path only, no locking requirements */
        unsigned long rx_packets, rx_bytes;
@@ -336,6 +351,9 @@ struct sta_info {
 
        unsigned int lost_packets;
 
+       /* should be right in front of sta to be in the same cache line */
+       bool dummy;
+
        /* keep last! */
        struct ieee80211_sta sta;
 };
@@ -348,60 +366,28 @@ static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta)
        return NL80211_PLINK_LISTEN;
 }
 
-static inline void set_sta_flags(struct sta_info *sta, const u32 flags)
+static inline void set_sta_flag(struct sta_info *sta,
+                               enum ieee80211_sta_info_flags flag)
 {
-       unsigned long irqfl;
-
-       spin_lock_irqsave(&sta->flaglock, irqfl);
-       sta->flags |= flags;
-       spin_unlock_irqrestore(&sta->flaglock, irqfl);
+       set_bit(flag, &sta->_flags);
 }
 
-static inline void clear_sta_flags(struct sta_info *sta, const u32 flags)
+static inline void clear_sta_flag(struct sta_info *sta,
+                                 enum ieee80211_sta_info_flags flag)
 {
-       unsigned long irqfl;
-
-       spin_lock_irqsave(&sta->flaglock, irqfl);
-       sta->flags &= ~flags;
-       spin_unlock_irqrestore(&sta->flaglock, irqfl);
+       clear_bit(flag, &sta->_flags);
 }
 
-static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags)
+static inline int test_sta_flag(struct sta_info *sta,
+                               enum ieee80211_sta_info_flags flag)
 {
-       u32 ret;
-       unsigned long irqfl;
-
-       spin_lock_irqsave(&sta->flaglock, irqfl);
-       ret = sta->flags & flags;
-       spin_unlock_irqrestore(&sta->flaglock, irqfl);
-
-       return ret;
-}
-
-static inline u32 test_and_clear_sta_flags(struct sta_info *sta,
-                                          const u32 flags)
-{
-       u32 ret;
-       unsigned long irqfl;
-
-       spin_lock_irqsave(&sta->flaglock, irqfl);
-       ret = sta->flags & flags;
-       sta->flags &= ~flags;
-       spin_unlock_irqrestore(&sta->flaglock, irqfl);
-
-       return ret;
+       return test_bit(flag, &sta->_flags);
 }
 
-static inline u32 get_sta_flags(struct sta_info *sta)
+static inline int test_and_clear_sta_flag(struct sta_info *sta,
+                                         enum ieee80211_sta_info_flags flag)
 {
-       u32 ret;
-       unsigned long irqfl;
-
-       spin_lock_irqsave(&sta->flaglock, irqfl);
-       ret = sta->flags;
-       spin_unlock_irqrestore(&sta->flaglock, irqfl);
-
-       return ret;
+       return test_and_clear_bit(flag, &sta->_flags);
 }
 
 void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
@@ -419,8 +405,8 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid)
 #define STA_HASH(sta) (sta[5])
 
 
-/* Maximum number of frames to buffer per power saving station */
-#define STA_MAX_TX_BUFFER 128
+/* Maximum number of frames to buffer per power saving station per AC */
+#define STA_MAX_TX_BUFFER      64
 
 /* Minimum buffered frame expiry time. If STA uses listen interval that is
  * smaller than this value, the minimum value here is used instead. */
@@ -436,9 +422,15 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid)
 struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
                              const u8 *addr);
 
+struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,
+                             const u8 *addr);
+
 struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
                                  const u8 *addr);
 
+struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
+                                 const u8 *addr);
+
 static inline
 void for_each_sta_info_type_check(struct ieee80211_local *local,
                                  const u8 *addr,
@@ -448,6 +440,22 @@ void for_each_sta_info_type_check(struct ieee80211_local *local,
 }
 
 #define for_each_sta_info(local, _addr, _sta, nxt)                     \
+       for (   /* initialise loop */                                   \
+               _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
+               nxt = _sta ? rcu_dereference(_sta->hnext) : NULL;       \
+               /* typecheck */                                         \
+               for_each_sta_info_type_check(local, (_addr), _sta, nxt),\
+               /* continue condition */                                \
+               _sta;                                                   \
+               /* advance loop */                                      \
+               _sta = nxt,                                             \
+               nxt = _sta ? rcu_dereference(_sta->hnext) : NULL        \
+            )                                                          \
+       /* run code only if address matches and it's not a dummy sta */ \
+       if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 &&           \
+               !_sta->dummy)
+
+#define for_each_sta_info_rx(local, _addr, _sta, nxt)                  \
        for (   /* initialise loop */                                   \
                _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
                nxt = _sta ? rcu_dereference(_sta->hnext) : NULL;       \
@@ -484,14 +492,14 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 int sta_info_insert(struct sta_info *sta);
 int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU);
 int sta_info_insert_atomic(struct sta_info *sta);
+int sta_info_reinsert(struct sta_info *sta);
 
 int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,
                          const u8 *addr);
 int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
                              const u8 *addr);
 
-void sta_info_set_tim_bit(struct sta_info *sta);
-void sta_info_clear_tim_bit(struct sta_info *sta);
+void sta_info_recalc_tim(struct sta_info *sta);
 
 void sta_info_init(struct ieee80211_local *local);
 void sta_info_stop(struct ieee80211_local *local);
@@ -502,5 +510,6 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
 
 void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
 void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
+void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);
 
 #endif /* STA_INFO_H */