#include <linux/list.h>
#include <linux/types.h>
#include <linux/if_ether.h>
-#include "ieee80211_key.h"
+#include "key.h"
/**
* enum ieee80211_sta_info_flags - Stations flags
* @WLAN_STA_WDS: Station is one of our WDS peers.
* @WLAN_STA_PSPOLL: Station has just PS-polled us.
* @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
- * IEEE80211_TXCTL_CLEAR_PS_FILT control flag) when the next
+ * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
* frame to this station is transmitted.
*/
enum ieee80211_sta_info_flags {
#define HT_AGG_STATE_OPERATIONAL (HT_ADDBA_REQUESTED_MSK | \
HT_ADDBA_DRV_READY_MSK | \
HT_ADDBA_RECEIVED_MSK)
+#define HT_AGG_STATE_DEBUGFS_CTL BIT(7)
/**
* struct tid_ampdu_tx - TID aggregation information (Tx).
*
- * @state: TID's state in session state machine.
- * @dialog_token: dialog token for aggregation session
- * @ssn: Starting Sequence Number expected to be aggregated.
* @addba_resp_timer: timer for peer's response to addba request
- * @addba_req_num: number of times addBA request has been sent.
+ * @ssn: Starting Sequence Number expected to be aggregated.
+ * @dialog_token: dialog token for aggregation session
*/
struct tid_ampdu_tx {
- u8 state;
- u8 dialog_token;
- u16 ssn;
struct timer_list addba_resp_timer;
- u8 addba_req_num;
+ u16 ssn;
+ u8 dialog_token;
};
/**
* struct tid_ampdu_rx - TID aggregation information (Rx).
*
- * @state: TID's state in session state machine.
- * @dialog_token: dialog token for aggregation session
+ * @reorder_buf: buffer to reorder incoming aggregated MPDUs
+ * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
+ * @head_seq_num: head sequence number in reordering buffer.
+ * @stored_mpdu_num: number of MPDUs in reordering buffer
* @ssn: Starting Sequence Number expected to be aggregated.
* @buf_size: buffer size for incoming A-MPDUs
* @timeout: reset timer value.
- * @head_seq_num: head sequence number in reordering buffer.
- * @stored_mpdu_num: number of MPDUs in reordering buffer
- * @reorder_buf: buffer to reorder incoming aggregated MPDUs
- * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
+ * @dialog_token: dialog token for aggregation session
*/
struct tid_ampdu_rx {
- u8 state;
- u8 dialog_token;
+ struct sk_buff **reorder_buf;
+ struct timer_list session_timer;
+ u16 head_seq_num;
+ u16 stored_mpdu_num;
u16 ssn;
u16 buf_size;
u16 timeout;
- u16 head_seq_num;
- u16 stored_mpdu_num;
- struct sk_buff **reorder_buf;
- struct timer_list session_timer;
+ u8 dialog_token;
};
/**
/**
* struct sta_ampdu_mlme - STA aggregation information.
*
+ * @tid_state_rx: TID's state in Rx session state machine.
* @tid_rx: aggregation info for Rx per TID
+ * @tid_state_tx: TID's state in Tx session state machine.
* @tid_tx: aggregation info for Tx per TID
- * @ampdu_rx: for locking sections in aggregation Rx flow
- * @ampdu_tx: for locking sectionsi in aggregation Tx flow
+ * @addba_req_num: number of times addBA request has been sent.
* @dialog_token_allocator: dialog token enumerator for each new session;
*/
struct sta_ampdu_mlme {
- struct tid_ampdu_rx tid_rx[STA_TID_NUM];
- struct tid_ampdu_tx tid_tx[STA_TID_NUM];
- spinlock_t ampdu_rx;
- spinlock_t ampdu_tx;
+ /* rx */
+ u8 tid_state_rx[STA_TID_NUM];
+ struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
+ /* tx */
+ u8 tid_state_tx[STA_TID_NUM];
+ struct tid_ampdu_tx *tid_tx[STA_TID_NUM];
+ u8 addba_req_num[STA_TID_NUM];
u8 dialog_token_allocator;
};
* @aid: STA's unique AID (1..2007, 0 = not assigned yet),
* only used in AP (and IBSS?) mode
* @flags: STA flags, see &enum ieee80211_sta_info_flags
+ * @flaglock: spinlock for flags accesses
* @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
* @rx_bytes: Number of bytes received from this STA
* @supp_rates: Bitmap of supported rates (per band)
* @ht_info: HT capabilities of this STA
+ * @lock: used for locking all fields that require locking, see comments
+ * in the header file.
*/
struct sta_info {
/* General information, mostly static */
struct ieee80211_key *key;
struct rate_control_ref *rate_ctrl;
void *rate_ctrl_priv;
+ spinlock_t lock;
+ spinlock_t flaglock;
struct ieee80211_ht_info ht_info;
u64 supp_rates[IEEE80211_NUM_BANDS];
u8 addr[ETH_ALEN];
*/
u8 pin_status;
- /* frequently updated information, needs locking? */
+ /*
+ * frequently updated, locked with own spinlock (flaglock),
+ * use the accessors defined below
+ */
u32 flags;
/*
* from this STA */
unsigned long rx_fragments; /* number of received MPDUs */
unsigned long rx_dropped; /* number of dropped MPDUs from this STA */
- int last_rssi; /* RSSI of last received frame from this STA */
int last_signal; /* signal of last received frame from this STA */
+ int last_qual; /* qual of last received frame from this STA */
int last_noise; /* noise of last received frame from this STA */
/* last received seq/frag number from this STA (per RX queue) */
__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
#endif
- /* Debug counters, no locking doesn't matter */
- int channel_use;
- int channel_use_raw;
-
/*
- * Aggregation information, comes with own locking.
+ * Aggregation information, locked with lock.
*/
struct sta_ampdu_mlme ampdu_mlme;
u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */
enum plink_state plink_state;
u32 plink_timeout;
struct timer_list plink_timer;
- spinlock_t plink_lock; /* For peer_state reads / updates and other
- updates in the structure. Ensures robust
- transitions for the peerlink FSM */
#endif
#ifdef CONFIG_MAC80211_DEBUGFS
return PLINK_LISTEN;
}
+static inline void set_sta_flags(struct sta_info *sta, const u32 flags)
+{
+ unsigned long irqfl;
+
+ spin_lock_irqsave(&sta->flaglock, irqfl);
+ sta->flags |= flags;
+ spin_unlock_irqrestore(&sta->flaglock, irqfl);
+}
+
+static inline void clear_sta_flags(struct sta_info *sta, const u32 flags)
+{
+ unsigned long irqfl;
+
+ spin_lock_irqsave(&sta->flaglock, irqfl);
+ sta->flags &= ~flags;
+ spin_unlock_irqrestore(&sta->flaglock, irqfl);
+}
+
+static inline void set_and_clear_sta_flags(struct sta_info *sta,
+ const u32 set, const u32 clear)
+{
+ unsigned long irqfl;
+
+ spin_lock_irqsave(&sta->flaglock, irqfl);
+ sta->flags |= set;
+ sta->flags &= ~clear;
+ spin_unlock_irqrestore(&sta->flaglock, irqfl);
+}
+
+static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags)
+{
+ 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;
+}
+
+static inline u32 get_sta_flags(struct sta_info *sta)
+{
+ u32 ret;
+ unsigned long irqfl;
+
+ spin_lock_irqsave(&sta->flaglock, irqfl);
+ ret = sta->flags;
+ spin_unlock_irqrestore(&sta->flaglock, irqfl);
+
+ return ret;
+}
+
/* Maximum number of concurrently registered stations */
#define MAX_STA_COUNT 2007
* has already unlinked it.
*/
void sta_info_unlink(struct sta_info **sta);
+void __sta_info_unlink(struct sta_info **sta);
void sta_info_destroy(struct sta_info *sta);
void sta_info_set_tim_bit(struct sta_info *sta);
void sta_info_stop(struct ieee80211_local *local);
int sta_info_flush(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata);
+void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata);
#endif /* STA_INFO_H */