diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00queue.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 81 |
1 files changed, 73 insertions, 8 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 898cdd7f57d9..c0f97c53e5ce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -33,10 +33,11 @@ | |||
33 | struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, | 33 | struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, |
34 | struct queue_entry *entry) | 34 | struct queue_entry *entry) |
35 | { | 35 | { |
36 | unsigned int frame_size; | ||
37 | unsigned int reserved_size; | ||
38 | struct sk_buff *skb; | 36 | struct sk_buff *skb; |
39 | struct skb_frame_desc *skbdesc; | 37 | struct skb_frame_desc *skbdesc; |
38 | unsigned int frame_size; | ||
39 | unsigned int head_size = 0; | ||
40 | unsigned int tail_size = 0; | ||
40 | 41 | ||
41 | /* | 42 | /* |
42 | * The frame size includes descriptor size, because the | 43 | * The frame size includes descriptor size, because the |
@@ -49,16 +50,32 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, | |||
49 | * this means we need at least 3 bytes for moving the frame | 50 | * this means we need at least 3 bytes for moving the frame |
50 | * into the correct offset. | 51 | * into the correct offset. |
51 | */ | 52 | */ |
52 | reserved_size = 4; | 53 | head_size = 4; |
54 | |||
55 | /* | ||
56 | * For IV/EIV/ICV assembly we must make sure there is | ||
57 | * at least 8 bytes bytes available in headroom for IV/EIV | ||
58 | * and 4 bytes for ICV data as tailroon. | ||
59 | */ | ||
60 | #ifdef CONFIG_RT2X00_LIB_CRYPTO | ||
61 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { | ||
62 | head_size += 8; | ||
63 | tail_size += 4; | ||
64 | } | ||
65 | #endif /* CONFIG_RT2X00_LIB_CRYPTO */ | ||
53 | 66 | ||
54 | /* | 67 | /* |
55 | * Allocate skbuffer. | 68 | * Allocate skbuffer. |
56 | */ | 69 | */ |
57 | skb = dev_alloc_skb(frame_size + reserved_size); | 70 | skb = dev_alloc_skb(frame_size + head_size + tail_size); |
58 | if (!skb) | 71 | if (!skb) |
59 | return NULL; | 72 | return NULL; |
60 | 73 | ||
61 | skb_reserve(skb, reserved_size); | 74 | /* |
75 | * Make sure we not have a frame with the requested bytes | ||
76 | * available in the head and tail. | ||
77 | */ | ||
78 | skb_reserve(skb, head_size); | ||
62 | skb_put(skb, frame_size); | 79 | skb_put(skb, frame_size); |
63 | 80 | ||
64 | /* | 81 | /* |
@@ -140,7 +157,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
140 | txdesc->cw_max = entry->queue->cw_max; | 157 | txdesc->cw_max = entry->queue->cw_max; |
141 | txdesc->aifs = entry->queue->aifs; | 158 | txdesc->aifs = entry->queue->aifs; |
142 | 159 | ||
143 | /* Data length should be extended with 4 bytes for CRC */ | 160 | /* Data length + CRC + IV/EIV/ICV/MMIC (when using encryption) */ |
144 | data_length = entry->skb->len + 4; | 161 | data_length = entry->skb->len + 4; |
145 | 162 | ||
146 | /* | 163 | /* |
@@ -149,6 +166,35 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
149 | if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) | 166 | if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) |
150 | __set_bit(ENTRY_TXD_ACK, &txdesc->flags); | 167 | __set_bit(ENTRY_TXD_ACK, &txdesc->flags); |
151 | 168 | ||
169 | #ifdef CONFIG_RT2X00_LIB_CRYPTO | ||
170 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) && | ||
171 | !entry->skb->do_not_encrypt) { | ||
172 | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; | ||
173 | |||
174 | __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); | ||
175 | |||
176 | txdesc->cipher = rt2x00crypto_key_to_cipher(hw_key); | ||
177 | |||
178 | if (hw_key->flags & IEEE80211_KEY_FLAG_PAIRWISE) | ||
179 | __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags); | ||
180 | |||
181 | txdesc->key_idx = hw_key->hw_key_idx; | ||
182 | txdesc->iv_offset = ieee80211_get_hdrlen_from_skb(entry->skb); | ||
183 | |||
184 | /* | ||
185 | * Extend frame length to include all encryption overhead | ||
186 | * that will be added by the hardware. | ||
187 | */ | ||
188 | data_length += rt2x00crypto_tx_overhead(tx_info); | ||
189 | |||
190 | if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) | ||
191 | __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags); | ||
192 | |||
193 | if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) | ||
194 | __set_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags); | ||
195 | } | ||
196 | #endif /* CONFIG_RT2X00_LIB_CRYPTO */ | ||
197 | |||
152 | /* | 198 | /* |
153 | * Check if this is a RTS/CTS frame | 199 | * Check if this is a RTS/CTS frame |
154 | */ | 200 | */ |
@@ -305,6 +351,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
305 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); | 351 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); |
306 | struct txentry_desc txdesc; | 352 | struct txentry_desc txdesc; |
307 | struct skb_frame_desc *skbdesc; | 353 | struct skb_frame_desc *skbdesc; |
354 | unsigned int iv_len = IEEE80211_SKB_CB(skb)->control.iv_len; | ||
308 | 355 | ||
309 | if (unlikely(rt2x00queue_full(queue))) | 356 | if (unlikely(rt2x00queue_full(queue))) |
310 | return -EINVAL; | 357 | return -EINVAL; |
@@ -326,15 +373,33 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
326 | rt2x00queue_create_tx_descriptor(entry, &txdesc); | 373 | rt2x00queue_create_tx_descriptor(entry, &txdesc); |
327 | 374 | ||
328 | /* | 375 | /* |
329 | * skb->cb array is now ours and we are free to use it. | 376 | * All information is retreived from the skb->cb array, |
377 | * now we should claim ownership of the driver part of that | ||
378 | * array. | ||
330 | */ | 379 | */ |
331 | skbdesc = get_skb_frame_desc(entry->skb); | 380 | skbdesc = get_skb_frame_desc(entry->skb); |
332 | memset(skbdesc, 0, sizeof(*skbdesc)); | 381 | memset(skbdesc, 0, sizeof(*skbdesc)); |
333 | skbdesc->entry = entry; | 382 | skbdesc->entry = entry; |
334 | 383 | ||
384 | /* | ||
385 | * When hardware encryption is supported, and this frame | ||
386 | * is to be encrypted, we should strip the IV/EIV data from | ||
387 | * the frame so we can provide it to the driver seperately. | ||
388 | */ | ||
389 | if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && | ||
390 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) | ||
391 | rt2x00crypto_tx_remove_iv(skb, iv_len); | ||
392 | |||
393 | /* | ||
394 | * It could be possible that the queue was corrupted and this | ||
395 | * call failed. Just drop the frame, we cannot rollback and pass | ||
396 | * the frame to mac80211 because the skb->cb has now been tainted. | ||
397 | */ | ||
335 | if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { | 398 | if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { |
336 | __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 399 | __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
337 | return -EIO; | 400 | dev_kfree_skb_any(entry->skb); |
401 | entry->skb = NULL; | ||
402 | return 0; | ||
338 | } | 403 | } |
339 | 404 | ||
340 | if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) | 405 | if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) |