Browse Source

qcacld-3.0: Prefer QDF_OPMODE in __wlan_hdd_cfg80211_change_iface

__wlan_hdd_cfg80211_change_iface() currently uses QDF_OPMODE and
nl80211_iftype relatively interchangeably, which forces the reader to
mentally convert between the two as they go and disperses the real
conversion of one into the other throughout the code. Instead, do the
conversion from nl80211_iftype to QDF_OPMODE once up front. This way
usage can be consistent and more easily followed.

Change-Id: Ie578865c3724e4a85bd249352288afac10928bb4
CRs-Fixed: 2331969
Dustin Brown 6 years ago
parent
commit
56377e1ebe
3 changed files with 138 additions and 96 deletions
  1. 10 0
      core/hdd/inc/wlan_hdd_main.h
  2. 89 96
      core/hdd/src/wlan_hdd_cfg80211.c
  3. 39 0
      core/hdd/src/wlan_hdd_main.c

+ 10 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -2629,6 +2629,16 @@ struct hdd_adapter *hdd_get_adapter_by_iface_name(struct hdd_context *hdd_ctx,
 					     const char *iface_name);
 enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width);
 
+/**
+ * hdd_nl_to_qdf_iface_type() - map nl80211_iftype to QDF_OPMODE
+ * @nl_type: the input NL80211 interface type to map
+ * @out_qdf_type: the output, equivalent QDF operating mode
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS hdd_nl_to_qdf_iface_type(enum nl80211_iftype nl_type,
+				    enum QDF_OPMODE *out_qdf_type);
+
 /**
  * wlan_hdd_find_opclass() - Find operating class for a channel
  * @mac_handle: global MAC handle

+ 89 - 96
core/hdd/src/wlan_hdd_cfg80211.c

@@ -13001,61 +13001,56 @@ static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
 }
 
 /**
- * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
- * @ndev: pointer to net device provided by supplicant
- * @type: type of the interface, upper layer wanted to change
+ * hdd_change_adapter_mode() - change @adapter's operating mode to @new_mode
+ * @adapter: the adapter to change modes on
+ * @new_mode: the new operating mode to change to
  *
- * Upper layer provides the new interface mode that needs to be changed
- * for given net device
- *
- * Return: success or failure in terms of integer value
+ * Return: Errno
  */
-static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
-					     enum nl80211_iftype type)
+static int hdd_change_adapter_mode(struct hdd_adapter *adapter,
+				   enum QDF_OPMODE new_mode)
 {
-	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	struct net_device *netdev = adapter->dev;
 	struct hdd_config *config = hdd_ctx->config;
 	struct csr_roam_profile *roam_profile;
-	struct wireless_dev *wdev;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	hdd_enter();
 
 	if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
-		hdd_warn("ACS is in progress, don't change iface!");
+		hdd_warn("Can't change interface: ACS in progress");
 		return -EBUSY;
 	}
 
-	wdev = ndev->ieee80211_ptr;
 	hdd_stop_adapter(hdd_ctx, adapter);
 	hdd_deinit_adapter(hdd_ctx, adapter, true);
-	wdev->iftype = type;
-	/*Check for sub-string p2p to confirm its a p2p interface */
-	if (NULL != strnstr(ndev->name, "p2p", 3)) {
-		adapter->device_mode =
-			(type == NL80211_IFTYPE_STATION) ?
-			QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
-	} else if (type == NL80211_IFTYPE_ADHOC) {
-		adapter->device_mode = QDF_IBSS_MODE;
-	} else {
-		adapter->device_mode =
-			(type == NL80211_IFTYPE_STATION) ?
-			QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
-	}
+
+	/* A userspace issue leads to it sending a 'change to station mode'
+	 * request on a "p2p" device, expecting the driver do execute a 'change
+	 * to p2p-device mode' request instead. The (unfortunate) work around
+	 * here is implemented by overriding the new mode if the net_device name
+	 * starts with "p2p" and the requested mode was station.
+	 */
+	if (strnstr(netdev->name, "p2p", 3) && new_mode == QDF_STA_MODE)
+		adapter->device_mode = QDF_P2P_DEVICE_MODE;
+	else
+		adapter->device_mode = new_mode;
+
 	memset(&adapter->session, 0, sizeof(adapter->session));
-	hdd_set_station_ops(adapter->dev);
+	hdd_set_station_ops(netdev);
 
 	roam_profile = hdd_roam_profile(adapter);
 	roam_profile->pAddIEScan = adapter->scan_info.scan_add_ie.addIEdata;
-	roam_profile->nAddIEScanLength =
-		adapter->scan_info.scan_add_ie.length;
-	if (type == NL80211_IFTYPE_ADHOC) {
+	roam_profile->nAddIEScanLength = adapter->scan_info.scan_add_ie.length;
+
+	if (new_mode == QDF_IBSS_MODE) {
 		status = hdd_start_station_adapter(adapter);
 		roam_profile->BSSType = eCSR_BSS_TYPE_START_IBSS;
 		roam_profile->phyMode =
 			hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
 	}
+
 	hdd_exit();
 
 	return qdf_status_to_os_return(status);
@@ -13094,7 +13089,9 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
 	struct hdd_context *hdd_ctx;
 	int errno;
-	bool iff_up = (ndev->flags & IFF_UP);
+	bool iff_up = ndev->flags & IFF_UP;
+	enum QDF_OPMODE new_mode;
+	QDF_STATUS status;
 
 	hdd_enter();
 
@@ -13112,8 +13109,20 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 			 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
 			 adapter->session_id, type));
 
-	hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
-		  adapter->device_mode, type);
+	wdev = ndev->ieee80211_ptr;
+	if (!wdev) {
+		hdd_err("Wireless dev is NULL");
+		return -EINVAL;
+	}
+
+	status = hdd_nl_to_qdf_iface_type(type, &new_mode);
+	if (QDF_IS_STATUS_ERROR(status))
+		return qdf_status_to_os_return(status);
+
+	hdd_debug("Changing mode for '%s' from %s to %s",
+		  ndev->name,
+		  qdf_opmode_str(adapter->device_mode),
+		  qdf_opmode_str(new_mode));
 
 	errno = hdd_wlan_start_modules(hdd_ctx, false);
 	if (errno) {
@@ -13128,14 +13137,12 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 		return -EINVAL;
 	}
 
-	wdev = ndev->ieee80211_ptr;
-
 	/* Reset the current device mode bit mask */
 	policy_mgr_clear_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
 
 	if (adapter->device_mode != QDF_P2P_DEVICE_MODE ||
-	    type != NL80211_IFTYPE_STATION) {
-		hdd_debug("Teardown tdls links and disable tdls in FW as new interface is coming up");
+	    new_mode != QDF_STA_MODE) {
+		hdd_debug("Disable tdls; new interface is coming up");
 		hdd_notify_teardown_tdls_links(adapter->vdev);
 	}
 
@@ -13143,38 +13150,31 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 	    adapter->device_mode == QDF_P2P_CLIENT_MODE ||
 	    adapter->device_mode == QDF_P2P_DEVICE_MODE ||
 	    adapter->device_mode == QDF_IBSS_MODE) {
-		switch (type) {
-		case NL80211_IFTYPE_STATION:
-		case NL80211_IFTYPE_P2P_CLIENT:
-		case NL80211_IFTYPE_ADHOC:
-			if (type == NL80211_IFTYPE_ADHOC) {
+		switch (new_mode) {
+		case QDF_STA_MODE:
+		case QDF_P2P_CLIENT_MODE:
+		case QDF_IBSS_MODE:
+			if (new_mode == QDF_IBSS_MODE)
 				hdd_deregister_tx_flow_control(adapter);
-				hdd_debug("Setting interface Type to ADHOC");
-			}
-			errno = wlan_hdd_change_client_iface_to_new_mode(ndev,
-									 type);
-			if (errno) {
-				hdd_err("Failed to change iface to new mode:%d; errno:%d",
-					type, errno);
+
+			errno = hdd_change_adapter_mode(adapter, new_mode);
+			if (errno)
 				return errno;
-			}
+
 			if (iff_up) {
-				if (hdd_start_adapter(adapter)) {
-					hdd_err("Failed to start adapter: %d",
-						adapter->device_mode);
+				errno = hdd_start_adapter(adapter);
+				if (errno) {
+					hdd_err("Failed to start adapter");
 					return -EINVAL;
 				}
 			}
+
+			wdev->iftype = type;
+
 			goto done;
-		case NL80211_IFTYPE_AP:
-		case NL80211_IFTYPE_P2P_GO:
-			hdd_debug("Setting interface Type to %s",
-			       (type ==
-				NL80211_IFTYPE_AP) ? "SoftAP" :
-			       "P2pGo");
-
-			/* Cancel any remain on channel for GO mode */
-			if (type == NL80211_IFTYPE_P2P_GO) {
+		case QDF_SAP_MODE:
+		case QDF_P2P_GO_MODE:
+			if (new_mode == QDF_P2P_GO_MODE) {
 				wlan_hdd_cancel_existing_remain_on_channel
 					(adapter);
 			}
@@ -13182,12 +13182,7 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 			hdd_stop_adapter(hdd_ctx, adapter);
 			hdd_deinit_adapter(hdd_ctx, adapter, true);
 			memset(&adapter->session, 0, sizeof(adapter->session));
-			adapter->device_mode = type == NL80211_IFTYPE_AP ?
-				QDF_SAP_MODE : QDF_P2P_GO_MODE;
-
-			/*
-			 * Fw will take care incase of concurrency
-			 */
+			adapter->device_mode = new_mode;
 
 			if (adapter->device_mode == QDF_SAP_MODE &&
 			    hdd_ctx->config->apRandomBssidEnabled) {
@@ -13210,61 +13205,59 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 			hdd_set_ap_ops(adapter->dev);
 
 			if (iff_up) {
-				if (hdd_start_adapter(adapter)) {
-					hdd_err("Failed to start adapter: %d",
-						adapter->device_mode);
-					return -EINVAL;
+				errno = hdd_start_adapter(adapter);
+				if (errno) {
+					hdd_err("Failed to start adapter");
+					return errno;
 				}
 			}
 
-			/* Interface type changed update in wiphy structure */
-			if (wdev) {
-				wdev->iftype = type;
-			} else {
-				hdd_err("Wireless dev is NULL");
-				return -EINVAL;
-			}
+			wdev->iftype = type;
 
 			goto done;
 		default:
-			hdd_err("Unsupported interface type: %d", type);
+			hdd_err("Changing to device mode '%s' is not supported",
+				qdf_opmode_str(new_mode));
 			return -EOPNOTSUPP;
 		}
 	} else if (adapter->device_mode == QDF_SAP_MODE ||
 		   adapter->device_mode == QDF_P2P_GO_MODE) {
-		switch (type) {
-		case NL80211_IFTYPE_STATION:
-		case NL80211_IFTYPE_P2P_CLIENT:
-		case NL80211_IFTYPE_ADHOC:
-			errno = wlan_hdd_change_client_iface_to_new_mode(ndev,
-									 type);
+		switch (new_mode) {
+		case QDF_STA_MODE:
+		case QDF_P2P_CLIENT_MODE:
+		case QDF_IBSS_MODE:
+			errno = hdd_change_adapter_mode(adapter, new_mode);
 			if (errno)
 				return errno;
 
 			if (iff_up) {
-				if (hdd_start_adapter(adapter)) {
-					hdd_err("Failed to start adapter: %d",
-						adapter->device_mode);
+				errno = hdd_start_adapter(adapter);
+				if (errno) {
+					hdd_err("Failed to start adapter");
 					return -EINVAL;
 				}
 			}
-			goto done;
 
-		case NL80211_IFTYPE_AP:
-		case NL80211_IFTYPE_P2P_GO:
 			wdev->iftype = type;
-			adapter->device_mode = type == NL80211_IFTYPE_AP ?
-				QDF_SAP_MODE : QDF_P2P_GO_MODE;
+
 			goto done;
+		case QDF_SAP_MODE:
+		case QDF_P2P_GO_MODE:
+			wdev->iftype = type;
+			adapter->device_mode = new_mode;
 
+			goto done;
 		default:
-			hdd_err("Unsupported interface type: %d", type);
+			hdd_err("Changing to device mode '%s' is not supported",
+				qdf_opmode_str(new_mode));
 			return -EOPNOTSUPP;
 		}
 	} else {
-		hdd_err("Unsupported device mode: %d", adapter->device_mode);
+		hdd_err("Changing from device mode '%s' is not supported",
+			qdf_opmode_str(adapter->device_mode));
 		return -EOPNOTSUPP;
 	}
+
 done:
 	/* Set bitmask based on updated value */
 	policy_mgr_set_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);

+ 39 - 0
core/hdd/src/wlan_hdd_main.c

@@ -802,6 +802,45 @@ enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
 	}
 }
 
+QDF_STATUS hdd_nl_to_qdf_iface_type(enum nl80211_iftype nl_type,
+				    enum QDF_OPMODE *out_qdf_type)
+{
+	switch (nl_type) {
+	case NL80211_IFTYPE_ADHOC:
+		*out_qdf_type = QDF_IBSS_MODE;
+		break;
+	case NL80211_IFTYPE_AP:
+		*out_qdf_type = QDF_SAP_MODE;
+		break;
+	case NL80211_IFTYPE_MONITOR:
+		*out_qdf_type = QDF_MONITOR_MODE;
+		break;
+	case NL80211_IFTYPE_OCB:
+		*out_qdf_type = QDF_OCB_MODE;
+		break;
+	case NL80211_IFTYPE_P2P_CLIENT:
+		*out_qdf_type = QDF_P2P_CLIENT_MODE;
+		break;
+	case NL80211_IFTYPE_P2P_DEVICE:
+		*out_qdf_type = QDF_P2P_DEVICE_MODE;
+		break;
+	case NL80211_IFTYPE_P2P_GO:
+		*out_qdf_type = QDF_P2P_GO_MODE;
+		break;
+	case NL80211_IFTYPE_STATION:
+		*out_qdf_type = QDF_STA_MODE;
+		break;
+	case NL80211_IFTYPE_WDS:
+		*out_qdf_type = QDF_WDS_MODE;
+		break;
+	default:
+		hdd_err("Invalid nl80211 interface type %d", nl_type);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 uint8_t wlan_hdd_find_opclass(mac_handle_t mac_handle, uint8_t channel,
 			      uint8_t bw_offset)
 {