diff --git a/target_if/mlo_mgr/inc/target_if_mlo_mgr.h b/target_if/mlo_mgr/inc/target_if_mlo_mgr.h index 7a999f1938..61715b8cf9 100644 --- a/target_if/mlo_mgr/inc/target_if_mlo_mgr.h +++ b/target_if/mlo_mgr/inc/target_if_mlo_mgr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -81,5 +81,16 @@ target_if_mlo_get_tx_ops(struct wlan_objmgr_psoc *psoc) QDF_STATUS target_if_mlo_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); +/** + * target_if_mlo_send_link_removal_cmd() - Send WMI command for MLO link removal + * @psoc: psoc pointer + * @param: MLO link removal command parameters + * + * Return: QDF_STATUS of operation + */ +QDF_STATUS target_if_mlo_send_link_removal_cmd( + struct wlan_objmgr_psoc *psoc, + const struct mlo_link_removal_cmd_params *param); + #endif /* __TARGET_IF_MLO_MGR_H__ */ diff --git a/target_if/mlo_mgr/src/target_if_mlo_mgr.c b/target_if/mlo_mgr/src/target_if_mlo_mgr.c index b1450cb39c..e524b24655 100644 --- a/target_if/mlo_mgr/src/target_if_mlo_mgr.c +++ b/target_if/mlo_mgr/src/target_if_mlo_mgr.c @@ -326,6 +326,26 @@ target_if_mlo_send_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev, return status; } +QDF_STATUS target_if_mlo_send_link_removal_cmd( + struct wlan_objmgr_psoc *psoc, + const struct mlo_link_removal_cmd_params *param) +{ + struct wmi_unified *wmi_handle; + + if (!psoc) { + target_if_err("null psoc"); + return QDF_STATUS_E_NULL_VALUE; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + target_if_err("null handle"); + return QDF_STATUS_E_FAILURE; + } + + return wmi_send_mlo_link_removal_cmd(wmi_handle, param); +} + /** * target_if_mlo_register_tx_ops() - lmac handler to register mlo tx ops * callback functions @@ -356,6 +376,7 @@ target_if_mlo_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) mlo_tx_ops->link_set_active = target_if_mlo_link_set_active; mlo_tx_ops->send_tid_to_link_mapping = target_if_mlo_send_tid_to_link_mapping; + mlo_tx_ops->send_link_removal_cmd = target_if_mlo_send_link_removal_cmd; return QDF_STATUS_SUCCESS; } diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h index 3d93a36353..f09d2161f6 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h @@ -234,6 +234,9 @@ /* for mlo reconfig link removal TBTT complete */ #define WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE 0x00800000 +/* MLO link removal is in progress on this VDEV */ +#define WLAN_VDEV_OP_MLO_LINK_REMOVAL_IN_PROGRESS 0x01000000 + /* CAPABILITY: IBSS available */ #define WLAN_VDEV_C_IBSS 0x00000001 /* CAPABILITY: HOSTAP avail */ diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h index 36eae90315..f8c423b224 100644 --- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h +++ b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h @@ -1388,6 +1388,7 @@ struct wlan_lmac_if_son_rx_ops { * @unregister_events: function to de-register event handlers with FW * @link_set_active: function to send mlo link set active command to FW * @send_tid_to_link_mapping: function to send T2LM command to FW + * @send_link_removal_cmd: function to send MLO link removal command to FW */ struct wlan_lmac_if_mlo_tx_ops { QDF_STATUS (*register_events)(struct wlan_objmgr_psoc *psoc); @@ -1399,6 +1400,9 @@ struct wlan_lmac_if_mlo_tx_ops { #endif QDF_STATUS (*send_tid_to_link_mapping)(struct wlan_objmgr_vdev *vdev, struct wlan_t2lm_info *t2lm); + QDF_STATUS (*send_link_removal_cmd)( + struct wlan_objmgr_psoc *psoc, + const struct mlo_link_removal_cmd_params *param); }; /** diff --git a/umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h b/umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h index 670a8a1d81..934b20cb70 100644 --- a/umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h +++ b/umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h @@ -1007,4 +1007,16 @@ struct mlo_vdev_host_tid_to_link_map_resp { enum wlan_t2lm_status status; uint8_t mapping_switch_tsf; }; + +/* + * struct mlo_link_removal_cmd_params - MLO link removal command parameters + * @vdev_id: vdev ID of the link to be removed + * @reconfig_ml_ie: Entire ML reconfiguration element + * @reconfig_ml_ie_size: size of the field @reconfig_ml_ie + */ +struct mlo_link_removal_cmd_params { + uint8_t vdev_id; + uint8_t *reconfig_ml_ie; + uint32_t reconfig_ml_ie_size; +}; #endif diff --git a/wmi/inc/wmi_unified_11be_api.h b/wmi/inc/wmi_unified_11be_api.h index a5afddb0be..611f621f49 100644 --- a/wmi/inc/wmi_unified_11be_api.h +++ b/wmi/inc/wmi_unified_11be_api.h @@ -64,6 +64,17 @@ wmi_send_mlo_link_set_active_cmd(wmi_unified_t wmi_handle, QDF_STATUS wmi_extract_mgmt_rx_ml_cu_params(wmi_unified_t wmi_handle, void *evt_buf, struct mlo_mgmt_ml_info *cu_params); + +/** + * wmi_send_mlo_link_removal_cmd() - Send WMI command for MLO link removal + * @wmi: wmi handle + * @param: MLO link removal command parameters + * + * Return: QDF_STATUS_SUCCESS of operation + */ +QDF_STATUS wmi_send_mlo_link_removal_cmd( + wmi_unified_t wmi, + const struct mlo_link_removal_cmd_params *param); #endif /*WLAN_FEATURE_11BE_MLO*/ #ifdef WLAN_FEATURE_11BE diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index 8774098435..df6e7d4b58 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -3035,6 +3035,10 @@ QDF_STATUS (*extract_mgmt_rx_ml_cu_params)(wmi_unified_t wmi_handle, void *evt_buf, struct mlo_mgmt_ml_info *cu_params); + +QDF_STATUS (*send_mlo_link_removal_cmd)( + wmi_unified_t wmi_handle, + const struct mlo_link_removal_cmd_params *params); #endif #ifdef WLAN_FEATURE_SON diff --git a/wmi/src/wmi_unified_11be_api.c b/wmi/src/wmi_unified_11be_api.c index ea8bb5bacd..a3521319b9 100644 --- a/wmi/src/wmi_unified_11be_api.c +++ b/wmi/src/wmi_unified_11be_api.c @@ -119,3 +119,13 @@ wmi_extract_mgmt_rx_ml_cu_params(wmi_unified_t wmi, void *evt_buf, return QDF_STATUS_E_FAILURE; } + +QDF_STATUS wmi_send_mlo_link_removal_cmd( + wmi_unified_t wmi, + const struct mlo_link_removal_cmd_params *param) +{ + if (wmi->ops->send_mlo_link_removal_cmd) + return wmi->ops->send_mlo_link_removal_cmd(wmi, param); + + return QDF_STATUS_E_FAILURE; +} diff --git a/wmi/src/wmi_unified_11be_tlv.c b/wmi/src/wmi_unified_11be_tlv.c index f26e8b2a96..7a51fb14cd 100644 --- a/wmi/src/wmi_unified_11be_tlv.c +++ b/wmi/src/wmi_unified_11be_tlv.c @@ -600,6 +600,74 @@ extract_mlo_link_set_active_resp_tlv(wmi_unified_t wmi_handle, void *evt_buf, return QDF_STATUS_SUCCESS; } +/** + * send_mlo_link_removal_cmd_tlv() - Send WMI command for MLO link removal + * @wmi_handle: wmi handle + * @params: MLO link removal command parameters + * + * Return: QDF_STATUS_SUCCESS of operation + */ +static QDF_STATUS send_mlo_link_removal_cmd_tlv( + wmi_unified_t wmi_handle, + const struct mlo_link_removal_cmd_params *params) +{ + wmi_mlo_link_removal_cmd_fixed_param *fixed_params; + wmi_buf_t buf; + uint8_t *buf_ptr; + uint32_t buf_len = 0; + uint32_t ie_len_aligned = 0; + QDF_STATUS ret; + + if (!params) { + wmi_err("command params is NULL"); + return QDF_STATUS_E_NULL_VALUE; + } + + ie_len_aligned = roundup(params->reconfig_ml_ie_size, sizeof(uint32_t)); + + buf_len = sizeof(wmi_mlo_link_removal_cmd_fixed_param) + + WMI_TLV_HDR_SIZE + ie_len_aligned; + + buf = wmi_buf_alloc(wmi_handle, buf_len); + if (!buf) { + wmi_err("wmi buf alloc failed for link removal cmd: psoc (%pK) vdev(%u)", + wmi_handle->soc->wmi_psoc, params->vdev_id); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_t *)wmi_buf_data(buf); + + /* Populate fixed params TLV */ + fixed_params = (wmi_mlo_link_removal_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&fixed_params->tlv_header, + WMITLV_TAG_STRUC_wmi_mlo_link_removal_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_mlo_link_removal_cmd_fixed_param)); + fixed_params->vdev_id = params->vdev_id; + fixed_params->reconfig_ml_ie_num_bytes_valid = + params->reconfig_ml_ie_size; + buf_ptr += sizeof(*fixed_params); + + /* Populate the array of bytes TLV */ + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_aligned); + buf_ptr += WMI_TLV_HDR_SIZE; + + /* Populate ML reconfiguration element in raw bytes */ + qdf_mem_copy(buf_ptr, params->reconfig_ml_ie, + params->reconfig_ml_ie_size); + + wmi_mtrace(WMI_MLO_LINK_REMOVAL_CMDID, fixed_params->vdev_id, 0); + ret = wmi_unified_cmd_send(wmi_handle, buf, buf_len, + WMI_MLO_LINK_REMOVAL_CMDID); + if (QDF_IS_STATUS_ERROR(ret)) { + wmi_err("Failed to send MLO link removal cmd: psoc (%pK) vdev(%u)", + wmi_handle->soc->wmi_psoc, params->vdev_id); + wmi_buf_free(buf); + } + + return ret; +} + #ifdef WLAN_FEATURE_11BE size_t peer_assoc_t2lm_params_size(struct peer_assoc_params *req) { @@ -1314,4 +1382,5 @@ void wmi_11be_attach_tlv(wmi_unified_t wmi_handle) #endif /* WLAN_FEATURE_11BE */ ops->extract_mgmt_rx_ml_cu_params = extract_mgmt_rx_ml_cu_params_tlv; + ops->send_mlo_link_removal_cmd = send_mlo_link_removal_cmd_tlv; }