Message ID | 20230602235820.23912-4-quic_alokad@quicinc.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Kalle Valo |
Headers | show |
Series | wifi: ath12k: (v4) EHT support | expand |
Aloka Dixit <quic_alokad@quicinc.com> writes: > Add WMI support to process the EHT capabilities passed by > the firmware. Add required EHT specific definitions in > structures ath12k_band_cap and ath12k_wmi_svc_rdy_ext_parse. > > For single_pdev chip such as WCN7850, only one pdev is created > and only one hardware is registered to mac80211. This one pdev > manages both 2.4 GHz radio and 5 GHz/6 GHz radio. > > Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 > Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 > Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com> > Co-developed-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com> > Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com> > Co-developed-by: Wen Gong <quic_wgong@quicinc.com> > Signed-off-by: Wen Gong <quic_wgong@quicinc.com> [...] > +struct ath12k_fw_pdev { > + u32 pdev_id; > + u32 phy_id; > + u32 supported_bands; > +}; So we have now two very similar structures, ath12k_pdev and ath12k_fw_pdev. It would be good to document above the structs their purpose. Any ideas what I could add?
On 6/15/2023 7:49 PM, Kalle Valo wrote: > Aloka Dixit <quic_alokad@quicinc.com> writes: > >> Add WMI support to process the EHT capabilities passed by >> the firmware. Add required EHT specific definitions in >> structures ath12k_band_cap and ath12k_wmi_svc_rdy_ext_parse. >> >> For single_pdev chip such as WCN7850, only one pdev is created >> and only one hardware is registered to mac80211. This one pdev >> manages both 2.4 GHz radio and 5 GHz/6 GHz radio. >> >> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 >> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 >> Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com> >> Co-developed-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com> >> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com> >> Co-developed-by: Wen Gong <quic_wgong@quicinc.com> >> Signed-off-by: Wen Gong <quic_wgong@quicinc.com> > [...] > >> +struct ath12k_fw_pdev { >> + u32 pdev_id; >> + u32 phy_id; >> + u32 supported_bands; >> +}; > So we have now two very similar structures, ath12k_pdev and > ath12k_fw_pdev. It would be good to document above the structs their > purpose. Any ideas what I could add? For single_pdev, the ath12k_pdev is always one pdev. and ath12k_fw_pdev is more than one for single_pdev. >
On 6/16/2023 3:50 AM, Wen Gong wrote: > On 6/15/2023 7:49 PM, Kalle Valo wrote: >> Aloka Dixit <quic_alokad@quicinc.com> writes: >> >>> Add WMI support to process the EHT capabilities passed by >>> the firmware. Add required EHT specific definitions in >>> structures ath12k_band_cap and ath12k_wmi_svc_rdy_ext_parse. >>> >>> For single_pdev chip such as WCN7850, only one pdev is created >>> and only one hardware is registered to mac80211. This one pdev >>> manages both 2.4 GHz radio and 5 GHz/6 GHz radio. >>> >>> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 >>> Tested-on: WCN7850 hw2.0 PCI >>> WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 >>> Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com> >>> Co-developed-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com> >>> Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com> >>> Co-developed-by: Wen Gong <quic_wgong@quicinc.com> >>> Signed-off-by: Wen Gong <quic_wgong@quicinc.com> >> [...] >> >>> +struct ath12k_fw_pdev { >>> + u32 pdev_id; >>> + u32 phy_id; >>> + u32 supported_bands; >>> +}; >> So we have now two very similar structures, ath12k_pdev and >> ath12k_fw_pdev. It would be good to document above the structs their >> purpose. Any ideas what I could add? > > For single_pdev, the ath12k_pdev is always one pdev. > > and ath12k_fw_pdev is more than one for single_pdev. > >> Okay will add a comment in the next version.
On 6/15/2023 7:49 PM, Kalle Valo wrote: > Aloka Dixit <quic_alokad@quicinc.com> writes: > [...] > [...] > >> +struct ath12k_fw_pdev { >> + u32 pdev_id; >> + u32 phy_id; >> + u32 supported_bands; >> +}; > So we have now two very similar structures, ath12k_pdev and > ath12k_fw_pdev. It would be good to document above the structs their > purpose. Any ideas what I could add? Currently ath12k has single_pdev parameter, it impact the interface number of wifi. For single_pdev=ture, ab->num_radios is set to 1 and all capbility of 2.4 GHz/ 5 GHz/6 GHz is saved into ab->pdevs[0] in ath12k_wmi_ext_soc_hal_reg_caps_parse(). ath12k_mac_register() will call only one time into __ath12k_mac_register(), and ieee80211_register_hw() is called only one time, and only one wifi interface in the result of "iw dev/ifconfig", the interface support 2.4 GHz/5 GHz/6 GHz. Actually there hare more than one PHY in firmware, firmware maintain the all PHY data and provide a single pdev/soc interface to ath12k, then ath12k do not need to consider the PHY info such as channel/BAND<->PHY mapping relationship, it is convenient for ath12k to support 2.4 GHz/5 GHz/6 GHz. For single_pdev=false, ab->num_radios is more than 1, ab->pdevs[] has muti valid element, each element only support one BAND. Firmware do not provide a single pdev/soc interface, so ath12k need to maintain the PHY data such as channel/BAND<-> PHY mapping relationship, and ath12k_mac_register() will call muti-time into __ath12k_mac_register(), and ieee80211_register_hw() is called muti-time, and muti wifi interface in the result of "iw dev/ifconfig", and each interface only support one BAND, for example, wlan0 only support 2.4 GHz, wlan1 only support 5 GHz, and wlan2 only support 6 GHz. For single_pdev=ture, ath12k also need to know some info about the PHYs sush as pdev_id/phy_id/supported_bands in this patch, so ab->fw_pdev is used to store the PHY data.
On 7/25/2023 3:51 AM, Wen Gong wrote: > On 6/15/2023 7:49 PM, Kalle Valo wrote: >> Aloka Dixit <quic_alokad@quicinc.com> writes: >> > [...] >> [...] >> >>> +struct ath12k_fw_pdev { >>> + u32 pdev_id; >>> + u32 phy_id; >>> + u32 supported_bands; >>> +}; >> So we have now two very similar structures, ath12k_pdev and >> ath12k_fw_pdev. It would be good to document above the structs their >> purpose. Any ideas what I could add? > Currently ath12k has single_pdev parameter, it impact the interface > number of wifi. > > For single_pdev=ture, ab->num_radios is set to 1 and all capbility of > 2.4 GHz/ > 5 GHz/6 GHz is saved into ab->pdevs[0] in > ath12k_wmi_ext_soc_hal_reg_caps_parse(). > ath12k_mac_register() will call only one time into > __ath12k_mac_register(), and > ieee80211_register_hw() is called only one time, and only one wifi > interface in > the result of "iw dev/ifconfig", the interface support 2.4 GHz/5 GHz/6 > GHz. Actually > there hare more than one PHY in firmware, firmware maintain the all PHY > data and > provide a single pdev/soc interface to ath12k, then ath12k do not need > to consider > the PHY info such as channel/BAND<->PHY mapping relationship, it is > convenient for > ath12k to support 2.4 GHz/5 GHz/6 GHz. > > For single_pdev=false, ab->num_radios is more than 1, ab->pdevs[] has > muti valid > element, each element only support one BAND. Firmware do not provide a > single > pdev/soc interface, so ath12k need to maintain the PHY data such as > channel/BAND<-> > PHY mapping relationship, and ath12k_mac_register() will call muti-time > into > __ath12k_mac_register(), and ieee80211_register_hw() is called > muti-time, and muti > wifi interface in the result of "iw dev/ifconfig", and each interface > only support > one BAND, for example, wlan0 only support 2.4 GHz, wlan1 only support 5 > GHz, and > wlan2 only support 6 GHz. > > For single_pdev=ture, ath12k also need to know some info about the PHYs > sush as > pdev_id/phy_id/supported_bands in this patch, so ab->fw_pdev is used to > store the > PHY data. The new struct ath12k_fw_pdev is anyway going to have as many elements as the num_radio, right? Then there must be a way to reuse the common struct ath12k_pdev instead as it done for QCN devices. I understand this it will need changes to all the existing code for the single-pdev where it might have hard-coded pdev[0] for the original structure. Something to think about in a separate patch-set. For now I will send new version with comments (as far as I understood it) because without this patch WCN devices show a crash during boot-up. Thanks.
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 2f93296db792..df762cabacc2 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -580,6 +580,14 @@ struct ath12k_band_cap { u32 he_cap_phy_info[PSOC_HOST_MAX_PHY_SIZE]; struct ath12k_wmi_ppe_threshold_arg he_ppet; u16 he_6ghz_capa; + u32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE]; + u32 eht_cap_phy_info[WMI_MAX_EHTCAP_PHY_SIZE]; + u32 eht_mcs_20_only; + u32 eht_mcs_80; + u32 eht_mcs_160; + u32 eht_mcs_320; + struct ath12k_wmi_ppe_threshold_arg eht_ppet; + u32 eht_cap_info_internal; }; struct ath12k_pdev_cap { @@ -638,6 +646,12 @@ struct ath12k_soc_dp_stats { struct ath12k_soc_dp_tx_err_stats tx_err; }; +struct ath12k_fw_pdev { + u32 pdev_id; + u32 phy_id; + u32 supported_bands; +}; + /* Master structure to hold the hw data which may be used in core module */ struct ath12k_base { enum ath12k_hw_rev hw_rev; @@ -670,6 +684,8 @@ struct ath12k_base { /* Protects data like peers */ spinlock_t base_lock; struct ath12k_pdev pdevs[MAX_RADIOS]; + struct ath12k_fw_pdev fw_pdev[MAX_RADIOS]; + u8 fw_pdev_count; struct ath12k_pdev __rcu *pdevs_active[MAX_RADIOS]; struct ath12k_wmi_hal_reg_capabilities_ext_arg hal_reg_cap[MAX_RADIOS]; unsigned long long free_vdev_map; diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 6512267ae4ca..7b82e7240594 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -65,6 +65,8 @@ struct ath12k_wmi_svc_rdy_ext_parse { struct ath12k_wmi_svc_rdy_ext2_parse { struct ath12k_wmi_dma_ring_caps_parse dma_caps_parse; bool dma_ring_cap_done; + bool spectral_bin_scaling_done; + bool mac_phy_caps_ext_done; }; struct ath12k_wmi_rdy_parse { @@ -445,8 +447,10 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle, const struct ath12k_wmi_soc_mac_phy_hw_mode_caps_params *hw_caps = svc->hw_caps; const struct ath12k_wmi_hw_mode_cap_params *wmi_hw_mode_caps = svc->hw_mode_caps; const struct ath12k_wmi_mac_phy_caps_params *wmi_mac_phy_caps = svc->mac_phy_caps; + struct ath12k_base *ab = wmi_handle->wmi_ab->ab; struct ath12k_band_cap *cap_band; struct ath12k_pdev_cap *pdev_cap = &pdev->cap; + struct ath12k_fw_pdev *fw_pdev; u32 phy_map; u32 hw_idx, phy_idx = 0; int i; @@ -475,6 +479,12 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle, pdev_cap->supported_bands |= le32_to_cpu(mac_caps->supported_bands); pdev_cap->ampdu_density = le32_to_cpu(mac_caps->ampdu_density); + fw_pdev = &ab->fw_pdev[ab->fw_pdev_count]; + fw_pdev->supported_bands = le32_to_cpu(mac_caps->supported_bands); + fw_pdev->pdev_id = le32_to_cpu(mac_caps->pdev_id); + fw_pdev->phy_id = le32_to_cpu(mac_caps->phy_id); + ab->fw_pdev_count++; + /* Take non-zero tx/rx chainmask. If tx/rx chainmask differs from * band to band for a single radio, need to see how this should be * handled. @@ -3811,6 +3821,7 @@ static int ath12k_wmi_ext_soc_hal_reg_caps_parse(struct ath12k_base *soc, soc->num_radios = 0; phy_id_map = le32_to_cpu(svc_rdy_ext->pref_hw_mode_caps.phy_id_map); + soc->fw_pdev_count = 0; while (phy_id_map && soc->num_radios < MAX_RADIOS) { ret = ath12k_pull_mac_phy_cap_svc_ready_ext(wmi_handle, @@ -4038,6 +4049,126 @@ static int ath12k_service_ready_ext_event(struct ath12k_base *ab, return ret; } +static void ath12k_wmi_eht_caps_parse(struct ath12k_pdev *pdev, u32 band, + __le32 cap_mac_info[], + __le32 cap_phy_info[], + __le32 supp_mcs[], + struct ath12k_wmi_ppe_threshold_params *ppet, + __le32 cap_info_internal) +{ + struct ath12k_band_cap *cap_band = &pdev->cap.band[band]; + u8 i; + + for (i = 0; i < WMI_MAX_EHTCAP_MAC_SIZE; i++) + cap_band->eht_cap_mac_info[i] = le32_to_cpu(cap_mac_info[i]); + + for (i = 0; i < WMI_MAX_EHTCAP_PHY_SIZE; i++) + cap_band->eht_cap_phy_info[i] = le32_to_cpu(cap_phy_info[i]); + + cap_band->eht_mcs_20_only = le32_to_cpu(supp_mcs[0]); + cap_band->eht_mcs_80 = le32_to_cpu(supp_mcs[1]); + if (band != NL80211_BAND_2GHZ) { + cap_band->eht_mcs_160 = le32_to_cpu(supp_mcs[2]); + cap_band->eht_mcs_320 = le32_to_cpu(supp_mcs[3]); + } + + cap_band->eht_ppet.numss_m1 = le32_to_cpu(ppet->numss_m1); + cap_band->eht_ppet.ru_bit_mask = le32_to_cpu(ppet->ru_info); + for (i = 0; i < WMI_MAX_NUM_SS; i++) + cap_band->eht_ppet.ppet16_ppet8_ru3_ru0[i] = + le32_to_cpu(ppet->ppet16_ppet8_ru3_ru0[i]); + + cap_band->eht_cap_info_internal = le32_to_cpu(cap_info_internal); +} + +static int +ath12k_wmi_tlv_mac_phy_caps_ext_parse(struct ath12k_base *ab, + struct ath12k_wmi_mac_phy_caps_ext_params *caps, + struct ath12k_pdev *pdev) +{ + u32 bands; + int i; + + if (ab->hw_params->single_pdev_only) { + for (i = 0; i < ab->fw_pdev_count; i++) { + struct ath12k_fw_pdev *fw_pdev = &ab->fw_pdev[i]; + + if (fw_pdev->pdev_id == le32_to_cpu(caps->pdev_id) && + fw_pdev->phy_id == le32_to_cpu(caps->phy_id)) { + bands = fw_pdev->supported_bands; + break; + } + } + + if (i == ab->fw_pdev_count) + return -EINVAL; + } else { + bands = pdev->cap.supported_bands; + } + + if (bands & WMI_HOST_WLAN_2G_CAP) { + ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_2GHZ, + caps->eht_cap_mac_info_2ghz, + caps->eht_cap_phy_info_2ghz, + caps->eht_supp_mcs_ext_2ghz, + &caps->eht_ppet_2ghz, + caps->eht_cap_info_internal); + } + + if (bands & WMI_HOST_WLAN_5G_CAP) { + ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_5GHZ, + caps->eht_cap_mac_info_5ghz, + caps->eht_cap_phy_info_5ghz, + caps->eht_supp_mcs_ext_5ghz, + &caps->eht_ppet_5ghz, + caps->eht_cap_info_internal); + + ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_6GHZ, + caps->eht_cap_mac_info_5ghz, + caps->eht_cap_phy_info_5ghz, + caps->eht_supp_mcs_ext_5ghz, + &caps->eht_ppet_5ghz, + caps->eht_cap_info_internal); + } + + return 0; +} + +static int ath12k_wmi_tlv_mac_phy_caps_ext(struct ath12k_base *ab, u16 tag, + u16 len, const void *ptr, + void *data) +{ + struct ath12k_wmi_mac_phy_caps_ext_params *caps = + (struct ath12k_wmi_mac_phy_caps_ext_params *)ptr; + int i = 0, ret; + + if (tag != WMI_TAG_MAC_PHY_CAPABILITIES_EXT) + return -EPROTO; + + if (ab->hw_params->single_pdev_only) { + if (ab->wmi_ab.preferred_hw_mode != le32_to_cpu(caps->hw_mode_id)) + return 0; + } else { + for (i = 0; i < ab->num_radios; i++) { + if (ab->pdevs[i].pdev_id == le32_to_cpu(caps->pdev_id)) + break; + } + + if (i == ab->num_radios) + return -EINVAL; + } + + ret = ath12k_wmi_tlv_mac_phy_caps_ext_parse(ab, caps, &ab->pdevs[i]); + if (ret) { + ath12k_warn(ab, + "failed to extract mac phy caps ext, pdev_id:%d\n", + ab->pdevs[i].pdev_id); + return ret; + } + + return 0; +} + static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab, u16 tag, u16 len, const void *ptr, void *data) @@ -4054,6 +4185,22 @@ static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab, return ret; parse->dma_ring_cap_done = true; + } else if (!parse->spectral_bin_scaling_done) { + /* TODO: This is a place-holder as WMI tag for + * spectral scaling is before + * WMI_TAG_MAC_PHY_CAPABILITIES_EXT + */ + parse->spectral_bin_scaling_done = true; + } else if (!parse->mac_phy_caps_ext_done) { + ret = ath12k_wmi_tlv_iter(ab, ptr, len, + ath12k_wmi_tlv_mac_phy_caps_ext, + parse); + if (ret) { + ath12k_warn(ab, "failed to parse tlv %d\n", ret); + return ret; + } + + parse->mac_phy_caps_ext_done = true; } break; default: diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index d89c12bfb009..b722eab281c3 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -2581,6 +2581,44 @@ struct ath12k_wmi_soc_hal_reg_caps_params { __le32 num_phy; } __packed; +#define WMI_MAX_EHTCAP_MAC_SIZE 2 +#define WMI_MAX_EHTCAP_PHY_SIZE 3 + +/* Used for EHT MCS-NSS array. Data at each array index follows the format given + * in IEEE P802.11be/D2.0, May 20229.4.2.313.4. + * + * Index interpretation: + * 0 - 20 MHz only sta, all 4 bytes valid + * 1 - index for bandwidths <= 80 MHz except 20 MHz-only, first 3 bytes valid + * 2 - index for 160 MHz, first 3 bytes valid + * 3 - index for 320 MHz, first 3 bytes valid + */ +#define WMI_MAX_EHT_SUPP_MCS_2G_SIZE 2 +#define WMI_MAX_EHT_SUPP_MCS_5G_SIZE 4 + +struct ath12k_wmi_mac_phy_caps_ext_params { + __le32 hw_mode_id; + union { + struct { + __le16 pdev_id; + __le16 hw_link_id; + } __packed ath12k_wmi_pdev_to_link_map; + __le32 pdev_id; + }; + __le32 phy_id; + __le32 wireless_modes_ext; + __le32 eht_cap_mac_info_2ghz[WMI_MAX_EHTCAP_MAC_SIZE]; + __le32 eht_cap_mac_info_5ghz[WMI_MAX_EHTCAP_MAC_SIZE]; + __le32 rsvd0[2]; + __le32 eht_cap_phy_info_2ghz[WMI_MAX_EHTCAP_PHY_SIZE]; + __le32 eht_cap_phy_info_5ghz[WMI_MAX_EHTCAP_PHY_SIZE]; + struct ath12k_wmi_ppe_threshold_params eht_ppet_2ghz; + struct ath12k_wmi_ppe_threshold_params eht_ppet_5ghz; + __le32 eht_cap_info_internal; + __le32 eht_supp_mcs_ext_2ghz[WMI_MAX_EHT_SUPP_MCS_2G_SIZE]; + __le32 eht_supp_mcs_ext_5ghz[WMI_MAX_EHT_SUPP_MCS_5G_SIZE]; +} __packed; + /* 2 word representation of MAC addr */ struct ath12k_wmi_mac_addr_params { u8 addr[ETH_ALEN];