aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h45
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c99
4 files changed, 116 insertions, 44 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 30fbd3bbe08b..de36837dcf86 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -154,7 +154,7 @@ void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length)
154 skbdesc->flags &= ~SKBDESC_IV_STRIPPED; 154 skbdesc->flags &= ~SKBDESC_IV_STRIPPED;
155} 155}
156 156
157void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, 157void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
158 unsigned int header_length, 158 unsigned int header_length,
159 struct rxdone_entry_desc *rxdesc) 159 struct rxdone_entry_desc *rxdesc)
160{ 160{
@@ -199,7 +199,7 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
199 * move the header more then iv_len since we must 199 * move the header more then iv_len since we must
200 * make room for the payload move as well. 200 * make room for the payload move as well.
201 */ 201 */
202 if (l2pad) { 202 if (rxdesc->dev_flags & RXDONE_L2PAD) {
203 skb_push(skb, iv_len - align); 203 skb_push(skb, iv_len - align);
204 skb_put(skb, icv_len); 204 skb_put(skb, icv_len);
205 205
@@ -230,7 +230,7 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
230 * Move payload for alignment purposes. Note that 230 * Move payload for alignment purposes. Note that
231 * this is only needed when no l2 padding is present. 231 * this is only needed when no l2 padding is present.
232 */ 232 */
233 if (!l2pad) { 233 if (!(rxdesc->dev_flags & RXDONE_L2PAD)) {
234 memmove(skb->data + transfer, 234 memmove(skb->data + transfer,
235 skb->data + transfer + align, 235 skb->data + transfer + align,
236 payload_len); 236 payload_len);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 0647e514dde1..71761b343839 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -217,7 +217,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
217 * Remove L2 padding which was added during 217 * Remove L2 padding which was added during
218 */ 218 */
219 if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) 219 if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
220 rt2x00queue_payload_align(entry->skb, true, header_length); 220 rt2x00queue_remove_l2pad(entry->skb, header_length);
221 221
222 /* 222 /*
223 * If the IV/EIV data was stripped from the frame before it was 223 * If the IV/EIV data was stripped from the frame before it was
@@ -364,7 +364,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
364 struct sk_buff *skb; 364 struct sk_buff *skb;
365 struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; 365 struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
366 unsigned int header_length; 366 unsigned int header_length;
367 bool l2pad;
368 int rate_idx; 367 int rate_idx;
369 /* 368 /*
370 * Allocate a new sk_buffer. If no new buffer available, drop the 369 * Allocate a new sk_buffer. If no new buffer available, drop the
@@ -393,7 +392,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
393 * aligned on a 4 byte boundary. 392 * aligned on a 4 byte boundary.
394 */ 393 */
395 header_length = ieee80211_get_hdrlen_from_skb(entry->skb); 394 header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
396 l2pad = !!(rxdesc.dev_flags & RXDONE_L2PAD);
397 395
398 /* 396 /*
399 * Hardware might have stripped the IV/EIV/ICV data, 397 * Hardware might have stripped the IV/EIV/ICV data,
@@ -403,10 +401,12 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
403 */ 401 */
404 if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) && 402 if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) &&
405 (rxdesc.flags & RX_FLAG_IV_STRIPPED)) 403 (rxdesc.flags & RX_FLAG_IV_STRIPPED))
406 rt2x00crypto_rx_insert_iv(entry->skb, l2pad, header_length, 404 rt2x00crypto_rx_insert_iv(entry->skb, header_length,
407 &rxdesc); 405 &rxdesc);
406 else if (rxdesc.dev_flags & RXDONE_L2PAD)
407 rt2x00queue_remove_l2pad(entry->skb, header_length);
408 else 408 else
409 rt2x00queue_payload_align(entry->skb, l2pad, header_length); 409 rt2x00queue_align_payload(entry->skb, header_length);
410 410
411 /* 411 /*
412 * Check if the frame was received using HT. In that case, 412 * Check if the frame was received using HT. In that case,
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index eeb2881e818e..5462cb5ad994 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -120,21 +120,42 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
120void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); 120void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
121 121
122/** 122/**
123 * rt2x00queue_payload_align - Align 802.11 payload to 4-byte boundary 123 * rt2x00queue_align_frame - Align 802.11 frame to 4-byte boundary
124 * @skb: The skb to align
125 *
126 * Align the start of the 802.11 frame to a 4-byte boundary, this could
127 * mean the payload is not aligned properly though.
128 */
129void rt2x00queue_align_frame(struct sk_buff *skb);
130
131/**
132 * rt2x00queue_align_payload - Align 802.11 payload to 4-byte boundary
133 * @skb: The skb to align
134 * @header_length: Length of 802.11 header
135 *
136 * Align the 802.11 payload to a 4-byte boundary, this could
137 * mean the header is not aligned properly though.
138 */
139void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length);
140
141/**
142 * rt2x00queue_insert_l2pad - Align 802.11 header & payload to 4-byte boundary
143 * @skb: The skb to align
144 * @header_length: Length of 802.11 header
145 *
146 * Apply L2 padding to align both header and payload to 4-byte boundary
147 */
148void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length);
149
150/**
151 * rt2x00queue_insert_l2pad - Remove L2 padding from 802.11 frame
124 * @skb: The skb to align 152 * @skb: The skb to align
125 * @l2pad: Should L2 padding be used
126 * @header_length: Length of 802.11 header 153 * @header_length: Length of 802.11 header
127 * 154 *
128 * This function prepares the @skb to be send to the device or mac80211. 155 * Remove L2 padding used to align both header and payload to 4-byte boundary,
129 * If @l2pad is set to true padding will occur between the 802.11 header 156 * by removing the L2 padding the header will no longer be 4-byte aligned.
130 * and payload. Otherwise the padding will be done in front of the 802.11
131 * header.
132 * When @l2pad is set the function will check for the &SKBDESC_L2_PADDED
133 * flag in &skb_frame_desc. If that flag is set, the padding is removed
134 * and the flag cleared. Otherwise the padding is added and the flag is set.
135 */ 157 */
136void rt2x00queue_payload_align(struct sk_buff *skb, 158void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length);
137 bool l2pad, unsigned int header_length);
138 159
139/** 160/**
140 * rt2x00queue_write_tx_frame - Write TX frame to hardware 161 * rt2x00queue_write_tx_frame - Write TX frame to hardware
@@ -324,7 +345,7 @@ void rt2x00crypto_tx_copy_iv(struct sk_buff *skb,
324void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, 345void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
325 struct txentry_desc *txdesc); 346 struct txentry_desc *txdesc);
326void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length); 347void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length);
327void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, 348void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
328 unsigned int header_length, 349 unsigned int header_length,
329 struct rxdone_entry_desc *rxdesc); 350 struct rxdone_entry_desc *rxdesc);
330#else 351#else
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 06af823efd83..577029efe320 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -148,35 +148,89 @@ 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, 151void rt2x00queue_align_frame(struct sk_buff *skb)
152 bool l2pad, unsigned int header_length)
153{ 152{
154 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
155 unsigned int frame_length = skb->len; 153 unsigned int frame_length = skb->len;
156 unsigned int align = ALIGN_SIZE(skb, header_length); 154 unsigned int align = ALIGN_SIZE(skb, 0);
157 155
158 if (!align) 156 if (!align)
159 return; 157 return;
160 158
161 if (l2pad) { 159 skb_push(skb, align);
162 if (skbdesc->flags & SKBDESC_L2_PADDED) { 160 memmove(skb->data, skb->data + align, frame_length);
163 /* Remove L2 padding */ 161 skb_trim(skb, frame_length);
164 memmove(skb->data + align, skb->data, header_length); 162}
165 skb_pull(skb, align); 163
166 skbdesc->flags &= ~SKBDESC_L2_PADDED; 164void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_lengt)
167 } else { 165{
168 /* Add L2 padding */ 166 unsigned int frame_length = skb->len;
169 skb_push(skb, align); 167 unsigned int align = ALIGN_SIZE(skb, header_lengt);
170 memmove(skb->data, skb->data + align, header_length); 168
171 skbdesc->flags |= SKBDESC_L2_PADDED; 169 if (!align)
172 } 170 return;
171
172 skb_push(skb, align);
173 memmove(skb->data, skb->data + align, frame_length);
174 skb_trim(skb, frame_length);
175}
176
177void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
178{
179 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
180 unsigned int frame_length = skb->len;
181 unsigned int header_align = ALIGN_SIZE(skb, 0);
182 unsigned int payload_align = ALIGN_SIZE(skb, header_length);
183 unsigned int l2pad = 4 - (payload_align - header_align);
184
185 if (header_align == payload_align) {
186 /*
187 * Both header and payload must be moved the same
188 * amount of bytes to align them properly. This means
189 * we don't use the L2 padding but just move the entire
190 * frame.
191 */
192 rt2x00queue_align_frame(skb);
193 } else if (!payload_align) {
194 /*
195 * Simple L2 padding, only the header needs to be moved,
196 * the payload is already properly aligned.
197 */
198 skb_push(skb, header_align);
199 memmove(skb->data, skb->data + header_align, frame_length);
200 skbdesc->flags |= SKBDESC_L2_PADDED;
173 } else { 201 } else {
174 /* Generic payload alignment to 4-byte boundary */ 202 /*
175 skb_push(skb, align); 203 *
176 memmove(skb->data, skb->data + align, frame_length); 204 * Complicated L2 padding, both header and payload need
205 * to be moved. By default we only move to the start
206 * of the buffer, so our header alignment needs to be
207 * increased if there is not enough room for the header
208 * to be moved.
209 */
210 if (payload_align > header_align)
211 header_align += 4;
212
213 skb_push(skb, header_align);
214 memmove(skb->data, skb->data + header_align, header_length);
215 memmove(skb->data + header_length + l2pad,
216 skb->data + header_length + l2pad + header_align,
217 frame_length - header_length);
218 skbdesc->flags |= SKBDESC_L2_PADDED;
177 } 219 }
178} 220}
179 221
222void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
223{
224 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
225 unsigned int l2pad = 4 - (header_length & 3);
226
227 if (!l2pad || (skbdesc->flags & SKBDESC_L2_PADDED))
228 return;
229
230 memmove(skb->data + l2pad, skb->data, header_length);
231 skb_pull(skb, l2pad);
232}
233
180static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, 234static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
181 struct txentry_desc *txdesc) 235 struct txentry_desc *txdesc)
182{ 236{
@@ -456,18 +510,15 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
456 /* 510 /*
457 * When DMA allocation is required we should guarentee to the 511 * When DMA allocation is required we should guarentee to the
458 * driver that the DMA is aligned to a 4-byte boundary. 512 * driver that the DMA is aligned to a 4-byte boundary.
459 * Aligning the header to this boundary can be done by calling
460 * rt2x00queue_payload_align with the header length of 0.
461 * However some drivers require L2 padding to pad the payload 513 * However some drivers require L2 padding to pad the payload
462 * rather then the header. This could be a requirement for 514 * rather then the header. This could be a requirement for
463 * PCI and USB devices, while header alignment only is valid 515 * PCI and USB devices, while header alignment only is valid
464 * for PCI devices. 516 * for PCI devices.
465 */ 517 */
466 if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags)) 518 if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags))
467 rt2x00queue_payload_align(entry->skb, true, 519 rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length);
468 txdesc.header_length);
469 else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) 520 else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
470 rt2x00queue_payload_align(entry->skb, false, 0); 521 rt2x00queue_align_frame(entry->skb);
471 522
472 /* 523 /*
473 * It could be possible that the queue was corrupted and this 524 * It could be possible that the queue was corrupted and this