diff mbox series

wifi: ath12k: add keep backward compatibility of PHY mode to avoid firmware crash

Message ID 20230913105757.17744-1-quic_wgong@quicinc.com
State New
Headers show
Series wifi: ath12k: add keep backward compatibility of PHY mode to avoid firmware crash | expand

Commit Message

Wen Gong Sept. 13, 2023, 10:57 a.m. UTC
In a special WCN7855 firmware release the EHT (IEEE 802.11be) support has
been disabled for size reduction. Currently ath12k always enables EHT PHY
mode during vdev start but with the special firmware that will cause a
firmware crash during vdev start in firmware initialisation. This is
because the firmware will use the EHT mode to allocate resources but as
the EHT mode is not available in the firmware, there's an internal
conflict and the firmware will crash.

To fix the crash check the WMI_TLV_SERVICE_11BE flag to see if the firmware
supports EHT. If EHT is not supported downgrade the PHY mode to HE
(IEEE 802.11ax).

This does not impact QCN9274, because WMI_SERVICE_11BE is always enabled
for QCN9274, then eht_cap->has_eht will always set for it, and the logic
of this patch will not take effect and the PHY mode will not down grade
for it.

Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4

Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/mac.c | 65 ++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath12k/wmi.h |  3 ++
 2 files changed, 66 insertions(+), 2 deletions(-)


base-commit: 3f257461ab0ab19806bae2bfde4c3cd88dbf050e

Comments

Jeff Johnson Sept. 14, 2023, 1:53 a.m. UTC | #1
On 9/13/2023 3:57 AM, Wen Gong wrote:
> In a special WCN7855 firmware release the EHT (IEEE 802.11be) support has
> been disabled for size reduction. Currently ath12k always enables EHT PHY
> mode during vdev start but with the special firmware that will cause a
> firmware crash during vdev start in firmware initialisation. This is
> because the firmware will use the EHT mode to allocate resources but as
> the EHT mode is not available in the firmware, there's an internal
> conflict and the firmware will crash.
> 
> To fix the crash check the WMI_TLV_SERVICE_11BE flag to see if the firmware
> supports EHT. If EHT is not supported downgrade the PHY mode to HE
> (IEEE 802.11ax).
> 
> This does not impact QCN9274, because WMI_SERVICE_11BE is always enabled
> for QCN9274, then eht_cap->has_eht will always set for it, and the logic
> of this patch will not take effect and the PHY mode will not down grade
> for it.
> 
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4
> 
> Signed-off-by: Wen Gong <quic_wgong@quicinc.com>

Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>

> ---
>   drivers/net/wireless/ath/ath12k/mac.c | 65 ++++++++++++++++++++++++++-
>   drivers/net/wireless/ath/ath12k/wmi.h |  3 ++
>   2 files changed, 66 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 0f2af2f14ef7..c72a7028b4b3 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -4553,7 +4553,8 @@ static void ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *
>   	}
>   }
>   
> -static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,
> +static void ath12k_mac_copy_eht_cap(struct ath12k *ar,
> +				    struct ath12k_band_cap *band_cap,
>   				    struct ieee80211_he_cap_elem *he_cap_elem,
>   				    int iftype,
>   				    struct ieee80211_sta_eht_cap *eht_cap)
> @@ -4561,6 +4562,10 @@ static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,
>   	struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem;
>   
>   	memset(eht_cap, 0, sizeof(struct ieee80211_sta_eht_cap));
> +
> +	if (!(test_bit(WMI_TLV_SERVICE_11BE, ar->ab->wmi_ab.svc_map)))
> +		return;
> +
>   	eht_cap->has_eht = true;
>   	memcpy(eht_cap_elem->mac_cap_info, band_cap->eht_cap_mac_info,
>   	       sizeof(eht_cap_elem->mac_cap_info));
> @@ -4626,7 +4631,7 @@ static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar,
>   			data[idx].he_6ghz_capa.capa =
>   				ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
>   		}
> -		ath12k_mac_copy_eht_cap(band_cap, &he_cap->he_cap_elem, i,
> +		ath12k_mac_copy_eht_cap(ar, band_cap, &he_cap->he_cap_elem, i,
>   					&data[idx].eht_cap);
>   		idx++;
>   	}
> @@ -5789,6 +5794,59 @@ static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
>   	mutex_unlock(&ar->conf_mutex);
>   }
>   
> +static enum wmi_phy_mode
> +ath12k_mac_check_down_grade_phy_mode(struct ath12k *ar,
> +				     enum wmi_phy_mode mode,
> +				     enum nl80211_band band,
> +				     enum nl80211_iftype type)
> +{
> +	struct ieee80211_sta_eht_cap *eht_cap;
> +	enum wmi_phy_mode down_mode;
> +
> +	if (mode < MODE_11BE_EHT20)
> +		return mode;
> +
> +	eht_cap = &ar->mac.iftype[band][type].eht_cap;
> +	if (eht_cap->has_eht)
> +		return mode;
> +
> +	switch (mode) {
> +	case MODE_11BE_EHT20:
> +		down_mode = MODE_11AX_HE20;
> +		break;
> +	case MODE_11BE_EHT40:
> +		down_mode = MODE_11AX_HE40;
> +		break;
> +	case MODE_11BE_EHT80:
> +		down_mode = MODE_11AX_HE80;
> +		break;
> +	case MODE_11BE_EHT80_80:
> +		down_mode = MODE_11AX_HE80_80;
> +		break;
> +	case MODE_11BE_EHT160:
> +	case MODE_11BE_EHT160_160:
> +	case MODE_11BE_EHT320:
> +		down_mode = MODE_11AX_HE160;
> +		break;
> +	case MODE_11BE_EHT20_2G:
> +		down_mode = MODE_11AX_HE20_2G;
> +		break;
> +	case MODE_11BE_EHT40_2G:
> +		down_mode = MODE_11AX_HE40_2G;
> +		break;
> +	default:
> +		down_mode = mode;
> +		break;
> +	}
> +
> +	ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
> +		   "mac vdev start phymode %s downgrade to %s\n",
> +		   ath12k_mac_phymode_str(mode),
> +		   ath12k_mac_phymode_str(down_mode));
> +
> +	return down_mode;
> +}
> +
>   static int
>   ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
>   			      const struct cfg80211_chan_def *chandef,
> @@ -5814,6 +5872,9 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
>   	arg.band_center_freq2 = chandef->center_freq2;
>   	arg.mode = ath12k_phymodes[chandef->chan->band][chandef->width];
>   
> +	arg.mode = ath12k_mac_check_down_grade_phy_mode(ar, arg.mode,
> +							chandef->chan->band,
> +							arvif->vif->type);
>   	arg.min_power = 0;
>   	arg.max_power = chandef->chan->max_power * 2;
>   	arg.max_reg_power = chandef->chan->max_reg_power * 2;
> diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
> index 8c047a9623f9..d7ab8c3ff177 100644
> --- a/drivers/net/wireless/ath/ath12k/wmi.h
> +++ b/drivers/net/wireless/ath/ath12k/wmi.h
> @@ -2158,6 +2158,9 @@ enum wmi_tlv_service {
>   	WMI_MAX_EXT_SERVICE = 256,
>   
>   	WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
> +
> +	WMI_TLV_SERVICE_11BE = 289,
> +
>   	WMI_MAX_EXT2_SERVICE,
>   };
>   
> 
> base-commit: 3f257461ab0ab19806bae2bfde4c3cd88dbf050e
Kalle Valo Oct. 2, 2023, 4:53 p.m. UTC | #2
Wen Gong <quic_wgong@quicinc.com> wrote:

> In a special WCN7855 firmware release the EHT (IEEE 802.11be) support has
> been disabled for size reduction. Currently ath12k always enables EHT PHY
> mode during vdev start but with the special firmware that will cause a
> firmware crash during vdev start in firmware initialisation. This is
> because the firmware will use the EHT mode to allocate resources but as
> the EHT mode is not available in the firmware, there's an internal
> conflict and the firmware will crash.
> 
> To fix the crash check the WMI_TLV_SERVICE_11BE flag to see if the firmware
> supports EHT. If EHT is not supported downgrade the PHY mode to HE
> (IEEE 802.11ax).
> 
> This does not impact QCN9274, because WMI_SERVICE_11BE is always enabled
> for QCN9274, then eht_cap->has_eht will always set for it, and the logic
> of this patch will not take effect and the PHY mode will not down grade
> for it.
> 
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4
> 
> Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
> Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
> Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>

Patch applied to ath-next branch of ath.git, thanks.

972754bfeec4 wifi: ath12k: add keep backward compatibility of PHY mode to avoid firmware crash
diff mbox series

Patch

diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 0f2af2f14ef7..c72a7028b4b3 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -4553,7 +4553,8 @@  static void ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *
 	}
 }
 
-static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,
+static void ath12k_mac_copy_eht_cap(struct ath12k *ar,
+				    struct ath12k_band_cap *band_cap,
 				    struct ieee80211_he_cap_elem *he_cap_elem,
 				    int iftype,
 				    struct ieee80211_sta_eht_cap *eht_cap)
@@ -4561,6 +4562,10 @@  static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,
 	struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem;
 
 	memset(eht_cap, 0, sizeof(struct ieee80211_sta_eht_cap));
+
+	if (!(test_bit(WMI_TLV_SERVICE_11BE, ar->ab->wmi_ab.svc_map)))
+		return;
+
 	eht_cap->has_eht = true;
 	memcpy(eht_cap_elem->mac_cap_info, band_cap->eht_cap_mac_info,
 	       sizeof(eht_cap_elem->mac_cap_info));
@@ -4626,7 +4631,7 @@  static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar,
 			data[idx].he_6ghz_capa.capa =
 				ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
 		}
-		ath12k_mac_copy_eht_cap(band_cap, &he_cap->he_cap_elem, i,
+		ath12k_mac_copy_eht_cap(ar, band_cap, &he_cap->he_cap_elem, i,
 					&data[idx].eht_cap);
 		idx++;
 	}
@@ -5789,6 +5794,59 @@  static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
 	mutex_unlock(&ar->conf_mutex);
 }
 
+static enum wmi_phy_mode
+ath12k_mac_check_down_grade_phy_mode(struct ath12k *ar,
+				     enum wmi_phy_mode mode,
+				     enum nl80211_band band,
+				     enum nl80211_iftype type)
+{
+	struct ieee80211_sta_eht_cap *eht_cap;
+	enum wmi_phy_mode down_mode;
+
+	if (mode < MODE_11BE_EHT20)
+		return mode;
+
+	eht_cap = &ar->mac.iftype[band][type].eht_cap;
+	if (eht_cap->has_eht)
+		return mode;
+
+	switch (mode) {
+	case MODE_11BE_EHT20:
+		down_mode = MODE_11AX_HE20;
+		break;
+	case MODE_11BE_EHT40:
+		down_mode = MODE_11AX_HE40;
+		break;
+	case MODE_11BE_EHT80:
+		down_mode = MODE_11AX_HE80;
+		break;
+	case MODE_11BE_EHT80_80:
+		down_mode = MODE_11AX_HE80_80;
+		break;
+	case MODE_11BE_EHT160:
+	case MODE_11BE_EHT160_160:
+	case MODE_11BE_EHT320:
+		down_mode = MODE_11AX_HE160;
+		break;
+	case MODE_11BE_EHT20_2G:
+		down_mode = MODE_11AX_HE20_2G;
+		break;
+	case MODE_11BE_EHT40_2G:
+		down_mode = MODE_11AX_HE40_2G;
+		break;
+	default:
+		down_mode = mode;
+		break;
+	}
+
+	ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+		   "mac vdev start phymode %s downgrade to %s\n",
+		   ath12k_mac_phymode_str(mode),
+		   ath12k_mac_phymode_str(down_mode));
+
+	return down_mode;
+}
+
 static int
 ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
 			      const struct cfg80211_chan_def *chandef,
@@ -5814,6 +5872,9 @@  ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
 	arg.band_center_freq2 = chandef->center_freq2;
 	arg.mode = ath12k_phymodes[chandef->chan->band][chandef->width];
 
+	arg.mode = ath12k_mac_check_down_grade_phy_mode(ar, arg.mode,
+							chandef->chan->band,
+							arvif->vif->type);
 	arg.min_power = 0;
 	arg.max_power = chandef->chan->max_power * 2;
 	arg.max_reg_power = chandef->chan->max_reg_power * 2;
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index 8c047a9623f9..d7ab8c3ff177 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -2158,6 +2158,9 @@  enum wmi_tlv_service {
 	WMI_MAX_EXT_SERVICE = 256,
 
 	WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
+
+	WMI_TLV_SERVICE_11BE = 289,
+
 	WMI_MAX_EXT2_SERVICE,
 };