From patchwork Wed Dec 4 16:32:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 13894075 X-Patchwork-Delegate: quic_jjohnson@quicinc.com 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 1CAD620C48F for ; Wed, 4 Dec 2024 16:32:20 +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=1733329941; cv=none; b=gT9Bn368OCAXnc46svVE8y/h74Uufyd4qguU19I7PsO7zIYMc+90pIDwR8mMYH31G8gtG/D5WWlaMvkl6zrvIW9tJqNYFs1aSyMRLOWCZYrPl+ns712c4TDjLj55Xs2zM7B8Dec77HoQRwROY2HRMvcg0F3AQoOa6gd6B1LkaAU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733329941; c=relaxed/simple; bh=5NgdQtgdx9L6DLYrc7Hr1UkgwpKbPHyj9dlHR5lrHxs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=DXWwyFda2yaPPmF/OEIKLNRrhpkUOrCd7eqlGIRNJEzbkXGeROMxufvIpm5pUExK0Pi3smqnAOSrd+zeD1zj3tAEUsMgeFuY2PNhhSLGtF97Xq4wQHquVlBYTOX/8QV3BnMz7BGh+og9rPQa4cBwS4qqrvrsdNJigw1Ns7ZGCS4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=M1m2QM/I; 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="M1m2QM/I" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 17390C4CEDF; Wed, 4 Dec 2024 16:32:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733329940; bh=5NgdQtgdx9L6DLYrc7Hr1UkgwpKbPHyj9dlHR5lrHxs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=M1m2QM/IYsHu2P2KI6NHqw9tdNSanIGypnbAcJj1LXuOyGN17Et6mduC96xLnUOA6 jZwtdB9yDntUULDrPOLY5sbclYcEeIESbQaY5hItdwXSp7GlzWQjKnYeEoXZUZJHTG veIlPpAf+PP+N/eqjcbrPITvRKO3AbxxPKFMoOHJfLtsmgEkLmybmKrmXqsXSNfL4N Yyc1qqhyVVBeh3gq6QcwSBWxlqXTZYN+5QSyXM/m/dLLT85AheOc+yIlNbOWVJKKC4 ngrI0cQ7A2lSHKnroavj+ZpbhLBSSmOxwBHqOmPBKLWR9B5h15z0nq/RJ279npM0TF 6ARz2WWZXpnOQ== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org Subject: [PATCH 1/7] wifi: ath12k: move ATH12K_FLAG_REGISTERED handling to ath12k_mac_register() Date: Wed, 4 Dec 2024 18:32:10 +0200 Message-Id: <20241204163216.433795-2-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241204163216.433795-1-kvalo@kernel.org> References: <20241204163216.433795-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 When hardware device group abstraction is introduced, a group abstraction is registered to mac80211 rather than a particular single device. So we cannot set the device registered when the QMI firmware ready event is received, only after all the devices in group have received the event. To do that set and unset ATH12K_FLAG_REGISTERED flag inside ath12k_mac_register() and ath12k_mac_unregister() respectively. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/mac.c | 4 ++++ drivers/net/wireless/ath/ath12k/qmi.c | 4 +--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 129607ac6c1a..1180070278da 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -10839,6 +10839,8 @@ int ath12k_mac_register(struct ath12k_base *ab) goto err; } + set_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags); + return 0; err: @@ -10858,6 +10860,8 @@ void ath12k_mac_unregister(struct ath12k_base *ab) struct ath12k_hw *ah; int i; + clear_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags); + for (i = ath12k_get_num_hw(ab) - 1; i >= 0; i--) { ah = ath12k_ab_to_ah(ab, i); if (!ah) diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index 77d8ee14bf33..20382b751829 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -3349,11 +3349,9 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work) &ab->dev_flags); clear_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); ret = ath12k_core_qmi_firmware_ready(ab); - if (!ret) { + if (!ret) set_bit(ATH12K_FLAG_QMI_FW_READY_COMPLETE, &ab->dev_flags); - set_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags); - } break; default: From patchwork Wed Dec 4 16:32:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 13894076 X-Patchwork-Delegate: quic_jjohnson@quicinc.com 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 2BD4E20CCC9 for ; Wed, 4 Dec 2024 16:32:21 +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=1733329942; cv=none; b=taHUEuhtzbe5WvdzGaGCjbi+U0IBR4kqPOHNZv5Ij2szbgyMqf2tYY2Sa/0NcqYsIsWXYCSUg7F6F30nLxNpZ03QY00ZY6yr9jnuj58vQz6nyZxsChStCZ67pqeTny5FhAqkQU7VsrHYeeLd3+iHWPm+wRKsCg03uziPH7AKyXY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733329942; c=relaxed/simple; bh=1KYYy0zChNWRS9t83bRH1vuBONCPFVUq/ubaS1cNmg8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=BGuqKBEfhOwCO4I4kpjG0ym4C3p+DAw+wAn20mucsSrnl78x/FmIABHwiEF40q/pjNTdszO1T9myxZVQCdKTWqYhNikNJpvmZrj/RQ//DGqvDH53EChmW1bz3Ot9M1wNS1c5WZgi5FHvwtp/YyaaE7Or8gQZF5MtlNA/qlLfR5E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NX/2GEib; 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="NX/2GEib" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1EEF6C4CEDD; Wed, 4 Dec 2024 16:32:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733329941; bh=1KYYy0zChNWRS9t83bRH1vuBONCPFVUq/ubaS1cNmg8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NX/2GEibDlwpXchzlM/bFTyGQSvHxtkrO2Pu1L2QnFMdPb1v3FaBYdR05vLVK6UOj 1nwNCtQ2cTvGU4nw0JTJ851fuOpPNEdSgXY4CYuPHrBmyaW80RUBcEhtpN5xR2wgwc vO9b+BZQAVfphTHAjvikN4hDKumcty6dlnwdAqrVlaCIKoPikK9gYwZKrB8KWxwSHv 9yPzglSSRJj1ZLZKSTWQcAKjF8tz89cb6LX5jJy97s2UeL6kWmgDzWWK/uWoIqf979 6VyTrsWHJCF130bSrYbB/A0Z9ATYsLcBC9ACxakHuVrPHY//8IdmZV8eNQAGAC0EQ4 9Wcpj1MP17+lw== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org Subject: [PATCH 2/7] wifi: ath12k: rename mlo_capable_flags to single_chip_mlo_supp Date: Wed, 4 Dec 2024 18:32:11 +0200 Message-Id: <20241204163216.433795-3-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241204163216.433795-1-kvalo@kernel.org> References: <20241204163216.433795-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: Aditya Kumar Singh At present, the mlo_capable_flags in ath12k_base is used to indicate whether the chip supports inter (QCN9274) or intra (WCN7850) chip MLO. However, it’s possible that the chip supports neither, especially with older firmware versions. Additionally, if intra chip MLO is not supported, inter chip MLO will also be non-functional. Therefore, having two separate flags for this is unnecessary. Therefore, rename this flag to single_chip_mlo_supp. At the same time convert it into a bool data type. Also, get rid of the enums defined earlier. For the QCN9274 family of chipsets, this will be set only when firmware advertises the support during the QMI exchange. For the WCN7850 family of chipsets, since the event is not supported, assumption is made that single chip MLO is supported. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Aditya Kumar Singh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/core.c | 2 +- drivers/net/wireless/ath/ath12k/core.h | 23 ++--------------------- drivers/net/wireless/ath/ath12k/qmi.c | 13 +++++-------- 3 files changed, 8 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 4da147f7bfac..568c9b6e2c1c 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -1325,7 +1325,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size, ab->dev = dev; ab->hif.bus = bus; ab->qmi.num_radios = U8_MAX; - ab->mlo_capable_flags = ATH12K_INTRA_DEVICE_MLO_SUPPORT; + ab->single_chip_mlo_supp = false; /* Device index used to identify the devices in a group. * diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 9ddced140056..d93ba844f61d 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -816,21 +816,6 @@ struct ath12k_soc_dp_stats { struct ath12k_soc_dp_tx_err_stats tx_err; }; -/** - * enum ath12k_link_capable_flags - link capable flags - * - * Single/Multi link capability information - * - * @ATH12K_INTRA_DEVICE_MLO_SUPPORT: SLO/MLO form between the radio, where all - * the links (radios) present within a device. - * @ATH12K_INTER_DEVICE_MLO_SUPPORT: SLO/MLO form between the radio, where all - * the links (radios) present across the devices. - */ -enum ath12k_link_capable_flags { - ATH12K_INTRA_DEVICE_MLO_SUPPORT = BIT(0), - ATH12K_INTER_DEVICE_MLO_SUPPORT = BIT(1), -}; - /* Master structure to hold the hw data which may be used in core module */ struct ath12k_base { enum ath12k_hw_rev hw_rev; @@ -996,12 +981,8 @@ struct ath12k_base { const struct hal_rx_ops *hal_rx_ops; - /* mlo_capable_flags denotes the single/multi link operation - * capabilities of the Device. - * - * See enum ath12k_link_capable_flags - */ - u8 mlo_capable_flags; + /* Denotes the whether MLO is possible within the chip */ + bool single_chip_mlo_supp; struct completion restart_completed; diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index 20382b751829..efcf2dfac4ac 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -2023,14 +2023,14 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab, u8 hw_link_id = 0; int i; - if (!(ab->mlo_capable_flags & ATH12K_INTRA_DEVICE_MLO_SUPPORT)) { + if (!ab->single_chip_mlo_supp) { ath12k_dbg(ab, ATH12K_DBG_QMI, "intra device MLO is disabled hence skip QMI MLO cap"); return; } if (!ab->qmi.num_radios || ab->qmi.num_radios == U8_MAX) { - ab->mlo_capable_flags = 0; + ab->single_chip_mlo_supp = false; ath12k_dbg(ab, ATH12K_DBG_QMI, "skip QMI MLO cap due to invalid num_radio %d\n", @@ -2176,12 +2176,9 @@ static void ath12k_qmi_phy_cap_send(struct ath12k_base *ab) goto out; } - if (resp.single_chip_mlo_support_valid) { - if (resp.single_chip_mlo_support) - ab->mlo_capable_flags |= ATH12K_INTRA_DEVICE_MLO_SUPPORT; - else - ab->mlo_capable_flags &= ~ATH12K_INTRA_DEVICE_MLO_SUPPORT; - } + if (resp.single_chip_mlo_support_valid && + resp.single_chip_mlo_support) + ab->single_chip_mlo_supp = true; if (!resp.num_phy_valid) { ret = -ENODATA; From patchwork Wed Dec 4 16:32:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 13894077 X-Patchwork-Delegate: quic_jjohnson@quicinc.com 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 3213020CCD7 for ; Wed, 4 Dec 2024 16:32:22 +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=1733329943; cv=none; b=rLkLWVny7x/Jk7wsc7KYTtO+j7P0NiiY7h2O/b8fiWTmW6NkxGckK+vTJcdYj4k1Qm1Bu1J84ETM/4dc3iDZmfDZj2qlMyh93RN3jGTa+QZ3FbfRMxSO9Gz2Ln3Ffl7HOulzJB1Z/Iz7aKJGz99mNlliy5lcbKdqw6ygl1cwbqE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733329943; c=relaxed/simple; bh=eOwBX+tMPFKV/Z+PuXHK2DnM5Hw8dvGaA7Y4eazG6YM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pUGSoxOVA1nGGa65+eXYClVixx48ZogX9Xia2eHC7KqkfjiKSKolsAmzonlFDzfUc5C/k696f6qk7kSlB+J7I3BUDpK/qhIBb+9/xoEAlo0IeJfP5vS3a3ANEJm3fA1qjOXR2jh2WyLNXTnIL8aBII1deaTZnQkgazCzj6DWAUI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Y8UgreYk; 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="Y8UgreYk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 256A1C4CED1; Wed, 4 Dec 2024 16:32:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733329942; bh=eOwBX+tMPFKV/Z+PuXHK2DnM5Hw8dvGaA7Y4eazG6YM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y8UgreYkqZwy1KNtSJZ9MQyU/lrU4chGgFuOKmp/qHITZux96DFh7D9WKeuGIgZpR 0iTJPeX85+IPzmKDT9Ut5vI8Vxl4dFvRFI1CjobKYBDkVDjEy97blDll3jkPxtHGJ6 7+14KUAbNpK10B/eORVQR2GHUyMyeP7qfv5Pvhbdz9CRZMKr8U4BuKk57trhweDatu dYhfGetD2+iin3tRdStSy+b6dC5lR4kQC71kjJxVL2kHyHysm3ttcTlG1IhdYNlEOh KK/svsdyhP7F94c3K8gZo+p2TPFmF/jgVJRuLA9orN53RcMrRv5ESh3Kxi8zz8l2/v ThXW5HIZCbLtg== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org Subject: [PATCH 3/7] wifi: ath12k: introduce device group abstraction Date: Wed, 4 Dec 2024 18:32:12 +0200 Message-Id: <20241204163216.433795-4-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241204163216.433795-1-kvalo@kernel.org> References: <20241204163216.433795-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, single device is probed, and once firmware is ready, the device is registered to mac80211. For Multi-Link Operation, different bands of different devices or same device are part of a single wiphy and for this, hardware device group abstraction is needed. Hardware device group abstraction - when there are multiple devices (with single radio or dual radio) that are connected by any means of interface for communicating between them, then these devices can be combined together as a single group using a group id to form a group abstraction and register to mac80211. The grouping information of multiple devices would be based on device tree during device probe (will be implemented in future patches). If no such information is available, then a single device will be part of group abstraction and registered to mac80211, else multiple devices advertised in device tree are combined and then registered to mac80211. For device group abstraction, a base structure ath12k_hw_group (ag) and the helpers are implemented. These helpers are used during device probe and mapping the group to the devices involved. An illustration of how multiple devices might be combined together in future based on group id: +------------------------------------------------------------------------+ | +-------------------------------------+ +-------------------+ | | | +-----------+ | | +-----------+ | | +-----------+ | | | | | ar (2GHz) | | | | ar (5GHz) | | | | ar (6GHz) | | | | | +-----------+ | | +-----------+ | | +-----------+ | | | | ath12k_base (ab) | | ath12k_base (ab) | | | | (Dual band device) | | | | | +-------------------------------------+ +-------------------+ | | ath12k_hw_group (ag) based on group id | +------------------------------------------------------------------------+ In the above representation, two devices are combined into single group based on group id. Add base code changes where single device would be part of a group with an invalid group id forming an group abstraction. Multi device grouping will be introduced in future. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Karthikeyan Periyasamy Co-developed-by: Harshitha Prem Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/core.c | 237 +++++++++++++++++++++++-- drivers/net/wireless/ath/ath12k/core.h | 17 ++ drivers/net/wireless/ath/ath12k/pci.c | 1 + 3 files changed, 239 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 568c9b6e2c1c..41e3454b60f5 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -22,6 +22,11 @@ unsigned int ath12k_debug_mask; module_param_named(debug_mask, ath12k_debug_mask, uint, 0644); MODULE_PARM_DESC(debug_mask, "Debugging mask"); +/* protected with ath12k_hw_group_mutex */ +static struct list_head ath12k_hw_group_list = LIST_HEAD_INIT(ath12k_hw_group_list); + +static DEFINE_MUTEX(ath12k_hw_group_mutex); + static int ath12k_core_rfkill_config(struct ath12k_base *ab) { struct ath12k *ar; @@ -1244,27 +1249,112 @@ static void ath12k_core_panic_notifier_unregister(struct ath12k_base *ab) &ab->panic_nb); } -int ath12k_core_init(struct ath12k_base *ab) +static inline +bool ath12k_core_hw_group_create_ready(struct ath12k_hw_group *ag) { - int ret; + lockdep_assert_held(&ag->mutex); - ret = ath12k_core_soc_create(ab); - if (ret) { - ath12k_err(ab, "failed to create soc core: %d\n", ret); - return ret; - } - - ret = ath12k_core_panic_notifier_register(ab); - if (ret) - ath12k_warn(ab, "failed to register panic handler: %d\n", ret); - - return 0; + return (ag->num_probed == ag->num_devices); } -void ath12k_core_deinit(struct ath12k_base *ab) +static struct ath12k_hw_group *ath12k_core_hw_group_alloc(u8 id, u8 max_devices) { - ath12k_core_panic_notifier_unregister(ab); + struct ath12k_hw_group *ag; + lockdep_assert_held(&ath12k_hw_group_mutex); + + ag = kzalloc(sizeof(*ag), GFP_KERNEL); + if (!ag) + return NULL; + + ag->id = id; + ag->num_devices = max_devices; + list_add(&ag->list, &ath12k_hw_group_list); + mutex_init(&ag->mutex); + + return ag; +} + +static void ath12k_core_hw_group_free(struct ath12k_hw_group *ag) +{ + mutex_lock(&ath12k_hw_group_mutex); + + list_del(&ag->list); + kfree(ag); + + mutex_unlock(&ath12k_hw_group_mutex); +} + +static struct ath12k_hw_group *ath12k_core_hw_group_assign(struct ath12k_base *ab) +{ + u32 group_id = ATH12K_INVALID_GROUP_ID; + struct ath12k_hw_group *ag; + + lockdep_assert_held(&ath12k_hw_group_mutex); + + /* The grouping of multiple devices will be done based on device tree file. + * TODO: device tree file parsing to know about the devices involved in group. + * + * The platforms that do not have any valid group information would have each + * device to be part of its own invalid group. + * + * Currently, we are not parsing any device tree information and hence, grouping + * of multiple devices is not involved. Thus, single device is added to device + * group. + */ + ag = ath12k_core_hw_group_alloc(group_id, 1); + if (!ag) { + ath12k_warn(ab, "unable to create new hw group\n"); + return NULL; + } + + ath12k_dbg(ab, ATH12K_DBG_BOOT, "single device added to hardware group\n"); + + ab->device_id = ag->num_probed++; + ag->ab[ab->device_id] = ab; + ab->ag = ag; + + return ag; +} + +void ath12k_core_hw_group_unassign(struct ath12k_base *ab) +{ + struct ath12k_hw_group *ag = ab->ag; + u8 device_id = ab->device_id; + int num_probed; + + if (!ag) + return; + + mutex_lock(&ag->mutex); + + if (WARN_ON(device_id >= ag->num_devices)) { + mutex_unlock(&ag->mutex); + return; + } + + if (WARN_ON(ag->ab[device_id] != ab)) { + mutex_unlock(&ag->mutex); + return; + } + + ag->ab[device_id] = NULL; + ab->ag = NULL; + ab->device_id = ATH12K_INVALID_DEVICE_ID; + + if (ag->num_probed) + ag->num_probed--; + + num_probed = ag->num_probed; + + mutex_unlock(&ag->mutex); + + if (!num_probed) + ath12k_core_hw_group_free(ag); +} + +static void ath12k_core_device_cleanup(struct ath12k_base *ab) +{ mutex_lock(&ab->core_lock); ath12k_hif_irq_disable(ab); @@ -1274,8 +1364,123 @@ void ath12k_core_deinit(struct ath12k_base *ab) ath12k_core_stop(ab); mutex_unlock(&ab->core_lock); +} - ath12k_core_soc_destroy(ab); +static void ath12k_core_hw_group_destroy(struct ath12k_hw_group *ag) +{ + struct ath12k_base *ab; + int i; + + if (WARN_ON(!ag)) + return; + + for (i = 0; i < ag->num_devices; i++) { + ab = ag->ab[i]; + if (!ab) + continue; + + ath12k_core_soc_destroy(ab); + } +} + +static void ath12k_core_hw_group_cleanup(struct ath12k_hw_group *ag) +{ + struct ath12k_base *ab; + int i; + + if (!ag) + return; + + mutex_lock(&ag->mutex); + + for (i = 0; i < ag->num_devices; i++) { + ab = ag->ab[i]; + if (!ab) + continue; + + ath12k_core_device_cleanup(ab); + } + + mutex_unlock(&ag->mutex); +} + +static int ath12k_core_hw_group_create(struct ath12k_hw_group *ag) +{ + struct ath12k_base *ab; + int i, ret; + + lockdep_assert_held(&ag->mutex); + + for (i = 0; i < ag->num_devices; i++) { + ab = ag->ab[i]; + if (!ab) + continue; + + mutex_lock(&ab->core_lock); + + ret = ath12k_core_soc_create(ab); + if (ret) { + mutex_unlock(&ab->core_lock); + ath12k_err(ab, "failed to create soc core: %d\n", ret); + return ret; + } + + mutex_unlock(&ab->core_lock); + } + + return 0; +} + +int ath12k_core_init(struct ath12k_base *ab) +{ + struct ath12k_hw_group *ag; + int ret; + + ret = ath12k_core_panic_notifier_register(ab); + if (ret) + ath12k_warn(ab, "failed to register panic handler: %d\n", ret); + + mutex_lock(&ath12k_hw_group_mutex); + + ag = ath12k_core_hw_group_assign(ab); + if (!ag) { + mutex_unlock(&ath12k_hw_group_mutex); + ath12k_warn(ab, "unable to get hw group\n"); + return -ENODEV; + } + + mutex_unlock(&ath12k_hw_group_mutex); + + mutex_lock(&ag->mutex); + + ath12k_dbg(ab, ATH12K_DBG_BOOT, "num devices %d num probed %d\n", + ag->num_devices, ag->num_probed); + + if (ath12k_core_hw_group_create_ready(ag)) { + ret = ath12k_core_hw_group_create(ag); + if (ret) { + mutex_unlock(&ag->mutex); + ath12k_warn(ab, "unable to create hw group\n"); + goto err; + } + } + + mutex_unlock(&ag->mutex); + + return 0; + +err: + ath12k_core_hw_group_destroy(ab->ag); + ath12k_core_hw_group_unassign(ab); + return ret; +} + +void ath12k_core_deinit(struct ath12k_base *ab) +{ + ath12k_core_panic_notifier_unregister(ab); + ath12k_core_hw_group_cleanup(ab->ag); + ath12k_core_hw_group_destroy(ab->ag); + ath12k_core_hw_group_unassign(ab); } void ath12k_core_free(struct ath12k_base *ab) diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index d93ba844f61d..dca4b9a3538f 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -816,6 +816,20 @@ struct ath12k_soc_dp_stats { struct ath12k_soc_dp_tx_err_stats tx_err; }; +/* Holds info on the group of devices that are registered as a single + * wiphy, protected with struct ath12k_hw_group::mutex. + */ +struct ath12k_hw_group { + struct list_head list; + u8 id; + u8 num_devices; + u8 num_probed; + struct ath12k_base *ab[ATH12K_MAX_SOCS]; + + /* protects access to this struct */ + struct mutex mutex; +}; + /* Master structure to hold the hw data which may be used in core module */ struct ath12k_base { enum ath12k_hw_rev hw_rev; @@ -1005,6 +1019,8 @@ struct ath12k_base { struct notifier_block panic_nb; + struct ath12k_hw_group *ag; + /* must be last */ u8 drv_priv[] __aligned(sizeof(void *)); }; @@ -1035,6 +1051,7 @@ int ath12k_core_resume_early(struct ath12k_base *ab); int ath12k_core_resume(struct ath12k_base *ab); int ath12k_core_suspend(struct ath12k_base *ab); int ath12k_core_suspend_late(struct ath12k_base *ab); +void ath12k_core_hw_group_unassign(struct ath12k_base *ab); const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab, const char *filename); diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index 8dbc7377ae7c..06cff3849ab8 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -1725,6 +1725,7 @@ static void ath12k_pci_remove(struct pci_dev *pdev) if (test_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags)) { ath12k_pci_power_down(ab, false); ath12k_qmi_deinit_service(ab); + ath12k_core_hw_group_unassign(ab); goto qmi_fail; } From patchwork Wed Dec 4 16:32:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 13894078 X-Patchwork-Delegate: quic_jjohnson@quicinc.com 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 D771F20CCE2 for ; Wed, 4 Dec 2024 16:32:23 +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=1733329943; cv=none; b=b7yL3Gn5exlg+HSyqDkl95TmIAec5Cqo6J/NQOb4tJiCIaMRoSnXb0DAPHaeqTmMAoGelmeq92Mnzo+1RXp1Je9+JZk9QHb6Tr07XqqWdlFGH8OeSg1aJDQIuhnYaG/R0NTH4yjvex6KpG7OQf4d/UVq+O8ii8qxJhI+774XlB0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733329943; c=relaxed/simple; bh=yNWBoLpuMM1CGqIEGRaxfmG2n8G7gEySqM67EG1DS44=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=GpvFlSYsstLv12rxY7gymtbFDOxpKBu0M8JvOYcY7BYHINVAt/OJHqaljGl4rszrlVigDsDqZq/0PwDeiWBHCeDGa6M10wh/imMD4Plh1YZNGxohKloC2CsXGYIpdGSwnM1z4mVfyvkdOmKiLhq7Bcf6CvhNM3Fr0Z98Pgd/IuI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ir10Dx82; 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="Ir10Dx82" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2CB69C4CECD; Wed, 4 Dec 2024 16:32:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733329943; bh=yNWBoLpuMM1CGqIEGRaxfmG2n8G7gEySqM67EG1DS44=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ir10Dx82sh1N3rCqVjnJSMyHOmwz+xsxTzQ5ZdKoDvh3I1zbqx6+oJRGc7zgr9EQ6 WY58fIdYGWCBRcpeVkl2wbjpdzSfDcA1mz0xDlkMI5J5ksf/SoR0r4FcYI3WN7d9+A 6xKhJB3yZblgsC7rEjQnQwvRNv08AFz/Pipd3FVgg7ykxRpXbqnTBLwWlueU2/3btU 70rbx9xf7ANWPpZKXdlkIiO/dyFOO0LnB71JbRaJUXKpec0FJuJuIZ4LEDcmaF2Lwv Mi1No4zw2SHN4Ia/VB3lej2IWMrizq9fUVFSwRIVDCG1nMVYY/9s7+fmIoYGFbo+vH ASk8ZshJv9tVA== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org Subject: [PATCH 4/7] wifi: ath12k: refactor core start based on hardware group Date: Wed, 4 Dec 2024 18:32:13 +0200 Message-Id: <20241204163216.433795-5-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241204163216.433795-1-kvalo@kernel.org> References: <20241204163216.433795-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, mac allocate/register and core_pdev_create are initiated immediately when QMI firmware ready event is received for a particular device. With hardware device group abstraction, QMI firmware ready event can be received simultaneously for different devices in the group and so, it should not be registered immediately rather it has to be deferred until all devices in the group has received QMI firmware ready. To handle this, refactor the code of core start to have registering within ath12k_core_hw_group_start() and unregistering in ath12k_core_hw_group_stop(). Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Karthikeyan Periyasamy Co-developed-by: Harshitha Prem Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/core.c | 199 ++++++++++++++++++------- drivers/net/wireless/ath/ath12k/core.h | 22 +++ drivers/net/wireless/ath/ath12k/qmi.c | 4 +- 3 files changed, 172 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 41e3454b60f5..dea2c53bcc07 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -604,6 +604,8 @@ u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab) static void ath12k_core_stop(struct ath12k_base *ab) { + ath12k_core_stopped(ab); + if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags)) ath12k_qmi_firmware_stop(ab); @@ -743,6 +745,8 @@ static int ath12k_core_start(struct ath12k_base *ab, { int ret; + lockdep_assert_held(&ab->core_lock); + ret = ath12k_wmi_attach(ab); if (ret) { ath12k_err(ab, "failed to attach wmi: %d\n", ret); @@ -836,6 +840,10 @@ static int ath12k_core_start(struct ath12k_base *ab, /* ACPI is optional so continue in case of an error */ ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi failed: %d\n", ret); + if (!test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags)) + /* Indicate the core start in the appropriate group */ + ath12k_core_started(ab); + return 0; err_reo_cleanup: @@ -847,6 +855,96 @@ static int ath12k_core_start(struct ath12k_base *ab, return ret; } +static void ath12k_core_device_cleanup(struct ath12k_base *ab) +{ + mutex_lock(&ab->core_lock); + + ath12k_hif_irq_disable(ab); + ath12k_core_pdev_destroy(ab); + ath12k_mac_unregister(ab); + ath12k_mac_destroy(ab); + + mutex_unlock(&ab->core_lock); +} + +static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag) +{ + struct ath12k_base *ab; + int i; + + lockdep_assert_held(&ag->mutex); + + for (i = ag->num_devices - 1; i >= 0; i--) { + ab = ag->ab[i]; + if (!ab) + continue; + ath12k_core_device_cleanup(ab); + } +} + +static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag) +{ + struct ath12k_base *ab; + int ret, i; + + lockdep_assert_held(&ag->mutex); + + for (i = 0; i < ag->num_devices; i++) { + ab = ag->ab[i]; + if (!ab) + continue; + + mutex_lock(&ab->core_lock); + + /* Check if already registered or not, since same flow + * execute for HW restart case. + */ + if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) + goto core_pdev_create; + + ret = ath12k_mac_allocate(ab); + if (ret) { + ath12k_err(ab, "failed to create new hw device with mac80211 :%d\n", + ret); + mutex_unlock(&ab->core_lock); + return ret; + } + + ret = ath12k_mac_register(ab); + if (ret) { + ath12k_err(ab, "failed to register radio with mac80211: %d\n", + ret); + mutex_unlock(&ab->core_lock); + goto err; + } + +core_pdev_create: + ret = ath12k_core_pdev_create(ab); + if (ret) { + ath12k_err(ab, "failed to create pdev core %d\n", ret); + mutex_unlock(&ab->core_lock); + goto err; + } + + ath12k_hif_irq_enable(ab); + + ret = ath12k_core_rfkill_config(ab); + if (ret && ret != -EOPNOTSUPP) { + mutex_unlock(&ab->core_lock); + goto err; + } + + mutex_unlock(&ab->core_lock); + } + + return 0; + +err: + ath12k_core_hw_group_stop(ag); + + return ret; +} + static int ath12k_core_start_firmware(struct ath12k_base *ab, enum ath12k_firmware_mode mode) { @@ -864,9 +962,18 @@ static int ath12k_core_start_firmware(struct ath12k_base *ab, return ret; } +static inline +bool ath12k_core_hw_group_start_ready(struct ath12k_hw_group *ag) +{ + lockdep_assert_held(&ag->mutex); + + return (ag->num_started == ag->num_devices); +} + int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab) { - int ret; + struct ath12k_hw_group *ag = ath12k_ab_to_ag(ab); + int ret, i; ret = ath12k_core_start_firmware(ab, ATH12K_FIRMWARE_MODE_NORMAL); if (ret) { @@ -886,59 +993,50 @@ int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab) goto err_firmware_stop; } + mutex_lock(&ag->mutex); mutex_lock(&ab->core_lock); + ret = ath12k_core_start(ab, ATH12K_FIRMWARE_MODE_NORMAL); if (ret) { ath12k_err(ab, "failed to start core: %d\n", ret); goto err_dp_free; } - ret = ath12k_mac_allocate(ab); - if (ret) { - ath12k_err(ab, "failed to create new hw device with mac80211 :%d\n", - ret); - goto err_core_stop; - } - - ret = ath12k_mac_register(ab); - if (ret) { - ath12k_err(ab, "failed register the radio with mac80211: %d\n", ret); - goto err_mac_destroy; - } - - ret = ath12k_core_pdev_create(ab); - if (ret) { - ath12k_err(ab, "failed to create pdev core: %d\n", ret); - goto err_mac_unregister; - } - - ath12k_hif_irq_enable(ab); - - ret = ath12k_core_rfkill_config(ab); - if (ret && ret != -EOPNOTSUPP) { - ath12k_err(ab, "failed to config rfkill: %d\n", ret); - goto err_hif_irq_disable; - } - mutex_unlock(&ab->core_lock); + if (ath12k_core_hw_group_start_ready(ag)) { + ret = ath12k_core_hw_group_start(ag); + if (ret) { + ath12k_warn(ab, "unable to start hw group\n"); + goto err_core_stop; + } + ath12k_dbg(ab, ATH12K_DBG_BOOT, "group %d started\n", ag->id); + } + + mutex_unlock(&ag->mutex); + return 0; -err_hif_irq_disable: - ath12k_hif_irq_disable(ab); - ath12k_core_pdev_destroy(ab); -err_mac_unregister: - ath12k_mac_unregister(ab); -err_mac_destroy: - ath12k_mac_destroy(ab); err_core_stop: - ath12k_core_stop(ab); + for (i = ag->num_devices - 1; i >= 0; i--) { + ab = ag->ab[i]; + if (!ab) + continue; + + mutex_lock(&ab->core_lock); + ath12k_core_stop(ab); + mutex_unlock(&ab->core_lock); + } + goto exit; + err_dp_free: ath12k_dp_free(ab); mutex_unlock(&ab->core_lock); err_firmware_stop: ath12k_qmi_firmware_stop(ab); +exit: + mutex_unlock(&ag->mutex); return ret; } @@ -1135,6 +1233,14 @@ static void ath12k_core_restart(struct work_struct *work) } if (ab->is_reset) { + if (!test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) { + atomic_dec(&ab->reset_count); + complete(&ab->reset_complete); + ab->is_reset = false; + atomic_set(&ab->fail_cont_count, 0); + ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset success\n"); + } + for (i = 0; i < ath12k_get_num_hw(ab); i++) { ah = ath12k_ab_to_ah(ab, i); ieee80211_restart_hw(ah->hw); @@ -1319,7 +1425,7 @@ static struct ath12k_hw_group *ath12k_core_hw_group_assign(struct ath12k_base *a void ath12k_core_hw_group_unassign(struct ath12k_base *ab) { - struct ath12k_hw_group *ag = ab->ag; + struct ath12k_hw_group *ag = ath12k_ab_to_ag(ab); u8 device_id = ab->device_id; int num_probed; @@ -1353,19 +1459,6 @@ void ath12k_core_hw_group_unassign(struct ath12k_base *ab) ath12k_core_hw_group_free(ag); } -static void ath12k_core_device_cleanup(struct ath12k_base *ab) -{ - mutex_lock(&ab->core_lock); - - ath12k_hif_irq_disable(ab); - ath12k_core_pdev_destroy(ab); - ath12k_mac_unregister(ab); - ath12k_mac_destroy(ab); - ath12k_core_stop(ab); - - mutex_unlock(&ab->core_lock); -} - static void ath12k_core_hw_group_destroy(struct ath12k_hw_group *ag) { struct ath12k_base *ab; @@ -1393,12 +1486,16 @@ static void ath12k_core_hw_group_cleanup(struct ath12k_hw_group *ag) mutex_lock(&ag->mutex); + ath12k_core_hw_group_stop(ag); + for (i = 0; i < ag->num_devices; i++) { ab = ag->ab[i]; if (!ab) continue; - ath12k_core_device_cleanup(ab); + mutex_lock(&ab->core_lock); + ath12k_core_stop(ab); + mutex_unlock(&ab->core_lock); } mutex_unlock(&ag->mutex); diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index dca4b9a3538f..b8b1ee8d3302 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -824,6 +824,8 @@ struct ath12k_hw_group { u8 id; u8 num_devices; u8 num_probed; + u8 num_started; + unsigned long flags; struct ath12k_base *ab[ATH12K_MAX_SOCS]; /* protects access to this struct */ @@ -1175,4 +1177,24 @@ static inline int ath12k_get_num_hw(struct ath12k_base *ab) { return ab->num_hw; } + +static inline struct ath12k_hw_group *ath12k_ab_to_ag(struct ath12k_base *ab) +{ + return ab->ag; +} + +static inline void ath12k_core_started(struct ath12k_base *ab) +{ + lockdep_assert_held(&ab->ag->mutex); + + ab->ag->num_started++; +} + +static inline void ath12k_core_stopped(struct ath12k_base *ab) +{ + lockdep_assert_held(&ab->ag->mutex); + + ab->ag->num_started--; +} + #endif /* _CORE_H_ */ diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index efcf2dfac4ac..8b4d500fe426 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -3321,7 +3321,6 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work) break; case ATH12K_QMI_EVENT_SERVER_EXIT: set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags); - set_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); break; case ATH12K_QMI_EVENT_REQUEST_MEM: ret = ath12k_qmi_event_mem_request(qmi); @@ -3338,13 +3337,14 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work) if (test_bit(ATH12K_FLAG_QMI_FW_READY_COMPLETE, &ab->dev_flags)) { if (ab->is_reset) ath12k_hal_dump_srng_stats(ab); + + set_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); queue_work(ab->workqueue, &ab->restart_work); break; } clear_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags); - clear_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags); ret = ath12k_core_qmi_firmware_ready(ab); if (!ret) set_bit(ATH12K_FLAG_QMI_FW_READY_COMPLETE, From patchwork Wed Dec 4 16:32:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 13894079 X-Patchwork-Delegate: quic_jjohnson@quicinc.com 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 E6E0820CCFB for ; Wed, 4 Dec 2024 16:32:24 +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=1733329945; cv=none; b=FxlWj7rtnMsvnVaKzOezbcV+Pr/Bp2DtA30NdsPa1Qe1KH9EWe7AIMJdtdvLpchxRprCTcwjN93qM7NDUcuhgq+kHEsYXoGrdPVfx6sP7OTYa6pyYWWEvI45rhDTGxYPWTCZNzThEHlHln7XBEtI5AgqKJu4wi2BIZ6qcVmFHEY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733329945; c=relaxed/simple; bh=3gyXssl1Da6F82cyxFqcclJf+2FSUsY14Gf6RHS6UXc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=FEUp7Dt4w2xOXDei9G+nPqbnz5cPmv1mzAcQq5s2GehsEs+jcWAEOGn7zEdp1R4gGJJOVQ7QBtmgdG5pQXXTLCa2LIa1iPuYo68p+aNhoXp0IigJeCLmdxPR6ibcUoPnm7zyY7YWciMrZZ5LV17qD/EV8eby3KNeWWlCfN0VBJw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CzftGJLP; 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="CzftGJLP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 346C2C4CED2; Wed, 4 Dec 2024 16:32:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733329944; bh=3gyXssl1Da6F82cyxFqcclJf+2FSUsY14Gf6RHS6UXc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CzftGJLPhMZ2D9YAeFOfgtMSmJl4+3ENUkZH8vyodZonFQV9/+ljobQ+JzSpW4ekH +qxyNvfcYiAhiNK4r9PlzcgzgQZH7hpclYV9DDc5C3PxMzaDFnqvzsCnImBS0dh5yR eifejKF41QJCmGnqTWLlx9ndbrvfHe87rA+pGHhnjmtVpLqm2gmalLnGl1+3Mdmgj9 7DvhEojKEJgo9wtnjFetmN5neuEL3gxqe5svUQS6zqkddR1uH/ROcE8sppJj/Z2b1p 7+yx3vq+2PaF4MI3L4ddWQq3QGmcbNAhJHH8VXMuov0BGve0zGU9QKYVv0/1a3q5ag ZPzhLb3ZNnViw== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org Subject: [PATCH 5/7] wifi: ath12k: move struct ath12k_hw from per device to group Date: Wed, 4 Dec 2024 18:32:14 +0200 Message-Id: <20241204163216.433795-6-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241204163216.433795-1-kvalo@kernel.org> References: <20241204163216.433795-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, hardware abstractions (ah) of different radio bands are tightly coupled to a single device (ab). But, with hardware device group abstraction (ag), multiple radios across different devices in a group can form different combinations of hardware abstractions (ah) within the group. Hence, the mapping between ah to ab can be removed and instead it can be mapped with struct ath12k_hw_group (ag). Current mapping between struct ath12k_hw (ah), struct ath12k_base (ab) and struct ath12k_hw_group (ag): +------------------------------------------------+ | +-------------------------------------+ | | | +---------------+ +---------------+ | | | | |ath12k_hw (ah) | |ath12k_hw (ah) | | | | | +---------------+ +---------------+ | | | | | | | | +-----------+ | +-----------+ | | | | | ar (2GHz) | | | ar (5GHz) | | | | | +-----------+ | +-----------+ | | | | Dual band device-1 (ab) | | | +-------------------------------------+ | | ath12k_hw_group (ag) based on group id | +------------------------------------------------+ After hardware device group abstraction moving ah array out of ab to ag: +----------------------------------------------+ | +---------------+ +---------------+ | | |ath12k_hw (ah) | |ath12k_hw (ah) | | | +---------------+ +---------------+ | | +-------------------------------------+ | | | +-----------+ +-----------+ | | | | | ar (2GHz) | | ar (5GHz) | | | | | +-----------+ +-----------+ | | | | Dual band device-1 (ab) | | | +-------------------------------------+ | | ath12k_hw_group (ag) based on group id | +----------------------------------------------+ This decoupling of struct ath12k_hw (ah) from struct ath12k_base (ab) and mapping it to struct ath12k_hw_group (ag) will help in forming different combinations of multi-link devices. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/core.c | 49 +++++++------- drivers/net/wireless/ath/ath12k/core.h | 29 +++++---- drivers/net/wireless/ath/ath12k/dp.c | 19 ++---- drivers/net/wireless/ath/ath12k/dp.h | 2 +- drivers/net/wireless/ath/ath12k/mac.c | 89 ++++++++++++++++++-------- drivers/net/wireless/ath/ath12k/mac.h | 9 +-- 6 files changed, 115 insertions(+), 82 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index dea2c53bcc07..bbfa57d097af 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -861,8 +861,6 @@ static void ath12k_core_device_cleanup(struct ath12k_base *ab) ath12k_hif_irq_disable(ab); ath12k_core_pdev_destroy(ab); - ath12k_mac_unregister(ab); - ath12k_mac_destroy(ab); mutex_unlock(&ab->core_lock); } @@ -874,12 +872,18 @@ static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag) lockdep_assert_held(&ag->mutex); + clear_bit(ATH12K_GROUP_FLAG_REGISTERED, &ag->flags); + + ath12k_mac_unregister(ag); + for (i = ag->num_devices - 1; i >= 0; i--) { ab = ag->ab[i]; if (!ab) continue; ath12k_core_device_cleanup(ab); } + + ath12k_mac_destroy(ag); } static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag) @@ -889,6 +893,20 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag) lockdep_assert_held(&ag->mutex); + if (test_bit(ATH12K_GROUP_FLAG_REGISTERED, &ag->flags)) + goto core_pdev_create; + + ret = ath12k_mac_allocate(ag); + if (WARN_ON(ret)) + return ret; + + ret = ath12k_mac_register(ag); + if (WARN_ON(ret)) + goto err_mac_destroy; + + set_bit(ATH12K_GROUP_FLAG_REGISTERED, &ag->flags); + +core_pdev_create: for (i = 0; i < ag->num_devices; i++) { ab = ag->ab[i]; if (!ab) @@ -896,29 +914,6 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag) mutex_lock(&ab->core_lock); - /* Check if already registered or not, since same flow - * execute for HW restart case. - */ - if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) - goto core_pdev_create; - - ret = ath12k_mac_allocate(ab); - if (ret) { - ath12k_err(ab, "failed to create new hw device with mac80211 :%d\n", - ret); - mutex_unlock(&ab->core_lock); - return ret; - } - - ret = ath12k_mac_register(ab); - if (ret) { - ath12k_err(ab, "failed to register radio with mac80211: %d\n", - ret); - mutex_unlock(&ab->core_lock); - goto err; - } - -core_pdev_create: ret = ath12k_core_pdev_create(ab); if (ret) { ath12k_err(ab, "failed to create pdev core %d\n", ret); @@ -941,6 +936,10 @@ static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag) err: ath12k_core_hw_group_stop(ag); + return ret; + +err_mac_destroy: + ath12k_mac_destroy(ag); return ret; } diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index b8b1ee8d3302..64252d6491cd 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -64,6 +64,7 @@ #define ATH12K_RECOVER_START_TIMEOUT_HZ (20 * HZ) #define ATH12K_MAX_SOCS 3 +#define ATH12K_GROUP_MAX_RADIO (ATH12K_MAX_SOCS * MAX_RADIOS) #define ATH12K_INVALID_GROUP_ID 0xFF #define ATH12K_INVALID_DEVICE_ID 0xFF @@ -216,6 +217,10 @@ enum ath12k_scan_state { ATH12K_SCAN_ABORTING, }; +enum ath12k_hw_group_flags { + ATH12K_GROUP_FLAG_REGISTERED, +}; + enum ath12k_dev_flags { ATH12K_CAC_RUNNING, ATH12K_FLAG_CRASH_FLUSH, @@ -830,6 +835,15 @@ struct ath12k_hw_group { /* protects access to this struct */ struct mutex mutex; + + /* Holds information of wiphy (hw) registration. + * + * In Multi/Single Link Operation case, all pdevs are registered as + * a single wiphy. In other (legacy/Non-MLO) cases, each pdev is + * registered as separate wiphys. + */ + struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO]; + u8 num_hw; }; /* Master structure to hold the hw data which may be used in core module */ @@ -895,15 +909,6 @@ struct ath12k_base { struct ath12k_pdev __rcu *pdevs_active[MAX_RADIOS]; - /* Holds information of wiphy (hw) registration. - * - * In Multi/Single Link Operation case, all pdevs are registered as - * a single wiphy. In other (legacy/Non-MLO) cases, each pdev is - * registered as separate wiphys. - */ - struct ath12k_hw *ah[MAX_RADIOS]; - u8 num_hw; - struct ath12k_wmi_hal_reg_capabilities_ext_arg hal_reg_cap[MAX_RADIOS]; unsigned long long free_vdev_map; unsigned long long free_vdev_stats_id_map; @@ -1164,18 +1169,18 @@ static inline struct ieee80211_hw *ath12k_ar_to_hw(struct ath12k *ar) static inline struct ath12k_hw *ath12k_ab_to_ah(struct ath12k_base *ab, int idx) { - return ab->ah[idx]; + return ab->ag->ah[idx]; } static inline void ath12k_ab_set_ah(struct ath12k_base *ab, int idx, struct ath12k_hw *ah) { - ab->ah[idx] = ah; + ab->ag->ah[idx] = ah; } static inline int ath12k_get_num_hw(struct ath12k_base *ab) { - return ab->num_hw; + return ab->ag->num_hw; } static inline struct ath12k_hw_group *ath12k_ab_to_ag(struct ath12k_base *ab) diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c index ce823b1c175f..68abe9d4ab45 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c @@ -991,21 +991,14 @@ void ath12k_dp_pdev_free(struct ath12k_base *ab) ath12k_dp_rx_pdev_free(ab, i); } -void ath12k_dp_pdev_pre_alloc(struct ath12k_base *ab) +void ath12k_dp_pdev_pre_alloc(struct ath12k *ar) { - struct ath12k *ar; - struct ath12k_pdev_dp *dp; - int i; + struct ath12k_pdev_dp *dp = &ar->dp; - for (i = 0; i < ab->num_radios; i++) { - ar = ab->pdevs[i].ar; - dp = &ar->dp; - dp->mac_id = i; - atomic_set(&dp->num_tx_pending, 0); - init_waitqueue_head(&dp->tx_empty_waitq); - - /* TODO: Add any RXDMA setup required per pdev */ - } + dp->mac_id = ar->pdev_idx; + atomic_set(&dp->num_tx_pending, 0); + init_waitqueue_head(&dp->tx_empty_waitq); + /* TODO: Add any RXDMA setup required per pdev */ } bool ath12k_dp_wmask_compaction_rx_tlv_supported(struct ath12k_base *ab) diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h index a120b7a8477d..021cd9e8ee1d 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h @@ -1806,7 +1806,7 @@ void ath12k_dp_free(struct ath12k_base *ab); int ath12k_dp_alloc(struct ath12k_base *ab); void ath12k_dp_cc_config(struct ath12k_base *ab); int ath12k_dp_pdev_alloc(struct ath12k_base *ab); -void ath12k_dp_pdev_pre_alloc(struct ath12k_base *ab); +void ath12k_dp_pdev_pre_alloc(struct ath12k *ar); void ath12k_dp_pdev_free(struct ath12k_base *ab); int ath12k_dp_tx_htt_srng_setup(struct ath12k_base *ab, u32 ring_id, int mac_id, enum hal_ring_type ring_type); diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 1180070278da..1cf724a530b5 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -10818,19 +10818,13 @@ static void ath12k_mac_setup(struct ath12k *ar) skb_queue_head_init(&ar->wmi_mgmt_tx_queue); } -int ath12k_mac_register(struct ath12k_base *ab) +int ath12k_mac_register(struct ath12k_hw_group *ag) { + struct ath12k_base *ab = ag->ab[0]; struct ath12k_hw *ah; int i; int ret; - if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) - return 0; - - /* Initialize channel counters frequency value in hertz */ - ab->cc_freq_hz = 320000; - ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1; - for (i = 0; i < ath12k_get_num_hw(ab); i++) { ah = ath12k_ab_to_ah(ab, i); @@ -10855,8 +10849,9 @@ int ath12k_mac_register(struct ath12k_base *ab) return ret; } -void ath12k_mac_unregister(struct ath12k_base *ab) +void ath12k_mac_unregister(struct ath12k_hw_group *ag) { + struct ath12k_base *ab = ag->ab[0]; struct ath12k_hw *ah; int i; @@ -10876,12 +10871,13 @@ static void ath12k_mac_hw_destroy(struct ath12k_hw *ah) ieee80211_free_hw(ah->hw); } -static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_base *ab, +static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_hw_group *ag, struct ath12k_pdev_map *pdev_map, u8 num_pdev_map) { struct ieee80211_hw *hw; struct ath12k *ar; + struct ath12k_base *ab; struct ath12k_pdev *pdev; struct ath12k_hw *ah; int i; @@ -10913,23 +10909,30 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_base *ab, pdev->ar = ar; ath12k_mac_setup(ar); + ath12k_dp_pdev_pre_alloc(ar); } return ah; } -void ath12k_mac_destroy(struct ath12k_base *ab) +void ath12k_mac_destroy(struct ath12k_hw_group *ag) { struct ath12k_pdev *pdev; + struct ath12k_base *ab = ag->ab[0]; + int i, j; struct ath12k_hw *ah; - int i; - for (i = 0; i < ab->num_radios; i++) { - pdev = &ab->pdevs[i]; - if (!pdev->ar) + for (i = 0; i < ag->num_devices; i++) { + ab = ag->ab[i]; + if (!ab) continue; - pdev->ar = NULL; + for (j = 0; j < ab->num_radios; j++) { + pdev = &ab->pdevs[j]; + if (!pdev->ar) + continue; + pdev->ar = NULL; + } } for (i = 0; i < ath12k_get_num_hw(ab); i++) { @@ -10942,26 +10945,59 @@ void ath12k_mac_destroy(struct ath12k_base *ab) } } -int ath12k_mac_allocate(struct ath12k_base *ab) +static void ath12k_mac_set_device_defaults(struct ath12k_base *ab) { + /* Initialize channel counters frequency value in hertz */ + ab->cc_freq_hz = 320000; + ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1; +} + +int ath12k_mac_allocate(struct ath12k_hw_group *ag) +{ + struct ath12k_pdev_map pdev_map[ATH12K_GROUP_MAX_RADIO]; + int mac_id, device_id, total_radio, num_hw; + struct ath12k_base *ab; struct ath12k_hw *ah; - struct ath12k_pdev_map pdev_map[MAX_RADIOS]; int ret, i, j; u8 radio_per_hw; - if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) - return 0; + total_radio = 0; + for (i = 0; i < ag->num_devices; i++) + total_radio += ag->ab[i]->num_radios; - ab->num_hw = ab->num_radios; + /* All pdev get combined and register as single wiphy based on + * hardware group which participate in multi-link operation else + * each pdev get register separately. + * + * Currently, registering as single pdevs. + */ radio_per_hw = 1; + num_hw = total_radio / radio_per_hw; - for (i = 0; i < ath12k_get_num_hw(ab); i++) { + if (WARN_ON(num_hw >= ATH12K_GROUP_MAX_RADIO)) + return -ENOSPC; + + ag->num_hw = 0; + device_id = 0; + mac_id = 0; + for (i = 0; i < num_hw; i++) { for (j = 0; j < radio_per_hw; j++) { + ab = ag->ab[device_id]; pdev_map[j].ab = ab; - pdev_map[j].pdev_idx = (i * radio_per_hw) + j; + pdev_map[j].pdev_idx = mac_id; + mac_id++; + + /* If mac_id falls beyond the current device MACs then + * move to next device + */ + if (mac_id >= ab->num_radios) { + mac_id = 0; + device_id++; + ath12k_mac_set_device_defaults(ab); + } } - ah = ath12k_mac_hw_allocate(ab, pdev_map, radio_per_hw); + ah = ath12k_mac_hw_allocate(ag, pdev_map, radio_per_hw); if (!ah) { ath12k_warn(ab, "failed to allocate mac80211 hw device for hw_idx %d\n", i); @@ -10971,11 +11007,10 @@ int ath12k_mac_allocate(struct ath12k_base *ab) ah->dev = ab->dev; - ath12k_ab_set_ah(ab, i, ah); + ag->ah[i] = ah; + ag->num_hw++; } - ath12k_dp_pdev_pre_alloc(ab); - return 0; err: diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h index abdc9a6c0740..ccfc215d83ff 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h @@ -14,6 +14,7 @@ struct ath12k; struct ath12k_base; struct ath12k_hw; +struct ath12k_hw_group; struct ath12k_pdev_map; struct ath12k_generic_iter { @@ -60,10 +61,10 @@ enum ath12k_supported_bw { extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default; -void ath12k_mac_destroy(struct ath12k_base *ab); -void ath12k_mac_unregister(struct ath12k_base *ab); -int ath12k_mac_register(struct ath12k_base *ab); -int ath12k_mac_allocate(struct ath12k_base *ab); +void ath12k_mac_destroy(struct ath12k_hw_group *ag); +void ath12k_mac_unregister(struct ath12k_hw_group *ag); +int ath12k_mac_register(struct ath12k_hw_group *ag); +int ath12k_mac_allocate(struct ath12k_hw_group *ag); int ath12k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc, u8 preamble, u8 *rateidx, u16 *rate); u8 ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband, From patchwork Wed Dec 4 16:32:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 13894080 X-Patchwork-Delegate: quic_jjohnson@quicinc.com 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 3A0F020CCFB for ; Wed, 4 Dec 2024 16:32:25 +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=1733329946; cv=none; b=mUvOoY9iPj7mhab9Bwt7u8iMsjQLGnGUsZSyIuAtjhahgWim962NFk8XBmPF2F4mwL4CF4ym1WBTTEJvj5GXyy11CHwbUw1FHg7NkZsafyO5zBYBqKLhgCCzAYEqooT/bluVYQQ7vtwJGUEHuZEsWWBQDX9j+MGCJLBKrFjm9bY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733329946; c=relaxed/simple; bh=oJRYZN8/sjs3B+/L4nBwC7nAviSBM+E3+2mjM0dRU7w=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nDeibAUJLIEltZpUZY1WWF93IwpFhDEnUzowU2OnZm5pE3bKDC4fi9G7RUu+K2HokwsKe4qtlAyZYNktagM/mTNcw4GgHjpH0bV6Iraxsb2NfXT7B/cYyRxzedZxhwKY0Ee5DUtmmj9G/f8emcwH7gTP5wF1rZESWpi8jgHN4kg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mbQvmUXN; 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="mbQvmUXN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3B8EFC4CED1; Wed, 4 Dec 2024 16:32:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733329945; bh=oJRYZN8/sjs3B+/L4nBwC7nAviSBM+E3+2mjM0dRU7w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mbQvmUXN+97WBQfTRZpjB6RQgUOSuG5XPCgTkl8Ngfos5T4GGKWsan3896CaGD6y0 UfJSk9Qjxti4/RNAI7tJjUk7buC61dqU+dQy/ds25A7nfJdY2tcs5qTo5Smh01AJub lwapgKIr23nJZu6NCkOhb68QA/a4GUjO/5rh77PFz1xnVreGsYKM2joNWWDVQj52h7 aQyEEwbf8xnJ/u4JqxhgUJ501lLVBCXtalDjA0aVcw89H4AJNAEs7ZBuF1gOxXqf6s vuZ0K3Yvaa8JWPyZlLbUvQ+OJZlTRKz7U3I9uRnu6Y+gbqa28p5WpzOwxsk7hbqgSq OEZRmQFCbBiuA== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org Subject: [PATCH 6/7] wifi: ath12k: send QMI host capability after device group is ready Date: Wed, 4 Dec 2024 18:32:15 +0200 Message-Id: <20241204163216.433795-7-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241204163216.433795-1-kvalo@kernel.org> References: <20241204163216.433795-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 QMI host capability has the information regarding MLO parameters such as device_id, MLO capability, group id and the information of each devices involved in the group and sent immediately on QMI server arrive event. Currently, only one device is involved in the group and hence, single device information is sent as part of MLO capability of host. But, in future when multi device group abstraction is introduced, host should send all the device information involved in the group as part of QMI MLO host capability rather than single device. Hence, sending QMI host capability immediately on server arrive of a device might not be ideal for multi device group abstraction as the details of other devices in the group would not be available. Hence, once QMI server arrive event is received, request for QMI PHY capabilities of device, and defer the host capability send for that device. After QMI PHY capability is received for all the devices in the group trigger the host capability event for the deferred devices in the group. Hence, add changes to defer the QMI host capability event until the device group is ready and then resume the QMI exchange for all the device with host capabilities. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/core.c | 21 ++++++ drivers/net/wireless/ath/ath12k/qmi.c | 98 ++++++++++++++++++++++++-- drivers/net/wireless/ath/ath12k/qmi.h | 20 ++++++ 3 files changed, 134 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index bbfa57d097af..18b29515c6ae 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -969,6 +969,25 @@ bool ath12k_core_hw_group_start_ready(struct ath12k_hw_group *ag) return (ag->num_started == ag->num_devices); } +static void ath12k_core_trigger_partner(struct ath12k_base *ab) +{ + struct ath12k_hw_group *ag = ab->ag; + struct ath12k_base *partner_ab; + bool found = false; + int i; + + for (i = 0; i < ag->num_devices; i++) { + partner_ab = ag->ab[i]; + if (!partner_ab) + continue; + + if (found) + ath12k_qmi_trigger_host_cap(partner_ab); + + found = (partner_ab == ab); + } +} + int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab) { struct ath12k_hw_group *ag = ath12k_ab_to_ag(ab); @@ -1010,6 +1029,8 @@ int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab) goto err_core_stop; } ath12k_dbg(ab, ATH12K_DBG_BOOT, "group %d started\n", ag->id); + } else { + ath12k_core_trigger_partner(ab); } mutex_unlock(&ag->mutex); diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index 8b4d500fe426..2591d132a3fc 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -3088,11 +3088,69 @@ ath12k_qmi_driver_event_post(struct ath12k_qmi *qmi, return 0; } +void ath12k_qmi_trigger_host_cap(struct ath12k_base *ab) +{ + struct ath12k_qmi *qmi = &ab->qmi; + + spin_lock(&qmi->event_lock); + + if (ath12k_qmi_get_event_block(qmi)) + ath12k_qmi_set_event_block(qmi, false); + + spin_unlock(&qmi->event_lock); + + ath12k_dbg(ab, ATH12K_DBG_QMI, "trigger host cap for device id %d\n", + ab->device_id); + + ath12k_qmi_driver_event_post(qmi, ATH12K_QMI_EVENT_HOST_CAP, NULL); +} + +static bool ath12k_qmi_hw_group_host_cap_ready(struct ath12k_hw_group *ag) +{ + struct ath12k_base *ab; + int i; + + for (i = 0; i < ag->num_devices; i++) { + ab = ag->ab[i]; + + if (!(ab && ab->qmi.num_radios != U8_MAX)) + return false; + } + + return true; +} + +static struct ath12k_base *ath12k_qmi_hw_group_find_blocked(struct ath12k_hw_group *ag) +{ + struct ath12k_base *ab; + int i; + + lockdep_assert_held(&ag->mutex); + + for (i = 0; i < ag->num_devices; i++) { + ab = ag->ab[i]; + if (!ab) + continue; + + spin_lock(&ab->qmi.event_lock); + + if (ath12k_qmi_get_event_block(&ab->qmi)) { + spin_unlock(&ab->qmi.event_lock); + return ab; + } + + spin_unlock(&ab->qmi.event_lock); + } + + return NULL; +} + /* clang stack usage explodes if this is inlined */ static noinline_for_stack int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi) { - struct ath12k_base *ab = qmi->ab; + struct ath12k_base *ab = qmi->ab, *block_ab; + struct ath12k_hw_group *ag = ab->ag; int ret; ath12k_qmi_phy_cap_send(ab); @@ -3103,12 +3161,22 @@ int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi) return ret; } - ret = ath12k_qmi_host_cap_send(ab); - if (ret < 0) { - ath12k_warn(ab, "qmi failed to send host cap QMI:%d\n", ret); - return ret; + spin_lock(&qmi->event_lock); + + ath12k_qmi_set_event_block(qmi, true); + + spin_unlock(&qmi->event_lock); + + mutex_lock(&ag->mutex); + + if (ath12k_qmi_hw_group_host_cap_ready(ag)) { + block_ab = ath12k_qmi_hw_group_find_blocked(ag); + if (block_ab) + ath12k_qmi_trigger_host_cap(block_ab); } + mutex_unlock(&ag->mutex); + return ret; } @@ -3295,6 +3363,21 @@ static const struct qmi_ops ath12k_qmi_ops = { .del_server = ath12k_qmi_ops_del_server, }; +static int ath12k_qmi_event_host_cap(struct ath12k_qmi *qmi) +{ + struct ath12k_base *ab = qmi->ab; + int ret; + + ret = ath12k_qmi_host_cap_send(ab); + if (ret < 0) { + ath12k_warn(ab, "failed to send qmi host cap for device id %d: %d\n", + ab->device_id, ret); + return ret; + } + + return ret; +} + static void ath12k_qmi_driver_event_work(struct work_struct *work) { struct ath12k_qmi *qmi = container_of(work, struct ath12k_qmi, @@ -3351,6 +3434,11 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work) &ab->dev_flags); break; + case ATH12K_QMI_EVENT_HOST_CAP: + ret = ath12k_qmi_event_host_cap(qmi); + if (ret < 0) + set_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags); + break; default: ath12k_warn(ab, "invalid event type: %d", event->type); break; diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h index 0dfcbd8cb59b..98f6009ab21e 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.h +++ b/drivers/net/wireless/ath/ath12k/qmi.h @@ -68,6 +68,7 @@ enum ath12k_qmi_event_type { ATH12K_QMI_EVENT_FORCE_FW_ASSERT, ATH12K_QMI_EVENT_POWER_UP, ATH12K_QMI_EVENT_POWER_DOWN, + ATH12K_QMI_EVENT_HOST_CAP, ATH12K_QMI_EVENT_MAX, }; @@ -142,6 +143,10 @@ struct ath12k_qmi { u32 target_mem_mode; bool target_mem_delayed; u8 cal_done; + + /* protected with struct ath12k_qmi::event_lock */ + bool block_event; + u8 num_radios; struct target_info target; struct m3_mem_region m3_mem; @@ -594,11 +599,26 @@ struct qmi_wlanfw_wlan_ini_resp_msg_v01 { struct qmi_response_type_v01 resp; }; +static inline void ath12k_qmi_set_event_block(struct ath12k_qmi *qmi, bool block) +{ + lockdep_assert_held(&qmi->event_lock); + + qmi->block_event = block; +} + +static inline bool ath12k_qmi_get_event_block(struct ath12k_qmi *qmi) +{ + lockdep_assert_held(&qmi->event_lock); + + return qmi->block_event; +} + int ath12k_qmi_firmware_start(struct ath12k_base *ab, u32 mode); void ath12k_qmi_firmware_stop(struct ath12k_base *ab); void ath12k_qmi_deinit_service(struct ath12k_base *ab); int ath12k_qmi_init_service(struct ath12k_base *ab); void ath12k_qmi_free_resource(struct ath12k_base *ab); +void ath12k_qmi_trigger_host_cap(struct ath12k_base *ab); #endif From patchwork Wed Dec 4 16:32:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 13894081 X-Patchwork-Delegate: quic_jjohnson@quicinc.com 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 4B5EC20D4F1 for ; Wed, 4 Dec 2024 16:32:26 +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=1733329947; cv=none; b=DS0gseRRSEWbLpAfzpJhfwUxtM7GkQWbYcwUnAHgxcY4Z4WY5F1aLdWiooQOPTfGlVADnf/ALe59G3OAJz9FiyEf9HX1H3gVyma1U6EkEGwOEE5b5IHBwkoMw0QE4IQ86iy/T2WtJYkNfSvzWP75G4/KXmgLwsN0DOYmijBQzWU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733329947; c=relaxed/simple; bh=suF5wjzH9zVda5puY3Df1rUEkESjUa138xAJbbDq2XA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=YYzlg4tg5gHuUnzxep06xKnHJ2xswrdBPpOVk7yECVhrjpc+Cy3NS1an6yNBLYZgzu4mpl5da8S3ST0cmP8oEVzPAIK4KXXngbUPydFyCh0Mplx0OUiJpxLUU61Dp983AKYTLyRyZJ269fVdXuspU337NnKKuH+8+WdJHx3/eLw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Fd2n3ADc; 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="Fd2n3ADc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 42C76C4CED2; Wed, 4 Dec 2024 16:32:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733329946; bh=suF5wjzH9zVda5puY3Df1rUEkESjUa138xAJbbDq2XA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Fd2n3ADcilUxOZotIFVRi7WwKb4sI1aelt+fLU1dFqB5f6vH13NoZzFl4d7pBk/WK G7dbvUyK+441RVWnB/5kclWyIK98dU2R0nLTiegpB24tBQLOyU1kHaehYw4I7L+UUm 9yGyu0f00KCA16eG4lyX0xeFjFpwtoL/W5MD7i+qSbCp2es1lAV5SdFH8dHrEHMcDc 0ra+Z+4l1qOwjinn+xhC798t5bMRo5PligpPlStzpiJ5EBeqGTK4dIaP9OijBiKHSG fCYJzJP+m8C2vX8Qu24R3VjaITKqShBSCC41TBMjXKsPR8G2bxOnyj82E4bvwKxug8 uhg82kiECtMRQ== From: Kalle Valo To: ath12k@lists.infradead.org Cc: linux-wireless@vger.kernel.org Subject: [PATCH 7/7] wifi: ath12k: introduce mlo_capable flag for device group Date: Wed, 4 Dec 2024 18:32:16 +0200 Message-Id: <20241204163216.433795-8-kvalo@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241204163216.433795-1-kvalo@kernel.org> References: <20241204163216.433795-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, during mac80211 allocate and register single device is considered for the registration. But, in future, during multi device group abstraction is introduced, all the devices has to be combined together as a single abstraction and then hardware should be allocated. All the devices in the group should be combined together only if it supports inter device mlo capability. The decision of whether to combine the devices or not can be based on the mlo capability flag in ath12k_hw_group. By default, mlo_capable flag in the group would be set as false. During QMI PHY capability exchange, only when we have more than one chip in the group or if one chip, then that chip supports inter MLO, then mlo_capable flag in the group will be enabled. Add changes to introduce mlo_capable flag for device group and refactor ath12k_mac_hw_allocate() api based on device group (ag) rather than device (ab). Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Harshitha Prem Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath12k/core.c | 17 +++++++++++++++++ drivers/net/wireless/ath/ath12k/core.h | 3 +++ drivers/net/wireless/ath/ath12k/mac.c | 8 +++++--- drivers/net/wireless/ath/ath12k/qmi.c | 6 ++++-- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 18b29515c6ae..49d1ac15cb7a 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -1439,6 +1439,7 @@ static struct ath12k_hw_group *ath12k_core_hw_group_assign(struct ath12k_base *a ab->device_id = ag->num_probed++; ag->ab[ab->device_id] = ab; ab->ag = ag; + ag->mlo_capable = false; return ag; } @@ -1548,6 +1549,22 @@ static int ath12k_core_hw_group_create(struct ath12k_hw_group *ag) return 0; } +void ath12k_core_hw_group_set_mlo_capable(struct ath12k_hw_group *ag) +{ + lockdep_assert_held(&ag->mutex); + + /* If more than one devices are grouped, then inter MLO + * functionality can work still independent of whether internally + * each device supports single_chip_mlo or not. + * Only when there is one device, then it depends whether the + * device can support intra chip MLO or not + */ + if (ag->num_devices > 1) + ag->mlo_capable = true; + else + ag->mlo_capable = ag->ab[0]->single_chip_mlo_supp; +} + int ath12k_core_init(struct ath12k_base *ab) { struct ath12k_hw_group *ag; diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 64252d6491cd..458e3d0071a8 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -844,6 +844,7 @@ struct ath12k_hw_group { */ struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO]; u8 num_hw; + bool mlo_capable; }; /* Master structure to hold the hw data which may be used in core module */ @@ -1066,6 +1067,8 @@ u32 ath12k_core_get_max_station_per_radio(struct ath12k_base *ab); u32 ath12k_core_get_max_peers_per_radio(struct ath12k_base *ab); u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab); +void ath12k_core_hw_group_set_mlo_capable(struct ath12k_hw_group *ag); + static inline const char *ath12k_scan_state_str(enum ath12k_scan_state state) { switch (state) { diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 1cf724a530b5..c4eab4c1c10e 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -10968,10 +10968,12 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag) /* All pdev get combined and register as single wiphy based on * hardware group which participate in multi-link operation else * each pdev get register separately. - * - * Currently, registering as single pdevs. */ - radio_per_hw = 1; + if (ag->mlo_capable) + radio_per_hw = total_radio; + else + radio_per_hw = 1; + num_hw = total_radio / radio_per_hw; if (WARN_ON(num_hw >= ATH12K_GROUP_MAX_RADIO)) diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index 2591d132a3fc..ba3cd2342465 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -2023,9 +2023,9 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab, u8 hw_link_id = 0; int i; - if (!ab->single_chip_mlo_supp) { + if (!ab->ag->mlo_capable) { ath12k_dbg(ab, ATH12K_DBG_QMI, - "intra device MLO is disabled hence skip QMI MLO cap"); + "MLO is disabled hence skip QMI MLO cap"); return; } @@ -3170,6 +3170,8 @@ int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi) mutex_lock(&ag->mutex); if (ath12k_qmi_hw_group_host_cap_ready(ag)) { + ath12k_core_hw_group_set_mlo_capable(ag); + block_ab = ath12k_qmi_hw_group_find_blocked(ag); if (block_ab) ath12k_qmi_trigger_host_cap(block_ab);