qcacld-3.0: Add vendor attr to get rx aggregation statistics
qcacld-2.0 to qcacld-3.0 propagation
By setting the corresponding parameters: reorder timeout and window size
to FW, the host will deliver information about aggregation of the packets
on RX to upper layer.
Change-Id: I404d56d8d9ca3e90f8d1dee28abd80d784924901
CRs-fixed: 1078111
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 31f0ec3..676d2b1 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -4719,6 +4719,18 @@
QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT
#define ANT_DIV_ACK_SNR_WEIGHT \
QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT
+#define RX_REORDER_TIMEOUT_VOICE \
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE
+#define RX_REORDER_TIMEOUT_VIDEO \
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO
+#define RX_REORDER_TIMEOUT_BESTEFFORT \
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT
+#define RX_REORDER_TIMEOUT_BACKGROUND \
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND
+#define RX_BLOCKSIZE_PEER_MAC \
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC
+#define RX_BLOCKSIZE_WINLIMIT \
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT
static const struct nla_policy
wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
@@ -4743,6 +4755,12 @@
[ANT_DIV_DATA_SNR_WEIGHT] = {.type = NLA_U32},
[ANT_DIV_ACK_SNR_WEIGHT] = {.type = NLA_U32},
[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
+ [RX_REORDER_TIMEOUT_VOICE] = {.type = NLA_U32},
+ [RX_REORDER_TIMEOUT_VIDEO] = {.type = NLA_U32},
+ [RX_REORDER_TIMEOUT_BESTEFFORT] = {.type = NLA_U32},
+ [RX_REORDER_TIMEOUT_BACKGROUND] = {.type = NLA_U32},
+ [RX_BLOCKSIZE_PEER_MAC] = {.type = NLA_UNSPEC},
+ [RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
};
/**
@@ -4903,6 +4921,128 @@
}
/**
+ * wlan_hdd_cfg80211_wifi_set_reorder_timeout - set reorder timeout
+ *
+ * @hdd_ctx: hdd context
+ * @tb: array of pointer to struct nlattr
+ *
+ * Return: 0 on success; error number otherwise
+ */
+static int wlan_hdd_cfg80211_wifi_set_reorder_timeout(hdd_context_t *hdd_ctx,
+ struct nlattr *tb[])
+{
+ int ret_val;
+ QDF_STATUS qdf_status;
+ struct sir_set_rx_reorder_timeout_val reorder_timeout;
+
+#define RX_TIMEOUT_VAL_MIN 10
+#define RX_TIMEOUT_VAL_MAX 1000
+
+ if (tb[RX_REORDER_TIMEOUT_VOICE] ||
+ tb[RX_REORDER_TIMEOUT_VIDEO] ||
+ tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
+ tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
+
+ /* if one is specified, all must be specified */
+ if (!tb[RX_REORDER_TIMEOUT_VOICE] ||
+ !tb[RX_REORDER_TIMEOUT_VIDEO] ||
+ !tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
+ !tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
+ hdd_err("four AC timeout val are required MAC");
+ return -EINVAL;
+ }
+
+ reorder_timeout.rx_timeout_pri[0] = nla_get_u32(
+ tb[RX_REORDER_TIMEOUT_VOICE]);
+ reorder_timeout.rx_timeout_pri[1] = nla_get_u32(
+ tb[RX_REORDER_TIMEOUT_VIDEO]);
+ reorder_timeout.rx_timeout_pri[2] = nla_get_u32(
+ tb[RX_REORDER_TIMEOUT_BESTEFFORT]);
+ reorder_timeout.rx_timeout_pri[3] = nla_get_u32(
+ tb[RX_REORDER_TIMEOUT_BACKGROUND]);
+ /* timeout value is required to be in the rang 10 to 1000ms */
+ if (reorder_timeout.rx_timeout_pri[0] >= RX_TIMEOUT_VAL_MIN &&
+ reorder_timeout.rx_timeout_pri[0] <= RX_TIMEOUT_VAL_MAX &&
+ reorder_timeout.rx_timeout_pri[1] >= RX_TIMEOUT_VAL_MIN &&
+ reorder_timeout.rx_timeout_pri[1] <= RX_TIMEOUT_VAL_MAX &&
+ reorder_timeout.rx_timeout_pri[2] >= RX_TIMEOUT_VAL_MIN &&
+ reorder_timeout.rx_timeout_pri[2] <= RX_TIMEOUT_VAL_MAX &&
+ reorder_timeout.rx_timeout_pri[3] >= RX_TIMEOUT_VAL_MIN &&
+ reorder_timeout.rx_timeout_pri[3] <= RX_TIMEOUT_VAL_MAX) {
+ qdf_status = sme_set_reorder_timeout(hdd_ctx->hHal,
+ &reorder_timeout);
+ if (qdf_status != QDF_STATUS_SUCCESS) {
+ hdd_err("failed to set reorder timeout err %d",
+ qdf_status);
+ ret_val = -EPERM;
+ }
+ } else {
+ hdd_err("one of the timeout value is not in range");
+ ret_val = -EINVAL;
+ }
+ }
+
+ return ret_val;
+}
+
+/**
+ * wlan_hdd_cfg80211_wifi_set_rx_blocksize - set rx blocksize
+ *
+ * @hdd_ctx: hdd context
+ * @adapter: hdd adapter
+ * @tb: array of pointer to struct nlattr
+ *
+ * Return: 0 on success; error number otherwise
+ */
+static int wlan_hdd_cfg80211_wifi_set_rx_blocksize(hdd_context_t *hdd_ctx,
+ hdd_adapter_t *adapter,
+ struct nlattr *tb[])
+{
+ int ret_val;
+ uint32_t set_value;
+ QDF_STATUS qdf_status;
+ struct sir_peer_set_rx_blocksize rx_blocksize;
+
+#define WINDOW_SIZE_VAL_MIN 1
+#define WINDOW_SIZE_VAL_MAX 64
+
+ if (tb[RX_BLOCKSIZE_PEER_MAC] ||
+ tb[RX_BLOCKSIZE_WINLIMIT]) {
+
+ /* if one is specified, both must be specified */
+ if (!tb[RX_BLOCKSIZE_PEER_MAC] ||
+ !tb[RX_BLOCKSIZE_WINLIMIT]) {
+ hdd_err(FL("Both Peer MAC and windows limit required"));
+ return -EINVAL;
+ }
+
+ memcpy(&rx_blocksize.peer_macaddr,
+ nla_data(tb[RX_BLOCKSIZE_PEER_MAC]),
+ sizeof(rx_blocksize.peer_macaddr)),
+
+ rx_blocksize.vdev_id = adapter->sessionId;
+ set_value = nla_get_u32(tb[RX_BLOCKSIZE_WINLIMIT]);
+ /* maximum window size is 64 */
+ if (set_value >= WINDOW_SIZE_VAL_MIN &&
+ set_value <= WINDOW_SIZE_VAL_MAX) {
+ rx_blocksize.rx_block_ack_win_limit = set_value;
+ qdf_status = sme_set_rx_set_blocksize(hdd_ctx->hHal,
+ &rx_blocksize);
+ if (qdf_status != QDF_STATUS_SUCCESS) {
+ hdd_err("failed to set aggr sizes err %d",
+ qdf_status);
+ ret_val = -EPERM;
+ }
+ } else {
+ hdd_err("window size val is not in range");
+ ret_val = -EINVAL;
+ }
+ }
+
+ return ret_val;
+}
+
+/**
* __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
* vendor command
*
@@ -5337,6 +5477,17 @@
hdd_err("Invalid RESTRICT_OFFCHAN setting");
}
}
+
+ ret_val =
+ wlan_hdd_cfg80211_wifi_set_reorder_timeout(hdd_ctx, tb);
+ if (ret_val != 0)
+ return ret_val;
+
+ ret_val =
+ wlan_hdd_cfg80211_wifi_set_rx_blocksize(hdd_ctx, adapter, tb);
+ if (ret_val != 0)
+ return ret_val;
+
return ret_val;
}
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index fdd0fa3..1e2bca3 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -9598,6 +9598,8 @@
sme_ext_scan_register_callback(hdd_ctx->hHal,
wlan_hdd_cfg80211_extscan_callback);
+ sme_stats_ext2_register_callback(hdd_ctx->hHal,
+ wlan_hdd_cfg80211_stats_ext2_callback);
sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
hdd_rssi_threshold_breached);
diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c
index e05b1f3..f59204b 100644
--- a/core/hdd/src/wlan_hdd_stats.c
+++ b/core/hdd/src/wlan_hdd_stats.c
@@ -2932,6 +2932,59 @@
cfg80211_vendor_event(vendor_event, GFP_KERNEL);
}
+
+void wlan_hdd_cfg80211_stats_ext2_callback(void *ctx,
+ struct sir_sme_rx_aggr_hole_ind *pmsg)
+{
+ hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
+ int status;
+ uint32_t data_size, hole_info_size;
+ struct sk_buff *vendor_event;
+
+ status = wlan_hdd_validate_context(hdd_ctx);
+ if (0 != status)
+ return;
+
+ if (NULL == pmsg) {
+ hdd_err("msg received here is null");
+ return;
+ }
+
+ hole_info_size = (pmsg->hole_cnt)*sizeof(pmsg->hole_info_array[0]);
+ data_size = sizeof(struct sir_sme_rx_aggr_hole_ind) + hole_info_size;
+
+ vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
+ NULL,
+ data_size + NLMSG_HDRLEN + NLMSG_HDRLEN,
+ QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX,
+ GFP_KERNEL);
+
+ if (!vendor_event) {
+ hdd_err("vendor_event_alloc failed for STATS_EXT2");
+ return;
+ }
+
+ if (nla_put_u32(vendor_event,
+ QCA_WLAN_VENDOR_ATTR_RX_AGGREGATION_STATS_HOLES_NUM,
+ pmsg->hole_cnt)) {
+ hdd_err("%s put fail",
+ "QCA_WLAN_VENDOR_ATTR_RX_AGGREGATION_STATS_HOLES_NUM");
+ kfree_skb(vendor_event);
+ return;
+ }
+ if (nla_put(vendor_event,
+ QCA_WLAN_VENDOR_ATTR_RX_AGGREGATION_STATS_HOLES_INFO,
+ hole_info_size,
+ (void *)(pmsg->hole_info_array))) {
+ hdd_err("%s put fail",
+ "QCA_WLAN_VENDOR_ATTR_RX_AGGREGATION_STATS_HOLES_INFO");
+ kfree_skb(vendor_event);
+ return;
+ }
+
+ cfg80211_vendor_event(vendor_event, GFP_KERNEL);
+}
+
#endif /* End of WLAN_FEATURE_STATS_EXT */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
diff --git a/core/hdd/src/wlan_hdd_stats.h b/core/hdd/src/wlan_hdd_stats.h
index bad56e5..6a34cb1 100644
--- a/core/hdd/src/wlan_hdd_stats.h
+++ b/core/hdd/src/wlan_hdd_stats.h
@@ -276,6 +276,16 @@
void wlan_hdd_cfg80211_stats_ext_callback(void *ctx,
tStatsExtEvent *msg);
+/**
+ * wlan_hdd_cfg80211_stats_ext2_callback - stats_ext2_callback
+ * @ctx: hdd context
+ * @pmsg: sir_sme_rx_aggr_hole_ind
+ *
+ * Return: void
+ */
+void wlan_hdd_cfg80211_stats_ext2_callback(void *ctx,
+ struct sir_sme_rx_aggr_hole_ind *pmsg);
+
void wlan_hdd_cfg80211_link_layer_stats_callback(void *ctx,
int indType, void *pRsp);
/**
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 94b4892..8e34aa3 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -7234,4 +7234,38 @@
uint32_t param_val;
uint32_t req_type;
};
+
+/**
+ * sir_sme_rx_aggr_hole_ind - sme rx aggr hole indication
+ * @hole_cnt: num of holes detected
+ * @hole_info_array: hole info
+ */
+struct sir_sme_rx_aggr_hole_ind {
+ uint32_t hole_cnt;
+ uint32_t hole_info_array[];
+};
+
+/**
+ * struct sir_set_rx_reorder_timeout_val - rx reorder timeout
+ * @rx_timeout_pri: reorder timeout for AC
+ * rx_timeout_pri[0] : AC_VO
+ * rx_timeout_pri[1] : AC_VI
+ * rx_timeout_pri[2] : AC_BE
+ * rx_timeout_pri[3] : AC_BK
+ */
+struct sir_set_rx_reorder_timeout_val {
+ uint32_t rx_timeout_pri[4];
+};
+
+/**
+ * struct sir_peer_set_rx_blocksize - set rx blocksize
+ * @vdev_id: vdev id
+ * @peer_macaddr: peer mac address
+ * @rx_block_ack_win_limit: windows size limitation
+ */
+struct sir_peer_set_rx_blocksize {
+ uint32_t vdev_id;
+ struct qdf_mac_addr peer_macaddr;
+ uint32_t rx_block_ack_win_limit;
+};
#endif /* __SIR_API_H */
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index e2a1345..98b940e 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -811,6 +811,19 @@
typedef void (*StatsExtCallback)(void *, tStatsExtEvent *);
void sme_stats_ext_register_callback(tHalHandle hHal,
StatsExtCallback callback);
+/**
+ * sme_register_stats_ext2_callback() - Register stats ext2 register
+ * @hal_handle: hal handle for getting global mac struct
+ * @stats_ext2_cb: callback to be registered
+ *
+ * This function will register a callback for frame aggregation failure
+ * indications processing.
+ *
+ * Return: void
+ */
+void sme_stats_ext2_register_callback(tHalHandle hal_handle,
+ void (*stats_ext2_cb)(void *, struct sir_sme_rx_aggr_hole_ind *));
+
void sme_stats_ext_deregister_callback(tHalHandle hhal);
QDF_STATUS sme_stats_ext_request(uint8_t session_id,
tpStatsExtRequestReq input);
@@ -1518,4 +1531,28 @@
QDF_STATUS sme_ipa_uc_stat_request(tHalHandle hal,
uint32_t vdev_id, uint32_t param_id,
uint32_t param_val, uint32_t req_cat);
+
+/**
+ * sme_set_reorder_timeout() - set reorder timeout value
+ * including Voice,Video,Besteffort,Background parameters
+ * @hal: hal handle for getting global mac struct
+ * @reg: struct sir_set_rx_reorder_timeout_val
+ *
+ * Return: QDF_STATUS_SUCCESS or non-zero on failure.
+ */
+QDF_STATUS sme_set_reorder_timeout(tHalHandle hal,
+ struct sir_set_rx_reorder_timeout_val *req);
+
+/**
+ * sme_set_rx_set_blocksize() - set blocksize value
+ * including mac_addr and win_limit parameters
+ * @hal: hal handle for getting global mac struct
+ * @reg: struct sir_peer_set_rx_blocksize
+ *
+ * Return: QDF_STATUS_SUCCESS or non-zero on failure.
+ */
+
+QDF_STATUS sme_set_rx_set_blocksize(tHalHandle hal,
+ struct sir_peer_set_rx_blocksize *req);
+
#endif /* #if !defined( __SME_API_H ) */
diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h
index a70dd6e..adad9ec 100644
--- a/core/sme/inc/sme_internal.h
+++ b/core/sme/inc/sme_internal.h
@@ -248,6 +248,7 @@
void (*rso_cmd_status_cb)(void *hdd_context,
struct rso_cmd_status *rso_status);
void (*congestion_cb)(void *, uint32_t congestion, uint32_t vdev_id);
+ void (*stats_ext2_cb)(void *, struct sir_sme_rx_aggr_hole_ind *);
} tSmeStruct, *tpSmeStruct;
#endif /* #if !defined( __SMEINTERNAL_H ) */
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 18b435f..d7b74bb 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -2656,6 +2656,8 @@
case eWNI_SME_RSO_CMD_STATUS_IND:
if (pMac->sme.rso_cmd_status_cb)
pMac->sme.rso_cmd_status_cb(pMac->hHdd, pMsg->bodyptr);
+ qdf_mem_free(pMsg->bodyptr);
+ break;
case eWMI_SME_LL_STATS_IND:
if (pMac->sme.link_layer_stats_ext_cb)
pMac->sme.link_layer_stats_ext_cb(pMac->hHdd,
@@ -11919,6 +11921,14 @@
pMac->sme.StatsExtCallback = callback;
}
+void sme_stats_ext2_register_callback(tHalHandle hal_handle,
+ void (*stats_ext2_cb)(void *, struct sir_sme_rx_aggr_hole_ind *))
+{
+ tpAniSirGlobal pmac = PMAC_STRUCT(hal_handle);
+
+ pmac->sme.stats_ext2_cb = stats_ext2_cb;
+}
+
/**
* sme_stats_ext_deregister_callback() - De-register ext stats callback
* @h_hal: Hal Handle
@@ -16253,3 +16263,23 @@
return status;
}
+
+QDF_STATUS sme_set_reorder_timeout(tHalHandle hal,
+ struct sir_set_rx_reorder_timeout_val *req)
+{
+ QDF_STATUS status;
+
+ status = wma_set_rx_reorder_timeout_val(hal, req);
+
+ return status;
+}
+
+QDF_STATUS sme_set_rx_set_blocksize(tHalHandle hal,
+ struct sir_peer_set_rx_blocksize *req)
+{
+ QDF_STATUS status;
+
+ status = wma_set_rx_blocksize(hal, req);
+
+ return status;
+}
diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h
index 797ed4a..486693d 100644
--- a/core/wma/inc/wma.h
+++ b/core/wma/inc/wma.h
@@ -2501,4 +2501,24 @@
*/
void wma_ipa_uc_stat_request(wma_cli_set_cmd_t *privcmd);
+/**
+ * wma_set_rx_reorder_timeout_val() - set rx recorder timeout value
+ * @wma_handle: pointer to wma handle
+ * @reorder_timeout: rx reorder timeout value
+ *
+ * Return: VOS_STATUS_SUCCESS for success or error code.
+ */
+QDF_STATUS wma_set_rx_reorder_timeout_val(tp_wma_handle wma_handle,
+ struct sir_set_rx_reorder_timeout_val *reorder_timeout);
+
+/**
+ * wma_set_rx_blocksize() - set rx blocksize
+ * @wma_handle: pointer to wma handle
+ * @peer_rx_blocksize: rx blocksize for peer mac
+ *
+ * Return: QDF_STATUS_SUCCESS for success or error code.
+ */
+QDF_STATUS wma_set_rx_blocksize(tp_wma_handle wma_handle,
+ struct sir_peer_set_rx_blocksize *peer_rx_blocksize);
+
#endif
diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h
index 0231801..c031c19 100644
--- a/core/wma/inc/wma_internal.h
+++ b/core/wma/inc/wma_internal.h
@@ -1212,4 +1212,18 @@
*/
QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id);
+/*
+ * wma_rx_aggr_failure_event_handler - event handler to handle rx aggr failure
+ * @handle: the wma handle
+ * @event_buf: buffer with event
+ * @len: buffer length
+ *
+ * This function receives rx aggregation failure event and then pass to upper
+ * layer
+ *
+ * Return: 0 on success
+ */
+int wma_rx_aggr_failure_event_handler(void *handle, u_int8_t *event_buf,
+ u_int32_t len);
+
#endif
diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c
index cc463df..a5f34cd 100644
--- a/core/wma/src/wma_features.c
+++ b/core/wma/src/wma_features.c
@@ -5234,3 +5234,56 @@
return 0;
}
+
+int wma_rx_aggr_failure_event_handler(void *handle, u_int8_t *event_buf,
+ u_int32_t len)
+{
+ WMI_REPORT_RX_AGGR_FAILURE_EVENTID_param_tlvs *param_buf;
+ struct sir_sme_rx_aggr_hole_ind *rx_aggr_hole_event;
+ wmi_rx_aggr_failure_event_fixed_param *rx_aggr_failure_info;
+ wmi_rx_aggr_failure_info *hole_info;
+ uint32_t i, alloc_len;
+ tpAniSirGlobal mac;
+
+ mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE);
+ if (!mac || !mac->sme.stats_ext2_cb) {
+ WMA_LOGD("%s: NULL mac ptr or HDD callback is null", __func__);
+ return -EINVAL;
+ }
+
+ param_buf = (WMI_REPORT_RX_AGGR_FAILURE_EVENTID_param_tlvs *)event_buf;
+ if (!param_buf) {
+ WMA_LOGE("%s: Invalid stats ext event buf", __func__);
+ return -EINVAL;
+ }
+
+ rx_aggr_failure_info = param_buf->fixed_param;
+ hole_info = param_buf->failure_info;
+
+ alloc_len = sizeof(*rx_aggr_hole_event) +
+ (rx_aggr_failure_info->num_failure_info)*
+ sizeof(rx_aggr_hole_event->hole_info_array[0]);
+ rx_aggr_hole_event = qdf_mem_malloc(alloc_len);
+ if (NULL == rx_aggr_hole_event) {
+ WMA_LOGE("%s: Memory allocation failure", __func__);
+ return -ENOMEM;
+ }
+
+ rx_aggr_hole_event->hole_cnt = rx_aggr_failure_info->num_failure_info;
+ WMA_LOGD("aggr holes_sum: %d\n",
+ rx_aggr_failure_info->num_failure_info);
+ for (i = 0; i < rx_aggr_hole_event->hole_cnt; i++) {
+ rx_aggr_hole_event->hole_info_array[i] =
+ hole_info->end_seq - hole_info->start_seq + 1;
+ WMA_LOGD("aggr_index: %d\tstart_seq: %d\tend_seq: %d\t"
+ "hole_info: %d mpdu lost",
+ i, hole_info->start_seq, hole_info->end_seq,
+ rx_aggr_hole_event->hole_info_array[i]);
+ hole_info++;
+ }
+
+ mac->sme.stats_ext2_cb(mac->hHdd, rx_aggr_hole_event);
+ qdf_mem_free(rx_aggr_hole_event);
+
+ return 0;
+}
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index 3dd51f3..ebd187a 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -2550,6 +2550,10 @@
WMI_DEBUG_MESG_FLUSH_COMPLETE_EVENTID,
wma_flush_complete_evt_handler,
WMA_RX_WORK_CTX);
+ wmi_unified_register_event_handler(wma_handle->wmi_handle,
+ WMI_REPORT_RX_AGGR_FAILURE_EVENTID,
+ wma_rx_aggr_failure_event_handler,
+ WMA_RX_SERIALIZER_CTX);
wma_ndp_register_all_event_handlers(wma_handle);
@@ -6289,6 +6293,108 @@
}
#endif
+QDF_STATUS wma_set_rx_reorder_timeout_val(tp_wma_handle wma_handle,
+ struct sir_set_rx_reorder_timeout_val *reorder_timeout)
+{
+ wmi_pdev_set_reorder_timeout_val_cmd_fixed_param *cmd;
+ uint32_t len;
+ wmi_buf_t buf;
+ int ret;
+
+ if (!reorder_timeout) {
+ WMA_LOGE(FL("invalid pointer"));
+ return QDF_STATUS_E_INVAL;
+ }
+
+ if (!wma_handle) {
+ WMA_LOGE(FL("WMA context is invald!"));
+ return QDF_STATUS_E_INVAL;
+ }
+ len = sizeof(*cmd);
+ buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
+
+ if (!buf) {
+ WMA_LOGE(FL("Failed allocate wmi buffer"));
+ return QDF_STATUS_E_NOMEM;
+ }
+ cmd = (wmi_pdev_set_reorder_timeout_val_cmd_fixed_param *)
+ wmi_buf_data(buf);
+
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_pdev_set_reorder_timeout_val_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(wmi_pdev_set_reorder_timeout_val_cmd_fixed_param));
+
+ memcpy(cmd->rx_timeout_pri, reorder_timeout->rx_timeout_pri,
+ sizeof(reorder_timeout->rx_timeout_pri));
+
+ WMA_LOGD("rx aggr record timeout: VO: %d, VI: %d, BE: %d, BK: %d",
+ cmd->rx_timeout_pri[0], cmd->rx_timeout_pri[1],
+ cmd->rx_timeout_pri[2], cmd->rx_timeout_pri[3]);
+
+ ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
+ WMI_PDEV_SET_REORDER_TIMEOUT_VAL_CMDID);
+ if (ret) {
+ WMA_LOGE(FL("Failed to send aggregation timeout"));
+ wmi_buf_free(buf);
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wma_set_rx_blocksize(tp_wma_handle wma_handle,
+ struct sir_peer_set_rx_blocksize *peer_rx_blocksize)
+{
+ wmi_peer_set_rx_blocksize_cmd_fixed_param *cmd;
+ int32_t len;
+ wmi_buf_t buf;
+ u_int8_t *buf_ptr;
+ int ret;
+
+ if (!peer_rx_blocksize) {
+ WMA_LOGE(FL("invalid pointer"));
+ return QDF_STATUS_E_INVAL;
+ }
+
+ if (!wma_handle) {
+ WMA_LOGE(FL(" WMA context is invald!"));
+ return QDF_STATUS_E_INVAL;
+ }
+
+ len = sizeof(*cmd);
+ buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
+
+ if (!buf) {
+ WMA_LOGE(FL("Failed allocate wmi buffer"));
+ return QDF_STATUS_E_NOMEM;
+ }
+
+ buf_ptr = (u_int8_t *) wmi_buf_data(buf);
+ cmd = (wmi_peer_set_rx_blocksize_cmd_fixed_param *) buf_ptr;
+
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_peer_set_rx_blocksize_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(wmi_peer_set_rx_blocksize_cmd_fixed_param));
+
+ cmd->vdev_id = peer_rx_blocksize->vdev_id;
+ cmd->rx_block_ack_win_limit =
+ peer_rx_blocksize->rx_block_ack_win_limit;
+ WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_rx_blocksize->peer_macaddr.bytes,
+ &cmd->peer_macaddr);
+
+ WMA_LOGD("rx aggr blocksize: %d", cmd->rx_block_ack_win_limit);
+
+ ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
+ WMI_PEER_SET_RX_BLOCKSIZE_CMDID);
+ if (ret) {
+ WMA_LOGE(FL("Failed to send aggregation size command"));
+ wmi_buf_free(buf);
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ return QDF_STATUS_SUCCESS;
+}
+
/**
* wma_mc_process_msg() - process wma messages and call appropriate function.
* @cds_context: cds context