diff options
Diffstat (limited to 'net/ieee80211/ieee80211_tx.c')
-rw-r--r-- | net/ieee80211/ieee80211_tx.c | 321 |
1 files changed, 237 insertions, 84 deletions
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index eed07bbbe6b6..95ccbadbf55b 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | 2 | ||
3 | Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. | 3 | Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. |
4 | 4 | ||
5 | This program is free software; you can redistribute it and/or modify it | 5 | This program is free software; you can redistribute it and/or modify it |
6 | under the terms of version 2 of the GNU General Public License as | 6 | under the terms of version 2 of the GNU General Public License as |
@@ -128,7 +128,7 @@ payload of each frame is reduced to 492 bytes. | |||
128 | static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; | 128 | static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; |
129 | static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; | 129 | static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; |
130 | 130 | ||
131 | static inline int ieee80211_put_snap(u8 * data, u16 h_proto) | 131 | static inline int ieee80211_copy_snap(u8 * data, u16 h_proto) |
132 | { | 132 | { |
133 | struct ieee80211_snap_hdr *snap; | 133 | struct ieee80211_snap_hdr *snap; |
134 | u8 *oui; | 134 | u8 *oui; |
@@ -157,31 +157,14 @@ static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, | |||
157 | struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx]; | 157 | struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx]; |
158 | int res; | 158 | int res; |
159 | 159 | ||
160 | #ifdef CONFIG_IEEE80211_CRYPT_TKIP | 160 | if (crypt == NULL) |
161 | struct ieee80211_hdr *header; | ||
162 | |||
163 | if (ieee->tkip_countermeasures && | ||
164 | crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) { | ||
165 | header = (struct ieee80211_hdr *)frag->data; | ||
166 | if (net_ratelimit()) { | ||
167 | printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " | ||
168 | "TX packet to " MAC_FMT "\n", | ||
169 | ieee->dev->name, MAC_ARG(header->addr1)); | ||
170 | } | ||
171 | return -1; | 161 | return -1; |
172 | } | 162 | |
173 | #endif | ||
174 | /* To encrypt, frame format is: | 163 | /* To encrypt, frame format is: |
175 | * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */ | 164 | * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */ |
176 | |||
177 | // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption. | ||
178 | /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so | ||
179 | * call both MSDU and MPDU encryption functions from here. */ | ||
180 | atomic_inc(&crypt->refcnt); | 165 | atomic_inc(&crypt->refcnt); |
181 | res = 0; | 166 | res = 0; |
182 | if (crypt->ops->encrypt_msdu) | 167 | if (crypt->ops && crypt->ops->encrypt_mpdu) |
183 | res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv); | ||
184 | if (res == 0 && crypt->ops->encrypt_mpdu) | ||
185 | res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); | 168 | res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); |
186 | 169 | ||
187 | atomic_dec(&crypt->refcnt); | 170 | atomic_dec(&crypt->refcnt); |
@@ -207,7 +190,7 @@ void ieee80211_txb_free(struct ieee80211_txb *txb) | |||
207 | } | 190 | } |
208 | 191 | ||
209 | static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, | 192 | static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, |
210 | gfp_t gfp_mask) | 193 | int headroom, gfp_t gfp_mask) |
211 | { | 194 | { |
212 | struct ieee80211_txb *txb; | 195 | struct ieee80211_txb *txb; |
213 | int i; | 196 | int i; |
@@ -221,11 +204,13 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, | |||
221 | txb->frag_size = txb_size; | 204 | txb->frag_size = txb_size; |
222 | 205 | ||
223 | for (i = 0; i < nr_frags; i++) { | 206 | for (i = 0; i < nr_frags; i++) { |
224 | txb->fragments[i] = dev_alloc_skb(txb_size); | 207 | txb->fragments[i] = __dev_alloc_skb(txb_size + headroom, |
208 | gfp_mask); | ||
225 | if (unlikely(!txb->fragments[i])) { | 209 | if (unlikely(!txb->fragments[i])) { |
226 | i--; | 210 | i--; |
227 | break; | 211 | break; |
228 | } | 212 | } |
213 | skb_reserve(txb->fragments[i], headroom); | ||
229 | } | 214 | } |
230 | if (unlikely(i != nr_frags)) { | 215 | if (unlikely(i != nr_frags)) { |
231 | while (i >= 0) | 216 | while (i >= 0) |
@@ -236,25 +221,31 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, | |||
236 | return txb; | 221 | return txb; |
237 | } | 222 | } |
238 | 223 | ||
239 | /* SKBs are added to the ieee->tx_queue. */ | 224 | /* Incoming skb is converted to a txb which consists of |
225 | * a block of 802.11 fragment packets (stored as skbs) */ | ||
240 | int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | 226 | int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) |
241 | { | 227 | { |
242 | struct ieee80211_device *ieee = netdev_priv(dev); | 228 | struct ieee80211_device *ieee = netdev_priv(dev); |
243 | struct ieee80211_txb *txb = NULL; | 229 | struct ieee80211_txb *txb = NULL; |
244 | struct ieee80211_hdr *frag_hdr; | 230 | struct ieee80211_hdr_3addr *frag_hdr; |
245 | int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; | 231 | int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size, |
232 | rts_required; | ||
246 | unsigned long flags; | 233 | unsigned long flags; |
247 | struct net_device_stats *stats = &ieee->stats; | 234 | struct net_device_stats *stats = &ieee->stats; |
248 | int ether_type, encrypt; | 235 | int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv; |
249 | int bytes, fc, hdr_len; | 236 | int bytes, fc, hdr_len; |
250 | struct sk_buff *skb_frag; | 237 | struct sk_buff *skb_frag; |
251 | struct ieee80211_hdr header = { /* Ensure zero initialized */ | 238 | struct ieee80211_hdr_3addr header = { /* Ensure zero initialized */ |
252 | .duration_id = 0, | 239 | .duration_id = 0, |
253 | .seq_ctl = 0 | 240 | .seq_ctl = 0 |
254 | }; | 241 | }; |
255 | u8 dest[ETH_ALEN], src[ETH_ALEN]; | 242 | u8 dest[ETH_ALEN], src[ETH_ALEN]; |
256 | |||
257 | struct ieee80211_crypt_data *crypt; | 243 | struct ieee80211_crypt_data *crypt; |
244 | int priority = skb->priority; | ||
245 | int snapped = 0; | ||
246 | |||
247 | if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority)) | ||
248 | return NETDEV_TX_BUSY; | ||
258 | 249 | ||
259 | spin_lock_irqsave(&ieee->lock, flags); | 250 | spin_lock_irqsave(&ieee->lock, flags); |
260 | 251 | ||
@@ -276,7 +267,11 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
276 | crypt = ieee->crypt[ieee->tx_keyidx]; | 267 | crypt = ieee->crypt[ieee->tx_keyidx]; |
277 | 268 | ||
278 | encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && | 269 | encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && |
279 | ieee->host_encrypt && crypt && crypt->ops; | 270 | ieee->sec.encrypt; |
271 | |||
272 | host_encrypt = ieee->host_encrypt && encrypt && crypt; | ||
273 | host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt; | ||
274 | host_build_iv = ieee->host_build_iv && encrypt && crypt; | ||
280 | 275 | ||
281 | if (!encrypt && ieee->ieee802_1x && | 276 | if (!encrypt && ieee->ieee802_1x && |
282 | ieee->drop_unencrypted && ether_type != ETH_P_PAE) { | 277 | ieee->drop_unencrypted && ether_type != ETH_P_PAE) { |
@@ -285,8 +280,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
285 | } | 280 | } |
286 | 281 | ||
287 | /* Save source and destination addresses */ | 282 | /* Save source and destination addresses */ |
288 | memcpy(&dest, skb->data, ETH_ALEN); | 283 | memcpy(dest, skb->data, ETH_ALEN); |
289 | memcpy(&src, skb->data + ETH_ALEN, ETH_ALEN); | 284 | memcpy(src, skb->data + ETH_ALEN, ETH_ALEN); |
290 | 285 | ||
291 | /* Advance the SKB to the start of the payload */ | 286 | /* Advance the SKB to the start of the payload */ |
292 | skb_pull(skb, sizeof(struct ethhdr)); | 287 | skb_pull(skb, sizeof(struct ethhdr)); |
@@ -294,7 +289,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
294 | /* Determine total amount of storage required for TXB packets */ | 289 | /* Determine total amount of storage required for TXB packets */ |
295 | bytes = skb->len + SNAP_SIZE + sizeof(u16); | 290 | bytes = skb->len + SNAP_SIZE + sizeof(u16); |
296 | 291 | ||
297 | if (encrypt) | 292 | if (host_encrypt) |
298 | fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | | 293 | fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | |
299 | IEEE80211_FCTL_PROTECTED; | 294 | IEEE80211_FCTL_PROTECTED; |
300 | else | 295 | else |
@@ -302,70 +297,144 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
302 | 297 | ||
303 | if (ieee->iw_mode == IW_MODE_INFRA) { | 298 | if (ieee->iw_mode == IW_MODE_INFRA) { |
304 | fc |= IEEE80211_FCTL_TODS; | 299 | fc |= IEEE80211_FCTL_TODS; |
305 | /* To DS: Addr1 = BSSID, Addr2 = SA, | 300 | /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ |
306 | Addr3 = DA */ | 301 | memcpy(header.addr1, ieee->bssid, ETH_ALEN); |
307 | memcpy(&header.addr1, ieee->bssid, ETH_ALEN); | 302 | memcpy(header.addr2, src, ETH_ALEN); |
308 | memcpy(&header.addr2, &src, ETH_ALEN); | 303 | memcpy(header.addr3, dest, ETH_ALEN); |
309 | memcpy(&header.addr3, &dest, ETH_ALEN); | ||
310 | } else if (ieee->iw_mode == IW_MODE_ADHOC) { | 304 | } else if (ieee->iw_mode == IW_MODE_ADHOC) { |
311 | /* not From/To DS: Addr1 = DA, Addr2 = SA, | 305 | /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */ |
312 | Addr3 = BSSID */ | 306 | memcpy(header.addr1, dest, ETH_ALEN); |
313 | memcpy(&header.addr1, dest, ETH_ALEN); | 307 | memcpy(header.addr2, src, ETH_ALEN); |
314 | memcpy(&header.addr2, src, ETH_ALEN); | 308 | memcpy(header.addr3, ieee->bssid, ETH_ALEN); |
315 | memcpy(&header.addr3, ieee->bssid, ETH_ALEN); | ||
316 | } | 309 | } |
317 | header.frame_ctl = cpu_to_le16(fc); | 310 | header.frame_ctl = cpu_to_le16(fc); |
318 | hdr_len = IEEE80211_3ADDR_LEN; | 311 | hdr_len = IEEE80211_3ADDR_LEN; |
319 | 312 | ||
320 | /* Determine fragmentation size based on destination (multicast | 313 | /* Encrypt msdu first on the whole data packet. */ |
321 | * and broadcast are not fragmented) */ | 314 | if ((host_encrypt || host_encrypt_msdu) && |
322 | if (is_multicast_ether_addr(dest) || is_broadcast_ether_addr(dest)) | 315 | crypt && crypt->ops && crypt->ops->encrypt_msdu) { |
323 | frag_size = MAX_FRAG_THRESHOLD; | 316 | int res = 0; |
324 | else | 317 | int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len + |
325 | frag_size = ieee->fts; | 318 | crypt->ops->extra_msdu_postfix_len; |
319 | struct sk_buff *skb_new = dev_alloc_skb(len); | ||
320 | |||
321 | if (unlikely(!skb_new)) | ||
322 | goto failed; | ||
323 | |||
324 | skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len); | ||
325 | memcpy(skb_put(skb_new, hdr_len), &header, hdr_len); | ||
326 | snapped = 1; | ||
327 | ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)), | ||
328 | ether_type); | ||
329 | memcpy(skb_put(skb_new, skb->len), skb->data, skb->len); | ||
330 | res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv); | ||
331 | if (res < 0) { | ||
332 | IEEE80211_ERROR("msdu encryption failed\n"); | ||
333 | dev_kfree_skb_any(skb_new); | ||
334 | goto failed; | ||
335 | } | ||
336 | dev_kfree_skb_any(skb); | ||
337 | skb = skb_new; | ||
338 | bytes += crypt->ops->extra_msdu_prefix_len + | ||
339 | crypt->ops->extra_msdu_postfix_len; | ||
340 | skb_pull(skb, hdr_len); | ||
341 | } | ||
326 | 342 | ||
327 | /* Determine amount of payload per fragment. Regardless of if | 343 | if (host_encrypt || ieee->host_open_frag) { |
328 | * this stack is providing the full 802.11 header, one will | 344 | /* Determine fragmentation size based on destination (multicast |
329 | * eventually be affixed to this fragment -- so we must account for | 345 | * and broadcast are not fragmented) */ |
330 | * it when determining the amount of payload space. */ | 346 | if (is_multicast_ether_addr(dest) || |
331 | bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN; | 347 | is_broadcast_ether_addr(dest)) |
332 | if (ieee->config & | 348 | frag_size = MAX_FRAG_THRESHOLD; |
333 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | 349 | else |
334 | bytes_per_frag -= IEEE80211_FCS_LEN; | 350 | frag_size = ieee->fts; |
335 | 351 | ||
336 | /* Each fragment may need to have room for encryptiong pre/postfix */ | 352 | /* Determine amount of payload per fragment. Regardless of if |
337 | if (encrypt) | 353 | * this stack is providing the full 802.11 header, one will |
338 | bytes_per_frag -= crypt->ops->extra_prefix_len + | 354 | * eventually be affixed to this fragment -- so we must account |
339 | crypt->ops->extra_postfix_len; | 355 | * for it when determining the amount of payload space. */ |
340 | 356 | bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN; | |
341 | /* Number of fragments is the total bytes_per_frag / | 357 | if (ieee->config & |
342 | * payload_per_fragment */ | 358 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) |
343 | nr_frags = bytes / bytes_per_frag; | 359 | bytes_per_frag -= IEEE80211_FCS_LEN; |
344 | bytes_last_frag = bytes % bytes_per_frag; | 360 | |
345 | if (bytes_last_frag) | 361 | /* Each fragment may need to have room for encryptiong |
362 | * pre/postfix */ | ||
363 | if (host_encrypt) | ||
364 | bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len + | ||
365 | crypt->ops->extra_mpdu_postfix_len; | ||
366 | |||
367 | /* Number of fragments is the total | ||
368 | * bytes_per_frag / payload_per_fragment */ | ||
369 | nr_frags = bytes / bytes_per_frag; | ||
370 | bytes_last_frag = bytes % bytes_per_frag; | ||
371 | if (bytes_last_frag) | ||
372 | nr_frags++; | ||
373 | else | ||
374 | bytes_last_frag = bytes_per_frag; | ||
375 | } else { | ||
376 | nr_frags = 1; | ||
377 | bytes_per_frag = bytes_last_frag = bytes; | ||
378 | frag_size = bytes + IEEE80211_3ADDR_LEN; | ||
379 | } | ||
380 | |||
381 | rts_required = (frag_size > ieee->rts | ||
382 | && ieee->config & CFG_IEEE80211_RTS); | ||
383 | if (rts_required) | ||
346 | nr_frags++; | 384 | nr_frags++; |
347 | else | ||
348 | bytes_last_frag = bytes_per_frag; | ||
349 | 385 | ||
350 | /* When we allocate the TXB we allocate enough space for the reserve | 386 | /* When we allocate the TXB we allocate enough space for the reserve |
351 | * and full fragment bytes (bytes_per_frag doesn't include prefix, | 387 | * and full fragment bytes (bytes_per_frag doesn't include prefix, |
352 | * postfix, header, FCS, etc.) */ | 388 | * postfix, header, FCS, etc.) */ |
353 | txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC); | 389 | txb = ieee80211_alloc_txb(nr_frags, frag_size, |
390 | ieee->tx_headroom, GFP_ATOMIC); | ||
354 | if (unlikely(!txb)) { | 391 | if (unlikely(!txb)) { |
355 | printk(KERN_WARNING "%s: Could not allocate TXB\n", | 392 | printk(KERN_WARNING "%s: Could not allocate TXB\n", |
356 | ieee->dev->name); | 393 | ieee->dev->name); |
357 | goto failed; | 394 | goto failed; |
358 | } | 395 | } |
359 | txb->encrypted = encrypt; | 396 | txb->encrypted = encrypt; |
360 | txb->payload_size = bytes; | 397 | if (host_encrypt) |
398 | txb->payload_size = frag_size * (nr_frags - 1) + | ||
399 | bytes_last_frag; | ||
400 | else | ||
401 | txb->payload_size = bytes; | ||
402 | |||
403 | if (rts_required) { | ||
404 | skb_frag = txb->fragments[0]; | ||
405 | frag_hdr = | ||
406 | (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len); | ||
407 | |||
408 | /* | ||
409 | * Set header frame_ctl to the RTS. | ||
410 | */ | ||
411 | header.frame_ctl = | ||
412 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); | ||
413 | memcpy(frag_hdr, &header, hdr_len); | ||
361 | 414 | ||
362 | for (i = 0; i < nr_frags; i++) { | 415 | /* |
416 | * Restore header frame_ctl to the original data setting. | ||
417 | */ | ||
418 | header.frame_ctl = cpu_to_le16(fc); | ||
419 | |||
420 | if (ieee->config & | ||
421 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | ||
422 | skb_put(skb_frag, 4); | ||
423 | |||
424 | txb->rts_included = 1; | ||
425 | i = 1; | ||
426 | } else | ||
427 | i = 0; | ||
428 | |||
429 | for (; i < nr_frags; i++) { | ||
363 | skb_frag = txb->fragments[i]; | 430 | skb_frag = txb->fragments[i]; |
364 | 431 | ||
365 | if (encrypt) | 432 | if (host_encrypt || host_build_iv) |
366 | skb_reserve(skb_frag, crypt->ops->extra_prefix_len); | 433 | skb_reserve(skb_frag, |
434 | crypt->ops->extra_mpdu_prefix_len); | ||
367 | 435 | ||
368 | frag_hdr = (struct ieee80211_hdr *)skb_put(skb_frag, hdr_len); | 436 | frag_hdr = |
437 | (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len); | ||
369 | memcpy(frag_hdr, &header, hdr_len); | 438 | memcpy(frag_hdr, &header, hdr_len); |
370 | 439 | ||
371 | /* If this is not the last fragment, then add the MOREFRAGS | 440 | /* If this is not the last fragment, then add the MOREFRAGS |
@@ -379,11 +448,10 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
379 | bytes = bytes_last_frag; | 448 | bytes = bytes_last_frag; |
380 | } | 449 | } |
381 | 450 | ||
382 | /* Put a SNAP header on the first fragment */ | 451 | if (i == 0 && !snapped) { |
383 | if (i == 0) { | 452 | ieee80211_copy_snap(skb_put |
384 | ieee80211_put_snap(skb_put | 453 | (skb_frag, SNAP_SIZE + sizeof(u16)), |
385 | (skb_frag, SNAP_SIZE + sizeof(u16)), | 454 | ether_type); |
386 | ether_type); | ||
387 | bytes -= SNAP_SIZE + sizeof(u16); | 455 | bytes -= SNAP_SIZE + sizeof(u16); |
388 | } | 456 | } |
389 | 457 | ||
@@ -394,8 +462,19 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
394 | 462 | ||
395 | /* Encryption routine will move the header forward in order | 463 | /* Encryption routine will move the header forward in order |
396 | * to insert the IV between the header and the payload */ | 464 | * to insert the IV between the header and the payload */ |
397 | if (encrypt) | 465 | if (host_encrypt) |
398 | ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); | 466 | ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); |
467 | else if (host_build_iv) { | ||
468 | struct ieee80211_crypt_data *crypt; | ||
469 | |||
470 | crypt = ieee->crypt[ieee->tx_keyidx]; | ||
471 | atomic_inc(&crypt->refcnt); | ||
472 | if (crypt->ops->build_iv) | ||
473 | crypt->ops->build_iv(skb_frag, hdr_len, | ||
474 | crypt->priv); | ||
475 | atomic_dec(&crypt->refcnt); | ||
476 | } | ||
477 | |||
399 | if (ieee->config & | 478 | if (ieee->config & |
400 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | 479 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) |
401 | skb_put(skb_frag, 4); | 480 | skb_put(skb_frag, 4); |
@@ -407,11 +486,20 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
407 | dev_kfree_skb_any(skb); | 486 | dev_kfree_skb_any(skb); |
408 | 487 | ||
409 | if (txb) { | 488 | if (txb) { |
410 | if ((*ieee->hard_start_xmit) (txb, dev) == 0) { | 489 | int ret = (*ieee->hard_start_xmit) (txb, dev, priority); |
490 | if (ret == 0) { | ||
411 | stats->tx_packets++; | 491 | stats->tx_packets++; |
412 | stats->tx_bytes += txb->payload_size; | 492 | stats->tx_bytes += txb->payload_size; |
413 | return 0; | 493 | return 0; |
414 | } | 494 | } |
495 | |||
496 | if (ret == NETDEV_TX_BUSY) { | ||
497 | printk(KERN_ERR "%s: NETDEV_TX_BUSY returned; " | ||
498 | "driver should report queue full via " | ||
499 | "ieee_device->is_queue_full.\n", | ||
500 | ieee->dev->name); | ||
501 | } | ||
502 | |||
415 | ieee80211_txb_free(txb); | 503 | ieee80211_txb_free(txb); |
416 | } | 504 | } |
417 | 505 | ||
@@ -422,7 +510,72 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
422 | netif_stop_queue(dev); | 510 | netif_stop_queue(dev); |
423 | stats->tx_errors++; | 511 | stats->tx_errors++; |
424 | return 1; | 512 | return 1; |
513 | } | ||
514 | |||
515 | /* Incoming 802.11 strucure is converted to a TXB | ||
516 | * a block of 802.11 fragment packets (stored as skbs) */ | ||
517 | int ieee80211_tx_frame(struct ieee80211_device *ieee, | ||
518 | struct ieee80211_hdr *frame, int len) | ||
519 | { | ||
520 | struct ieee80211_txb *txb = NULL; | ||
521 | unsigned long flags; | ||
522 | struct net_device_stats *stats = &ieee->stats; | ||
523 | struct sk_buff *skb_frag; | ||
524 | int priority = -1; | ||
525 | |||
526 | spin_lock_irqsave(&ieee->lock, flags); | ||
425 | 527 | ||
528 | /* If there is no driver handler to take the TXB, dont' bother | ||
529 | * creating it... */ | ||
530 | if (!ieee->hard_start_xmit) { | ||
531 | printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); | ||
532 | goto success; | ||
533 | } | ||
534 | |||
535 | if (unlikely(len < 24)) { | ||
536 | printk(KERN_WARNING "%s: skb too small (%d).\n", | ||
537 | ieee->dev->name, len); | ||
538 | goto success; | ||
539 | } | ||
540 | |||
541 | /* When we allocate the TXB we allocate enough space for the reserve | ||
542 | * and full fragment bytes (bytes_per_frag doesn't include prefix, | ||
543 | * postfix, header, FCS, etc.) */ | ||
544 | txb = ieee80211_alloc_txb(1, len, ieee->tx_headroom, GFP_ATOMIC); | ||
545 | if (unlikely(!txb)) { | ||
546 | printk(KERN_WARNING "%s: Could not allocate TXB\n", | ||
547 | ieee->dev->name); | ||
548 | goto failed; | ||
549 | } | ||
550 | txb->encrypted = 0; | ||
551 | txb->payload_size = len; | ||
552 | |||
553 | skb_frag = txb->fragments[0]; | ||
554 | |||
555 | memcpy(skb_put(skb_frag, len), frame, len); | ||
556 | |||
557 | if (ieee->config & | ||
558 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | ||
559 | skb_put(skb_frag, 4); | ||
560 | |||
561 | success: | ||
562 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
563 | |||
564 | if (txb) { | ||
565 | if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) { | ||
566 | stats->tx_packets++; | ||
567 | stats->tx_bytes += txb->payload_size; | ||
568 | return 0; | ||
569 | } | ||
570 | ieee80211_txb_free(txb); | ||
571 | } | ||
572 | return 0; | ||
573 | |||
574 | failed: | ||
575 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
576 | stats->tx_errors++; | ||
577 | return 1; | ||
426 | } | 578 | } |
427 | 579 | ||
580 | EXPORT_SYMBOL(ieee80211_tx_frame); | ||
428 | EXPORT_SYMBOL(ieee80211_txb_free); | 581 | EXPORT_SYMBOL(ieee80211_txb_free); |