Procházet zdrojové kódy

qcacld-3.0: Set HW mode based on given channel in monitor mode

Current driver requires hardware mode to be changed to DBS explicitly
through private IOCTL commands before you can monitor 2.4G channel for
2x2 DBS platform.

Provide a fix which automatically switch the HW mode to DBS when
monitoring 2.4G channel 2x2 DBS platform and keep HW mode to SMM when
monitoring 5G channel.

CRs-Fixed: 2176055
Change-Id: Icc653d7b11c7e58b583e9cd23db6478f568bd172
Krunal Soni před 7 roky
rodič
revize
ed3bc8ec9f

+ 63 - 25
core/hdd/src/wlan_hdd_cfg80211.c

@@ -8366,34 +8366,12 @@ static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
 	if (0 != wlan_hdd_check_remain_on_channel(adapter))
 		hdd_warn("Remain On Channel Pending");
 
-	ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
-	if (!QDF_IS_STATUS_SUCCESS(ret))
-		hdd_err("clearing event failed");
-
-	ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
-				adapter->session_id, channel_hint,
-				SIR_UPDATE_REASON_SET_OPER_CHAN);
-	if (QDF_STATUS_E_FAILURE == ret) {
-		/* return in the failure case */
-		hdd_err("ERROR: connections update failed!!");
+	if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, channel_hint,
+				POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
+		hdd_err("Failed to change hw mode");
 		return -EINVAL;
 	}
 
-	if (QDF_STATUS_SUCCESS == ret) {
-		/*
-		 * Success is the only case for which we expect hw mode
-		 * change to take place, hence we need to wait.
-		 * For any other return value it should be a pass
-		 * through
-		 */
-		ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
-		if (!QDF_IS_STATUS_SUCCESS(ret)) {
-			hdd_err("ERROR: qdf wait for event failed!!");
-			return -EINVAL;
-		}
-
-	}
-
 	return 0;
 }
 
@@ -20998,6 +20976,60 @@ enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
 	return mode;
 }
 
+int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
+			uint8_t channel,
+			enum policy_mgr_conn_update_reason reason)
+{
+	QDF_STATUS status;
+	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+
+	ENTER();
+	if (0 != wlan_hdd_validate_context(hdd_ctx))
+		return -EINVAL;
+
+	status = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		hdd_err("clearing event failed");
+
+	status = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
+			adapter->session_id, channel, reason);
+	switch (status) {
+	case QDF_STATUS_E_FAILURE:
+		/*
+		 * QDF_STATUS_E_FAILURE indicates that some error has occured
+		 * while changing the hw mode
+		 */
+		hdd_err("ERROR: connections update failed!!");
+		return -EINVAL;
+
+	case QDF_STATUS_SUCCESS:
+		/*
+		 * QDF_STATUS_SUCCESS indicates that HW mode change has been
+		 * triggered and wait for it to finish.
+		 */
+		status = policy_mgr_wait_for_connection_update(
+						hdd_ctx->hdd_psoc);
+		if (!QDF_IS_STATUS_SUCCESS(status)) {
+			hdd_err("ERROR: qdf wait for event failed!!");
+			return -EINVAL;
+		}
+		if (QDF_MONITOR_MODE == adapter->device_mode)
+			hdd_info("Monitor mode:channel:%d (SMM->DBS)", channel);
+		break;
+
+	default:
+		/*
+		 * QDF_STATUS_E_NOSUPPORT indicates that no HW mode change is
+		 * required, so caller can proceed further.
+		 */
+		break;
+
+	}
+	EXIT();
+
+	return 0;
+}
+
 /**
  * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
  * @wiphy: Handle to struct wiphy to get handle to module context.
@@ -21064,6 +21096,11 @@ static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
 	}
 	wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
 			sec_ch, &ch_params);
+	if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, chan_num,
+				POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
+		hdd_err("Failed to change hw mode");
+		return -EINVAL;
+	}
 	status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
 						 &roam_profile);
 	if (status) {
@@ -21073,6 +21110,7 @@ static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
 		return ret;
 	}
 	EXIT();
+
 	return 0;
 }
 

+ 16 - 0
core/hdd/src/wlan_hdd_cfg80211.h

@@ -440,6 +440,22 @@ struct cfg80211_bss *
 wlan_hdd_cfg80211_inform_bss_frame(struct hdd_adapter *adapter,
 				   struct bss_description *bss_desc);
 
+/**
+ * wlan_hdd_change_hw_mode_for_given_chnl() - change HW mode for given channel
+ * @adapter: pointer to adapter
+ * @channel: given channel number
+ * @reason: reason for HW mode change is needed
+ *
+ * This API decides and sets hardware mode to DBS based on given channel.
+ * For example, some of the platforms require DBS hardware mode to operate
+ * in 2.4G channel
+ *
+ * Return: 0 for success and non-zero for failure
+ */
+int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
+				uint8_t channel,
+				enum policy_mgr_conn_update_reason reason);
+
 /**
  * hdd_rate_info_bw: an HDD internal rate bandwidth representation
  * @HDD_RATE_BW_5: 5MHz

+ 5 - 0
core/hdd/src/wlan_hdd_wext.c

@@ -10521,6 +10521,11 @@ int wlan_hdd_set_mon_chan(struct hdd_adapter *adapter, uint32_t chan,
 		hdd_err("Invalid capture channel or bandwidth for a country");
 		return -EINVAL;
 	}
+	if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, chan,
+				POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
+		hdd_err("Failed to change hw mode");
+		return -EINVAL;
+	}
 
 	status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
 					     &roam_profile);