Просмотр исходного кода

qcacld-3.0: Fix a peer phy mode update discrepancy

In function wma_process_update_opmode, interface phy mode
is used to update peer phy mode to FW, which will cause
a mis-behavior in FW during channel switch.

Use peer phy mode, instead of interface phy mode when
driver is sending WMI_PEER_PHYMODE cmd to FW.

Also to make peer phy mode population to FW possible,
add the following APIs to do host to FW phy mode
conversion:

	wma_host_to_fw_phymode_160
	wma_host_to_fw_phymode_11ax
	wma_host_to_fw_phymode

Fix some kernel-doc discrepancies for the following
existing functions:

	wma_fw_to_host_phymode
	wma_fw_to_host_phymode_160
	wma_fw_to_host_phymode_11ax

Change-Id: I6184a1735d37f648763b149795ac7930bce45346
CRs-Fixed: 2497684
wadesong 5 лет назад
Родитель
Сommit
d3f8d3a927
1 измененных файлов с 139 добавлено и 11 удалено
  1. 139 11
      core/wma/src/wma_mgmt.c

+ 139 - 11
core/wma/src/wma_mgmt.c

@@ -1062,10 +1062,10 @@ static void wma_mask_tx_ht_rate(tp_wma_handle wma, uint8_t *mcs_set)
 #if SUPPORT_11AX
 /**
  * wma_fw_to_host_phymode_11ax() - convert fw to host phymode for 11ax phymodes
- * @wma:     wma handle
  * @phymode: phymode to convert
  *
- * Return: None
+ * Return: one of the 11ax values defined in enum wlan_phymode;
+ *         or WLAN_PHYMODE_AUTO if the input is not an 11ax phymode
  */
 static enum wlan_phymode wma_fw_to_host_phymode_11ax(WLAN_PHY_MODE phymode)
 {
@@ -1100,10 +1100,10 @@ static enum wlan_phymode wma_fw_to_host_phymode_11ax(WLAN_PHY_MODE phymode)
 /**
  * wma_fw_to_host_phymode_160() - convert fw to host phymode for 160 mhz
  * phymodes
- * @wma:     wma handle
  * @phymode: phymode to convert
  *
- * Return: None
+ * Return: one of the 160 mhz values defined in enum wlan_phymode;
+ *         or WLAN_PHYMODE_AUTO if the input is not a 160 mhz phymode
  */
 static enum wlan_phymode wma_fw_to_host_phymode_160(WLAN_PHY_MODE phymode)
 {
@@ -1124,10 +1124,10 @@ static enum wlan_phymode wma_fw_to_host_phymode_160(WLAN_PHY_MODE phymode)
 #endif
 /**
  * wma_fw_to_host_phymode() - convert fw to host phymode
- * @wma:     wma handle
  * @phymode: phymode to convert
  *
- * Return: None
+ * Return: one of the values defined in enum wlan_phymode;
+ *         or WLAN_PHYMODE_AUTO if the conversion fails
  */
 static enum wlan_phymode wma_fw_to_host_phymode(WLAN_PHY_MODE phymode)
 {
@@ -1169,6 +1169,104 @@ static enum wlan_phymode wma_fw_to_host_phymode(WLAN_PHY_MODE phymode)
 	}
 }
 
+#ifdef CONFIG_160MHZ_SUPPORT
+/**
+ * wma_host_to_fw_phymode_160() - convert host to fw phymode for 160 mhz
+ * @host_phymode: phymode to convert
+ *
+ * Return: one of the 160 mhz values defined in enum WLAN_PHY_MODE;
+ *         or MODE_UNKNOWN if the input is not a 160 mhz phymode
+ */
+static WLAN_PHY_MODE wma_host_to_fw_phymode_160(enum wlan_phymode host_phymode)
+{
+	switch (host_phymode) {
+	case WLAN_PHYMODE_11AC_VHT80_80:
+		return MODE_11AC_VHT80_80;
+	case WLAN_PHYMODE_11AC_VHT160:
+		return MODE_11AC_VHT160;
+	default:
+		return MODE_UNKNOWN;
+	}
+}
+#else
+static WLAN_PHY_MODE wma_host_to_fw_phymode_160(enum wlan_phymode host_phymode)
+{
+	return MODE_UNKNOWN;
+}
+#endif
+
+#if SUPPORT_11AX
+/**
+ * wma_host_to_fw_phymode_11ax() - convert host to fw phymode for 11ax phymode
+ * @host_phymode: phymode to convert
+ *
+ * Return: one of the 11ax values defined in enum WLAN_PHY_MODE;
+ *         or MODE_UNKNOWN if the input is not an 11ax phymode
+ */
+static WLAN_PHY_MODE wma_host_to_fw_phymode_11ax(enum wlan_phymode host_phymode)
+{
+	switch (host_phymode) {
+	case WLAN_PHYMODE_11AXA_HE20:
+		return MODE_11AX_HE20;
+	case WLAN_PHYMODE_11AXA_HE40:
+		return MODE_11AX_HE40;
+	case WLAN_PHYMODE_11AXA_HE80:
+		return MODE_11AX_HE80;
+	case WLAN_PHYMODE_11AXA_HE80_80:
+		return MODE_11AX_HE80_80;
+	case WLAN_PHYMODE_11AXA_HE160:
+		return MODE_11AX_HE160;
+	default:
+		return MODE_UNKNOWN;
+	}
+}
+#else
+static WLAN_PHY_MODE wma_host_to_fw_phymode_11ax(enum wlan_phymode host_phymode)
+{
+	return MODE_UNKNOWN;
+}
+#endif
+
+/**
+ * wma_host_to_fw_phymode() - convert host to fw phymode
+ * @host_phymode: phymode to convert
+ *
+ * Return: one of the values defined in enum WLAN_PHY_MODE;
+ *         or MODE_UNKNOWN if the conversion fails
+ */
+static WLAN_PHY_MODE wma_host_to_fw_phymode(enum wlan_phymode host_phymode)
+{
+	WLAN_PHY_MODE fw_phymode;
+
+	switch (host_phymode) {
+	case WLAN_PHYMODE_11A:
+		return MODE_11A;
+	case WLAN_PHYMODE_11G:
+		return MODE_11G;
+	case WLAN_PHYMODE_11B:
+		return MODE_11B;
+	case WLAN_PHYMODE_11NA_HT20:
+		return MODE_11NA_HT20;
+	case WLAN_PHYMODE_11NG_HT20:
+		return MODE_11NG_HT20;
+	case WLAN_PHYMODE_11NA_HT40:
+		return MODE_11NA_HT40;
+	case WLAN_PHYMODE_11NG_HT40:
+		return MODE_11NG_HT40;
+	case WLAN_PHYMODE_11AC_VHT20:
+		return MODE_11AC_VHT20;
+	case WLAN_PHYMODE_11AC_VHT40:
+		return MODE_11AC_VHT40;
+	case WLAN_PHYMODE_11AC_VHT80:
+		return MODE_11AC_VHT80;
+	default:
+		fw_phymode = wma_host_to_fw_phymode_160(host_phymode);
+		if (fw_phymode != MODE_UNKNOWN)
+			return fw_phymode;
+		return wma_host_to_fw_phymode_11ax(host_phymode);
+	}
+}
+
 /**
  * wma_objmgr_set_peer_mlme_phymode() - set phymode to peer object
  * @wma:      wma handle
@@ -3433,23 +3531,53 @@ int wma_mgmt_tx_bundle_completion_handler(void *handle, uint8_t *buf,
 void wma_process_update_opmode(tp_wma_handle wma_handle,
 			       tUpdateVHTOpMode *update_vht_opmode)
 {
-	struct wma_txrx_node *iface;
 	wmi_host_channel_width ch_width;
+	uint8_t pdev_id;
+	struct wlan_objmgr_peer *peer;
+	struct wlan_objmgr_psoc *psoc = wma_handle->psoc;
+	enum wlan_phymode peer_phymode;
+	WLAN_PHY_MODE fw_phymode;
+	enum wlan_peer_type peer_type;
+
+	pdev_id = wlan_objmgr_pdev_get_pdev_id(wma_handle->pdev);
+	peer = wlan_objmgr_get_peer(psoc, pdev_id, update_vht_opmode->peer_mac,
+				    WLAN_LEGACY_WMA_ID);
+	if (!peer) {
+		WMA_LOGE("peer object invalid");
+		return;
+	}
+
+	peer_type = wlan_peer_get_peer_type(peer);
+	if (peer_type == WLAN_PEER_SELF) {
+		WMA_LOGE("self peer wrongly used");
+		wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
+		return;
+	}
+
+	wlan_peer_obj_lock(peer);
+	peer_phymode = wlan_peer_get_phymode(peer);
+	wlan_peer_obj_unlock(peer);
+	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID);
+
+	fw_phymode = wma_host_to_fw_phymode(peer_phymode);
 
-	iface = &wma_handle->interfaces[update_vht_opmode->smesessionId];
 	ch_width = wmi_get_ch_width_from_phy_mode(wma_handle->wmi_handle,
-						  iface->chanmode);
+						  (WMI_HOST_WLAN_PHY_MODE)
+						  fw_phymode);
+	WMA_LOGD("%s: peer phymode: %d, ch_width: %d, fw phymode: %d",
+		 __func__, peer_phymode, ch_width, fw_phymode);
 	if (ch_width < update_vht_opmode->opMode) {
 		WMA_LOGE("%s: Invalid peer bw update %d, self bw %d",
 				__func__, update_vht_opmode->opMode,
 				ch_width);
 		return;
 	}
-	WMA_LOGD("%s: phymode = %d", __func__, iface->chanmode);
+
 	/* Always send phymode before BW to avoid any mismatch in FW */
 	wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
-			   WMI_PEER_PHYMODE, iface->chanmode,
+			   WMI_PEER_PHYMODE, fw_phymode,
 			   update_vht_opmode->smesessionId);
+
 	WMA_LOGD("%s: opMode = %d", __func__, update_vht_opmode->opMode);
 	wma_set_peer_param(wma_handle, update_vht_opmode->peer_mac,
 			   WMI_PEER_CHWIDTH, update_vht_opmode->opMode,