aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2009-04-26 10:08:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-06 15:14:49 -0400
commit9f1661718c7fcf82e25c6aed20b729ee372d9d65 (patch)
tree099a3305c948f306f46e2cf2f0d24a8ef069f011 /drivers
parent9eb4e21e289beba9cfe34f24920eee83c144e62f (diff)
rt2x00: Add support for L2 padding during TX/RX
Some hardware require L2 padding between header and payload because both must be aligned to a 4-byte boundary. This hardware also is easier during the RX path since we no longer need to move the entire payload but rather only the header to remove the padding (mac80211 only wants the payload to be 4-byte aligned). Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c68
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c33
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h27
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c39
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h14
6 files changed, 143 insertions, 48 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 0be395528261..7c5cbb192a6c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -103,6 +103,15 @@
103#define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate)) 103#define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate))
104 104
105/* 105/*
106 * Determine the alignment requirement,
107 * to make sure the 802.11 payload is padded to a 4-byte boundrary
108 * we must determine the address of the payload and calculate the
109 * amount of bytes needed to move the data.
110 */
111#define ALIGN_SIZE(__skb, __header) \
112 ( ((unsigned long)((__skb)->data + (__header))) & 3 )
113
114/*
106 * Standard timing and size defines. 115 * Standard timing and size defines.
107 * These values should follow the ieee80211 specifications. 116 * These values should follow the ieee80211 specifications.
108 */ 117 */
@@ -590,6 +599,7 @@ enum rt2x00_flags {
590 DRIVER_REQUIRE_SCHEDULED, 599 DRIVER_REQUIRE_SCHEDULED,
591 DRIVER_REQUIRE_DMA, 600 DRIVER_REQUIRE_DMA,
592 DRIVER_REQUIRE_COPY_IV, 601 DRIVER_REQUIRE_COPY_IV,
602 DRIVER_REQUIRE_L2PAD,
593 603
594 /* 604 /*
595 * Driver features 605 * Driver features
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index ae31581372c0..57ab42cfed34 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -65,7 +65,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
65 __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags); 65 __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags);
66 66
67 txdesc->key_idx = hw_key->hw_key_idx; 67 txdesc->key_idx = hw_key->hw_key_idx;
68 txdesc->iv_offset = ieee80211_get_hdrlen_from_skb(entry->skb); 68 txdesc->iv_offset = txdesc->header_length;
69 txdesc->iv_len = hw_key->iv_len; 69 txdesc->iv_len = hw_key->iv_len;
70 70
71 if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) 71 if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
@@ -132,17 +132,16 @@ void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
132 skb_pull(skb, txdesc->iv_len); 132 skb_pull(skb, txdesc->iv_len);
133 133
134 /* IV/EIV data has officially be stripped */ 134 /* IV/EIV data has officially be stripped */
135 skbdesc->flags |= FRAME_DESC_IV_STRIPPED; 135 skbdesc->flags |= SKBDESC_IV_STRIPPED;
136} 136}
137 137
138void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) 138void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length)
139{ 139{
140 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 140 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
141 unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
142 const unsigned int iv_len = 141 const unsigned int iv_len =
143 ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4); 142 ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4);
144 143
145 if (!(skbdesc->flags & FRAME_DESC_IV_STRIPPED)) 144 if (!(skbdesc->flags & SKBDESC_IV_STRIPPED))
146 return; 145 return;
147 146
148 skb_push(skb, iv_len); 147 skb_push(skb, iv_len);
@@ -154,14 +153,15 @@ void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
154 memcpy(skb->data + header_length, skbdesc->iv, iv_len); 153 memcpy(skb->data + header_length, skbdesc->iv, iv_len);
155 154
156 /* IV/EIV data has returned into the frame */ 155 /* IV/EIV data has returned into the frame */
157 skbdesc->flags &= ~FRAME_DESC_IV_STRIPPED; 156 skbdesc->flags &= ~SKBDESC_IV_STRIPPED;
158} 157}
159 158
160void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, 159void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
161 unsigned int header_length, 160 unsigned int header_length,
162 struct rxdone_entry_desc *rxdesc) 161 struct rxdone_entry_desc *rxdesc)
163{ 162{
164 unsigned int payload_len = rxdesc->size - header_length; 163 unsigned int payload_len = rxdesc->size - header_length;
164 unsigned int align = ALIGN_SIZE(skb, header_length);
165 unsigned int iv_len; 165 unsigned int iv_len;
166 unsigned int icv_len; 166 unsigned int icv_len;
167 unsigned int transfer = 0; 167 unsigned int transfer = 0;
@@ -191,32 +191,48 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
191 } 191 }
192 192
193 /* 193 /*
194 * Make room for new data, note that we increase both 194 * Make room for new data. There are 2 possibilities
195 * headsize and tailsize when required. The tailsize is 195 * either the alignment is already present between
196 * only needed when ICV data needs to be inserted and 196 * the 802.11 header and payload. In that case we
197 * the padding is smaller than the ICV data. 197 * we have to move the header less then the iv_len
198 * When alignment requirements is greater than the 198 * since we can use the already available l2pad bytes
199 * ICV data we must trim the skb to the correct size 199 * for the iv data.
200 * because we need to remove the extra bytes. 200 * When the alignment must be added manually we must
201 * move the header more then iv_len since we must
202 * make room for the payload move as well.
201 */ 203 */
202 skb_push(skb, iv_len + align); 204 if (l2pad) {
203 if (align < icv_len) 205 skb_push(skb, iv_len - align);
204 skb_put(skb, icv_len - align); 206 skb_put(skb, icv_len);
205 else if (align > icv_len)
206 skb_trim(skb, rxdesc->size + iv_len + icv_len);
207 207
208 /* Move ieee80211 header */ 208 /* Move ieee80211 header */
209 memmove(skb->data + transfer, 209 memmove(skb->data + transfer,
210 skb->data + transfer + iv_len + align, 210 skb->data + transfer + (iv_len - align),
211 header_length); 211 header_length);
212 transfer += header_length; 212 transfer += header_length;
213 } else {
214 skb_push(skb, iv_len + align);
215 if (align < icv_len)
216 skb_put(skb, icv_len - align);
217 else if (align > icv_len)
218 skb_trim(skb, rxdesc->size + iv_len + icv_len);
219
220 /* Move ieee80211 header */
221 memmove(skb->data + transfer,
222 skb->data + transfer + iv_len + align,
223 header_length);
224 transfer += header_length;
225 }
213 226
214 /* Copy IV/EIV data */ 227 /* Copy IV/EIV data */
215 memcpy(skb->data + transfer, rxdesc->iv, iv_len); 228 memcpy(skb->data + transfer, rxdesc->iv, iv_len);
216 transfer += iv_len; 229 transfer += iv_len;
217 230
218 /* Move payload */ 231 /*
219 if (align) { 232 * Move payload for alignment purposes. Note that
233 * this is only needed when no l2 padding is present.
234 */
235 if (!l2pad) {
220 memmove(skb->data + transfer, 236 memmove(skb->data + transfer,
221 skb->data + transfer + align, 237 skb->data + transfer + align,
222 payload_len); 238 payload_len);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 5752aaae906b..e15086af7278 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -227,6 +227,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
227 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); 227 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
228 struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); 228 struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
229 enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); 229 enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
230 unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
230 u8 rate_idx, rate_flags; 231 u8 rate_idx, rate_flags;
231 232
232 /* 233 /*
@@ -235,13 +236,19 @@ void rt2x00lib_txdone(struct queue_entry *entry,
235 rt2x00queue_unmap_skb(rt2x00dev, entry->skb); 236 rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
236 237
237 /* 238 /*
239 * Remove L2 padding which was added during
240 */
241 if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
242 rt2x00queue_payload_align(entry->skb, true, header_length);
243
244 /*
238 * If the IV/EIV data was stripped from the frame before it was 245 * If the IV/EIV data was stripped from the frame before it was
239 * passed to the hardware, we should now reinsert it again because 246 * passed to the hardware, we should now reinsert it again because
240 * mac80211 will expect the the same data to be present it the 247 * mac80211 will expect the the same data to be present it the
241 * frame as it was passed to us. 248 * frame as it was passed to us.
242 */ 249 */
243 if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) 250 if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
244 rt2x00crypto_tx_insert_iv(entry->skb); 251 rt2x00crypto_tx_insert_iv(entry->skb, header_length);
245 252
246 /* 253 /*
247 * Send frame to debugfs immediately, after this call is completed 254 * Send frame to debugfs immediately, after this call is completed
@@ -325,7 +332,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
325 struct ieee80211_supported_band *sband; 332 struct ieee80211_supported_band *sband;
326 const struct rt2x00_rate *rate; 333 const struct rt2x00_rate *rate;
327 unsigned int header_length; 334 unsigned int header_length;
328 unsigned int align; 335 bool l2pad;
329 unsigned int i; 336 unsigned int i;
330 int idx = -1; 337 int idx = -1;
331 338
@@ -348,12 +355,15 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
348 memset(&rxdesc, 0, sizeof(rxdesc)); 355 memset(&rxdesc, 0, sizeof(rxdesc));
349 rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); 356 rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
350 357
358 /* Trim buffer to correct size */
359 skb_trim(entry->skb, rxdesc.size);
360
351 /* 361 /*
352 * The data behind the ieee80211 header must be 362 * The data behind the ieee80211 header must be
353 * aligned on a 4 byte boundary. 363 * aligned on a 4 byte boundary.
354 */ 364 */
355 header_length = ieee80211_get_hdrlen_from_skb(entry->skb); 365 header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
356 align = ((unsigned long)(entry->skb->data + header_length)) & 3; 366 l2pad = !!(rxdesc.dev_flags & RXDONE_L2PAD);
357 367
358 /* 368 /*
359 * Hardware might have stripped the IV/EIV/ICV data, 369 * Hardware might have stripped the IV/EIV/ICV data,
@@ -362,18 +372,11 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
362 * in which case we should reinsert the data into the frame. 372 * in which case we should reinsert the data into the frame.
363 */ 373 */
364 if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) && 374 if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) &&
365 (rxdesc.flags & RX_FLAG_IV_STRIPPED)) { 375 (rxdesc.flags & RX_FLAG_IV_STRIPPED))
366 rt2x00crypto_rx_insert_iv(entry->skb, align, 376 rt2x00crypto_rx_insert_iv(entry->skb, l2pad, header_length,
367 header_length, &rxdesc); 377 &rxdesc);
368 } else if (align) { 378 else
369 skb_push(entry->skb, align); 379 rt2x00queue_payload_align(entry->skb, l2pad, header_length);
370 /* Move entire frame in 1 command */
371 memmove(entry->skb->data, entry->skb->data + align,
372 rxdesc.size);
373 }
374
375 /* Update data pointers, trim buffer to correct size */
376 skb_trim(entry->skb, rxdesc.size);
377 380
378 /* 381 /*
379 * Update RX statistics. 382 * Update RX statistics.
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index af3c47bd43bd..aa284e48d2c2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -113,6 +113,23 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
113void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); 113void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
114 114
115/** 115/**
116 * rt2x00queue_payload_align - Align 802.11 payload to 4-byte boundary
117 * @skb: The skb to align
118 * @l2pad: Should L2 padding be used
119 * @header_length: Length of 802.11 header
120 *
121 * This function prepares the @skb to be send to the device or mac80211.
122 * If @l2pad is set to true padding will occur between the 802.11 header
123 * and payload. Otherwise the padding will be done in front of the 802.11
124 * header.
125 * When @l2pad is set the function will check for the &SKBDESC_L2_PADDED
126 * flag in &skb_frame_desc. If that flag is set, the padding is removed
127 * and the flag cleared. Otherwise the padding is added and the flag is set.
128 */
129void rt2x00queue_payload_align(struct sk_buff *skb,
130 bool l2pad, unsigned int header_length);
131
132/**
116 * rt2x00queue_write_tx_frame - Write TX frame to hardware 133 * rt2x00queue_write_tx_frame - Write TX frame to hardware
117 * @queue: Queue over which the frame should be send 134 * @queue: Queue over which the frame should be send
118 * @skb: The skb to send 135 * @skb: The skb to send
@@ -299,8 +316,8 @@ void rt2x00crypto_tx_copy_iv(struct sk_buff *skb,
299 struct txentry_desc *txdesc); 316 struct txentry_desc *txdesc);
300void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, 317void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
301 struct txentry_desc *txdesc); 318 struct txentry_desc *txdesc);
302void rt2x00crypto_tx_insert_iv(struct sk_buff *skb); 319void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length);
303void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, 320void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
304 unsigned int header_length, 321 unsigned int header_length,
305 struct rxdone_entry_desc *rxdesc); 322 struct rxdone_entry_desc *rxdesc);
306#else 323#else
@@ -330,12 +347,12 @@ static inline void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
330{ 347{
331} 348}
332 349
333static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) 350static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb,
351 unsigned int header_length)
334{ 352{
335} 353}
336 354
337static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, 355static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
338 unsigned int align,
339 unsigned int header_length, 356 unsigned int header_length,
340 struct rxdone_entry_desc *rxdesc) 357 struct rxdone_entry_desc *rxdesc)
341{ 358{
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 6f78915b364c..bc1742c1d51c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -148,6 +148,35 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
148 dev_kfree_skb_any(skb); 148 dev_kfree_skb_any(skb);
149} 149}
150 150
151void rt2x00queue_payload_align(struct sk_buff *skb,
152 bool l2pad, unsigned int header_length)
153{
154 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
155 unsigned int frame_length = skb->len;
156 unsigned int align = ALIGN_SIZE(skb, header_length);
157
158 if (!align)
159 return;
160
161 if (l2pad) {
162 if (skbdesc->flags & SKBDESC_L2_PADDED) {
163 /* Remove L2 padding */
164 memmove(skb->data + align, skb->data, header_length);
165 skb_pull(skb, align);
166 skbdesc->flags &= ~SKBDESC_L2_PADDED;
167 } else {
168 /* Add L2 padding */
169 skb_push(skb, align);
170 memmove(skb->data, skb->data + align, header_length);
171 skbdesc->flags |= SKBDESC_L2_PADDED;
172 }
173 } else {
174 /* Generic payload alignment to 4-byte boundary */
175 skb_push(skb, align);
176 memmove(skb->data, skb->data + align, frame_length);
177 }
178}
179
151static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, 180static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
152 struct txentry_desc *txdesc) 181 struct txentry_desc *txdesc)
153{ 182{
@@ -259,6 +288,12 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
259 txdesc->aifs = entry->queue->aifs; 288 txdesc->aifs = entry->queue->aifs;
260 289
261 /* 290 /*
291 * Header and alignment information.
292 */
293 txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
294 txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length);
295
296 /*
262 * Check whether this frame is to be acked. 297 * Check whether this frame is to be acked.
263 */ 298 */
264 if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) 299 if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK))
@@ -416,6 +451,10 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
416 rt2x00crypto_tx_remove_iv(skb, &txdesc); 451 rt2x00crypto_tx_remove_iv(skb, &txdesc);
417 } 452 }
418 453
454 if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags))
455 rt2x00queue_payload_align(entry->skb, true,
456 txdesc.header_length);
457
419 /* 458 /*
420 * It could be possible that the queue was corrupted and this 459 * It could be possible that the queue was corrupted and this
421 * call failed. Since we always return NETDEV_TX_OK to mac80211, 460 * call failed. Since we always return NETDEV_TX_OK to mac80211,
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index e3bfd73e319b..13e0ece176a1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -87,13 +87,16 @@ enum data_queue_qid {
87 * 87 *
88 * @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX 88 * @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX
89 * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX 89 * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX
90 * @FRAME_DESC_IV_STRIPPED: Frame contained a IV/EIV provided by 90 * @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by
91 * mac80211 but was stripped for processing by the driver. 91 * mac80211 but was stripped for processing by the driver.
92 * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment,
93 * the padded bytes are located between header and payload.
92 */ 94 */
93enum skb_frame_desc_flags { 95enum skb_frame_desc_flags {
94 SKBDESC_DMA_MAPPED_RX = 1 << 0, 96 SKBDESC_DMA_MAPPED_RX = 1 << 0,
95 SKBDESC_DMA_MAPPED_TX = 1 << 1, 97 SKBDESC_DMA_MAPPED_TX = 1 << 1,
96 FRAME_DESC_IV_STRIPPED = 1 << 2, 98 SKBDESC_IV_STRIPPED = 1 << 2,
99 SKBDESC_L2_PADDED = 1 << 3
97}; 100};
98 101
99/** 102/**
@@ -148,6 +151,7 @@ static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb)
148 * @RXDONE_MY_BSS: Does this frame originate from device's BSS. 151 * @RXDONE_MY_BSS: Does this frame originate from device's BSS.
149 * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data. 152 * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data.
150 * @RXDONE_CRYPTO_ICV: Driver provided ICV data. 153 * @RXDONE_CRYPTO_ICV: Driver provided ICV data.
154 * @RXDONE_L2PAD: 802.11 payload has been padded to 4-byte boundary.
151 */ 155 */
152enum rxdone_entry_desc_flags { 156enum rxdone_entry_desc_flags {
153 RXDONE_SIGNAL_PLCP = 1 << 0, 157 RXDONE_SIGNAL_PLCP = 1 << 0,
@@ -155,6 +159,7 @@ enum rxdone_entry_desc_flags {
155 RXDONE_MY_BSS = 1 << 2, 159 RXDONE_MY_BSS = 1 << 2,
156 RXDONE_CRYPTO_IV = 1 << 3, 160 RXDONE_CRYPTO_IV = 1 << 3,
157 RXDONE_CRYPTO_ICV = 1 << 4, 161 RXDONE_CRYPTO_ICV = 1 << 4,
162 RXDONE_L2PAD = 1 << 5,
158}; 163};
159 164
160/** 165/**
@@ -267,6 +272,8 @@ enum txentry_desc_flags {
267 * 272 *
268 * @flags: Descriptor flags (See &enum queue_entry_flags). 273 * @flags: Descriptor flags (See &enum queue_entry_flags).
269 * @queue: Queue identification (See &enum data_queue_qid). 274 * @queue: Queue identification (See &enum data_queue_qid).
275 * @header_length: Length of 802.11 header.
276 * @l2pad: Amount of padding to align 802.11 payload to 4-byte boundrary.
270 * @length_high: PLCP length high word. 277 * @length_high: PLCP length high word.
271 * @length_low: PLCP length low word. 278 * @length_low: PLCP length low word.
272 * @signal: PLCP signal. 279 * @signal: PLCP signal.
@@ -287,6 +294,9 @@ struct txentry_desc {
287 294
288 enum data_queue_qid queue; 295 enum data_queue_qid queue;
289 296
297 u16 header_length;
298 u16 l2pad;
299
290 u16 length_high; 300 u16 length_high;
291 u16 length_low; 301 u16 length_low;
292 u16 signal; 302 u16 signal;