diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00crypto.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00lib.h | 45 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 99 |
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 | ||
157 | void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, | 157 | void 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); | |||
120 | void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); | 120 | void 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 | */ | ||
129 | void 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 | */ | ||
139 | void 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 | */ | ||
148 | void 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 | */ |
136 | void rt2x00queue_payload_align(struct sk_buff *skb, | 158 | void 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, | |||
324 | void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, | 345 | void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, |
325 | struct txentry_desc *txdesc); | 346 | struct txentry_desc *txdesc); |
326 | void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length); | 347 | void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length); |
327 | void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, | 348 | void 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 | ||
151 | void rt2x00queue_payload_align(struct sk_buff *skb, | 151 | void 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; | 164 | void 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 | |||
177 | void 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 | ||
222 | void 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 | |||
180 | static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, | 234 | static 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 |