From patchwork Mon Mar 7 02:16:23 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sujith Manoharan X-Patchwork-Id: 614431 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p272GZE8019426 for ; Mon, 7 Mar 2011 02:16:35 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755252Ab1CGCQd (ORCPT ); Sun, 6 Mar 2011 21:16:33 -0500 Received: from mail-gx0-f174.google.com ([209.85.161.174]:51536 "EHLO mail-gx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755136Ab1CGCQd (ORCPT ); Sun, 6 Mar 2011 21:16:33 -0500 Received: by gxk8 with SMTP id 8so1465578gxk.19 for ; Sun, 06 Mar 2011 18:16:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:mime-version:content-type :content-transfer-encoding:message-id:date:to:x-mailer:cc:subject; bh=rfsy/WRkI0P+1fXWvXYRezl1CJiz2R2Qf1SauEnQMao=; b=aJsCZ/WuyDgM+5L/adUXfosRdv+rt8rn0rwq0GOZKUWzWjSuDNgcmnS1L1kksm9LK5 iyfMEhY1GKniJQQHCQezj2F4h/x3EmnzXP9QB4oyI6t3jhBTyPUaiyKgM0vS48tZ3h+l YmdvK/K1Fsn9hkX8OXTCqb/O/Llj3/RNbrumo= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:mime-version:content-type:content-transfer-encoding:message-id :date:to:x-mailer:cc:subject; b=D8+ydlnLi97NSPKlkzLPHArGJqCQcd91hvSpiwa4uVAE5PkEvuzlBCYtlRjmLcmcWE NrRzwKWKTxLpYIXI582NUqg/D57AyTu+nx321Cr5gfxtzNWbs5vlV6IAiZrkKd/6B9XE Fd0GqgM6stKFE9CzNrYMo9bBSRt5HJU1niTj8= Received: by 10.101.14.10 with SMTP id r10mr1096203ani.155.1299464192475; Sun, 06 Mar 2011 18:16:32 -0800 (PST) Received: from bodhi ([117.197.194.30]) by mx.google.com with ESMTPS id x31sm434327ana.29.2011.03.06.18.16.29 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 06 Mar 2011 18:16:31 -0800 (PST) From: Sujith MIME-Version: 1.0 Message-ID: <19828.16375.933094.853917@gargle.gargle.HOWL> Date: Mon, 7 Mar 2011 07:46:23 +0530 To: linux-wireless@vger.kernel.org X-Mailer: VM 8.1.1 under 23.2.1 (x86_64-unknown-linux-gnu) CC: ath9k-devel@venema.h4ckr.net Subject: [RFC 34/34] ath9k_htc: Use separate URB pool for management frames 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.6 (demeter1.kernel.org [140.211.167.41]); Mon, 07 Mar 2011 02:16:35 +0000 (UTC) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 4fb9585..e7cccf8 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -80,7 +80,7 @@ static void hif_usb_regout_cb(struct urb *urb) if (cmd) { ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, - cmd->skb, 1); + cmd->skb, true); kfree(cmd); } @@ -126,6 +126,90 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, return ret; } +static void hif_usb_mgmt_cb(struct urb *urb) +{ + struct cmd_buf *cmd = (struct cmd_buf *)urb->context; + struct hif_device_usb *hif_dev = cmd->hif_dev; + bool txok = true; + + if (!cmd || !cmd->skb || !cmd->hif_dev) + return; + + switch (urb->status) { + case 0: + break; + case -ENOENT: + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: + txok = false; + + /* + * If the URBs are being flushed, no need to complete + * this packet. + */ + spin_lock(&hif_dev->tx.tx_lock); + if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { + spin_unlock(&hif_dev->tx.tx_lock); + dev_kfree_skb_any(cmd->skb); + kfree(cmd); + return; + } + spin_unlock(&hif_dev->tx.tx_lock); + + break; + default: + txok = false; + break; + } + + skb_pull(cmd->skb, 4); + ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, + cmd->skb, txok); + kfree(cmd); +} + +static int hif_usb_send_mgmt(struct hif_device_usb *hif_dev, + struct sk_buff *skb) +{ + struct urb *urb; + struct cmd_buf *cmd; + int ret = 0; + __le16 *hdr; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (urb == NULL) + return -ENOMEM; + + cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); + if (cmd == NULL) { + usb_free_urb(urb); + return -ENOMEM; + } + + cmd->skb = skb; + cmd->hif_dev = hif_dev; + + hdr = (__le16 *) skb_push(skb, 4); + *hdr++ = cpu_to_le16(skb->len); + *hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG); + + usb_fill_bulk_urb(urb, hif_dev->udev, + usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE), + skb->data, skb->len, + hif_usb_mgmt_cb, cmd); + + usb_anchor_urb(urb, &hif_dev->mgmt_submitted); + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) { + usb_unanchor_urb(urb); + kfree(cmd); + } + usb_free_urb(urb); + + return ret; +} + static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, struct sk_buff_head *list) { @@ -277,6 +361,7 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb) { struct ath9k_htc_tx_ctl *tx_ctl; unsigned long flags; + int ret = 0; spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); @@ -291,25 +376,33 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb) return -ENOMEM; } - __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); - hif_dev->tx.tx_skb_cnt++; + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); tx_ctl = HTC_SKB_CB(skb); - /* Send normal/mgmt/beacon frames immediately */ - if (tx_ctl->type != ATH9K_HTC_AMPDU) - __hif_usb_tx(hif_dev); + /* Mgmt/Beacon frames don't use the TX buffer pool */ + if ((tx_ctl->type == ATH9K_HTC_MGMT) || + (tx_ctl->type == ATH9K_HTC_BEACON)) { + ret = hif_usb_send_mgmt(hif_dev, skb); + } + + spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + + if ((tx_ctl->type == ATH9K_HTC_NORMAL) || + (tx_ctl->type == ATH9K_HTC_AMPDU)) { + __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); + hif_dev->tx.tx_skb_cnt++; + } /* Check if AMPDUs have to be sent immediately */ - if ((tx_ctl->type == ATH9K_HTC_AMPDU) && - (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && + if ((hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && (hif_dev->tx.tx_skb_cnt < 2)) { __hif_usb_tx(hif_dev); } spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); - return 0; + return ret; } static void hif_usb_start(void *hif_handle) @@ -341,6 +434,8 @@ static void hif_usb_stop(void *hif_handle) &hif_dev->tx.tx_pending, list) { usb_kill_urb(tx_buf->urb); } + + usb_kill_anchored_urbs(&hif_dev->mgmt_submitted); } static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb) @@ -659,6 +754,8 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) kfree(tx_buf->buf); kfree(tx_buf); } + + usb_kill_anchored_urbs(&hif_dev->mgmt_submitted); } static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) @@ -670,6 +767,7 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) INIT_LIST_HEAD(&hif_dev->tx.tx_pending); spin_lock_init(&hif_dev->tx.tx_lock); __skb_queue_head_init(&hif_dev->tx.tx_skb_queue); + init_usb_anchor(&hif_dev->mgmt_submitted); for (i = 0; i < MAX_TX_URB_NUM; i++) { tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 8b98d64..f59df48 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -93,6 +93,7 @@ struct hif_device_usb { struct usb_anchor regout_submitted; struct usb_anchor rx_submitted; struct usb_anchor reg_in_submitted; + struct usb_anchor mgmt_submitted; struct sk_buff *remain_skb; const char *fw_name; int rx_remain_len;