From patchwork Wed Sep 25 09:38:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Markowski X-Patchwork-Id: 2941121 Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 1FC939F476 for ; Wed, 25 Sep 2013 09:38:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 45FFD20417 for ; Wed, 25 Sep 2013 09:38:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 011F220580 for ; Wed, 25 Sep 2013 09:38:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754880Ab3IYJie (ORCPT ); Wed, 25 Sep 2013 05:38:34 -0400 Received: from ebb06.tieto.com ([131.207.168.38]:61761 "EHLO ebb06.tieto.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754561Ab3IYJib (ORCPT ); Wed, 25 Sep 2013 05:38:31 -0400 X-AuditID: 83cfa826-b7f408e000003a47-1a-5242af1293a8 Received: from FIVLA-EXHUB02.eu.tieto.com ( [131.207.136.42]) by ebb06.tieto.com (SMTP Mailer) with SMTP id 4F.82.14919.31FA2425; Wed, 25 Sep 2013 12:38:27 +0300 (EEST) Received: from uw000975.eu.tieto.com (10.28.19.100) by inbound.tieto.com (131.207.136.49) with Microsoft SMTP Server id 8.3.298.1; Wed, 25 Sep 2013 12:38:26 +0300 From: Bartosz Markowski To: CC: , Bartosz Markowski Subject: [PATCH 08/13] ath10k: bring back the WMI path for mgmt frames Date: Wed, 25 Sep 2013 11:38:06 +0200 Message-ID: <1380101891-18312-9-git-send-email-bartosz.markowski@tieto.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: <1380101891-18312-1-git-send-email-bartosz.markowski@tieto.com> References: <1380101891-18312-1-git-send-email-bartosz.markowski@tieto.com> MIME-Version: 1.0 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrJIsWRmVeSWpSXmKPExsXSfL5DS1d4vVOQwceDEhaPLh1jtngy+TuL xZsVd9gdmD0+z7zL5rF5Sb3H501yAcxRXDYpqTmZZalF+nYJXBnfOpcxFhywqNh58hlLA2OD fhcjJ4eEgInEmhX/WSBsMYkL99azdTFycQgJrGKUuLr7OyuEs4xR4sH9Q8wgVWwCphL3N6xg BbFFBBQkfk36yAZiMwuES7za+gtskrCAm8Su2c/YQWwWAVWJuW1nGLsYOTh4BbwlLs4Rh1gm L/H0fh9YK6eAj8TRfa/ByoWASpqmXwcbzysgKHFy5hMWiPESEgdfvGCGqNGQmLPzJcsERoFZ SMpmISlbwMi0ipE/NSnJwEyvJDO1JF8vOT93EyM4BFeo7WB89kDqEKMAB6MSD++LhY5BQqyJ ZcWVuYcYJTmYlER576x1ChLiS8pPqcxILM6ILyrNSS0+xCjBwawkwhu+GCjHm5JYWZValA+T kuZgURLn3dABNEkgPbEkNTs1tSC1CCYrw8GhJMG7GmSoYFFqempFWmZOCUKaiYMTZDgP0PAP IDW8xQWJucWZ6RD5U4yKUuK8m0ASAiCJjNI8uF5YinjFKA70ijDvSZAqHmB6get+BTSYCWiw QwfY4JJEhJRUA2OPF2c7s8XjVouLGgHz/t5IiLLs+arHdWNjYvOOoBvzLQyKL545E263V+2V lDS7XMYOt2vGh4v55B5H7PiQlhB7PdrbdMXsexHB2k9zrZNvuDaVztz//XiBtPX0yknNaeFK CUW3ND4Zsh4zbOK79nj9U5VDoq+Xbkr/9Xpn4C1jy07Na0cPr1RiKc5INNRiLipOBAD56f1e 7AIAAA== Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-8.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, 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 This is still used by the 10.X firmware. Signed-off-by: Bartosz Markowski --- drivers/net/wireless/ath/ath10k/core.h | 5 ++- drivers/net/wireless/ath/ath10k/htt_tx.c | 4 +-- drivers/net/wireless/ath/ath10k/mac.c | 27 ++++++++++------ drivers/net/wireless/ath/ath10k/wmi.c | 49 ++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 1 + 5 files changed, 73 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 0c9e6f3..377560d 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -49,9 +49,9 @@ struct ath10k_skb_cb { dma_addr_t paddr; bool is_mapped; bool is_aborted; + u8 vdev_id; struct { - u8 vdev_id; u8 tid; bool is_offchan; @@ -284,6 +284,9 @@ enum ath10k_fw_features { /* firmware from 10X branch */ ATH10K_FW_FEATURE_10X = 1, + /* firmware support tx frame management over WMI, otherwise it's HTT */ + ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX = 2, + /* keep last */ ATH10K_FW_FEATURE_COUNT, }; diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 3b93c6a..d9335e9 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -308,7 +308,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) struct sk_buff *txdesc = NULL; struct htt_cmd *cmd; struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); - u8 vdev_id = skb_cb->htt.vdev_id; + u8 vdev_id = skb_cb->vdev_id; int len = 0; int msdu_id = -1; int res; @@ -384,7 +384,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); struct sk_buff *txdesc = NULL; bool use_frags; - u8 vdev_id = ATH10K_SKB_CB(msdu)->htt.vdev_id; + u8 vdev_id = ATH10K_SKB_CB(msdu)->vdev_id; u8 tid; int prefetch_len, desc_len; int msdu_id = -1; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 99a9bad..18fae5e 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1489,7 +1489,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb) static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - int ret; + int ret = 0; if (ar->htt.target_version_major >= 3) { /* Since HTT 3.0 there is no separate mgmt tx command */ @@ -1497,16 +1497,23 @@ static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb) goto exit; } - if (ieee80211_is_mgmt(hdr->frame_control)) - ret = ath10k_htt_mgmt_tx(&ar->htt, skb); - else if (ieee80211_is_nullfunc(hdr->frame_control)) + if (ieee80211_is_mgmt(hdr->frame_control)) { + if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, + ar->fw_features)) + ret = ath10k_wmi_mgmt_tx(ar, skb); + else + ret = ath10k_htt_mgmt_tx(&ar->htt, skb); + } else if (!test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, + ar->fw_features) && + ieee80211_is_nullfunc(hdr->frame_control)) { /* FW does not report tx status properly for NullFunc frames * unless they are sent through mgmt tx path. mac80211 sends - * those frames when it detects link/beacon loss and depends on - * the tx status to be correct. */ + * those frames when it detects link/beacon loss and depends + * on the tx status to be correct. */ ret = ath10k_htt_mgmt_tx(&ar->htt, skb); - else + } else { ret = ath10k_htt_tx(&ar->htt, skb); + } exit: if (ret) { @@ -1557,7 +1564,7 @@ void ath10k_offchan_tx_work(struct work_struct *work) hdr = (struct ieee80211_hdr *)skb->data; peer_addr = ieee80211_get_DA(hdr); - vdev_id = ATH10K_SKB_CB(skb)->htt.vdev_id; + vdev_id = ATH10K_SKB_CB(skb)->vdev_id; spin_lock_bh(&ar->data_lock); peer = ath10k_peer_find(ar, vdev_id, peer_addr); @@ -1757,14 +1764,14 @@ static void ath10k_tx(struct ieee80211_hw *hw, ath10k_tx_h_seq_no(skb); } + ATH10K_SKB_CB(skb)->vdev_id = vdev_id; ATH10K_SKB_CB(skb)->htt.is_offchan = false; - ATH10K_SKB_CB(skb)->htt.vdev_id = vdev_id; ATH10K_SKB_CB(skb)->htt.tid = tid; if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) { spin_lock_bh(&ar->data_lock); ATH10K_SKB_CB(skb)->htt.is_offchan = true; - ATH10K_SKB_CB(skb)->htt.vdev_id = ar->scan.vdev_id; + ATH10K_SKB_CB(skb)->vdev_id = ar->scan.vdev_id; spin_unlock_bh(&ar->data_lock); ath10k_dbg(ATH10K_DBG_MAC, "queued offchannel skb %p\n", skb); diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 3b1ae88..4992ad1 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -418,6 +418,55 @@ static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, return ret; } +int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb) +{ + int ret = 0; + struct wmi_mgmt_tx_cmd *cmd; + struct ieee80211_hdr *hdr; + struct sk_buff *wmi_skb; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + int len; + u16 fc; + + hdr = (struct ieee80211_hdr *)skb->data; + fc = le16_to_cpu(hdr->frame_control); + + if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control))) + return -EINVAL; + + len = sizeof(cmd->hdr) + skb->len; + len = round_up(len, 4); + + wmi_skb = ath10k_wmi_alloc_skb(len); + if (!wmi_skb) + return -ENOMEM; + + cmd = (struct wmi_mgmt_tx_cmd *)wmi_skb->data; + + cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(skb)->vdev_id); + cmd->hdr.tx_rate = 0; + cmd->hdr.tx_power = 0; + cmd->hdr.buf_len = __cpu_to_le32((u32)(skb->len)); + + memcpy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr), ETH_ALEN); + memcpy(cmd->buf, skb->data, skb->len); + + ath10k_dbg(ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n", + wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE, + fc & IEEE80211_FCTL_STYPE); + + /* Send the management frame buffer to the target */ + ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->wmi_mgmt_tx_cmdid); + if (ret) + return ret; + + /* TODO: report tx status to mac80211 - temporary just ACK */ + info->flags |= IEEE80211_TX_STAT_ACK; + ieee80211_tx_status_irqsafe(ar->hw, skb); + + return ret; +} + static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) { struct wmi_scan_event *event = (struct wmi_scan_event *)skb->data; diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 3825937..8c67fb4 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -3483,5 +3483,6 @@ int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id); int ath10k_wmi_force_fw_hang(struct ath10k *ar, enum wmi_force_fw_hang_type type, u32 delay_ms); +int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb); #endif /* _WMI_H_ */