aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00
diff options
context:
space:
mode:
authorGertjan van Wingerde <gwingerde@kpnplanet.nl>2008-06-16 13:56:08 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-26 16:49:15 -0400
commit30caa6e3d586442f7c3ad081260ee1b22bb123de (patch)
tree094bc3a12f31bc418b95a366d3602f1ab34b75bf /drivers/net/wireless/rt2x00
parent14a3bf89212b5c758bd39bb4afc972c4ba6d599f (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.h10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c77
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c71
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c21
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 */
905struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue); 905struct 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 */
911void 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 */
77static 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
77void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) 125void 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
32struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue) 32struct 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}
69EXPORT_SYMBOL_GPL(rt2x00queue_alloc_rxskb); 62EXPORT_SYMBOL_GPL(rt2x00queue_alloc_skb);
63
64void rt2x00queue_free_skb(struct sk_buff *skb)
65{
66 dev_kfree_skb_any(skb);
67}
68EXPORT_SYMBOL_GPL(rt2x00queue_free_skb);
70 69
71void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, 70void 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
424static 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
437static 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
452exit:
453 rt2x00queue_free_skbs(queue);
454
455 return -ENOMEM;
456}
457
425int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) 458int 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,
457int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) 455int 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
488exit: 471exit: