From patchwork Thu Apr 22 03:43:21 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sujith X-Patchwork-Id: 93992 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o3M3i09D002776 for ; Thu, 22 Apr 2010 03:44:03 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753812Ab0DVDnz (ORCPT ); Wed, 21 Apr 2010 23:43:55 -0400 Received: from mail.atheros.com ([12.36.123.2]:43123 "EHLO mail.atheros.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753475Ab0DVDnr (ORCPT ); Wed, 21 Apr 2010 23:43:47 -0400 Received: from mail.atheros.com ([10.10.20.108]) by sidewinder.atheros.com for ; Wed, 21 Apr 2010 20:43:47 -0700 Received: from CHEXHC-01.global.atheros.com (10.12.0.100) by SC1EXHC-02.global.atheros.com (10.10.20.107) with Microsoft SMTP Server (TLS) id 8.2.213.0; Wed, 21 Apr 2010 20:43:46 -0700 Received: from kamboji (10.12.0.31) by CHEXHC-01.global.atheros.com (10.12.0.100) with Microsoft SMTP Server (TLS) id 8.2.176.0; Thu, 22 Apr 2010 09:13:43 +0530 From: Sujith MIME-Version: 1.0 Message-ID: <19407.50649.569071.103503@gargle.gargle.HOWL> Date: Thu, 22 Apr 2010 09:13:21 +0530 To: X-Mailer: VM 8.0.12 under 23.1.1 (x86_64-unknown-linux-gnu) CC: Subject: [PATCH 1/9] ath9k_htc: Simplify TX URB management Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 22 Apr 2010 03:44:04 +0000 (UTC) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 3091bb3..cee5feb 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -93,14 +93,24 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, return ret; } +static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, + struct sk_buff_head *list) +{ + struct sk_buff *skb; + + while ((skb = __skb_dequeue(list)) != NULL) { + dev_kfree_skb_any(skb); + TX_STAT_INC(skb_dropped); + } +} + static void hif_usb_tx_cb(struct urb *urb) { struct tx_buf *tx_buf = (struct tx_buf *) urb->context; struct hif_device_usb *hif_dev = tx_buf->hif_dev; struct sk_buff *skb; - bool drop, flush; - if (!hif_dev) + if (!hif_dev || !tx_buf) return; switch (urb->status) { @@ -108,57 +118,47 @@ static void hif_usb_tx_cb(struct urb *urb) break; case -ENOENT: case -ECONNRESET: - break; case -ENODEV: case -ESHUTDOWN: + /* + * The URB has been killed, free the SKBs + * and return. + */ + ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); return; default: break; } - if (tx_buf) { - spin_lock(&hif_dev->tx.tx_lock); - drop = !!(hif_dev->tx.flags & HIF_USB_TX_STOP); - flush = !!(hif_dev->tx.flags & HIF_USB_TX_FLUSH); - spin_unlock(&hif_dev->tx.tx_lock); - - while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { - if (!drop && !flush) { - ath9k_htc_txcompletion_cb(hif_dev->htc_handle, - skb, 1); - TX_STAT_INC(skb_completed); - } else { - dev_kfree_skb_any(skb); - TX_STAT_INC(skb_dropped); - } - } - - if (flush) - return; - - tx_buf->len = tx_buf->offset = 0; - __skb_queue_head_init(&tx_buf->skb_queue); - - spin_lock(&hif_dev->tx.tx_lock); - list_del(&tx_buf->list); - list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf); - hif_dev->tx.tx_buf_cnt++; - if (!drop) - __hif_usb_tx(hif_dev); /* Check for pending SKBs */ - TX_STAT_INC(buf_completed); + /* Check if TX has been stopped */ + spin_lock(&hif_dev->tx.tx_lock); + if (hif_dev->tx.flags & HIF_USB_TX_STOP) { spin_unlock(&hif_dev->tx.tx_lock); - } -} - -static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, - struct sk_buff_head *list) -{ - struct sk_buff *skb; - - while ((skb = __skb_dequeue(list)) != NULL) { - dev_kfree_skb_any(skb); - TX_STAT_INC(skb_dropped); - } + ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); + goto add_free; + } + spin_unlock(&hif_dev->tx.tx_lock); + + /* Complete the queued SKBs. */ + while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { + ath9k_htc_txcompletion_cb(hif_dev->htc_handle, + skb, 1); + TX_STAT_INC(skb_completed); + } + +add_free: + /* Re-initialize the SKB queue */ + tx_buf->len = tx_buf->offset = 0; + __skb_queue_head_init(&tx_buf->skb_queue); + + /* Add this TX buffer to the free list */ + spin_lock(&hif_dev->tx.tx_lock); + list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); + hif_dev->tx.tx_buf_cnt++; + if (!(hif_dev->tx.flags & HIF_USB_TX_STOP)) + __hif_usb_tx(hif_dev); /* Check for pending SKBs */ + TX_STAT_INC(buf_completed); + spin_unlock(&hif_dev->tx.tx_lock); } /* TX lock has to be taken */ @@ -178,8 +178,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) return 0; tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list); - list_del(&tx_buf->list); - list_add_tail(&tx_buf->list, &hif_dev->tx.tx_pending); + list_move_tail(&tx_buf->list, &hif_dev->tx.tx_pending); hif_dev->tx.tx_buf_cnt--; tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM); @@ -548,20 +547,17 @@ free: static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) { - unsigned long flags; struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; - list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_buf, list) { + list_for_each_entry_safe(tx_buf, tx_buf_tmp, + &hif_dev->tx.tx_buf, list) { + usb_kill_urb(tx_buf->urb); list_del(&tx_buf->list); usb_free_urb(tx_buf->urb); kfree(tx_buf->buf); kfree(tx_buf); } - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - hif_dev->tx.flags |= HIF_USB_TX_FLUSH; - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); - list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_pending, list) { usb_kill_urb(tx_buf->urb); @@ -570,10 +566,6 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) kfree(tx_buf->buf); kfree(tx_buf); } - - spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); - hif_dev->tx.flags &= ~HIF_USB_TX_FLUSH; - spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); } static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 7d49a8a..0aca49b 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -61,7 +61,6 @@ struct tx_buf { }; #define HIF_USB_TX_STOP BIT(0) -#define HIF_USB_TX_FLUSH BIT(1) struct hif_usb_tx { u8 flags;