diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 31f0ec34ec7b..676d2b1646d1 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -4719,6 +4719,18 @@ nla_put_failure: 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 @@ wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = { [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}, }; /** @@ -4902,6 +4920,128 @@ static int wlan_hdd_handle_restrict_offchan_config(hdd_adapter_t *adapter, return ret_val; } +/** + * 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 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, 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 fdd0fa3f9948..1e2bca3435ac 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -9598,6 +9598,8 @@ int hdd_register_cb(hdd_context_t *hdd_ctx) 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 e05b1f369969..f59204beea66 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -2932,6 +2932,59 @@ void wlan_hdd_cfg80211_stats_ext_callback(void *ctx, 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 bad56e54097f..6a34cb12d787 100644 --- a/core/hdd/src/wlan_hdd_stats.h +++ b/core/hdd/src/wlan_hdd_stats.h @@ -276,6 +276,16 @@ void hdd_clear_hif_stats(void); 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 94b48928a581..8e34aa36148b 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -7234,4 +7234,38 @@ struct ani_ipa_stat_req { 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 e2a134560111..98b940ed7839 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -811,6 +811,19 @@ typedef struct sStatsExtRequestReq { 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 @@ void sme_store_pdev(tHalHandle hal, struct wlan_objmgr_pdev *pdev); 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 a70dd6e5ed5d..adad9ec18584 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -248,6 +248,7 @@ typedef struct tagSmeStruct { 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 18b435f05d82..d7b74bb0048f 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -2656,6 +2656,8 @@ QDF_STATUS sme_process_msg(tHalHandle hHal, struct scheduler_msg *pMsg) 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 @@ void sme_stats_ext_register_callback(tHalHandle hHal, StatsExtCallback callback) 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 @@ QDF_STATUS sme_ipa_uc_stat_request(tHalHandle hal, uint32_t vdev_id, 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 797ed4a5a954..486693daa529 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -2501,4 +2501,24 @@ static inline void wma_print_wmi_mgmt_event_log(uint32_t count, */ 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 02318017d9bc..c031c19a7776 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1212,4 +1212,18 @@ wma_send_vdev_start_to_fw(t_wma_handle *wma, struct vdev_start_params *params); */ 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 cc463dffef53..a5f34cd9a9f3 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -5234,3 +5234,56 @@ int wma_chan_info_event_handler(void *handle, uint8_t *event_buf, 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 3dd51f33b35f..ebd187ad7618 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -2550,6 +2550,10 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, void *cds_context, 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 @@ static QDF_STATUS wma_process_power_debug_stats_req(tp_wma_handle wma_handle) } #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