From patchwork Tue Mar 1 10:32:48 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Kazior X-Patchwork-Id: 8463911 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 668F9C0553 for ; Tue, 1 Mar 2016 10:32:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 218EA2012D for ; Tue, 1 Mar 2016 10:32:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1D928201BC for ; Tue, 1 Mar 2016 10:32:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752901AbcCAKcR (ORCPT ); Tue, 1 Mar 2016 05:32:17 -0500 Received: from mail-lf0-f50.google.com ([209.85.215.50]:34761 "EHLO mail-lf0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752804AbcCAKcM (ORCPT ); Tue, 1 Mar 2016 05:32:12 -0500 Received: by mail-lf0-f50.google.com with SMTP id j78so110091556lfb.1 for ; Tue, 01 Mar 2016 02:32:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tieto.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=P4t6hqCyk3ATZAADlIi5O5w+BZb7EQ8IpkGa3vbwzAY=; b=bnbLJWp/RwmAHP/dFpmg8klJUgE4GZJby+OIIzZCLxFmNdBYbMXI6SEGGVL3YlE6Sp W7/4BS7CxGeKiEq0HRNLSCXSvk4A/8nWHKN4bmudfl8YVZQUL16knyMt9+ATxM+DljqS X4OS4woO0iPE1CVQAmqy4/LlX9G/Ccq+ZeArM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=P4t6hqCyk3ATZAADlIi5O5w+BZb7EQ8IpkGa3vbwzAY=; b=OKCIc58+He5vQr9bwzMASDAIOVXd1NqMjHjCrMHtdkijZP8LmFA1W9YYYAZZepb7XM o8+fAmllOIBIB36Uye+qcdvRnce0pVuwozgJoIiQAdADWIqzbgeeJiHeAKvJNupk5bhj /5w7lStuE5UiNAPIvI3KPEmryWNCmMzoCdULkHCisQJN9Dybi0ceYsvzV1GA/ATOlbXJ afp4gGyOfO0Q4fcFGY0Pn/hFK+af0aIflO2wBltjBKOs8T28gdGW1ef2VA1jjPbTAzIe ikCordHaKqcrNzLsvd7vVgo/NVQvsK/qHxPqECs7Uw4p1gDnUk/n9rpEj9j1f58wg661 Ayqg== X-Gm-Message-State: AD7BkJIj9FmBOf7MnsBXw0kiwBgtoRCMj4Pyowh61Ra5A7c/A6k9m9qK3XZCQw6UD6ciyQ7QurENZhNM8lqNJ5+J7Fr6gzyfKEK2WJ7rxZ/zCrHgguliosbenX5tCyja6bTdhEo1iqpWIQ== X-Received: by 10.25.137.67 with SMTP id l64mr6457539lfd.158.1456828331123; Tue, 01 Mar 2016 02:32:11 -0800 (PST) Received: from localhost.localdomain ([91.198.246.10]) by smtp.gmail.com with ESMTPSA id i2sm4644857lfd.43.2016.03.01.02.32.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 01 Mar 2016 02:32:09 -0800 (PST) From: Michal Kazior To: ath10k@lists.infradead.org Cc: linux-wireless@vger.kernel.org, Michal Kazior Subject: [PATCH v2 03/11] ath10k: refactor tx pending management Date: Tue, 1 Mar 2016 11:32:48 +0100 Message-Id: <1456828376-2795-4-git-send-email-michal.kazior@tieto.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1456828376-2795-1-git-send-email-michal.kazior@tieto.com> References: <1453384006-31907-1-git-send-email-michal.kazior@tieto.com> <1456828376-2795-1-git-send-email-michal.kazior@tieto.com> X-DomainID: tieto.com Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Tx pending counter logic assumed that the sk_buff is already known and hence was performed in HTT functions themselves. However, for the sake of future wake_tx_queue() usage the driver must be able to tell whether it can submit more frames to firmware before it dequeues frame from ieee80211_txq (and thus long before HTT Tx functions are called) because once a frame is dequeued it cannot be requeud back to mac80211. This prepares the driver for future changes. Signed-off-by: Michal Kazior --- drivers/net/wireless/ath/ath10k/htt.h | 7 ++- drivers/net/wireless/ath/ath10k/htt_tx.c | 85 ++++++++------------------------ drivers/net/wireless/ath/ath10k/mac.c | 51 ++++++++++++++++--- drivers/net/wireless/ath/ath10k/txrx.c | 2 +- 4 files changed, 71 insertions(+), 74 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 13391ea4422d..cb6d4fd687da 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1753,7 +1753,12 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, u8 max_subfrms_amsdu); void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb); -void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc); +void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, + bool is_mgmt); +int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, + bool is_mgmt, + bool is_presp); + int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb); void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 95acb727c068..860661d3812f 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -22,9 +22,12 @@ #include "txrx.h" #include "debug.h" -void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc) +void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, + bool is_mgmt) { - if (limit_mgmt_desc) + lockdep_assert_held(&htt->tx_lock); + + if (is_mgmt) htt->num_pending_mgmt_tx--; htt->num_pending_tx--; @@ -32,43 +35,31 @@ void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc) ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); } -static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, - bool limit_mgmt_desc) -{ - spin_lock_bh(&htt->tx_lock); - __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); - spin_unlock_bh(&htt->tx_lock); -} - -static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, - bool limit_mgmt_desc, bool is_probe_resp) +int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, + bool is_mgmt, + bool is_presp) { struct ath10k *ar = htt->ar; - int ret = 0; - spin_lock_bh(&htt->tx_lock); + lockdep_assert_held(&htt->tx_lock); - if (htt->num_pending_tx >= htt->max_num_pending_tx) { - ret = -EBUSY; - goto exit; - } + if (htt->num_pending_tx >= htt->max_num_pending_tx) + return -EBUSY; - if (limit_mgmt_desc) { - if (is_probe_resp && (htt->num_pending_mgmt_tx > - ar->hw_params.max_probe_resp_desc_thres)) { - ret = -EBUSY; - goto exit; - } + if (is_mgmt && + is_presp && + ar->hw_params.max_probe_resp_desc_thres && + ar->hw_params.max_probe_resp_desc_thres < htt->num_pending_mgmt_tx) + return -EBUSY; + + if (is_mgmt) htt->num_pending_mgmt_tx++; - } htt->num_pending_tx++; if (htt->num_pending_tx == htt->max_num_pending_tx) ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); -exit: - spin_unlock_bh(&htt->tx_lock); - return ret; + return 0; } int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb) @@ -576,20 +567,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) int msdu_id = -1; int res; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; - bool limit_mgmt_desc = false; - bool is_probe_resp = false; - - if (ar->hw_params.max_probe_resp_desc_thres) { - limit_mgmt_desc = true; - - if (ieee80211_is_probe_resp(hdr->frame_control)) - is_probe_resp = true; - } - - res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp); - - if (res) - goto err; len += sizeof(cmd->hdr); len += sizeof(cmd->mgmt_tx); @@ -598,7 +575,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); spin_unlock_bh(&htt->tx_lock); if (res < 0) - goto err_tx_dec; + goto err; msdu_id = res; @@ -649,8 +626,6 @@ err_free_msdu_id: spin_lock_bh(&htt->tx_lock); ath10k_htt_tx_free_msdu_id(htt, msdu_id); spin_unlock_bh(&htt->tx_lock); -err_tx_dec: - ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); err: return res; } @@ -677,26 +652,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode, u32 frags_paddr = 0; u32 txbuf_paddr; struct htt_msdu_ext_desc *ext_desc = NULL; - bool limit_mgmt_desc = false; - bool is_probe_resp = false; - - if (unlikely(ieee80211_is_mgmt(hdr->frame_control)) && - ar->hw_params.max_probe_resp_desc_thres) { - limit_mgmt_desc = true; - - if (ieee80211_is_probe_resp(hdr->frame_control)) - is_probe_resp = true; - } - - res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp); - if (res) - goto err; spin_lock_bh(&htt->tx_lock); res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); spin_unlock_bh(&htt->tx_lock); if (res < 0) - goto err_tx_dec; + goto err; msdu_id = res; @@ -862,11 +823,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode, err_unmap_msdu: dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); err_free_msdu_id: - spin_lock_bh(&htt->tx_lock); ath10k_htt_tx_free_msdu_id(htt, msdu_id); - spin_unlock_bh(&htt->tx_lock); -err_tx_dec: - ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); err: return res; } diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 67a50a61afb4..140ad250ea69 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3358,13 +3358,11 @@ ath10k_mac_tx_h_get_txpath(struct ath10k *ar, static int ath10k_mac_tx_submit(struct ath10k *ar, enum ath10k_hw_txrx_mode txmode, + enum ath10k_mac_tx_path txpath, struct sk_buff *skb) { struct ath10k_htt *htt = &ar->htt; - enum ath10k_mac_tx_path txpath; - int ret; - - txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); + int ret = -EINVAL; switch (txpath) { case ATH10K_MAC_TX_HTT: @@ -3398,6 +3396,7 @@ static int ath10k_mac_tx(struct ath10k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, enum ath10k_hw_txrx_mode txmode, + enum ath10k_mac_tx_path txpath, struct sk_buff *skb) { struct ieee80211_hw *hw = ar->hw; @@ -3437,7 +3436,7 @@ static int ath10k_mac_tx(struct ath10k *ar, } } - ret = ath10k_mac_tx_submit(ar, txmode, skb); + ret = ath10k_mac_tx_submit(ar, txmode, txpath, skb); if (ret) { ath10k_warn(ar, "failed to submit frame: %d\n", ret); return ret; @@ -3465,6 +3464,7 @@ void ath10k_offchan_tx_work(struct work_struct *work) struct ath10k_peer *peer; struct ath10k_vif *arvif; enum ath10k_hw_txrx_mode txmode; + enum ath10k_mac_tx_path txpath; struct ieee80211_hdr *hdr; struct ieee80211_vif *vif; struct ieee80211_sta *sta; @@ -3533,8 +3533,9 @@ void ath10k_offchan_tx_work(struct work_struct *work) } txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); + txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); - ret = ath10k_mac_tx(ar, vif, sta, txmode, skb); + ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb); if (ret) { ath10k_warn(ar, "failed to transmit offchannel frame: %d\n", ret); @@ -3758,19 +3759,53 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct ath10k *ar = hw->priv; + struct ath10k_htt *htt = &ar->htt; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; struct ieee80211_sta *sta = control->sta; + struct ieee80211_hdr *hdr = (void *)skb->data; enum ath10k_hw_txrx_mode txmode; + enum ath10k_mac_tx_path txpath; + bool is_htt; + bool is_mgmt; + bool is_presp; int ret; ath10k_mac_tx_h_fill_cb(ar, vif, skb); txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); + txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); + is_htt = (txpath == ATH10K_MAC_TX_HTT || + txpath == ATH10K_MAC_TX_HTT_MGMT); - ret = ath10k_mac_tx(ar, vif, sta, txmode, skb); - if (ret) + if (is_htt) { + spin_lock_bh(&ar->htt.tx_lock); + + is_mgmt = ieee80211_is_mgmt(hdr->frame_control); + is_presp = ieee80211_is_probe_resp(hdr->frame_control); + + ret = ath10k_htt_tx_inc_pending(htt, is_mgmt, is_presp); + if (ret) { + ath10k_warn(ar, "failed to increase tx pending count: %d, dropping\n", + ret); + spin_unlock_bh(&ar->htt.tx_lock); + ieee80211_free_txskb(ar->hw, skb); + return; + } + + spin_unlock_bh(&ar->htt.tx_lock); + } + + ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb); + if (ret) { ath10k_warn(ar, "failed to transmit frame: %d\n", ret); + if (is_htt) { + spin_lock_bh(&ar->htt.tx_lock); + ath10k_htt_tx_dec_pending(htt, is_mgmt); + spin_unlock_bh(&ar->htt.tx_lock); + } + return; + } } /* Must not be called with conf_mutex held as workers can use that also. */ diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index fbfb608e48ab..118586ece20e 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -86,7 +86,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, limit_mgmt_desc = true; ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); - __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); + ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); if (htt->num_pending_tx == 0) wake_up(&htt->empty_tx_wq); spin_unlock_bh(&htt->tx_lock);