浏览代码

qcacld-3.0: Implement ECSA Action Frame

qcacld-2.0 to qcacld-3.0 propagation

Implement:
1. Send & receive logic of ECSA action frame from P2P-CLI/GO
2. Trigger channel change on P2P GO side once ECSA action frame
   is received by,
  i) Adding CSA & ESCA IE in beacon template and updating FW to
     send it out .
  ii) Notifying supplicant of channel change for P2P GO.

This change include HDD changes

CRs-fixed: 895240
Change-Id: Iea66ddbbb8946443d5e701e3c14b2f33c6bb6bf8
Abhishek Singh 9 年之前
父节点
当前提交
1bdb157ba5

+ 92 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -624,6 +624,27 @@ static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
 #define PARAM_TDLS_FEATURE_SUPPORT \
 		QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
 
+/**
+ * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
+ * @flags: Pointer to the flags to Add channel switch flag.
+ *
+ * This Function adds Channel Switch support flag, if channel switch is
+ * supported by kernel.
+ * Return: void.
+ */
+#ifdef CHANNEL_SWITCH_SUPPORTED
+static inline void hdd_add_channel_switch_support(uint32_t *flags)
+{
+	flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+	return;
+}
+#else
+static inline void hdd_add_channel_switch_support(uint32_t *flags)
+{
+	return;
+}
+#endif
+
 /**
  * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
  * @wiphy:    WIPHY structure pointer
@@ -4956,6 +4977,8 @@ int wlan_hdd_cfg80211_init(struct device *dev,
 	wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
 #endif
 
+	hdd_add_channel_switch_support(&wiphy->flags);
+
 	EXIT();
 	return 0;
 }
@@ -10551,6 +10574,72 @@ wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
 }
 #endif
 
+#ifdef CHANNEL_SWITCH_SUPPORTED
+/**
+ * __wlan_hdd_cfg80211_channel_switch()- function to switch
+ * channel in SAP/GO
+ * @wiphy:  wiphy pointer
+ * @dev: dev pointer.
+ * @csa_params: Change channel params
+ *
+ * This function is called to switch channel in SAP/GO
+ *
+ * Return: 0 if success else return non zero
+ */
+static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
+				struct net_device *dev,
+				struct cfg80211_csa_settings *csa_params)
+{
+	hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	hdd_context_t *hdd_ctx;
+	uint8_t channel;
+	uint16_t freq;
+	int ret;
+
+	hddLog(LOG1, FL("Set Freq %d"),
+		  csa_params->chandef.chan->center_freq);
+
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	ret = wlan_hdd_validate_context(hdd_ctx);
+
+	if (0 != ret)
+		return ret;
+
+	if ((WLAN_HDD_P2P_GO != adapter->device_mode) &&
+		(WLAN_HDD_SOFTAP != adapter->device_mode))
+		return -ENOTSUPP;
+
+	freq = csa_params->chandef.chan->center_freq;
+	channel = cds_freq_to_chan(freq);
+
+	ret = hdd_softap_set_channel_change(dev, channel);
+	return ret;
+}
+
+/**
+ * wlan_hdd_cfg80211_channel_switch()- function to switch
+ * channel in SAP/GO
+ * @wiphy:  wiphy pointer
+ * @dev: dev pointer.
+ * @csa_params: Change channel params
+ *
+ * This function is called to switch channel in SAP/GO
+ *
+ * Return: 0 if success else return non zero
+ */
+static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
+				struct net_device *dev,
+				struct cfg80211_csa_settings *csa_params)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
+	cds_ssr_unprotect(__func__);
+	return ret;
+}
+#endif
+
 /**
  * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
  * translation from NL to policy manager type
@@ -10708,4 +10797,7 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
 	.set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
 #endif
 	.dump_survey = wlan_hdd_cfg80211_dump_survey,
+#ifdef CHANNEL_SWITCH_SUPPORTED
+	.channel_switch = wlan_hdd_cfg80211_channel_switch,
+#endif
 };

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

@@ -101,6 +101,11 @@
 #define MAX_CHANNEL (NUM_24GHZ_CHANNELS + NUM_5GHZ_CHANNELS)
 #define MAX_SCAN_SSID 10
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) \
+	|| defined(BACKPORTED_CHANNEL_SWITCH_PRESENT)
+#define CHANNEL_SWITCH_SUPPORTED
+#endif
+
 /**
  * typedef struct qcom_ie_age - age ie
  *

+ 13 - 4
core/hdd/src/wlan_hdd_hostapd.c

@@ -1693,6 +1693,16 @@ CDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
 		if (!pHddCtx->config->force_sap_acs)
 			wlan_hdd_cfg80211_acs_ch_select_evt(pHostapdAdapter);
 		return CDF_STATUS_SUCCESS;
+	case eSAP_ECSA_CHANGE_CHAN_IND:
+		hddLog(LOG1,
+		  FL("Channel change indication from peer for channel %d"),
+				pSapEvent->sapevt.sap_chan_cng_ind.new_chan);
+		if (hdd_softap_set_channel_change(dev,
+			 pSapEvent->sapevt.sap_chan_cng_ind.new_chan))
+			return CDF_STATUS_E_FAILURE;
+		else
+			return CDF_STATUS_SUCCESS;
+
 	default:
 		hddLog(LOG1, "SAP message is not handled");
 		goto stopbss;
@@ -1883,7 +1893,6 @@ int hdd_softap_unpack_ie(tHalHandle halHandle,
  *
  * Return: 0 for success, non zero for failure
  */
-static
 int hdd_softap_set_channel_change(struct net_device *dev, int target_channel)
 {
 	CDF_STATUS status;
@@ -1900,7 +1909,6 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel)
 	ret = wlan_hdd_validate_context(pHddCtx);
 	if (ret) {
 		hddLog(LOGE, FL("invalid HDD context"));
-		ret = -EBUSY;
 		return ret;
 	}
 
@@ -2251,9 +2259,10 @@ static __iw_softap_setparam(struct net_device *dev,
 		break;
 
 	case QCSAP_PARAM_SET_CHANNEL_CHANGE:
-		if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) {
+		if ((WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode) ||
+		   (WLAN_HDD_P2P_GO == pHostapdAdapter->device_mode)) {
 			hddLog(LOG1,
-			       "SET SAP Channel Change to new channel= %d",
+			       "SET Channel Change to new channel= %d",
 			       set_value);
 			ret = hdd_softap_set_channel_change(dev, set_value);
 		} else {

+ 3 - 0
core/hdd/src/wlan_hdd_hostapd.h

@@ -57,6 +57,9 @@ CDF_STATUS hdd_unregister_hostapd(hdd_adapter_t *pAdapter, bool rtnl_held);
 eCsrAuthType
 hdd_translate_rsn_to_csr_auth_type(uint8_t auth_suite[4]);
 
+int hdd_softap_set_channel_change(struct net_device *dev,
+					  int target_channel);
+
 eCsrEncryptionType
 hdd_translate_rsn_to_csr_encryption_type(uint8_t cipher_suite[4]);
 

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

@@ -215,6 +215,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = {
 #define WE_CLEAR_STATS                        86
 /* Private sub ioctl for starting/stopping the profiling */
 #define WE_START_FW_PROFILE                      87
+#define WE_SET_CHANNEL                        88
 
 /* Private ioctls and their sub-ioctls */
 #define WLAN_PRIV_SET_NONE_GET_INT    (SIOCIWFIRSTPRIV + 1)
@@ -4938,6 +4939,7 @@ static int __iw_setint_getnone(struct net_device *dev,
 	int set_value = value[1];
 	int ret;
 	int enable_pbm, enable_mp;
+	CDF_STATUS status;
 
 	INIT_COMPLETION(pWextState->completion_var);
 	memset(&smeConfig, 0x00, sizeof(smeConfig));
@@ -6122,6 +6124,31 @@ static int __iw_setint_getnone(struct net_device *dev,
 					set_value, DBG_CMD);
 		break;
 	}
+	case WE_SET_CHANNEL:
+	{
+		hddLog(LOG1, "Set Channel %d Session ID %d mode %d", set_value,
+				  pAdapter->sessionId, pAdapter->device_mode);
+
+		if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
+		   (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) {
+
+			status = sme_ext_change_channel(hHal,
+				   set_value, pAdapter->sessionId);
+			if (status != CDF_STATUS_SUCCESS) {
+				hddLog(LOGE,
+				  FL("Error in change channel status %d"),
+				  status);
+				ret = -EINVAL;
+			}
+		} else {
+			hddLog(LOGE,
+			  FL("change channel not supported for device mode %d"),
+			  pAdapter->device_mode);
+			ret = -EINVAL;
+		}
+		break;
+	}
+
 	default:
 	{
 		hddLog(LOGE, "%s: Invalid sub command %d", __func__,
@@ -10065,6 +10092,10 @@ static const struct iw_priv_args we_private_args[] = {
 	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
 	 0, "startProfile"},
 
+	{WE_SET_CHANNEL,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 0, "setChanChange" },
+
 	{WLAN_PRIV_SET_NONE_GET_INT,
 	 0,
 	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,