diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00queue.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 71 |
1 files changed, 54 insertions, 17 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 15660b588a12..278f1a1ac926 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include "rt2x00.h" | 29 | #include "rt2x00.h" |
30 | #include "rt2x00lib.h" | 30 | #include "rt2x00lib.h" |
31 | 31 | ||
32 | struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue) | 32 | struct sk_buff *rt2x00queue_alloc_skb(struct data_queue *queue) |
33 | { | 33 | { |
34 | struct sk_buff *skb; | 34 | struct sk_buff *skb; |
35 | unsigned int frame_size; | 35 | unsigned int frame_size; |
@@ -42,17 +42,10 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue) | |||
42 | frame_size = queue->data_size + queue->desc_size; | 42 | frame_size = queue->data_size + queue->desc_size; |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * For the allocation we should keep a few things in mind: | 45 | * Reserve a few bytes extra headroom to allow drivers some moving |
46 | * 1) 4byte alignment of 802.11 payload | 46 | * space (e.g. for alignment), while keeping the skb aligned. |
47 | * | ||
48 | * For (1) we need at most 4 bytes to guarentee the correct | ||
49 | * alignment. We are going to optimize the fact that the chance | ||
50 | * that the 802.11 header_size % 4 == 2 is much bigger then | ||
51 | * anything else. However since we need to move the frame up | ||
52 | * to 3 bytes to the front, which means we need to preallocate | ||
53 | * 6 bytes. | ||
54 | */ | 47 | */ |
55 | reserved_size = 6; | 48 | reserved_size = 8; |
56 | 49 | ||
57 | /* | 50 | /* |
58 | * Allocate skbuffer. | 51 | * Allocate skbuffer. |
@@ -66,7 +59,13 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue) | |||
66 | 59 | ||
67 | return skb; | 60 | return skb; |
68 | } | 61 | } |
69 | EXPORT_SYMBOL_GPL(rt2x00queue_alloc_rxskb); | 62 | EXPORT_SYMBOL_GPL(rt2x00queue_alloc_skb); |
63 | |||
64 | void rt2x00queue_free_skb(struct sk_buff *skb) | ||
65 | { | ||
66 | dev_kfree_skb_any(skb); | ||
67 | } | ||
68 | EXPORT_SYMBOL_GPL(rt2x00queue_free_skb); | ||
70 | 69 | ||
71 | void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | 70 | void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, |
72 | struct txentry_desc *txdesc) | 71 | struct txentry_desc *txdesc) |
@@ -422,12 +421,45 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, | |||
422 | return 0; | 421 | return 0; |
423 | } | 422 | } |
424 | 423 | ||
424 | static void rt2x00queue_free_skbs(struct data_queue *queue) | ||
425 | { | ||
426 | unsigned int i; | ||
427 | |||
428 | if (!queue->entries) | ||
429 | return; | ||
430 | |||
431 | for (i = 0; i < queue->limit; i++) { | ||
432 | if (queue->entries[i].skb) | ||
433 | rt2x00queue_free_skb(queue->entries[i].skb); | ||
434 | } | ||
435 | } | ||
436 | |||
437 | static int rt2x00queue_alloc_skbs(struct data_queue *queue) | ||
438 | { | ||
439 | unsigned int i; | ||
440 | struct sk_buff *skb; | ||
441 | |||
442 | for (i = 0; i < queue->limit; i++) { | ||
443 | skb = rt2x00queue_alloc_skb(queue); | ||
444 | if (!skb) | ||
445 | goto exit; | ||
446 | |||
447 | queue->entries[i].skb = skb; | ||
448 | } | ||
449 | |||
450 | return 0; | ||
451 | |||
452 | exit: | ||
453 | rt2x00queue_free_skbs(queue); | ||
454 | |||
455 | return -ENOMEM; | ||
456 | } | ||
457 | |||
425 | int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) | 458 | int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) |
426 | { | 459 | { |
427 | struct data_queue *queue; | 460 | struct data_queue *queue; |
428 | int status; | 461 | int status; |
429 | 462 | ||
430 | |||
431 | status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx); | 463 | status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx); |
432 | if (status) | 464 | if (status) |
433 | goto exit; | 465 | goto exit; |
@@ -442,11 +474,14 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) | |||
442 | if (status) | 474 | if (status) |
443 | goto exit; | 475 | goto exit; |
444 | 476 | ||
445 | if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) | 477 | if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) { |
446 | return 0; | 478 | status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1], |
479 | rt2x00dev->ops->atim); | ||
480 | if (status) | ||
481 | goto exit; | ||
482 | } | ||
447 | 483 | ||
448 | status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1], | 484 | status = rt2x00queue_alloc_skbs(rt2x00dev->rx); |
449 | rt2x00dev->ops->atim); | ||
450 | if (status) | 485 | if (status) |
451 | goto exit; | 486 | goto exit; |
452 | 487 | ||
@@ -464,6 +499,8 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) | |||
464 | { | 499 | { |
465 | struct data_queue *queue; | 500 | struct data_queue *queue; |
466 | 501 | ||
502 | rt2x00queue_free_skbs(rt2x00dev->rx); | ||
503 | |||
467 | queue_for_each(rt2x00dev, queue) { | 504 | queue_for_each(rt2x00dev, queue) { |
468 | kfree(queue->entries); | 505 | kfree(queue->entries); |
469 | queue->entries = NULL; | 506 | queue->entries = NULL; |