aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2011-04-30 11:14:23 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-05-02 14:49:16 -0400
commita073fdef46d50440ee573452a436023dcf4f9edf (patch)
treeea24b8ae383103b74cb1864e66d0fef82ecee6cf
parent16763478892c271293d02872475a67a648ae12fc (diff)
rt2x00: Optimize TX_STA_FIFO register reading
Add recycling functionality to rt2x00usb_register_read_async. When the callback function returns true, resubmit the urb to read the register again. This optimizes the rt2800usb driver when multiple TX status reports are pending in the register, because now we don't need to allocate the rt2x00_async_read_data and urb structure each time. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Acked-by: Gertjan van Wingerde <gwingerde@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c9
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.h4
3 files changed, 15 insertions, 9 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index e4f82d2f341..b5d5f2203c5 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -114,12 +114,12 @@ static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
114 return false; 114 return false;
115} 115}
116 116
117static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, 117static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
118 int urb_status, u32 tx_status) 118 int urb_status, u32 tx_status)
119{ 119{
120 if (urb_status) { 120 if (urb_status) {
121 WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status); 121 WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status);
122 return; 122 return false;
123 } 123 }
124 124
125 /* try to read all TX_STA_FIFO entries before scheduling txdone_work */ 125 /* try to read all TX_STA_FIFO entries before scheduling txdone_work */
@@ -129,13 +129,14 @@ static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
129 "drop tx status report.\n"); 129 "drop tx status report.\n");
130 queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); 130 queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
131 } else 131 } else
132 rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, 132 return true;
133 rt2800usb_tx_sta_fifo_read_completed);
134 } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) { 133 } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
135 queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); 134 queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
136 } else if (rt2800usb_txstatus_pending(rt2x00dev)) { 135 } else if (rt2800usb_txstatus_pending(rt2x00dev)) {
137 mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(2)); 136 mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(2));
138 } 137 }
138
139 return false;
139} 140}
140 141
141static void rt2800usb_tx_dma_done(struct queue_entry *entry) 142static void rt2800usb_tx_dma_done(struct queue_entry *entry)
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 570184ee163..e027ebd4458 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -170,19 +170,22 @@ struct rt2x00_async_read_data {
170 __le32 reg; 170 __le32 reg;
171 struct usb_ctrlrequest cr; 171 struct usb_ctrlrequest cr;
172 struct rt2x00_dev *rt2x00dev; 172 struct rt2x00_dev *rt2x00dev;
173 void (*callback)(struct rt2x00_dev *,int,u32); 173 bool (*callback)(struct rt2x00_dev *, int, u32);
174}; 174};
175 175
176static void rt2x00usb_register_read_async_cb(struct urb *urb) 176static void rt2x00usb_register_read_async_cb(struct urb *urb)
177{ 177{
178 struct rt2x00_async_read_data *rd = urb->context; 178 struct rt2x00_async_read_data *rd = urb->context;
179 rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg)); 179 if (rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg))) {
180 kfree(urb->context); 180 if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
181 kfree(rd);
182 } else
183 kfree(rd);
181} 184}
182 185
183void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, 186void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
184 const unsigned int offset, 187 const unsigned int offset,
185 void (*callback)(struct rt2x00_dev*,int,u32)) 188 bool (*callback)(struct rt2x00_dev*, int, u32))
186{ 189{
187 struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); 190 struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
188 struct urb *urb; 191 struct urb *urb;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 52b09d2e11d..a69f1875887 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -349,10 +349,12 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
349 * be called from atomic context. The callback will be called 349 * be called from atomic context. The callback will be called
350 * when the URB completes. Otherwise the function is similar 350 * when the URB completes. Otherwise the function is similar
351 * to rt2x00usb_register_read(). 351 * to rt2x00usb_register_read().
352 * When the callback function returns false, the memory will be cleaned up,
353 * when it returns true, the urb will be fired again.
352 */ 354 */
353void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, 355void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
354 const unsigned int offset, 356 const unsigned int offset,
355 void (*callback)(struct rt2x00_dev*,int,u32)); 357 bool (*callback)(struct rt2x00_dev*, int, u32));
356 358
357/* 359/*
358 * Radio handlers 360 * Radio handlers