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,
        .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,
        .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,
 
 #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,
        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,
        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
 };
 
 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