From patchwork Fri Feb 6 12:02:52 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Kazior X-Patchwork-Id: 5790121 Return-Path: X-Original-To: patchwork-ath10k@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 0E12E9FA44 for ; Fri, 6 Feb 2015 12:04:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 91C6B201DD for ; Fri, 6 Feb 2015 12:04:24 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 84349200E6 for ; Fri, 6 Feb 2015 12:04:22 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YJhdz-0005ID-Fl; Fri, 06 Feb 2015 12:04:19 +0000 Received: from mail-wi0-x232.google.com ([2a00:1450:400c:c05::232]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YJhdw-0004yd-U4 for ath10k@lists.infradead.org; Fri, 06 Feb 2015 12:04:18 +0000 Received: by mail-wi0-f178.google.com with SMTP id bs8so1869088wib.5 for ; Fri, 06 Feb 2015 04:03:55 -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=5gcgyp8X4EAAiZHlXEBKLx0G7I5hnzFd9tJY6UewF14=; b=hQIiYOt+NMz6um6GVMuUCC1ILnsUDgn8u+Fk4lAgcA11Sdz0CCKPuDwdfTm8loBS6d 4q+Z02x2BJdj4t1EsoV6PPKTkkuRYEoi/rjBGvY706wgq+UKkCTutQZHeLBZu7daTwVX fxpUMM4erhcmbR+zRz4nuyOljZ3t3RqGlgzsI= 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=5gcgyp8X4EAAiZHlXEBKLx0G7I5hnzFd9tJY6UewF14=; b=ck+/ZVu3y0yfLj8drjlfeVLlh5G+m9EW2ZKWQGLUBWLTyu4zXcCy5x4CwrYOPcWsv7 qHeDlypXP9rwQ3dyqZi43MD+NE+rFwrkm+k58QOwB1dPDDttpb8axWGOTINvfNP5EjEg rgrzyg0y9Q7mXT3O6P0l2srNGNsMRKF+wu4smPBRlHjboAeHeAbUApr2Q1R83hTvClsM sO5sIJkKe83py257NSAKcx6hegGPqgQRcLHFJA8EF8uImXXL52SIx8xbCLzDdw7U2kYA 7JPcyzjdy5ibNbDyxOckVV5ITdDYdLGhN2q7c4lqk5/sTgxB0Phz/SLyFIN5NH6Wx/9+ C5ww== X-Gm-Message-State: ALoCoQmJkp+TCFGHIsYeyHUXmN33qHbiEuhAmvxTh/qwg34KVjlvcEsyi8be/DOJU84/fVlItn/U2AvGCiI38Ge2tQcIL3mqf3BIBxEMIkdhZirvtQJ2VC6nDqyjnAqfuIvrIDMAcHEYAzaHa5hRShVQCQ4LZs1XNlM2XlsvCOOs2LVsZEbT/3Y= X-Received: by 10.180.74.229 with SMTP id x5mr2685582wiv.1.1423224234983; Fri, 06 Feb 2015 04:03:54 -0800 (PST) Received: from bob.homerouter.cpe (apn-31-1-134-151.dynamic.gprs.plus.pl. [31.1.134.151]) by mx.google.com with ESMTPSA id kj8sm3070158wjc.29.2015.02.06.04.03.54 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 06 Feb 2015 04:03:54 -0800 (PST) From: Michal Kazior To: ath10k@lists.infradead.org Subject: [PATCH v3 5/7] ath10k: rework tx queue locking Date: Fri, 6 Feb 2015 13:02:52 +0100 Message-Id: <1423224174-24764-6-git-send-email-michal.kazior@tieto.com> X-Mailer: git-send-email 1.8.5.3 In-Reply-To: <1423224174-24764-1-git-send-email-michal.kazior@tieto.com> References: <1423224174-24764-1-git-send-email-michal.kazior@tieto.com> X-DomainID: tieto.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150206_040417_283644_32B04026 X-CRM114-Status: GOOD ( 15.04 ) X-Spam-Score: -0.8 (/) Cc: linux-wireless@vger.kernel.org, Michal Kazior X-BeenThere: ath10k@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "ath10k" Errors-To: ath10k-bounces+patchwork-ath10k=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable 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 queue locking was very simple until now. Multi-channel support will require a more flexible and fine grained control. This introduces a per-hw and per-vif (each with a bitmask of reasons) tx queue locking. Signed-off-by: Michal Kazior --- drivers/net/wireless/ath/ath10k/core.h | 8 +++++ drivers/net/wireless/ath/ath10k/htt_tx.c | 11 ++++-- drivers/net/wireless/ath/ath10k/mac.c | 22 ++++++++++-- drivers/net/wireless/ath/ath10k/mac.h | 57 ++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 6df0b56..08f0f06 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -290,6 +290,7 @@ struct ath10k_vif { enum ath10k_beacon_state beacon_state; void *beacon_buf; dma_addr_t beacon_paddr; + unsigned long tx_paused; /* arbitrary values defined by target */ struct ath10k *ar; struct ieee80211_vif *vif; @@ -480,6 +481,11 @@ static inline const char *ath10k_scan_state_str(enum ath10k_scan_state state) return "unknown"; } +enum ath10k_tx_pause_reason { + ATH10K_TX_PAUSE_Q_FULL, + ATH10K_TX_PAUSE_MAX, +}; + struct ath10k { struct ath_common ath_common; struct ieee80211_hw *hw; @@ -638,6 +644,8 @@ struct ath10k { struct dfs_pattern_detector *dfs_detector; + unsigned long tx_paused; /* see ATH10K_TX_PAUSE_ */ + #ifdef CONFIG_ATH10K_DEBUGFS struct ath10k_debug debug; #endif diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index cbd2bc9..9b34e3f 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -24,9 +24,14 @@ void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) { + struct ath10k *ar = htt->ar; + htt->num_pending_tx--; - if (htt->num_pending_tx == htt->max_num_pending_tx - 1) - ieee80211_wake_queues(htt->ar->hw); + if (htt->num_pending_tx == htt->max_num_pending_tx - 1) { + spin_lock_bh(&ar->data_lock); + ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); + spin_unlock_bh(&ar->data_lock); + } } static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) @@ -49,7 +54,7 @@ static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) htt->num_pending_tx++; if (htt->num_pending_tx == htt->max_num_pending_tx) - ieee80211_stop_queues(htt->ar->hw); + ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); exit: spin_unlock_bh(&htt->tx_lock); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 1d7e0ae..056f94c 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -2821,6 +2821,7 @@ void ath10k_halt(struct ath10k *ar) ath10k_monitor_stop(ar); ar->monitor_started = false; + ar->tx_paused = 0; ath10k_scan_finish(ar); ath10k_peer_cleanup_all(ar); @@ -3217,6 +3218,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, int ret = 0; u32 value; int bit; + int i; u32 vdev_param; vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD; @@ -3271,6 +3273,15 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, break; } + /* Using vdev_id as queue number will make it very easy to do per-vif + * tx queue locking. This shouldn't wrap due to interface combinations + * but do a modulo for correctness sake and prevent using offchannel tx + * queues for regular vif tx. + */ + vif->cab_queue = arvif->vdev_id % (IEEE80211_MAX_QUEUES - 1); + for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++) + vif->hw_queue[i] = arvif->vdev_id % (IEEE80211_MAX_QUEUES - 1); + /* Some firmware revisions don't wait for beacon tx completion before * sending another SWBA event. This could lead to hardware using old * (freed) beacon data in some cases, e.g. tx credit starvation @@ -5775,7 +5786,8 @@ int ath10k_mac_register(struct ath10k *ar) IEEE80211_HW_AP_LINK_PS | IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_SW_CRYPTO_CONTROL | - IEEE80211_HW_WANT_MONITOR_VIF; + IEEE80211_HW_WANT_MONITOR_VIF | + IEEE80211_HW_QUEUE_CONTROL; ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS; @@ -5820,7 +5832,13 @@ int ath10k_mac_register(struct ath10k *ar) * on LL hardware queues are managed entirely by the FW * so we only advertise to mac we can do the queues thing */ - ar->hw->queues = 4; + ar->hw->queues = IEEE80211_MAX_QUEUES; + + /* vdev_ids are used as hw queue numbers. Make sure offchan tx queue is + * something that vdev_ids can't reach so that we don't stop the queue + * accidentally. + */ + ar->hw->offchannel_tx_hw_queue = IEEE80211_MAX_QUEUES - 1; switch (ar->wmi.op_version) { case ATH10K_FW_WMI_OP_VERSION_MAIN: diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 212689f..b11f1d9 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h @@ -80,4 +80,61 @@ static inline void ath10k_tx_h_seq_no(struct ieee80211_vif *vif, } } +static inline void ath10k_mac_tx_lock(struct ath10k *ar, int reason) +{ + lockdep_assert_held(&ar->htt.tx_lock); + + WARN_ON(reason >= ATH10K_TX_PAUSE_MAX); + ar->tx_paused |= BIT(reason); + ieee80211_stop_queues(ar->hw); +} + +static inline void ath10k_mac_tx_unlock(struct ath10k *ar, int reason) +{ + struct ath10k_vif *arvif; + + lockdep_assert_held(&ar->htt.tx_lock); + lockdep_assert_held(&ar->data_lock); + + WARN_ON(reason >= ATH10K_TX_PAUSE_MAX); + ar->tx_paused &= ~BIT(reason); + + if (ar->tx_paused) + return; + + list_for_each_entry(arvif, &ar->arvifs, list) + if (!arvif->tx_paused) + ieee80211_wake_queue(ar->hw, arvif->vdev_id); +} + +static inline void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason) +{ + struct ath10k *ar = arvif->ar; + + lockdep_assert_held(&ar->htt.tx_lock); + + WARN_ON(reason >= BITS_PER_LONG); + arvif->tx_paused |= BIT(reason); + ieee80211_stop_queue(ar->hw, arvif->vdev_id); +} + +static inline void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, + int reason) +{ + struct ath10k *ar = arvif->ar; + + lockdep_assert_held(&ar->htt.tx_lock); + + WARN_ON(reason >= BITS_PER_LONG); + arvif->tx_paused &= ~BIT(reason); + + if (ar->tx_paused) + return; + + if (arvif->tx_paused) + return; + + ieee80211_wake_queue(ar->hw, arvif->vdev_id); +} + #endif /* _MAC_H_ */