diff options
author | Gertjan van Wingerde <gwingerde@kpnplanet.nl> | 2008-06-16 13:56:08 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-06-26 16:49:15 -0400 |
commit | 30caa6e3d586442f7c3ad081260ee1b22bb123de (patch) | |
tree | 094bc3a12f31bc418b95a366d3602f1ab34b75bf /drivers/net/wireless/rt2x00 | |
parent | 14a3bf89212b5c758bd39bb4afc972c4ba6d599f (diff) |
rt2x00: Centralize allocation of RX skbs.
In preparation of replacing the statically allocated DMA buffers with
dynamically mapped skbs, centralize the allocation of RX skbs to rt2x00queue.c
and let rt2x00pci already use them.
Signed-off-by: Gertjan van Wingerde <gwingerde@kpnplanet.nl>
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')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00pci.c | 77 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 71 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 21 |
4 files changed, 113 insertions, 66 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 8d45235ecc3..08e8b0a005a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -899,10 +899,16 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate) | |||
899 | } | 899 | } |
900 | 900 | ||
901 | /** | 901 | /** |
902 | * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes. | 902 | * rt2x00queue_alloc_skb - allocate a skb. |
903 | * @queue: The queue for which the skb will be applicable. | 903 | * @queue: The queue for which the skb will be applicable. |
904 | */ | 904 | */ |
905 | struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue); | 905 | struct sk_buff *rt2x00queue_alloc_skb(struct data_queue *queue); |
906 | |||
907 | /** | ||
908 | * rt2x00queue_free_skb - free a skb | ||
909 | * @skb: The skb to free. | ||
910 | */ | ||
911 | void rt2x00queue_free_skb(struct sk_buff *skb); | ||
906 | 912 | ||
907 | /** | 913 | /** |
908 | * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input | 914 | * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index d6138389a5d..e7e3a459b66 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -74,13 +74,59 @@ EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); | |||
74 | /* | 74 | /* |
75 | * TX/RX data handlers. | 75 | * TX/RX data handlers. |
76 | */ | 76 | */ |
77 | static void rt2x00pci_rxdone_entry(struct rt2x00_dev *rt2x00dev, | ||
78 | struct queue_entry *entry) | ||
79 | { | ||
80 | struct sk_buff *skb; | ||
81 | struct skb_frame_desc *skbdesc; | ||
82 | struct rxdone_entry_desc rxdesc; | ||
83 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | ||
84 | |||
85 | /* | ||
86 | * Allocate a new sk_buffer. If no new buffer available, drop the | ||
87 | * received frame and reuse the existing buffer. | ||
88 | */ | ||
89 | skb = rt2x00queue_alloc_skb(entry->queue); | ||
90 | if (!skb) | ||
91 | return; | ||
92 | |||
93 | /* | ||
94 | * Extract the RXD details. | ||
95 | */ | ||
96 | memset(&rxdesc, 0, sizeof(rxdesc)); | ||
97 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); | ||
98 | |||
99 | /* | ||
100 | * Copy the received data to the entries' skb. | ||
101 | */ | ||
102 | memcpy(entry->skb->data, entry_priv->data, rxdesc.size); | ||
103 | skb_trim(entry->skb, rxdesc.size); | ||
104 | |||
105 | /* | ||
106 | * Fill in skb descriptor | ||
107 | */ | ||
108 | skbdesc = get_skb_frame_desc(entry->skb); | ||
109 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
110 | skbdesc->desc = entry_priv->desc; | ||
111 | skbdesc->desc_len = entry->queue->desc_size; | ||
112 | skbdesc->entry = entry; | ||
113 | |||
114 | /* | ||
115 | * Send the frame to rt2x00lib for further processing. | ||
116 | */ | ||
117 | rt2x00lib_rxdone(entry, &rxdesc); | ||
118 | |||
119 | /* | ||
120 | * Replace the entries' skb with the newly allocated one. | ||
121 | */ | ||
122 | entry->skb = skb; | ||
123 | } | ||
124 | |||
77 | void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) | 125 | void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) |
78 | { | 126 | { |
79 | struct data_queue *queue = rt2x00dev->rx; | 127 | struct data_queue *queue = rt2x00dev->rx; |
80 | struct queue_entry *entry; | 128 | struct queue_entry *entry; |
81 | struct queue_entry_priv_pci *entry_priv; | 129 | struct queue_entry_priv_pci *entry_priv; |
82 | struct skb_frame_desc *skbdesc; | ||
83 | struct rxdone_entry_desc rxdesc; | ||
84 | u32 word; | 130 | u32 word; |
85 | 131 | ||
86 | while (1) { | 132 | while (1) { |
@@ -91,32 +137,7 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) | |||
91 | if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC)) | 137 | if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC)) |
92 | break; | 138 | break; |
93 | 139 | ||
94 | memset(&rxdesc, 0, sizeof(rxdesc)); | 140 | rt2x00pci_rxdone_entry(rt2x00dev, entry); |
95 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); | ||
96 | |||
97 | /* | ||
98 | * Allocate the sk_buffer and copy all data into it. | ||
99 | */ | ||
100 | entry->skb = rt2x00queue_alloc_rxskb(queue); | ||
101 | if (!entry->skb) | ||
102 | return; | ||
103 | |||
104 | memcpy(entry->skb->data, entry_priv->data, rxdesc.size); | ||
105 | skb_trim(entry->skb, rxdesc.size); | ||
106 | |||
107 | /* | ||
108 | * Fill in skb descriptor | ||
109 | */ | ||
110 | skbdesc = get_skb_frame_desc(entry->skb); | ||
111 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
112 | skbdesc->desc = entry_priv->desc; | ||
113 | skbdesc->desc_len = queue->desc_size; | ||
114 | skbdesc->entry = entry; | ||
115 | |||
116 | /* | ||
117 | * Send the frame to rt2x00lib for further processing. | ||
118 | */ | ||
119 | rt2x00lib_rxdone(entry, &rxdesc); | ||
120 | 141 | ||
121 | if (test_bit(DEVICE_ENABLED_RADIO, &queue->rt2x00dev->flags)) { | 142 | if (test_bit(DEVICE_ENABLED_RADIO, &queue->rt2x00dev->flags)) { |
122 | rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1); | 143 | rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 15660b588a1..278f1a1ac92 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; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index f91901ffda5..29dba86c8cf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -300,7 +300,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
300 | * If allocation fails, we should drop the current frame | 300 | * If allocation fails, we should drop the current frame |
301 | * so we can recycle the existing sk buffer for the new frame. | 301 | * so we can recycle the existing sk buffer for the new frame. |
302 | */ | 302 | */ |
303 | skb = rt2x00queue_alloc_rxskb(entry->queue); | 303 | skb = rt2x00queue_alloc_skb(entry->queue); |
304 | if (!skb) | 304 | if (!skb) |
305 | goto skip_entry; | 305 | goto skip_entry; |
306 | 306 | ||
@@ -434,8 +434,6 @@ static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, | |||
434 | entry_priv = queue->entries[i].priv_data; | 434 | entry_priv = queue->entries[i].priv_data; |
435 | usb_kill_urb(entry_priv->urb); | 435 | usb_kill_urb(entry_priv->urb); |
436 | usb_free_urb(entry_priv->urb); | 436 | usb_free_urb(entry_priv->urb); |
437 | if (queue->entries[i].skb) | ||
438 | kfree_skb(queue->entries[i].skb); | ||
439 | } | 437 | } |
440 | 438 | ||
441 | /* | 439 | /* |
@@ -457,10 +455,7 @@ static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, | |||
457 | int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) | 455 | int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) |
458 | { | 456 | { |
459 | struct data_queue *queue; | 457 | struct data_queue *queue; |
460 | struct sk_buff *skb; | 458 | int status; |
461 | unsigned int entry_size; | ||
462 | unsigned int i; | ||
463 | int uninitialized_var(status); | ||
464 | 459 | ||
465 | /* | 460 | /* |
466 | * Allocate DMA | 461 | * Allocate DMA |
@@ -471,18 +466,6 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) | |||
471 | goto exit; | 466 | goto exit; |
472 | } | 467 | } |
473 | 468 | ||
474 | /* | ||
475 | * For the RX queue, skb's should be allocated. | ||
476 | */ | ||
477 | entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size; | ||
478 | for (i = 0; i < rt2x00dev->rx->limit; i++) { | ||
479 | skb = rt2x00queue_alloc_rxskb(rt2x00dev->rx); | ||
480 | if (!skb) | ||
481 | goto exit; | ||
482 | |||
483 | rt2x00dev->rx->entries[i].skb = skb; | ||
484 | } | ||
485 | |||
486 | return 0; | 469 | return 0; |
487 | 470 | ||
488 | exit: | 471 | exit: |