arg->desc_id = ev->desc_id;
arg->status = ev->status;
arg->pdev_id = ev->pdev_id;
+ arg->ppdu_id = ev->ppdu_id;
+
+ if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+ arg->ack_rssi = ev->ack_rssi;
kfree(tb);
return 0;
const __le32 *num_reports;
const __le32 *desc_ids;
const __le32 *status;
+ const __le32 *ppdu_ids;
+ const __le32 *ack_rssi;
bool desc_ids_done;
bool status_done;
+ bool ppdu_ids_done;
+ bool ack_rssi_done;
};
static int
} else if (!bundle_tx_compl->status_done) {
bundle_tx_compl->status_done = true;
bundle_tx_compl->status = ptr;
+ } else if (!bundle_tx_compl->ppdu_ids_done) {
+ bundle_tx_compl->ppdu_ids_done = true;
+ bundle_tx_compl->ppdu_ids = ptr;
+ } else if (!bundle_tx_compl->ack_rssi_done) {
+ bundle_tx_compl->ack_rssi_done = true;
+ bundle_tx_compl->ack_rssi = ptr;
}
break;
default:
arg->num_reports = *bundle_tx_compl.num_reports;
arg->desc_ids = bundle_tx_compl.desc_ids;
arg->status = bundle_tx_compl.status;
+ arg->ppdu_ids = bundle_tx_compl.ppdu_ids;
+
+ if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+ arg->ack_rssi = bundle_tx_compl.ack_rssi;
return 0;
}
cfg->num_ocb_schedules = __cpu_to_le32(0);
cfg->host_capab = __cpu_to_le32(WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL);
+ if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+ cfg->host_capab |= __cpu_to_le32(WMI_RSRC_CFG_FLAG_TX_ACK_RSSI);
+
ath10k_wmi_put_host_mem_chunks(ar, chunks);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n");
arvif = (void *)cb->vif->drv_priv;
vdev_id = arvif->vdev_id;
- if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
+ if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control) &&
+ (!(ieee80211_is_nullfunc(hdr->frame_control) ||
+ ieee80211_is_qos_nullfunc(hdr->frame_control)))))
return ERR_PTR(-EINVAL);
len = sizeof(*cmd) + 2 * sizeof(*tlv);
#define WMI_TLV_VDEV_PARAM_UNSUPPORTED 0
#define WMI_TLV_MGMT_TX_FRAME_MAX_LEN 64
+#define WMI_RSRC_CFG_FLAG_TX_ACK_RSSI BIT(18)
+
enum wmi_tlv_grp_id {
WMI_TLV_GRP_START = 0x3,
WMI_TLV_GRP_SCAN = WMI_TLV_GRP_START,
WMI_TLV_SERVICE_AP_TWT = 153,
WMI_TLV_SERVICE_GMAC_OFFLOAD_SUPPORT = 154,
WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT = 155,
+ WMI_TLV_SERVICE_PEER_TID_CONFIGS_SUPPORT = 156,
+ WMI_TLV_SERVICE_VDEV_SWRETRY_PER_AC_CONFIG_SUPPORT = 157,
+ WMI_TLV_SERVICE_DUAL_BEACON_ON_SINGLE_MAC_SCC_SUPPORT = 158,
+ WMI_TLV_SERVICE_DUAL_BEACON_ON_SINGLE_MAC_MCC_SUPPORT = 159,
+ WMI_TLV_SERVICE_MOTION_DET = 160,
+ WMI_TLV_SERVICE_INFRA_MBSSID = 161,
+ WMI_TLV_SERVICE_OBSS_SPATIAL_REUSE = 162,
+ WMI_TLV_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT = 163,
+ WMI_TLV_SERVICE_NAN_DBS_SUPPORT = 164,
+ WMI_TLV_SERVICE_NDI_DBS_SUPPORT = 165,
+ WMI_TLV_SERVICE_NAN_SAP_SUPPORT = 166,
+ WMI_TLV_SERVICE_NDI_SAP_SUPPORT = 167,
+ WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT = 168,
+ WMI_TLV_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1 = 169,
+ WMI_TLV_SERVICE_ESP_SUPPORT = 170,
+ WMI_TLV_SERVICE_PEER_CHWIDTH_CHANGE = 171,
+ WMI_TLV_SERVICE_WLAN_HPCS_PULSE = 172,
+ WMI_TLV_SERVICE_PER_VDEV_CHAINMASK_CONFIG_SUPPORT = 173,
+ WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI = 174,
WMI_TLV_MAX_EXT_SERVICE = 256,
};
SVCMAP(WMI_TLV_SERVICE_THERM_THROT,
WMI_SERVICE_THERM_THROT,
WMI_TLV_MAX_SERVICE);
+ SVCMAP(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
+ WMI_SERVICE_TX_DATA_ACK_RSSI, WMI_TLV_MAX_SERVICE);
}
#undef SVCMAP
__le32 desc_id;
__le32 status;
__le32 pdev_id;
+ __le32 ppdu_id;
+ __le32 ack_rssi;
};
#define WMI_TLV_MGMT_RX_NUM_RSSI 4
return true;
}
-static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id,
- u32 status)
+static int
+wmi_process_mgmt_tx_comp(struct ath10k *ar, struct mgmt_tx_compl_params *param)
{
struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
struct ath10k_wmi *wmi = &ar->wmi;
spin_lock_bh(&ar->data_lock);
- pkt_addr = idr_find(&wmi->mgmt_pending_tx, desc_id);
+ pkt_addr = idr_find(&wmi->mgmt_pending_tx, param->desc_id);
if (!pkt_addr) {
ath10k_warn(ar, "received mgmt tx completion for invalid msdu_id: %d\n",
- desc_id);
+ param->desc_id);
ret = -ENOENT;
goto out;
}
msdu->len, DMA_TO_DEVICE);
info = IEEE80211_SKB_CB(msdu);
- if (status)
+ if (param->status) {
info->flags &= ~IEEE80211_TX_STAT_ACK;
- else
+ } else {
info->flags |= IEEE80211_TX_STAT_ACK;
+ info->status.ack_signal = ATH10K_DEFAULT_NOISE_FLOOR +
+ param->ack_rssi;
+ info->status.is_valid_ack_signal = true;
+ }
ieee80211_tx_status_irqsafe(ar->hw, msdu);
ret = 0;
out:
- idr_remove(&wmi->mgmt_pending_tx, desc_id);
+ idr_remove(&wmi->mgmt_pending_tx, param->desc_id);
spin_unlock_bh(&ar->data_lock);
return ret;
}
int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_tlv_mgmt_tx_compl_ev_arg arg;
+ struct mgmt_tx_compl_params param;
int ret;
ret = ath10k_wmi_pull_mgmt_tx_compl(ar, skb, &arg);
return ret;
}
- wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_id),
- __le32_to_cpu(arg.status));
+ memset(¶m, 0, sizeof(struct mgmt_tx_compl_params));
+ param.desc_id = __le32_to_cpu(arg.desc_id);
+ param.status = __le32_to_cpu(arg.status);
+
+ if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+ param.ack_rssi = __le32_to_cpu(arg.ack_rssi);
+
+ wmi_process_mgmt_tx_comp(ar, ¶m);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv evnt mgmt tx completion\n");
int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg arg;
+ struct mgmt_tx_compl_params param;
u32 num_reports;
int i, ret;
num_reports = __le32_to_cpu(arg.num_reports);
- for (i = 0; i < num_reports; i++)
- wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_ids[i]),
- __le32_to_cpu(arg.status[i]));
+ for (i = 0; i < num_reports; i++) {
+ memset(¶m, 0, sizeof(struct mgmt_tx_compl_params));
+ param.desc_id = __le32_to_cpu(arg.desc_ids[i]);
+ param.status = __le32_to_cpu(arg.desc_ids[i]);
+
+ if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+ param.ack_rssi = __le32_to_cpu(arg.ack_rssi[i]);
+ wmi_process_mgmt_tx_comp(ar, ¶m);
+ }
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv event bundle mgmt tx completion\n");
__le32 vdev_id;
};
+struct mgmt_tx_compl_params {
+ u32 desc_id;
+ u32 status;
+ u32 ppdu_id;
+ int ack_rssi;
+};
+
struct wmi_tlv_mgmt_tx_compl_ev_arg {
__le32 desc_id;
__le32 status;
__le32 pdev_id;
+ __le32 ppdu_id;
+ __le32 ack_rssi;
};
struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg {
__le32 num_reports;
const __le32 *desc_ids;
const __le32 *status;
+ const __le32 *ppdu_ids;
+ const __le32 *ack_rssi;
};
struct wmi_mgmt_rx_ev_arg {