diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2009-04-26 10:08:50 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-05-06 15:14:49 -0400 |
commit | 9f1661718c7fcf82e25c6aed20b729ee372d9d65 (patch) | |
tree | 099a3305c948f306f46e2cf2f0d24a8ef069f011 /drivers/net/wireless/rt2x00/rt2x00queue.c | |
parent | 9eb4e21e289beba9cfe34f24920eee83c144e62f (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/net/wireless/rt2x00/rt2x00queue.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 39 |
1 files changed, 39 insertions, 0 deletions
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 | ||
151 | void 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 | |||
151 | static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, | 180 | static 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, |