diff --git a/qdf/inc/qdf_types.h b/qdf/inc/qdf_types.h index df07ba798e..7202a13140 100644 --- a/qdf/inc/qdf_types.h +++ b/qdf/inc/qdf_types.h @@ -1412,6 +1412,7 @@ enum qdf_suspend_type { * @QDF_VDEV_SM_OUT_OF_SYNC: Vdev SM is out of sync and connect req received * when already connected * @QDF_STATS_REQ_TIMEDOUT: Stats request timedout + * @QDF_RSO_STOP_RSP_TIMEOUT: Firmware hasn't sent RSO stop response */ enum qdf_hang_reason { QDF_REASON_UNSPECIFIED, @@ -1443,6 +1444,7 @@ enum qdf_hang_reason { QDF_VDEV_SM_OUT_OF_SYNC, QDF_STATS_REQ_TIMEDOUT, QDF_TX_DESC_LEAK, + QDF_RSO_STOP_RSP_TIMEOUT, }; /** diff --git a/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_tx_ops.h b/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_tx_ops.h index 9029b456b9..c6d2208c7d 100644 --- a/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_tx_ops.h +++ b/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_tx_ops.h @@ -118,4 +118,17 @@ QDF_STATUS target_if_vdev_mgr_rsp_timer_stop( struct vdev_response_timer *vdev_rsp, enum wlan_vdev_mgr_tgt_if_rsp_bit clear_bit); +/** + * target_if_vdev_mgr_rsp_timer_start() - API to start response timer for + * vdev manager operations + * @psoc: pointer to psoc object + * @vdev_rsp: vdev response timer + * @set_bit: enum of wlan_vdev_mgr_tgt_if_rsp_bit + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +target_if_vdev_mgr_rsp_timer_start(struct wlan_objmgr_psoc *psoc, + struct vdev_response_timer *vdev_rsp, + enum wlan_vdev_mgr_tgt_if_rsp_bit set_bit); #endif /* __TARGET_IF_VDEV_MGR_TX_OPS_H__ */ diff --git a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c index 7811a7abbe..909967c212 100644 --- a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c +++ b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c @@ -33,6 +33,9 @@ #include #include #include +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#include +#endif static inline void target_if_vdev_mgr_handle_recovery(struct wlan_objmgr_psoc *psoc, @@ -49,6 +52,22 @@ void target_if_vdev_mgr_handle_recovery(struct wlan_objmgr_psoc *psoc, wlan_psoc_get_id(psoc), vdev_id); } +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +static inline QDF_STATUS +target_if_send_rso_stop_failure_rsp(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) +{ + return target_if_cm_send_rso_stop_failure_rsp(psoc, vdev_id); +} +#else +static inline QDF_STATUS +target_if_send_rso_stop_failure_rsp(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id) +{ + return QDF_STATUS_E_NOSUPPORT; +} +#endif + void target_if_vdev_mgr_rsp_timer_cb(void *arg) { struct wlan_objmgr_psoc *psoc; @@ -83,9 +102,10 @@ void target_if_vdev_mgr_rsp_timer_cb(void *arg) !qdf_atomic_test_bit(RESTART_RESPONSE_BIT, &vdev_rsp->rsp_status) && !qdf_atomic_test_bit(STOP_RESPONSE_BIT, &vdev_rsp->rsp_status) && !qdf_atomic_test_bit(DELETE_RESPONSE_BIT, &vdev_rsp->rsp_status) && - !qdf_atomic_test_bit( - PEER_DELETE_ALL_RESPONSE_BIT, - &vdev_rsp->rsp_status)) { + !qdf_atomic_test_bit(PEER_DELETE_ALL_RESPONSE_BIT, + &vdev_rsp->rsp_status) && + !qdf_atomic_test_bit(RSO_STOP_RESPONSE_BIT, + &vdev_rsp->rsp_status)) { mlme_debug("No response bit is set, ignoring actions :%d", vdev_rsp->vdev_id); return; @@ -151,6 +171,14 @@ void target_if_vdev_mgr_rsp_timer_cb(void *arg) recovery_reason, rsp_pos); rx_ops->vdev_mgr_peer_delete_all_response(psoc, &peer_del_all_rsp); + } else if (qdf_atomic_test_bit(RSO_STOP_RESPONSE_BIT, + &vdev_rsp->rsp_status)) { + rsp_pos = RSO_STOP_RESPONSE_BIT; + recovery_reason = QDF_RSO_STOP_RSP_TIMEOUT; + target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); + target_if_vdev_mgr_handle_recovery(psoc, vdev_id, + recovery_reason, rsp_pos); + target_if_send_rso_stop_failure_rsp(psoc, vdev_id); } else { mlme_err("PSOC_%d VDEV_%d: Unknown error", wlan_psoc_get_id(psoc), vdev_id); diff --git a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c index 4905baa4b2..7c65769747 100644 --- a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c +++ b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c @@ -101,10 +101,10 @@ target_if_vdev_mgr_rsp_timer_stop(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_E_FAILURE; } -static QDF_STATUS target_if_vdev_mgr_rsp_timer_start( - struct wlan_objmgr_psoc *psoc, - struct vdev_response_timer *vdev_rsp, - enum wlan_vdev_mgr_tgt_if_rsp_bit set_bit) +QDF_STATUS +target_if_vdev_mgr_rsp_timer_start(struct wlan_objmgr_psoc *psoc, + struct vdev_response_timer *vdev_rsp, + enum wlan_vdev_mgr_tgt_if_rsp_bit set_bit) { uint8_t rsp_pos; uint8_t vdev_id; diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c b/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c index 88e40de4a9..682ec81780 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c @@ -377,29 +377,24 @@ QDF_STATUS cm_disconnect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id) { struct wlan_cm_vdev_discon_req *req; struct cm_req *cm_req; - struct qdf_mac_addr bssid = QDF_MAC_ADDR_ZERO_INIT; - QDF_STATUS status; + QDF_STATUS status = QDF_STATUS_E_NOSUPPORT; cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id); if (!cm_req) return QDF_STATUS_E_INVAL; + cm_ctx->active_cm_id = *cm_id; + + if (wlan_vdev_mlme_get_opmode(cm_ctx->vdev) == QDF_STA_MODE) + status = mlme_cm_rso_stop_req(cm_ctx->vdev); + + if (status != QDF_STATUS_E_NOSUPPORT) + return status; + req = qdf_mem_malloc(sizeof(*req)); if (!req) return QDF_STATUS_E_NOMEM; - cm_ctx->active_cm_id = *cm_id; - wlan_vdev_get_bss_peer_mac(cm_ctx->vdev, &bssid); - /* - * for northbound req, bssid is not provided so update it from vdev - * in case bssid is not present - */ - if (qdf_is_macaddr_zero(&cm_req->discon_req.req.bssid) || - qdf_is_macaddr_broadcast(&cm_req->discon_req.req.bssid)) - qdf_copy_macaddr(&cm_req->discon_req.req.bssid, &bssid); - - qdf_copy_macaddr(&req->req.bssid, &bssid); - req->cm_id = *cm_id; req->req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev); req->req.source = cm_req->discon_req.req.source; @@ -407,20 +402,70 @@ QDF_STATUS cm_disconnect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id) req->req.is_no_disassoc_disconnect = cm_req->discon_req.req.is_no_disassoc_disconnect; + cm_disconnect_continue_after_rso_stop(cm_ctx->vdev, false, + req); + qdf_mem_free(req); + + return status; +} + +QDF_STATUS +cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev, + bool is_ho_fail, + struct wlan_cm_vdev_discon_req *req) +{ + struct cm_req *cm_req; + QDF_STATUS status; + struct qdf_mac_addr bssid = QDF_MAC_ADDR_ZERO_INIT; + struct cnx_mgr *cm_ctx = cm_get_cm_ctx(vdev); + + if (!cm_ctx) + return QDF_STATUS_E_INVAL; + + if ((CM_ID_GET_PREFIX(req->cm_id)) != DISCONNECT_REQ_PREFIX) { + mlme_err(CM_PREFIX_FMT "active req is not disconnect req", + CM_PREFIX_REF(wlan_vdev_get_id(vdev), req->cm_id)); + return QDF_STATUS_E_INVAL; + } + + cm_req = cm_get_req_by_cm_id(cm_ctx, req->cm_id); + if (!cm_req) + return QDF_STATUS_E_INVAL; + + if (is_ho_fail) { + mlme_debug(CM_PREFIX_FMT "Updating source(%d) and reason code (%d) to RSO reason and source as ho fail is received in RSO stop", + CM_PREFIX_REF(req->req.vdev_id, req->cm_id), + req->req.source, req->req.reason_code); + req->req.source = CM_MLME_DISCONNECT; + req->req.reason_code = REASON_FW_TRIGGERED_ROAM_FAILURE; + } + + wlan_vdev_get_bss_peer_mac(cm_ctx->vdev, &bssid); + /* + * for northbound req, bssid is not provided so update it from vdev + * in case bssid is not present + */ + if (qdf_is_macaddr_zero(&cm_req->discon_req.req.bssid) || + qdf_is_macaddr_broadcast(&cm_req->discon_req.req.bssid)) + qdf_copy_macaddr(&cm_req->discon_req.req.bssid, + &req->req.bssid); + + qdf_copy_macaddr(&req->req.bssid, &bssid); cm_update_scan_mlme_on_disconnect(cm_ctx->vdev, &cm_req->discon_req); - mlme_debug(CM_PREFIX_FMT "disconnect " QDF_MAC_ADDR_FMT " source %d reason %d", + mlme_debug(CM_PREFIX_FMT "disconnect " QDF_MAC_ADDR_FMT + " source %d reason %d is_ho_fail: %u", CM_PREFIX_REF(req->req.vdev_id, req->cm_id), QDF_MAC_ADDR_REF(req->req.bssid.bytes), - req->req.source, req->req.reason_code); + req->req.source, req->req.reason_code, is_ho_fail); + status = mlme_cm_disconnect_req(cm_ctx->vdev, req); if (QDF_IS_STATUS_ERROR(status)) { mlme_err(CM_PREFIX_FMT "disconnect req fail", CM_PREFIX_REF(req->req.vdev_id, req->cm_id)); cm_send_disconnect_resp(cm_ctx, req->cm_id); } - qdf_mem_free(req); return status; } diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h b/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h index e58c98811c..e02212fabf 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2015, 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 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 @@ -460,6 +461,19 @@ void cm_initiate_internal_disconnect(struct cnx_mgr *cm_ctx); */ void cm_send_disconnect_resp(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id); +/** + * cm_disconnect_continue_after_rso_stop() - Continue disconnect after RSO stop + * @vdev: Objmgr vdev + * @is_ho_fail: True if ho_fail happened + * @req: pointer to cm vdev disconnect req + * + * Return: QDF_STATUS + */ +QDF_STATUS +cm_disconnect_continue_after_rso_stop(struct wlan_objmgr_vdev *vdev, + bool is_ho_fail, + struct wlan_cm_vdev_discon_req *req); + /*************** UTIL APIs ****************/ /** @@ -1153,5 +1167,4 @@ void cm_set_candidate_custom_sort_cb( qdf_list_t *list)); #endif - #endif /* __WLAN_CM_MAIN_API_H__ */ diff --git a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h b/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h index af348e338c..ba71ca2cfe 100644 --- a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h +++ b/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 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 @@ -459,4 +460,19 @@ void wlan_cm_set_candidate_custom_sort_cb( */ struct reduced_neighbor_report *wlan_cm_get_rnr(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id); + +/** + * wlan_cm_disc_cont_after_rso_stop() - Continue disconnect after RSO stop + * @vdev: Objmgr vdev + * @is_ho_fail: True if ho_fail happened + * @req: pointer to cm vdev disconnect req + + * This is a wrapper to call core API cm_disconnect_continue_after_rso_stop + * + * Return: QDF_STATUS + */ +QDF_STATUS +wlan_cm_disc_cont_after_rso_stop(struct wlan_objmgr_vdev *vdev, + bool is_ho_fail, + struct wlan_cm_vdev_discon_req *req); #endif /* __WLAN_CM_UCFG_API_H */ diff --git a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h b/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h index 1193f90450..866ab1c483 100644 --- a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h +++ b/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2015,2020-2021 The Linux Foundation. All rights reserved. - * 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 @@ -35,7 +35,9 @@ typedef uint32_t wlan_cm_id; /* Diconnect active timeout */ -#define DISCONNECT_TIMEOUT STOP_RESPONSE_TIMER + DELETE_RESPONSE_TIMER + 1000 +#define DISCONNECT_TIMEOUT \ + ((STOP_RESPONSE_TIMER) + (DELETE_RESPONSE_TIMER) +\ + (RSO_STOP_RESPONSE_TIMER) + (1000)) /* * Disconnect command wait timeout VDEV timeouts + 5 sec buff for current active diff --git a/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c b/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c index 7a6b9760b7..caee61f9fa 100644 --- a/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c +++ b/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2015, 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 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 @@ -370,3 +371,12 @@ struct reduced_neighbor_report *wlan_cm_get_rnr(struct wlan_objmgr_vdev *vdev, return NULL; } + +QDF_STATUS +wlan_cm_disc_cont_after_rso_stop(struct wlan_objmgr_vdev *vdev, + bool is_ho_fail, + struct wlan_cm_vdev_discon_req *req) +{ + return cm_disconnect_continue_after_rso_stop(vdev, is_ho_fail, + req); +} diff --git a/umac/mlme/include/wlan_mlme_cmn.h b/umac/mlme/include/wlan_mlme_cmn.h index 7e8c7c4214..ec34ac8ecc 100644 --- a/umac/mlme/include/wlan_mlme_cmn.h +++ b/umac/mlme/include/wlan_mlme_cmn.h @@ -258,6 +258,7 @@ struct mlme_twt_ops { * complete * @mlme_cm_ext_vdev_down_req_cb: callback to send vdev down to FW * @mlme_cm_ext_roam_start_ind_cb: callback to indicate roam start + * @mlme_cm_ext_rso_stop_cb: callback to send rso stop to FW * @mlme_cm_ext_reassoc_req_cb: callback for reassoc request to * VDEV/PEER SM * @mlme_vdev_send_set_mac_addr: callback to send set MAC address @@ -329,6 +330,7 @@ struct mlme_ext_ops { QDF_STATUS (*mlme_cm_ext_roam_start_ind_cb)( struct wlan_objmgr_vdev *vdev, struct wlan_cm_roam_req *req); + QDF_STATUS (*mlme_cm_ext_rso_stop_cb)(struct wlan_objmgr_vdev *vdev); QDF_STATUS (*mlme_cm_ext_reassoc_req_cb)( struct wlan_objmgr_vdev *vdev, struct wlan_cm_vdev_reassoc_req *req); @@ -629,6 +631,14 @@ QDF_STATUS mlme_cm_connect_complete_ind(struct wlan_objmgr_vdev *vdev, QDF_STATUS mlme_cm_roam_start_ind(struct wlan_objmgr_vdev *vdev, struct wlan_cm_roam_req *req); +/** + * mlme_cm_rso_stop_req() - Connection manager ext RSO stop request + * @vdev: VDEV object + * + * Return: QDF_STATUS + */ +QDF_STATUS mlme_cm_rso_stop_req(struct wlan_objmgr_vdev *vdev); + /** * mlme_cm_reassoc_req() - Connection manager ext reassoc request * @vdev: VDEV object diff --git a/umac/mlme/mlme_objmgr/dispatcher/src/wlan_cmn_mlme_main.c b/umac/mlme/mlme_objmgr/dispatcher/src/wlan_cmn_mlme_main.c index 3feeb05901..323bb65337 100644 --- a/umac/mlme/mlme_objmgr/dispatcher/src/wlan_cmn_mlme_main.c +++ b/umac/mlme/mlme_objmgr/dispatcher/src/wlan_cmn_mlme_main.c @@ -356,6 +356,16 @@ QDF_STATUS mlme_cm_roam_start_ind(struct wlan_objmgr_vdev *vdev, return ret; } +QDF_STATUS mlme_cm_rso_stop_req(struct wlan_objmgr_vdev *vdev) +{ + QDF_STATUS ret = QDF_STATUS_E_NOSUPPORT; + + if ((glbl_ops) && glbl_ops->mlme_cm_ext_rso_stop_cb) + ret = glbl_ops->mlme_cm_ext_rso_stop_cb(vdev); + + return ret; +} + QDF_STATUS mlme_cm_reassoc_req(struct wlan_objmgr_vdev *vdev, struct wlan_cm_vdev_reassoc_req *req) { diff --git a/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_rx_defs.h b/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_rx_defs.h index f9fe075179..5acd1c9087 100644 --- a/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_rx_defs.h +++ b/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_rx_defs.h @@ -42,6 +42,7 @@ * STOP_RESPONSE_BIT: vdev stop response bit * DELETE_RESPONSE_BIT: vdev delete response bit * PEER_DELETE_ALL_RESPONSE_BIT: vdev peer delete all response bit + * RSO_STOP_RESPONSE_BIT : RSO stop response bit */ enum wlan_vdev_mgr_tgt_if_rsp_bit { START_RESPONSE_BIT = 0, @@ -49,6 +50,7 @@ enum wlan_vdev_mgr_tgt_if_rsp_bit { STOP_RESPONSE_BIT = 2, DELETE_RESPONSE_BIT = 3, PEER_DELETE_ALL_RESPONSE_BIT = 4, + RSO_STOP_RESPONSE_BIT = 5, RESPONSE_BIT_MAX, }; @@ -66,6 +68,7 @@ static inline char *string_from_rsp_bit(enum wlan_vdev_mgr_tgt_if_rsp_bit bit) "STOP", "DELETE", "PEER DELETE ALL", + "RSO STOP", "RESPONE MAX"}; return (char *)strings[bit]; } @@ -76,17 +79,20 @@ static inline char *string_from_rsp_bit(enum wlan_vdev_mgr_tgt_if_rsp_bit bit) #define STOP_RESPONSE_TIMER (4000 + PMO_RESUME_TIMEOUT) #define DELETE_RESPONSE_TIMER (4000 + PMO_RESUME_TIMEOUT) #define PEER_DELETE_ALL_RESPONSE_TIMER (6000 + PMO_RESUME_TIMEOUT) +#define RSO_STOP_RESPONSE_TIMER (6000 + PMO_RESUME_TIMEOUT) #elif defined(QCA_LOWMEM_CONFIG) || defined(QCA_512M_CONFIG) || \ defined(QCA_WIFI_QCA5018) #define START_RESPONSE_TIMER 15000 #define STOP_RESPONSE_TIMER 15000 #define DELETE_RESPONSE_TIMER 15000 #define PEER_DELETE_ALL_RESPONSE_TIMER 15000 +#define RSO_STOP_RESPONSE_TIMER 15000 #else #define START_RESPONSE_TIMER 8000 #define STOP_RESPONSE_TIMER 6000 #define DELETE_RESPONSE_TIMER 4000 #define PEER_DELETE_ALL_RESPONSE_TIMER 6000 +#define RSO_STOP_RESPONSE_TIMER 6000 #endif #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE