Skip to content

Commit

Permalink
ath10k: wmi: add management tx by reference support over wmi
Browse files Browse the repository at this point in the history
HL1.0 firmware branch, used in wcn3990, transmits management
frames by reference over WMI.

Add support for management tx by reference over WMI.

Signed-off-by: Rakesh Pillai <pillair@qti.qualcomm.com>
Signed-off-by: Govind Singh <govinds@qti.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
  • Loading branch information
Rakesh Pillai authored and Kalle Valo committed Dec 14, 2017
1 parent 229329f commit 1807da4
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 1 deletion.
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath10k/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR] = "skip-null-func-war",
[ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST] = "allows-mesh-bcast",
[ATH10K_FW_FEATURE_NO_PS] = "no-ps",
[ATH10K_FW_FEATURE_MGMT_TX_BY_REF] = "mgmt-tx-by-reference",
};

static unsigned int ath10k_core_get_fw_feature_str(char *buf,
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/wireless/ath/ath10k/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,9 @@ enum ath10k_fw_features {
/* Firmware does not support power save in station mode. */
ATH10K_FW_FEATURE_NO_PS = 17,

/* Firmware allows management tx by reference instead of by value. */
ATH10K_FW_FEATURE_MGMT_TX_BY_REF = 18,

/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
Expand Down
9 changes: 8 additions & 1 deletion drivers/net/wireless/ath/ath10k/wmi-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
struct sk_buff *skb;
int ret;
u32 mgmt_tx_cmdid;

if (!ar->wmi.ops->gen_mgmt_tx)
return -EOPNOTSUPP;
Expand All @@ -385,7 +386,13 @@ ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
if (IS_ERR(skb))
return PTR_ERR(skb);

ret = ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->mgmt_tx_cmdid);
if (test_bit(ATH10K_FW_FEATURE_MGMT_TX_BY_REF,
ar->running_fw->fw_file.fw_features))
mgmt_tx_cmdid = ar->wmi.cmd->mgmt_tx_send_cmdid;
else
mgmt_tx_cmdid = ar->wmi.cmd->mgmt_tx_cmdid;

ret = ath10k_wmi_cmd_send(ar, skb, mgmt_tx_cmdid);
if (ret)
return ret;

Expand Down
78 changes: 78 additions & 0 deletions drivers/net/wireless/ath/ath10k/wmi-tlv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2482,6 +2482,82 @@ ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
return skb;
}

static struct sk_buff *
ath10k_wmi_tlv_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
{
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
struct wmi_tlv_mgmt_tx_cmd *cmd;
struct wmi_tlv *tlv;
struct ieee80211_hdr *hdr;
struct sk_buff *skb;
void *ptr;
int len;
u32 buf_len = msdu->len;
u16 fc;
struct ath10k_vif *arvif;
dma_addr_t mgmt_frame_dma;
u32 vdev_id;

if (!cb->vif)
return ERR_PTR(-EINVAL);

hdr = (struct ieee80211_hdr *)msdu->data;
fc = le16_to_cpu(hdr->frame_control);
arvif = (void *)cb->vif->drv_priv;
vdev_id = arvif->vdev_id;

if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
return ERR_PTR(-EINVAL);

len = sizeof(*cmd) + 2 * sizeof(*tlv);

if ((ieee80211_is_action(hdr->frame_control) ||
ieee80211_is_deauth(hdr->frame_control) ||
ieee80211_is_disassoc(hdr->frame_control)) &&
ieee80211_has_protected(hdr->frame_control)) {
len += IEEE80211_CCMP_MIC_LEN;
buf_len += IEEE80211_CCMP_MIC_LEN;
}

buf_len = min_t(u32, buf_len, WMI_TLV_MGMT_TX_FRAME_MAX_LEN);
buf_len = round_up(buf_len, 4);

len += buf_len;
len = round_up(len, 4);
skb = ath10k_wmi_alloc_skb(ar, len);
if (!skb)
return ERR_PTR(-ENOMEM);

ptr = (void *)skb->data;
tlv = ptr;
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_MGMT_TX_CMD);
tlv->len = __cpu_to_le16(sizeof(*cmd));
cmd = (void *)tlv->value;
cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->desc_id = 0;
cmd->chanfreq = 0;
cmd->buf_len = __cpu_to_le32(buf_len);
cmd->frame_len = __cpu_to_le32(msdu->len);
mgmt_frame_dma = dma_map_single(arvif->ar->dev, msdu->data,
msdu->len, DMA_TO_DEVICE);
if (!mgmt_frame_dma)
return ERR_PTR(-ENOMEM);

cmd->paddr = __cpu_to_le64(mgmt_frame_dma);

ptr += sizeof(*tlv);
ptr += sizeof(*cmd);

tlv = ptr;
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
tlv->len = __cpu_to_le16(buf_len);

ptr += sizeof(*tlv);
memcpy(ptr, msdu->data, buf_len);

return skb;
}

static struct sk_buff *
ath10k_wmi_tlv_op_gen_force_fw_hang(struct ath10k *ar,
enum wmi_force_fw_hang_type type,
Expand Down Expand Up @@ -3291,6 +3367,7 @@ static struct wmi_cmd_map wmi_tlv_cmd_map = {
.bcn_filter_rx_cmdid = WMI_TLV_BCN_FILTER_RX_CMDID,
.prb_req_filter_rx_cmdid = WMI_TLV_PRB_REQ_FILTER_RX_CMDID,
.mgmt_tx_cmdid = WMI_TLV_MGMT_TX_CMDID,
.mgmt_tx_send_cmdid = WMI_TLV_MGMT_TX_SEND_CMD,
.prb_tmpl_cmdid = WMI_TLV_PRB_TMPL_CMDID,
.addba_clear_resp_cmdid = WMI_TLV_ADDBA_CLEAR_RESP_CMDID,
.addba_send_cmdid = WMI_TLV_ADDBA_SEND_CMDID,
Expand Down Expand Up @@ -3625,6 +3702,7 @@ static const struct wmi_ops wmi_tlv_ops = {
.gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats,
.gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang,
/* .gen_mgmt_tx = not implemented; HTT is used */
.gen_mgmt_tx = ath10k_wmi_tlv_op_gen_mgmt_tx,
.gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg,
.gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable,
.gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable,
Expand Down
67 changes: 67 additions & 0 deletions drivers/net/wireless/ath/ath10k/wmi-tlv.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#define WMI_TLV_CMD_UNSUPPORTED 0
#define WMI_TLV_PDEV_PARAM_UNSUPPORTED 0
#define WMI_TLV_VDEV_PARAM_UNSUPPORTED 0
#define WMI_TLV_MGMT_TX_FRAME_MAX_LEN 64

enum wmi_tlv_grp_id {
WMI_TLV_GRP_START = 0x3,
Expand Down Expand Up @@ -132,6 +133,7 @@ enum wmi_tlv_cmd_id {
WMI_TLV_PRB_REQ_FILTER_RX_CMDID,
WMI_TLV_MGMT_TX_CMDID,
WMI_TLV_PRB_TMPL_CMDID,
WMI_TLV_MGMT_TX_SEND_CMD,
WMI_TLV_ADDBA_CLEAR_RESP_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_BA_NEG),
WMI_TLV_ADDBA_SEND_CMDID,
WMI_TLV_ADDBA_STATUS_CMDID,
Expand Down Expand Up @@ -890,6 +892,63 @@ enum wmi_tlv_tag {
WMI_TLV_TAG_STRUCT_SAP_OFL_DEL_STA_EVENT,
WMI_TLV_TAG_STRUCT_APFIND_CMD_PARAM,
WMI_TLV_TAG_STRUCT_APFIND_EVENT_HDR,
WMI_TLV_TAG_STRUCT_OCB_SET_SCHED_CMD,
WMI_TLV_TAG_STRUCT_OCB_SET_SCHED_EVENT,
WMI_TLV_TAG_STRUCT_OCB_SET_CONFIG_CMD,
WMI_TLV_TAG_STRUCT_OCB_SET_CONFIG_RESP_EVENT,
WMI_TLV_TAG_STRUCT_OCB_SET_UTC_TIME_CMD,
WMI_TLV_TAG_STRUCT_OCB_START_TIMING_ADVERT_CMD,
WMI_TLV_TAG_STRUCT_OCB_STOP_TIMING_ADVERT_CMD,
WMI_TLV_TAG_STRUCT_OCB_GET_TSF_TIMER_CMD,
WMI_TLV_TAG_STRUCT_OCB_GET_TSF_TIMER_RESP_EVENT,
WMI_TLV_TAG_STRUCT_DCC_GET_STATS_CMD,
WMI_TLV_TAG_STRUCT_DCC_CHANNEL_STATS_REQUEST,
WMI_TLV_TAG_STRUCT_DCC_GET_STATS_RESP_EVENT,
WMI_TLV_TAG_STRUCT_DCC_CLEAR_STATS_CMD,
WMI_TLV_TAG_STRUCT_DCC_UPDATE_NDL_CMD,
WMI_TLV_TAG_STRUCT_DCC_UPDATE_NDL_RESP_EVENT,
WMI_TLV_TAG_STRUCT_DCC_STATS_EVENT,
WMI_TLV_TAG_STRUCT_OCB_CHANNEL,
WMI_TLV_TAG_STRUCT_OCB_SCHEDULE_ELEMENT,
WMI_TLV_TAG_STRUCT_DCC_NDL_STATS_PER_CHANNEL,
WMI_TLV_TAG_STRUCT_DCC_NDL_CHAN,
WMI_TLV_TAG_STRUCT_QOS_PARAMETER,
WMI_TLV_TAG_STRUCT_DCC_NDL_ACTIVE_STATE_CONFIG,
WMI_TLV_TAG_STRUCT_ROAM_SCAN_EXTENDED_THRESHOLD_PARAM,
WMI_TLV_TAG_STRUCT_ROAM_FILTER_FIXED_PARAM,
WMI_TLV_TAG_STRUCT_PASSPOINT_CONFIG_CMD,
WMI_TLV_TAG_STRUCT_PASSPOINT_EVENT_HDR,
WMI_TLV_TAG_STRUCT_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMD,
WMI_TLV_TAG_STRUCT_EXTSCAN_HOTLIST_SSID_MATCH_EVENT,
WMI_TLV_TAG_STRUCT_VDEV_TSF_TSTAMP_ACTION_CMD,
WMI_TLV_TAG_STRUCT_VDEV_TSF_REPORT_EVENT,
WMI_TLV_TAG_STRUCT_GET_FW_MEM_DUMP,
WMI_TLV_TAG_STRUCT_UPDATE_FW_MEM_DUMP,
WMI_TLV_TAG_STRUCT_FW_MEM_DUMP_PARAMS,
WMI_TLV_TAG_STRUCT_DEBUG_MESG_FLUSH,
WMI_TLV_TAG_STRUCT_DEBUG_MESG_FLUSH_COMPLETE,
WMI_TLV_TAG_STRUCT_PEER_SET_RATE_REPORT_CONDITION,
WMI_TLV_TAG_STRUCT_ROAM_SUBNET_CHANGE_CONFIG,
WMI_TLV_TAG_STRUCT_VDEV_SET_IE_CMD,
WMI_TLV_TAG_STRUCT_RSSI_BREACH_MONITOR_CONFIG,
WMI_TLV_TAG_STRUCT_RSSI_BREACH_EVENT,
WMI_TLV_TAG_STRUCT_EVENT_INITIAL_WAKEUP,
WMI_TLV_TAG_STRUCT_SOC_SET_PCL_CMD,
WMI_TLV_TAG_STRUCT_SOC_SET_HW_MODE_CMD,
WMI_TLV_TAG_STRUCT_SOC_SET_HW_MODE_RESPONSE_EVENT,
WMI_TLV_TAG_STRUCT_SOC_HW_MODE_TRANSITION_EVENT,
WMI_TLV_TAG_STRUCT_VDEV_TXRX_STREAMS,
WMI_TLV_TAG_STRUCT_SOC_SET_HW_MODE_RESPONSE_VDEV_MAC_ENTRY,
WMI_TLV_TAG_STRUCT_SOC_SET_DUAL_MAC_CONFIG_CMD,
WMI_TLV_TAG_STRUCT_SOC_SET_DUAL_MAC_CONFIG_RESPONSE_EVENT,
WMI_TLV_TAG_STRUCT_IOAC_SOCK_PATTERN_T,
WMI_TLV_TAG_STRUCT_WOW_ENABLE_ICMPV6_NA_FLT_CMD,
WMI_TLV_TAG_STRUCT_DIAG_EVENT_LOG_CONFIG,
WMI_TLV_TAG_STRUCT_DIAG_EVENT_LOG_SUPPORTED_EVENT,
WMI_TLV_TAG_STRUCT_PACKET_FILTER_CONFIG,
WMI_TLV_TAG_STRUCT_PACKET_FILTER_ENABLE,
WMI_TLV_TAG_STRUCT_SAP_SET_BLACKLIST_PARAM_CMD,
WMI_TLV_TAG_STRUCT_MGMT_TX_CMD,

WMI_TLV_TAG_MAX
};
Expand Down Expand Up @@ -1689,4 +1748,12 @@ struct wmi_tlv_tx_pause_ev {

void ath10k_wmi_tlv_attach(struct ath10k *ar);

struct wmi_tlv_mgmt_tx_cmd {
__le32 vdev_id;
__le32 desc_id;
__le32 chanfreq;
__le64 paddr;
__le32 frame_len;
__le32 buf_len;
} __packed;
#endif
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath10k/wmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,7 @@ struct wmi_cmd_map {
u32 bcn_filter_rx_cmdid;
u32 prb_req_filter_rx_cmdid;
u32 mgmt_tx_cmdid;
u32 mgmt_tx_send_cmdid;
u32 prb_tmpl_cmdid;
u32 addba_clear_resp_cmdid;
u32 addba_send_cmdid;
Expand Down

0 comments on commit 1807da4

Please sign in to comment.