From patchwork Mon Nov 18 20:29:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Crispin X-Patchwork-Id: 11250259 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 24710109A for ; Mon, 18 Nov 2019 20:29:38 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id EC14F22302 for ; Mon, 18 Nov 2019 20:29:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Fky0bDR9" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EC14F22302 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=phrozen.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=ath11k-bounces+patchwork-ath11k=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:To :From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=XegiQogSxh/FweNv9q4hFnC7DgIrd8NCRigUzsOtcVo=; b=Fky0bDR9Q+WYE6 rj8th8olTWQ10uqWJAaH/LZYT9mgNj6Y5amLCp76ZtCp7WNJUN0lqi6o7Wc3u592Pki1JBYW7nip0 V8MfLlr15vTm04M4gnlhTIroWjXGDRxnPrXoIERcn8bUMus63NYG0Lmpnbbwz4feYAP2yjQvbGrcY rWTsKMjlbyy2Z35VbAibWnLAO3oqBjFgFu0nLm0QrtCAEz/EjhIAUOmor2JpWX6zD0POrFH3o5KUR Z4HQ07GLIWiMvCYOTkEdfmm+WA4kwd5vMlFmE5AYb9+7LqMpzK1YdJLAkm682U6+yZy/rH/b3+khu wPcN+cSVlesfBCW8w2xw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1iWneR-0001Sb-C2; Mon, 18 Nov 2019 20:29:35 +0000 Received: from nbd.name ([2a01:4f8:221:3d45::2]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1iWneN-0001Ro-RA for ath11k@lists.infradead.org; Mon, 18 Nov 2019 20:29:33 +0000 Received: from p5dcfbb96.dip0.t-ipconnect.de ([93.207.187.150] helo=bertha.datto.lan) by ds12 with esmtpa (Exim 4.89) (envelope-from ) id 1iWneL-0000o7-L3; Mon, 18 Nov 2019 21:29:29 +0100 From: John Crispin To: Kalle Valo Subject: [PATCH V2 1/2] ath11k: add WMI calls to manually add/del/pause/resume TWT dialogs Date: Mon, 18 Nov 2019 21:29:23 +0100 Message-Id: <20191118202924.24427-1-john@phrozen.org> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191118_122932_045756_746F8892 X-CRM114-Status: GOOD ( 12.40 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-BeenThere: ath11k@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: ath11k@lists.infradead.org, John Crispin Sender: "ath11k" Errors-To: ath11k-bounces+patchwork-ath11k=patchwork.kernel.org@lists.infradead.org These calls are used for debugging and will be required for WFA certification tests. Signed-off-by: John Crispin --- patches depend on https://patchwork.kernel.org/patch/11250245/ drivers/net/wireless/ath/ath11k/wmi.c | 194 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/wmi.h | 114 +++++++++++++++ 2 files changed, 308 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index b16bfb50d73e..dba7bfd225c9 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -97,6 +97,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = { = { .min_len = sizeof(struct wmi_stats_event) }, [WMI_TAG_PDEV_CTL_FAILSAFE_CHECK_EVENT] = { .min_len = sizeof(struct wmi_pdev_ctl_failsafe_chk_event) }, + [WMI_TAG_TWT_ADD_DIALOG_COMPLETE_EVENT] + = { .min_len = sizeof(struct wmi_twt_add_dialog_event) }, }; #define PRIMAP(_hw_mode_) \ @@ -2580,6 +2582,161 @@ ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id) return ret; } +int +ath11k_wmi_send_twt_add_dialog_cmd(struct ath11k *ar, + struct wmi_twt_add_dialog_params *params) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_sc->sc; + struct wmi_twt_add_dialog_params_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len); + if (!skb) + return -ENOMEM; + + cmd = (void *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_TWT_ADD_DIALOG_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + + cmd->vdev_id = params->vdev_id; + ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr); + cmd->dialog_id = params->dialog_id; + cmd->wake_intvl_us = params->wake_intvl_us; + cmd->wake_intvl_mantis = params->wake_intvl_mantis; + cmd->wake_dura_us = params->wake_dura_us; + cmd->sp_offset_us = params->sp_offset_us; + cmd->flags = params->twt_cmd; + if (params->flag_bcast) + cmd->flags |= WMI_TWT_ADD_DIALOG_FLAG_BCAST; + if (params->flag_trigger) + cmd->flags |= WMI_TWT_ADD_DIALOG_FLAG_TRIGGER; + if (params->flag_flow_type) + cmd->flags |= WMI_TWT_ADD_DIALOG_FLAG_FLOW_TYPE; + if (params->flag_protection) + cmd->flags |= WMI_TWT_ADD_DIALOG_FLAG_PROTECTION; + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_TWT_ADD_DIALOG_CMDID); + if (ret) { + ath11k_warn(ab, "Failed to send WMI_TWT_ADD_DIALOG_CMDID"); + dev_kfree_skb(skb); + } + return ret; +} + +int +ath11k_wmi_send_twt_del_dialog_cmd(struct ath11k *ar, + struct wmi_twt_del_dialog_params *params) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_sc->sc; + struct wmi_twt_del_dialog_params_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len); + if (!skb) + return -ENOMEM; + + cmd = (void *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_TWT_DEL_DIALOG_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + + cmd->vdev_id = params->vdev_id; + ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr); + cmd->dialog_id = params->dialog_id; + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_TWT_DEL_DIALOG_CMDID); + if (ret) { + ath11k_warn(ab, "Failed to send WMI_TWT_DEL_DIALOG_CMDID"); + dev_kfree_skb(skb); + } + return ret; +} + +int +ath11k_wmi_send_twt_pause_dialog_cmd(struct ath11k *ar, + struct wmi_twt_pause_dialog_params *params) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_sc->sc; + struct wmi_twt_pause_dialog_params_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len); + if (!skb) + return -ENOMEM; + + cmd = (void *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_TWT_PAUSE_DIALOG_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + + cmd->vdev_id = params->vdev_id; + ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr); + cmd->dialog_id = params->dialog_id; + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_TWT_PAUSE_DIALOG_CMDID); + if (ret) { + ath11k_warn(ab, "Failed to send WMI_TWT_PAUSE_DIALOG_CMDID"); + dev_kfree_skb(skb); + } + return ret; +} + +int +ath11k_wmi_send_twt_resume_dialog_cmd(struct ath11k *ar, + struct wmi_twt_resume_dialog_params *params) +{ + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ath11k_base *ab = wmi->wmi_sc->sc; + struct wmi_twt_resume_dialog_params_cmd *cmd; + struct sk_buff *skb; + int ret, len; + + len = sizeof(*cmd); + + skb = ath11k_wmi_alloc_skb(wmi->wmi_sc, len); + if (!skb) + return -ENOMEM; + + cmd = (void *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_TWT_RESUME_DIALOG_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + + cmd->vdev_id = params->vdev_id; + ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr); + cmd->dialog_id = params->dialog_id; + cmd->sp_offset_us = params->sp_offset_us; + cmd->next_twt_size = params->next_twt_size; + printk("%s:%s[%d]%x %x %x %x %x\n", __FILE__, __func__, __LINE__, + cmd->peer_macaddr.word0, + cmd->peer_macaddr.word1, + cmd->dialog_id, params->sp_offset_us, params->next_twt_size); + + ret = ath11k_wmi_cmd_send(wmi, skb, + WMI_TWT_RESUME_DIALOG_CMDID); + if (ret) { + ath11k_warn(ab, "Failed to send WMI_TWT_RESUME_DIALOG_CMDID"); + dev_kfree_skb(skb); + } + return ret; +} + int ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id, struct ieee80211_he_obss_pd *he_obss_pd) @@ -5511,6 +5668,37 @@ ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff kfree(tb); } +static void ath11k_wmi_twt_add_dialog_event(struct ath11k_base *ab, struct sk_buff *skb) +{ + const char *status[] = { + "OK", "TWT_NOT_ENABLED", "USED_DIALOG_ID", "INVALID_PARAM", + "NOT_READY", "NO_RESOURCE", "NO_ACK", "NO_RESPONSE", + "DENIED", "UNKNOWN_ERROR" + }; + const void **tb; + const struct wmi_twt_add_dialog_event *ev; + int ret; + + tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); + if (IS_ERR(tb)) { + ret = PTR_ERR(tb); + ath11k_warn(ab, "failed to parse tlv: %d\n", ret); + return; + } + + ev = tb[WMI_TAG_TWT_ADD_DIALOG_COMPLETE_EVENT]; + if (!ev) { + ath11k_warn(ab, "failed to fetch twt add dialog ev"); + goto exit; + } + + ath11k_info(ab, "TWT Add Dialog Event - Status: %s, DialogId: %d, VdevId: %d\n", + status[ev->status], ev->vdev_id, ev->dialog_id); + +exit: + kfree(tb); +} + static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; @@ -5588,12 +5776,18 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) case WMI_PDEV_CSA_SWITCH_COUNT_STATUS_EVENTID: ath11k_wmi_pdev_csa_switch_count_status_event(ab, skb); break; + case WMI_TWT_ADD_DIALOG_EVENTID: + ath11k_wmi_twt_add_dialog_event(ab, skb); + break; /* add Unsupported events here */ case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID: case WMI_VDEV_DELETE_RESP_EVENTID: case WMI_PEER_OPER_MODE_CHANGE_EVENTID: case WMI_TWT_ENABLE_EVENTID: case WMI_TWT_DISABLE_EVENTID: + case WMI_TWT_DEL_DIALOG_EVENTID: + case WMI_TWT_PAUSE_DIALOG_EVENTID: + case WMI_TWT_RESUME_DIALOG_EVENTID: ath11k_dbg(ab, ATH11K_DBG_WMI, "ignoring unsupported event 0x%x\n", id); break; diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index ab983aac604b..b01fdc842519 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -4569,6 +4569,112 @@ struct wmi_twt_disable_params_cmd { u32 pdev_id; }; +enum WMI_HOST_TWT_COMMAND { + WMI_HOST_TWT_COMMAND_REQUEST_TWT = 0, + WMI_HOST_TWT_COMMAND_SUGGEST_TWT, + WMI_HOST_TWT_COMMAND_DEMAND_TWT, + WMI_HOST_TWT_COMMAND_TWT_GROUPING, + WMI_HOST_TWT_COMMAND_ACCEPT_TWT, + WMI_HOST_TWT_COMMAND_ALTERNATE_TWT, + WMI_HOST_TWT_COMMAND_DICTATE_TWT, + WMI_HOST_TWT_COMMAND_REJECT_TWT, +}; + +#define WMI_TWT_ADD_DIALOG_FLAG_BCAST BIT(8) +#define WMI_TWT_ADD_DIALOG_FLAG_TRIGGER BIT(9) +#define WMI_TWT_ADD_DIALOG_FLAG_FLOW_TYPE BIT(10) +#define WMI_TWT_ADD_DIALOG_FLAG_PROTECTION BIT(11) + +struct wmi_twt_add_dialog_params_cmd { + u32 tlv_header; + u32 vdev_id; + struct wmi_mac_addr peer_macaddr; + u32 dialog_id; + u32 wake_intvl_us; + u32 wake_intvl_mantis; + u32 wake_dura_us; + u32 sp_offset_us; + u32 flags; +}; + +struct wmi_twt_add_dialog_params { + u32 vdev_id; + u8 peer_macaddr[ETH_ALEN]; + u32 dialog_id; + u32 wake_intvl_us; + u32 wake_intvl_mantis; + u32 wake_dura_us; + u32 sp_offset_us; + u8 twt_cmd; + u8 flag_bcast; + u8 flag_trigger; + u8 flag_flow_type; + u8 flag_protection; +}; + +enum wmi_twt_add_dialog_status { + WMI_ADD_TWT_STATUS_OK, /* adding TWT dialog successfully completed */ + WMI_ADD_TWT_STATUS_TWT_NOT_ENABLED, /* TWT not enabled */ + WMI_ADD_TWT_STATUS_USED_DIALOG_ID, /* TWT dialog ID is already used */ + WMI_ADD_TWT_STATUS_INVALID_PARAM, /* invalid parameters */ + WMI_ADD_TWT_STATUS_NOT_READY, /* FW not ready */ + WMI_ADD_TWT_STATUS_NO_RESOURCE, /* FW resource exhausted */ + WMI_ADD_TWT_STATUS_NO_ACK, /* peer AP/STA did not ACK the request/response frame */ + WMI_ADD_TWT_STATUS_NO_RESPONSE, /* peer AP did not send the response frame */ + WMI_ADD_TWT_STATUS_DENIED, /* AP did not accept the request */ + WMI_ADD_TWT_STATUS_UNKNOWN_ERROR, /* adding TWT dialog failed with an unknown reason */ +}; + +struct wmi_twt_add_dialog_event { + u32 vdev_id; + struct wmi_mac_addr peer_macaddr; + u32 dialog_id; + u32 status; +}; + +struct wmi_twt_del_dialog_params { + u32 vdev_id; + u8 peer_macaddr[ETH_ALEN]; + u32 dialog_id; +}; + +struct wmi_twt_del_dialog_params_cmd { + u32 tlv_header; + u32 vdev_id; + struct wmi_mac_addr peer_macaddr; + u32 dialog_id; +}; + +struct wmi_twt_pause_dialog_params { + u32 vdev_id; + u8 peer_macaddr[ETH_ALEN]; + u32 dialog_id; +}; + +struct wmi_twt_pause_dialog_params_cmd { + u32 tlv_header; + u32 vdev_id; + struct wmi_mac_addr peer_macaddr; + u32 dialog_id; +}; + +struct wmi_twt_resume_dialog_params { + u32 vdev_id; + u8 peer_macaddr[ETH_ALEN]; + u32 dialog_id; + u32 sp_offset_us; + u32 next_twt_size; +}; + +struct wmi_twt_resume_dialog_params_cmd { + u32 tlv_header; + u32 vdev_id; + struct wmi_mac_addr peer_macaddr; + u32 dialog_id; + u32 sp_offset_us; + u32 next_twt_size; +}; + struct wmi_obss_spatial_reuse_params_cmd { u32 tlv_header; u32 pdev_id; @@ -4766,6 +4872,14 @@ void ath11k_wmi_fw_stats_fill(struct ath11k *ar, int ath11k_wmi_simulate_radar(struct ath11k *ar); int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id); int ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id); +int ath11k_wmi_send_twt_add_dialog_cmd(struct ath11k *ar, + struct wmi_twt_add_dialog_params *params); +int ath11k_wmi_send_twt_del_dialog_cmd(struct ath11k *ar, + struct wmi_twt_del_dialog_params *params); +int ath11k_wmi_send_twt_pause_dialog_cmd(struct ath11k *ar, + struct wmi_twt_pause_dialog_params *params); +int ath11k_wmi_send_twt_resume_dialog_cmd(struct ath11k *ar, + struct wmi_twt_resume_dialog_params *params); int ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id, struct ieee80211_he_obss_pd *he_obss_pd); #endif