linux-surface/patches/5.14/0002-mwifiex.patch
Maximilian Luz 9dc59ad56e
Update v5.14 patches
Changes:
 - Fixes for AMD pinctrl wakeup (https://github.com/linux-surface/kernel/pull/104).
   This should allow the AMD versions of the SL3 and SL4 to wake up by
   opening the lid.
 - Rebase onto v5.14.6

Links:
 - kernel: e48e5b7abb
2021-09-18 16:34:45 +02:00

2473 lines
86 KiB
Diff

From 63750c713f707e960ef2ff9688f0a6ad55b31522 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Fri, 20 Aug 2021 16:20:49 +0200
Subject: [PATCH] mwifiex: pcie: add DMI-based quirk implementation for Surface
devices
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This commit adds the ability to apply device-specific quirks to the
mwifiex driver. It uses DMI matching similar to the quirks brcmfmac uses
with dmi.c. We'll add identifiers to match various MS Surface devices,
which this is primarily meant for, later.
This commit is a slightly modified version of a previous patch sent in
by Tsuchiya Yuto.
Co-developed-by: Tsuchiya Yuto <kitakar@gmail.com>
Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
Signed-off-by: Jonas Dreßler <verdre@v0yd.nl>
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/Makefile | 1 +
drivers/net/wireless/marvell/mwifiex/pcie.c | 4 ++
drivers/net/wireless/marvell/mwifiex/pcie.h | 1 +
.../wireless/marvell/mwifiex/pcie_quirks.c | 38 +++++++++++++++++++
.../wireless/marvell/mwifiex/pcie_quirks.h | 20 ++++++++++
5 files changed, 64 insertions(+)
create mode 100644 drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
create mode 100644 drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
diff --git a/drivers/net/wireless/marvell/mwifiex/Makefile b/drivers/net/wireless/marvell/mwifiex/Makefile
index 162d557b78af..2bd00f40958e 100644
--- a/drivers/net/wireless/marvell/mwifiex/Makefile
+++ b/drivers/net/wireless/marvell/mwifiex/Makefile
@@ -49,6 +49,7 @@ mwifiex_sdio-y += sdio.o
obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o
mwifiex_pcie-y += pcie.o
+mwifiex_pcie-y += pcie_quirks.o
obj-$(CONFIG_MWIFIEX_PCIE) += mwifiex_pcie.o
mwifiex_usb-y += usb.o
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 46517515ba72..a530832c9421 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -27,6 +27,7 @@
#include "wmm.h"
#include "11n.h"
#include "pcie.h"
+#include "pcie_quirks.h"
#define PCIE_VERSION "1.0"
#define DRV_NAME "Marvell mwifiex PCIe"
@@ -410,6 +411,9 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
return ret;
}
+ /* check quirks */
+ mwifiex_initialize_quirks(card);
+
if (mwifiex_add_card(card, &card->fw_done, &pcie_ops,
MWIFIEX_PCIE, &pdev->dev)) {
pr_err("%s failed\n", __func__);
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h
index 5ed613d65709..981e330c77d7 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
@@ -244,6 +244,7 @@ struct pcie_service_card {
unsigned long work_flags;
bool pci_reset_ongoing;
+ unsigned long quirks;
};
static inline int
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
new file mode 100644
index 000000000000..c1665ac5c5d9
--- /dev/null
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
@@ -0,0 +1,38 @@
+/*
+ * NXP Wireless LAN device driver: PCIE and platform specific quirks
+ *
+ * This software file (the "File") is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include <linux/dmi.h>
+
+#include "pcie_quirks.h"
+
+/* quirk table based on DMI matching */
+static const struct dmi_system_id mwifiex_quirk_table[] = {
+ {}
+};
+
+void mwifiex_initialize_quirks(struct pcie_service_card *card)
+{
+ struct pci_dev *pdev = card->dev;
+ const struct dmi_system_id *dmi_id;
+
+ dmi_id = dmi_first_match(mwifiex_quirk_table);
+ if (dmi_id)
+ card->quirks = (uintptr_t)dmi_id->driver_data;
+
+ if (!card->quirks)
+ dev_info(&pdev->dev, "no quirks enabled\n");
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
new file mode 100644
index 000000000000..18eacc8c2d3a
--- /dev/null
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
@@ -0,0 +1,20 @@
+/*
+ * NXP Wireless LAN device driver: PCIE and platform specific quirks
+ *
+ * This software file (the "File") is distributed by NXP
+ * under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "pcie.h"
+
+void mwifiex_initialize_quirks(struct pcie_service_card *card);
--
2.33.0
From e2024dec594efc75ee26055e5570babfc50c5cbb Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Fri, 20 Aug 2021 16:20:50 +0200
Subject: [PATCH] mwifiex: pcie: add reset_d3cold quirk for Surface gen4+
devices
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
To reset mwifiex on Surface gen4+ (Pro 4 or later gen) devices, it
seems that putting the wifi device into D3cold is required according
to errata.inf file on Windows installation (Windows/INF/errata.inf).
This patch adds a function that performs power-cycle (put into D3cold
then D0) and call the function at the end of reset_prepare().
Note: Need to also reset the parent device (bridge) of wifi on SB1;
it might be because the bridge of wifi always reports it's in D3hot.
When I tried to reset only the wifi device (not touching parent), it gave
the following error and the reset failed:
acpi device:4b: Cannot transition to power state D0 for parent in D3hot
mwifiex_pcie 0000:03:00.0: can't change power state from D3cold to D0 (config space inaccessible)
Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
Signed-off-by: Jonas Dreßler <verdre@v0yd.nl>
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/pcie.c | 7 +
.../wireless/marvell/mwifiex/pcie_quirks.c | 123 ++++++++++++++++++
.../wireless/marvell/mwifiex/pcie_quirks.h | 3 +
3 files changed, 133 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index a530832c9421..c6ccce426b49 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -528,6 +528,13 @@ static void mwifiex_pcie_reset_prepare(struct pci_dev *pdev)
mwifiex_shutdown_sw(adapter);
clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
+
+ /* On MS Surface gen4+ devices FLR isn't effective to recover from
+ * hangups, so we power-cycle the card instead.
+ */
+ if (card->quirks & QUIRK_FW_RST_D3COLD)
+ mwifiex_pcie_reset_d3cold_quirk(pdev);
+
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
card->pci_reset_ongoing = true;
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
index c1665ac5c5d9..0234cf3c2974 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
@@ -21,6 +21,72 @@
/* quirk table based on DMI matching */
static const struct dmi_system_id mwifiex_quirk_table[] = {
+ {
+ .ident = "Surface Pro 4",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 4"),
+ },
+ .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ },
+ {
+ .ident = "Surface Pro 5",
+ .matches = {
+ /* match for SKU here due to generic product name "Surface Pro" */
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1796"),
+ },
+ .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ },
+ {
+ .ident = "Surface Pro 5 (LTE)",
+ .matches = {
+ /* match for SKU here due to generic product name "Surface Pro" */
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1807"),
+ },
+ .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ },
+ {
+ .ident = "Surface Pro 6",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 6"),
+ },
+ .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ },
+ {
+ .ident = "Surface Book 1",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book"),
+ },
+ .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ },
+ {
+ .ident = "Surface Book 2",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book 2"),
+ },
+ .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ },
+ {
+ .ident = "Surface Laptop 1",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop"),
+ },
+ .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ },
+ {
+ .ident = "Surface Laptop 2",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop 2"),
+ },
+ .driver_data = (void *)QUIRK_FW_RST_D3COLD,
+ },
{}
};
@@ -35,4 +101,61 @@ void mwifiex_initialize_quirks(struct pcie_service_card *card)
if (!card->quirks)
dev_info(&pdev->dev, "no quirks enabled\n");
+ if (card->quirks & QUIRK_FW_RST_D3COLD)
+ dev_info(&pdev->dev, "quirk reset_d3cold enabled\n");
+}
+
+static void mwifiex_pcie_set_power_d3cold(struct pci_dev *pdev)
+{
+ dev_info(&pdev->dev, "putting into D3cold...\n");
+
+ pci_save_state(pdev);
+ if (pci_is_enabled(pdev))
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, PCI_D3cold);
+}
+
+static int mwifiex_pcie_set_power_d0(struct pci_dev *pdev)
+{
+ int ret;
+
+ dev_info(&pdev->dev, "putting into D0...\n");
+
+ pci_set_power_state(pdev, PCI_D0);
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "pci_enable_device failed\n");
+ return ret;
+ }
+ pci_restore_state(pdev);
+
+ return 0;
+}
+
+int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev)
+{
+ struct pci_dev *parent_pdev = pci_upstream_bridge(pdev);
+ int ret;
+
+ /* Power-cycle (put into D3cold then D0) */
+ dev_info(&pdev->dev, "Using reset_d3cold quirk to perform FW reset\n");
+
+ /* We need to perform power-cycle also for bridge of wifi because
+ * on some devices (e.g. Surface Book 1), the OS for some reasons
+ * can't know the real power state of the bridge.
+ * When tried to power-cycle only wifi, the reset failed with the
+ * following dmesg log:
+ * "Cannot transition to power state D0 for parent in D3hot".
+ */
+ mwifiex_pcie_set_power_d3cold(pdev);
+ mwifiex_pcie_set_power_d3cold(parent_pdev);
+
+ ret = mwifiex_pcie_set_power_d0(parent_pdev);
+ if (ret)
+ return ret;
+ ret = mwifiex_pcie_set_power_d0(pdev);
+ if (ret)
+ return ret;
+
+ return 0;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
index 18eacc8c2d3a..8ec4176d698f 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
@@ -17,4 +17,7 @@
#include "pcie.h"
+#define QUIRK_FW_RST_D3COLD BIT(0)
+
void mwifiex_initialize_quirks(struct pcie_service_card *card);
+int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
--
2.33.0
From 0eef489e04420b39eb090226728a2c648a888357 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Tue, 29 Sep 2020 17:32:22 +0900
Subject: [PATCH] mwifiex: pcie: add reset_wsid quirk for Surface 3
This commit adds reset_wsid quirk and uses this quirk for Surface 3 on
card reset.
To reset mwifiex on Surface 3, it seems that calling the _DSM method
exists in \_SB.WSID [1] device is required.
On Surface 3, calling the _DSM method removes/re-probes the card by
itself. So, need to place the reset function before performing FLR and
skip performing any other reset-related works.
Note that Surface Pro 3 also has the WSID device [2], but it seems to need
more work. This commit only supports Surface 3 yet.
[1] https://github.com/linux-surface/acpidumps/blob/05cba925f3a515f222acb5b3551a032ddde958fe/surface_3/dsdt.dsl#L11947-L12011
[2] https://github.com/linux-surface/acpidumps/blob/05cba925f3a515f222acb5b3551a032ddde958fe/surface_pro_3/dsdt.dsl#L12164-L12216
Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/pcie.c | 10 +++
.../wireless/marvell/mwifiex/pcie_quirks.c | 83 +++++++++++++++++++
.../wireless/marvell/mwifiex/pcie_quirks.h | 6 ++
3 files changed, 99 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index c6ccce426b49..a9d704e8c008 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -2967,6 +2967,16 @@ static void mwifiex_pcie_card_reset_work(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
+ /* On Surface 3, reset_wsid method removes then re-probes card by
+ * itself. So, need to place it here and skip performing any other
+ * reset-related works.
+ */
+ if (card->quirks & QUIRK_FW_RST_WSID_S3) {
+ mwifiex_pcie_reset_wsid_quirk(card->dev);
+ /* skip performing any other reset-related works */
+ return;
+ }
+
/* We can't afford to wait here; remove() might be waiting on us. If we
* can't grab the device lock, maybe we'll get another chance later.
*/
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
index 0234cf3c2974..563dd0d5ac79 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
@@ -15,10 +15,21 @@
* this warranty disclaimer.
*/
+#include <linux/acpi.h>
#include <linux/dmi.h>
#include "pcie_quirks.h"
+/* For reset_wsid quirk */
+#define ACPI_WSID_PATH "\\_SB.WSID"
+#define WSID_REV 0x0
+#define WSID_FUNC_WIFI_PWR_OFF 0x1
+#define WSID_FUNC_WIFI_PWR_ON 0x2
+/* WSID _DSM UUID: "534ea3bf-fcc2-4e7a-908f-a13978f0c7ef" */
+static const guid_t wsid_dsm_guid =
+ GUID_INIT(0x534ea3bf, 0xfcc2, 0x4e7a,
+ 0x90, 0x8f, 0xa1, 0x39, 0x78, 0xf0, 0xc7, 0xef);
+
/* quirk table based on DMI matching */
static const struct dmi_system_id mwifiex_quirk_table[] = {
{
@@ -87,6 +98,14 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
},
.driver_data = (void *)QUIRK_FW_RST_D3COLD,
},
+ {
+ .ident = "Surface 3",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface 3"),
+ },
+ .driver_data = (void *)QUIRK_FW_RST_WSID_S3,
+ },
{}
};
@@ -103,6 +122,9 @@ 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_FW_RST_WSID_S3)
+ dev_info(&pdev->dev,
+ "quirk reset_wsid for Surface 3 enabled\n");
}
static void mwifiex_pcie_set_power_d3cold(struct pci_dev *pdev)
@@ -159,3 +181,64 @@ int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev)
return 0;
}
+
+int mwifiex_pcie_reset_wsid_quirk(struct pci_dev *pdev)
+{
+ acpi_handle handle;
+ union acpi_object *obj;
+ acpi_status status;
+
+ dev_info(&pdev->dev, "Using reset_wsid quirk to perform FW reset\n");
+
+ status = acpi_get_handle(NULL, ACPI_WSID_PATH, &handle);
+ if (ACPI_FAILURE(status)) {
+ dev_err(&pdev->dev, "No ACPI handle for path %s\n",
+ ACPI_WSID_PATH);
+ return -ENODEV;
+ }
+
+ if (!acpi_has_method(handle, "_DSM")) {
+ dev_err(&pdev->dev, "_DSM method not found\n");
+ return -ENODEV;
+ }
+
+ if (!acpi_check_dsm(handle, &wsid_dsm_guid,
+ WSID_REV, WSID_FUNC_WIFI_PWR_OFF)) {
+ dev_err(&pdev->dev,
+ "_DSM method doesn't support wifi power off func\n");
+ return -ENODEV;
+ }
+
+ if (!acpi_check_dsm(handle, &wsid_dsm_guid,
+ WSID_REV, WSID_FUNC_WIFI_PWR_ON)) {
+ dev_err(&pdev->dev,
+ "_DSM method doesn't support wifi power on func\n");
+ return -ENODEV;
+ }
+
+ /* card will be removed immediately after this call on Surface 3 */
+ dev_info(&pdev->dev, "turning wifi off...\n");
+ obj = acpi_evaluate_dsm(handle, &wsid_dsm_guid,
+ WSID_REV, WSID_FUNC_WIFI_PWR_OFF,
+ NULL);
+ if (!obj) {
+ dev_err(&pdev->dev,
+ "device _DSM execution failed for turning wifi off\n");
+ return -EIO;
+ }
+ ACPI_FREE(obj);
+
+ /* card will be re-probed immediately after this call on Surface 3 */
+ dev_info(&pdev->dev, "turning wifi on...\n");
+ obj = acpi_evaluate_dsm(handle, &wsid_dsm_guid,
+ WSID_REV, WSID_FUNC_WIFI_PWR_ON,
+ NULL);
+ if (!obj) {
+ dev_err(&pdev->dev,
+ "device _DSM execution failed for turning wifi on\n");
+ return -EIO;
+ }
+ ACPI_FREE(obj);
+
+ return 0;
+}
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
index 8ec4176d698f..25370c5a4f59 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
@@ -19,5 +19,11 @@
#define QUIRK_FW_RST_D3COLD BIT(0)
+/* Surface 3 and Surface Pro 3 have the same _DSM method but need to
+ * be handled differently. Currently, only S3 is supported.
+ */
+#define QUIRK_FW_RST_WSID_S3 BIT(1)
+
void mwifiex_initialize_quirks(struct pcie_service_card *card);
int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
+int mwifiex_pcie_reset_wsid_quirk(struct pci_dev *pdev);
--
2.33.0
From aebd4ce5cbd13a92df7a90ad197c06a4483e8b14 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Wed, 30 Sep 2020 18:08:24 +0900
Subject: [PATCH] mwifiex: pcie: (OEMB) add quirk for Surface 3 with broken DMI
table
(made referring to http://git.osdn.net/view?p=android-x86/kernel.git;a=commitdiff;h=18e2e857c57633b25b3b4120f212224a108cd883)
On some Surface 3, the DMI table gets corrupted for unknown reasons
and breaks existing DMI matching used for device-specific quirks.
This commit adds the (broken) DMI info for the affected Surface 3.
On affected systems, DMI info will look like this:
$ grep . /sys/devices/virtual/dmi/id/{bios_vendor,board_name,board_vendor,\
chassis_vendor,product_name,sys_vendor}
/sys/devices/virtual/dmi/id/bios_vendor:American Megatrends Inc.
/sys/devices/virtual/dmi/id/board_name:OEMB
/sys/devices/virtual/dmi/id/board_vendor:OEMB
/sys/devices/virtual/dmi/id/chassis_vendor:OEMB
/sys/devices/virtual/dmi/id/product_name:OEMB
/sys/devices/virtual/dmi/id/sys_vendor:OEMB
Expected:
$ grep . /sys/devices/virtual/dmi/id/{bios_vendor,board_name,board_vendor,\
chassis_vendor,product_name,sys_vendor}
/sys/devices/virtual/dmi/id/bios_vendor:American Megatrends Inc.
/sys/devices/virtual/dmi/id/board_name:Surface 3
/sys/devices/virtual/dmi/id/board_vendor:Microsoft Corporation
/sys/devices/virtual/dmi/id/chassis_vendor:Microsoft Corporation
/sys/devices/virtual/dmi/id/product_name:Surface 3
/sys/devices/virtual/dmi/id/sys_vendor:Microsoft Corporation
Signed-off-by: Tsuchiya Yuto <kitakar@gmail.com>
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/pcie_quirks.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
index 563dd0d5ac79..32e2f000e57b 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
@@ -106,6 +106,15 @@ static const struct dmi_system_id mwifiex_quirk_table[] = {
},
.driver_data = (void *)QUIRK_FW_RST_WSID_S3,
},
+ {
+ .ident = "Surface 3",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "OEMB"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "OEMB"),
+ },
+ .driver_data = (void *)QUIRK_FW_RST_WSID_S3,
+ },
{}
};
--
2.33.0
From cb18657288d940515df43d301a23f4a7ccdaa105 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 a9d704e8c008..76e34eeba3af 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -379,6 +379,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",
@@ -420,6 +421,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 32e2f000e57b..356401bab59c 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
@@ -38,7 +38,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_NO_BRIDGE_D3),
},
{
.ident = "Surface Pro 5",
@@ -47,7 +48,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_NO_BRIDGE_D3),
},
{
.ident = "Surface Pro 5 (LTE)",
@@ -56,7 +58,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_NO_BRIDGE_D3),
},
{
.ident = "Surface Pro 6",
@@ -64,7 +67,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_NO_BRIDGE_D3),
},
{
.ident = "Surface Book 1",
@@ -72,7 +76,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_NO_BRIDGE_D3),
},
{
.ident = "Surface Book 2",
@@ -80,7 +85,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_NO_BRIDGE_D3),
},
{
.ident = "Surface Laptop 1",
@@ -88,7 +94,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_NO_BRIDGE_D3),
},
{
.ident = "Surface Laptop 2",
@@ -96,7 +103,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_NO_BRIDGE_D3),
},
{
.ident = "Surface 3",
@@ -134,6 +142,9 @@ void mwifiex_initialize_quirks(struct pcie_service_card *card)
if (card->quirks & QUIRK_FW_RST_WSID_S3)
dev_info(&pdev->dev,
"quirk reset_wsid for Surface 3 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 25370c5a4f59..a1de111ad1db 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
@@ -23,6 +23,7 @@
* be handled differently. Currently, only S3 is supported.
*/
#define QUIRK_FW_RST_WSID_S3 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.33.0
From 7c914c722e8d0680c147e1229b9df5faeecf64ee 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 76e34eeba3af..ca06eb7ac4aa 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -1755,9 +1755,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 356401bab59c..6437f067d07a 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
@@ -39,7 +39,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_NO_BRIDGE_D3),
+ QUIRK_NO_BRIDGE_D3 |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Pro 5",
@@ -49,7 +50,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_NO_BRIDGE_D3),
+ QUIRK_NO_BRIDGE_D3 |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Pro 5 (LTE)",
@@ -59,7 +61,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_NO_BRIDGE_D3),
+ QUIRK_NO_BRIDGE_D3 |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Pro 6",
@@ -68,7 +71,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_NO_BRIDGE_D3),
+ QUIRK_NO_BRIDGE_D3 |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Book 1",
@@ -77,7 +81,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_NO_BRIDGE_D3),
+ QUIRK_NO_BRIDGE_D3 |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Book 2",
@@ -86,7 +91,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_NO_BRIDGE_D3),
+ QUIRK_NO_BRIDGE_D3 |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Laptop 1",
@@ -95,7 +101,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_NO_BRIDGE_D3),
+ QUIRK_NO_BRIDGE_D3 |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface Laptop 2",
@@ -104,7 +111,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_NO_BRIDGE_D3),
+ QUIRK_NO_BRIDGE_D3 |
+ QUIRK_DO_FLR_ON_BRIDGE),
},
{
.ident = "Surface 3",
@@ -145,6 +153,8 @@ void mwifiex_initialize_quirks(struct pcie_service_card *card)
if (card->quirks & QUIRK_NO_BRIDGE_D3)
dev_info(&pdev->dev,
"quirk no_brigde_d3 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 a1de111ad1db..0e429779bb04 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
@@ -24,6 +24,7 @@
*/
#define QUIRK_FW_RST_WSID_S3 BIT(1)
#define QUIRK_NO_BRIDGE_D3 BIT(2)
+#define QUIRK_DO_FLR_ON_BRIDGE BIT(3)
void mwifiex_initialize_quirks(struct pcie_service_card *card);
int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
--
2.33.0
From d15aa728be4149bb4952487314c89f6ade1fb5e0 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 bd37d6fb88c2..d12fb2034d46 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -61,6 +61,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_VALID_LE_STATES 0x800000
#define BTUSB_QCA_WCN6855 0x1000000
#define BTUSB_INTEL_NEWGEN 0x2000000
+#define BTUSB_LOWER_LESCAN_INTERVAL BIT(26)
static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -359,6 +360,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_NEW |
@@ -4697,6 +4699,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.33.0
From 9a562e8d4d3e5e6bd9a6d5520c59b628f81fcc7d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Wed, 11 Nov 2020 12:31:26 +0100
Subject: [PATCH] mwifiex: Small cleanup for handling virtual interface type
changes
Handle the obvious invalid virtual interface type changes with a general
check instead of looking at the individual change.
For type changes from P2P_CLIENT to P2P_GO and the other way round, this
changes the behavior slightly: We now still do nothing, but return
-EOPNOTSUPP instead of 0. Now that behavior was incorrect before and
still is, because type changes between these two types are actually
possible and supported, which we'll fix in a following commit.
Patchset: mwifiex
---
.../net/wireless/marvell/mwifiex/cfg80211.c | 39 +++++++------------
1 file changed, 14 insertions(+), 25 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 0961f4a5e415..e8deba119ff1 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -1141,6 +1141,20 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
return -EBUSY;
}
+ if (type == NL80211_IFTYPE_UNSPECIFIED) {
+ mwifiex_dbg(priv->adapter, INFO,
+ "%s: no new type specified, keeping old type %d\n",
+ dev->name, curr_iftype);
+ return 0;
+ }
+
+ if (curr_iftype == type) {
+ mwifiex_dbg(priv->adapter, INFO,
+ "%s: interface already is of type %d\n",
+ dev->name, curr_iftype);
+ return 0;
+ }
+
switch (curr_iftype) {
case NL80211_IFTYPE_ADHOC:
switch (type) {
@@ -1160,12 +1174,6 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
case NL80211_IFTYPE_AP:
return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
params);
- case NL80211_IFTYPE_UNSPECIFIED:
- mwifiex_dbg(priv->adapter, INFO,
- "%s: kept type as IBSS\n", dev->name);
- fallthrough;
- case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */
- return 0;
default:
mwifiex_dbg(priv->adapter, ERROR,
"%s: changing to %d not supported\n",
@@ -1191,12 +1199,6 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
case NL80211_IFTYPE_AP:
return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
params);
- case NL80211_IFTYPE_UNSPECIFIED:
- mwifiex_dbg(priv->adapter, INFO,
- "%s: kept type as STA\n", dev->name);
- fallthrough;
- case NL80211_IFTYPE_STATION: /* This shouldn't happen */
- return 0;
default:
mwifiex_dbg(priv->adapter, ERROR,
"%s: changing to %d not supported\n",
@@ -1214,12 +1216,6 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
case NL80211_IFTYPE_P2P_GO:
return mwifiex_change_vif_to_p2p(dev, curr_iftype,
type, params);
- case NL80211_IFTYPE_UNSPECIFIED:
- mwifiex_dbg(priv->adapter, INFO,
- "%s: kept type as AP\n", dev->name);
- fallthrough;
- case NL80211_IFTYPE_AP: /* This shouldn't happen */
- return 0;
default:
mwifiex_dbg(priv->adapter, ERROR,
"%s: changing to %d not supported\n",
@@ -1254,13 +1250,6 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
return -EFAULT;
return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
params);
- case NL80211_IFTYPE_UNSPECIFIED:
- mwifiex_dbg(priv->adapter, INFO,
- "%s: kept type as P2P\n", dev->name);
- fallthrough;
- case NL80211_IFTYPE_P2P_CLIENT:
- case NL80211_IFTYPE_P2P_GO:
- return 0;
default:
mwifiex_dbg(priv->adapter, ERROR,
"%s: changing to %d not supported\n",
--
2.33.0
From a61e93f29b79c77dc8ece1b94252a6b170fbd70f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Tue, 10 Nov 2020 12:49:56 +0100
Subject: [PATCH] mwifiex: Use non-posted PCI register writes
On the 88W8897 card it's very important the TX ring write pointer is
updated correctly to its new value before setting the TX ready
interrupt, otherwise the firmware appears to crash (probably because
it's trying to DMA-read from the wrong place).
Since PCI uses "posted writes" when writing to a register, it's not
guaranteed that a write will happen immediately. That means the pointer
might be outdated when setting the TX ready interrupt, leading to
firmware crashes especially when ASPM L1 and L1 substates are enabled
(because of the higher link latency, the write will probably take
longer).
So fix those firmware crashes by always forcing non-posted writes. We do
that by simply reading back the register after writing it, just as a lot
of other drivers do.
There are two reproducers that are fixed with this patch:
1) During rx/tx traffic and with ASPM L1 substates enabled (the enabled
substates are platform dependent), the firmware crashes and eventually a
command timeout appears in the logs. That crash is fixed by using a
non-posted write in mwifiex_pcie_send_data().
2) When sending lots of commands to the card, waking it up from sleep in
very quick intervals, the firmware eventually crashes. That crash
appears to be fixed by some other non-posted write included here.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/pcie.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index ca06eb7ac4aa..95e5851d2d0a 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -237,6 +237,12 @@ static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data)
iowrite32(data, card->pci_mmap1 + reg);
+ /* Do a read-back, which makes the write non-posted, ensuring the
+ * completion before returning.
+ * The firmware of the 88W8897 card is buggy and this avoids crashes.
+ */
+ ioread32(card->pci_mmap1 + reg);
+
return 0;
}
--
2.33.0
From e317bc90fb1361684fdbfd77484fa0f231710c25 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Wed, 11 Nov 2020 12:44:39 +0100
Subject: [PATCH] mwifiex: Use function to check whether interface type change
is allowed
Instead of bailing out in the function which is supposed to do the type
change, detect invalid changes beforehand using a generic function and
return an error if the change is not allowed.
Patchset: mwifiex
---
.../net/wireless/marvell/mwifiex/cfg80211.c | 139 ++++++++++++------
1 file changed, 92 insertions(+), 47 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index e8deba119ff1..dabc59c47de3 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -939,6 +939,76 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv,
return 0;
}
+static bool
+is_vif_type_change_allowed(struct mwifiex_adapter *adapter,
+ enum nl80211_iftype old_iftype,
+ enum nl80211_iftype new_iftype)
+{
+ switch (old_iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ switch (new_iftype) {
+ case NL80211_IFTYPE_STATION:
+ return true;
+ case NL80211_IFTYPE_P2P_CLIENT:
+ case NL80211_IFTYPE_P2P_GO:
+ return adapter->curr_iface_comb.p2p_intf !=
+ adapter->iface_limit.p2p_intf;
+ case NL80211_IFTYPE_AP:
+ return adapter->curr_iface_comb.uap_intf !=
+ adapter->iface_limit.uap_intf;
+ default:
+ return false;
+ }
+
+ case NL80211_IFTYPE_STATION:
+ switch (new_iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ return true;
+ case NL80211_IFTYPE_P2P_CLIENT:
+ case NL80211_IFTYPE_P2P_GO:
+ return adapter->curr_iface_comb.p2p_intf !=
+ adapter->iface_limit.p2p_intf;
+ case NL80211_IFTYPE_AP:
+ return adapter->curr_iface_comb.uap_intf !=
+ adapter->iface_limit.uap_intf;
+ default:
+ return false;
+ }
+
+ case NL80211_IFTYPE_AP:
+ switch (new_iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_STATION:
+ return adapter->curr_iface_comb.sta_intf !=
+ adapter->iface_limit.sta_intf;
+ case NL80211_IFTYPE_P2P_CLIENT:
+ case NL80211_IFTYPE_P2P_GO:
+ return adapter->curr_iface_comb.p2p_intf !=
+ adapter->iface_limit.p2p_intf;
+ default:
+ return false;
+ }
+
+ case NL80211_IFTYPE_P2P_CLIENT:
+ case NL80211_IFTYPE_P2P_GO:
+ switch (new_iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_STATION:
+ return true;
+ case NL80211_IFTYPE_AP:
+ return adapter->curr_iface_comb.uap_intf !=
+ adapter->iface_limit.uap_intf;
+ default:
+ return false;
+ }
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
static int
mwifiex_change_vif_to_p2p(struct net_device *dev,
enum nl80211_iftype curr_iftype,
@@ -955,13 +1025,6 @@ mwifiex_change_vif_to_p2p(struct net_device *dev,
adapter = priv->adapter;
- if (adapter->curr_iface_comb.p2p_intf ==
- adapter->iface_limit.p2p_intf) {
- mwifiex_dbg(adapter, ERROR,
- "cannot create multiple P2P ifaces\n");
- return -1;
- }
-
mwifiex_dbg(adapter, INFO,
"%s: changing role to p2p\n", dev->name);
@@ -1027,15 +1090,6 @@ mwifiex_change_vif_to_sta_adhoc(struct net_device *dev,
adapter = priv->adapter;
- if ((curr_iftype != NL80211_IFTYPE_P2P_CLIENT &&
- curr_iftype != NL80211_IFTYPE_P2P_GO) &&
- (adapter->curr_iface_comb.sta_intf ==
- adapter->iface_limit.sta_intf)) {
- mwifiex_dbg(adapter, ERROR,
- "cannot create multiple station/adhoc ifaces\n");
- return -1;
- }
-
if (type == NL80211_IFTYPE_STATION)
mwifiex_dbg(adapter, INFO,
"%s: changing role to station\n", dev->name);
@@ -1086,13 +1140,6 @@ mwifiex_change_vif_to_ap(struct net_device *dev,
adapter = priv->adapter;
- if (adapter->curr_iface_comb.uap_intf ==
- adapter->iface_limit.uap_intf) {
- mwifiex_dbg(adapter, ERROR,
- "cannot create multiple AP ifaces\n");
- return -1;
- }
-
mwifiex_dbg(adapter, INFO,
"%s: changing role to AP\n", dev->name);
@@ -1155,6 +1202,13 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
return 0;
}
+ if (!is_vif_type_change_allowed(priv->adapter, curr_iftype, type)) {
+ mwifiex_dbg(priv->adapter, ERROR,
+ "%s: change from type %d to %d is not allowed\n",
+ dev->name, curr_iftype, type);
+ return -EOPNOTSUPP;
+ }
+
switch (curr_iftype) {
case NL80211_IFTYPE_ADHOC:
switch (type) {
@@ -1175,12 +1229,9 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
params);
default:
- mwifiex_dbg(priv->adapter, ERROR,
- "%s: changing to %d not supported\n",
- dev->name, type);
- return -EOPNOTSUPP;
+ goto errnotsupp;
}
- break;
+
case NL80211_IFTYPE_STATION:
switch (type) {
case NL80211_IFTYPE_ADHOC:
@@ -1200,12 +1251,9 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
params);
default:
- mwifiex_dbg(priv->adapter, ERROR,
- "%s: changing to %d not supported\n",
- dev->name, type);
- return -EOPNOTSUPP;
+ goto errnotsupp;
}
- break;
+
case NL80211_IFTYPE_AP:
switch (type) {
case NL80211_IFTYPE_ADHOC:
@@ -1217,12 +1265,9 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
return mwifiex_change_vif_to_p2p(dev, curr_iftype,
type, params);
default:
- mwifiex_dbg(priv->adapter, ERROR,
- "%s: changing to %d not supported\n",
- dev->name, type);
- return -EOPNOTSUPP;
+ goto errnotsupp;
}
- break;
+
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
switch (type) {
@@ -1251,21 +1296,21 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
params);
default:
- mwifiex_dbg(priv->adapter, ERROR,
- "%s: changing to %d not supported\n",
- dev->name, type);
- return -EOPNOTSUPP;
+ goto errnotsupp;
}
- break;
+
default:
- mwifiex_dbg(priv->adapter, ERROR,
- "%s: unknown iftype: %d\n",
- dev->name, dev->ieee80211_ptr->iftype);
- return -EOPNOTSUPP;
+ goto errnotsupp;
}
return 0;
+
+errnotsupp:
+ mwifiex_dbg(priv->adapter, ERROR,
+ "unsupported interface type transition: %d to %d\n",
+ curr_iftype, type);
+ return -EOPNOTSUPP;
}
static void
--
2.33.0
From 8db27093a9ee1559e44f29c9fa2b26e6c718776c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Wed, 11 Nov 2020 13:33:04 +0100
Subject: [PATCH] mwifiex: Run SET_BSS_MODE when changing from P2P to STATION
vif-type
We currently handle changing from the P2P to the STATION virtual
interface type slightly different than changing from P2P to ADHOC: When
changing to STATION, we don't send the SET_BSS_MODE command. We do send
that command on all other type-changes though, and it probably makes
sense to send the command since after all we just changed our BSS_MODE.
Looking at prior changes to this part of the code, it seems that this is
simply a leftover from old refactorings.
Since sending the SET_BSS_MODE command is the only difference between
mwifiex_change_vif_to_sta_adhoc() and the current code, we can now use
mwifiex_change_vif_to_sta_adhoc() for both switching to ADHOC and
STATION interface type.
This does not fix any particular bug and just "looked right", so there's
a small chance it might be a regression.
Patchset: mwifiex
---
.../net/wireless/marvell/mwifiex/cfg80211.c | 22 ++++---------------
1 file changed, 4 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index dabc59c47de3..146aabe14753 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -1270,29 +1270,15 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
+ if (mwifiex_cfg80211_deinit_p2p(priv))
+ return -EFAULT;
+
switch (type) {
- case NL80211_IFTYPE_STATION:
- if (mwifiex_cfg80211_deinit_p2p(priv))
- return -EFAULT;
- priv->adapter->curr_iface_comb.p2p_intf--;
- priv->adapter->curr_iface_comb.sta_intf++;
- dev->ieee80211_ptr->iftype = type;
- if (mwifiex_deinit_priv_params(priv))
- return -1;
- if (mwifiex_init_new_priv_params(priv, dev, type))
- return -1;
- if (mwifiex_sta_init_cmd(priv, false, false))
- return -1;
- break;
case NL80211_IFTYPE_ADHOC:
- if (mwifiex_cfg80211_deinit_p2p(priv))
- return -EFAULT;
+ case NL80211_IFTYPE_STATION:
return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
type, params);
- break;
case NL80211_IFTYPE_AP:
- if (mwifiex_cfg80211_deinit_p2p(priv))
- return -EFAULT;
return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
params);
default:
--
2.33.0
From b8a8179135bedf5f9149bf11a7d9d4cfce79c0e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Wed, 11 Nov 2020 14:42:54 +0100
Subject: [PATCH] mwifiex: Use helper function for counting interface types
Use a small helper function to increment and decrement the counter of
the interface types we currently manage. This makes the code that
actually changes and sets up the interface type a bit less messy and
also helps avoiding mistakes in case someone increments/decrements a
counter wrongly.
Patchset: mwifiex
---
.../net/wireless/marvell/mwifiex/cfg80211.c | 110 ++++++------------
1 file changed, 35 insertions(+), 75 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 146aabe14753..8b9517c243c8 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -1009,6 +1009,32 @@ is_vif_type_change_allowed(struct mwifiex_adapter *adapter,
return false;
}
+static void
+update_vif_type_counter(struct mwifiex_adapter *adapter,
+ enum nl80211_iftype iftype,
+ int change)
+{
+ switch (iftype) {
+ case NL80211_IFTYPE_UNSPECIFIED:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_STATION:
+ adapter->curr_iface_comb.sta_intf += change;
+ break;
+ case NL80211_IFTYPE_AP:
+ adapter->curr_iface_comb.uap_intf += change;
+ break;
+ case NL80211_IFTYPE_P2P_CLIENT:
+ case NL80211_IFTYPE_P2P_GO:
+ adapter->curr_iface_comb.p2p_intf += change;
+ break;
+ default:
+ mwifiex_dbg(adapter, ERROR,
+ "%s: Unsupported iftype passed: %d\n",
+ __func__, iftype);
+ break;
+ }
+}
+
static int
mwifiex_change_vif_to_p2p(struct net_device *dev,
enum nl80211_iftype curr_iftype,
@@ -1056,19 +1082,8 @@ mwifiex_change_vif_to_p2p(struct net_device *dev,
if (mwifiex_sta_init_cmd(priv, false, false))
return -1;
- switch (curr_iftype) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- adapter->curr_iface_comb.sta_intf--;
- break;
- case NL80211_IFTYPE_AP:
- adapter->curr_iface_comb.uap_intf--;
- break;
- default:
- break;
- }
-
- adapter->curr_iface_comb.p2p_intf++;
+ update_vif_type_counter(adapter, curr_iftype, -1);
+ update_vif_type_counter(adapter, type, +1);
dev->ieee80211_ptr->iftype = type;
return 0;
@@ -1107,20 +1122,10 @@ mwifiex_change_vif_to_sta_adhoc(struct net_device *dev,
if (mwifiex_sta_init_cmd(priv, false, false))
return -1;
- switch (curr_iftype) {
- case NL80211_IFTYPE_P2P_CLIENT:
- case NL80211_IFTYPE_P2P_GO:
- adapter->curr_iface_comb.p2p_intf--;
- break;
- case NL80211_IFTYPE_AP:
- adapter->curr_iface_comb.uap_intf--;
- break;
- default:
- break;
- }
-
- adapter->curr_iface_comb.sta_intf++;
+ update_vif_type_counter(adapter, curr_iftype, -1);
+ update_vif_type_counter(adapter, type, +1);
dev->ieee80211_ptr->iftype = type;
+
return 0;
}
@@ -1153,20 +1158,8 @@ mwifiex_change_vif_to_ap(struct net_device *dev,
if (mwifiex_sta_init_cmd(priv, false, false))
return -1;
- switch (curr_iftype) {
- case NL80211_IFTYPE_P2P_CLIENT:
- case NL80211_IFTYPE_P2P_GO:
- adapter->curr_iface_comb.p2p_intf--;
- break;
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- adapter->curr_iface_comb.sta_intf--;
- break;
- default:
- break;
- }
-
- adapter->curr_iface_comb.uap_intf++;
+ update_vif_type_counter(adapter, curr_iftype, -1);
+ update_vif_type_counter(adapter, type, +1);
dev->ieee80211_ptr->iftype = type;
return 0;
}
@@ -3128,23 +3121,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
mwifiex_dev_debugfs_init(priv);
#endif
- switch (type) {
- case NL80211_IFTYPE_UNSPECIFIED:
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- adapter->curr_iface_comb.sta_intf++;
- break;
- case NL80211_IFTYPE_AP:
- adapter->curr_iface_comb.uap_intf++;
- break;
- case NL80211_IFTYPE_P2P_CLIENT:
- adapter->curr_iface_comb.p2p_intf++;
- break;
- default:
- /* This should be dead code; checked above */
- mwifiex_dbg(adapter, ERROR, "type not supported\n");
- return ERR_PTR(-EINVAL);
- }
+ update_vif_type_counter(adapter, type, +1);
return &priv->wdev;
@@ -3210,24 +3187,7 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
/* Clear the priv in adapter */
priv->netdev = NULL;
- switch (priv->bss_mode) {
- case NL80211_IFTYPE_UNSPECIFIED:
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_ADHOC:
- adapter->curr_iface_comb.sta_intf--;
- break;
- case NL80211_IFTYPE_AP:
- adapter->curr_iface_comb.uap_intf--;
- break;
- case NL80211_IFTYPE_P2P_CLIENT:
- case NL80211_IFTYPE_P2P_GO:
- adapter->curr_iface_comb.p2p_intf--;
- break;
- default:
- mwifiex_dbg(adapter, ERROR,
- "del_virtual_intf: type not supported\n");
- break;
- }
+ update_vif_type_counter(adapter, priv->bss_mode, -1);
priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
--
2.33.0
From 3f8e5d2d1d7cab48aa5c5f63cf5ddd63dc71ac37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Fri, 26 Mar 2021 15:56:58 +0100
Subject: [PATCH] mwifiex: Update virtual interface counters right after
setting bss_type
In mwifiex_init_new_priv_params() we update our private driver state to
reflect the currently selected virtual interface type. Most notably we
set the bss_mode to the mode we're going to put the firmware in.
Now after we updated the driver state we actually start talking to the
firmware and instruct it to set up the new mode. Those commands can and
will sometimes fail, in which case we return with an error from
mwifiex_change_vif_to_*. We currently update our virtual interface type
counters after this return, which means the code is never reached when a
firmware error happens and we never update the counters. Since we have
updated our bss_mode earlier though, the counters now no longer reflect
the actual state of the driver.
This will break things on the next virtual interface change, because the
virtual interface type we're switching away from didn't get its counter
incremented, and we end up decrementing a 0-counter.
To fix this, simply update the virtual interface type counters right
after updating our driver structures, so that they are always in sync.
Patchset: mwifiex
---
.../net/wireless/marvell/mwifiex/cfg80211.c | 25 +++++++++++--------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 8b9517c243c8..f2797102c5a2 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -1059,6 +1059,10 @@ mwifiex_change_vif_to_p2p(struct net_device *dev,
if (mwifiex_init_new_priv_params(priv, dev, type))
return -1;
+ update_vif_type_counter(adapter, curr_iftype, -1);
+ update_vif_type_counter(adapter, type, +1);
+ dev->ieee80211_ptr->iftype = type;
+
switch (type) {
case NL80211_IFTYPE_P2P_CLIENT:
if (mwifiex_cfg80211_init_p2p_client(priv))
@@ -1082,10 +1086,6 @@ mwifiex_change_vif_to_p2p(struct net_device *dev,
if (mwifiex_sta_init_cmd(priv, false, false))
return -1;
- update_vif_type_counter(adapter, curr_iftype, -1);
- update_vif_type_counter(adapter, type, +1);
- dev->ieee80211_ptr->iftype = type;
-
return 0;
}
@@ -1116,16 +1116,17 @@ mwifiex_change_vif_to_sta_adhoc(struct net_device *dev,
return -1;
if (mwifiex_init_new_priv_params(priv, dev, type))
return -1;
+
+ update_vif_type_counter(adapter, curr_iftype, -1);
+ update_vif_type_counter(adapter, type, +1);
+ dev->ieee80211_ptr->iftype = type;
+
if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
HostCmd_ACT_GEN_SET, 0, NULL, true))
return -1;
if (mwifiex_sta_init_cmd(priv, false, false))
return -1;
- update_vif_type_counter(adapter, curr_iftype, -1);
- update_vif_type_counter(adapter, type, +1);
- dev->ieee80211_ptr->iftype = type;
-
return 0;
}
@@ -1152,15 +1153,17 @@ mwifiex_change_vif_to_ap(struct net_device *dev,
return -1;
if (mwifiex_init_new_priv_params(priv, dev, type))
return -1;
+
+ update_vif_type_counter(adapter, curr_iftype, -1);
+ update_vif_type_counter(adapter, type, +1);
+ dev->ieee80211_ptr->iftype = type;
+
if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
HostCmd_ACT_GEN_SET, 0, NULL, true))
return -1;
if (mwifiex_sta_init_cmd(priv, false, false))
return -1;
- update_vif_type_counter(adapter, curr_iftype, -1);
- update_vif_type_counter(adapter, type, +1);
- dev->ieee80211_ptr->iftype = type;
return 0;
}
/*
--
2.33.0
From fd44539bf3227619c474ccd7669c2ad5406a48e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Wed, 11 Nov 2020 13:42:40 +0100
Subject: [PATCH] mwifiex: Allow switching interface type from P2P_CLIENT to
P2P_GO
It's possible to change virtual interface type between P2P_CLIENT and
P2P_GO, the card supports that just fine, and it happens for example
when using miracast with the miraclecast software.
So allow type changes between P2P_CLIENT and P2P_GO and simply call into
mwifiex_change_vif_to_p2p(), which handles this just fine. We have to
call mwifiex_cfg80211_deinit_p2p() before though to make sure the old
p2p mode is properly uninitialized.
Patchset: mwifiex
---
.../net/wireless/marvell/mwifiex/cfg80211.c | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index f2797102c5a2..ed4041ff9c89 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -990,11 +990,26 @@ is_vif_type_change_allowed(struct mwifiex_adapter *adapter,
}
case NL80211_IFTYPE_P2P_CLIENT:
+ switch (new_iftype) {
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_STATION:
+ return true;
+ case NL80211_IFTYPE_P2P_GO:
+ return true;
+ case NL80211_IFTYPE_AP:
+ return adapter->curr_iface_comb.uap_intf !=
+ adapter->iface_limit.uap_intf;
+ default:
+ return false;
+ }
+
case NL80211_IFTYPE_P2P_GO:
switch (new_iftype) {
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_STATION:
return true;
+ case NL80211_IFTYPE_P2P_CLIENT:
+ return true;
case NL80211_IFTYPE_AP:
return adapter->curr_iface_comb.uap_intf !=
adapter->iface_limit.uap_intf;
@@ -1265,6 +1280,24 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
}
case NL80211_IFTYPE_P2P_CLIENT:
+ if (mwifiex_cfg80211_deinit_p2p(priv))
+ return -EFAULT;
+
+ switch (type) {
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_STATION:
+ return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
+ type, params);
+ case NL80211_IFTYPE_P2P_GO:
+ return mwifiex_change_vif_to_p2p(dev, curr_iftype,
+ type, params);
+ case NL80211_IFTYPE_AP:
+ return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
+ params);
+ default:
+ goto errnotsupp;
+ }
+
case NL80211_IFTYPE_P2P_GO:
if (mwifiex_cfg80211_deinit_p2p(priv))
return -EFAULT;
@@ -1274,6 +1307,9 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
case NL80211_IFTYPE_STATION:
return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
type, params);
+ case NL80211_IFTYPE_P2P_CLIENT:
+ return mwifiex_change_vif_to_p2p(dev, curr_iftype,
+ type, params);
case NL80211_IFTYPE_AP:
return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
params);
--
2.33.0
From 38fa37ffe773e897f383536b560b63f9d6e5d0d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Fri, 26 Mar 2021 15:31:08 +0100
Subject: [PATCH] mwifiex: Handle interface type changes from AP to STATION
Looks like this case was simply overseen, so handle it, too.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/cfg80211.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index ed4041ff9c89..64caa5c4350d 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -1268,6 +1268,7 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
case NL80211_IFTYPE_AP:
switch (type) {
case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_STATION:
return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
type, params);
break;
--
2.33.0
From 64848fc13ca03a4bd7a8c7d7bd90b71d2ebfedab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Fri, 26 Mar 2021 15:32:16 +0100
Subject: [PATCH] mwifiex: Properly initialize private structure on interface
type changes
When creating a new virtual interface in mwifiex_add_virtual_intf(), we
update our internal driver states like bss_type, bss_priority, bss_role
and bss_mode to reflect the mode the firmware will be set to.
When switching virtual interface mode using
mwifiex_init_new_priv_params() though, we currently only update bss_mode
and bss_role. In order for the interface mode switch to actually work,
we also need to update bss_type to its proper value, so do that.
This fixes a crash of the firmware (because the driver tries to execute
commands that are invalid in AP mode) when switching from station mode
to AP mode.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/cfg80211.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 64caa5c4350d..0eb31201a82b 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -908,16 +908,20 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv,
switch (type) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
- priv->bss_role = MWIFIEX_BSS_ROLE_STA;
+ priv->bss_role = MWIFIEX_BSS_ROLE_STA;
+ priv->bss_type = MWIFIEX_BSS_TYPE_STA;
break;
case NL80211_IFTYPE_P2P_CLIENT:
- priv->bss_role = MWIFIEX_BSS_ROLE_STA;
+ priv->bss_role = MWIFIEX_BSS_ROLE_STA;
+ priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
break;
case NL80211_IFTYPE_P2P_GO:
- priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
+ priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
+ priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
break;
case NL80211_IFTYPE_AP:
priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
+ priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
break;
default:
mwifiex_dbg(adapter, ERROR,
--
2.33.0
From ae5eb238986422d88710d1bf75a1969d0985fb7e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Sat, 27 Mar 2021 12:19:14 +0100
Subject: [PATCH] mwifiex: Fix copy-paste mistake when creating virtual
interface
The BSS priority here for a new P2P_CLIENT device was accidentally set
to an enum that's certainly not meant for this. Since
MWIFIEX_BSS_ROLE_STA is 0 anyway, we can just set the bss_priority to 0
instead here.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/cfg80211.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 0eb31201a82b..d62a20de3ada 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -3054,7 +3054,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
- priv->bss_priority = MWIFIEX_BSS_ROLE_STA;
+ priv->bss_priority = 0;
priv->bss_role = MWIFIEX_BSS_ROLE_STA;
priv->bss_started = 0;
--
2.33.0
From 01195d6a6019274b2e5cac35077cff9dd08bf907 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Sun, 28 Mar 2021 21:10:06 +0200
Subject: [PATCH] mwifiex: Try waking the firmware until we get an interrupt
It seems that the firmware of the 88W8897 card sometimes ignores or
misses when we try to wake it up by reading the firmware status
register. This leads to the firmware wakeup timeout expiring and the
driver resetting the card because we assume the firmware has hung up or
crashed (unfortunately that's not unlikely with this card).
Turns out that most of the time the firmware actually didn't hang up,
but simply "missed" our wakeup request and doesn't send us an AWAKE
event.
Trying again to read the firmware status register after a short timeout
usually makes the firmware wake we up as expected, so add a small retry
loop to mwifiex_pm_wakeup_card() that looks at the interrupt status to
check whether the card woke up.
The number of tries and timeout lengths for this were determined
experimentally: The firmware usually takes about 500 us to wake up
after we attempt to read the status register. In some cases where the
firmware is very busy (for example while doing a bluetooth scan) it
might even miss our requests for multiple milliseconds, which is why
after 15 tries the waiting time gets increased to 10 ms. The maximum
number of tries it took to wake the firmware when testing this was
around 20, so a maximum number of 50 tries should give us plenty of
safety margin.
A good reproducer for this issue is letting the firmware sleep and wake
up in very short intervals, for example by pinging an device on the
network every 0.1 seconds.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/pcie.c | 29 ++++++++++++++++-----
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 95e5851d2d0a..ccae1532a580 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -665,6 +665,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+ int n_tries = 0;
mwifiex_dbg(adapter, EVENT,
"event: Wakeup device...\n");
@@ -672,12 +673,28 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
if (reg->sleep_cookie)
mwifiex_pcie_dev_wakeup_delay(adapter);
- /* Accessing fw_status register will wakeup device */
- if (mwifiex_write_reg(adapter, reg->fw_status, FIRMWARE_READY_PCIE)) {
- mwifiex_dbg(adapter, ERROR,
- "Writing fw_status register failed\n");
- return -1;
- }
+ /* Access the fw_status register to wake up the device.
+ * Since the 88W8897 firmware sometimes appears to ignore or miss
+ * that wakeup request, we continue trying until we receive an
+ * interrupt from the card.
+ */
+ do {
+ if (mwifiex_write_reg(adapter, reg->fw_status, FIRMWARE_READY_PCIE)) {
+ mwifiex_dbg(adapter, ERROR,
+ "Writing fw_status register failed\n");
+ return -1;
+ }
+
+ n_tries++;
+
+ if (n_tries <= 15)
+ usleep_range(400, 700);
+ else
+ msleep(10);
+ } while (n_tries <= 50 && READ_ONCE(adapter->int_status) == 0);
+
+ mwifiex_dbg(adapter, EVENT,
+ "event: Tried %d times until firmware woke up\n", n_tries);
if (reg->sleep_cookie) {
mwifiex_pcie_dev_wakeup_delay(adapter);
--
2.33.0
From 2abfccaf8b127ff858950d277d97994d38af800c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Tue, 13 Apr 2021 14:30:28 +0200
Subject: [PATCH] mwifiex: Deactive host sleep using HSCFG after it was
activated manually
When powersaving (so either wifi powersaving or deep sleep, depending on
which state the firmware is in) is disabled, the way the firmware goes
into host sleep is different: Usually the firmware implicitely enters
host sleep on the next SLEEP event we get when we configured host sleep
via HSCFG before. When powersaving is disabled though, there are no
SLEEP events, the way we enter host sleep in that case is different: The
firmware will send us a HS_ACT_REQ event and after that we "manually"
make the firmware enter host sleep by sending it another HSCFG command
with the action HS_ACTIVATE.
Now waking up from host sleep appears to be different depending on
whether powersaving is enabled again: When powersaving is enabled, the
firmware implicitely leaves host sleep as soon as it wakes up and sends
us an AWAKE event. When powersaving is disabled though, it apparently
doesn't implicitely leave host sleep, but instead we need to send it a
HSCFG command with the HS_CONFIGURE action and the HS_CFG_CANCEL
condition. We didn't do that so far, which is why waking up from host
sleep was broken when powersaving is disabled.
So add some additional state to mwifiex_adapter where we keep track of
whether host sleep was activated manually via HS_ACTIVATE, and if that
was the case, deactivate it manually again via HS_CFG_CANCEL.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/cmdevt.c | 21 +++++++++++++++++++
drivers/net/wireless/marvell/mwifiex/main.c | 18 ++++++++++++++++
drivers/net/wireless/marvell/mwifiex/main.h | 1 +
.../net/wireless/marvell/mwifiex/sta_cmd.c | 4 ++++
4 files changed, 44 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 3a11342a6bde..5487df8f994d 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -608,6 +608,11 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
return -1;
}
+ if (priv->adapter->hs_activated_manually &&
+ cmd_no != HostCmd_CMD_802_11_HS_CFG_ENH) {
+ mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD);
+ priv->adapter->hs_activated_manually = false;
+ }
/* Get a new command node */
cmd_node = mwifiex_get_cmd_node(adapter);
@@ -714,6 +719,15 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,
}
}
+ /* Same with exit host sleep cmd, luckily that can't happen at the same time as EXIT_PS */
+ if (command == HostCmd_CMD_802_11_HS_CFG_ENH) {
+ struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg =
+ &host_cmd->params.opt_hs_cfg;
+
+ if (le16_to_cpu(hs_cfg->action) == HS_ACTIVATE)
+ add_tail = false;
+ }
+
spin_lock_bh(&adapter->cmd_pending_q_lock);
if (add_tail)
list_add_tail(&cmd_node->list, &adapter->cmd_pending_q);
@@ -1216,6 +1230,13 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter)
__func__);
adapter->if_ops.wakeup(adapter);
+
+ if (adapter->hs_activated_manually) {
+ mwifiex_cancel_hs(mwifiex_get_priv (adapter, MWIFIEX_BSS_ROLE_ANY),
+ MWIFIEX_ASYNC_CMD);
+ adapter->hs_activated_manually = false;
+ }
+
adapter->hs_activated = false;
clear_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags);
clear_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags);
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 17399d4aa129..1fbf5ba1042b 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -401,6 +401,12 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
!adapter->scan_processing) &&
!adapter->data_sent &&
!skb_queue_empty(&adapter->tx_data_q)) {
+ if (adapter->hs_activated_manually) {
+ mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY),
+ MWIFIEX_ASYNC_CMD);
+ adapter->hs_activated_manually = false;
+ }
+
mwifiex_process_tx_queue(adapter);
if (adapter->hs_activated) {
clear_bit(MWIFIEX_IS_HS_CONFIGURED,
@@ -418,6 +424,12 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
!mwifiex_bypass_txlist_empty(adapter) &&
!mwifiex_is_tdls_chan_switching
(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
+ if (adapter->hs_activated_manually) {
+ mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY),
+ MWIFIEX_ASYNC_CMD);
+ adapter->hs_activated_manually = false;
+ }
+
mwifiex_process_bypass_tx(adapter);
if (adapter->hs_activated) {
clear_bit(MWIFIEX_IS_HS_CONFIGURED,
@@ -434,6 +446,12 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
!adapter->data_sent && !mwifiex_wmm_lists_empty(adapter) &&
!mwifiex_is_tdls_chan_switching
(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
+ if (adapter->hs_activated_manually) {
+ mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY),
+ MWIFIEX_ASYNC_CMD);
+ adapter->hs_activated_manually = false;
+ }
+
mwifiex_wmm_process_tx(adapter);
if (adapter->hs_activated) {
clear_bit(MWIFIEX_IS_HS_CONFIGURED,
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 5923c5c14c8d..90012cbcfd15 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -986,6 +986,7 @@ struct mwifiex_adapter {
struct timer_list wakeup_timer;
struct mwifiex_hs_config_param hs_cfg;
u8 hs_activated;
+ u8 hs_activated_manually;
u16 hs_activate_wait_q_woken;
wait_queue_head_t hs_activate_wait_q;
u8 event_body[MAX_EVENT_SIZE];
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index 48ea00da1fc9..1e2798dce18f 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -396,6 +396,10 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
if (hs_activate) {
hs_cfg->action = cpu_to_le16(HS_ACTIVATE);
hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED);
+
+ adapter->hs_activated_manually = true;
+ mwifiex_dbg(priv->adapter, CMD,
+ "cmd: Activating host sleep manually\n");
} else {
hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
--
2.33.0
From ba9905381f77b5ce4e5a27b7bc32a1315a1ea52c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Tue, 13 Apr 2021 14:23:05 +0200
Subject: [PATCH] mwifiex: Add quirk to disable deep sleep with certain
hardware revision
The 88W8897 pcie card with the hardware revision 20 apparently has a
hardware issue where the card wakes up from deep sleep randomly and very
often, somewhat depending on the card activity, maybe the hardware has a
floating wakeup pin or something.
Those continuous wakeups prevent the card from entering host sleep when
the computer suspends. And because the host won't answer to events from
the card anymore while it's suspended, the firmwares internal
powersaving state machine seems to get confused and the card can't sleep
anymore at all after that.
Since we can't work around that hardware bug in the firmware, let's
get the hardware revision string from the firmware and match it with
known bad revisions. Then disable auto deep sleep for those revisions,
which makes sure we no longer get those spurious wakeups.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/main.c | 14 ++++++++++++++
drivers/net/wireless/marvell/mwifiex/main.h | 1 +
.../net/wireless/marvell/mwifiex/sta_cmdresp.c | 16 ++++++++++++++++
3 files changed, 31 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 1fbf5ba1042b..be40813ffa5c 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -226,6 +226,19 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
return 0;
}
+static void maybe_quirk_fw_disable_ds(struct mwifiex_adapter *adapter)
+{
+ struct mwifiex_private *priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
+ struct mwifiex_ver_ext ver_ext;
+
+ set_bit(MWIFIEX_IS_REQUESTING_FW_VEREXT, &adapter->work_flags);
+
+ memset(&ver_ext, 0, sizeof(ver_ext));
+ ver_ext.version_str_sel = 1;
+ mwifiex_send_cmd(priv, HostCmd_CMD_VERSION_EXT,
+ HostCmd_ACT_GEN_GET, 0, &ver_ext, false);
+}
+
/*
* The main process.
*
@@ -356,6 +369,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
if (adapter->hw_status == MWIFIEX_HW_STATUS_INIT_DONE) {
adapter->hw_status = MWIFIEX_HW_STATUS_READY;
mwifiex_init_fw_complete(adapter);
+ maybe_quirk_fw_disable_ds(adapter);
}
}
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 90012cbcfd15..1e829d84b1f6 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -524,6 +524,7 @@ enum mwifiex_adapter_work_flags {
MWIFIEX_IS_SUSPENDED,
MWIFIEX_IS_HS_CONFIGURED,
MWIFIEX_IS_HS_ENABLING,
+ MWIFIEX_IS_REQUESTING_FW_VEREXT,
};
struct mwifiex_band_config {
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
index 6b5d35d9e69f..8e49ebca1847 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
@@ -708,6 +708,22 @@ static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
{
struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
+ if (test_and_clear_bit(MWIFIEX_IS_REQUESTING_FW_VEREXT, &priv->adapter->work_flags)) {
+ if (strncmp(ver_ext->version_str, "ChipRev:20, BB:9b(10.00), RF:40(21)", 128) == 0) {
+ struct mwifiex_ds_auto_ds auto_ds = {
+ .auto_ds = DEEP_SLEEP_OFF,
+ };
+
+ mwifiex_dbg(priv->adapter, MSG,
+ "Bad HW revision detected, disabling deep sleep\n");
+
+ mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
+ DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds, false);
+ }
+
+ return 0;
+ }
+
if (version_ext) {
version_ext->version_str_sel = ver_ext->version_str_sel;
memcpy(version_ext->version_str, ver_ext->version_str,
--
2.33.0
From b952f6890a6f0e43ecb0241bd08778a48e90aa36 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Wed, 11 Nov 2020 15:17:07 +0100
Subject: [PATCH] mwifiex: Don't log error on suspend if wake-on-wlan is
disabled
It's not an error if someone chooses to put their computer to sleep, not
wanting it to wake up because the person next door has just discovered
what a magic packet is. So change the loglevel of this annoying message
from ERROR to INFO.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/cfg80211.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index d62a20de3ada..18b1a6d54bc8 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -3494,7 +3494,7 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
}
if (!wowlan) {
- mwifiex_dbg(adapter, ERROR,
+ mwifiex_dbg(adapter, INFO,
"None of the WOWLAN triggers enabled\n");
ret = 0;
goto done;
--
2.33.0
From bc16053076d6f5b343da6e8b593a23987e6b3513 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Sun, 28 Mar 2021 21:42:54 +0200
Subject: [PATCH] mwifiex: Log an error on command failure during key-material
upload
Sometimes the KEY_MATERIAL command can fail with the 88W8897 firmware
(when this happens exactly seems pretty random). This appears to prevent
the access point from starting, so it seems like a good idea to log an
error in that case.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/cfg80211.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 18b1a6d54bc8..c00791701d78 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -519,8 +519,14 @@ mwifiex_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
encrypt_key.is_igtk_def_key = true;
eth_broadcast_addr(encrypt_key.mac_addr);
- return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
- HostCmd_ACT_GEN_SET, true, &encrypt_key, true);
+ if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,
+ HostCmd_ACT_GEN_SET, true, &encrypt_key, true)) {
+ mwifiex_dbg(priv->adapter, ERROR,
+ "Sending KEY_MATERIAL command failed\n");
+ return -1;
+ }
+
+ return 0;
}
/*
--
2.33.0
From 947ac6a6a5c0331f405a56e278eecc86ced19413 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Tue, 13 Apr 2021 12:44:03 +0200
Subject: [PATCH] mwifiex: Fix an incorrect comment
We're sending DELBA requests here, not ADDBA requests.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/11n.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c
index 6696bce56178..b0695432b26a 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n.c
@@ -125,7 +125,7 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
tx_ba_tbl->ra);
} else { /*
* In case of failure, recreate the deleted stream in case
- * we initiated the ADDBA
+ * we initiated the DELBA
*/
if (!INITIATOR_BIT(del_ba_param_set))
return 0;
--
2.33.0
From d7b4956649da1da0568297eb66d2d0c2d9b623b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Tue, 13 Apr 2021 12:45:59 +0200
Subject: [PATCH] mwifiex: Send DELBA requests according to spec
We're currently failing to set the initiator bit for DELBA requests:
While we set the bit on our del_ba_param_set bitmask, we forget to
actually copy that bitmask over to the command struct, which means we
never actually set the initiator bit.
Fix that and copy the bitmask over to the host_cmd_ds_11n_delba command
struct.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/11n.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c
index b0695432b26a..9ff2058bcd7e 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n.c
@@ -657,14 +657,15 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
uint16_t del_ba_param_set;
memset(&delba, 0, sizeof(delba));
- delba.del_ba_param_set = cpu_to_le16(tid << DELBA_TID_POS);
- del_ba_param_set = le16_to_cpu(delba.del_ba_param_set);
+ del_ba_param_set = tid << DELBA_TID_POS;
+
if (initiator)
del_ba_param_set |= IEEE80211_DELBA_PARAM_INITIATOR_MASK;
else
del_ba_param_set &= ~IEEE80211_DELBA_PARAM_INITIATOR_MASK;
+ delba.del_ba_param_set = cpu_to_le16(del_ba_param_set);
memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN);
/* We don't wait for the response of this command */
--
2.33.0
From c3212b41c15af15ddd24779de13f939b5d5ac847 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Tue, 13 Apr 2021 12:57:41 +0200
Subject: [PATCH] mwifiex: Ignore BTCOEX events from the firmware
The firmware of the pcie 88W8897 chip sends those events very
unreliably, which means we sometimes end up actually capping the window
size while bluetooth is disabled, artifically limiting wifi speeds even
though it's not needed.
Since we can't fix the firmware, let's just ignore those events, it
seems that the Windows driver also doesn't change the rx/tx block ack
buffer sizes when bluetooth gets enabled or disabled, so this is
consistent with the Windows driver.
Patchset: mwifiex
---
drivers/net/wireless/marvell/mwifiex/sta_event.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
index 68c63268e2e6..933111a3511c 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
@@ -1057,9 +1057,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
adapter->event_skb);
break;
case EVENT_BT_COEX_WLAN_PARA_CHANGE:
- dev_dbg(adapter->dev, "EVENT: BT coex wlan param update\n");
- mwifiex_bt_coex_wlan_param_update_event(priv,
- adapter->event_skb);
+ dev_dbg(adapter->dev, "EVENT: ignoring BT coex wlan param update\n");
break;
case EVENT_RXBA_SYNC:
dev_dbg(adapter->dev, "EVENT: RXBA_SYNC\n");
--
2.33.0