iwlwifi: mvm: allocate reorder buffer according to need
Now that we may have up to 256 entries per reorder buffer, and possibly up
to 16 queues, we can use a LOT of memory for this (64k for each station).
Allocate it according to what we need, which is of course much less for HT
stations (only 16k at a max of 16 queues).
However, this comes at the expense of complicating the code a bit to
calculate the right entry structure to use for each frame.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index bf25c3c..52a2f49 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -590,8 +590,6 @@ enum iwl_mvm_tdls_cs_state {
* @last_amsdu: track last ASMDU SN for duplication detection
* @last_sub_index: track ASMDU sub frame index for duplication detection
* @tid: the tid
- * @entries: list of skbs stored
- * @reorder_time: time the packet was stored in the reorder buffer
* @reorder_timer: timer for frames are in the reorder buffer. For AMSDU
* it is the time of last received sub-frame
* @removed: prevent timer re-arming
@@ -608,8 +606,6 @@ struct iwl_mvm_reorder_buffer {
u16 last_amsdu;
u8 last_sub_index;
u8 tid;
- struct sk_buff_head entries[IEEE80211_MAX_AMPDU_BUF];
- unsigned long reorder_time[IEEE80211_MAX_AMPDU_BUF];
struct timer_list reorder_timer;
bool removed;
bool valid;
@@ -618,15 +614,38 @@ struct iwl_mvm_reorder_buffer {
} ____cacheline_aligned_in_smp;
/**
+ * struct _iwl_mvm_reorder_buf_entry - reorder buffer entry per-queue/per-seqno
+ * @frames: list of skbs stored
+ * @reorder_time: time the packet was stored in the reorder buffer
+ */
+struct _iwl_mvm_reorder_buf_entry {
+ struct sk_buff_head frames;
+ unsigned long reorder_time;
+};
+
+/* make this indirection to get the aligned thing */
+struct iwl_mvm_reorder_buf_entry {
+ struct _iwl_mvm_reorder_buf_entry e;
+}
+#ifndef __CHECKER__
+/* sparse doesn't like this construct: "bad integer constant expression" */
+__aligned(roundup_pow_of_two(sizeof(struct _iwl_mvm_reorder_buf_entry)))
+#endif
+;
+
+/**
* struct iwl_mvm_baid_data - BA session data
* @sta_id: station id
* @tid: tid of the session
* @baid baid of the session
* @timeout: the timeout set in the addba request
+ * @entries_per_queue: # of buffers per queue, this actually gets
+ * aligned up to avoid cache line sharing between queues
* @last_rx: last rx jiffies, updated only if timeout passed from last update
* @session_timer: timer to check if BA session expired, runs at 2 * timeout
* @mvm: mvm pointer, needed for timer context
* @reorder_buf: reorder buffer, allocated per queue
+ * @reorder_buf_data: data
*/
struct iwl_mvm_baid_data {
struct rcu_head rcu_head;
@@ -634,12 +653,22 @@ struct iwl_mvm_baid_data {
u8 tid;
u8 baid;
u16 timeout;
+ u16 entries_per_queue;
unsigned long last_rx;
struct timer_list session_timer;
struct iwl_mvm *mvm;
- struct iwl_mvm_reorder_buffer reorder_buf[];
+ struct iwl_mvm_reorder_buffer reorder_buf[IWL_MAX_RX_HW_QUEUES];
+ struct iwl_mvm_reorder_buf_entry entries[];
};
+static inline struct iwl_mvm_baid_data *
+iwl_mvm_baid_data_from_reorder_buf(struct iwl_mvm_reorder_buffer *buf)
+{
+ return (void *)((u8 *)buf -
+ offsetof(struct iwl_mvm_baid_data, reorder_buf) -
+ sizeof(*buf) * buf->queue);
+}
+
/*
* enum iwl_mvm_queue_status - queue status
* @IWL_MVM_QUEUE_FREE: the queue is not allocated nor reserved