From patchwork Fri Jan 9 11:14:08 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Kazior X-Patchwork-Id: 5599011 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 E7EA2C058D for ; Fri, 9 Jan 2015 11:15:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DA06020480 for ; Fri, 9 Jan 2015 11:15:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A67F4204DF for ; Fri, 9 Jan 2015 11:15:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932651AbbAILPD (ORCPT ); Fri, 9 Jan 2015 06:15:03 -0500 Received: from mail-wi0-f171.google.com ([209.85.212.171]:43549 "EHLO mail-wi0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932616AbbAILOy (ORCPT ); Fri, 9 Jan 2015 06:14:54 -0500 Received: by mail-wi0-f171.google.com with SMTP id bs8so1555282wib.4 for ; Fri, 09 Jan 2015 03:14:53 -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=VuxGKcNIWBX2YtYHcbDBMRlbHJwxgwXRyMNSitFMHG4=; b=sJ2tCoYr4i0lNghA9HaI/+xiDFgCCf7lDQIG7cK1T5o97YtTbsR/UiicxdW5T4N1LM BO8erdZpdwkKh6KJ1BUMbFu590jc8VlGEHjJEdhLfHHx3oOqwdiYAULgt4GVy5Xp+aJv CsaCluNPSdTmprpV+sK/AUUcJM3ta9wA9lvtI= 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=VuxGKcNIWBX2YtYHcbDBMRlbHJwxgwXRyMNSitFMHG4=; b=Ws/eOekKusKH8aDKOEd9rQ1rHbnqcxW6OY9IwjBg2cZeAPpjS1glGEGWtATYYkcUL6 Bpar96xtb4/Xs5G8TVXoRQ1oA8goYem213dcC6rXFCTh4ibFr5vSeEiV9byd4H7cFzgc oUjNnQo/wnmOm4apa03Px5etHa5Yh7EtxfSmD3JDavrYBP9qhQrhwL3FW/EeM7TCBIaE W31yqPPpnHkYr4/QxJMWVgadx8xWJdtTa5IOW40rYJHOJ1i4ztOYdC6WuHkU9oBwgHno KhjMNUGYCIu4TxU765exX08gMvE7qMq71HpDWAdxPmkYRarJ1lq2+v1sCJTMV8TYyUT/ w1zA== X-Gm-Message-State: ALoCoQkPG+EyXK+buM4m2dzCpbNqqFE8rA2VTRAAq7Pf2CMJsSvyTPFd3AEvxtFSfAJWNWPYhyon+uV4Jcj1fEVpeYPemGqwC+iVkHoTMd9iiSlTWaXX6CgdgvgvNfA6nVFfL+iP0LCc X-Received: by 10.180.75.42 with SMTP id z10mr4016036wiv.70.1420802091496; Fri, 09 Jan 2015 03:14:51 -0800 (PST) Received: from localhost.localdomain ([91.198.246.8]) by mx.google.com with ESMTPSA id gb10sm9612608wjb.21.2015.01.09.03.14.50 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 09 Jan 2015 03:14:51 -0800 (PST) From: Michal Kazior To: ath10k@lists.infradead.org Cc: linux-wireless@vger.kernel.org, Michal Kazior Subject: [RFC 7/8] ath10k: implement tx pause wmi event Date: Fri, 9 Jan 2015 12:14:08 +0100 Message-Id: <1420802049-11962-8-git-send-email-michal.kazior@tieto.com> X-Mailer: git-send-email 1.8.5.3 In-Reply-To: <1420802049-11962-1-git-send-email-michal.kazior@tieto.com> References: <1420802049-11962-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,T_DKIM_INVALID,T_RP_MATCHES_RCVD,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 New wmi-tlv firmware can ask host to pause certain tx queues. This is used to improve multi-channel performance. Signed-off-by: Michal Kazior --- drivers/net/wireless/ath/ath10k/mac.c | 12 +++++ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 86 +++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi-tlv.h | 42 +++++++++++++++ 3 files changed, 140 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 9b6fab4..6e069a8 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3430,6 +3430,14 @@ err: return ret; } +static void ath10k_mac_vif_tx_unlock_all(struct ath10k_vif *arvif) +{ + int i; + + for (i = 0; i < BITS_PER_LONG; i++) + ath10k_mac_vif_tx_unlock(arvif, i); +} + static void ath10k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -3498,6 +3506,10 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, ath10k_warn(ar, "failed to recalc monitor: %d\n", ret); } + spin_lock_bh(&ar->htt.tx_lock); + ath10k_mac_vif_tx_unlock_all(arvif); + spin_unlock_bh(&ar->htt.tx_lock); + mutex_unlock(&ar->conf_mutex); } diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index ef55110..b1461ca 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -16,6 +16,7 @@ */ #include "core.h" #include "debug.h" +#include "mac.h" #include "hw.h" #include "wmi.h" #include "wmi-ops.h" @@ -62,6 +63,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = { = { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) }, [WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT] = { .min_len = sizeof(struct wmi_tlv_diag_data_ev) }, + [WMI_TLV_TAG_STRUCT_TX_PAUSE_EVENT] + = { .min_len = sizeof(struct wmi_tlv_tx_pause_ev) }, }; static int @@ -296,6 +299,86 @@ static int ath10k_wmi_tlv_event_diag(struct ath10k *ar, return 0; } +static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar, + struct sk_buff *skb) +{ + const void **tb; + const struct wmi_tlv_tx_pause_ev *ev; + int ret, vdev_id; + u32 pause_id, action, vdev_map, peer_id, tid_map; + struct ath10k_vif *arvif; + + tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); + if (IS_ERR(tb)) { + ret = PTR_ERR(tb); + ath10k_warn(ar, "failed to parse tlv: %d\n", ret); + return ret; + } + + ev = tb[WMI_TLV_TAG_STRUCT_TX_PAUSE_EVENT]; + if (!ev) { + kfree(tb); + return -EPROTO; + } + + pause_id = __le32_to_cpu(ev->pause_id); + action = __le32_to_cpu(ev->action); + vdev_map = __le32_to_cpu(ev->vdev_map); + peer_id = __le32_to_cpu(ev->peer_id); + tid_map = __le32_to_cpu(ev->tid_map); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi tlv tx pause pause_id %u action %u vdev_map 0x%08x peer_id %u tid_map 0x%08x\n", + pause_id, action, vdev_map, peer_id, tid_map); + + for (vdev_id = 0; vdev_map; vdev_id++) { + if (!(vdev_map & BIT(vdev_id))) + continue; + + vdev_map &= ~BIT(vdev_id); + + spin_lock_bh(&ar->htt.tx_lock); + spin_lock_bh(&ar->data_lock); + + arvif = ath10k_get_arvif(ar, vdev_id); + if (!arvif) { + ath10k_warn(ar, "failed to find arvif for vdev %i for tx pause event\n", + vdev_id); + spin_unlock_bh(&ar->data_lock); + spin_unlock_bh(&ar->htt.tx_lock); + continue; + } + + /* FIXME: Some pause_id aren't vdev orinted. Instead they are + * peer_id oriented (mostly for AP mode scenarios). + */ + if (pause_id == WMI_TLV_TX_PAUSE_ID_MCC || + pause_id == WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA || + pause_id == WMI_TLV_TX_PAUSE_ID_P2P_GO_PS || + pause_id == WMI_TLV_TX_PAUSE_ID_AP_PS || + pause_id == WMI_TLV_TX_PAUSE_ID_IBSS_PS) { + switch (action) { + case WMI_TLV_TX_PAUSE_ACTION_STOP: + ath10k_mac_vif_tx_lock(arvif, pause_id); + break; + case WMI_TLV_TX_PAUSE_ACTION_WAKE: + ath10k_mac_vif_tx_unlock(arvif, pause_id); + break; + default: + ath10k_warn(ar, "received unknown tx pause action %d on vdev %i, ignoring\n", + action, vdev_id); + break; + } + } + + spin_unlock_bh(&ar->data_lock); + spin_unlock_bh(&ar->htt.tx_lock); + } + + kfree(tb); + return 0; +} + /***********/ /* TLV ops */ /***********/ @@ -417,6 +500,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) case WMI_TLV_DIAG_EVENTID: ath10k_wmi_tlv_event_diag(ar, skb); break; + case WMI_TLV_TX_PAUSE_EVENTID: + ath10k_wmi_tlv_event_tx_pause(ar, skb); + break; default: ath10k_warn(ar, "Unknown eventid: %d\n", id); break; diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index c311b3c..9d61063 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -1432,6 +1432,48 @@ struct wmi_tlv_adaptive_qcs { __le32 enable; } __packed; +/** + * wmi_tlv_tx_pause_id - firmware tx queue pause reason types + * + * @WMI_TLV_TX_PAUSE_ID_MCC: used for by multi-channel firmware scheduler. + * Only vdev_map is valid. + * @WMI_TLV_TX_PAUSE_ID_AP_PEER_PS: peer in AP mode is asleep. + * Only peer_id is valid. + * @WMI_TLV_TX_PAUSE_ID_AP_PEER_UAPSD: Only peer_id and tid_map are valid. + * @WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA: Only vdev_map is valid. + * @WMI_TLV_TX_PAUSE_ID_P2P_GO_PS: Only vdev_map is valid. + * @WMI_TLV_TX_PAUSE_ID_STA_ADD_BA: Only peer_id and tid_map are valid. + * @WMI_TLV_TX_PAUSE_ID_AP_PS: When all peers are asleep in AP mode. Only + * vdev_map is valid. + * @WMI_TLV_TX_PAUSE_ID_IBSS_PS: When all peers are asleep in IBSS mode. Only + * vdev_map is valid. + * @WMI_TLV_TX_PAUSE_ID_HOST: Host itself requested tx pause. + */ +enum wmi_tlv_tx_pause_id { + WMI_TLV_TX_PAUSE_ID_MCC = 1, + WMI_TLV_TX_PAUSE_ID_AP_PEER_PS = 2, + WMI_TLV_TX_PAUSE_ID_AP_PEER_UAPSD = 3, + WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA = 4, + WMI_TLV_TX_PAUSE_ID_P2P_GO_PS = 5, + WMI_TLV_TX_PAUSE_ID_STA_ADD_BA = 6, + WMI_TLV_TX_PAUSE_ID_AP_PS = 7, + WMI_TLV_TX_PAUSE_ID_IBSS_PS = 8, + WMI_TLV_TX_PAUSE_ID_HOST = 21, +}; + +enum wmi_tlv_tx_pause_action { + WMI_TLV_TX_PAUSE_ACTION_STOP, + WMI_TLV_TX_PAUSE_ACTION_WAKE, +}; + +struct wmi_tlv_tx_pause_ev { + __le32 pause_id; + __le32 action; + __le32 vdev_map; + __le32 peer_id; + __le32 tid_map; +} __packed; + void ath10k_wmi_tlv_attach(struct ath10k *ar); #endif