From patchwork Wed Dec 11 15:34:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 850047 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 98ACE13B2A9; Wed, 11 Dec 2024 15:34:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931277; cv=none; b=VV5g4k7YN5rvOxXPxPmIYrS2LWSR9YtQgGt5uCD4iouvRWSii4l1dGnx6Yihr8OIa6rZJCI9VS2DBegGZZY2fLj75cecQ7S+QEx1/P1HYxTjl46c08MjN33n20oxVVQBW+d6ecq/SL1O9XkCQf8DOKgzeGQ469Hm/ei9AFgPtnc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931277; c=relaxed/simple; bh=gD+erWKg1WYx/d4VCqYCo1hgx/4qc9+Utl+HoeSnyT8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=jCIfY+HssBNiZ1rqbJHzv860Peeh3W8G0J6pY6WYLVfycTNeM/yGqMPYAwvmDds1XbyGuWr6nW7frDwgGFKMixx20PFw/YAENG6dXXDsFjE6lSkO5rUkTI0YedQnarsSBTQzq1vGwj9R2PWUe1JlCtMrLeNSMb1ifqAZWMnBRbk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hyeNf2pP; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hyeNf2pP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 39C17C4CED4; Wed, 11 Dec 2024 15:34:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733931277; bh=gD+erWKg1WYx/d4VCqYCo1hgx/4qc9+Utl+HoeSnyT8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hyeNf2pPhxf8OrXPynw3ZOnsQRAiKq2XlKgysFLHjNEeondWlJi1qYzAJqvr3nyTw mz3Yah9fUlONwnwrXY7bURsih52xrL+tlzo6lDb80FE5fdDQ4fyFzI7gVc86Ixlf2p WNWGCFUq3OqYxiOvszzEAhhX8fBooyknPPE/Nq52hrip5c9etxr8so0xgEqh4c1NZa doh9hnTTIfg2em46LXr64ffSLauOZX2rWcsHViU2xFvnVAQhBpOUKg2PEPm6VJMjjl pMGMALN8PqTgZI/WFZE3lpvbAtjMP2mpzKf1JJgFI20yVOtYvPop9bOclD38FA47Wi ca2yi+7iUZbow== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v3 1/8] dt-bindings: net: wireless: Describe ath12k PCI module with WSI Date: Wed, 11 Dec 2024 17:34:25 +0200 Message-Id: <20241211153432.775335-2-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241211153432.775335-1-kvalo@kernel.org> References: <20241211153432.775335-1-kvalo@kernel.org> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Raj Kumar Bhagat 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 Signed-off-by: Kalle Valo --- .../net/wireless/qcom,ath12k-wsi.yaml | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,ath12k-wsi.yaml diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath12k-wsi.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath12k-wsi.yaml new file mode 100644 index 000000000000..cbfb559f6b69 --- /dev/null +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath12k-wsi.yaml @@ -0,0 +1,204 @@ +# 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 + - Kalle Valo + +description: | + Qualcomm Technologies IEEE 802.11be PCIe devices with WSI interface. + + 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. + + The WSI interface includes TX and RX ports, which are used to connect + multiple WSI-supported devices together, forming a WSI group. + + 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 | | + | +-------+ +-------+ | | +-------+ +-------+ | + +---------------------------+ +---------------------------+ + +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 + 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>; + }; + }; + }; + }; + }; + }; From patchwork Wed Dec 11 15:34:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 849710 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F8601CF7C3; Wed, 11 Dec 2024 15:34:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931278; cv=none; b=F+yMSanJl9PK9aXy89dElXMz7XhyT9g9UmYzdQJZvO/PXZ8N1La+e0o3Aktjzz47p9Ct3GbPLMw0UqX861ENsgUxXUw9+crxqIKdgxsI7pQZ/bYKy+R3UYyf+OMuBDoXpKn8lzLhebeEQIdBiynyxMBdR3DDeEARPt6i77cBa/Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931278; c=relaxed/simple; bh=4Q8+H2y5FnU0Zo2LpMai5VHA+mQYFkZLKUDC/zyQpog=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=WNJiuORCrFOM1KYKhpkta7300+21cQ9SrhHHhIjt9IbOzFcYIaY4gjc58ClDMM8FMegCKtE6LMDr+VSbUEPJN/TrpeWkBEFadVdIvVk7uJi1zMnicJuA/aCCDU5F5g2vOWgH+AM932vPCF7aGWVi1637tD7N5PGvC7ecoSdgE0w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MG2qRlzD; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MG2qRlzD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 95DC6C4CED2; Wed, 11 Dec 2024 15:34:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733931278; bh=4Q8+H2y5FnU0Zo2LpMai5VHA+mQYFkZLKUDC/zyQpog=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MG2qRlzDJ0qSmd3eeF4x7cpDMGGQ3fb+DZtJARlQoo6aT4OfvUBFlg6udnDBHkoyv uzoIZR8Bb++DAM0Swji/YmF/acuRMG5nnXyeBxkDXleAVjWuWRGZDPvf5gu11xO1+C X1kR/TpkWoYsp7eezOkmeqJl8cmUYrJGUCxF2Kx6rFjhWC6yZeKbHgJI3lWoQ6LhqM PUAMrSuBsvpQ81DpkH5KRNe/iPbJEMo9maUfbEqYClUeWWwBTt14LkSAzOsMoVP/Ia tV98LtL1/kcCkorPRmJiJOlQl1Qlf1c+dSK7EZjMkvSwgb6ggXy1DXGZylIpDQIx6P t+T+ygd+5t17w== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v3 2/8] wifi: ath12k: parse multiple device information from Device Tree Date: Wed, 11 Dec 2024 17:34:26 +0200 Message-Id: <20241211153432.775335-3-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241211153432.775335-1-kvalo@kernel.org> References: <20241211153432.775335-1-kvalo@kernel.org> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Raj Kumar Bhagat 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 Co-developed-by: Harshitha Prem Signed-off-by: Harshitha Prem Signed-off-by: Raj Kumar Bhagat Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/core.c | 183 +++++++++++++++++++++++-- drivers/net/wireless/ath/ath12k/core.h | 8 ++ 2 files changed, 178 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 49d1ac15cb7a..1a43e00cffb2 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -9,6 +9,7 @@ #include #include #include +#include #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++) { diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 458e3d0071a8..d0e466819036 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -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 *)); From patchwork Wed Dec 11 15:34:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 850046 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 43BC71CF7C3; Wed, 11 Dec 2024 15:34:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931280; cv=none; b=rybvuO10CEVFMWSvJjFFJjLvXbCxmhfuKFvCIxutMXz8rE3IiAiPdSH6lQ6/q0FLoBGojbdPDo63wgKgq2ngQNMChofvUkzWXqCDw5V3YiFt6MEkhrHEYgW6a7FSYxxoqMeHr91F9sCVcx8hd0kLznbEcUhhhjxYGH3K5BgoE64= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931280; c=relaxed/simple; bh=ovfxJKKuAKObm63Zu7VlrOl+EmqKnRC/02p0uoNmAPw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=kve8XxrK2xHXlOj0pgZHvpaE+BpEH/MBVlKoeyPVeqGMNzAKMvITnnragh9BZYpBeSbdR9uUbDFzg8Muhkf3f300dlcY+KCxi01wMavZkny/p6IbzJN6FN0W0k7Y3t0GRYJvOinjIdyLqcWsWrTsocl0Cc8uddNEd+6sQ9UhrF0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=H3PBRCfd; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="H3PBRCfd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F1218C4CEDD; Wed, 11 Dec 2024 15:34:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733931279; bh=ovfxJKKuAKObm63Zu7VlrOl+EmqKnRC/02p0uoNmAPw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=H3PBRCfdJ4ef17E+QolZQaLXf5Xaskkuv1D/BQRzTg0qly5/B8YWRoL45L2U1q8X0 MzDUuBJONAefhQxxB0MHoHCb2cduCNf0x9agvk4Ud4oqxoP8UDyXcvBF4cAmD8xBFj cuijVDjsEKySUwtORPk383TijEk/PyPF1FGI3u7jkDue4ewJ6c72mKl1VsmTfoRogB oK4HGusG/MCiD02eYhXrsE3TEtsUnLmlDKeJ10ygKdY9MnHmRrLeD0G7a3ahOy0nNP CMnDcrinWKhKxQnTQI+EyzXWpvL+nu4r8zens3ZEOyL+c4JYtPMnXDHwjSAsKHi6KK 9WOqGXvv47gTg== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v3 3/8] wifi: ath12k: send partner device details in QMI MLO capability Date: Wed, 11 Dec 2024 17:34:27 +0200 Message-Id: <20241211153432.775335-4-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241211153432.775335-1-kvalo@kernel.org> References: <20241211153432.775335-1-kvalo@kernel.org> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Karthikeyan Periyasamy 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 Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/qmi.c | 88 ++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index ba3cd2342465..2f10c83ef54a 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -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); From patchwork Wed Dec 11 15:34:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 849709 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 737F91CF7C3; Wed, 11 Dec 2024 15:34:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931281; cv=none; b=WlLuUrVYqfR/S6Tan+l6fUSLETebuzQrxFEnR0lL/3ANufH0Dld8/qwimoOwBIjdFcWXG8PzJOjL0pxSeR2/L7Q2++lNBqKknFwfkLTsBgu3cUSZ+w1Xem0cLZgGF95CftfNlph16uEcs+7GaC/KQ/S2CeecJ94ZRk44eOuL/Mw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931281; c=relaxed/simple; bh=STfKckyL0TMpxsYw5pn1QelzJf/9pGSJYyWVqtZs/DY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=DEBmKyga+/YOgeASl11S4ywVTQX8XM2wHAVReLctYkj2SfnpRmCn8klWxS/b1JAFibLaOwjRSLGIwuPP+yo9B/VQdilHEppr3ueMHyBfMg/BWxcVlDvvPQxfxo32VyZg/CuxNX0OCNBWXpp6tABIQ5QhZMQmUAHH1igtswmTq9w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OWKRadtZ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="OWKRadtZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 50486C4CED2; Wed, 11 Dec 2024 15:34:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733931281; bh=STfKckyL0TMpxsYw5pn1QelzJf/9pGSJYyWVqtZs/DY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OWKRadtZjptrSNbANkPIl8auh1MwkBsuWxwytuc4JZIJozeDb0VQ0U2pU1xR0jnlw WcPvdSgxgon+Qdgfh5wWrd60b3hVLh/Y77S2gWsCA83mPlVwc+J3+my7ghI6nZv8zP u6frTWXkCpcYAcCCHDiMBEUBy/KEksXZb4qIofLeb7GvGZ1bwT46i3s5RZYkPVWXd3 jhmuo9vR9s2Z4GA/DHFQ0eAlhTlgMBKKs6FlXr02R+dIe3Hp6zBdNrelJXhNXPBtgU knuPb6Vr8Hq6x6rV/KijCdPDcUP4A+W1cW2HbQckSOVQPk521VyV3IicVfai4kkPaD 7ItDII2JxlElw== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v3 4/8] wifi: ath12k: refactor ath12k_qmi_alloc_target_mem_chunk() Date: Wed, 11 Dec 2024 17:34:28 +0200 Message-Id: <20241211153432.775335-5-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241211153432.775335-1-kvalo@kernel.org> References: <20241211153432.775335-1-kvalo@kernel.org> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Karthikeyan Periyasamy 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 Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Raj Kumar Bhagat Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/qmi.c | 82 ++++++++++++++------------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index 2f10c83ef54a..7f3d5b269b9e 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -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 */ From patchwork Wed Dec 11 15:34:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 850045 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9293C1D6DA4; Wed, 11 Dec 2024 15:34:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931282; cv=none; b=FkmOWBMX4A3IEVn+/Stck8eUjPDimC+Nm/sr4omLlrOLHGlx8sFolCi8kSPUkj8f4sEdYPvGafAd8yFMBanS5/I1K/wtMiyjfIjd3l3JfMppj7mOV9gc3ewsLW/2QUz+rU5I3lczydOYjrWjVLW+GXeIi5rpv32si7F8DphhRT4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931282; c=relaxed/simple; bh=0MpnDzEdOw00/eEu1dedSOMrvM8zY0rTM/h1/lkQtCA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=glsc+XYqJHVxc88t+0Aa6AZHMXyYZaKj8uW2NJ7/+tTi8kD51iyG76CFJ4+XIFqtZqo7KKLPX5xpTSLhv2tj+jtDA9hJKXPUXZKHH5BbQZt/BxvWGCYVwFXxTV4cbLSvbXgOVktaEEa1R1pBzgIwZJ0//+KD0Oc5jvJtBO3FGgY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GC/A+1Yv; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GC/A+1Yv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8648CC4CED7; Wed, 11 Dec 2024 15:34:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733931282; bh=0MpnDzEdOw00/eEu1dedSOMrvM8zY0rTM/h1/lkQtCA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GC/A+1YvP3zzzZOR+YHGSVVxsJkfQ1k/Q/F9GU2bI7Zg+ee1EUYyJ2dCsUuj/VqIH O/GZBS+d2m4oG0qUfzeR++IpnqOuN8GPbnQJvQ5at7097oLMKJrl8nopZoNGhXze5y zCHbjQ37scr9Kq5Hn0wbw1gGWYCFO30KU3b7sAiXKMBmux/6LDnllmYUgZ7tiz9bjN O5nRT2/h+Z2U2nEBW1W7JOoicjmCjptdYnbUUdfbNHB+fA+bpap0GfDqBL4cD37QXa HTCgX4FEz3hksBZpb44e611Ho9wtnPY57bw09R+hSEjwbqk9BS5DTgWn4BILRLJP+Z QiuXv0RKNTYGg== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v3 5/8] wifi: ath12k: add support to allocate MLO global memory region Date: Wed, 11 Dec 2024 17:34:29 +0200 Message-Id: <20241211153432.775335-6-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241211153432.775335-1-kvalo@kernel.org> References: <20241211153432.775335-1-kvalo@kernel.org> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Karthikeyan Periyasamy 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 Signed-off-by: Karthikeyan Periyasamy Co-developed-by: Raj Kumar Bhagat Signed-off-by: Raj Kumar Bhagat Signed-off-by: Kalle Valo --- 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(-) diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index d0e466819036..bf310df3d8f7 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -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 */ diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index 7f3d5b269b9e..e7846aaca10a 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -2407,19 +2407,64 @@ int ath12k_qmi_respond_fw_mem_request(struct ath12k_base *ab) return ret; } +static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab, + struct target_mem_chunk *chunk, + int idx) +{ + struct ath12k_hw_group *ag = ab->ag; + struct target_mem_chunk *mlo_chunk; + + lockdep_assert_held(&ag->mutex); + + if (!ag->mlo_mem.init_done || ag->num_started) + return; + + if (idx >= ARRAY_SIZE(ag->mlo_mem.chunk)) { + ath12k_warn(ab, "invalid index for MLO memory chunk free: %d\n", idx); + return; + } + + mlo_chunk = &ag->mlo_mem.chunk[idx]; + if (mlo_chunk->v.addr) { + dma_free_coherent(ab->dev, + mlo_chunk->size, + mlo_chunk->v.addr, + mlo_chunk->paddr); + mlo_chunk->v.addr = NULL; + } + + mlo_chunk->paddr = 0; + mlo_chunk->size = 0; + chunk->v.addr = NULL; + chunk->paddr = 0; + chunk->size = 0; +} + static void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab) { - int i; + struct ath12k_hw_group *ag = ab->ag; + int i, mlo_idx; - for (i = 0; i < ab->qmi.mem_seg_count; i++) { + for (i = 0, mlo_idx = 0; i < ab->qmi.mem_seg_count; i++) { if (!ab->qmi.target_mem[i].v.addr) continue; - dma_free_coherent(ab->dev, - ab->qmi.target_mem[i].prev_size, - ab->qmi.target_mem[i].v.addr, - ab->qmi.target_mem[i].paddr); - ab->qmi.target_mem[i].v.addr = NULL; + if (ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) { + ath12k_qmi_free_mlo_mem_chunk(ab, + &ab->qmi.target_mem[i], + mlo_idx++); + } else { + dma_free_coherent(ab->dev, + ab->qmi.target_mem[i].prev_size, + ab->qmi.target_mem[i].v.addr, + ab->qmi.target_mem[i].paddr); + ab->qmi.target_mem[i].v.addr = NULL; + } + } + + if (!ag->num_started && ag->mlo_mem.init_done) { + ag->mlo_mem.init_done = false; + ag->mlo_mem.mlo_mem_size = 0; } } @@ -2466,12 +2511,21 @@ static int ath12k_qmi_alloc_chunk(struct ath12k_base *ab, static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab) { - int i, ret = 0; - struct target_mem_chunk *chunk; + struct target_mem_chunk *chunk, *mlo_chunk; + struct ath12k_hw_group *ag = ab->ag; + int i, mlo_idx, ret; + int mlo_size = 0; + + mutex_lock(&ag->mutex); + + if (!ag->mlo_mem.init_done) { + memset(ag->mlo_mem.chunk, 0, sizeof(ag->mlo_mem.chunk)); + ag->mlo_mem.init_done = true; + } ab->qmi.target_mem_delayed = false; - for (i = 0; i < ab->qmi.mem_seg_count; i++) { + for (i = 0, mlo_idx = 0; i < ab->qmi.mem_seg_count; i++) { chunk = &ab->qmi.target_mem[i]; /* Allocate memory for the region and the functionality supported @@ -2484,6 +2538,40 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab) case PAGEABLE_MEM_REGION_TYPE: case CALDB_MEM_REGION_TYPE: ret = ath12k_qmi_alloc_chunk(ab, chunk); + if (ret) + goto err; + break; + case MLO_GLOBAL_MEM_REGION_TYPE: + mlo_size += chunk->size; + if (ag->mlo_mem.mlo_mem_size && + mlo_size > ag->mlo_mem.mlo_mem_size) { + ath12k_err(ab, "QMI MLO memory allocation failure, requested size %d is more than allocated size %d", + mlo_size, ag->mlo_mem.mlo_mem_size); + ret = -EINVAL; + goto err; + } + + mlo_chunk = &ag->mlo_mem.chunk[mlo_idx]; + if (mlo_chunk->paddr) { + if (chunk->size != mlo_chunk->size) { + ath12k_err(ab, "QMI MLO chunk memory allocation failure for index %d, requested size %d is more than allocated size %d", + mlo_idx, chunk->size, mlo_chunk->size); + ret = -EINVAL; + goto err; + } + } else { + mlo_chunk->size = chunk->size; + mlo_chunk->type = chunk->type; + ret = ath12k_qmi_alloc_chunk(ab, mlo_chunk); + if (ret) + goto err; + memset(mlo_chunk->v.addr, 0, mlo_chunk->size); + } + + chunk->paddr = mlo_chunk->paddr; + chunk->v.addr = mlo_chunk->v.addr; + mlo_idx++; + break; default: ath12k_warn(ab, "memory type %u not supported\n", @@ -2493,6 +2581,25 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab) break; } } + + if (!ag->mlo_mem.mlo_mem_size) { + ag->mlo_mem.mlo_mem_size = mlo_size; + } else if (ag->mlo_mem.mlo_mem_size != mlo_size) { + ath12k_err(ab, "QMI MLO memory size error, expected size is %d but requestted size is %d", + ag->mlo_mem.mlo_mem_size, mlo_size); + ret = -EINVAL; + goto err; + } + + mutex_unlock(&ag->mutex); + + return 0; + +err: + ath12k_qmi_free_target_mem_chunk(ab); + + mutex_unlock(&ag->mutex); + return ret; } diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h index 98f6009ab21e..45d7c3fcafdd 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.h +++ b/drivers/net/wireless/ath/ath12k/qmi.h @@ -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, }; From patchwork Wed Dec 11 15:34:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 849708 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2537B1ABEA1; Wed, 11 Dec 2024 15:34:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931284; cv=none; b=otMY0sYFnbisOKt44UNJvxe9QaTzacJZPcJrvhhasBvGSFSrp/+O2gKiOHjxIjRtsWCKiNMhqjW8R5NMTIPQ+T4jcZyZZMTJFT6dFRnV77nNU9LOcxdGAQDgH42t7KMwxlKldD4A5yrcMmY8gpNnBxRkZLciHjNTCv+phbhbEe0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931284; c=relaxed/simple; bh=waznicM3+KHfgV1HmksA5+1fyaqEwxvI99nayrQMkMY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Po4wanWMQj23SdOO30t0bjSMnfdE4BqnDlo7U8/PsIBpn59dzptO4ytbe/XwUjmY1Y8TOACGNZIjLjqDzU/yNB2janqTwVG8QvP7+DgxhGdTdGKOWZff+A8wvuaUErwnXqEFAwrLMclSA5gIcQXO8deBg4yyZ4HBJ8EVB1d3UrE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=K7jPxGj3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="K7jPxGj3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D9BA8C4CED2; Wed, 11 Dec 2024 15:34:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733931283; bh=waznicM3+KHfgV1HmksA5+1fyaqEwxvI99nayrQMkMY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=K7jPxGj3DZ4ouwTorvfuIDVK49U2c7q2aYGX6EJ1zeIT32zdoe4v6sNNreeBAe74x YkwNXVuN5CuraQCovktRwuAnrxoUlqFG543nIgHschLfUWlBwN/P0StQkxeFeY+EyP kPLI+FUNcyjFg+7XG7WbdlB+vyVpKEKFgVaOGxbKJQ6iF/KvAa5G6kbc5sCJjXlLU6 tTER/LDFsetaovTbNhxaxFk5JJGMz9tV09hHya9U2lQ/H+MR96JpX+zjB8r2dGeMpn qBzGNUkD+cVnActZPPayXlYe8pOOID73TER88Gap4lkn5jbcqoYxSFQQ1crVhcgytp W44zYz1pRixxA== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v3 6/8] wifi: ath12k: Add MLO WMI setup and teardown functions Date: Wed, 11 Dec 2024 17:34:30 +0200 Message-Id: <20241211153432.775335-7-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241211153432.775335-1-kvalo@kernel.org> References: <20241211153432.775335-1-kvalo@kernel.org> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Bhagavathi Perumal S 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 Co-developed-by: Karthikeyan Periyasamy Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Bhagavathi Perumal S Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/wmi.c | 177 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 48 +++++++ 2 files changed, 225 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 402ae477da61..8f4b0941360d 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -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; +} diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 05aa9754118a..640720b68782 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -285,6 +285,7 @@ enum wmi_cmd_group { WMI_GRP_TWT = 0x3e, WMI_GRP_MOTION_DET = 0x3f, WMI_GRP_SPATIAL_REUSE = 0x40, + WMI_GRP_MLO = 0x48, }; #define WMI_CMD_GRP(grp_id) (((grp_id) << 12) | 0x1) @@ -665,6 +666,10 @@ enum wmi_tlv_cmd_id { WMI_PDEV_OBSS_PD_SPATIAL_REUSE_CMDID = WMI_TLV_CMD(WMI_GRP_SPATIAL_REUSE), WMI_PDEV_OBSS_PD_SPATIAL_REUSE_SET_DEF_OBSS_THRESH_CMDID, + WMI_MLO_LINK_SET_ACTIVE_CMDID = WMI_TLV_CMD(WMI_GRP_MLO), + WMI_MLO_SETUP_CMDID, + WMI_MLO_READY_CMDID, + WMI_MLO_TEARDOWN_CMDID, }; enum wmi_tlv_event_id { @@ -874,6 +879,9 @@ enum wmi_tlv_event_id { WMI_TWT_DEL_DIALOG_EVENTID, WMI_TWT_PAUSE_DIALOG_EVENTID, WMI_TWT_RESUME_DIALOG_EVENTID, + WMI_MLO_LINK_SET_ACTIVE_RESP_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_MLO), + WMI_MLO_SETUP_COMPLETE_EVENTID, + WMI_MLO_TEARDOWN_COMPLETE_EVENTID, }; enum wmi_tlv_pdev_param { @@ -5026,6 +5034,43 @@ struct wmi_twt_disable_event { __le32 status; } __packed; +struct wmi_mlo_setup_cmd { + __le32 tlv_header; + __le32 mld_group_id; + __le32 pdev_id; +} __packed; + +struct wmi_mlo_setup_arg { + __le32 group_id; + u8 num_partner_links; + u8 *partner_link_id; +}; + +struct wmi_mlo_ready_cmd { + __le32 tlv_header; + __le32 pdev_id; +} __packed; + +enum wmi_mlo_tear_down_reason_code_type { + WMI_MLO_TEARDOWN_SSR_REASON, +}; + +struct wmi_mlo_teardown_cmd { + __le32 tlv_header; + __le32 pdev_id; + __le32 reason_code; +} __packed; + +struct wmi_mlo_setup_complete_event { + __le32 pdev_id; + __le32 status; +} __packed; + +struct wmi_mlo_teardown_complete_event { + __le32 pdev_id; + __le32 status; +} __packed; + /* WOW structures */ enum wmi_wow_wakeup_event { WOW_BMISS_EVENT = 0, @@ -5751,5 +5796,8 @@ int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar, struct ath12k_link_vif *arvif); int ath12k_wmi_sta_keepalive(struct ath12k *ar, const struct wmi_sta_keepalive_arg *arg); +int ath12k_wmi_mlo_setup(struct ath12k *ar, struct wmi_mlo_setup_arg *mlo_params); +int ath12k_wmi_mlo_ready(struct ath12k *ar); +int ath12k_wmi_mlo_teardown(struct ath12k *ar); #endif From patchwork Wed Dec 11 15:34:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 850044 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3A6E91D8E10; Wed, 11 Dec 2024 15:34:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931285; cv=none; b=Ox5tBl43vPu5F4PCmQF4xdRIwufpmONda/Ac9oE5YDu9I9aLKQMTgJXqgyF7QMdS0lf9QPbUdW3RhU0YDgrVy1Je/A6D/2Zlc1dR+1Cubdxo+B9ljzWYuVnwWFOKzNNeg8vnFre3+CYWne7r3iY+YvpSjEkTptqECF8LBQn74gk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931285; c=relaxed/simple; bh=d0QZughSZQWEuh5lk2IPYSI2BmSOFSPhXvF7DYFzblM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=OqwAblBnXl/LnLmcWVct9itxMnmJmGp5dmke7B79lYN5DMHUVhK9ySWsTM8RFBy4z8PpuxKlkabdap9BP4jQQSzZJOxmFZruxlSn59M3y/TE76fzR2NIrUdBSuO4XTKNbjymeIvX82H1etyEavfjMOFC7lryJxElK9hZD8QNy7A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=p1tmzEoJ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="p1tmzEoJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 39011C4CED4; Wed, 11 Dec 2024 15:34:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733931285; bh=d0QZughSZQWEuh5lk2IPYSI2BmSOFSPhXvF7DYFzblM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=p1tmzEoJOID7lrvwx32B5BVB1WqDvtHKX2QqnlsxURouLCu/ZXRPBAKfSMflv+QFM 5qP5oVEw8+14t75C0geAPYJRfy1Lu+AwQRGxkd4/eGN1vDry0Kw1nKecq7owxk1gUG BWAJrO+/JCcB4M7GuunPsHyxhUpJE+oLbKgckTE+G7LlWCVzVKrbxYRJvmVyOdeTIR XTw2/OCixN1Q0f3oZP+9NPzX7by87SJkAt6IF66fR8f9Hbmn0Jjf1M7KydMzPCLBvk sRvN1uAxeQTi7/faHbp6khm4N6lfHBW836ALA/bn58ixLNWsARrsUBMVVfRLolYr1s UQgxgz+3jsFAg== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v3 7/8] wifi: ath12k: enable MLO setup and teardown from core Date: Wed, 11 Dec 2024 17:34:31 +0200 Message-Id: <20241211153432.775335-8-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241211153432.775335-1-kvalo@kernel.org> References: <20241211153432.775335-1-kvalo@kernel.org> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Karthikeyan Periyasamy 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 Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo --- 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(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 1a43e00cffb2..af642b466ea0 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -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); diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index bf310df3d8f7..dc01f7b3fd73 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -715,6 +715,9 @@ struct ath12k { u32 freq_high; bool nlo_enabled; + + struct completion mlo_setup_done; + u32 mlo_setup_status; }; struct ath12k_hw { diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index c4eab4c1c10e..23c5c8fd952d 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -10810,6 +10810,7 @@ static void ath12k_mac_setup(struct ath12k *ar) init_completion(&ar->scan.started); init_completion(&ar->scan.completed); init_completion(&ar->scan.on_channel); + init_completion(&ar->mlo_setup_done); INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work); INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work); @@ -10818,6 +10819,147 @@ static void ath12k_mac_setup(struct ath12k *ar) skb_queue_head_init(&ar->wmi_mgmt_tx_queue); } +static int __ath12k_mac_mlo_setup(struct ath12k *ar) +{ + u8 num_link = 0, partner_link_id[ATH12K_GROUP_MAX_RADIO] = {}; + struct ath12k_base *partner_ab, *ab = ar->ab; + struct ath12k_hw_group *ag = ab->ag; + struct wmi_mlo_setup_arg mlo = {}; + struct ath12k_pdev *pdev; + unsigned long time_left; + int i, j, ret; + + lockdep_assert_held(&ag->mutex); + + reinit_completion(&ar->mlo_setup_done); + + for (i = 0; i < ag->num_devices; i++) { + partner_ab = ag->ab[i]; + + for (j = 0; j < partner_ab->num_radios; j++) { + pdev = &partner_ab->pdevs[j]; + + /* Avoid the self link */ + if (ar == pdev->ar) + continue; + + partner_link_id[num_link] = pdev->hw_link_id; + num_link++; + + ath12k_dbg(ab, ATH12K_DBG_MAC, "device %d pdev %d hw_link_id %d num_link %d\n", + i, j, pdev->hw_link_id, num_link); + } + } + + mlo.group_id = cpu_to_le32(ag->id); + mlo.partner_link_id = partner_link_id; + mlo.num_partner_links = num_link; + ar->mlo_setup_status = 0; + + ath12k_dbg(ab, ATH12K_DBG_MAC, "group id %d num_link %d\n", ag->id, num_link); + + ret = ath12k_wmi_mlo_setup(ar, &mlo); + if (ret) { + ath12k_err(ab, "failed to send setup MLO WMI command for pdev %d: %d\n", + ar->pdev_idx, ret); + return ret; + } + + time_left = wait_for_completion_timeout(&ar->mlo_setup_done, + WMI_MLO_CMD_TIMEOUT_HZ); + + if (!time_left || ar->mlo_setup_status) + return ar->mlo_setup_status ? : -ETIMEDOUT; + + ath12k_dbg(ab, ATH12K_DBG_MAC, "mlo setup done for pdev %d\n", ar->pdev_idx); + + return 0; +} + +static int __ath12k_mac_mlo_teardown(struct ath12k *ar) +{ + struct ath12k_base *ab = ar->ab; + int ret; + + if (test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags)) + return 0; + + ret = ath12k_wmi_mlo_teardown(ar); + if (ret) { + ath12k_warn(ab, "failed to send MLO teardown WMI command for pdev %d: %d\n", + ar->pdev_idx, ret); + return ret; + } + + ath12k_dbg(ab, ATH12K_DBG_MAC, "mlo teardown for pdev %d\n", ar->pdev_idx); + + return 0; +} + +int ath12k_mac_mlo_setup(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_setup(ar); + if (ret) { + ath12k_err(ar->ab, "failed to setup MLO: %d\n", ret); + goto err_setup; + } + } + } + + return 0; + +err_setup: + for (i = i - 1; i >= 0; i--) { + ah = ag->ah[i]; + if (!ah) + continue; + + for (j = j - 1; j >= 0; j--) { + ar = &ah->radio[j]; + if (!ar) + continue; + + __ath12k_mac_mlo_teardown(ar); + } + } + + return ret; +} + +void ath12k_mac_mlo_teardown(struct ath12k_hw_group *ag) +{ + struct ath12k_hw *ah; + struct ath12k *ar; + int ret, 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_teardown(ar); + if (ret) { + ath12k_err(ar->ab, "failed to teardown MLO: %d\n", ret); + break; + } + } + } +} + int ath12k_mac_register(struct ath12k_hw_group *ag) { struct ath12k_base *ab = ag->ab[0]; diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h index ccfc215d83ff..81cfb950e6cd 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h @@ -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 diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 8f4b0941360d..10a6ba926343 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -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); } diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 640720b68782..270ed458302e 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -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) From patchwork Wed Dec 11 15:34:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 849707 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A88511D8E10; Wed, 11 Dec 2024 15:34:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931286; cv=none; b=C55vvKSnoZndYMwHJ4KW5tF17Wty4MgDXJK5ZZMQaLzY1DQ0F/4nNHqQd0wGFkl2YAF1mT71oAOyfrT/ZbxqBHJklpy0xyvYgh5R0Q6GBlucqeOC2QkAvkywS9sgrxU1NT6EvbXCWdsdmZ9VGXzjwna49UfDpqq7I73ONWD0wCI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733931286; c=relaxed/simple; bh=ZM8zjJkGa/qRK0XshDVNYNacIug+9Bt5JFORjs69WfE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=loEHkWG95F/wWC9qOwkGs68czQ8NrCy9TexkGoxJhkdclxrUOIkqqxVsQOtbp+tSLgHrqWfRgtZlNlvYX6XGpMxOrv8CYlJHqsRW/sss6uyLJxC8D8wD4B8uNEFm6qBnkCLgufA0QZc++H1km08UQPq7TGqBAnZTdzmQCTvN75U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=d6mjK6FM; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="d6mjK6FM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8CC62C4CED2; Wed, 11 Dec 2024 15:34:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733931286; bh=ZM8zjJkGa/qRK0XshDVNYNacIug+9Bt5JFORjs69WfE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d6mjK6FMSKMZXybSt4Zs22OiBDMQjrE1GgwA1U/ErLdDFx21KA5c1g11JwdmWl5d/ tm2i314NohBkrjYcZ6sQMS7YGqYNbQ3d7iuOWqfxYomeSolXNxYOvGu/zTHtP4ORxP do/gWnr18Cx04LRzkmr/5G0z3yG13CSZSYzKrBHlHDFv4Gcb/Eypqpn1rLfOqwnybn iKquvS+euEG87PWhqs1CYH1AuENSPu+cgCcT74G2DKwzJHH0F4AFm0bfoCsROY7KEa UQwGUF82EmtvuC1Qm2nhZ04JTSVj16vJpJ2AQRpxzLBTyDbOeByr84z01nHuf64izJ qL7AUk97DnA2A== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v3 8/8] wifi: ath12k: avoid redundant code in DP Rx error process Date: Wed, 11 Dec 2024 17:34:32 +0200 Message-Id: <20241211153432.775335-9-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241211153432.775335-1-kvalo@kernel.org> References: <20241211153432.775335-1-kvalo@kernel.org> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Karthikeyan Periyasamy 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 Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/dp_rx.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index b24d1de4aabb..2c919503ddef 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -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,