diff --git a/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h b/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h index 7dc6d12ba209..7a70a04bfe6f 100644 --- a/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h +++ b/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h @@ -1730,11 +1730,51 @@ bool policy_mgr_is_current_hwmode_dbs(struct wlan_objmgr_psoc *psoc); * DBS and there is no need for downgrading while entering DBS. * true: DBS 2x2 can always be supported * false: hw_modes support DBS 1x1 as well + * Genoa DBS 2x2 + 1x1 will not be included. * * Return: true - DBS2x2, false - DBS1x1 */ bool policy_mgr_is_hw_dbs_2x2_capable(struct wlan_objmgr_psoc *psoc); +/* + * policy_mgr_is_2x2_1x1_dbs_capable() - check 2x2+1x1 DBS supported or not + * @psoc: PSOC object data + * + * This routine is called to check 2x2 5G + 1x1 2G (DBS1) or + * 2x2 2G + 1x1 5G (DBS2) support or not. + * Either DBS1 or DBS2 supported + * + * Return: true/false + */ +bool policy_mgr_is_2x2_1x1_dbs_capable(struct wlan_objmgr_psoc *psoc); + +/* + * policy_mgr_is_2x2_5G_1x1_2G_dbs_capable() - check Genoa DBS1 enabled or not + * @psoc: PSOC object data + * + * This routine is called to check support DBS1 or not. + * Notes: DBS1: 2x2 5G + 1x1 2G. + * This function will call policy_mgr_get_hw_mode_idx_from_dbs_hw_list to match + * the HW mode from hw mode list. The parameters will also be matched to + * 2x2 5G +2x2 2G HW mode. But firmware will not report 2x2 5G + 2x2 2G alone + * with 2x2 5G + 1x1 2G at same time. So, it is safe to find DBS1 with + * policy_mgr_get_hw_mode_idx_from_dbs_hw_list. + * + * Return: true/false + */ +bool policy_mgr_is_2x2_5G_1x1_2G_dbs_capable(struct wlan_objmgr_psoc *psoc); + +/* + * policy_mgr_is_2x2_2G_1x1_5G_dbs_capable() - check Genoa DBS2 enabled or not + * @psoc: PSOC object data + * + * This routine is called to check support DBS2 or not. + * Notes: DBS2: 2x2 2G + 1x1 5G + * + * Return: true/false + */ +bool policy_mgr_is_2x2_2G_1x1_5G_dbs_capable(struct wlan_objmgr_psoc *psoc); + /** * policy_mgr_init() - Policy Manager component initialization * routine diff --git a/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h b/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h index ea748b230b35..021ad962227b 100644 --- a/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h +++ b/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h @@ -689,6 +689,12 @@ enum policy_mgr_two_connection_mode { * @PM_SBS_DOWNGRADE: switch to SBS mode & downgrade to 1x1 * @PM_DOWNGRADE: downgrade to 1x1 * @PM_UPGRADE: upgrade to 2x2 + * @PM_DBS1: switch to DBS 1 + * @PM_DBS1_DOWNGRADE: downgrade 2G beaconing entity to 1x1 and switch to DBS1. + * @PM_DBS2: switch to DBS 2 + * @PM_DBS2_DOWNGRADE: downgrade 5G beaconing entity to 1x1 and switch to DBS2. + * @PM_UPGRADE_5G: upgrade 5g beaconing entity to 2x2. + * @PM_UPGRADE_2G: upgrade 2g beaconing entity to 2x2. * @PM_MAX_CONC_PRIORITY_MODE: Max place holder * * These are generic IDs that identify the various roles @@ -705,6 +711,12 @@ enum policy_mgr_conc_next_action { PM_SBS_DOWNGRADE, PM_DOWNGRADE, PM_UPGRADE, + PM_DBS1, + PM_DBS1_DOWNGRADE, + PM_DBS2, + PM_DBS2_DOWNGRADE, + PM_UPGRADE_5G, + PM_UPGRADE_2G, PM_MAX_CONC_NEXT_ACTION }; @@ -882,8 +894,10 @@ struct policy_mgr_conc_connection_info { * @mac0_bw: MAC0 bandwidth * @mac1_bw: MAC1 bandwidth * @mac0_band_cap: mac0 band (5g/2g) capability - * @dbs_cap: DBS capability - * @agile_dfs_cap: Agile DFS capability + * @dbs_cap: DBS capabality + * @agile_dfs_cap: Agile DFS capabality + * @action_type: for dbs mode, the field indicates the "Action type" to be + * used to switch to the mode. To help the hw mode validation. */ struct policy_mgr_hw_mode_params { uint8_t mac0_tx_ss; @@ -896,6 +910,7 @@ struct policy_mgr_hw_mode_params { uint8_t dbs_cap; uint8_t agile_dfs_cap; uint8_t sbs_cap; + enum policy_mgr_conc_next_action action_type; }; /** diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c index 061a068e6eb0..5f90175345b7 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c @@ -620,14 +620,108 @@ done: return status; } -QDF_STATUS policy_mgr_next_actions(struct wlan_objmgr_psoc *psoc, +/** + * policy_mgr_validate_dbs_switch() - Check DBS action valid or not + * @psoc: Pointer to psoc + * @session_id: vdev id + * @action: action requested + * @reason: reason of hw mode change + * + * This routine will check the current hw mode with requested action. + * If we are already in the mode, the caller will do nothing. + * This will be called by policy_mgr_next_actions to check the action needed + * or not. + * + * return : QDF_STATUS_SUCCESS, action is allowed. + * QDF_STATUS_E_ALREADY, action is not needed. + * QDF_STATUS_E_FAILURE, error happens. + * QDF_STATUS_E_NOSUPPORT, the requested mode not supported. + */ +static +QDF_STATUS policy_mgr_validate_dbs_switch( + struct wlan_objmgr_psoc *psoc, + uint32_t session_id, + enum policy_mgr_conc_next_action action, + enum policy_mgr_conn_update_reason reason) +{ + QDF_STATUS status; + struct policy_mgr_hw_mode_params hw_mode; + + /* check for the current HW index to see if really need any action */ + status = policy_mgr_get_current_hw_mode(psoc, &hw_mode); + if (!QDF_IS_STATUS_SUCCESS(status)) { + policy_mgr_err("policy_mgr_get_current_hw_mode failed"); + return status; + } + + if (hw_mode.sbs_cap) { + if ((action == PM_SBS) || (action == PM_SBS_DOWNGRADE)) { + if (!policy_mgr_is_hw_sbs_capable(psoc)) { + /* No action */ + policy_mgr_notice("firmware is not sbs capable"); + return QDF_STATUS_E_NOSUPPORT; + } + /* current mode is already SBS nothing to be + * done + */ + policy_mgr_notice("current mode is already SBS"); + return QDF_STATUS_E_ALREADY; + } else { + return QDF_STATUS_SUCCESS; + } + } + + if (!hw_mode.dbs_cap) { + if (action == PM_SINGLE_MAC || + action == PM_SINGLE_MAC_UPGRADE) { + policy_mgr_notice("current mode is already single MAC"); + return QDF_STATUS_E_ALREADY; + } else { + return QDF_STATUS_SUCCESS; + } + } + /** + * If already in DBS, no need to request DBS again (HL, Napier). + * For dual DBS HW, in case DBS1 -> DBS2 or DBS2 -> DBS1 + * switching, we need to check the current DBS mode is same as + * requested or not. + */ + if (policy_mgr_is_2x2_5G_1x1_2G_dbs_capable(psoc) || + policy_mgr_is_2x2_2G_1x1_5G_dbs_capable(psoc)) { + policy_mgr_info("curr dbs action %d new action %d", + hw_mode.action_type, action); + if (hw_mode.action_type == PM_DBS1 && + ((action == PM_DBS1 || + action == PM_DBS1_DOWNGRADE))) { + policy_mgr_err("driver is already in DBS_5G_2x2_24G_1x1 (%d), no further action %d needed", + hw_mode.action_type, action); + return QDF_STATUS_E_ALREADY; + } else if (hw_mode.action_type == PM_DBS2 && + ((action == PM_DBS2 || + action == PM_DBS2_DOWNGRADE))) { + policy_mgr_err("driver is already in DBS_24G_2x2_5G_1x1 (%d), no further action %d needed", + hw_mode.action_type, action); + return QDF_STATUS_E_ALREADY; + } + } else if ((action == PM_DBS_DOWNGRADE) || (action == PM_DBS) || + (action == PM_DBS_UPGRADE)) { + policy_mgr_err("driver is already in %s mode, no further action needed", + (hw_mode.dbs_cap) ? "dbs" : "non dbs"); + return QDF_STATUS_E_ALREADY; + } + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS policy_mgr_next_actions( + struct wlan_objmgr_psoc *psoc, uint32_t session_id, enum policy_mgr_conc_next_action action, enum policy_mgr_conn_update_reason reason) { QDF_STATUS status = QDF_STATUS_E_FAILURE; - struct policy_mgr_hw_mode_params hw_mode; struct dbs_nss nss_dbs = {0}; + struct policy_mgr_hw_mode_params hw_mode; + enum policy_mgr_conc_next_action next_action; if (policy_mgr_is_hw_dbs_capable(psoc) == false) { policy_mgr_err("driver isn't dbs capable, no further action needed"); @@ -640,28 +734,14 @@ QDF_STATUS policy_mgr_next_actions(struct wlan_objmgr_psoc *psoc, policy_mgr_err("policy_mgr_get_current_hw_mode failed"); return status; } - /** - * if already in DBS no need to request DBS. Might be needed - * to extend the logic when multiple dbs HW mode is available - */ - if ((((PM_DBS_DOWNGRADE == action) || (PM_DBS == action) || - (PM_DBS_UPGRADE == action)) - && hw_mode.dbs_cap)) { - policy_mgr_err("driver is already in %s mode, no further action needed", - (hw_mode.dbs_cap) ? "dbs" : "non dbs"); - return QDF_STATUS_E_ALREADY; - } - - if ((PM_SBS == action) || (action == PM_SBS_DOWNGRADE)) { - if (!policy_mgr_is_hw_sbs_capable(psoc)) { - /* No action */ - policy_mgr_notice("firmware is not sbs capable"); - return QDF_STATUS_E_NOSUPPORT; - } - /* check if current mode is already SBS nothing to be - * done - */ + /* check for the current HW index to see if really need any action */ + status = policy_mgr_validate_dbs_switch(psoc, session_id, action, + reason); + if (!QDF_IS_STATUS_SUCCESS(status)) { + policy_mgr_err(" not take action %d reason %d session %d status %d", + action, reason, session_id, status); + return status; } switch (action) { @@ -755,6 +835,70 @@ QDF_STATUS policy_mgr_next_actions(struct wlan_objmgr_psoc *psoc, status = policy_mgr_nss_update(psoc, POLICY_MGR_RX_NSS_2, PM_NOP, POLICY_MGR_ANY, reason); break; + case PM_DBS1_DOWNGRADE: + status = policy_mgr_complete_action(psoc, POLICY_MGR_RX_NSS_1, + PM_DBS1, reason, + session_id); + break; + case PM_DBS2_DOWNGRADE: + status = policy_mgr_complete_action(psoc, POLICY_MGR_RX_NSS_1, + PM_DBS2, reason, + session_id); + break; + case PM_DBS1: + /* + * PM_DBS1 (2x2 5G + 1x1 2G) will support 5G 2x2. If previous + * mode is DBS, that should be 2x2 2G + 1x1 5G mode and + * the 5G band was downgraded to 1x1. So, we need to + * upgrade 5G vdevs after hw mode change. + */ + if (hw_mode.dbs_cap) + next_action = PM_UPGRADE_5G; + else + next_action = PM_NOP; + status = policy_mgr_pdev_set_hw_mode( + psoc, session_id, + HW_MODE_SS_2x2, + HW_MODE_80_MHZ, + HW_MODE_SS_1x1, HW_MODE_40_MHZ, + HW_MODE_MAC_BAND_5G, + HW_MODE_DBS, + HW_MODE_AGILE_DFS_NONE, + HW_MODE_SBS_NONE, + reason, next_action); + break; + case PM_DBS2: + /* + * PM_DBS2 (2x2 2G + 1x1 5G) will support 2G 2x2. If previous + * mode is DBS, that should be 2x2 5G + 1x1 2G mode and + * the 2G band was downgraded to 1x1. So, we need to + * upgrade 5G vdevs after hw mode change. + */ + if (hw_mode.dbs_cap) + next_action = PM_UPGRADE_2G; + else + next_action = PM_NOP; + status = policy_mgr_pdev_set_hw_mode( + psoc, session_id, + HW_MODE_SS_2x2, + HW_MODE_40_MHZ, + HW_MODE_SS_1x1, HW_MODE_40_MHZ, + HW_MODE_MAC_BAND_2G, + HW_MODE_DBS, + HW_MODE_AGILE_DFS_NONE, + HW_MODE_SBS_NONE, + reason, next_action); + break; + case PM_UPGRADE_5G: + status = policy_mgr_nss_update( + psoc, POLICY_MGR_RX_NSS_2, + PM_NOP, POLICY_MGR_BAND_5, reason); + break; + case PM_UPGRADE_2G: + status = policy_mgr_nss_update( + psoc, POLICY_MGR_RX_NSS_2, + PM_NOP, POLICY_MGR_BAND_24, reason); + break; default: policy_mgr_err("unexpected action value %d", action); status = QDF_STATUS_E_FAILURE; diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c index 8417228ae08a..e7f2303e8fa1 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c @@ -480,6 +480,8 @@ QDF_STATUS policy_mgr_get_hw_mode_from_idx( { uint32_t param; struct policy_mgr_psoc_priv_obj *pm_ctx; + uint8_t mac0_min_ss; + uint8_t mac1_min_ss; uint32_t i, hw_mode_id; pm_ctx = policy_mgr_get_context(psoc); @@ -514,7 +516,20 @@ QDF_STATUS policy_mgr_get_hw_mode_from_idx( hw_mode->dbs_cap = POLICY_MGR_HW_MODE_DBS_MODE_GET(param); hw_mode->agile_dfs_cap = POLICY_MGR_HW_MODE_AGILE_DFS_GET(param); hw_mode->sbs_cap = POLICY_MGR_HW_MODE_SBS_MODE_GET(param); - + if (hw_mode->dbs_cap) { + mac0_min_ss = QDF_MIN(hw_mode->mac0_tx_ss, hw_mode->mac0_rx_ss); + mac1_min_ss = QDF_MIN(hw_mode->mac1_tx_ss, hw_mode->mac1_rx_ss); + if (hw_mode->mac0_band_cap == WLAN_5G_CAPABILITY && + mac0_min_ss && mac1_min_ss && + mac0_min_ss > mac1_min_ss) + hw_mode->action_type = PM_DBS1; + else if (hw_mode->mac0_band_cap == WLAN_2G_CAPABILITY && + mac0_min_ss && mac1_min_ss && + mac0_min_ss > mac1_min_ss) + hw_mode->action_type = PM_DBS2; + else + hw_mode->action_type = PM_DBS; + } return QDF_STATUS_SUCCESS; } @@ -2613,6 +2628,7 @@ QDF_STATUS policy_mgr_complete_action(struct wlan_objmgr_psoc *psoc, uint32_t session_id) { QDF_STATUS status = QDF_STATUS_E_FAILURE; + enum policy_mgr_band downgrade_band; if (policy_mgr_is_hw_dbs_capable(psoc) == false) { policy_mgr_err("driver isn't dbs capable, no further action needed"); @@ -2624,8 +2640,15 @@ QDF_STATUS policy_mgr_complete_action(struct wlan_objmgr_psoc *psoc, * protection. So, not taking any lock inside * policy_mgr_complete_action() during pm_conc_connection_list access. */ + if (next_action == PM_DBS1) + downgrade_band = POLICY_MGR_BAND_24; + else if (next_action == PM_DBS2) + downgrade_band = POLICY_MGR_BAND_5; + else + downgrade_band = POLICY_MGR_ANY; + status = policy_mgr_nss_update(psoc, new_nss, next_action, - POLICY_MGR_ANY, reason); + downgrade_band, reason); if (!QDF_IS_STATUS_SUCCESS(status)) status = policy_mgr_next_actions(psoc, session_id, next_action, reason); diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c index d27f61c5709e..3e239b3b6d0c 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c @@ -769,9 +769,86 @@ bool policy_mgr_is_dbs_enable(struct wlan_objmgr_psoc *psoc) bool policy_mgr_is_hw_dbs_2x2_capable(struct wlan_objmgr_psoc *psoc) { struct dbs_nss nss_dbs; + uint32_t nss; - return ((policy_mgr_get_hw_dbs_nss(psoc, &nss_dbs)) >= HW_MODE_SS_2x2) - ? true : false; + nss = policy_mgr_get_hw_dbs_nss(psoc, &nss_dbs); + if (nss >= HW_MODE_SS_2x2 && (nss_dbs.mac0_ss == nss_dbs.mac1_ss)) + return true; + else + return false; +} + +/* + * policy_mgr_is_2x2_1x1_dbs_capable() - check 2x2+1x1 DBS supported or not + * @psoc: PSOC object data + * + * This routine is called to check 2x2 5G + 1x1 2G (DBS1) or + * 2x2 2G + 1x1 5G (DBS2) support or not. + * Either DBS1 or DBS2 supported + * + * Return: true/false + */ +bool policy_mgr_is_2x2_1x1_dbs_capable(struct wlan_objmgr_psoc *psoc) +{ + struct dbs_nss nss_dbs; + uint32_t nss; + + nss = policy_mgr_get_hw_dbs_nss(psoc, &nss_dbs); + if (nss >= HW_MODE_SS_2x2 && (nss_dbs.mac0_ss > nss_dbs.mac1_ss)) + return true; + else + return false; +} + +/* + * policy_mgr_is_2x2_5G_1x1_2G_dbs_capable() - check Genoa DBS1 enabled or not + * @psoc: PSOC object data + * + * This routine is called to check support DBS1 or not. + * Notes: DBS1: 2x2 5G + 1x1 2G. + * This function will call policy_mgr_get_hw_mode_idx_from_dbs_hw_list to match + * the HW mode from hw mode list. The parameters will also be matched to + * 2x2 5G +2x2 2G HW mode. But firmware will not report 2x2 5G + 2x2 2G alone + * with 2x2 5G + 1x1 2G at same time. So, it is safe to find DBS1 with + * policy_mgr_get_hw_mode_idx_from_dbs_hw_list. + * + * Return: true/false + */ +bool policy_mgr_is_2x2_5G_1x1_2G_dbs_capable(struct wlan_objmgr_psoc *psoc) +{ + return policy_mgr_is_2x2_1x1_dbs_capable(psoc) && + (policy_mgr_get_hw_mode_idx_from_dbs_hw_list( + psoc, + HW_MODE_SS_2x2, + HW_MODE_80_MHZ, + HW_MODE_SS_1x1, HW_MODE_40_MHZ, + HW_MODE_MAC_BAND_5G, + HW_MODE_DBS, + HW_MODE_AGILE_DFS_NONE, + HW_MODE_SBS_NONE) >= 0); +} + +/* + * policy_mgr_is_2x2_2G_1x1_5G_dbs_capable() - check Genoa DBS2 enabled or not + * @psoc: PSOC object data + * + * This routine is called to check support DBS2 or not. + * Notes: DBS2: 2x2 2G + 1x1 5G + * + * Return: true/false + */ +bool policy_mgr_is_2x2_2G_1x1_5G_dbs_capable(struct wlan_objmgr_psoc *psoc) +{ + return policy_mgr_is_2x2_1x1_dbs_capable(psoc) && + (policy_mgr_get_hw_mode_idx_from_dbs_hw_list( + psoc, + HW_MODE_SS_2x2, + HW_MODE_40_MHZ, + HW_MODE_SS_1x1, HW_MODE_40_MHZ, + HW_MODE_MAC_BAND_2G, + HW_MODE_DBS, + HW_MODE_AGILE_DFS_NONE, + HW_MODE_SBS_NONE) >= 0); } uint32_t policy_mgr_get_connection_count(struct wlan_objmgr_psoc *psoc)