lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250212-wilc3000_bt-v1-9-9609b784874e@bootlin.com>
Date: Wed, 12 Feb 2025 16:46:28 +0100
From: Alexis Lothoré <alexis.lothore@...tlin.com>
To: Alexis Lothoré <alexis.lothore@...tlin.com>, 
 Marcel Holtmann <marcel@...tmann.org>, 
 Luiz Augusto von Dentz <luiz.dentz@...il.com>, 
 Rob Herring <robh@...nel.org>, Krzysztof Kozlowski <krzk+dt@...nel.org>, 
 Conor Dooley <conor+dt@...nel.org>, Ajay Singh <ajay.kathat@...rochip.com>, 
 Claudiu Beznea <claudiu.beznea@...on.dev>, Kalle Valo <kvalo@...nel.org>, 
 "David S. Miller" <davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>, 
 Jakub Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>, 
 Simon Horman <horms@...nel.org>, 
 Nicolas Ferre <nicolas.ferre@...rochip.com>, 
 Alexandre Belloni <alexandre.belloni@...tlin.com>
Cc: Marek Vasut <marex@...x.de>, 
 Thomas Petazzoni <thomas.petazzoni@...tlin.com>, 
 linux-bluetooth@...r.kernel.org, devicetree@...r.kernel.org, 
 linux-kernel@...r.kernel.org, linux-wireless@...r.kernel.org, 
 netdev@...r.kernel.org, linux-arm-kernel@...ts.infradead.org
Subject: [PATCH 09/12] wifi: wilc1000: disable firmware power save if
 bluetooth is in use

If the wlan interface exposed by wilc driver has power save enabled
(either explicitly with iw dev wlan set power_save on, or because
kernel is built with CONFIG_CFG80211_DEFAULT_PS), it will send a power
management command to the wlan firmware when corresponding interface is
brought up. The bluetooth part, if used, is supposed to work
independently from the WLAN CPU. Unfortunately, this power save
management, if applied by the WLAN side, disrupts bluetooth operations
(the bluetooth CPU does not answer any command anymore on the UART
interface)

Make sure that the bluetooth part can work independently by disabling
power save in wlan firmware when bluetooth is in use.

Signed-off-by: Alexis Lothoré <alexis.lothore@...tlin.com>
---
 drivers/net/wireless/microchip/wilc1000/bt.c       | 29 +++++++++++++++++++---
 drivers/net/wireless/microchip/wilc1000/cfg80211.c |  5 +++-
 drivers/net/wireless/microchip/wilc1000/netdev.h   |  3 +++
 3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/microchip/wilc1000/bt.c b/drivers/net/wireless/microchip/wilc1000/bt.c
index b0f68a5479a5bd6f70e2390a35512037dc6c332b..f0eb5fb506eddf0f6f4f3f0b182eaa650c1c7a87 100644
--- a/drivers/net/wireless/microchip/wilc1000/bt.c
+++ b/drivers/net/wireless/microchip/wilc1000/bt.c
@@ -7,6 +7,7 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <net/wilc.h>
+#include "cfg80211.h"
 #include "netdev.h"
 #include "wlan_if.h"
 #include "wlan.h"
@@ -261,22 +262,36 @@ static int wilc_bt_start(struct wilc *wilc)
 int wilc_bt_init(void *wilc_wl_priv)
 {
 	struct wilc *wilc = (struct wilc *)wilc_wl_priv;
+	struct wilc_vif *vif;
 	int ret;
 
+	wilc->bt_enabled = true;
+
 	if (!wilc->hif_func->hif_is_init(wilc)) {
 		dev_info(wilc->dev, "Initializing bus before starting BT");
 		acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
 		ret = wilc->hif_func->hif_init(wilc, false);
 		release_bus(wilc, WILC_BUS_RELEASE_ONLY);
-		if (ret)
+		if (ret) {
+			wilc->bt_enabled = false;
 			return ret;
+		}
 	}
 
+	/* Power save feature managed by WLAN firmware may disrupt
+	 * operations from the bluetooth CPU, so disable it while bluetooth
+	 * is in use (if enabled, it will be enabled back when bluetooth is
+	 * not used anymore)
+	 */
+	vif = wilc_get_wl_to_vif(wilc);
+	if (wilc->power_save_mode && wilc_set_power_mgmt(vif, false))
+		goto hif_deinit;
+
 	mutex_lock(&wilc->radio_fw_start);
 	ret = wilc_bt_power_up(wilc);
 	if (ret) {
 		dev_err(wilc->dev, "Error powering up bluetooth chip\n");
-		goto hif_deinit;
+		goto reenable_power_save;
 	}
 	ret = wilc_bt_firmware_download(wilc);
 	if (ret) {
@@ -293,10 +308,14 @@ int wilc_bt_init(void *wilc_wl_priv)
 
 power_down:
 	wilc_bt_power_down(wilc);
-hif_deinit:
+reenable_power_save:
+	if (wilc->power_save_mode_request)
+		wilc_set_power_mgmt(vif, true);
 	mutex_unlock(&wilc->radio_fw_start);
+hif_deinit:
 	if (!wilc->initialized)
 		wilc->hif_func->hif_deinit(wilc);
+	wilc->bt_enabled = false;
 	return ret;
 }
 EXPORT_SYMBOL(wilc_bt_init);
@@ -304,6 +323,7 @@ EXPORT_SYMBOL(wilc_bt_init);
 int wilc_bt_shutdown(void *wilc_wl_priv)
 {
 	struct wilc *wilc = (struct wilc *)wilc_wl_priv;
+	struct wilc_vif *vif;
 	int ret;
 
 	mutex_lock(&wilc->radio_fw_start);
@@ -313,6 +333,9 @@ int wilc_bt_shutdown(void *wilc_wl_priv)
 		dev_warn(wilc->dev, "Failed to disable BT CPU\n");
 	if (wilc_bt_power_down(wilc))
 		dev_warn(wilc->dev, "Failed to power down BT CPU\n");
+	vif = wilc_get_wl_to_vif(wilc);
+	if (wilc->power_save_mode_request && wilc_set_power_mgmt(vif, true))
+		dev_warn(wilc->dev, "Failed to set back wlan power save\n");
 	if (!wilc->initialized)
 		wilc->hif_func->hif_deinit(wilc);
 	mutex_unlock(&wilc->radio_fw_start);
diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
index ff8c1a40634cee9960777eb017f6b2905e6399a5..04cff3561aad847a3f58a09766d0ef0fa61603e0 100644
--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c
+++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
@@ -1344,11 +1344,14 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 {
 	struct wilc_vif *vif = netdev_priv(dev);
 	struct wilc_priv *priv = &vif->priv;
+	struct wilc *wilc = vif->wilc;
 
 	if (!priv->hif_drv)
 		return -EIO;
 
-	wilc_set_power_mgmt(vif, enabled);
+	wilc->power_save_mode_request = enabled;
+	if (!wilc->bt_enabled)
+		wilc_set_power_mgmt(vif, enabled);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.h b/drivers/net/wireless/microchip/wilc1000/netdev.h
index 5837f8ffe548dad1b756cdbd8543636f2be0e9b0..4c297eb95eeb143fc2f1248e616ee307afa52dbd 100644
--- a/drivers/net/wireless/microchip/wilc1000/netdev.h
+++ b/drivers/net/wireless/microchip/wilc1000/netdev.h
@@ -213,6 +213,7 @@ struct wilc {
 	struct clk *rtc_clk;
 	bool initialized;
 	u32 chipid;
+	bool power_save_mode_request;
 	bool power_save_mode;
 	int dev_irq_num;
 	int close;
@@ -289,6 +290,8 @@ struct wilc {
 	u8 nv_mac_address[ETH_ALEN];
 	/* Lock to prevent concurrent start of wlan/bluetooth firmware */
 	struct mutex radio_fw_start;
+	/* Is the bluetooth part in use ? */
+	bool bt_enabled;
 };
 
 struct wilc_wfi_mon_priv {

-- 
2.48.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ