wifi: ath12k: MLO support part 6
cover wifi: ath12k: MLO support part 6
From: Kalle Valo <[email protected]>
In this patchset there's refactoring to support hardware grouping, meaning multiple hardware devices can be registered to mac80211 as a single device.
Please review.
Aditya Kumar Singh (1):
wifi: ath12k: rename mlo_capable_flags to single_chip_mlo_supp
Karthikeyan Periyasamy (6):
wifi: ath12k: move ATH12K_FLAG_REGISTERED handling to
ath12k_mac_register()
wifi: ath12k: introduce device group abstraction
wifi: ath12k: refactor core start based on hardware group
wifi: ath12k: move struct ath12k_hw from per device to group
wifi: ath12k: send QMI host capability after device group is ready
wifi: ath12k: introduce mlo_capable flag for device group
drivers/net/wireless/ath/ath12k/core.c | 449 ++++++++++++++++++++++--- drivers/net/wireless/ath/ath12k/core.h | 88 +++-- drivers/net/wireless/ath/ath12k/dp.c | 19 +- drivers/net/wireless/ath/ath12k/dp.h | 2 +- drivers/net/wireless/ath/ath12k/mac.c | 97 ++++-- drivers/net/wireless/ath/ath12k/mac.h | 9 +- drivers/net/wireless/ath/ath12k/pci.c | 1 + drivers/net/wireless/ath/ath12k/qmi.c | 123 +++++-- drivers/net/wireless/ath/ath12k/qmi.h | 20 ++ 9 files changed, 658 insertions(+), 150 deletions(-)
base-commit: 3b2ab397d31f926523f2781d7f0a14a387415bf4
Signature · 1 line
2.39.5
PATCH 1/7 wifi: ath12k: move ATH12K_FLAG_REGISTERED handling to ath12k_mac_register()
From: Karthikeyan Periyasamy <[email protected]>
When hardware device group abstraction is introduced, a group abstraction is registered to mac80211 rather than a particular single device. So we cannot set the device registered when the QMI firmware ready event is received, only after all the devices in group have received the event. To do that set and unset ATH12K_FLAG_REGISTERED flag inside ath12k_mac_register() and ath12k_mac_unregister() respectively.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
--- drivers/net/wireless/ath/ath12k/mac.c | 4 ++++ drivers/net/wireless/ath/ath12k/qmi.c | 4 +--- 2 files changed, 5 insertions(+), 3 deletions(-)
drivers/net/wireless/ath/ath12k/mac.c +4 -0
@@ -10839,6 +10839,8 @@ int ath12k_mac_register(struct ath12k_base *ab) goto err; } +set_bit (ATH12K_FLAG_REGISTERED , &ab->dev_flags); +return 0 ; err:
@@ -10858,6 +10860,8 @@ void ath12k_mac_unregister(struct ath12k_base *ab)struct ath12k_hw *ah;int i; +clear_bit (ATH12K_FLAG_REGISTERED , &ab->dev_flags); +for (i =ath12k_get_num_hw (ab) -1 ; i >=0 ; i--) { ah =ath12k_ab_to_ah (ab, i);if (!ah)
drivers/net/wireless/ath/ath12k/qmi.c +1 -3
@@ -3349,11 +3349,9 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work) &ab->dev_flags);clear_bit (ATH12K_FLAG_RECOVERY , &ab->dev_flags); ret =ath12k_core_qmi_firmware_ready (ab); -if (!ret) { +if (!ret)set_bit (ATH12K_FLAG_QMI_FW_READY_COMPLETE , &ab->dev_flags); -set_bit (ATH12K_FLAG_REGISTERED , &ab->dev_flags); - }break ;default :
Signature · 1 line
2.39.5
PATCH 2/7 wifi: ath12k: rename mlo_capable_flags to single_chip_mlo_supp
In reply to Kalle ValoFrom: Aditya Kumar Singh <[email protected]>
At present, the mlo_capable_flags in ath12k_base is used to indicate whether the chip supports inter (QCN9274) or intra (WCN7850) chip MLO. However, it’s possible that the chip supports neither, especially with older firmware versions. Additionally, if intra chip MLO is not supported, inter chip MLO will also be non-functional. Therefore, having two separate flags for this is unnecessary.
Therefore, rename this flag to single_chip_mlo_supp. At the same time convert it into a bool data type. Also, get rid of the enums defined earlier.
For the QCN9274 family of chipsets, this will be set only when firmware advertises the support during the QMI exchange.
For the WCN7850 family of chipsets, since the event is not supported, assumption is made that single chip MLO is supported.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
--- drivers/net/wireless/ath/ath12k/core.c | 2 +- drivers/net/wireless/ath/ath12k/core.h | 23 ++--------------------- drivers/net/wireless/ath/ath12k/qmi.c | 13 +++++-------- 3 files changed, 8 insertions(+), 30 deletions(-)
drivers/net/wireless/ath/ath12k/core.c +1 -1
@@ -1325,7 +1325,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size, ab->dev = dev; ab->hif.bus = bus; ab->qmi.num_radios =U8_MAX ; - ab->mlo_capable_flags =ATH12K_INTRA_DEVICE_MLO_SUPPORT ; + ab->single_chip_mlo_supp = false;/* Device index used to identify the devices in a group. *
drivers/net/wireless/ath/ath12k/core.h +2 -21
@@ -816,21 +816,6 @@ struct ath12k_soc_dp_stats {struct ath12k_soc_dp_tx_err_stats tx_err; }; -/** -* enum ath12k_link_capable_flags - link capable flags -* -* Single/Multi link capability information -* -* @ATH12K_INTRA_DEVICE_MLO_SUPPORT: SLO/MLO form between the radio, where all -* the links (radios) present within a device. -* @ATH12K_INTER_DEVICE_MLO_SUPPORT: SLO/MLO form between the radio, where all -* the links (radios) present across the devices. -*/ -enum ath12k_link_capable_flags { -ATH12K_INTRA_DEVICE_MLO_SUPPORT =BIT (0 ), -ATH12K_INTER_DEVICE_MLO_SUPPORT =BIT (1 ), -}; -/* Master structure to hold the hw data which may be used in core module */ struct ath12k_base {enum ath12k_hw_rev hw_rev;
@@ -996,12 +981,8 @@ struct ath12k_base {const struct hal_rx_ops *hal_rx_ops; -/* mlo_capable_flags denotes the single/multi link operation -* capabilities of the Device. -* -* See enum ath12k_link_capable_flags -*/ -u8 mlo_capable_flags; +/* Denotes the whether MLO is possible within the chip */ +bool single_chip_mlo_supp;struct completion restart_completed;
drivers/net/wireless/ath/ath12k/qmi.c +5 -8
@@ -2023,14 +2023,14 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,u8 hw_link_id =0 ;int i; -if (!(ab->mlo_capable_flags &ATH12K_INTRA_DEVICE_MLO_SUPPORT )) { +if (!ab->single_chip_mlo_supp) {ath12k_dbg (ab,ATH12K_DBG_QMI ,"intra device MLO is disabled hence skip QMI MLO cap" );return ; }if (!ab->qmi.num_radios || ab->qmi.num_radios ==U8_MAX ) { - ab->mlo_capable_flags =0 ; + ab->single_chip_mlo_supp = false; ath12k_dbg(ab, ATH12K_DBG_QMI, "skip QMI MLO cap due to invalid num_radio %d\n",
@@ -2176,12 +2176,9 @@ static void ath12k_qmi_phy_cap_send(struct ath12k_base *ab) goto out; } -if (resp.single_chip_mlo_support_valid) { -if (resp.single_chip_mlo_support) - ab->mlo_capable_flags |=ATH12K_INTRA_DEVICE_MLO_SUPPORT ; -else - ab->mlo_capable_flags &= ~ATH12K_INTRA_DEVICE_MLO_SUPPORT ; - } +if (resp.single_chip_mlo_support_valid && + resp.single_chip_mlo_support) + ab->single_chip_mlo_supp = true;if (!resp.num_phy_valid) { ret = -ENODATA ;
Signature · 1 line
2.39.5
Re: [PATCH 2/7] wifi: ath12k: rename mlo_capable_flags to single_chip_mlo_supp
Quoted 15 lines · Kalle Valo
From: Aditya Kumar Singh <[email protected]>
At present, the
mlo_capable_flagsinath12k_baseis used to indicate whether the chip supports inter (QCN9274) or intra (WCN7850) chip MLO. However, it’s possible that the chip supports neither, especially with older firmware versions. Additionally, if intra chip MLO is not supported, inter chip MLO will also be non-functional. Therefore, having two separate flags for this is unnecessary.Therefore, rename this flag to
single_chip_mlo_supp. At the same time convert it into a bool data type. Also, get rid of the enums defined earlier.For the QCN9274 family of chipsets, this will be set only when firmware advertises the support during the QMI exchange.
Quoted 7 lines
For the WCN7850 family of chipsets, since the event is not supported, assumption is made that single chip MLO is supported.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3Signed-off-by Aditya Kumar Singh <[email protected]>
Kalle, this patch is missing your SOB. Please reply with the tag and I'll fix in 'pending'
Quoted 1 line
---
Re: [PATCH 2/7] wifi: ath12k: rename mlo_capable_flags to single_chip_mlo_supp
Quoted 20 lines · Jeff Johnson
Quoted 18 lines · Kalle Valo
From: Aditya Kumar Singh <[email protected]>
At present, the
mlo_capable_flagsinath12k_baseis used to indicate whether the chip supports inter (QCN9274) or intra (WCN7850) chip MLO. However, it’s possible that the chip supports neither, especially with older firmware versions. Additionally, if intra chip MLO is not supported, inter chip MLO will also be non-functional. Therefore, having two separate flags for this is unnecessary.Therefore, rename this flag to
single_chip_mlo_supp. At the same time convert it into a bool data type. Also, get rid of the enums defined earlier.For the QCN9274 family of chipsets, this will be set only when firmware advertises the support during the QMI exchange.
For the WCN7850 family of chipsets, since the event is not supported, assumption is made that single chip MLO is supported.
Quoted 7 lines
Quoted 4 lines
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3Signed-off-by Aditya Kumar Singh <[email protected]>Kalle, this patch is missing your SOB. Please reply with the tag and I'll fix in 'pending'
Oh darn, sorry about that. Here it is:
Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/list/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
PATCH 3/7 wifi: ath12k: introduce device group abstraction
In reply to Kalle ValoFrom: Karthikeyan Periyasamy <[email protected]>
Currently, single device is probed, and once firmware is ready, the device is registered to mac80211. For Multi-Link Operation, different bands of different devices or same device are part of a single wiphy and for this, hardware device group abstraction is needed.
Hardware device group abstraction - when there are multiple devices (with single radio or dual radio) that are connected by any means of interface for communicating between them, then these devices can be combined together as a single group using a group id to form a group abstraction and register to mac80211.
The grouping information of multiple devices would be based on device tree during device probe (will be implemented in future patches). If no such information is available, then a single device will be part of group abstraction and registered to mac80211, else multiple devices advertised in device tree are combined and then registered to mac80211.
For device group abstraction, a base structure ath12k_hw_group (ag) and the helpers are implemented. These helpers are used during device probe and mapping the group to the devices involved.
An illustration of how multiple devices might be combined together in future based on group id:
+------------------------------------------------------------------------+ | +-------------------------------------+ +-------------------+ | | | +-----------+ | | +-----------+ | | +-----------+ | | | | | ar (2GHz) | | | | ar (5GHz) | | | | ar (6GHz) | | | | | +-----------+ | | +-----------+ | | +-----------+ | | | | ath12k_base (ab) | | ath12k_base (ab) | | | | (Dual band device) | | | | | +-------------------------------------+ +-------------------+ | | ath12k_hw_group (ag) based on group id | +------------------------------------------------------------------------+
In the above representation, two devices are combined into single group based on group id.
Add base code changes where single device would be part of a group with an invalid group id forming an group abstraction. Multi device grouping will be introduced in future.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
--- drivers/net/wireless/ath/ath12k/core.c | 237 +++++++++++++++++++++++-- drivers/net/wireless/ath/ath12k/core.h | 17 ++ drivers/net/wireless/ath/ath12k/pci.c | 1 + 3 files changed, 239 insertions(+), 16 deletions(-)
drivers/net/wireless/ath/ath12k/core.c +221 -16
@@ -22,6 +22,11 @@ unsigned int ath12k_debug_mask;module_param_named (debug_mask, ath12k_debug_mask, uint,0644 );MODULE_PARM_DESC (debug_mask,"Debugging mask" ); +/* protected with ath12k_hw_group_mutex */ +static struct list_head ath12k_hw_group_list =LIST_HEAD_INIT (ath12k_hw_group_list); + +static DEFINE_MUTEX (ath12k_hw_group_mutex); +static int ath12k_core_rfkill_config (struct ath12k_base *ab) {struct ath12k *ar;
@@ -1244,27 +1249,112 @@ static void ath12k_core_panic_notifier_unregister(struct ath12k_base *ab) &ab->panic_nb); } -int ath12k_core_init (struct ath12k_base *ab) +static inline +bool ath12k_core_hw_group_create_ready (struct ath12k_hw_group *ag) { -int ret; +lockdep_assert_held (&ag->mutex); - ret =ath12k_core_soc_create (ab); -if (ret) { -ath12k_err (ab,"failed to create soc core: %d\n" , ret); -return ret; - } - - ret =ath12k_core_panic_notifier_register (ab); -if (ret) -ath12k_warn (ab,"failed to register panic handler: %d\n" , ret); - -return 0 ; +return (ag->num_probed == ag->num_devices); } -void ath12k_core_deinit (struct ath12k_base *ab) +static struct ath12k_hw_group *ath12k_core_hw_group_alloc (u8 id,u8 max_devices) { -ath12k_core_panic_notifier_unregister (ab); +struct ath12k_hw_group *ag; +lockdep_assert_held (&ath12k_hw_group_mutex); + + ag =kzalloc (sizeof (*ag),GFP_KERNEL ); +if (!ag) +return NULL ; + + ag->id = id; + ag->num_devices = max_devices; +list_add (&ag->list, &ath12k_hw_group_list); +mutex_init (&ag->mutex); + +return ag; +} + +static void ath12k_core_hw_group_free (struct ath12k_hw_group *ag) +{ +mutex_lock (&ath12k_hw_group_mutex); + +list_del (&ag->list); +kfree (ag); + +mutex_unlock (&ath12k_hw_group_mutex); +} + +static struct ath12k_hw_group *ath12k_core_hw_group_assign (struct ath12k_base *ab) +{ +u32 group_id =ATH12K_INVALID_GROUP_ID ; +struct ath12k_hw_group *ag; + +lockdep_assert_held (&ath12k_hw_group_mutex); + +/* The grouping of multiple devices will be done based on device tree file. +* TODO: device tree file parsing to know about the devices involved in group. +* +* The platforms that do not have any valid group information would have each +* device to be part of its own invalid group. +* +* Currently, we are not parsing any device tree information and hence, grouping +* of multiple devices is not involved. Thus, single device is added to device +* group. +*/ + ag =ath12k_core_hw_group_alloc (group_id,1 ); +if (!ag) { +ath12k_warn (ab,"unable to create new hw group\n" ); +return NULL ; + } + +ath12k_dbg (ab,ATH12K_DBG_BOOT ,"single device added to hardware group\n" ); + + ab->device_id = ag->num_probed++; + ag->ab[ab->device_id] = ab; + ab->ag = ag; + +return ag; +} + +void ath12k_core_hw_group_unassign (struct ath12k_base *ab) +{ +struct ath12k_hw_group *ag = ab->ag; +u8 device_id = ab->device_id; +int num_probed; + +if (!ag) +return ; + +mutex_lock (&ag->mutex); + +if (WARN_ON (device_id >= ag->num_devices)) { +mutex_unlock (&ag->mutex); +return ; + } + +if (WARN_ON (ag->ab[device_id] != ab)) { +mutex_unlock (&ag->mutex); +return ; + } + + ag->ab[device_id] =NULL ; + ab->ag =NULL ; + ab->device_id =ATH12K_INVALID_DEVICE_ID ; + +if (ag->num_probed) + ag->num_probed--; + + num_probed = ag->num_probed; + +mutex_unlock (&ag->mutex); + +if (!num_probed) +ath12k_core_hw_group_free (ag); +} + +static void ath12k_core_device_cleanup (struct ath12k_base *ab) +{mutex_lock (&ab->core_lock);ath12k_hif_irq_disable (ab);
@@ -1274,8 +1364,123 @@ void ath12k_core_deinit(struct ath12k_base *ab)ath12k_core_stop (ab);mutex_unlock (&ab->core_lock); +} -ath12k_core_soc_destroy (ab); +static void ath12k_core_hw_group_destroy (struct ath12k_hw_group *ag) +{ +struct ath12k_base *ab; +int i; + +if (WARN_ON (!ag)) +return ; + +for (i =0 ; i < ag->num_devices; i++) { + ab = ag->ab[i]; +if (!ab) +continue ; + +ath12k_core_soc_destroy (ab); + } +} + +static void ath12k_core_hw_group_cleanup (struct ath12k_hw_group *ag) +{ +struct ath12k_base *ab; +int i; + +if (!ag) +return ; + +mutex_lock (&ag->mutex); + +for (i =0 ; i < ag->num_devices; i++) { + ab = ag->ab[i]; +if (!ab) +continue ; + +ath12k_core_device_cleanup (ab); + } + +mutex_unlock (&ag->mutex); +} + +static int ath12k_core_hw_group_create (struct ath12k_hw_group *ag) +{ +struct ath12k_base *ab; +int i, ret; + +lockdep_assert_held (&ag->mutex); + +for (i =0 ; i < ag->num_devices; i++) { + ab = ag->ab[i]; +if (!ab) +continue ; + +mutex_lock (&ab->core_lock); + + ret =ath12k_core_soc_create (ab); +if (ret) { +mutex_unlock (&ab->core_lock); +ath12k_err (ab,"failed to create soc core: %d\n" , ret); +return ret; + } + +mutex_unlock (&ab->core_lock); + } + +return 0 ; +} + +int ath12k_core_init (struct ath12k_base *ab) +{ +struct ath12k_hw_group *ag; +int ret; + + ret =ath12k_core_panic_notifier_register (ab); +if (ret) +ath12k_warn (ab,"failed to register panic handler: %d\n" , ret); + +mutex_lock (&ath12k_hw_group_mutex); + + ag =ath12k_core_hw_group_assign (ab); +if (!ag) { +mutex_unlock (&ath12k_hw_group_mutex); +ath12k_warn (ab,"unable to get hw group\n" ); +return -ENODEV ; + } + +mutex_unlock (&ath12k_hw_group_mutex); + +mutex_lock (&ag->mutex); + +ath12k_dbg (ab,ATH12K_DBG_BOOT ,"num devices %d num probed %d\n" , + ag->num_devices, ag->num_probed); + +if (ath12k_core_hw_group_create_ready (ag)) { + ret =ath12k_core_hw_group_create (ag); +if (ret) { +mutex_unlock (&ag->mutex); +ath12k_warn (ab,"unable to create hw group\n" ); + goto err; + } + } + +mutex_unlock (&ag->mutex); + +return 0 ; + +err: +ath12k_core_hw_group_destroy (ab->ag); +ath12k_core_hw_group_unassign (ab); +return ret; +} + +void ath12k_core_deinit (struct ath12k_base *ab) +{ +ath12k_core_panic_notifier_unregister (ab); +ath12k_core_hw_group_cleanup (ab->ag); +ath12k_core_hw_group_destroy (ab->ag); +ath12k_core_hw_group_unassign (ab); }void ath12k_core_free (struct ath12k_base *ab)
drivers/net/wireless/ath/ath12k/core.h +17 -0
@@ -816,6 +816,20 @@ struct ath12k_soc_dp_stats {struct ath12k_soc_dp_tx_err_stats tx_err; }; +/* Holds info on the group of devices that are registered as a single +* wiphy, protected with struct ath12k_hw_group::mutex. +*/ +struct ath12k_hw_group { +struct list_head list; +u8 id; +u8 num_devices; +u8 num_probed; +struct ath12k_base *ab[ATH12K_MAX_SOCS ]; + +/* protects access to this struct */ +struct mutex mutex; +}; +/* Master structure to hold the hw data which may be used in core module */ struct ath12k_base {enum ath12k_hw_rev hw_rev;
@@ -1005,6 +1019,8 @@ struct ath12k_base {struct notifier_block panic_nb; +struct ath12k_hw_group *ag; +/* must be last */ u8 drv_priv[]__aligned(sizeof(void *)) ; };
@@ -1035,6 +1051,7 @@ int ath12k_core_resume_early(struct ath12k_base *ab);int ath12k_core_resume (struct ath12k_base *ab);int ath12k_core_suspend (struct ath12k_base *ab);int ath12k_core_suspend_late (struct ath12k_base *ab); +void ath12k_core_hw_group_unassign (struct ath12k_base *ab);const struct firmware *ath12k_core_firmware_request (struct ath12k_base *ab,const char *filename);
drivers/net/wireless/ath/ath12k/pci.c +1 -0
@@ -1725,6 +1725,7 @@ static void ath12k_pci_remove(struct pci_dev *pdev)if (test_bit (ATH12K_FLAG_QMI_FAIL , &ab->dev_flags)) {ath12k_pci_power_down (ab, false);ath12k_qmi_deinit_service (ab); +ath12k_core_hw_group_unassign (ab); goto qmi_fail; }
Signature · 1 line
2.39.5
PATCH 4/7 wifi: ath12k: refactor core start based on hardware group
In reply to Kalle ValoFrom: Karthikeyan Periyasamy <[email protected]>
Currently, mac allocate/register and core_pdev_create are initiated immediately when QMI firmware ready event is received for a particular device. With hardware device group abstraction, QMI firmware ready event can be received simultaneously for different devices in the group and so, it should not be registered immediately rather it has to be deferred until all devices in the group has received QMI firmware ready.
To handle this, refactor the code of core start to have registering within ath12k_core_hw_group_start() and unregistering in ath12k_core_hw_group_stop().
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
--- drivers/net/wireless/ath/ath12k/core.c | 199 ++++++++++++++++++------- drivers/net/wireless/ath/ath12k/core.h | 22 +++ drivers/net/wireless/ath/ath12k/qmi.c | 4 +- 3 files changed, 172 insertions(+), 53 deletions(-)
drivers/net/wireless/ath/ath12k/core.c +148 -51
@@ -604,6 +604,8 @@ u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab)static void ath12k_core_stop (struct ath12k_base *ab) { +ath12k_core_stopped (ab); +if (!test_bit (ATH12K_FLAG_CRASH_FLUSH , &ab->dev_flags))ath12k_qmi_firmware_stop (ab);
@@ -743,6 +745,8 @@ static int ath12k_core_start(struct ath12k_base *ab, {int ret; +lockdep_assert_held (&ab->core_lock); + ret =ath12k_wmi_attach (ab);if (ret) {ath12k_err (ab,"failed to attach wmi: %d\n" , ret);
@@ -836,6 +840,10 @@ static int ath12k_core_start(struct ath12k_base *ab,/* ACPI is optional so continue in case of an error */ ath12k_dbg (ab,ATH12K_DBG_BOOT ,"acpi failed: %d\n" , ret); +if (!test_bit (ATH12K_FLAG_RECOVERY , &ab->dev_flags)) +/* Indicate the core start in the appropriate group */ +ath12k_core_started (ab); +return 0 ; err_reo_cleanup:
@@ -847,6 +855,96 @@ static int ath12k_core_start(struct ath12k_base *ab,return ret; } +static void ath12k_core_device_cleanup (struct ath12k_base *ab) +{ +mutex_lock (&ab->core_lock); + +ath12k_hif_irq_disable (ab); +ath12k_core_pdev_destroy (ab); +ath12k_mac_unregister (ab); +ath12k_mac_destroy (ab); + +mutex_unlock (&ab->core_lock); +} + +static void ath12k_core_hw_group_stop (struct ath12k_hw_group *ag) +{ +struct ath12k_base *ab; +int i; + +lockdep_assert_held (&ag->mutex); + +for (i = ag->num_devices -1 ; i >=0 ; i--) { + ab = ag->ab[i]; +if (!ab) +continue ; +ath12k_core_device_cleanup (ab); + } +} + +static int ath12k_core_hw_group_start (struct ath12k_hw_group *ag) +{ +struct ath12k_base *ab; +int ret, i; + +lockdep_assert_held (&ag->mutex); + +for (i =0 ; i < ag->num_devices; i++) { + ab = ag->ab[i]; +if (!ab) +continue ; + +mutex_lock (&ab->core_lock); + +/* Check if already registered or not, since same flow +* execute for HW restart case. +*/ +if (test_bit (ATH12K_FLAG_REGISTERED , &ab->dev_flags)) + goto core_pdev_create; + + ret =ath12k_mac_allocate (ab); +if (ret) { +ath12k_err (ab,"failed to create new hw device with mac80211 :%d\n" , + ret); +mutex_unlock (&ab->core_lock); +return ret; + } + + ret =ath12k_mac_register (ab); +if (ret) { +ath12k_err (ab,"failed to register radio with mac80211: %d\n" , + ret); +mutex_unlock (&ab->core_lock); + goto err; + } + +core_pdev_create: + ret =ath12k_core_pdev_create (ab); +if (ret) { +ath12k_err (ab,"failed to create pdev core %d\n" , ret); +mutex_unlock (&ab->core_lock); + goto err; + } + +ath12k_hif_irq_enable (ab); + + ret =ath12k_core_rfkill_config (ab); +if (ret && ret != -EOPNOTSUPP ) { +mutex_unlock (&ab->core_lock); + goto err; + } + +mutex_unlock (&ab->core_lock); + } + +return 0 ; + +err: +ath12k_core_hw_group_stop (ag); + +return ret; +} +static int ath12k_core_start_firmware (struct ath12k_base *ab,enum ath12k_firmware_mode mode) {
@@ -864,9 +962,18 @@ static int ath12k_core_start_firmware(struct ath12k_base *ab,return ret; } +static inline +bool ath12k_core_hw_group_start_ready (struct ath12k_hw_group *ag) +{ +lockdep_assert_held (&ag->mutex); + +return (ag->num_started == ag->num_devices); +} +int ath12k_core_qmi_firmware_ready (struct ath12k_base *ab) { -int ret; +struct ath12k_hw_group *ag =ath12k_ab_to_ag (ab); +int ret, i; ret =ath12k_core_start_firmware (ab,ATH12K_FIRMWARE_MODE_NORMAL );if (ret) {
@@ -886,59 +993,50 @@ int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab) goto err_firmware_stop; } +mutex_lock (&ag->mutex);mutex_lock (&ab->core_lock); + ret =ath12k_core_start (ab,ATH12K_FIRMWARE_MODE_NORMAL );if (ret) {ath12k_err (ab,"failed to start core: %d\n" , ret); goto err_dp_free; } - ret =ath12k_mac_allocate (ab); -if (ret) { -ath12k_err (ab,"failed to create new hw device with mac80211 :%d\n" , - ret); - goto err_core_stop; - } - - ret =ath12k_mac_register (ab); -if (ret) { -ath12k_err (ab,"failed register the radio with mac80211: %d\n" , ret); - goto err_mac_destroy; - } - - ret =ath12k_core_pdev_create (ab); -if (ret) { -ath12k_err (ab,"failed to create pdev core: %d\n" , ret); - goto err_mac_unregister; - } - -ath12k_hif_irq_enable (ab); - - ret =ath12k_core_rfkill_config (ab); -if (ret && ret != -EOPNOTSUPP ) { -ath12k_err (ab,"failed to config rfkill: %d\n" , ret); - goto err_hif_irq_disable; - } -mutex_unlock (&ab->core_lock); +if (ath12k_core_hw_group_start_ready (ag)) { + ret =ath12k_core_hw_group_start (ag); +if (ret) { +ath12k_warn (ab,"unable to start hw group\n" ); + goto err_core_stop; + } +ath12k_dbg (ab,ATH12K_DBG_BOOT ,"group %d started\n" , ag->id); + } + +mutex_unlock (&ag->mutex); +return 0 ; -err_hif_irq_disable: -ath12k_hif_irq_disable (ab); -ath12k_core_pdev_destroy (ab); -err_mac_unregister: -ath12k_mac_unregister (ab); -err_mac_destroy: -ath12k_mac_destroy (ab); err_core_stop: -ath12k_core_stop (ab); +for (i = ag->num_devices -1 ; i >=0 ; i--) { + ab = ag->ab[i]; +if (!ab) +continue ; + +mutex_lock (&ab->core_lock); +ath12k_core_stop (ab); +mutex_unlock (&ab->core_lock); + } + goto exit; + err_dp_free:ath12k_dp_free (ab);mutex_unlock (&ab->core_lock); err_firmware_stop:ath12k_qmi_firmware_stop (ab); +exit: +mutex_unlock (&ag->mutex);return ret; }
@@ -1135,6 +1233,14 @@ static void ath12k_core_restart(struct work_struct *work) }if (ab->is_reset) { +if (!test_bit (ATH12K_FLAG_REGISTERED , &ab->dev_flags)) { +atomic_dec (&ab->reset_count); +complete (&ab->reset_complete); + ab->is_reset = false; +atomic_set (&ab->fail_cont_count,0 ); +ath12k_dbg (ab,ATH12K_DBG_BOOT ,"reset success\n" ); + } +for (i =0 ; i <ath12k_get_num_hw (ab); i++) { ah =ath12k_ab_to_ah (ab, i);ieee80211_restart_hw (ah->hw);
@@ -1319,7 +1425,7 @@ static struct ath12k_hw_group *ath12k_core_hw_group_assign(struct ath12k_base *avoid ath12k_core_hw_group_unassign (struct ath12k_base *ab) { -struct ath12k_hw_group *ag = ab->ag; +struct ath12k_hw_group *ag =ath12k_ab_to_ag (ab);u8 device_id = ab->device_id;int num_probed;
@@ -1353,19 +1459,6 @@ void ath12k_core_hw_group_unassign(struct ath12k_base *ab)ath12k_core_hw_group_free (ag); } -static void ath12k_core_device_cleanup (struct ath12k_base *ab) -{ -mutex_lock (&ab->core_lock); - -ath12k_hif_irq_disable (ab); -ath12k_core_pdev_destroy (ab); -ath12k_mac_unregister (ab); -ath12k_mac_destroy (ab); -ath12k_core_stop (ab); - -mutex_unlock (&ab->core_lock); -} -static void ath12k_core_hw_group_destroy (struct ath12k_hw_group *ag) {struct ath12k_base *ab;
@@ -1393,12 +1486,16 @@ static void ath12k_core_hw_group_cleanup(struct ath12k_hw_group *ag)mutex_lock (&ag->mutex); +ath12k_core_hw_group_stop (ag); +for (i =0 ; i < ag->num_devices; i++) { ab = ag->ab[i];if (!ab)continue ; -ath12k_core_device_cleanup (ab); +mutex_lock (&ab->core_lock); +ath12k_core_stop (ab); +mutex_unlock (&ab->core_lock); }mutex_unlock (&ag->mutex);
drivers/net/wireless/ath/ath12k/core.h +22 -0
@@ -824,6 +824,8 @@ struct ath12k_hw_group {u8 id;u8 num_devices;u8 num_probed; +u8 num_started; +unsigned long flags;struct ath12k_base *ab[ATH12K_MAX_SOCS ];/* protects access to this struct */
@@ -1175,4 +1177,24 @@ static inline int ath12k_get_num_hw(struct ath12k_base *ab) {return ab->num_hw; } + +static inline struct ath12k_hw_group *ath12k_ab_to_ag (struct ath12k_base *ab) +{ +return ab->ag; +} + +static inline void ath12k_core_started (struct ath12k_base *ab) +{ +lockdep_assert_held (&ab->ag->mutex); + + ab->ag->num_started++; +} + +static inline void ath12k_core_stopped (struct ath12k_base *ab) +{ +lockdep_assert_held (&ab->ag->mutex); + + ab->ag->num_started--; +} +#endif /* _CORE_H_ */
drivers/net/wireless/ath/ath12k/qmi.c +2 -2
@@ -3321,7 +3321,6 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work)break ;case ATH12K_QMI_EVENT_SERVER_EXIT :set_bit (ATH12K_FLAG_CRASH_FLUSH , &ab->dev_flags); -set_bit (ATH12K_FLAG_RECOVERY , &ab->dev_flags);break ;case ATH12K_QMI_EVENT_REQUEST_MEM : ret =ath12k_qmi_event_mem_request (qmi);
@@ -3338,13 +3337,14 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work)if (test_bit (ATH12K_FLAG_QMI_FW_READY_COMPLETE , &ab->dev_flags)) {if (ab->is_reset)ath12k_hal_dump_srng_stats (ab); + +set_bit (ATH12K_FLAG_RECOVERY , &ab->dev_flags);queue_work (ab->workqueue, &ab->restart_work);break ; }clear_bit (ATH12K_FLAG_CRASH_FLUSH , &ab->dev_flags); -clear_bit (ATH12K_FLAG_RECOVERY , &ab->dev_flags); ret =ath12k_core_qmi_firmware_ready (ab);if (!ret) set_bit(ATH12K_FLAG_QMI_FW_READY_COMPLETE,
Signature · 1 line
2.39.5
PATCH 5/7 wifi: ath12k: move struct ath12k_hw from per device to group
In reply to Kalle ValoFrom: Karthikeyan Periyasamy <[email protected]>
Currently, hardware abstractions (ah) of different radio bands are tightly coupled to a single device (ab). But, with hardware device group abstraction (ag), multiple radios across different devices in a group can form different combinations of hardware abstractions (ah) within the group. Hence, the mapping between ah to ab can be removed and instead it can be mapped with struct ath12k_hw_group (ag).
Current mapping between struct ath12k_hw (ah), struct ath12k_base (ab) and struct ath12k_hw_group (ag):
+------------------------------------------------+
| +-------------------------------------+ |
| | +---------------+ +---------------+ | |
| | |ath12k_hw (ah) | |ath12k_hw (ah) | | |
| | +---------------+ +---------------+ | |
| | | |
| | +-----------+ | +-----------+ | |
| | | ar (2GHz) | | | ar (5GHz) | | |
| | +-----------+ | +-----------+ | |
| | Dual band device-1 (ab) | |
| +-------------------------------------+ |
| ath12k_hw_group (ag) based on group id |
+------------------------------------------------+After hardware device group abstraction moving ah array out of ab to ag:
+----------------------------------------------+
| +---------------+ +---------------+ |
| |ath12k_hw (ah) | |ath12k_hw (ah) | |
| +---------------+ +---------------+ |
| +-------------------------------------+ |
| | +-----------+ +-----------+ | |
| | | ar (2GHz) | | ar (5GHz) | | |
| | +-----------+ +-----------+ | |
| | Dual band device-1 (ab) | |
| +-------------------------------------+ |
| ath12k_hw_group (ag) based on group id |
+----------------------------------------------+This decoupling of struct ath12k_hw (ah) from struct ath12k_base (ab) and mapping it to struct ath12k_hw_group (ag) will help in forming different combinations of multi-link devices.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
--- drivers/net/wireless/ath/ath12k/core.c | 49 +++++++------- drivers/net/wireless/ath/ath12k/core.h | 29 +++++---- drivers/net/wireless/ath/ath12k/dp.c | 19 ++---- drivers/net/wireless/ath/ath12k/dp.h | 2 +- drivers/net/wireless/ath/ath12k/mac.c | 89 ++++++++++++++++++-------- drivers/net/wireless/ath/ath12k/mac.h | 9 +-- 6 files changed, 115 insertions(+), 82 deletions(-)
drivers/net/wireless/ath/ath12k/core.c +24 -25
@@ -861,8 +861,6 @@ static void ath12k_core_device_cleanup(struct ath12k_base *ab)ath12k_hif_irq_disable (ab);ath12k_core_pdev_destroy (ab); -ath12k_mac_unregister (ab); -ath12k_mac_destroy (ab);mutex_unlock (&ab->core_lock); }
@@ -874,12 +872,18 @@ static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag)lockdep_assert_held (&ag->mutex); +clear_bit (ATH12K_GROUP_FLAG_REGISTERED , &ag->flags); + +ath12k_mac_unregister (ag); +for (i = ag->num_devices -1 ; i >=0 ; i--) { ab = ag->ab[i];if (!ab)continue ;ath12k_core_device_cleanup (ab); } + +ath12k_mac_destroy (ag); }static int ath12k_core_hw_group_start (struct ath12k_hw_group *ag)
@@ -889,6 +893,20 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag)lockdep_assert_held (&ag->mutex); +if (test_bit (ATH12K_GROUP_FLAG_REGISTERED , &ag->flags)) + goto core_pdev_create; + + ret =ath12k_mac_allocate (ag); +if (WARN_ON (ret)) +return ret; + + ret =ath12k_mac_register (ag); +if (WARN_ON (ret)) + goto err_mac_destroy; + +set_bit (ATH12K_GROUP_FLAG_REGISTERED , &ag->flags); + +core_pdev_create:for (i =0 ; i < ag->num_devices; i++) { ab = ag->ab[i];if (!ab)
@@ -896,29 +914,6 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag)mutex_lock (&ab->core_lock); -/* Check if already registered or not, since same flow -* execute for HW restart case. -*/ -if (test_bit (ATH12K_FLAG_REGISTERED , &ab->dev_flags)) - goto core_pdev_create; - - ret =ath12k_mac_allocate (ab); -if (ret) { -ath12k_err (ab,"failed to create new hw device with mac80211 :%d\n" , - ret); -mutex_unlock (&ab->core_lock); -return ret; - } - - ret =ath12k_mac_register (ab); -if (ret) { -ath12k_err (ab,"failed to register radio with mac80211: %d\n" , - ret); -mutex_unlock (&ab->core_lock); - goto err; - } - -core_pdev_create: ret =ath12k_core_pdev_create (ab);if (ret) {ath12k_err (ab,"failed to create pdev core %d\n" , ret);
@@ -941,6 +936,10 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag) err:ath12k_core_hw_group_stop (ag); +return ret; + +err_mac_destroy: +ath12k_mac_destroy (ag);return ret; }
drivers/net/wireless/ath/ath12k/core.h +17 -12
@@ -64,6 +64,7 @@#define ATH12K_RECOVER_START_TIMEOUT_HZ (20 * HZ)#define ATH12K_MAX_SOCS 3 +#define ATH12K_GROUP_MAX_RADIO (ATH12K_MAX_SOCS * MAX_RADIOS)#define ATH12K_INVALID_GROUP_ID 0xFF#define ATH12K_INVALID_DEVICE_ID 0xFF
@@ -216,6 +217,10 @@ enum ath12k_scan_state { ATH12K_SCAN_ABORTING, }; +enum ath12k_hw_group_flags { +ATH12K_GROUP_FLAG_REGISTERED , +}; +enum ath12k_dev_flags {ATH12K_CAC_RUNNING ,ATH12K_FLAG_CRASH_FLUSH ,
@@ -830,6 +835,15 @@ struct ath12k_hw_group {/* protects access to this struct */ struct mutex mutex; + +/* Holds information of wiphy (hw) registration. +* +* In Multi/Single Link Operation case, all pdevs are registered as +* a single wiphy. In other (legacy/Non-MLO) cases, each pdev is +* registered as separate wiphys. +*/ +struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO ]; +u8 num_hw; };/* Master structure to hold the hw data which may be used in core module */
@@ -895,15 +909,6 @@ struct ath12k_base {struct ath12k_pdev __rcu *pdevs_active[MAX_RADIOS ]; -/* Holds information of wiphy (hw) registration. -* -* In Multi/Single Link Operation case, all pdevs are registered as -* a single wiphy. In other (legacy/Non-MLO) cases, each pdev is -* registered as separate wiphys. -*/ -struct ath12k_hw *ah[MAX_RADIOS ]; -u8 num_hw; -struct ath12k_wmi_hal_reg_capabilities_ext_arg hal_reg_cap[MAX_RADIOS ];unsigned long long free_vdev_map;unsigned long long free_vdev_stats_id_map;
@@ -1164,18 +1169,18 @@ static inline struct ieee80211_hw *ath12k_ar_to_hw(struct ath12k *ar)static inline struct ath12k_hw *ath12k_ab_to_ah (struct ath12k_base *ab,int idx) { -return ab->ah[idx]; +return ab->ag->ah[idx]; }static inline void ath12k_ab_set_ah (struct ath12k_base *ab,int idx,struct ath12k_hw *ah) { - ab->ah[idx] = ah; + ab->ag->ah[idx] = ah; }static inline int ath12k_get_num_hw (struct ath12k_base *ab) { -return ab->num_hw; +return ab->ag->num_hw; }static inline struct ath12k_hw_group *ath12k_ab_to_ag (struct ath12k_base *ab)
drivers/net/wireless/ath/ath12k/dp.c +6 -13
@@ -991,21 +991,14 @@ void ath12k_dp_pdev_free(struct ath12k_base *ab)ath12k_dp_rx_pdev_free (ab, i); } -void ath12k_dp_pdev_pre_alloc (struct ath12k_base *ab) +void ath12k_dp_pdev_pre_alloc (struct ath12k *ar) { -struct ath12k *ar; -struct ath12k_pdev_dp *dp; -int i; +struct ath12k_pdev_dp *dp = &ar->dp; -for (i =0 ; i < ab->num_radios; i++) { - ar = ab->pdevs[i].ar; - dp = &ar->dp; - dp->mac_id = i; -atomic_set (&dp->num_tx_pending,0 ); -init_waitqueue_head (&dp->tx_empty_waitq); - -/* TODO: Add any RXDMA setup required per pdev */ - } + dp->mac_id = ar->pdev_idx; +atomic_set (&dp->num_tx_pending,0 ); +init_waitqueue_head (&dp->tx_empty_waitq); +/* TODO: Add any RXDMA setup required per pdev */ }bool ath12k_dp_wmask_compaction_rx_tlv_supported (struct ath12k_base *ab)
drivers/net/wireless/ath/ath12k/dp.h +1 -1
@@ -1806,7 +1806,7 @@ void ath12k_dp_free(struct ath12k_base *ab);int ath12k_dp_alloc (struct ath12k_base *ab);void ath12k_dp_cc_config (struct ath12k_base *ab);int ath12k_dp_pdev_alloc (struct ath12k_base *ab); -void ath12k_dp_pdev_pre_alloc (struct ath12k_base *ab); +void ath12k_dp_pdev_pre_alloc (struct ath12k *ar);void ath12k_dp_pdev_free (struct ath12k_base *ab);int ath12k_dp_tx_htt_srng_setup (struct ath12k_base *ab,u32 ring_id,int mac_id,enum hal_ring_type ring_type);
drivers/net/wireless/ath/ath12k/mac.c +62 -27
161 lines not on this page · raw message
drivers/net/wireless/ath/ath12k/mac.h +5 -4
@@ -14,6 +14,7 @@struct ath12k ;struct ath12k_base ;struct ath12k_hw ; +struct ath12k_hw_group ;struct ath12k_pdev_map ;struct ath12k_generic_iter {
@@ -60,10 +61,10 @@ enum ath12k_supported_bw {extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default; -void ath12k_mac_destroy (struct ath12k_base *ab); -void ath12k_mac_unregister (struct ath12k_base *ab); -int ath12k_mac_register (struct ath12k_base *ab); -int ath12k_mac_allocate (struct ath12k_base *ab); +void ath12k_mac_destroy (struct ath12k_hw_group *ag); +void ath12k_mac_unregister (struct ath12k_hw_group *ag); +int ath12k_mac_register (struct ath12k_hw_group *ag); +int ath12k_mac_allocate (struct ath12k_hw_group *ag);int ath12k_mac_hw_ratecode_to_legacy_rate (u8 hw_rc,u8 preamble,u8 *rateidx,u16 *rate); u8 ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
Signature · 1 line
2.39.5
Re: [PATCH 5/7] wifi: ath12k: move struct ath12k_hw from per device to group
Op 04-12-2024 om 17:32 schreef Kalle Valo:
Quoted 39 lines
From: Karthikeyan Periyasamy <[email protected]>
Currently, hardware abstractions (ah) of different radio bands are tightly coupled to a single device (ab). But, with hardware device group abstraction (ag), multiple radios across different devices in a group can form different combinations of hardware abstractions (ah) within the group. Hence, the mapping between ah to ab can be removed and instead it can be mapped with struct
ath12k_hw_group(ag).
[...]drivers/net/wireless/ath/ath12k/mac.c +12
-6-void ath12k_mac_destroy (struct ath12k_base *ab) +void ath12k_mac_destroy (struct ath12k_hw_group *ag) {struct ath12k_pdev *pdev; +struct ath12k_base *ab = ag->ab[0 ]; +int i, j;struct ath12k_hw *ah; -int i; -for (i =0 ; i < ab->num_radios; i++) { - pdev = &ab->pdevs[i]; -if (!pdev->ar) +for (i =0 ; i < ag->num_devices; i++) { + ab = ag->ab[i]; +if (!ab)continue ; - pdev->ar =NULL ; +for (j =0 ; j < ab->num_radios; j++) { + pdev = &ab->pdevs[j]; +if (!pdev->ar) +continue ; + pdev->ar =NULL ; + } }for (i =0 ; i <ath12k_get_num_hw (ab); i++) {
drivers/net/wireless/ath/ath12k/mac.c void ath12k_mac_destroy(struct ath12k_base *ab) · line 10947
Quoted 3 lines
drivers/net/wireless/ath/ath12k/mac.c +0
-0@@ -10942,26 +10945,59 @@ void ath12k_mac_destroy(struct ath12k_base *ab) } }
The new ath12k_mac_destroy() looks suspicious with respect to "ab". Here is the new function with comments.
void ath12k_mac_destroy(struct ath12k_hw_group *ag)
{
struct ath12k_pdev *pdev;
struct ath12k_base *ab = ag->ab[0];
==> here ag->ab[0] is used before checking if ag->num_devices is greater than zero
==> If ag->num_devices will never be zero then this first assignment will be repeated in the next for-loop ==> if ag->num_devices can be zero then you need to confirm that ag->ab[0] is non-NULL
int i, j;
struct ath12k_hw *ah;
for (i = 0; i < ag->num_devices; i++) {
ab = ag->ab[i];
if (!ab)
=>> This if check indicates that ab can be NULL
continue;
for (j = 0; j < ab->num_radios; j++) { pdev = &ab->pdevs[j]; if (!pdev->ar) continue; pdev->ar = NULL;
}
}
==> Now ab is going to be used, but as shown above, ab can be NULL for (i = 0; i < ath12k_get_num_hw(ab); i++) { ah = ath12k_ab_to_ah(ab, i);
if (!ah)
continue;
ath12k_mac_hw_destroy(ah);
ath12k_ab_set_ah(ab, i, NULL);
}
}
Signature · 1 line
Kees
Re: [PATCH 5/7] wifi: ath12k: move struct ath12k_hw from per device to group
Quoted 38 lines · Kees Bakker
Op 04-12-2024 om 17:32 schreef Kalle Valo:
Quoted 37 lines
From: Karthikeyan Periyasamy <[email protected]>
Currently, hardware abstractions (ah) of different radio bands are tightly coupled to a single device (ab). But, with hardware device group abstraction (ag), multiple radios across different devices in a group can form different combinations of hardware abstractions (ah) within the group. Hence, the mapping between ah to ab can be removed and instead it can be mapped with struct
ath12k_hw_group(ag).
[...]drivers/net/wireless/ath/ath12k/mac.c +12
-6-void ath12k_mac_destroy (struct ath12k_base *ab) +void ath12k_mac_destroy (struct ath12k_hw_group *ag) {struct ath12k_pdev *pdev; +struct ath12k_base *ab = ag->ab[0 ]; +int i, j;struct ath12k_hw *ah; -int i; -for (i =0 ; i < ab->num_radios; i++) { - pdev = &ab->pdevs[i]; -if (!pdev->ar) +for (i =0 ; i < ag->num_devices; i++) { + ab = ag->ab[i]; +if (!ab)continue ; - pdev->ar =NULL ; +for (j =0 ; j < ab->num_radios; j++) { + pdev = &ab->pdevs[j]; +if (!pdev->ar) +continue ; + pdev->ar =NULL ; + } }
Quoted 6 lines
drivers/net/wireless/ath/ath12k/mac.c void ath12k_mac_destroy(struct ath12k_base *ab) · line 10947
Quoted 5 lines
for (i = 0; i < ath12k_get_num_hw(ab); i++) {drivers/net/wireless/ath/ath12k/mac.c +0
-0@@ -10942,26 +10945,59 @@ void ath12k_mac_destroy(struct ath12k_base *ab) } }The new
ath12k_mac_destroy()looks suspicious with respect to "ab".
There is already a patch in the internal pipeline to address this linux-next Coverity CID
PATCH 6/7 wifi: ath12k: send QMI host capability after device group is ready
In reply to Kalle ValoFrom: Karthikeyan Periyasamy <[email protected]>
QMI host capability has the information regarding MLO parameters such as device_id, MLO capability, group id and the information of each devices involved in the group and sent immediately on QMI server arrive event. Currently, only one device is involved in the group and hence, single device information is sent as part of MLO capability of host.
But, in future when multi device group abstraction is introduced, host should send all the device information involved in the group as part of QMI MLO host capability rather than single device. Hence, sending QMI host capability immediately on server arrive of a device might not be ideal for multi device group abstraction as the details of other devices in the group would not be available.
Hence, once QMI server arrive event is received, request for QMI PHY capabilities of device, and defer the host capability send for that device. After QMI PHY capability is received for all the devices in the group trigger the host capability event for the deferred devices in the group.
Hence, add changes to defer the QMI host capability event until the device group is ready and then resume the QMI exchange for all the device with host capabilities.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
--- drivers/net/wireless/ath/ath12k/core.c | 21 ++++++ drivers/net/wireless/ath/ath12k/qmi.c | 98 ++++++++++++++++++++++++-- drivers/net/wireless/ath/ath12k/qmi.h | 20 ++++++ 3 files changed, 134 insertions(+), 5 deletions(-)
drivers/net/wireless/ath/ath12k/core.c +21 -0
@@ -969,6 +969,25 @@ bool ath12k_core_hw_group_start_ready(struct ath12k_hw_group *ag)return (ag->num_started == ag->num_devices); } +static void ath12k_core_trigger_partner (struct ath12k_base *ab) +{ +struct ath12k_hw_group *ag = ab->ag; +struct ath12k_base *partner_ab; +bool found = false; +int i; + +for (i =0 ; i < ag->num_devices; i++) { + partner_ab = ag->ab[i]; +if (!partner_ab) +continue ; + +if (found) +ath12k_qmi_trigger_host_cap (partner_ab); + + found = (partner_ab == ab); + } +} +int ath12k_core_qmi_firmware_ready (struct ath12k_base *ab) {struct ath12k_hw_group *ag =ath12k_ab_to_ag (ab);
@@ -1010,6 +1029,8 @@ int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab) goto err_core_stop; }ath12k_dbg (ab,ATH12K_DBG_BOOT ,"group %d started\n" , ag->id); + }else { +ath12k_core_trigger_partner (ab); }mutex_unlock (&ag->mutex);
drivers/net/wireless/ath/ath12k/qmi.c +93 -5
128 lines not on this page · raw message
drivers/net/wireless/ath/ath12k/qmi.h +20 -0
@@ -68,6 +68,7 @@ enum ath12k_qmi_event_type {ATH12K_QMI_EVENT_FORCE_FW_ASSERT ,ATH12K_QMI_EVENT_POWER_UP ,ATH12K_QMI_EVENT_POWER_DOWN , +ATH12K_QMI_EVENT_HOST_CAP , ATH12K_QMI_EVENT_MAX, };
@@ -142,6 +143,10 @@ struct ath12k_qmi {u32 target_mem_mode;bool target_mem_delayed;u8 cal_done; + +/* protected with struct ath12k_qmi::event_lock */ +bool block_event; +u8 num_radios;struct target_info target;struct m3_mem_region m3_mem;
@@ -594,11 +599,26 @@ struct qmi_wlanfw_wlan_ini_resp_msg_v01 { struct qmi_response_type_v01 resp; }; +static inline void ath12k_qmi_set_event_block (struct ath12k_qmi *qmi,bool block) +{ +lockdep_assert_held (&qmi->event_lock); + + qmi->block_event = block; +} + +static inline bool ath12k_qmi_get_event_block (struct ath12k_qmi *qmi) +{ +lockdep_assert_held (&qmi->event_lock); + +return qmi->block_event; +} +int ath12k_qmi_firmware_start (struct ath12k_base *ab,u32 mode);void ath12k_qmi_firmware_stop (struct ath12k_base *ab);void ath12k_qmi_deinit_service (struct ath12k_base *ab);int ath12k_qmi_init_service (struct ath12k_base *ab);void ath12k_qmi_free_resource (struct ath12k_base *ab); +void ath12k_qmi_trigger_host_cap (struct ath12k_base *ab);#endif
Signature · 1 line
2.39.5
PATCH 7/7 wifi: ath12k: introduce mlo_capable flag for device group
In reply to Kalle ValoFrom: Karthikeyan Periyasamy <[email protected]>
Currently, during mac80211 allocate and register single device is considered for the registration. But, in future, during multi device group abstraction is introduced, all the devices has to be combined together as a single abstraction and then hardware should be allocated.
All the devices in the group should be combined together only if it supports inter device mlo capability. The decision of whether to combine the devices or not can be based on the mlo capability flag in ath12k_hw_group.
By default, mlo_capable flag in the group would be set as false. During QMI PHY capability exchange, only when we have more than one chip in the group or if one chip, then that chip supports inter MLO, then mlo_capable flag in the group will be enabled.
Add changes to introduce mlo_capable flag for device group and refactor ath12k_mac_hw_allocate() api based on device group (ag) rather than device (ab).
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
--- drivers/net/wireless/ath/ath12k/core.c | 17 +++++++++++++++++ drivers/net/wireless/ath/ath12k/core.h | 3 +++ drivers/net/wireless/ath/ath12k/mac.c | 8 +++++--- drivers/net/wireless/ath/ath12k/qmi.c | 6 ++++-- 4 files changed, 29 insertions(+), 5 deletions(-)
drivers/net/wireless/ath/ath12k/core.c +17 -0
@@ -1439,6 +1439,7 @@ static struct ath12k_hw_group *ath12k_core_hw_group_assign(struct ath12k_base *a ab->device_id = ag->num_probed++; ag->ab[ab->device_id] = ab; ab->ag = ag; + ag->mlo_capable = false;return ag; }
@@ -1548,6 +1549,22 @@ static int ath12k_core_hw_group_create(struct ath12k_hw_group *ag)return 0 ; } +void ath12k_core_hw_group_set_mlo_capable (struct ath12k_hw_group *ag) +{ +lockdep_assert_held (&ag->mutex); + +/* If more than one devices are grouped, then inter MLO +* functionality can work still independent of whether internally +* each device supports single_chip_mlo or not. +* Only when there is one device, then it depends whether the +* device can support intra chip MLO or not +*/ +if (ag->num_devices >1 ) + ag->mlo_capable = true; +else + ag->mlo_capable = ag->ab[0 ]->single_chip_mlo_supp; +} +int ath12k_core_init (struct ath12k_base *ab) {struct ath12k_hw_group *ag;
drivers/net/wireless/ath/ath12k/core.h +3 -0
@@ -844,6 +844,7 @@ struct ath12k_hw_group {*/ struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO ];u8 num_hw; +bool mlo_capable; };/* Master structure to hold the hw data which may be used in core module */
@@ -1066,6 +1067,8 @@ u32 ath12k_core_get_max_station_per_radio(struct ath12k_base *ab);u32 ath12k_core_get_max_peers_per_radio (struct ath12k_base *ab);u32 ath12k_core_get_max_num_tids (struct ath12k_base *ab); +void ath12k_core_hw_group_set_mlo_capable (struct ath12k_hw_group *ag); +static inline const char *ath12k_scan_state_str (enum ath12k_scan_state state) {switch (state) {
drivers/net/wireless/ath/ath12k/mac.c +5 -3
@@ -10968,10 +10968,12 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)/* All pdev get combined and register as single wiphy based on * hardware group which participate in multi-link operation else * each pdev get register separately. -* -* Currently, registering as single pdevs. */ - radio_per_hw =1 ; +if (ag->mlo_capable) + radio_per_hw = total_radio; +else + radio_per_hw =1 ; + num_hw = total_radio / radio_per_hw;if (WARN_ON (num_hw >=ATH12K_GROUP_MAX_RADIO ))
drivers/net/wireless/ath/ath12k/qmi.c +4 -2
@@ -2023,9 +2023,9 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,u8 hw_link_id =0 ;int i; -if (!ab->single_chip_mlo_supp) { +if (!ab->ag->mlo_capable) {ath12k_dbg (ab,ATH12K_DBG_QMI , -"intra device MLO is disabled hence skip QMI MLO cap" ); +"MLO is disabled hence skip QMI MLO cap" );return ; }
@@ -3170,6 +3170,8 @@ int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi)mutex_lock (&ag->mutex);if (ath12k_qmi_hw_group_host_cap_ready (ag)) { +ath12k_core_hw_group_set_mlo_capable (ag); + block_ab =ath12k_qmi_hw_group_find_blocked (ag);if (block_ab)ath12k_qmi_trigger_host_cap (block_ab);
Signature · 1 line
2.39.5
Jeff Johnson
AppliedQuoted 9 lines · Kalle Valo
In this patchset there's refactoring to support hardware grouping, meaning multiple hardware devices can be registered to mac80211 as a single device.
Please review.
Aditya Kumar Singh (1):
wifi: ath12k: renamemlo_capable_flagstosingle_chip_mlo_supp[...]
Applied, thanks!
[1/7] wifi: ath12k: move ATH12K_FLAG_REGISTERED handling to ath12k_mac_register()
commit: a5686ae820fa7ab03226a3b0ff529720b7bac599
[2/7] wifi: ath12k: rename mlo_capable_flags to single_chip_mlo_supp
commit: 46d16f7e1d1413ad7ff99c1334d8874623717745
[3/7] wifi: ath12k: introduce device group abstraction
commit: 6f245ea0ec6c29b90c8fa4fdf6e178c646125d7e
[4/7] wifi: ath12k: refactor core start based on hardware group
commit: ee146e11b4d9183e01d8b7e4963941730ed4af6d
[5/7] wifi: ath12k: move struct ath12k_hw from per device to group
commit: a343d97f27f514015e6d5e789672cf4ab4111720
[6/7] wifi: ath12k: send QMI host capability after device group is ready
commit: d302ac65ac938516487f57ae20f11e9cf6327606
[7/7] wifi: ath12k: introduce mlo_capable flag for device group
commit: da8656797ae10b524a7a0c3d5eeb6237fa3ddd70Best regards,
Signature · 1 line
Jeff Johnson <[email protected]>