From 75f622428bf8d53c66caaa8a69e8772c90f54b99 Mon Sep 17 00:00:00 2001 From: Tushnim Bhattacharyya Date: Wed, 8 Mar 2017 09:15:15 -0800 Subject: [PATCH] qcacmn: Define DBS action functions of policy manager component Define DBS & concurrency action functions for policy manager component. Change-Id: I86cfb364e4753825ef650dc00a38d5226aa110ee CRs-Fixed: 2009818 --- .../policy_mgr/src/wlan_policy_mgr_action.c | 723 +++++++++++++++++- 1 file changed, 714 insertions(+), 9 deletions(-) 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 41f994c0d241..3cd97c828bb1 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 @@ -50,6 +50,43 @@ void policy_mgr_hw_mode_transition_cb(uint32_t old_hw_mode_index, struct policy_mgr_vdev_mac_map *vdev_mac_map, struct wlan_objmgr_psoc *context) { + QDF_STATUS status; + struct policy_mgr_hw_mode_params hw_mode; + uint32_t i; + + if (!vdev_mac_map) { + policy_mgr_err("vdev_mac_map is NULL"); + return; + } + + policy_mgr_notice("old_hw_mode_index=%d, new_hw_mode_index=%d", + old_hw_mode_index, new_hw_mode_index); + + for (i = 0; i < num_vdev_mac_entries; i++) + policy_mgr_notice("vdev_id:%d mac_id:%d", + vdev_mac_map[i].vdev_id, + vdev_mac_map[i].mac_id); + + status = policy_mgr_get_hw_mode_from_idx(context, + new_hw_mode_index, &hw_mode); + if (status != QDF_STATUS_SUCCESS) { + policy_mgr_err("Get HW mode failed: %d", status); + return; + } + + policy_mgr_notice("MAC0: TxSS:%d, RxSS:%d, Bw:%d", + hw_mode.mac0_tx_ss, hw_mode.mac0_rx_ss, hw_mode.mac0_bw); + policy_mgr_notice("MAC1: TxSS:%d, RxSS:%d, Bw:%d", + hw_mode.mac1_tx_ss, hw_mode.mac1_rx_ss, hw_mode.mac1_bw); + policy_mgr_notice("DBS:%d, Agile DFS:%d, SBS:%d", + hw_mode.dbs_cap, hw_mode.agile_dfs_cap, hw_mode.sbs_cap); + + /* update pm_conc_connection_list */ + policy_mgr_update_hw_mode_conn_info(context, num_vdev_mac_entries, + vdev_mac_map, + hw_mode); + + return; } QDF_STATUS policy_mgr_pdev_set_hw_mode(struct wlan_objmgr_psoc *psoc, @@ -63,18 +100,199 @@ QDF_STATUS policy_mgr_pdev_set_hw_mode(struct wlan_objmgr_psoc *psoc, enum hw_mode_sbs_capab sbs, enum policy_mgr_conn_update_reason reason) { + int8_t hw_mode_index; + struct policy_mgr_hw_mode msg; + QDF_STATUS status; + struct policy_mgr_psoc_priv_obj *pm_ctx; + + pm_ctx = policy_mgr_get_context(psoc); + if (!pm_ctx) { + policy_mgr_err("Invalid context"); + return QDF_STATUS_E_FAILURE; + } + + /* + * if HW is not capable of doing 2x2 or ini config disabled 2x2, don't + * allow to request FW for 2x2 + */ + if ((HW_MODE_SS_2x2 == mac0_ss) && (!pm_ctx->enable2x2)) { + policy_mgr_notice("2x2 is not allowed downgrading to 1x1 for mac0"); + mac0_ss = HW_MODE_SS_1x1; + } + if ((HW_MODE_SS_2x2 == mac1_ss) && (!pm_ctx->enable2x2)) { + policy_mgr_notice("2x2 is not allowed downgrading to 1x1 for mac1"); + mac1_ss = HW_MODE_SS_1x1; + } + + hw_mode_index = policy_mgr_get_hw_mode_idx_from_dbs_hw_list(psoc, + mac0_ss, mac0_bw, mac1_ss, mac1_bw, dbs, dfs, sbs); + if (hw_mode_index < 0) { + policy_mgr_err("Invalid HW mode index obtained"); + return QDF_STATUS_E_FAILURE; + } + + msg.hw_mode_index = hw_mode_index; + msg.set_hw_mode_cb = (void *)policy_mgr_pdev_set_hw_mode_cb; + msg.reason = reason; + msg.session_id = session_id; + + policy_mgr_notice("set hw mode to sme: hw_mode_index: %d session:%d reason:%d", + msg.hw_mode_index, msg.session_id, msg.reason); + + status = pm_ctx->sme_cbacks.sme_pdev_set_hw_mode(msg); + if (status != QDF_STATUS_SUCCESS) { + policy_mgr_err("Failed to set hw mode to SME"); + return status; + } + return QDF_STATUS_SUCCESS; } enum policy_mgr_conc_next_action policy_mgr_need_opportunistic_upgrade( struct wlan_objmgr_psoc *psoc) { - return PM_NOP; + uint32_t conn_index; + enum policy_mgr_conc_next_action upgrade = PM_NOP; + uint8_t mac = 0; + struct policy_mgr_hw_mode_params hw_mode; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct policy_mgr_psoc_priv_obj *pm_ctx; + + pm_ctx = policy_mgr_get_context(psoc); + if (!pm_ctx) { + policy_mgr_err("Invalid Context"); + goto done; + } + + if (policy_mgr_is_hw_dbs_capable(psoc) == false) { + policy_mgr_err("driver isn't dbs capable, no further action needed"); + goto done; + } + + 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"); + goto done; + } + if (!hw_mode.dbs_cap) { + policy_mgr_notice("current HW mode is non-DBS capable"); + goto done; + } + + qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock); + /* Are both mac's still in use */ + for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; + conn_index++) { + policy_mgr_debug("index:%d mac:%d in_use:%d chan:%d org_nss:%d", + conn_index, + pm_conc_connection_list[conn_index].mac, + pm_conc_connection_list[conn_index].in_use, + pm_conc_connection_list[conn_index].chan, + pm_conc_connection_list[conn_index].original_nss); + if ((pm_conc_connection_list[conn_index].mac == 0) && + pm_conc_connection_list[conn_index].in_use) { + mac |= POLICY_MGR_MAC0; + if (POLICY_MGR_MAC0_AND_MAC1 == mac) { + qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); + goto done; + } + } else if ((pm_conc_connection_list[conn_index].mac == 1) && + pm_conc_connection_list[conn_index].in_use) { + mac |= POLICY_MGR_MAC1; + if (POLICY_MGR_MAC0_AND_MAC1 == mac) { + qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); + goto done; + } + } + } + /* Let's request for single MAC mode */ + upgrade = PM_SINGLE_MAC; + /* Is there any connection had an initial connection with 2x2 */ + for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; + conn_index++) { + if ((pm_conc_connection_list[conn_index].original_nss == 2) && + pm_conc_connection_list[conn_index].in_use) { + upgrade = PM_SINGLE_MAC_UPGRADE; + qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); + goto done; + } + } + qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); + +done: + return upgrade; } QDF_STATUS policy_mgr_update_connection_info(struct wlan_objmgr_psoc *psoc, uint32_t vdev_id) { + QDF_STATUS status = QDF_STATUS_E_FAILURE; + uint32_t conn_index = 0; + bool found = false; + struct policy_mgr_vdev_entry_info conn_table_entry; + enum policy_mgr_chain_mode chain_mask = POLICY_MGR_ONE_ONE; + uint8_t nss_2g, nss_5g; + enum policy_mgr_con_mode mode; + uint8_t chan; + uint32_t nss = 0; + struct policy_mgr_psoc_priv_obj *pm_ctx; + + pm_ctx = policy_mgr_get_context(psoc); + if (!pm_ctx) { + policy_mgr_err("Invalid Context"); + return status; + } + + qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock); + while (PM_CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + if (vdev_id == pm_conc_connection_list[conn_index].vdev_id) { + /* debug msg */ + found = true; + break; + } + conn_index++; + } + qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); + if (!found) { + /* err msg */ + policy_mgr_err("can't find vdev_id %d in pm_conc_connection_list", + vdev_id); + return status; + } + + status = pm_ctx->wma_cbacks.wma_get_connection_info( + vdev_id, &conn_table_entry); + if (QDF_STATUS_SUCCESS != status) { + policy_mgr_err("can't find vdev_id %d in connection table", + vdev_id); + return status; + } + mode = policy_mgr_get_mode(conn_table_entry.type, + conn_table_entry.sub_type); + chan = reg_freq_to_chan(conn_table_entry.mhz); + status = policy_mgr_get_nss_for_vdev(psoc, mode, &nss_2g, &nss_5g); + if (QDF_IS_STATUS_SUCCESS(status)) { + if ((WLAN_REG_IS_24GHZ_CH(chan) && (nss_2g > 1)) || + (WLAN_REG_IS_5GHZ_CH(chan) && (nss_5g > 1))) + chain_mask = POLICY_MGR_TWO_TWO; + else + chain_mask = POLICY_MGR_ONE_ONE; + nss = (WLAN_REG_IS_24GHZ_CH(chan)) ? nss_2g : nss_5g; + } else { + policy_mgr_err("Error in getting nss"); + } + + policy_mgr_debug("update PM connection table for vdev:%d", vdev_id); + + /* add the entry */ + policy_mgr_update_conc_list(psoc, conn_index, + mode, + chan, + policy_mgr_get_bw(conn_table_entry.chan_width), + conn_table_entry.mac_id, + chain_mask, + nss, vdev_id, true); + return QDF_STATUS_SUCCESS; } @@ -84,6 +302,31 @@ QDF_STATUS policy_mgr_update_and_wait_for_connection_update( uint8_t channel, enum policy_mgr_conn_update_reason reason) { + QDF_STATUS status; + + policy_mgr_debug("session:%d channel:%d reason:%d", + session_id, channel, reason); + + status = policy_mgr_reset_connection_update(psoc); + if (QDF_IS_STATUS_ERROR(status)) + policy_mgr_err("clearing event failed"); + + status = policy_mgr_current_connections_update(psoc, + session_id, channel, reason); + if (QDF_STATUS_E_FAILURE == status) { + policy_mgr_err("connections update failed"); + return QDF_STATUS_E_FAILURE; + } + + /* Wait only when status is success */ + if (QDF_IS_STATUS_SUCCESS(status)) { + status = policy_mgr_wait_for_connection_update(psoc); + if (QDF_IS_STATUS_ERROR(status)) { + policy_mgr_err("qdf wait for event failed"); + return QDF_STATUS_E_FAILURE; + } + } + return QDF_STATUS_SUCCESS; } @@ -92,7 +335,78 @@ QDF_STATUS policy_mgr_current_connections_update(struct wlan_objmgr_psoc *psoc, uint8_t channel, enum policy_mgr_conn_update_reason reason) { - return QDF_STATUS_SUCCESS; + enum policy_mgr_conc_next_action next_action = PM_NOP; + uint32_t num_connections = 0; + enum policy_mgr_one_connection_mode second_index = 0; + enum policy_mgr_two_connection_mode third_index = 0; + enum policy_mgr_band band; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + if (policy_mgr_is_hw_dbs_capable(psoc) == false) { + policy_mgr_err("driver isn't dbs capable, no further action needed"); + return QDF_STATUS_E_NOSUPPORT; + } + if (WLAN_REG_IS_24GHZ_CH(channel)) + band = POLICY_MGR_BAND_24; + else + band = POLICY_MGR_BAND_5; + + num_connections = policy_mgr_get_connection_count(psoc); + + policy_mgr_debug("num_connections=%d channel=%d", + num_connections, channel); + + switch (num_connections) { + case 0: + if (band == POLICY_MGR_BAND_24) + if (policy_mgr_is_hw_dbs_2x2_capable(psoc)) + next_action = PM_DBS; + else + next_action = PM_NOP; + else + next_action = PM_NOP; + break; + case 1: + second_index = + policy_mgr_get_second_connection_pcl_table_index(psoc); + if (PM_MAX_ONE_CONNECTION_MODE == second_index) { + policy_mgr_err( + "couldn't find index for 2nd connection next action table"); + goto done; + } + next_action = + (*next_action_two_connection_table)[second_index][band]; + break; + case 2: + third_index = + policy_mgr_get_third_connection_pcl_table_index(psoc); + if (PM_MAX_TWO_CONNECTION_MODE == third_index) { + policy_mgr_err( + "couldn't find index for 3rd connection next action table"); + goto done; + } + next_action = (*next_action_three_connection_table) + [third_index][band]; + break; + default: + policy_mgr_err("unexpected num_connections value %d", + num_connections); + break; + } + + if (PM_NOP != next_action) + status = policy_mgr_next_actions(psoc, session_id, + next_action, reason); + else + status = QDF_STATUS_E_NOSUPPORT; + + policy_mgr_debug( + "idx2=%d idx3=%d next_action=%d, band=%d status=%d reason=%d session_id=%d", + second_index, third_index, next_action, band, status, + reason, session_id); + +done: + return status; } QDF_STATUS policy_mgr_next_actions(struct wlan_objmgr_psoc *psoc, @@ -100,13 +414,164 @@ QDF_STATUS policy_mgr_next_actions(struct wlan_objmgr_psoc *psoc, enum policy_mgr_conc_next_action action, enum policy_mgr_conn_update_reason reason) { - return QDF_STATUS_SUCCESS; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct policy_mgr_hw_mode_params hw_mode; + + if (policy_mgr_is_hw_dbs_capable(psoc) == false) { + policy_mgr_err("driver isn't dbs capable, no further action needed"); + return QDF_STATUS_E_NOSUPPORT; + } + + /* 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 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_SUCCESS; + } + /* check if current mode is already SBS nothing to be + * done + */ + + } + + switch (action) { + case PM_DBS_DOWNGRADE: + /* + * check if we have a beaconing entity that is using 2x2. If yes, + * update the beacon template & notify FW. Once FW confirms + * beacon updated, send down the HW mode change req + */ + status = policy_mgr_complete_action(psoc, POLICY_MGR_RX_NSS_1, + PM_DBS, reason, session_id); + break; + case PM_DBS: + if (policy_mgr_is_hw_dbs_2x2_capable(psoc)) + status = policy_mgr_pdev_set_hw_mode(psoc, session_id, + HW_MODE_SS_2x2, + HW_MODE_80_MHZ, + HW_MODE_SS_2x2, HW_MODE_40_MHZ, + HW_MODE_DBS, + HW_MODE_AGILE_DFS_NONE, + HW_MODE_SBS_NONE, + reason); + else + status = policy_mgr_pdev_set_hw_mode(psoc, session_id, + HW_MODE_SS_1x1, + HW_MODE_80_MHZ, + HW_MODE_SS_1x1, HW_MODE_40_MHZ, + HW_MODE_DBS, + HW_MODE_AGILE_DFS_NONE, + HW_MODE_SBS_NONE, + reason); + break; + case PM_SINGLE_MAC_UPGRADE: + /* + * change the HW mode first before the NSS upgrade + */ + status = policy_mgr_pdev_set_hw_mode(psoc, session_id, + HW_MODE_SS_2x2, + HW_MODE_80_MHZ, + HW_MODE_SS_0x0, HW_MODE_BW_NONE, + HW_MODE_DBS_NONE, + HW_MODE_AGILE_DFS_NONE, + HW_MODE_SBS_NONE, + reason); + /* + * check if we have a beaconing entity that advertised 2x2 + * intially. If yes, update the beacon template & notify FW. + * Once FW confirms beacon updated, send the HW mode change req + */ + status = policy_mgr_complete_action(psoc, POLICY_MGR_RX_NSS_2, + PM_SINGLE_MAC, reason, session_id); + break; + case PM_SINGLE_MAC: + status = policy_mgr_pdev_set_hw_mode(psoc, session_id, + HW_MODE_SS_2x2, + HW_MODE_80_MHZ, + HW_MODE_SS_0x0, HW_MODE_BW_NONE, + HW_MODE_DBS_NONE, + HW_MODE_AGILE_DFS_NONE, + HW_MODE_SBS_NONE, + reason); + break; + case PM_DBS_UPGRADE: + status = policy_mgr_pdev_set_hw_mode(psoc, session_id, + HW_MODE_SS_2x2, + HW_MODE_80_MHZ, + HW_MODE_SS_2x2, HW_MODE_80_MHZ, + HW_MODE_DBS, + HW_MODE_AGILE_DFS_NONE, + HW_MODE_SBS_NONE, + reason); + + status = policy_mgr_complete_action(psoc, POLICY_MGR_RX_NSS_2, + PM_DBS, reason, session_id); + break; + case PM_SBS_DOWNGRADE: + status = policy_mgr_complete_action(psoc, POLICY_MGR_RX_NSS_1, + PM_SBS, reason, session_id); + break; + case PM_SBS: + status = policy_mgr_pdev_set_hw_mode(psoc, session_id, + HW_MODE_SS_1x1, + HW_MODE_80_MHZ, + HW_MODE_SS_1x1, HW_MODE_80_MHZ, + HW_MODE_DBS, + HW_MODE_AGILE_DFS_NONE, + HW_MODE_SBS, + reason); + break; + default: + policy_mgr_err("unexpected action value %d", action); + status = QDF_STATUS_E_FAILURE; + break; + } + + return status; } QDF_STATUS policy_mgr_handle_conc_multiport(struct wlan_objmgr_psoc *psoc, uint8_t session_id, uint8_t channel) { - return QDF_STATUS_SUCCESS; + QDF_STATUS status; + + if (!policy_mgr_check_for_session_conc(psoc, session_id, channel)) { + policy_mgr_err("Conc not allowed for the session %d", + session_id); + return QDF_STATUS_E_FAILURE; + } + + status = policy_mgr_reset_connection_update(psoc); + if (!QDF_IS_STATUS_SUCCESS(status)) + policy_mgr_err("clearing event failed"); + + status = policy_mgr_current_connections_update(psoc, session_id, + channel, + POLICY_MGR_UPDATE_REASON_NORMAL_STA); + if (QDF_STATUS_E_FAILURE == status) { + policy_mgr_err("connections update failed"); + return status; + } + + return status; } #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH @@ -131,23 +596,99 @@ void policy_mgr_change_sap_channel_with_csa(struct wlan_objmgr_psoc *psoc) QDF_STATUS policy_mgr_wait_for_connection_update(struct wlan_objmgr_psoc *psoc) { + QDF_STATUS status; + struct policy_mgr_psoc_priv_obj *policy_mgr_context; + + policy_mgr_context = policy_mgr_get_context(psoc); + if (!policy_mgr_context) { + policy_mgr_err("Invalid context"); + return QDF_STATUS_E_FAILURE; + } + + status = qdf_wait_single_event( + &policy_mgr_context->connection_update_done_evt, + CONNECTION_UPDATE_TIMEOUT); + + if (!QDF_IS_STATUS_SUCCESS(status)) { + policy_mgr_err("wait for event failed"); + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; } QDF_STATUS policy_mgr_reset_connection_update(struct wlan_objmgr_psoc *psoc) { + QDF_STATUS status; + struct policy_mgr_psoc_priv_obj *policy_mgr_context; + + policy_mgr_context = policy_mgr_get_context(psoc); + if (!policy_mgr_context) { + policy_mgr_err("Invalid context"); + return QDF_STATUS_E_FAILURE; + } + + status = qdf_event_reset( + &policy_mgr_context->connection_update_done_evt); + + if (!QDF_IS_STATUS_SUCCESS(status)) { + policy_mgr_err("clear event failed"); + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; } QDF_STATUS policy_mgr_set_connection_update(struct wlan_objmgr_psoc *psoc) { + QDF_STATUS status; + struct policy_mgr_psoc_priv_obj *policy_mgr_context; + + policy_mgr_context = policy_mgr_get_context(psoc); + if (!policy_mgr_context) { + policy_mgr_err("Invalid context"); + return QDF_STATUS_E_FAILURE; + } + + status = qdf_event_set(&policy_mgr_context->connection_update_done_evt); + + if (!QDF_IS_STATUS_SUCCESS(status)) { + policy_mgr_err("set event failed"); + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; } QDF_STATUS policy_mgr_restart_opportunistic_timer( struct wlan_objmgr_psoc *psoc, bool check_state) { - return QDF_STATUS_SUCCESS; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct policy_mgr_psoc_priv_obj *policy_mgr_ctx; + + policy_mgr_ctx = policy_mgr_get_context(psoc); + if (!policy_mgr_ctx) { + policy_mgr_err("Invalid context"); + return status; + } + + if (check_state && + QDF_TIMER_STATE_RUNNING != + policy_mgr_ctx->dbs_opportunistic_timer.state) + return status; + + qdf_mc_timer_stop(&policy_mgr_ctx->dbs_opportunistic_timer); + + status = qdf_mc_timer_start( + &policy_mgr_ctx->dbs_opportunistic_timer, + DBS_OPPORTUNISTIC_TIME * 1000); + + if (!QDF_IS_STATUS_SUCCESS(status)) { + policy_mgr_err("failed to start opportunistic timer"); + return status; + } + + return status; } #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH @@ -155,12 +696,32 @@ QDF_STATUS policy_mgr_register_sap_restart_channel_switch_cb( struct wlan_objmgr_psoc *psoc, void (*sap_restart_chan_switch_cb)(void *, uint32_t, uint32_t)) { + struct policy_mgr_psoc_priv_obj *policy_mgr_ctx; + + policy_mgr_ctx = policy_mgr_get_context(psoc); + if (!policy_mgr_ctx) { + policy_mgr_err("Invalid context"); + return QDF_STATUS_E_FAILURE; + } + + policy_mgr_ctx->sap_restart_chan_switch_cb = sap_restart_chan_switch_cb; + return QDF_STATUS_SUCCESS; } QDF_STATUS policy_mgr_deregister_sap_restart_channel_switch_cb( struct wlan_objmgr_psoc *psoc) { + struct policy_mgr_psoc_priv_obj *policy_mgr_ctx; + + policy_mgr_ctx = policy_mgr_get_context(psoc); + if (!policy_mgr_ctx) { + policy_mgr_err("Invalid context"); + return QDF_STATUS_E_FAILURE; + } + + policy_mgr_ctx->sap_restart_chan_switch_cb = NULL; + return QDF_STATUS_SUCCESS; } @@ -169,12 +730,77 @@ QDF_STATUS policy_mgr_deregister_sap_restart_channel_switch_cb( QDF_STATUS policy_mgr_set_hw_mode_on_channel_switch( struct wlan_objmgr_psoc *psoc, uint8_t session_id) { - return QDF_STATUS_SUCCESS; + QDF_STATUS status = QDF_STATUS_E_FAILURE, qdf_status; + enum policy_mgr_conc_next_action action; + + if (!policy_mgr_is_hw_dbs_capable(psoc)) { + policy_mgr_err("PM/DBS is disabled"); + return status; + } + + action = (*policy_mgr_get_current_pref_hw_mode_ptr)(psoc); + if ((action != PM_DBS_DOWNGRADE) && + (action != PM_SINGLE_MAC_UPGRADE)) { + policy_mgr_err("Invalid action: %d", action); + status = QDF_STATUS_SUCCESS; + goto done; + } + + policy_mgr_notice("action:%d session id:%d", action, session_id); + + /* Opportunistic timer is started, PM will check if MCC upgrade can be + * done on timer expiry. This avoids any possible ping pong effect + * as well. + */ + if (action == PM_SINGLE_MAC_UPGRADE) { + qdf_status = policy_mgr_restart_opportunistic_timer( + psoc, false); + if (QDF_IS_STATUS_SUCCESS(qdf_status)) + policy_mgr_notice("opportunistic timer for MCC upgrade"); + goto done; + } + + /* For DBS, we want to move right away to DBS mode */ + status = policy_mgr_next_actions(psoc, session_id, action, + POLICY_MGR_UPDATE_REASON_CHANNEL_SWITCH); + if (!QDF_IS_STATUS_SUCCESS(status)) { + policy_mgr_err("no set hw mode command was issued"); + goto done; + } +done: + /* success must be returned only when a set hw mode was done */ + return status; } void policy_mgr_checkn_update_hw_mode_single_mac_mode( struct wlan_objmgr_psoc *psoc, uint8_t channel) { + uint8_t i; + struct policy_mgr_psoc_priv_obj *pm_ctx; + + pm_ctx = policy_mgr_get_context(psoc); + if (!pm_ctx) { + policy_mgr_err("Invalid Context"); + return; + } + + qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock); + for (i = 0; i < MAX_NUMBER_OF_CONC_CONNECTIONS; i++) { + if (pm_conc_connection_list[i].in_use) + if (!WLAN_REG_IS_SAME_BAND_CHANNELS(channel, + pm_conc_connection_list[i].chan)) { + qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); + policy_mgr_notice("DBS required"); + return; + } + } + qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); + + if (QDF_TIMER_STATE_RUNNING == + pm_ctx->dbs_opportunistic_timer.state) + qdf_mc_timer_stop(&pm_ctx->dbs_opportunistic_timer); + + pm_dbs_opportunistic_timer_handler((void *)psoc); } void policy_mgr_set_hw_mode_change_in_progress( @@ -201,6 +827,39 @@ QDF_STATUS policy_mgr_update_connection_info_utfw( uint32_t chain_mask, uint32_t type, uint32_t sub_type, uint32_t channelid, uint32_t mac_id) { + QDF_STATUS status = QDF_STATUS_E_FAILURE; + uint32_t conn_index = 0, found = 0; + struct policy_mgr_psoc_priv_obj *pm_ctx; + + pm_ctx = policy_mgr_get_context(psoc); + if (!pm_ctx) { + policy_mgr_err("Invalid Context"); + return status; + } + + qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock); + while (PM_CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + if (vdev_id == pm_conc_connection_list[conn_index].vdev_id) { + /* debug msg */ + found = 1; + break; + } + conn_index++; + } + qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); + if (!found) { + /* err msg */ + policy_mgr_err("can't find vdev_id %d in pm_conc_connection_list", + vdev_id); + return status; + } + policy_mgr_notice("--> updating entry at index[%d]", conn_index); + + policy_mgr_update_conc_list(psoc, conn_index, + policy_mgr_get_mode(type, sub_type), + channelid, HW_MODE_20_MHZ, + mac_id, chain_mask, 0, vdev_id, true); + return QDF_STATUS_SUCCESS; } @@ -209,12 +868,41 @@ QDF_STATUS policy_mgr_incr_connection_count_utfw(struct wlan_objmgr_psoc *psoc, uint32_t chain_mask, uint32_t type, uint32_t sub_type, uint32_t channelid, uint32_t mac_id) { + QDF_STATUS status = QDF_STATUS_E_FAILURE; + uint32_t conn_index = 0; + + conn_index = policy_mgr_get_connection_count(psoc); + if (MAX_NUMBER_OF_CONC_CONNECTIONS <= conn_index) { + /* err msg */ + policy_mgr_err("exceeded max connection limit %d", + MAX_NUMBER_OF_CONC_CONNECTIONS); + return status; + } + policy_mgr_notice("--> filling entry at index[%d]", conn_index); + + policy_mgr_update_conc_list(psoc, conn_index, + policy_mgr_get_mode(type, sub_type), + channelid, HW_MODE_20_MHZ, + mac_id, chain_mask, 0, vdev_id, true); + return QDF_STATUS_SUCCESS; } QDF_STATUS policy_mgr_decr_connection_count_utfw(struct wlan_objmgr_psoc *psoc, uint32_t del_all, uint32_t vdev_id) { + QDF_STATUS status; + + if (del_all) { + status = policy_mgr_psoc_enable(psoc); + if (!QDF_IS_STATUS_SUCCESS(status)) { + policy_mgr_err("Policy manager initialization failed"); + return QDF_STATUS_E_FAILURE; + } + } else { + policy_mgr_decr_connection_count(psoc, vdev_id); + } + return QDF_STATUS_SUCCESS; } @@ -222,20 +910,37 @@ enum policy_mgr_pcl_type policy_mgr_get_pcl_from_first_conn_table( enum policy_mgr_con_mode type, enum policy_mgr_conc_priority_mode sys_pref) { - return PM_NONE; + if ((sys_pref >= PM_MAX_CONC_PRIORITY_MODE) || + (type >= PM_MAX_NUM_OF_MODE)) + return PM_MAX_PCL_TYPE; + return first_connection_pcl_table[type][sys_pref]; } enum policy_mgr_pcl_type policy_mgr_get_pcl_from_second_conn_table( enum policy_mgr_one_connection_mode idx, enum policy_mgr_con_mode type, enum policy_mgr_conc_priority_mode sys_pref, uint8_t dbs_capable) { - return PM_NONE; + if ((idx >= PM_MAX_ONE_CONNECTION_MODE) || + (sys_pref >= PM_MAX_CONC_PRIORITY_MODE) || + (type >= PM_MAX_NUM_OF_MODE)) + return PM_MAX_PCL_TYPE; + if (dbs_capable) + return (*second_connection_pcl_dbs_table)[idx][type][sys_pref]; + else + return second_connection_pcl_nodbs_table[idx][type][sys_pref]; } enum policy_mgr_pcl_type policy_mgr_get_pcl_from_third_conn_table( enum policy_mgr_two_connection_mode idx, enum policy_mgr_con_mode type, enum policy_mgr_conc_priority_mode sys_pref, uint8_t dbs_capable) { - return PM_NONE; + if ((idx >= PM_MAX_TWO_CONNECTION_MODE) || + (sys_pref >= PM_MAX_CONC_PRIORITY_MODE) || + (type >= PM_MAX_NUM_OF_MODE)) + return PM_MAX_PCL_TYPE; + if (dbs_capable) + return (*third_connection_pcl_dbs_table)[idx][type][sys_pref]; + else + return third_connection_pcl_nodbs_table[idx][type][sys_pref]; } #endif