linux-pikaos-template/patches/surface/0002-mwifiex.patch

401 lines
16 KiB
Diff
Raw Normal View History

2023-04-24 13:43:21 +02:00
From efd716f5123331754ebfc53bccfef07e17fb328b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Tue, 3 Nov 2020 13:28:04 +0100
Subject: [PATCH] mwifiex: Add quirk resetting the PCI bridge on MS Surface
devices
The most recent firmware of the 88W8897 card reports a hardcoded LTR
value to the system during initialization, probably as an (unsuccessful)
attempt of the developers to fix firmware crashes. This LTR value
prevents most of the Microsoft Surface devices from entering deep
powersaving states (either platform C-State 10 or S0ix state), because
the exit latency of that state would be higher than what the card can
tolerate.
Turns out the card works just the same (including the firmware crashes)
no matter if that hardcoded LTR value is reported or not, so it's kind
of useless and only prevents us from saving power.
To get rid of those hardcoded LTR reports, it's possible to reset the
PCI bridge device after initializing the cards firmware. I'm not exactly
sure why that works, maybe the power management subsystem of the PCH
resets its stored LTR values when doing a function level reset of the
bridge device. Doing the reset once after starting the wifi firmware
works very well, probably because the firmware only reports that LTR
value a single time during firmware startup.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/pcie.c | 12 +++++++++
.../wireless/marvell/mwifiex/pcie_quirks.c | 26 +++++++++++++------
.../wireless/marvell/mwifiex/pcie_quirks.h | 1 +
3 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 9a698a16a8f38..14687342bc81c 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -1762,9 +1762,21 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
+ struct pci_dev *pdev = card->dev;
+ struct pci_dev *parent_pdev = pci_upstream_bridge(pdev);
const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
int tx_wrap = card->txbd_wrptr & reg->tx_wrap_mask;
+ /* Trigger a function level reset of the PCI bridge device, this makes
+ * the firmware of PCIe 88W8897 cards stop reporting a fixed LTR value
+ * that prevents the system from entering package C10 and S0ix powersaving
+ * states.
+ * We need to do it here because it must happen after firmware
+ * initialization and this function is called after that is done.
+ */
+ if (card->quirks & QUIRK_DO_FLR_ON_BRIDGE)
+ pci_reset_function(parent_pdev);
+
/* Write the RX ring read pointer in to reg->rx_rdptr */
if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr |
tx_wrap)) {
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
index dd6d21f1dbfd7..f46b06f8d6435 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
@@ -13,7 +13,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 4"),
},
- .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Pro 5",
@@ -22,7 +23,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1796"),
},
- .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Pro 5 (LTE)",
@@ -31,7 +33,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1807"),
},
- .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Pro 6",
@@ -39,7 +42,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 6"),
},
- .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Book 1",
@@ -47,7 +51,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book"),
},
- .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Book 2",
@@ -55,7 +60,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book 2"),
},
- .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Laptop 1",
@@ -63,7 +69,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop"),
},
- .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Laptop 2",
@@ -71,7 +78,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop 2"),
},
- .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ .driver_data = (void *)(QUIRK_FW_RST_D3COLD |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{}
};
@@ -89,6 +97,8 @@ void mwifiex_initialize_quirks(struct pcie_service_card *card)
dev_info(&pdev->dev, "no quirks enabled\n");
if (card->quirks & QUIRK_FW_RST_D3COLD)
dev_info(&pdev->dev, "quirk reset_d3cold enabled\n");
+ if (card->quirks & QUIRK_DO_FLR_ON_BRIDGE)
+ dev_info(&pdev->dev, "quirk do_flr_on_bridge enabled\n");
}
static void mwifiex_pcie_set_power_d3cold(struct pci_dev *pdev)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
index d6ff964aec5bf..5d30ae39d65ec 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
@@ -4,6 +4,7 @@
#include "pcie.h"
#define QUIRK_FW_RST_D3COLD BIT(0)
+#define QUIRK_DO_FLR_ON_BRIDGE BIT(1)
void mwifiex_initialize_quirks(struct pcie_service_card *card);
int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
--
2.40.0
From 2de203271a35cc09eff860df2f35c5ca5e6ae52c Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Sun, 4 Oct 2020 00:11:49 +0900
Subject: [PATCH] mwifiex: pcie: disable bridge_d3 for Surface gen4+
Currently, mwifiex fw will crash after suspend on recent kernel series.
On Windows, it seems that the root port of wifi will never enter D3 state
(stay on D0 state). And on Linux, disabling the D3 state for the
bridge fixes fw crashing after suspend.
This commit disables the D3 state of root port on driver initialization
and fixes fw crashing after suspend.
Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/pcie.c | 7 +++++
.../wireless/marvell/mwifiex/pcie_quirks.c | 27 +++++++++++++------
.../wireless/marvell/mwifiex/pcie_quirks.h | 1 +
3 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 14687342bc81c..5e1a341f63dff 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -368,6 +368,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct pcie_service_card *card;
+ struct pci_dev *parent_pdev = pci_upstream_bridge(pdev);
int ret;
pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
@@ -409,6 +410,12 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
return -1;
}
+ /* disable bridge_d3 for Surface gen4+ devices to fix fw crashing
+ * after suspend
+ */
+ if (card->quirks & QUIRK_NO_BRIDGE_D3)
+ parent_pdev->bridge_d3 = false;
+
return 0;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
index f46b06f8d6435..99b024ecbadea 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
@@ -14,7 +14,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 4"),
},
.driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- QUIRK_DO_FLR_ON_BRIDGE),
+ QUIRK_DO_FLR_ON_BRIDGE |
+ QUIRK_NO_BRIDGE_D3),
},
{
.ident = "Surface Pro 5",
@@ -24,7 +25,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1796"),
},
.driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- QUIRK_DO_FLR_ON_BRIDGE),
+ QUIRK_DO_FLR_ON_BRIDGE |
+ QUIRK_NO_BRIDGE_D3),
},
{
.ident = "Surface Pro 5 (LTE)",
@@ -34,7 +36,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1807"),
},
.driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- QUIRK_DO_FLR_ON_BRIDGE),
+ QUIRK_DO_FLR_ON_BRIDGE |
+ QUIRK_NO_BRIDGE_D3),
},
{
.ident = "Surface Pro 6",
@@ -43,7 +46,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 6"),
},
.driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- QUIRK_DO_FLR_ON_BRIDGE),
+ QUIRK_DO_FLR_ON_BRIDGE |
+ QUIRK_NO_BRIDGE_D3),
},
{
.ident = "Surface Book 1",
@@ -52,7 +56,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book"),
},
.driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- QUIRK_DO_FLR_ON_BRIDGE),
+ QUIRK_DO_FLR_ON_BRIDGE |
+ QUIRK_NO_BRIDGE_D3),
},
{
.ident = "Surface Book 2",
@@ -61,7 +66,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book 2"),
},
.driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- QUIRK_DO_FLR_ON_BRIDGE),
+ QUIRK_DO_FLR_ON_BRIDGE |
+ QUIRK_NO_BRIDGE_D3),
},
{
.ident = "Surface Laptop 1",
@@ -70,7 +76,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop"),
},
.driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- QUIRK_DO_FLR_ON_BRIDGE),
+ QUIRK_DO_FLR_ON_BRIDGE |
+ QUIRK_NO_BRIDGE_D3),
},
{
.ident = "Surface Laptop 2",
@@ -79,7 +86,8 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop 2"),
},
.driver_data = (void *)(QUIRK_FW_RST_D3COLD |
- QUIRK_DO_FLR_ON_BRIDGE),
+ QUIRK_DO_FLR_ON_BRIDGE |
+ QUIRK_NO_BRIDGE_D3),
},
{}
};
@@ -99,6 +107,9 @@ void mwifiex_initialize_quirks(struct pcie_service_card *card)
dev_info(&pdev->dev, "quirk reset_d3cold enabled\n");
if (card->quirks & QUIRK_DO_FLR_ON_BRIDGE)
dev_info(&pdev->dev, "quirk do_flr_on_bridge enabled\n");
+ if (card->quirks & QUIRK_NO_BRIDGE_D3)
+ dev_info(&pdev->dev,
+ "quirk no_brigde_d3 enabled\n");
}
static void mwifiex_pcie_set_power_d3cold(struct pci_dev *pdev)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
index 5d30ae39d65ec..c14eb56eb9118 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
@@ -5,6 +5,7 @@
#define QUIRK_FW_RST_D3COLD BIT(0)
#define QUIRK_DO_FLR_ON_BRIDGE BIT(1)
+#define QUIRK_NO_BRIDGE_D3 BIT(2)
void mwifiex_initialize_quirks(struct pcie_service_card *card);
int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
--
2.40.0
From 16c7b19c13e1edab7f236baa59f8f685a4d719b4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Thu, 25 Mar 2021 11:33:02 +0100
Subject: [PATCH] Bluetooth: btusb: Lower passive lescan interval on Marvell
88W8897
The Marvell 88W8897 combined wifi and bluetooth card (pcie+usb version)
is used in a lot of Microsoft Surface devices, and all those devices
suffer from very low 2.4GHz wifi connection speeds while bluetooth is
enabled. The reason for that is that the default passive scanning
interval for Bluetooth Low Energy devices is quite high in Linux
(interval of 60 msec and scan window of 30 msec, see hci_core.c), and
the Marvell chip is known for its bad bt+wifi coexisting performance.
So decrease that passive scan interval and make the scan window shorter
on this particular device to allow for spending more time transmitting
wifi signals: The new scan interval is 250 msec (0x190 * 0.625 msec) and
the new scan window is 6.25 msec (0xa * 0,625 msec).
This change has a very large impact on the 2.4GHz wifi speeds and gets
it up to performance comparable with the Windows driver, which seems to
apply a similar quirk.
The interval and window length were tested and found to work very well
with a lot of Bluetooth Low Energy devices, including the Surface Pen, a
Bluetooth Speaker and two modern Bluetooth headphones. All devices were
discovered immediately after turning them on. Even lower values were
also tested, but they introduced longer delays until devices get
discovered.
Patchset: mwifiex
---
drivers/bluetooth/btusb.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 5c536151ef836..4de564dd1c604 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -65,6 +65,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_INTEL_BROKEN_INITIAL_NCMD BIT(25)
#define BTUSB_INTEL_NO_WBS_SUPPORT BIT(26)
#define BTUSB_ACTIONS_SEMI BIT(27)
+#define BTUSB_LOWER_LESCAN_INTERVAL BIT(28)
static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -468,6 +469,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL },
{ USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL },
{ USB_DEVICE(0x1286, 0x204e), .driver_info = BTUSB_MARVELL },
+ { USB_DEVICE(0x1286, 0x204c), .driver_info = BTUSB_LOWER_LESCAN_INTERVAL },
/* Intel Bluetooth devices */
{ USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_COMBINED },
@@ -4033,6 +4035,19 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info & BTUSB_MARVELL)
hdev->set_bdaddr = btusb_set_bdaddr_marvell;
+ /* The Marvell 88W8897 combined wifi and bluetooth card is known for
+ * very bad bt+wifi coexisting performance.
+ *
+ * Decrease the passive BT Low Energy scan interval a bit
+ * (0x0190 * 0.625 msec = 250 msec) and make the scan window shorter
+ * (0x000a * 0,625 msec = 6.25 msec). This allows for significantly
+ * higher wifi throughput while passively scanning for BT LE devices.
+ */
+ if (id->driver_info & BTUSB_LOWER_LESCAN_INTERVAL) {
+ hdev->le_scan_interval = 0x0190;
+ hdev->le_scan_window = 0x000a;
+ }
+
if (IS_ENABLED(CONFIG_BT_HCIBTUSB_MTK) &&
(id->driver_info & BTUSB_MEDIATEK)) {
hdev->setup = btusb_mtk_setup;
--
2.40.0