Browse Source

qcacld-3.0: Set hw mode during channel switch in STA/P2P-CLI case

Set the hw mode, if needed, during channel switch in STA and
P2P-CLI scenario. The STA/P2P-CLI on receiving the channel change
event may need to do a hw mode change to get the best out of the
hw capabilities.

e.g.1, In a STA+SAP concurrency, the STA and SAP are doing SCC on
channel 6. When the STA interface receives a channel event for
channel 36, it is better the driver moves to a DBS scenario.

e.g.2, In a STA+SAP concurrency, the STA is on channel 6 and the
SAP is on channel 36. When the STA interface receives a channel
event for channel 36, it is better the driver moves from a DBS
scenario to a SCC scenario.

For MCC upgrade, the following steps are taken
1. Opportunistic timer is started
2. vdev restart is initiated on the new channel
3. PM will check if MCC upgrade can be done on timer expiry

For DBS downgrade, the following steps are taken
1. PM will initiate HW mode change to DBS right away
2. vdev restart is initiated on the new channel

Change-Id: I202842bf28c3117e8cc91954cdfd3b39a0062f4e
CRs-Fixed: 972184
Chandrasekaran, Manishekar 9 years ago
parent
commit
5c19dc5f8e

+ 1 - 0
core/cds/inc/cds_concurrency.h

@@ -656,4 +656,5 @@ QDF_STATUS qdf_wait_for_connection_update(void);
 QDF_STATUS qdf_reset_connection_update(void);
 QDF_STATUS qdf_set_connection_update(void);
 QDF_STATUS qdf_init_connection_update(void);
+QDF_STATUS cds_stop_start_opportunistic_timer(void);
 #endif /* __CDS_CONCURRENCY_H */

+ 34 - 2
core/cds/src/cds_concurrency.c

@@ -3614,8 +3614,8 @@ enum cds_conc_next_action cds_need_opportunistic_upgrade(void)
 #ifdef QCA_WIFI_3_0_EMU
 	/* For M2M emulation only: if we have a connection on 2.4, stay in DBS */
 	if (hdd_ctx->config->enable_m2m_limitation &&
-		CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) {
-		cds_debug("For emulation only: connection on 2.4, stay in DBS");
+	    CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) {
+		cds_debug("emulation only: conn on 2.4, stay in DBS");
 		goto done;
 	}
 #endif
@@ -7983,3 +7983,35 @@ enum cds_conc_next_action cds_get_pref_hw_mode_for_chan(uint32_t vdev_id,
 		return CDS_NOP;
 	}
 }
+
+/**
+ * cds_stop_start_opportunistic_timer() - Start and stop the opportunistic timer
+ *
+ * Stops and starts the opportunistic timer for DBS_OPPORTUNISTIC_TIME seconds
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS cds_stop_start_opportunistic_timer(void)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	p_cds_contextType cds_ctx;
+
+	cds_ctx = cds_get_global_context();
+	if (!cds_ctx) {
+		cds_err("Invalid CDS context");
+		return status;
+	}
+
+	qdf_mc_timer_stop(&cds_ctx->dbs_opportunistic_timer);
+
+	status = qdf_mc_timer_start(
+			&cds_ctx->dbs_opportunistic_timer,
+			DBS_OPPORTUNISTIC_TIME * 1000);
+
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		cds_err("failed to start opportunistic timer");
+		return status;
+	}
+
+	return status;
+}

+ 37 - 0
core/mac/inc/sir_api.h

@@ -105,6 +105,7 @@ typedef uint8_t tSirVersionString[SIR_VERSION_STRING_LEN];
  * @CDS_UPDATE_REASON_OPPORTUNISTIC: Opportunistic HW mode update
  * @CDS_UPDATE_REASON_NSS_UPDATE: NSS update
  * @CDS_UPDATE_REASON_CHANNEL_SWITCH: Channel switch
+ * @CDS_UPDATE_REASON_CHANNEL_SWITCH_STA: Channel switch for STA
  */
 enum cds_conn_update_reason {
 	CDS_UPDATE_REASON_SET_OPER_CHAN,
@@ -116,6 +117,7 @@ enum cds_conn_update_reason {
 	CDS_UPDATE_REASON_OPPORTUNISTIC,
 	CDS_UPDATE_REASON_NSS_UPDATE,
 	CDS_UPDATE_REASON_CHANNEL_SWITCH,
+	CDS_UPDATE_REASON_CHANNEL_SWITCH_STA,
 };
 
 typedef enum {
@@ -5518,4 +5520,39 @@ struct egap_conf_params {
 	uint32_t   wait_time;
 	uint32_t   flags;
 };
+
+/**
+ * struct csa_offload_params - CSA offload request parameters
+ * @channel: channel
+ * @switch_mode: switch mode
+ * @sec_chan_offset: second channel offset
+ * @new_ch_width: new channel width
+ * @new_ch_freq_seg1: channel center freq 1
+ * @new_ch_freq_seg2: channel center freq 2
+ * @ies_present_flag: IE present flag
+ */
+struct csa_offload_params {
+	uint8_t channel;
+	uint8_t switch_mode;
+	uint8_t sec_chan_offset;
+	uint8_t new_ch_width;
+	uint8_t new_op_class;
+	uint8_t new_ch_freq_seg1;
+	uint8_t new_ch_freq_seg2;
+	uint32_t ies_present_flag;
+	tSirMacAddr bssId;
+};
+
+/**
+ * struct sir_saved_csa_params - saved csa offload params
+ * @message_type: Message type
+ * @length: Message length
+ * @session_id: Session id
+ */
+struct sir_saved_csa_params {
+	uint16_t message_type;
+	uint16_t length;
+	uint32_t session_id;
+};
+
 #endif /* __SIR_API_H */

+ 1 - 4
core/mac/src/include/sir_params.h

@@ -642,10 +642,7 @@ typedef struct sSirMbMsgP2p {
 #define SIR_LIM_SCH_CLEAN_MSG              (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xB)
 /* Message from ISR upon Radar Detection */
 #define SIR_LIM_RADAR_DETECT_IND           (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xC)
-
-/* /////////////////////////////////// */
-/* message id Available */
-/* ////////////////////////////////// */
+#define SIR_LIM_CSA_POST_HW_MODE_CHANGE    (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xD)
 
 /* Message from Hal to send out a DEL-TS indication */
 #define SIR_LIM_DEL_TS_IND                  (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xE)

+ 1 - 0
core/mac/src/pe/include/lim_session.h

@@ -471,6 +471,7 @@ typedef struct sPESession       /* Added to Support BT-AMP */
 	uint8_t country_info_present;
 	uint8_t nss;
 	bool add_bss_failed;
+	struct csa_offload_params saved_csa_params;
 } tPESession, *tpPESession;
 
 /*-------------------------------------------------------------------------

+ 209 - 1
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -62,6 +62,7 @@
 #include "qdf_types.h"
 #include "cds_packet.h"
 #include "qdf_mem.h"
+#include "cds_concurrency.h"
 
 void lim_log_session_states(tpAniSirGlobal pMac);
 static void lim_process_normal_hdd_msg(tpAniSirGlobal mac_ctx,
@@ -1146,6 +1147,210 @@ void lim_process_oem_data_rsp(tpAniSirGlobal pMac, uint32_t *body)
 
 #endif
 
+/**
+ * lim_handle_hw_mode_change_on_csa() - Do HW mode change on CSA for STA mode
+ * @mac_ctx: Global MAC context
+ * @msg: Received message
+ *
+ * Checks if hw mode change is required for the new channel.
+ * If MCC upgrade is required, this function will start the opportunistic
+ * timer and the caller will invoke the other APIs to perform vdev restart on
+ * the new channel.
+ *
+ * If DBS downgrade is required, this function will initiate the hw mode
+ * change and vdev restart will happen on the new channel after getting hw
+ * mode response
+ *
+ * Return: QDF_STATUS_SUCCESS if processing of csa params (and hence vdev
+ * restart) needs to happen or if no hw mode change is required,
+ * QDF_STATUS_E_FAILURE otherwise.
+ */
+static QDF_STATUS lim_handle_hw_mode_change_on_csa(tpAniSirGlobal mac_ctx,
+							tpSirMsgQ msg)
+{
+	tpPESession session_entry;
+	struct csa_offload_params *csa_params =
+				(struct csa_offload_params *) (msg->bodyptr);
+	tpDphHashNode sta_ds = NULL;
+	uint8_t session_id;
+	uint16_t aid = 0;
+	enum cds_conc_next_action action;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	lim_log(mac_ctx, LOG1, FL("handle hw mode change for csa"));
+
+	if (!csa_params) {
+		lim_log(mac_ctx, LOGE, FL("limMsgQ body ptr is NULL"));
+		/* qdf_mem_free() can handle NULL values */
+		goto err;
+	}
+
+	session_entry = pe_find_session_by_bssid(mac_ctx,
+					csa_params->bssId, &session_id);
+	if (!session_entry) {
+		lim_log(mac_ctx, LOGE, FL("Session does not exist"));
+		goto err;
+	}
+
+	sta_ds = dph_lookup_hash_entry(mac_ctx, session_entry->bssId, &aid,
+			&session_entry->dph.dphHashTable);
+
+	if (!sta_ds) {
+		lim_log(mac_ctx, LOGE, FL("sta_ds does not exist"));
+		goto err;
+	}
+
+	/* Since all the write to the policy manager table happens in the
+	 * MC thread context and this channel change event is also processed
+	 * in the MC thread context, explicit lock/unlock of qdf_conc_list_lock
+	 * is not done here
+	 */
+	action = cds_get_pref_hw_mode_for_chan(session_entry->smeSessionId,
+				csa_params->channel);
+
+	if (action == CDS_NOP) {
+		lim_log(mac_ctx, LOG1, FL("no need for hw mode change"));
+		/* Proceed with processing csa params. So, not freeing it */
+		return QDF_STATUS_SUCCESS;
+	}
+
+	lim_log(mac_ctx, LOG1, FL("session:%d action:%d"),
+		session_entry->smeSessionId, action);
+
+	/*     1. Start opportunistic timer
+	 *     2. Do vdev restart on the new channel (by the caller)
+	 *     3. PM will check if MCC upgrade can be done after timer expiry
+	 */
+	if (action == CDS_MCC_UPGRADE) {
+		status = cds_stop_start_opportunistic_timer();
+		if (QDF_IS_STATUS_SUCCESS(status))
+			lim_log(mac_ctx, LOG1,
+				FL("opportunistic timer for MCC upgrade"));
+
+		/* After opportunistic timer is triggered, we can go ahead
+		 * with processing the csa params. So, not freeing the memory
+		 * through 'err' label.
+		 */
+		return QDF_STATUS_SUCCESS;
+	}
+
+	/*     CDS_DBS_DOWNGRADE:
+	 *     1. PM will initiate HW mode change to DBS rightaway
+	 *     2. Do vdev restart on the new channel (on getting hw mode resp)
+	 */
+	status = cds_next_actions(session_entry->smeSessionId, action,
+				CDS_UPDATE_REASON_CHANNEL_SWITCH_STA);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		lim_log(mac_ctx, LOGE, FL("no set hw mode command was issued"));
+		/* Proceed with processing csa params. So, not freeing it */
+		return QDF_STATUS_SUCCESS;
+	} else {
+		/* Save the csa params to be used after DBS downgrade */
+		qdf_mem_copy(&session_entry->saved_csa_params, csa_params,
+				sizeof(session_entry->saved_csa_params));
+
+		lim_log(mac_ctx, LOG1,
+			FL("saved csa params for dbs downgrade for %pM"),
+			session_entry->saved_csa_params.bssId);
+
+		/* Returning error so that csa params are not processed here */
+		status = QDF_STATUS_E_FAILURE;
+	}
+
+err:
+	qdf_mem_free(csa_params);
+	return status;
+}
+
+/**
+ * lim_handle_hw_mode_change_on_csa_event() - Handle hw mode change on csa
+ * @mac_ctx: Pointer to the Global Mac Context
+ * @msg: Received message
+ *
+ * Checks if a hw mode change is required for the received csa event. Processes
+ * csa params and do vdev restart immediately if the there is no need for a hw
+ * mode change or if MCC upgrade is required
+ *
+ * Return: None
+ */
+static void lim_handle_hw_mode_change_on_csa_event(tpAniSirGlobal mac_ctx,
+							tpSirMsgQ msg)
+{
+	QDF_STATUS qdf_status;
+
+	lim_log(mac_ctx, LOG1, FL("lim received csa offload event"));
+	if (mac_ctx->policy_manager_enabled &&
+			wma_is_hw_dbs_capable() == true) {
+		/* Check if a hw mode change is required */
+		qdf_status = lim_handle_hw_mode_change_on_csa(mac_ctx,
+				msg);
+		/* Process csa params and do vdev restart immediately if
+		 * there is no need for a hw mode change or if MCC upgrade is
+		 * required.
+		 */
+		if (QDF_IS_STATUS_SUCCESS(qdf_status))
+			lim_handle_csa_offload_msg(mac_ctx, msg);
+	} else {
+		lim_handle_csa_offload_msg(mac_ctx, msg);
+	}
+}
+
+/**
+ * lim_handle_csa_event_post_dbs_downgrade() - Process csa event post dbs
+ * downgrade
+ * @mac_ctx: Pointer to the Global Mac Context
+ * @msg: Received message
+ *
+ * Process the csa event to do vdev restart on the new channel after the dbs
+ * downgrade. If there was a DBS downgrade as part of the event
+ * WMA_CSA_OFFLOAD_EVENT, SIR_LIM_CSA_POST_HW_MODE_CHANGE will be received after
+ * receiving the set hw mode response, where this processing will happen.
+ *
+ * Return: None
+ */
+static void lim_handle_csa_event_post_dbs_downgrade(tpAniSirGlobal mac_ctx,
+							tpSirMsgQ msg)
+{
+	tSirMsgQ csa_msg;
+	tpPESession session_entry;
+
+	struct sir_saved_csa_params *buf =
+		(struct sir_saved_csa_params *)msg->bodyptr;
+
+	/* Null check for 'msg' already done before coming here in the caller */
+
+	session_entry = pe_find_session_by_sme_session_id(mac_ctx,
+				buf->session_id);
+	if (!session_entry) {
+		lim_log(mac_ctx, LOGE, FL("Invalid session id:%d"),
+			buf->session_id);
+		return;
+	}
+
+	lim_log(mac_ctx, LOG1,
+			FL("received csa offload event post hw change for %pM"),
+			session_entry->saved_csa_params.bssId);
+
+	csa_msg.bodyptr = qdf_mem_malloc(
+			sizeof(struct csa_offload_params));
+	if (!csa_msg.bodyptr) {
+		lim_log(mac_ctx, LOGE, FL("malloc failed for csa msg"));
+		goto clean_msg_body;
+	}
+
+	qdf_mem_copy((void *)csa_msg.bodyptr,
+			(void *)&session_entry->saved_csa_params,
+			sizeof(struct csa_offload_params));
+	/* If there was a DBS downgrade as part of the event
+	 * WMA_CSA_OFFLOAD_EVENT, SIR_LIM_CSA_POST_HW_MODE_CHANGE will
+	 * be received after receiving the set hw mode response.
+	 */
+	lim_handle_csa_offload_msg(mac_ctx, &csa_msg);
+clean_msg_body:
+	if (msg->bodyptr)
+		qdf_mem_free(msg->bodyptr);
+}
+
 /**
  * lim_process_messages() - Process messages from upper layers.
  *
@@ -1605,7 +1810,10 @@ void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
 		lim_handle_delete_bss_rsp(mac_ctx, msg);
 		break;
 	case WMA_CSA_OFFLOAD_EVENT:
-		lim_handle_csa_offload_msg(mac_ctx, msg);
+		lim_handle_hw_mode_change_on_csa_event(mac_ctx, msg);
+		break;
+	case SIR_LIM_CSA_POST_HW_MODE_CHANGE:
+		lim_handle_csa_event_post_dbs_downgrade(mac_ctx, msg);
 		break;
 	case WMA_SET_BSSKEY_RSP:
 	case WMA_SET_STA_BCASTKEY_RSP:

+ 7 - 3
core/mac/src/pe/lim/lim_send_sme_rsp_messages.c

@@ -2016,7 +2016,8 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
 {
 	tpPESession session_entry;
 	tSirMsgQ mmh_msg;
-	tpCSAOffloadParams csa_params = (tpCSAOffloadParams) (msg->bodyptr);
+	struct csa_offload_params *csa_params =
+				(struct csa_offload_params *) (msg->bodyptr);
 	tpSmeCsaOffloadInd csa_offload_ind;
 	tpDphHashNode sta_ds = NULL;
 	uint8_t session_id;
@@ -2027,6 +2028,8 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
 	tLimWiderBWChannelSwitchInfo *chnl_switch_info = NULL;
 	tLimChannelSwitchInfo *lim_ch_switch = NULL;
 
+	lim_log(mac_ctx, LOG1, FL("handle csa offload msg"));
+
 	if (!csa_params) {
 		lim_log(mac_ctx, LOGE, FL("limMsgQ body ptr is NULL"));
 		return;
@@ -2037,7 +2040,8 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
 			csa_params->bssId, &session_id);
 	if (!session_entry) {
 		lim_log(mac_ctx, LOGE,
-			FL("Session does not exist"));
+			FL("Session does not exists for %pM"),
+				csa_params->bssId);
 		goto err;
 	}
 
@@ -2059,7 +2063,7 @@ void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
 
 		lim_ch_switch = &session_entry->gLimChannelSwitch;
 		session_entry->gLimChannelSwitch.switchMode =
-			csa_params->switchmode;
+			csa_params->switch_mode;
 		/* timer already started by firmware, switch immediately */
 		session_entry->gLimChannelSwitch.switchCount = 0;
 		session_entry->gLimChannelSwitch.primaryChannel =

+ 1 - 0
core/sme/inc/sme_internal.h

@@ -220,6 +220,7 @@ typedef struct tagSmeStruct {
 	ocb_callback dcc_stats_event_callback;
 	sme_set_thermal_level_callback set_thermal_level_cb;
 	void *saved_scan_cmd;
+	struct csa_offload_params saved_csa_params;
 } tSmeStruct, *tpSmeStruct;
 
 #endif /* #if !defined( __SMEINTERNAL_H ) */

+ 23 - 0
core/sme/src/common/sme_api.c

@@ -156,6 +156,7 @@ static QDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg)
 	enum cds_conn_update_reason reason;
 	tSmeCmd *saved_cmd;
 	tCsrRoamInfo roam_info = {0};
+	QDF_STATUS status;
 
 	sms_log(mac, LOG1, FL("%s"), __func__);
 	param = (struct sir_set_hw_mode_resp *)msg;
@@ -234,6 +235,28 @@ static QDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg)
 					&roam_info, 0,
 					eCSR_ROAM_STATUS_UPDATE_HW_MODE,
 					eCSR_ROAM_RESULT_UPDATE_HW_MODE);
+		} else if (reason == CDS_UPDATE_REASON_CHANNEL_SWITCH_STA) {
+			struct sir_saved_csa_params *msg;
+
+			sms_log(mac, LOG1, FL("process channel switch sta"));
+			msg = qdf_mem_malloc(sizeof(*msg));
+			if (!msg) {
+				sms_log(mac, LOGE,
+					FL("memory alloc fail for csa "));
+				goto end;
+			}
+
+			msg->message_type = SIR_LIM_CSA_POST_HW_MODE_CHANGE;
+			msg->length = sizeof(*msg);
+			msg->session_id = command->u.set_hw_mode_cmd.session_id;
+
+			status = cds_send_mb_message_to_mac(msg);
+			if (!QDF_IS_STATUS_SUCCESS(status))
+				sms_log(mac, LOGE,
+					FL("failed to process csa params"));
+			else
+				sms_log(mac, LOG1,
+					FL("csa after hw mode change"));
 		} else {
 			sms_log(mac, LOGE,
 			      FL("Calling HDD callback for HW mode response"));

+ 0 - 22
core/wma/inc/wma_if.h

@@ -921,28 +921,6 @@ typedef struct {
 	uint8_t nss;
 } tSwitchChannelParams, *tpSwitchChannelParams;
 
-/**
- * struct tpCSAOffloadParams - CSA offload request parameters
- * @channel: channel
- * @switchmode: switch mode
- * @sec_chan_offset: second channel offset
- * @new_ch_width: new channel width
- * @new_ch_freq_seg1: channel center freq 1
- * @new_ch_freq_seg2: channel center freq 2
- * @ies_present_flag: IE present flag
- */
-typedef struct CSAOffloadParams {
-	uint8_t channel;
-	uint8_t switchmode;
-	uint8_t sec_chan_offset;
-	uint8_t new_ch_width;
-	uint8_t new_op_class;
-	uint8_t new_ch_freq_seg1;
-	uint8_t new_ch_freq_seg2;
-	uint32_t ies_present_flag;
-	tSirMacAddr bssId;
-} *tpCSAOffloadParams, tCSAOffloadParams;
-
 typedef void (*tpSetLinkStateCallback)(tpAniSirGlobal pMac, void *msgParam,
 		bool status);
 

+ 3 - 3
core/wma/src/wma_features.c

@@ -1143,7 +1143,7 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
 	uint8_t vdev_id = 0;
 	uint8_t cur_chan = 0;
 	struct ieee80211_channelswitch_ie *csa_ie;
-	tpCSAOffloadParams csa_offload_event;
+	struct csa_offload_params *csa_offload_event;
 	struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
 	struct ieee80211_ie_wide_bw_switch *wb_ie;
 	struct wma_txrx_node *intr = wma->interfaces;
@@ -1176,12 +1176,12 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
 		csa_ie = (struct ieee80211_channelswitch_ie *)
 						(&csa_event->csa_ie[0]);
 		csa_offload_event->channel = csa_ie->newchannel;
-		csa_offload_event->switchmode = csa_ie->switchmode;
+		csa_offload_event->switch_mode = csa_ie->switchmode;
 	} else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
 		xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
 						(&csa_event->xcsa_ie[0]);
 		csa_offload_event->channel = xcsa_ie->newchannel;
-		csa_offload_event->switchmode = xcsa_ie->switchmode;
+		csa_offload_event->switch_mode = xcsa_ie->switchmode;
 		csa_offload_event->new_op_class = xcsa_ie->newClass;
 	} else {
 		WMA_LOGE("CSA Event error: No CSA IE present");