aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl1251/tx.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 19:29:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 19:29:25 -0400
commit7a6362800cb7d1d618a697a650c7aaed3eb39320 (patch)
tree087f9bc6c13ef1fad4b392c5cf9325cd28fa8523 /drivers/net/wireless/wl1251/tx.c
parent6445ced8670f37cfc2c5e24a9de9b413dbfc788d (diff)
parentceda86a108671294052cbf51660097b6534672f5 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1480 commits) bonding: enable netpoll without checking link status xfrm: Refcount destination entry on xfrm_lookup net: introduce rx_handler results and logic around that bonding: get rid of IFF_SLAVE_INACTIVE netdev->priv_flag bonding: wrap slave state work net: get rid of multiple bond-related netdevice->priv_flags bonding: register slave pointer for rx_handler be2net: Bump up the version number be2net: Copyright notice change. Update to Emulex instead of ServerEngines e1000e: fix kconfig for crc32 dependency netfilter ebtables: fix xt_AUDIT to work with ebtables xen network backend driver bonding: Improve syslog message at device creation time bonding: Call netif_carrier_off after register_netdevice bonding: Incorrect TX queue offset net_sched: fix ip_tos2prio xfrm: fix __xfrm_route_forward() be2net: Fix UDP packet detected status in RX compl Phonet: fix aligned-mode pipe socket buffer header reserve netxen: support for GbE port settings ... Fix up conflicts in drivers/staging/brcm80211/brcmsmac/wl_mac80211.c with the staging updates.
Diffstat (limited to 'drivers/net/wireless/wl1251/tx.c')
-rw-r--r--drivers/net/wireless/wl1251/tx.c74
1 files changed, 32 insertions, 42 deletions
diff --git a/drivers/net/wireless/wl1251/tx.c b/drivers/net/wireless/wl1251/tx.c
index 554b4f9a3d3e..28121c590a2b 100644
--- a/drivers/net/wireless/wl1251/tx.c
+++ b/drivers/net/wireless/wl1251/tx.c
@@ -213,16 +213,30 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb,
213 wl1251_debug(DEBUG_TX, "skb offset %d", offset); 213 wl1251_debug(DEBUG_TX, "skb offset %d", offset);
214 214
215 /* check whether the current skb can be used */ 215 /* check whether the current skb can be used */
216 if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) { 216 if (skb_cloned(skb) || (skb_tailroom(skb) < offset)) {
217 unsigned char *src = skb->data; 217 struct sk_buff *newskb = skb_copy_expand(skb, 0, 3,
218 GFP_KERNEL);
219
220 if (unlikely(newskb == NULL)) {
221 wl1251_error("Can't allocate skb!");
222 return -EINVAL;
223 }
218 224
219 /* align the buffer on a 4-byte boundary */ 225 tx_hdr = (struct tx_double_buffer_desc *) newskb->data;
226
227 dev_kfree_skb_any(skb);
228 wl->tx_frames[tx_hdr->id] = skb = newskb;
229
230 offset = (4 - (long)skb->data) & 0x03;
231 wl1251_debug(DEBUG_TX, "new skb offset %d", offset);
232 }
233
234 /* align the buffer on a 4-byte boundary */
235 if (offset) {
236 unsigned char *src = skb->data;
220 skb_reserve(skb, offset); 237 skb_reserve(skb, offset);
221 memmove(skb->data, src, skb->len); 238 memmove(skb->data, src, skb->len);
222 tx_hdr = (struct tx_double_buffer_desc *) skb->data; 239 tx_hdr = (struct tx_double_buffer_desc *) skb->data;
223 } else {
224 wl1251_info("No handler, fixme!");
225 return -EINVAL;
226 } 240 }
227 } 241 }
228 242
@@ -368,7 +382,7 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl,
368{ 382{
369 struct ieee80211_tx_info *info; 383 struct ieee80211_tx_info *info;
370 struct sk_buff *skb; 384 struct sk_buff *skb;
371 int hdrlen, ret; 385 int hdrlen;
372 u8 *frame; 386 u8 *frame;
373 387
374 skb = wl->tx_frames[result->id]; 388 skb = wl->tx_frames[result->id];
@@ -407,40 +421,12 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl,
407 ieee80211_tx_status(wl->hw, skb); 421 ieee80211_tx_status(wl->hw, skb);
408 422
409 wl->tx_frames[result->id] = NULL; 423 wl->tx_frames[result->id] = NULL;
410
411 if (wl->tx_queue_stopped) {
412 wl1251_debug(DEBUG_TX, "cb: queue was stopped");
413
414 skb = skb_dequeue(&wl->tx_queue);
415
416 /* The skb can be NULL because tx_work might have been
417 scheduled before the queue was stopped making the
418 queue empty */
419
420 if (skb) {
421 ret = wl1251_tx_frame(wl, skb);
422 if (ret == -EBUSY) {
423 /* firmware buffer is still full */
424 wl1251_debug(DEBUG_TX, "cb: fw buffer "
425 "still full");
426 skb_queue_head(&wl->tx_queue, skb);
427 return;
428 } else if (ret < 0) {
429 dev_kfree_skb(skb);
430 return;
431 }
432 }
433
434 wl1251_debug(DEBUG_TX, "cb: waking queues");
435 ieee80211_wake_queues(wl->hw);
436 wl->tx_queue_stopped = false;
437 }
438} 424}
439 425
440/* Called upon reception of a TX complete interrupt */ 426/* Called upon reception of a TX complete interrupt */
441void wl1251_tx_complete(struct wl1251 *wl) 427void wl1251_tx_complete(struct wl1251 *wl)
442{ 428{
443 int i, result_index, num_complete = 0; 429 int i, result_index, num_complete = 0, queue_len;
444 struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr; 430 struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr;
445 unsigned long flags; 431 unsigned long flags;
446 432
@@ -471,18 +457,22 @@ void wl1251_tx_complete(struct wl1251 *wl)
471 } 457 }
472 } 458 }
473 459
474 if (wl->tx_queue_stopped 460 queue_len = skb_queue_len(&wl->tx_queue);
475 &&
476 skb_queue_len(&wl->tx_queue) <= WL1251_TX_QUEUE_LOW_WATERMARK){
477 461
478 /* firmware buffer has space, restart queues */ 462 if ((num_complete > 0) && (queue_len > 0)) {
463 /* firmware buffer has space, reschedule tx_work */
464 wl1251_debug(DEBUG_TX, "tx_complete: reschedule tx_work");
465 ieee80211_queue_work(wl->hw, &wl->tx_work);
466 }
467
468 if (wl->tx_queue_stopped &&
469 queue_len <= WL1251_TX_QUEUE_LOW_WATERMARK) {
470 /* tx_queue has space, restart queues */
479 wl1251_debug(DEBUG_TX, "tx_complete: waking queues"); 471 wl1251_debug(DEBUG_TX, "tx_complete: waking queues");
480 spin_lock_irqsave(&wl->wl_lock, flags); 472 spin_lock_irqsave(&wl->wl_lock, flags);
481 ieee80211_wake_queues(wl->hw); 473 ieee80211_wake_queues(wl->hw);
482 wl->tx_queue_stopped = false; 474 wl->tx_queue_stopped = false;
483 spin_unlock_irqrestore(&wl->wl_lock, flags); 475 spin_unlock_irqrestore(&wl->wl_lock, flags);
484 ieee80211_queue_work(wl->hw, &wl->tx_work);
485
486 } 476 }
487 477
488 /* Every completed frame needs to be acknowledged */ 478 /* Every completed frame needs to be acknowledged */