qcacmn: Change to handle ML reconfig link delete
Change to handle ML reconfig link delete Change-Id: Iaf743a1a61534f2f4bb12be7fccad48e67b81c12 CRs-Fixed: 3346537
此提交包含在:
@@ -151,7 +151,7 @@ osif_cm_indicate_disconnect(struct wlan_objmgr_vdev *vdev,
|
|||||||
struct vdev_osif_priv *osif_priv = NULL;
|
struct vdev_osif_priv *osif_priv = NULL;
|
||||||
struct wlan_objmgr_vdev *assoc_vdev = NULL;
|
struct wlan_objmgr_vdev *assoc_vdev = NULL;
|
||||||
|
|
||||||
if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
|
if (!wlan_vdev_mlme_is_mlo_vdev(vdev) || (link_id != -1)) {
|
||||||
osif_cm_indicate_disconnect_result(
|
osif_cm_indicate_disconnect_result(
|
||||||
netdev, reason, ie, ie_len,
|
netdev, reason, ie, ie_len,
|
||||||
locally_generated, link_id, gfp);
|
locally_generated, link_id, gfp);
|
||||||
@@ -274,6 +274,10 @@ QDF_STATUS osif_disconnect_handler(struct wlan_objmgr_vdev *vdev,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If disconnect due to ML Reconfig, fill link id */
|
||||||
|
if (rsp->req.req.reason_code == REASON_HOST_TRIGGERED_LINK_DELETE)
|
||||||
|
link_id = wlan_vdev_get_link_id(vdev);
|
||||||
|
|
||||||
osif_cm_disconnect_comp_ind(vdev, rsp, OSIF_PRE_USERSPACE_UPDATE);
|
osif_cm_disconnect_comp_ind(vdev, rsp, OSIF_PRE_USERSPACE_UPDATE);
|
||||||
osif_cm_indicate_disconnect(vdev, osif_priv->wdev->netdev,
|
osif_cm_indicate_disconnect(vdev, osif_priv->wdev->netdev,
|
||||||
ieee80211_reason,
|
ieee80211_reason,
|
||||||
|
@@ -32,6 +32,8 @@ typedef __qdf_ktime_t qdf_ktime_t;
|
|||||||
typedef __qdf_timespec_t qdf_timespec_t;
|
typedef __qdf_timespec_t qdf_timespec_t;
|
||||||
typedef __qdf_work_struct_t qdf_work_struct_t;
|
typedef __qdf_work_struct_t qdf_work_struct_t;
|
||||||
|
|
||||||
|
#define qdf_time_uint_to_ms(tu) (((tu) * 1024) / 1000)
|
||||||
|
|
||||||
#ifdef ENHANCED_OS_ABSTRACTION
|
#ifdef ENHANCED_OS_ABSTRACTION
|
||||||
/**
|
/**
|
||||||
* qdf_ns_to_ktime - Converts nanoseconds to a qdf_ktime_t object
|
* qdf_ns_to_ktime - Converts nanoseconds to a qdf_ktime_t object
|
||||||
|
@@ -793,6 +793,7 @@ enum extn_element_ie {
|
|||||||
* accordingly.
|
* accordingly.
|
||||||
*
|
*
|
||||||
* @REASON_PROP_START: Start of prop reason code
|
* @REASON_PROP_START: Start of prop reason code
|
||||||
|
* @REASON_HOST_TRIGGERED_LINK_DELETE: Dynamic link removal
|
||||||
* @REASON_OCI_MISMATCH: Reason OCI Mismatch happens
|
* @REASON_OCI_MISMATCH: Reason OCI Mismatch happens
|
||||||
* @REASON_HOST_TRIGGERED_ROAM_FAILURE: Reason host triggered roam failed
|
* @REASON_HOST_TRIGGERED_ROAM_FAILURE: Reason host triggered roam failed
|
||||||
* @REASON_FW_TRIGGERED_ROAM_FAILURE: Firmware triggered roam failed
|
* @REASON_FW_TRIGGERED_ROAM_FAILURE: Firmware triggered roam failed
|
||||||
@@ -884,7 +885,8 @@ enum wlan_reason_code {
|
|||||||
* REASON_PROP_START and decrease the value of REASON_PROP_START
|
* REASON_PROP_START and decrease the value of REASON_PROP_START
|
||||||
* accordingly.
|
* accordingly.
|
||||||
*/
|
*/
|
||||||
REASON_PROP_START = 65517,
|
REASON_PROP_START = 65516,
|
||||||
|
REASON_HOST_TRIGGERED_LINK_DELETE = 65517,
|
||||||
REASON_OCI_MISMATCH = 65518,
|
REASON_OCI_MISMATCH = 65518,
|
||||||
REASON_HOST_TRIGGERED_ROAM_FAILURE = 65519,
|
REASON_HOST_TRIGGERED_ROAM_FAILURE = 65519,
|
||||||
REASON_FW_TRIGGERED_ROAM_FAILURE = 65520,
|
REASON_FW_TRIGGERED_ROAM_FAILURE = 65520,
|
||||||
|
@@ -1224,4 +1224,11 @@ mlme_twt_vdev_destroy_notification(struct wlan_objmgr_vdev *vdev)
|
|||||||
|
|
||||||
#endif /* WLAN_SUPPORT_TWT && WLAN_TWT_CONV_SUPPORTED */
|
#endif /* WLAN_SUPPORT_TWT && WLAN_TWT_CONV_SUPPORTED */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mlme_vdev_reconfig_timer_cb() - vdev ml reconfig timer callback
|
||||||
|
* @arg: timer argument
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
void mlme_vdev_reconfig_timer_cb(void *arg);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -696,6 +696,8 @@ enum vdev_start_resp_type {
|
|||||||
* @mlme_vdev_dfs_cac_wait_notify: callback to notify about CAC state
|
* @mlme_vdev_dfs_cac_wait_notify: callback to notify about CAC state
|
||||||
* @mlme_vdev_csa_complete: callback to indicate CSA complete
|
* @mlme_vdev_csa_complete: callback to indicate CSA complete
|
||||||
* @mlme_vdev_sta_disconn_start: callback to initiate STA disconnection
|
* @mlme_vdev_sta_disconn_start: callback to initiate STA disconnection
|
||||||
|
* @mlme_vdev_reconfig_timer_complete: callback to process ml reconfing
|
||||||
|
* operation
|
||||||
*/
|
*/
|
||||||
struct vdev_mlme_ops {
|
struct vdev_mlme_ops {
|
||||||
QDF_STATUS (*mlme_vdev_validate_basic_params)(
|
QDF_STATUS (*mlme_vdev_validate_basic_params)(
|
||||||
@@ -774,6 +776,8 @@ struct vdev_mlme_ops {
|
|||||||
QDF_STATUS (*mlme_vdev_sta_disconn_start)(
|
QDF_STATUS (*mlme_vdev_sta_disconn_start)(
|
||||||
struct vdev_mlme_obj *vdev_mlme,
|
struct vdev_mlme_obj *vdev_mlme,
|
||||||
uint16_t event_data_len, void *event_data);
|
uint16_t event_data_len, void *event_data);
|
||||||
|
void (*mlme_vdev_reconfig_timer_complete)(
|
||||||
|
struct vdev_mlme_obj *vdev_mlme);
|
||||||
QDF_STATUS (*mlme_vdev_notify_mlo_sync_wait_entry)(
|
QDF_STATUS (*mlme_vdev_notify_mlo_sync_wait_entry)(
|
||||||
struct vdev_mlme_obj *vdev_mlme);
|
struct vdev_mlme_obj *vdev_mlme);
|
||||||
};
|
};
|
||||||
@@ -790,8 +794,8 @@ struct vdev_mlme_ops {
|
|||||||
* @ops: VDEV MLME callback table
|
* @ops: VDEV MLME callback table
|
||||||
* @ext_vdev_ptr: VDEV MLME legacy pointer
|
* @ext_vdev_ptr: VDEV MLME legacy pointer
|
||||||
* @reg_tpc_obj: Regulatory transmit power info
|
* @reg_tpc_obj: Regulatory transmit power info
|
||||||
* @vdev_rt: VDEV response timer
|
* @ml_reconfig_timer: VDEV ml reconfig timer
|
||||||
* @vdev_wakelock: vdev wakelock sub structure
|
* @ml_reconfig_started: Flag to indicate reconfig status for vdev
|
||||||
*/
|
*/
|
||||||
struct vdev_mlme_obj {
|
struct vdev_mlme_obj {
|
||||||
struct vdev_mlme_proto proto;
|
struct vdev_mlme_proto proto;
|
||||||
@@ -808,6 +812,8 @@ struct vdev_mlme_obj {
|
|||||||
struct vdev_mlme_ops *ops;
|
struct vdev_mlme_ops *ops;
|
||||||
mlme_vdev_ext_t *ext_vdev_ptr;
|
mlme_vdev_ext_t *ext_vdev_ptr;
|
||||||
struct reg_tpc_power_info reg_tpc_obj;
|
struct reg_tpc_power_info reg_tpc_obj;
|
||||||
|
qdf_timer_t ml_reconfig_timer;
|
||||||
|
bool ml_reconfig_started;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -836,3 +836,15 @@ mlme_twt_vdev_destroy_notification(struct wlan_objmgr_vdev *vdev)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void mlme_vdev_reconfig_timer_cb(void *arg)
|
||||||
|
{
|
||||||
|
struct vdev_mlme_obj *vdev_mlme;
|
||||||
|
|
||||||
|
vdev_mlme = (struct vdev_mlme_obj *)arg;
|
||||||
|
if (!vdev_mlme)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((vdev_mlme->ops) &&
|
||||||
|
vdev_mlme->ops->mlme_vdev_reconfig_timer_complete)
|
||||||
|
vdev_mlme->ops->mlme_vdev_reconfig_timer_complete(vdev_mlme);
|
||||||
|
}
|
||||||
|
@@ -116,6 +116,10 @@ static QDF_STATUS mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev,
|
|||||||
goto ext_hdl_create_failed;
|
goto ext_hdl_create_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qdf_timer_init(NULL, &vdev_mlme->ml_reconfig_timer,
|
||||||
|
mlme_vdev_reconfig_timer_cb, (void *)(vdev_mlme),
|
||||||
|
QDF_TIMER_TYPE_WAKE_APPS);
|
||||||
|
|
||||||
wlan_objmgr_vdev_component_obj_attach((struct wlan_objmgr_vdev *)vdev,
|
wlan_objmgr_vdev_component_obj_attach((struct wlan_objmgr_vdev *)vdev,
|
||||||
WLAN_UMAC_COMP_MLME,
|
WLAN_UMAC_COMP_MLME,
|
||||||
(void *)vdev_mlme,
|
(void *)vdev_mlme,
|
||||||
@@ -134,6 +138,7 @@ static QDF_STATUS mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev,
|
|||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
|
|
||||||
ext_hdl_post_create_failed:
|
ext_hdl_post_create_failed:
|
||||||
|
qdf_timer_free(&vdev_mlme->ml_reconfig_timer);
|
||||||
mlme_vdev_ops_ext_hdl_destroy(vdev_mlme);
|
mlme_vdev_ops_ext_hdl_destroy(vdev_mlme);
|
||||||
wlan_objmgr_vdev_component_obj_detach(vdev, WLAN_UMAC_COMP_MLME,
|
wlan_objmgr_vdev_component_obj_detach(vdev, WLAN_UMAC_COMP_MLME,
|
||||||
vdev_mlme);
|
vdev_mlme);
|
||||||
@@ -165,6 +170,7 @@ static QDF_STATUS mlme_vdev_obj_destroy_handler(struct wlan_objmgr_vdev *vdev,
|
|||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qdf_timer_free(&vdev_mlme->ml_reconfig_timer);
|
||||||
wlan_cm_deinit(vdev_mlme);
|
wlan_cm_deinit(vdev_mlme);
|
||||||
mlme_vdev_sm_destroy(vdev_mlme);
|
mlme_vdev_sm_destroy(vdev_mlme);
|
||||||
mlme_vdev_ops_ext_hdl_destroy(vdev_mlme);
|
mlme_vdev_ops_ext_hdl_destroy(vdev_mlme);
|
||||||
|
@@ -561,6 +561,19 @@ void mlo_internal_disconnect_links(struct wlan_objmgr_vdev *vdev);
|
|||||||
*/
|
*/
|
||||||
void mlo_sta_get_vdev_list(struct wlan_objmgr_vdev *vdev, uint16_t *vdev_count,
|
void mlo_sta_get_vdev_list(struct wlan_objmgr_vdev *vdev, uint16_t *vdev_count,
|
||||||
struct wlan_objmgr_vdev **wlan_vdev_list);
|
struct wlan_objmgr_vdev **wlan_vdev_list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mlo_process_ml_reconfig_ie() - process ml reconfig ie for vdev
|
||||||
|
* @vdev: vdev pointer
|
||||||
|
* @scan_entry: RootAP scan entry
|
||||||
|
* @ml_ie: Pointer to ML IE
|
||||||
|
* @ml_ie_len: Length of ML IE
|
||||||
|
*
|
||||||
|
* Return: None
|
||||||
|
*/
|
||||||
|
void mlo_process_ml_reconfig_ie(struct wlan_objmgr_vdev *vdev,
|
||||||
|
struct scan_cache_entry *scan_entry,
|
||||||
|
uint8_t *ml_ie, qdf_size_t ml_ie_len);
|
||||||
#else
|
#else
|
||||||
static inline
|
static inline
|
||||||
QDF_STATUS mlo_connect(struct wlan_objmgr_vdev *vdev,
|
QDF_STATUS mlo_connect(struct wlan_objmgr_vdev *vdev,
|
||||||
@@ -707,5 +720,11 @@ bool mlo_get_keys_saved(struct wlan_objmgr_vdev *vdev,
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void mlo_process_ml_reconfig_ie(struct wlan_objmgr_vdev *vdev,
|
||||||
|
struct scan_cache_entry *scan_entry,
|
||||||
|
uint8_t *ml_ie, qdf_size_t ml_ie_len)
|
||||||
|
{ }
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@@ -28,6 +28,9 @@
|
|||||||
#include <wlan_scan_api.h>
|
#include <wlan_scan_api.h>
|
||||||
#include <scheduler_api.h>
|
#include <scheduler_api.h>
|
||||||
#include <wlan_crypto_global_api.h>
|
#include <wlan_crypto_global_api.h>
|
||||||
|
#include <utils_mlo.h>
|
||||||
|
#include <qdf_time.h>
|
||||||
|
#include <wlan_objmgr_peer_obj.h>
|
||||||
|
|
||||||
#ifdef WLAN_FEATURE_11BE_MLO
|
#ifdef WLAN_FEATURE_11BE_MLO
|
||||||
static inline void
|
static inline void
|
||||||
@@ -1911,4 +1914,151 @@ bool mlo_get_keys_saved(struct wlan_objmgr_vdev *vdev,
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint16_t
|
||||||
|
mlo_get_bcn_interval_by_bssid(struct wlan_objmgr_pdev *pdev,
|
||||||
|
uint8_t *bssid)
|
||||||
|
{
|
||||||
|
struct scan_filter *scan_filter;
|
||||||
|
uint16_t bcn_int = 0;
|
||||||
|
qdf_list_t *list = NULL;
|
||||||
|
struct scan_cache_node *first_node = NULL;
|
||||||
|
qdf_list_node_t *cur_node = NULL;
|
||||||
|
|
||||||
|
scan_filter = qdf_mem_malloc(sizeof(*scan_filter));
|
||||||
|
if (!scan_filter)
|
||||||
|
return bcn_int;
|
||||||
|
|
||||||
|
scan_filter->num_of_bssid = 1;
|
||||||
|
qdf_mem_copy(scan_filter->bssid_list[0].bytes,
|
||||||
|
bssid, sizeof(struct qdf_mac_addr));
|
||||||
|
list = wlan_scan_get_result(pdev, scan_filter);
|
||||||
|
qdf_mem_free(scan_filter);
|
||||||
|
|
||||||
|
if (!list || (list && !qdf_list_size(list))) {
|
||||||
|
mlo_debug("scan list empty");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
qdf_list_peek_front(list, &cur_node);
|
||||||
|
first_node = qdf_container_of(cur_node,
|
||||||
|
struct scan_cache_node,
|
||||||
|
node);
|
||||||
|
if (first_node && first_node->entry)
|
||||||
|
bcn_int = first_node->entry->bcn_int;
|
||||||
|
error:
|
||||||
|
if (list)
|
||||||
|
wlan_scan_purge_results(list);
|
||||||
|
|
||||||
|
return bcn_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mlo_process_link_remove(struct wlan_objmgr_vdev *vdev,
|
||||||
|
struct ml_rv_partner_link_info *link_info)
|
||||||
|
{
|
||||||
|
struct vdev_mlme_obj *vdev_mlme = NULL;
|
||||||
|
struct wlan_objmgr_peer *bss_peer = NULL;
|
||||||
|
uint16_t bcn_int = 0;
|
||||||
|
uint16_t tbtt_count = 0;
|
||||||
|
|
||||||
|
vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
|
||||||
|
if (!vdev_mlme)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (vdev_mlme->ml_reconfig_started == true)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bss_peer = wlan_vdev_get_bsspeer(vdev);
|
||||||
|
if (!bss_peer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Link delete triggered from AP,
|
||||||
|
* start timer with tbtt count * beacon interval
|
||||||
|
*/
|
||||||
|
tbtt_count = link_info->delete_timer;
|
||||||
|
bcn_int = mlo_get_bcn_interval_by_bssid(
|
||||||
|
wlan_vdev_get_pdev(vdev),
|
||||||
|
wlan_peer_get_macaddr(bss_peer));
|
||||||
|
if (!bcn_int)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vdev_mlme->ml_reconfig_started = true;
|
||||||
|
qdf_timer_mod(&vdev_mlme->ml_reconfig_timer,
|
||||||
|
qdf_time_uint_to_ms(tbtt_count * bcn_int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlo_process_ml_reconfig_ie(struct wlan_objmgr_vdev *vdev,
|
||||||
|
struct scan_cache_entry *scan_entry,
|
||||||
|
uint8_t *ml_ie, qdf_size_t ml_ie_len)
|
||||||
|
{
|
||||||
|
struct wlan_objmgr_vdev *co_mld_vdev = NULL;
|
||||||
|
struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {NULL};
|
||||||
|
uint16_t vdev_count = 0;
|
||||||
|
uint8_t idx = 0;
|
||||||
|
uint8_t i = 0;
|
||||||
|
uint8_t link_ix = 0;
|
||||||
|
struct ml_rv_info reconfig_info = {0};
|
||||||
|
uint8_t *ml_rv_ie = NULL;
|
||||||
|
qdf_size_t ml_rv_ie_len = 0;
|
||||||
|
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (!vdev || !mlo_is_mld_sta(vdev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mlo_get_ml_vdev_list(vdev, &vdev_count, wlan_vdev_list);
|
||||||
|
if (!vdev_count) {
|
||||||
|
mlo_debug("Number of VDEVs under MLD is reported as 0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add code for link add here */
|
||||||
|
|
||||||
|
/* Processing for ML Reconfig IE */
|
||||||
|
if (vdev_count == 1) {
|
||||||
|
/* Single link MLO, no need to process link delete */
|
||||||
|
goto err_release_refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = util_find_mlie_by_variant(ml_ie,
|
||||||
|
ml_ie_len,
|
||||||
|
&ml_rv_ie,
|
||||||
|
&ml_rv_ie_len,
|
||||||
|
WLAN_ML_VARIANT_RECONFIG);
|
||||||
|
if (QDF_IS_STATUS_ERROR(status) || !ml_rv_ie) {
|
||||||
|
mlo_debug("ML IE for reconfig variant not found");
|
||||||
|
goto err_release_refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = util_get_rvmlie_persta_link_info(ml_rv_ie, ml_rv_ie_len,
|
||||||
|
&reconfig_info);
|
||||||
|
if (QDF_IS_STATUS_ERROR(status)) {
|
||||||
|
mlo_err("Unable to get persta link info from ML RV IE");
|
||||||
|
goto err_release_refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reconfig_info.num_links) {
|
||||||
|
mlo_err("No. of links is 0 in ML reconfig IE");
|
||||||
|
goto err_release_refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (idx = 0; idx < vdev_count; idx++) {
|
||||||
|
co_mld_vdev = wlan_vdev_list[idx];
|
||||||
|
if (!co_mld_vdev) {
|
||||||
|
mlo_debug("VDEV in MLD VDEV list is NULL");
|
||||||
|
goto err_release_refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
link_ix = wlan_vdev_get_link_id(co_mld_vdev);
|
||||||
|
for (i = 0; i < reconfig_info.num_links; i++) {
|
||||||
|
if (link_ix == reconfig_info.link_info[i].link_id)
|
||||||
|
mlo_process_link_remove(co_mld_vdev,
|
||||||
|
&reconfig_info.link_info[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err_release_refs:
|
||||||
|
|
||||||
|
for (i = 0; i < vdev_count; i++)
|
||||||
|
mlo_release_vdev_ref(wlan_vdev_list[i]);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
新增問題並參考
封鎖使用者