ath10k: Handle bundled tx completion for management frames
WCN3990 supports sending tx completion for multiple management frames bundled together in a single event. Add support to handle the bundled tx completion event for WCN3990. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Signed-off-by: Rakesh Pillai <pillair@codeaurora.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
parent
768ec4c012
commit
cc123fac97
|
@ -33,6 +33,9 @@ struct wmi_ops {
|
|||
struct wmi_mgmt_rx_ev_arg *arg);
|
||||
int (*pull_mgmt_tx_compl)(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_tlv_mgmt_tx_compl_ev_arg *arg);
|
||||
int (*pull_mgmt_tx_bundle_compl)(
|
||||
struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg);
|
||||
int (*pull_ch_info)(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_ch_info_ev_arg *arg);
|
||||
int (*pull_vdev_start)(struct ath10k *ar, struct sk_buff *skb,
|
||||
|
@ -279,6 +282,16 @@ ath10k_wmi_pull_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb,
|
|||
return ar->wmi.ops->pull_mgmt_tx_compl(ar, skb, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_pull_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg)
|
||||
{
|
||||
if (!ar->wmi.ops->pull_mgmt_tx_bundle_compl)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar->wmi.ops->pull_mgmt_tx_bundle_compl(ar, skb, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_pull_mgmt_rx(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_mgmt_rx_ev_arg *arg)
|
||||
|
|
|
@ -620,6 +620,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
case WMI_TLV_MGMT_TX_COMPLETION_EVENTID:
|
||||
ath10k_wmi_event_mgmt_tx_compl(ar, skb);
|
||||
break;
|
||||
case WMI_TLV_MGMT_TX_BUNDLE_COMPLETION_EVENTID:
|
||||
ath10k_wmi_event_mgmt_tx_bundle_compl(ar, skb);
|
||||
break;
|
||||
default:
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "Unknown eventid: %d\n", id);
|
||||
break;
|
||||
|
@ -686,6 +689,65 @@ ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct wmi_tlv_tx_bundle_compl_parse {
|
||||
const __le32 *num_reports;
|
||||
const __le32 *desc_ids;
|
||||
const __le32 *status;
|
||||
bool desc_ids_done;
|
||||
bool status_done;
|
||||
};
|
||||
|
||||
static int
|
||||
ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k *ar, u16 tag, u16 len,
|
||||
const void *ptr, void *data)
|
||||
{
|
||||
struct wmi_tlv_tx_bundle_compl_parse *bundle_tx_compl = data;
|
||||
|
||||
switch (tag) {
|
||||
case WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_BUNDLE_EVENT:
|
||||
bundle_tx_compl->num_reports = ptr;
|
||||
break;
|
||||
case WMI_TLV_TAG_ARRAY_UINT32:
|
||||
if (!bundle_tx_compl->desc_ids_done) {
|
||||
bundle_tx_compl->desc_ids_done = true;
|
||||
bundle_tx_compl->desc_ids = ptr;
|
||||
} else if (!bundle_tx_compl->status_done) {
|
||||
bundle_tx_compl->status_done = true;
|
||||
bundle_tx_compl->status = ptr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev(
|
||||
struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg)
|
||||
{
|
||||
struct wmi_tlv_tx_bundle_compl_parse bundle_tx_compl = { };
|
||||
int ret;
|
||||
|
||||
ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
|
||||
ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse,
|
||||
&bundle_tx_compl);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!bundle_tx_compl.num_reports || !bundle_tx_compl.desc_ids ||
|
||||
!bundle_tx_compl.status)
|
||||
return -EPROTO;
|
||||
|
||||
arg->num_reports = *bundle_tx_compl.num_reports;
|
||||
arg->desc_ids = bundle_tx_compl.desc_ids;
|
||||
arg->status = bundle_tx_compl.status;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
|
||||
struct sk_buff *skb,
|
||||
struct wmi_mgmt_rx_ev_arg *arg)
|
||||
|
@ -4093,6 +4155,7 @@ static const struct wmi_ops wmi_tlv_ops = {
|
|||
.pull_scan = ath10k_wmi_tlv_op_pull_scan_ev,
|
||||
.pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev,
|
||||
.pull_mgmt_tx_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev,
|
||||
.pull_mgmt_tx_bundle_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev,
|
||||
.pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev,
|
||||
.pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
|
||||
.pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
|
||||
|
|
|
@ -321,6 +321,7 @@ enum wmi_tlv_event_id {
|
|||
WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID,
|
||||
WMI_TLV_OFFLOAD_PROB_RESP_TX_STATUS_EVENTID,
|
||||
WMI_TLV_MGMT_TX_COMPLETION_EVENTID,
|
||||
WMI_TLV_MGMT_TX_BUNDLE_COMPLETION_EVENTID,
|
||||
WMI_TLV_TX_DELBA_COMPLETE_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_BA_NEG),
|
||||
WMI_TLV_TX_ADDBA_COMPLETE_EVENTID,
|
||||
WMI_TLV_BA_RSP_SSN_EVENTID,
|
||||
|
|
|
@ -2383,6 +2383,29 @@ int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
u32 num_reports;
|
||||
int i, ret;
|
||||
|
||||
ret = ath10k_wmi_pull_mgmt_tx_bundle_compl(ar, skb, &arg);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to parse bundle mgmt compl event: %d\n", ret);
|
||||
return 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]));
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv event bundle mgmt tx completion\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_mgmt_rx_ev_arg arg = {};
|
||||
|
|
|
@ -6688,6 +6688,12 @@ struct wmi_tlv_mgmt_tx_compl_ev_arg {
|
|||
__le32 pdev_id;
|
||||
};
|
||||
|
||||
struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg {
|
||||
__le32 num_reports;
|
||||
const __le32 *desc_ids;
|
||||
const __le32 *status;
|
||||
};
|
||||
|
||||
struct wmi_mgmt_rx_ev_arg {
|
||||
__le32 channel;
|
||||
__le32 snr;
|
||||
|
@ -7244,6 +7250,7 @@ int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg);
|
|||
int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb);
|
||||
int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb);
|
||||
int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb);
|
||||
int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb);
|
||||
void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb);
|
||||
void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb);
|
||||
int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb);
|
||||
|
|
Loading…
Reference in New Issue