wifi: ath12k: MLO support part 7
v2 cover wifi: ath12k: MLO support part 7
From: Kalle Valo <[email protected]>
Implementing Multi-Link Operation (MLO) continues. Bindings document is added to get WSI information from DT (patch 1) with the code parsing the information (patch 2). Rest of the patches are about configuring MLO in firmware.
Device Tree bindings were reviewed as RFC earlier:
[RFC PATCH v3 1/5] dt-bindings: net: wireless: Describe ath12k PCI module with WSI
https://lore.kernel.org/ath12k/[email protected]/
The only changes from the RFC are Jeff's email address and using flag instead of bool.
This patchset applies to ath.git main branch. Please review.
Kalle
v2:
* patch 1: change qcom,wsi-controller from a boolean to a flag
v1: https://patchwork.kernel.org/project/linux-wireless/cover/[email protected]/
Bhagavathi Perumal S (1):
wifi: ath12k: Add MLO WMI setup and teardown functions
Karthikeyan Periyasamy (5):
wifi: ath12k: send partner device details in QMI MLO capability
wifi: ath12k: refactor ath12k_qmi_alloc_target_mem_chunk()
wifi: ath12k: add support to allocate MLO global memory region
wifi: ath12k: enable MLO setup and teardown from core
wifi: ath12k: avoid redundant code in DP Rx error process
Raj Kumar Bhagat (2):
dt-bindings: net: wireless: Describe ath12k PCI module with WSI
wifi: ath12k: parse multiple device information from Device Tree
.../net/wireless/qcom,ath12k-wsi.yaml | 205 +++++++++++++ drivers/net/wireless/ath/ath12k/core.c | 256 +++++++++++++++- drivers/net/wireless/ath/ath12k/core.h | 18 ++ drivers/net/wireless/ath/ath12k/dp_rx.c | 13 +- drivers/net/wireless/ath/ath12k/mac.c | 142 +++++++++ drivers/net/wireless/ath/ath12k/mac.h | 3 + drivers/net/wireless/ath/ath12k/qmi.c | 283 ++++++++++++++---- drivers/net/wireless/ath/ath12k/qmi.h | 1 + drivers/net/wireless/ath/ath12k/wmi.c | 180 +++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 49 +++ 10 files changed, 1073 insertions(+), 77 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,ath12k-wsi.yaml
base-commit: 400568fb3b022247c1603fdbdd6444b3ef14ffce
Signature · 1 line
2.39.5
PATCH v2 1/8 dt-bindings: net: wireless: Describe ath12k PCI module with WSI
From: Raj Kumar Bhagat <[email protected]>
The QCN9274 WiFi device supports WSI (WLAN Serial Interface). WSI is used to exchange specific control information across radios using a doorbell mechanism. This WSI connection is essential for exchanging control information among these devices. The WSI interface in the QCN9274 includes TX and RX ports, which are used to connect multiple WSI-supported devices together, forming a WSI group.
Describe QCN9274 PCI wifi device with WSI interface.
--- .../net/wireless/qcom,ath12k-wsi.yaml | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,ath12k-wsi.yaml
Documentation/devicetree/bindings/net/wireless/qcom,ath12k-wsi.yaml new file +205 -0
@@ -0,0 +1,205 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/wireless/qcom,ath12k-wsi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies ath12k wireless devices (PCIe) with WSI interface + +maintainers: + - Jeff Johnson <[email protected]> + - Kalle Valo <[email protected]> + +description: + Qualcomm Technologies IEEE 802.11be PCIe devices with WSI interface. + +properties: + compatible: + enum: + - pci17cb,1109 # QCN9274 + + reg: + maxItems: 1 + + qcom,ath12k-calibration-variant: + $ref: /schemas/types.yaml#/definitions/string + description: + String to uniquely identify variant of the calibration data for designs + with colliding bus and device ids + + qcom,wsi-controller: + $ref: /schemas/types.yaml#/definitions/flag + description: + The WSI controller device in the WSI group aids (is capable) to + synchronize the Timing Synchronization Function (TSF) clock across + all devices in the WSI group. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + description: | + The ath12k devices (QCN9274) feature WSI support. WSI stands for + WLAN Serial Interface. It is used for the exchange of specific + control information across radios based on the doorbell mechanism. + This WSI connection is essential to exchange control information + among these devices. + + Diagram to represent one WSI connection (one WSI group) among + three devices. + + +-------+ +-------+ +-------+ + | pcie1 | | pcie2 | | pcie3 | + | | | | | | + +----->| wsi |------->| wsi |------->| wsi |-----+ + | | grp 0 | | grp 0 | | grp 0 | | + | +-------+ +-------+ +-------+ | + +------------------------------------------------------+ + + Diagram to represent two WSI connections (two separate WSI groups) + among four devices. + + +-------+ +-------+ +-------+ +-------+ + | pcie0 | | pcie1 | | pcie2 | | pcie3 | + | | | | | | | | + +-->| wsi |--->| wsi |--+ +-->| wsi |--->| wsi |--+ + | | grp 0 | | grp 0 | | | | grp 1 | | grp 1 | | + | +-------+ +-------+ | | +-------+ +-------+ | + +---------------------------+ +---------------------------+ + + These ports are used to connect multiple WSI supported devices to + form a WSI group. + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: + This is the TX port of WSI interface. It is attached to the RX + port of the next device in the WSI connection. + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: + This is the RX port of WSI interface. It is attached to the TX + port of the previous device in the WSI connection. + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + pcie { + #address-cells = <3>; + #size-cells = <2>; + + pcie@0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@0 { + compatible = "pci17cb,1109"; + reg = <0x0 0x0 0x0 0x0 0x0>; + + qcom,ath12k-calibration-variant = "RDP433_1"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + wifi1_wsi_tx: endpoint { + remote-endpoint = <&wifi2_wsi_rx>; + }; + }; + + port@1 { + reg = <1>; + + wifi1_wsi_rx: endpoint { + remote-endpoint = <&wifi3_wsi_tx>; + }; + }; + }; + }; + }; + + pcie@1 { + device_type = "pci"; + reg = <0x0 0x0 0x1 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@0 { + compatible = "pci17cb,1109"; + reg = <0x0 0x0 0x0 0x0 0x0>; + + qcom,ath12k-calibration-variant = "RDP433_2"; + qcom,wsi-controller; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + wifi2_wsi_tx: endpoint { + remote-endpoint = <&wifi3_wsi_rx>; + }; + }; + + port@1 { + reg = <1>; + + wifi2_wsi_rx: endpoint { + remote-endpoint = <&wifi1_wsi_tx>; + }; + }; + }; + }; + }; + + pcie@2 { + device_type = "pci"; + reg = <0x0 0x0 0x2 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@0 { + compatible = "pci17cb,1109"; + reg = <0x0 0x0 0x0 0x0 0x0>; + + qcom,ath12k-calibration-variant = "RDP433_3"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + wifi3_wsi_tx: endpoint { + remote-endpoint = <&wifi1_wsi_rx>; + }; + }; + + port@1 { + reg = <1>; + + wifi3_wsi_rx: endpoint { + remote-endpoint = <&wifi2_wsi_tx>; + }; + }; + }; + }; + }; + };
Signature · 1 line
2.39.5
Re: [PATCH v2 1/8] dt-bindings: net: wireless: Describe ath12k PCI module with WSI
Documentation/devicetree/bindings/net/wireless/qcom,ath12k-wsi.yaml
Quoted 23 lines · Kalle Valo
From: Raj Kumar Bhagat <[email protected]>
The QCN9274 WiFi device supports WSI (WLAN Serial Interface). WSI is used to exchange specific control information across radios using a doorbell mechanism. This WSI connection is essential for exchanging control information among these devices. The WSI interface in the QCN9274 includes TX and RX ports, which are used to connect multiple WSI-supported devices together, forming a WSI group.
Describe QCN9274 PCI wifi device with WSI interface.
Signed-off-by Raj Kumar Bhagat <[email protected]>Signed-off-by Kalle Valo <[email protected]>--- .../net/wireless/qcom,ath12k-wsi.yaml | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,ath12k-wsi.yamlDocumentation/devicetree/bindings/net/wireless/qcom,ath12k-wsi.yaml new file +0
-0
Usually I'd comment on the mismatch between this and the compatible, but naming the file after the pcie id would do noone any favours. This seems fine to me,
Cheers,
Conor.
PATCH v2 2/8 wifi: ath12k: parse multiple device information from Device Tree
In reply to Kalle ValoFrom: Raj Kumar Bhagat <[email protected]>
Currently, a single device is part of the device group abstraction. However, for multi-link operations, multiple devices need to be combined. This multi-device grouping is done via WSI (WLAN Serial Interface), which is described in the Device Tree. Information about different WSI groups and the number of devices involved in each group can be parsed from the Device Tree.
Add changes to parse the Device Tree and determine WSI information, such as the different WSI groups and the number of devices per WSI group. Assign WSI index zero to the WSI controller device (to synchronize the clock among the devices within the WSI group), and increment the WSI index of each device in the order of the WSI connection.
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 | 183 +++++++++++++++++++++++-- drivers/net/wireless/ath/ath12k/core.h | 8 ++ 2 files changed, 178 insertions(+), 13 deletions(-)
drivers/net/wireless/ath/ath12k/core.c +170 -13
@@ -9,6 +9,7 @@#include <linux/remoteproc.h> #include <linux/firmware.h> #include <linux/of.h> +#include <linux/of_graph.h> #include "core.h" #include "dp_tx.h" #include "dp_rx.h"
@@ -1383,20 +1384,24 @@ bool ath12k_core_hw_group_create_ready(struct ath12k_hw_group *ag)return (ag->num_probed == ag->num_devices); } -static struct ath12k_hw_group *ath12k_core_hw_group_alloc (u8 id,u8 max_devices) +static struct ath12k_hw_group *ath12k_core_hw_group_alloc (struct ath12k_base *ab) {struct ath12k_hw_group *ag; +int count =0 ;lockdep_assert_held (&ath12k_hw_group_mutex); +list_for_each_entry (ag, &ath12k_hw_group_list, list) + count++; + ag =kzalloc (sizeof (*ag),GFP_KERNEL );if (!ag)return NULL ; - ag->id = id; - ag->num_devices = max_devices; + ag->id = count;list_add (&ag->list, &ath12k_hw_group_list);mutex_init (&ag->mutex); + ag->mlo_capable = false;return ag; }
@@ -1411,35 +1416,180 @@ static void ath12k_core_hw_group_free(struct ath12k_hw_group *ag)mutex_unlock (&ath12k_hw_group_mutex); } +static struct ath12k_hw_group *ath12k_core_hw_group_find_by_dt (struct ath12k_base *ab) +{ +struct ath12k_hw_group *ag; +int i; + +if (!ab->dev->of_node) +return NULL ; + +list_for_each_entry (ag, &ath12k_hw_group_list, list) +for (i =0 ; i < ag->num_devices; i++) +if (ag->wsi_node[i] == ab->dev->of_node) +return ag; + +return NULL ; +} + +static int ath12k_core_get_wsi_info (struct ath12k_hw_group *ag, +struct ath12k_base *ab) +{ +struct device_node *wsi_dev = ab->dev->of_node, *next_wsi_dev; +struct device_node *tx_endpoint, *next_rx_endpoint; +int device_count =0 ; + + next_wsi_dev = wsi_dev; + +if (!next_wsi_dev) +return -ENODEV ; + +do { + ag->wsi_node[device_count] = next_wsi_dev; + + tx_endpoint =of_graph_get_endpoint_by_regs (next_wsi_dev,0 ,-1 ); +if (!tx_endpoint) { +of_node_put (next_wsi_dev); +return -ENODEV ; + } + + next_rx_endpoint =of_graph_get_remote_endpoint (tx_endpoint); +if (!next_rx_endpoint) { +of_node_put (next_wsi_dev); +of_node_put (tx_endpoint); +return -ENODEV ; + } + +of_node_put (tx_endpoint); +of_node_put (next_wsi_dev); + + next_wsi_dev =of_graph_get_port_parent (next_rx_endpoint); +if (!next_wsi_dev) { +of_node_put (next_rx_endpoint); +return -ENODEV ; + } + +of_node_put (next_rx_endpoint); + + device_count++; +if (device_count >ATH12K_MAX_SOCS ) { +ath12k_warn (ab,"device count in DT %d is more than limit %d\n" , + device_count,ATH12K_MAX_SOCS ); +of_node_put (next_wsi_dev); +return -EINVAL ; + } + }while (wsi_dev != next_wsi_dev); + +of_node_put (next_wsi_dev); + ag->num_devices = device_count; + +return 0 ; +} + +static int ath12k_core_get_wsi_index (struct ath12k_hw_group *ag, +struct ath12k_base *ab) +{ +int i, wsi_controller_index =-1 , node_index =-1 ; +bool control; + +for (i =0 ; i < ag->num_devices; i++) { + control =of_property_read_bool (ag->wsi_node[i],"qcom,wsi-controller" ); +if (control) + wsi_controller_index = i; + +if (ag->wsi_node[i] == ab->dev->of_node) + node_index = i; + } + +if (wsi_controller_index ==-1 ) { +ath12k_dbg (ab,ATH12K_DBG_BOOT ,"wsi controller is not defined in dt" ); +return -EINVAL ; + } + +if (node_index ==-1 ) { +ath12k_dbg (ab,ATH12K_DBG_BOOT ,"unable to get WSI node index" ); +return -EINVAL ; + } + + ab->wsi_info.index = (ag->num_devices + node_index - wsi_controller_index) % + ag->num_devices; + +return 0 ; +} +static struct ath12k_hw_group *ath12k_core_hw_group_assign (struct ath12k_base *ab) { -u32 group_id =ATH12K_INVALID_GROUP_ID ; +struct ath12k_wsi_info *wsi = &ab->wsi_info;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. * -* 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. +* We use group id ATH12K_INVALID_GROUP_ID for single device group +* which didn't have dt entry or wrong dt entry, there could be many +* groups with same group id, i.e ATH12K_INVALID_GROUP_ID. So +* default group id of ATH12K_INVALID_GROUP_ID combined with +* num devices in ath12k_hw_group determines if the group is +* multi device or single device group */ - ag =ath12k_core_hw_group_alloc (group_id,1 ); + + ag =ath12k_core_hw_group_find_by_dt (ab); +if (!ag) { + ag =ath12k_core_hw_group_alloc (ab); +if (!ag) { +ath12k_warn (ab,"unable to create new hw group\n" ); +return NULL ; + } + +if (ath12k_core_get_wsi_info (ag, ab) || +ath12k_core_get_wsi_index (ag, ab)) { +ath12k_dbg (ab,ATH12K_DBG_BOOT , +"unable to get wsi info from dt, grouping single device" ); + ag->id =ATH12K_INVALID_GROUP_ID ; + ag->num_devices =1 ; +memset (ag->wsi_node,0 ,sizeof (ag->wsi_node)); + wsi->index =0 ; + } + + goto exit; + }else if (test_bit (ATH12K_GROUP_FLAG_UNREGISTER , &ag->flags)) { +ath12k_dbg (ab,ATH12K_DBG_BOOT ,"group id %d in unregister state\n" , + ag->id); + goto invalid_group; + }else { +if (ath12k_core_get_wsi_index (ag, ab)) + goto invalid_group; + goto exit; + } + +invalid_group: + ag =ath12k_core_hw_group_alloc (ab);if (!ag) {ath12k_warn (ab,"unable to create new hw group\n" );return NULL ; } + ag->id =ATH12K_INVALID_GROUP_ID ; + ag->num_devices =1 ; + wsi->index =0 ; +ath12k_dbg (ab,ATH12K_DBG_BOOT ,"single device added to hardware group\n" ); +exit: +if (ag->num_probed >= ag->num_devices) { +ath12k_warn (ab,"unable to add new device to group, max limit reached\n" ); + goto invalid_group; + } + ab->device_id = ag->num_probed++; ag->ab[ab->device_id] = ab; ab->ag = ag; - ag->mlo_capable = false; + +ath12k_dbg (ab,ATH12K_DBG_BOOT ,"wsi group-id %d num-devices %d index %d" , + ag->id, ag->num_devices, wsi->index);return ag; }
@@ -1507,6 +1657,13 @@ static void ath12k_core_hw_group_cleanup(struct ath12k_hw_group *ag)mutex_lock (&ag->mutex); +if (test_bit (ATH12K_GROUP_FLAG_UNREGISTER , &ag->flags)) { +mutex_unlock (&ag->mutex); +return ; + } + +set_bit (ATH12K_GROUP_FLAG_UNREGISTER , &ag->flags); +ath12k_core_hw_group_stop (ag);for (i =0 ; i < ag->num_devices; i++) {
drivers/net/wireless/ath/ath12k/core.h +8 -0
@@ -219,6 +219,7 @@ enum ath12k_scan_state {enum ath12k_hw_group_flags {ATH12K_GROUP_FLAG_REGISTERED , +ATH12K_GROUP_FLAG_UNREGISTER , };enum ath12k_dev_flags {
@@ -845,6 +846,12 @@ struct ath12k_hw_group {struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO ];u8 num_hw;bool mlo_capable; +struct device_node *wsi_node[ATH12K_MAX_SOCS ]; +}; + +/* Holds WSI info specific to each device, excluding WSI group info */ +struct ath12k_wsi_info { +u32 index; };/* Master structure to hold the hw data which may be used in core module */
@@ -1028,6 +1035,7 @@ struct ath12k_base {struct notifier_block panic_nb;struct ath12k_hw_group *ag; +struct ath12k_wsi_info wsi_info;/* must be last */ u8 drv_priv[]__aligned(sizeof(void *)) ;
Signature · 1 line
2.39.5
PATCH v2 3/8 wifi: ath12k: send partner device details in QMI MLO capability
In reply to Kalle ValoFrom: Karthikeyan Periyasamy <[email protected]>
Currently, QMI MLO host capability is sent with the details of local links and hw_link id only for particular device. But in the case of multi device group abstraction, it has to include the details of hw_link_id, num_local_links of every partner device that is involved in the group during QMI MLO capability exchange. Add changes to send partner device details to the firmware in QMI MLO capability exchange.
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/qmi.c | 88 ++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 16 deletions(-)
drivers/net/wireless/ath/ath12k/qmi.c +72 -16
@@ -2016,17 +2016,19 @@ static const struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = { }, }; -static void ath12k_host_cap_parse_mlo (struct ath12k_base *ab, -struct qmi_wlanfw_host_cap_req_msg_v01 *req) +static int ath12k_host_cap_parse_mlo (struct ath12k_base *ab, +struct qmi_wlanfw_host_cap_req_msg_v01 *req) {struct wlfw_host_mlo_chip_info_s_v01 *info; +struct ath12k_hw_group *ag = ab->ag; +struct ath12k_base *partner_ab;u8 hw_link_id =0 ; -int i; +int i, j, ret; -if (!ab->ag->mlo_capable) { +if (!ag->mlo_capable) {ath12k_dbg (ab,ATH12K_DBG_QMI ,"MLO is disabled hence skip QMI MLO cap" ); -return ; +return 0 ; }if (!ab->qmi.num_radios || ab->qmi.num_radios ==U8_MAX ) {
@@ -2035,7 +2037,12 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,ath12k_dbg (ab,ATH12K_DBG_QMI ,"skip QMI MLO cap due to invalid num_radio %d\n" , ab->qmi.num_radios); -return ; +return 0 ; + } + +if (ab->device_id ==ATH12K_INVALID_DEVICE_ID ) { +ath12k_err (ab,"failed to send MLO cap due to invalid device id\n" ); +return -EINVAL ; } req->mlo_capable_valid =1 ;
@@ -2043,27 +2050,74 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab, req->mlo_chip_id_valid =1 ; req->mlo_chip_id = ab->device_id; req->mlo_group_id_valid =1 ; - req->mlo_group_id =0 ; + req->mlo_group_id = ag->id; req->max_mlo_peer_valid =1 ;/* Max peer number generally won't change for the same device * but needs to be synced with host driver. */ req->max_mlo_peer = ab->hw_params->max_mlo_peer; req->mlo_num_chips_valid =1 ; - req->mlo_num_chips =1 ; + req->mlo_num_chips = ag->num_devices; - info = &req->mlo_chip_info[0 ]; - info->chip_id = ab->device_id; - info->num_local_links = ab->qmi.num_radios; +mutex_lock (&ag->mutex); -for (i =0 ; i < info->num_local_links; i++) { - info->hw_link_id[i] = hw_link_id; - info->valid_mlo_link_id[i] =1 ; +for (i =0 ; i < ag->num_devices; i++) { + info = &req->mlo_chip_info[i]; + partner_ab = ag->ab[i]; - hw_link_id++; +if (partner_ab->device_id ==ATH12K_INVALID_DEVICE_ID ) { +ath12k_err (ab,"failed to send MLO cap due to invalid partner device id\n" ); + ret = -EINVAL ; + goto device_cleanup; + } + + info->chip_id = partner_ab->device_id; + info->num_local_links = partner_ab->qmi.num_radios; + +ath12k_dbg (ab,ATH12K_DBG_QMI ,"mlo device id %d num_link %d\n" , + info->chip_id, info->num_local_links); + +for (j =0 ; j < info->num_local_links; j++) { + info->hw_link_id[j] = hw_link_id; + info->valid_mlo_link_id[j] =1 ; + + hw_link_id++; + } } +if (hw_link_id <=0 ) + ag->mlo_capable = false; + req->mlo_chip_info_valid =1 ; + +mutex_unlock (&ag->mutex); + +return 0 ; + +device_cleanup: +for (i = i -1 ; i >=0 ; i--) { + info = &req->mlo_chip_info[i]; + +memset (info,0 ,sizeof (*info)); + } + + req->mlo_num_chips =0 ; + req->mlo_num_chips_valid =0 ; + + req->max_mlo_peer =0 ; + req->max_mlo_peer_valid =0 ; + req->mlo_group_id =0 ; + req->mlo_group_id_valid =0 ; + req->mlo_chip_id =0 ; + req->mlo_chip_id_valid =0 ; + req->mlo_capable =0 ; + req->mlo_capable_valid =0 ; + + ag->mlo_capable = false; + +mutex_unlock (&ag->mutex); + +return ret; }/* clang stack usage explodes if this is inlined */
@@ -2113,7 +2167,9 @@ int ath12k_qmi_host_cap_send(struct ath12k_base *ab) req.nm_modem |=PLATFORM_CAP_PCIE_GLOBAL_RESET ; } -ath12k_host_cap_parse_mlo (ab, &req); + ret =ath12k_host_cap_parse_mlo (ab, &req); +if (ret <0 ) + goto out; ret =qmi_txn_init (&ab->qmi.handle, &txn, qmi_wlanfw_host_cap_resp_msg_v01_ei, &resp);
Signature · 1 line
2.39.5
PATCH v2 4/8 wifi: ath12k: refactor ath12k_qmi_alloc_target_mem_chunk()
In reply to Kalle ValoFrom: Karthikeyan Periyasamy <[email protected]>
Currently, all QMI target memory types share the same allocation logic within ath12k_qmi_alloc_target_mem_chunk(). However, for Multi-Link Operation (MLO), the firmware requests a new MLO global memory region. This memory is shared across different firmware (SoC) participating in the MLO. To accommodate this logic change, refactor ath12k_qmi_alloc_target_mem_chunk() and introduce a helper function ath12k_qmi_alloc_chunk() for memory chunk allocation. Subsequent patch will add MLO global memory allocation logic.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00210-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/qmi.c | 82 ++++++++++++++------------- 1 file changed, 44 insertions(+), 38 deletions(-)
drivers/net/wireless/ath/ath12k/qmi.c +44 -38
@@ -2423,9 +2423,50 @@ static void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab) } } +static int ath12k_qmi_alloc_chunk (struct ath12k_base *ab, +struct target_mem_chunk *chunk) +{ +/* Firmware reloads in recovery/resume. +* In such cases, no need to allocate memory for FW again. +*/ +if (chunk->v.addr) { +if (chunk->prev_type == chunk->type && + chunk->prev_size == chunk->size) + goto this_chunk_done; + +/* cannot reuse the existing chunk */ +dma_free_coherent (ab->dev, chunk->prev_size, + chunk->v.addr, chunk->paddr); + chunk->v.addr =NULL ; + } + + chunk->v.addr =dma_alloc_coherent (ab->dev, + chunk->size, + &chunk->paddr, +GFP_KERNEL | __GFP_NOWARN); +if (!chunk->v.addr) { +if (chunk->size >ATH12K_QMI_MAX_CHUNK_SIZE ) { + ab->qmi.target_mem_delayed = true; +ath12k_warn (ab, +"qmi dma allocation failed (%d B type %u), will try later with small size\n" , + chunk->size, + chunk->type); +ath12k_qmi_free_target_mem_chunk (ab); +return 0 ; + } +ath12k_warn (ab,"memory allocation failure for %u size: %d\n" , + chunk->type, chunk->size); +return -ENOMEM ; + } + chunk->prev_type = chunk->type; + chunk->prev_size = chunk->size; +this_chunk_done: +return 0 ; +} +static int ath12k_qmi_alloc_target_mem_chunk (struct ath12k_base *ab) { -int i; +int i, ret =0 ;struct target_mem_chunk *chunk; ab->qmi.target_mem_delayed = false;
@@ -2442,42 +2483,7 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab)case M3_DUMP_REGION_TYPE :case PAGEABLE_MEM_REGION_TYPE :case CALDB_MEM_REGION_TYPE : -/* Firmware reloads in recovery/resume. -* In such cases, no need to allocate memory for FW again. -*/ -if (chunk->v.addr) { -if (chunk->prev_type == chunk->type && - chunk->prev_size == chunk->size) - goto this_chunk_done; - -/* cannot reuse the existing chunk */ -dma_free_coherent (ab->dev, chunk->prev_size, - chunk->v.addr, chunk->paddr); - chunk->v.addr =NULL ; - } - - chunk->v.addr =dma_alloc_coherent (ab->dev, - chunk->size, - &chunk->paddr, -GFP_KERNEL | __GFP_NOWARN); -if (!chunk->v.addr) { -if (chunk->size >ATH12K_QMI_MAX_CHUNK_SIZE ) { - ab->qmi.target_mem_delayed = true; -ath12k_warn (ab, -"qmi dma allocation failed (%d B type %u), will try later with small size\n" , - chunk->size, - chunk->type); -ath12k_qmi_free_target_mem_chunk (ab); -return 0 ; - } -ath12k_warn (ab,"memory allocation failure for %u size: %d\n" , - chunk->type, chunk->size); -return -ENOMEM ; - } - - chunk->prev_type = chunk->type; - chunk->prev_size = chunk->size; -this_chunk_done: + ret =ath12k_qmi_alloc_chunk (ab, chunk);break ;default : ath12k_warn(ab, "memory type %u not supported\n",
@@ -2487,7 +2493,7 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab)break ; } } -return 0 ; +return ret; }/* clang stack usage explodes if this is inlined */
Signature · 1 line
2.39.5
PATCH v2 5/8 wifi: ath12k: add support to allocate MLO global memory region
In reply to Kalle ValoFrom: Karthikeyan Periyasamy <[email protected]>
To enable Multi-Link Operation (MLO), QCN9274 firmware requests MLO global memory (MLO_GLOBAL_MEM_REGION_TYPE). This memory region is shared across all the firmware (SoC) that are participation in the MLO.
Hence, add support to allocate and free MLO global memory region. Allocate one MLO global memory per struct ath12k_hw_group and assign the same memory to all firmware in the same struct ath12k_hw_group. WCN7850 firmware does not request this memory type, therefore this change will have no impact on WCN7850 device.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00210-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.h | 7 ++ drivers/net/wireless/ath/ath12k/qmi.c | 127 +++++++++++++++++++++++-- drivers/net/wireless/ath/ath12k/qmi.h | 1 + 3 files changed, 125 insertions(+), 10 deletions(-)
drivers/net/wireless/ath/ath12k/core.h +7 -0
@@ -822,6 +822,12 @@ struct ath12k_soc_dp_stats {struct ath12k_soc_dp_tx_err_stats tx_err; }; +struct ath12k_mlo_memory { +struct target_mem_chunk chunk[ATH12K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01 ]; +int mlo_mem_size; +bool init_done; +}; +/* Holds info on the group of devices that are registered as a single * wiphy, protected with struct ath12k_hw_group::mutex. */
@@ -847,6 +853,7 @@ struct ath12k_hw_group {u8 num_hw;bool mlo_capable;struct device_node *wsi_node[ATH12K_MAX_SOCS ]; +struct ath12k_mlo_memory mlo_mem; };/* Holds WSI info specific to each device, excluding WSI group info */
drivers/net/wireless/ath/ath12k/qmi.c +117 -10
160 lines not on this page · raw message
drivers/net/wireless/ath/ath12k/qmi.h +1 -0
@@ -172,6 +172,7 @@ enum ath12k_qmi_target_mem {BDF_MEM_REGION_TYPE =0x2 ,M3_DUMP_REGION_TYPE =0x3 ,CALDB_MEM_REGION_TYPE =0x4 , +MLO_GLOBAL_MEM_REGION_TYPE =0x8 , PAGEABLE_MEM_REGION_TYPE = 0x9, };
Signature · 1 line
2.39.5
PATCH v2 6/8 wifi: ath12k: Add MLO WMI setup and teardown functions
In reply to Kalle ValoFrom: Bhagavathi Perumal S <[email protected]>
In case of multi device group abstraction, host has to exchange the MLO commands such as setup, teardown and ready to firmware.
Once multi device group is ready, host has to exchange MLO setup command with partner devices link information and followed by MLO ready command to firmware. During deinit, MLO teardown command should be sent to firmware. Firmware would send MLO setup complete and MLO teardown complete to host for MLO setup command and MLO teardown command respectively.
Added WMI helper functions for the MLO setup, ready and teardown command and the handling for corresponding event from firmware. Add appropriate WMI tag, command id and event id to parse the event and send request.
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/wmi.c | 177 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 48 +++++++ 2 files changed, 225 insertions(+)
drivers/net/wireless/ath/ath12k/wmi.c +177 -0
@@ -7327,6 +7327,76 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,kfree (tb); } +static void ath12k_wmi_event_mlo_setup_complete (struct ath12k_base *ab, +struct sk_buff *skb) +{ +const struct wmi_mlo_setup_complete_event *ev; +struct ath12k *ar =NULL ; +struct ath12k_pdev *pdev; +const void **tb; +int ret, i; + + tb =ath12k_wmi_tlv_parse_alloc (ab, skb,GFP_ATOMIC ); +if (IS_ERR (tb)) { + ret =PTR_ERR (tb); +ath12k_warn (ab,"failed to parse mlo setup complete event tlv: %d\n" , + ret); +return ; + } + + ev = tb[WMI_TAG_MLO_SETUP_COMPLETE_EVENT ]; +if (!ev) { +ath12k_warn (ab,"failed to fetch mlo setup complete event\n" ); +kfree (tb); +return ; + } + +if (le32_to_cpu (ev->pdev_id) > ab->num_radios) + goto skip_lookup; + +for (i =0 ; i < ab->num_radios; i++) { + pdev = &ab->pdevs[i]; +if (pdev && pdev->pdev_id ==le32_to_cpu (ev->pdev_id)) { + ar = pdev->ar; +break ; + } + } + +skip_lookup: +if (!ar) { +ath12k_warn (ab,"invalid pdev_id %d status %u in setup complete event\n" , + ev->pdev_id, ev->status); + goto out; + } + +out: +kfree (tb); +} + +static void ath12k_wmi_event_teardown_complete (struct ath12k_base *ab, +struct sk_buff *skb) +{ +const struct wmi_mlo_teardown_complete_event *ev; +const void **tb; +int ret; + + tb =ath12k_wmi_tlv_parse_alloc (ab, skb,GFP_ATOMIC ); +if (IS_ERR (tb)) { + ret =PTR_ERR (tb); +ath12k_warn (ab,"failed to parse teardown complete event tlv: %d\n" , ret); +return ; + } + + ev = tb[WMI_TAG_MLO_TEARDOWN_COMPLETE ]; +if (!ev) { +ath12k_warn (ab,"failed to fetch teardown complete event\n" ); +kfree (tb); +return ; + } + +kfree (tb); +} +static void ath12k_wmi_op_rx (struct ath12k_base *ab,struct sk_buff *skb) {struct wmi_cmd_hdr *cmd_hdr;
@@ -7453,6 +7523,12 @@ static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)case WMI_GTK_OFFLOAD_STATUS_EVENTID :ath12k_wmi_gtk_offload_status_event (ab, skb);break ; +case WMI_MLO_SETUP_COMPLETE_EVENTID : +ath12k_wmi_event_mlo_setup_complete (ab, skb); +break ; +case WMI_MLO_TEARDOWN_COMPLETE_EVENTID : +ath12k_wmi_event_teardown_complete (ab, skb); +break ;/* TODO: Add remaining events */ default :ath12k_dbg (ab,ATH12K_DBG_WMI ,"Unknown eventid: 0x%x\n" , id);
@@ -8269,3 +8345,104 @@ int ath12k_wmi_sta_keepalive(struct ath12k *ar,return ath12k_wmi_cmd_send (wmi, skb,WMI_STA_KEEPALIVE_CMDID ); } + +int ath12k_wmi_mlo_setup (struct ath12k *ar,struct wmi_mlo_setup_arg *mlo_params) +{ +struct wmi_mlo_setup_cmd *cmd; +struct ath12k_wmi_pdev *wmi = ar->wmi; +u32 *partner_links, num_links; +int i, ret, buf_len, arg_len; +struct sk_buff *skb; +struct wmi_tlv *tlv; +void *ptr; + + num_links = mlo_params->num_partner_links; + arg_len = num_links *sizeof (u32); + buf_len =sizeof (*cmd) +TLV_HDR_SIZE + arg_len; + + skb =ath12k_wmi_alloc_skb (wmi->wmi_ab, buf_len); +if (!skb) +return -ENOMEM ; + + cmd = (struct wmi_mlo_setup_cmd *)skb->data; + cmd->tlv_header =ath12k_wmi_tlv_cmd_hdr (WMI_TAG_MLO_SETUP_CMD , +sizeof (*cmd)); + cmd->mld_group_id = mlo_params->group_id; + cmd->pdev_id =cpu_to_le32 (ar->pdev->pdev_id); + ptr = skb->data +sizeof (*cmd); + + tlv = ptr; + tlv->header =ath12k_wmi_tlv_hdr (WMI_TAG_ARRAY_UINT32 , arg_len); + ptr +=TLV_HDR_SIZE ; + + partner_links = ptr; +for (i =0 ; i < num_links; i++) + partner_links[i] = mlo_params->partner_link_id[i]; + + ret =ath12k_wmi_cmd_send (wmi, skb,WMI_MLO_SETUP_CMDID ); +if (ret) { +ath12k_warn (ar->ab,"failed to submit WMI_MLO_SETUP_CMDID command: %d\n" , + ret); +dev_kfree_skb (skb); +return ret; + } + +return 0 ; +} + +int ath12k_wmi_mlo_ready (struct ath12k *ar) +{ +struct wmi_mlo_ready_cmd *cmd; +struct ath12k_wmi_pdev *wmi = ar->wmi; +struct sk_buff *skb; +int ret, len; + + len =sizeof (*cmd); + skb =ath12k_wmi_alloc_skb (wmi->wmi_ab, len); +if (!skb) +return -ENOMEM ; + + cmd = (struct wmi_mlo_ready_cmd *)skb->data; + cmd->tlv_header =ath12k_wmi_tlv_cmd_hdr (WMI_TAG_MLO_READY_CMD , +sizeof (*cmd)); + cmd->pdev_id =cpu_to_le32 (ar->pdev->pdev_id); + + ret =ath12k_wmi_cmd_send (wmi, skb,WMI_MLO_READY_CMDID ); +if (ret) { +ath12k_warn (ar->ab,"failed to submit WMI_MLO_READY_CMDID command: %d\n" , + ret); +dev_kfree_skb (skb); +return ret; + } + +return 0 ; +} + +int ath12k_wmi_mlo_teardown (struct ath12k *ar) +{ +struct wmi_mlo_teardown_cmd *cmd; +struct ath12k_wmi_pdev *wmi = ar->wmi; +struct sk_buff *skb; +int ret, len; + + len =sizeof (*cmd); + skb =ath12k_wmi_alloc_skb (wmi->wmi_ab, len); +if (!skb) +return -ENOMEM ; + + cmd = (struct wmi_mlo_teardown_cmd *)skb->data; + cmd->tlv_header =ath12k_wmi_tlv_cmd_hdr (WMI_TAG_MLO_TEARDOWN_CMD , +sizeof (*cmd)); + cmd->pdev_id =cpu_to_le32 (ar->pdev->pdev_id); + cmd->reason_code =WMI_MLO_TEARDOWN_SSR_REASON ; + + ret =ath12k_wmi_cmd_send (wmi, skb,WMI_MLO_TEARDOWN_CMDID ); +if (ret) { +ath12k_warn (ar->ab,"failed to submit WMI MLO teardown command: %d\n" , + ret); +dev_kfree_skb (skb); +return ret; + } + +return 0 ; +}
drivers/net/wireless/ath/ath12k/wmi.h +48 -0
77 lines not on this page · raw message
Signature · 1 line
2.39.5
PATCH v2 7/8 wifi: ath12k: enable MLO setup and teardown from core
In reply to Kalle ValoFrom: Karthikeyan Periyasamy <[email protected]>
In case of multi device group abstraction, host has to exchange the multi-link operation commands such as setup and ready to firmware before registering the device group to mac80211.
The multi-link operation commands - setup, ready and teardown are necessary for many commands such as WMI_PEER_ASSOC_CMD, WMI_BCN_TMPL_CMD in case of multi-link interfaces.
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 | 73 ++++++++++++- drivers/net/wireless/ath/ath12k/core.h | 3 + drivers/net/wireless/ath/ath12k/mac.c | 142 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/mac.h | 3 + drivers/net/wireless/ath/ath12k/wmi.c | 3 + drivers/net/wireless/ath/ath12k/wmi.h | 1 + 6 files changed, 224 insertions(+), 1 deletion(-)
drivers/net/wireless/ath/ath12k/core.c +72 -1
@@ -887,6 +887,70 @@ static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag)ath12k_mac_destroy (ag); } +static int __ath12k_mac_mlo_ready (struct ath12k *ar) +{ +int ret; + + ret =ath12k_wmi_mlo_ready (ar); +if (ret) { +ath12k_err (ar->ab,"MLO ready failed for pdev %d: %d\n" , + ar->pdev_idx, ret); +return ret; + } + +ath12k_dbg (ar->ab,ATH12K_DBG_MAC ,"mlo ready done for pdev %d\n" , + ar->pdev_idx); + +return 0 ; +} + +int ath12k_mac_mlo_ready (struct ath12k_hw_group *ag) +{ +struct ath12k_hw *ah; +struct ath12k *ar; +int ret; +int i, j; + +for (i =0 ; i < ag->num_hw; i++) { + ah = ag->ah[i]; +if (!ah) +continue ; + +for_each_ar (ah, ar, j) { + ar = &ah->radio[j]; + ret =__ath12k_mac_mlo_ready (ar); +if (ret) + goto out; + } + } + +out: +return ret; +} + +static int ath12k_core_mlo_setup (struct ath12k_hw_group *ag) +{ +int ret; + +if (!ag->mlo_capable || ag->num_devices ==1 ) +return 0 ; + + ret =ath12k_mac_mlo_setup (ag); +if (ret) +return ret; + + ret =ath12k_mac_mlo_ready (ag); +if (ret) + goto err_mlo_teardown; + +return 0 ; + +err_mlo_teardown: +ath12k_mac_mlo_teardown (ag); + +return ret; +} +static int ath12k_core_hw_group_start (struct ath12k_hw_group *ag) {struct ath12k_base *ab;
@@ -901,10 +965,14 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag)if (WARN_ON (ret))return ret; - ret =ath12k_mac_register (ag); + ret =ath12k_core_mlo_setup (ag);if (WARN_ON (ret)) goto err_mac_destroy; + ret =ath12k_mac_register (ag); +if (WARN_ON (ret)) + goto err_mlo_teardown; +set_bit (ATH12K_GROUP_FLAG_REGISTERED , &ag->flags); core_pdev_create:
@@ -939,6 +1007,9 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag)ath12k_core_hw_group_stop (ag);return ret; +err_mlo_teardown: +ath12k_mac_mlo_teardown (ag); + err_mac_destroy:ath12k_mac_destroy (ag);
drivers/net/wireless/ath/ath12k/core.h +3 -0
@@ -715,6 +715,9 @@ struct ath12k {u32 freq_high;bool nlo_enabled; + +struct completion mlo_setup_done; +u32 mlo_setup_status; };struct ath12k_hw {
drivers/net/wireless/ath/ath12k/mac.c +142 -0
154 lines not on this page · raw message
drivers/net/wireless/ath/ath12k/mac.h +3 -0
@@ -96,6 +96,9 @@ int ath12k_mac_vif_set_keepalive(struct ath12k_link_vif *arvif,enum wmi_sta_keepalive_method method, u32 interval);u8 ath12k_mac_get_target_pdev_id (struct ath12k *ar); +int ath12k_mac_mlo_setup (struct ath12k_hw_group *ag); +int ath12k_mac_mlo_ready (struct ath12k_hw_group *ag); +void ath12k_mac_mlo_teardown (struct ath12k_hw_group *ag);int ath12k_mac_vdev_stop (struct ath12k_link_vif *arvif);#endif
drivers/net/wireless/ath/ath12k/wmi.c +3 -0
@@ -7369,6 +7369,9 @@ static void ath12k_wmi_event_mlo_setup_complete(struct ath12k_base *ab, goto out; } + ar->mlo_setup_status =le32_to_cpu (ev->status); +complete (&ar->mlo_setup_done); + out:kfree (tb); }
drivers/net/wireless/ath/ath12k/wmi.h +1 -0
@@ -4938,6 +4938,7 @@ struct wmi_probe_tmpl_cmd {#define MAX_RADIOS 2 +#define WMI_MLO_CMD_TIMEOUT_HZ (5 * HZ)#define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ)#define WMI_SEND_TIMEOUT_HZ (3 * HZ)
Signature · 1 line
2.39.5
PATCH v2 8/8 wifi: ath12k: avoid redundant code in DP Rx error process
In reply to Kalle ValoFrom: Karthikeyan Periyasamy <[email protected]>
Currently, in DP rx error processing, the MAC id is fetched redundantly from the same descriptor for each MSDU. To avoid this redundancy, move the fetch handling before the iteration.
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/dp_rx.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/net/wireless/ath/ath12k/dp_rx.c +7 -6
@@ -3516,6 +3516,13 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi, ret);continue ; } + + mac_id =le32_get_bits (reo_desc->info0, +HAL_REO_DEST_RING_INFO0_SRC_LINK_ID ); + + pdev_id =ath12k_hw_mac_id_to_pdev_id (ab->hw_params, mac_id); + ar = ab->pdevs[pdev_id].ar; + link_desc_va = link_desc_banks[desc_bank].vaddr + (paddr - link_desc_banks[desc_bank].paddr); ath12k_hal_rx_msdu_link_info_get(link_desc_va, &num_msdus, msdu_cookies,
@@ -3544,12 +3551,6 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi, } for (i = 0; i < num_msdus; i++) { - mac_id = le32_get_bits(reo_desc->info0, - HAL_REO_DEST_RING_INFO0_SRC_LINK_ID); - - pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id); - ar = ab->pdevs[pdev_id].ar; - if (!ath12k_dp_process_rx_err_buf(ar, reo_desc, &rx_desc_used_list, drop,
Signature · 1 line
2.39.5