diff --git a/components/umac/twt/core/src/wlan_twt_main.c b/components/umac/twt/core/src/wlan_twt_main.c index d8d50d3806..f93a752caf 100644 --- a/components/umac/twt/core/src/wlan_twt_main.c +++ b/components/umac/twt/core/src/wlan_twt_main.c @@ -26,6 +26,7 @@ #include "twt/core/src/wlan_twt_priv.h" #include "twt/core/src/wlan_twt_common.h" #include +#include /** * wlan_twt_add_session() - Add TWT session entry in the TWT context @@ -1385,3 +1386,17 @@ wlan_twt_notify_event_handler(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } + +QDF_STATUS wlan_twt_update_beacon_template(void) +{ + struct scheduler_msg msg = { 0 }; + QDF_STATUS status; + + msg.type = SIR_LIM_UPDATE_BEACON; + status = scheduler_post_message(QDF_MODULE_ID_TWT, QDF_MODULE_ID_PE, + QDF_MODULE_ID_PE, &msg); + if (QDF_IS_STATUS_ERROR(status)) + twt_err("scheduler_post_message failed, status = %u", status); + + return status; +} diff --git a/components/umac/twt/core/src/wlan_twt_main.h b/components/umac/twt/core/src/wlan_twt_main.h index e002514f0f..051278fc2b 100644 --- a/components/umac/twt/core/src/wlan_twt_main.h +++ b/components/umac/twt/core/src/wlan_twt_main.h @@ -179,3 +179,23 @@ QDF_STATUS wlan_twt_init_context(struct wlan_objmgr_psoc *psoc, struct qdf_mac_addr *peer_mac, uint8_t dialog_id); + +/** + * wlan_twt_update_beacon_template() - update beacon template + * + * SoftAP (SAP) is the beaconing entity, as per current requirement + * during Single Channel Concurrency (SCC) or Multi-Channel Concurrency (MCC) + * TWT is not supported on STA as well as SAP. + * + * Whenever SAP is forming SCC/MCC, this function shall be called to update the + * beacon, underlying LIM layer based the TWT responder flag, it disables the + * TWT responder advertisement bit in the beacon. + * + * When SAP moves from SCC/MCC to Standalone, this function shall be called + * to update the beacon, underlying LIM layer based the TWT responder flag, + * it enables the TWT responder advertisement bit in the beacon. + * + * Return: QDF_STATUS + */ +QDF_STATUS wlan_twt_update_beacon_template(void); + diff --git a/components/umac/twt/dispatcher/inc/wlan_twt_ucfg_ext_api.h b/components/umac/twt/dispatcher/inc/wlan_twt_ucfg_ext_api.h index dc36bc1f11..f25b6d511a 100644 --- a/components/umac/twt/dispatcher/inc/wlan_twt_ucfg_ext_api.h +++ b/components/umac/twt/dispatcher/inc/wlan_twt_ucfg_ext_api.h @@ -162,6 +162,25 @@ ucfg_twt_init_context(struct wlan_objmgr_psoc *psoc, */ QDF_STATUS ucfg_twt_set_osif_cb(osif_twt_get_global_ops_cb osif_twt_ops); + +/** + * ucfg_twt_update_beacon_template() - update beacon template + * + * SoftAP (SAP) is the beaconing entity, as per current requirement + * during Single Channel Concurrency (SCC) or Multi-Channel Concurrency (MCC) + * TWT is not supported on STA as well as SAP. + * + * Whenever SAP is forming SCC/MCC, this function shall be called to update the + * beacon, underlying LIM layer based the TWT responder flag, it disables the + * TWT responder advertisement bit in the beacon. + * + * When SAP moves from SCC/MCC to Standalone, this function shall be called + * to update the beacon, underlying LIM layer based the TWT responder flag, + * it enables the TWT responder advertisement bit in the beacon. + * + * Return: QDF_STATUS_SUCCESS + */ +QDF_STATUS ucfg_twt_update_beacon_template(void); #else static inline QDF_STATUS ucfg_twt_psoc_open(struct wlan_objmgr_psoc *psoc) diff --git a/components/umac/twt/dispatcher/src/wlan_twt_ucfg_ext_api.c b/components/umac/twt/dispatcher/src/wlan_twt_ucfg_ext_api.c index 6876e8c166..9f9d647126 100644 --- a/components/umac/twt/dispatcher/src/wlan_twt_ucfg_ext_api.c +++ b/components/umac/twt/dispatcher/src/wlan_twt_ucfg_ext_api.c @@ -141,3 +141,8 @@ ucfg_twt_reset_active_command(struct wlan_objmgr_psoc *psoc, WLAN_TWT_NONE); } +QDF_STATUS ucfg_twt_update_beacon_template(void) +{ + return wlan_twt_update_beacon_template(); +} + diff --git a/core/hdd/src/wlan_hdd_twt.c b/core/hdd/src/wlan_hdd_twt.c index 6dd0fca9b6..b5a64035f5 100644 --- a/core/hdd/src/wlan_hdd_twt.c +++ b/core/hdd/src/wlan_hdd_twt.c @@ -79,6 +79,26 @@ QDF_STATUS hdd_send_twt_responder_enable_cmd(struct hdd_context *hdd_ctx) return QDF_STATUS_SUCCESS; } +void wlan_twt_concurrency_update(struct hdd_context *hdd_ctx) +{ + qdf_sched_work(0, &hdd_ctx->twt_en_dis_work); +} + +void hdd_twt_update_work_handler(void *data) +{ + struct hdd_context *hdd_ctx = (struct hdd_context *)data; + struct osif_psoc_sync *psoc_sync; + int ret; + + ret = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync); + if (ret) + return; + + osif_twt_concurrency_update_handler(hdd_ctx->psoc, hdd_ctx->pdev); + + osif_psoc_sync_op_stop(psoc_sync); +} + QDF_STATUS hdd_send_twt_requestor_enable_cmd(struct hdd_context *hdd_ctx) { uint8_t pdev_id = hdd_ctx->pdev->pdev_objmgr.wlan_pdev_id; @@ -109,6 +129,8 @@ int hdd_test_config_twt_setup_session(struct hdd_adapter *adapter, void wlan_hdd_twt_deinit(struct hdd_context *hdd_ctx) { + qdf_flush_work(&hdd_ctx->twt_en_dis_work); + qdf_destroy_work(NULL, &hdd_ctx->twt_en_dis_work); } void @@ -130,6 +152,13 @@ QDF_STATUS hdd_send_twt_responder_disable_cmd(struct hdd_context *hdd_ctx) return QDF_STATUS_SUCCESS; } +void wlan_hdd_twt_init(struct hdd_context *hdd_ctx) +{ + osif_twt_send_requestor_enable_cmd(hdd_ctx->psoc, 0); + qdf_create_work(0, &hdd_ctx->twt_en_dis_work, + hdd_twt_update_work_handler, hdd_ctx); +} + /** * hdd_twt_terminate_session - Process TWT terminate * operation in the received vendor command and diff --git a/os_if/twt/src/osif_twt_ext_req.c b/os_if/twt/src/osif_twt_ext_req.c index 025e0d516d..b537160c88 100644 --- a/os_if/twt/src/osif_twt_ext_req.c +++ b/os_if/twt/src/osif_twt_ext_req.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -814,3 +813,139 @@ int osif_twt_sta_teardown_req(struct wlan_objmgr_vdev *vdev, return osif_send_sta_twt_teardown_req(vdev, psoc, ¶ms); } + +static void +osif_twt_concurrency_update_on_scc_mcc(struct wlan_objmgr_pdev *pdev, + void *object, void *arg) +{ + struct wlan_objmgr_vdev *vdev = object; + struct twt_conc_context *twt_arg = arg; + QDF_STATUS status; + uint8_t pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE && + vdev->vdev_mlme.mlme_state == WLAN_VDEV_S_UP) { + osif_debug("Concurrency exist on SAP vdev"); + status = osif_twt_send_responder_disable_cmd(twt_arg->psoc, + pdev_id); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("TWT responder disable cmd to fw failed"); + return; + } + ucfg_twt_update_beacon_template(); + } + + if (vdev->vdev_mlme.vdev_opmode == QDF_STA_MODE && + vdev->vdev_mlme.mlme_state == WLAN_VDEV_S_UP) { + osif_debug("Concurrency exist on STA vdev"); + status = osif_twt_send_requestor_disable_cmd(twt_arg->psoc, + pdev_id); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("TWT requestor disable cmd to fw failed"); + return; + } + } +} + +static void +osif_twt_concurrency_update_on_dbs(struct wlan_objmgr_pdev *pdev, + void *object, void *arg) +{ + struct wlan_objmgr_vdev *vdev = object; + struct twt_conc_context *twt_arg = arg; + QDF_STATUS status; + uint8_t pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE && + vdev->vdev_mlme.mlme_state == WLAN_VDEV_S_UP) { + osif_debug("SAP vdev exist"); + status = osif_twt_send_responder_enable_cmd(twt_arg->psoc, + pdev_id); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("TWT responder enable cmd to firmware failed"); + return; + } + ucfg_twt_update_beacon_template(); + } + + if (vdev->vdev_mlme.vdev_opmode == QDF_STA_MODE && + vdev->vdev_mlme.mlme_state == WLAN_VDEV_S_UP) { + osif_debug("STA vdev exist"); + status = osif_twt_send_requestor_enable_cmd(twt_arg->psoc, + pdev_id); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("TWT requestor enable cmd to firmware failed"); + return; + } + } +} + +void osif_twt_concurrency_update_handler(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + uint32_t num_connections, sap_count, sta_count; + QDF_STATUS status; + struct twt_conc_context twt_arg; + uint8_t pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + num_connections = policy_mgr_get_connection_count(psoc); + sta_count = policy_mgr_mode_specific_connection_count(psoc, + PM_STA_MODE, + NULL); + sap_count = policy_mgr_mode_specific_connection_count(psoc, + PM_SAP_MODE, + NULL); + twt_arg.psoc = psoc; + + osif_debug("Total connection %d, sta_count %d, sap_count %d", + num_connections, sta_count, sap_count); + switch (num_connections) { + case 1: + if (sta_count == 1) { + osif_twt_send_requestor_enable_cmd(psoc, pdev_id); + } else if (sap_count == 1) { + osif_twt_send_responder_enable_cmd(psoc, pdev_id); + ucfg_twt_update_beacon_template(); + } + break; + case 2: + if (policy_mgr_current_concurrency_is_scc(psoc) || + policy_mgr_current_concurrency_is_mcc(psoc)) { + status = wlan_objmgr_pdev_iterate_obj_list( + pdev, + WLAN_VDEV_OP, + osif_twt_concurrency_update_on_scc_mcc, + &twt_arg, 0, + WLAN_TWT_ID); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("SAP not in SCC/MCC concurrency"); + return; + } + } else if (policy_mgr_is_current_hwmode_dbs(psoc)) { + status = wlan_objmgr_pdev_iterate_obj_list( + pdev, + WLAN_VDEV_OP, + osif_twt_concurrency_update_on_dbs, + &twt_arg, 0, + WLAN_TWT_ID); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("SAP not in DBS case"); + return; + } + } + break; + case 3: + status = wlan_objmgr_pdev_iterate_obj_list( + pdev, + WLAN_VDEV_OP, + osif_twt_concurrency_update_on_scc_mcc, + &twt_arg, 0, + WLAN_TWT_ID); + break; + default: + osif_err("Unexpected number of connections: %d", + num_connections); + break; + } +} +