Update v4.19 patches

Changes:
 - SAM:
   - Fix bug in packet submission leading to a potential deadlock when
     packets need to be resent in constested situations
   - Misc. other fixes.
   - Rename surface_aggregator_debugfs module to surface_aggregator_cdev
     and make it a proper character device (miscdevice).
   - Add copyright notices.
   - Continued cleanup and code improvements.
   - Change core from late to standard initialization
   - Add sysfs attribute for SAM firmware version
   - Register SAN consumers dynamically
   - Misc. fixes and cleanup

 - mwifiex:
   - Revert auto_ds force-disablement
   - Add enable_device_dump module parameter
   - Try to improve suspend behavior

Links:
- SAM: 47bb8f0824
- kernel: f9183418ae
This commit is contained in:
Maximilian Luz 2020-10-01 17:54:09 +02:00
parent 629849060e
commit cda77f53f5
No known key found for this signature in database
GPG key ID: 70EC0937F6C26F02
12 changed files with 1522 additions and 893 deletions

View file

@ -11,7 +11,7 @@ CONFIG_GPIO_SYSFS=y # required for SURFACE_HOTPLUG
CONFIG_SURFACE_AGGREGATOR=m
CONFIG_SURFACE_AGGREGATOR_ERROR_INJECTION=n
CONFIG_SURFACE_AGGREGATOR_BUS=y
CONFIG_SURFACE_AGGREGATOR_DEBUGFS=m
CONFIG_SURFACE_AGGREGATOR_CDEV=m
CONFIG_SURFACE_AGGREGATOR_REGISTRY=m
CONFIG_SURFACE_ACPI_NOTIFY=m
CONFIG_SURFACE_BATTERY=m

View file

@ -1,4 +1,4 @@
From 77a51c2de712616a7d15544b9f5cc391e9b8e25c Mon Sep 17 00:00:00 2001
From 4e90ff5333233ee75c7eaec1a5e9c8800f0d837d Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 28 Sep 2019 18:00:43 +0200
Subject: [PATCH 01/10] surface3-power

View file

@ -1,4 +1,4 @@
From e1d0615633bb751f4b5fee62790b8dace6061177 Mon Sep 17 00:00:00 2001
From a01d95125b34cf6945e9562543a6c377bf20467d Mon Sep 17 00:00:00 2001
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date: Sun, 5 Jul 2020 14:56:20 +0300
Subject: [PATCH 02/10] surface3-touchscreen-dma-fix

View file

@ -1,4 +1,4 @@
From 086d4ac825d05e3cd9ce5a1fc961058272c32ff1 Mon Sep 17 00:00:00 2001
From d5b6b26107bded3fe3b245f268885871dc81f0be Mon Sep 17 00:00:00 2001
From: Chih-Wei Huang <cwhuang@linux.org.tw>
Date: Tue, 18 Sep 2018 11:01:37 +0800
Subject: [PATCH 03/10] surface3-oemb

View file

@ -1,4 +1,4 @@
From 2fe0cc32b80f3989e956f4d7b18e7735f144cd6d Mon Sep 17 00:00:00 2001
From 81abff2f2f5fe52b0ff3a31851584ba624e7ee0c Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 27 Jul 2019 17:51:37 +0200
Subject: [PATCH 04/10] surface-buttons

View file

@ -1,4 +1,4 @@
From 62b2bc9997d187d9fc51e8faa766360ee27ef4fa Mon Sep 17 00:00:00 2001
From b420c60ae36c19a367834badda4a6a4a3c2b876d Mon Sep 17 00:00:00 2001
From: kitakar5525 <34676735+kitakar5525@users.noreply.github.com>
Date: Sat, 28 Sep 2019 17:48:21 +0200
Subject: [PATCH 05/10] suspend
@ -12,10 +12,10 @@ Subject: [PATCH 05/10] suspend
5 files changed, 162 insertions(+), 6 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 0d60f2f8f3ee..6dcd37c10153 100644
index 33dad9774da0..742b84a6f344 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1068,15 +1068,15 @@ static struct nvme_id_ns *nvme_identify_ns(struct nvme_ctrl *ctrl,
@@ -1065,15 +1065,15 @@ static struct nvme_id_ns *nvme_identify_ns(struct nvme_ctrl *ctrl,
return id;
}
@ -34,7 +34,7 @@ index 0d60f2f8f3ee..6dcd37c10153 100644
c.features.fid = cpu_to_le32(fid);
c.features.dword11 = cpu_to_le32(dword11);
@@ -1087,6 +1087,24 @@ static int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword
@@ -1084,6 +1084,24 @@ static int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword
return ret;
}
@ -59,7 +59,7 @@ index 0d60f2f8f3ee..6dcd37c10153 100644
int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count)
{
u32 q_count = (*count - 1) | ((*count - 1) << 16);
@@ -3613,6 +3631,18 @@ static void nvme_free_ctrl(struct device *dev)
@@ -3615,6 +3633,18 @@ static void nvme_free_ctrl(struct device *dev)
nvme_put_subsystem(subsys);
}
@ -79,10 +79,10 @@ index 0d60f2f8f3ee..6dcd37c10153 100644
* Initialize a NVMe controller structures. This needs to be called during
* earliest initialization so that we have the initialized structured around
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index cc4273f11989..40192b661798 100644
index 9c2e7a151e40..8cf74e854610 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -436,6 +436,7 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
@@ -437,6 +437,7 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
void nvme_stop_queues(struct nvme_ctrl *ctrl);
void nvme_start_queues(struct nvme_ctrl *ctrl);
void nvme_kill_queues(struct nvme_ctrl *ctrl);
@ -90,7 +90,7 @@ index cc4273f11989..40192b661798 100644
void nvme_unfreeze(struct nvme_ctrl *ctrl);
void nvme_wait_freeze(struct nvme_ctrl *ctrl);
void nvme_wait_freeze_timeout(struct nvme_ctrl *ctrl, long timeout);
@@ -453,6 +454,12 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
@@ -454,6 +455,12 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
union nvme_result *result, void *buffer, unsigned bufflen,
unsigned timeout, int qid, int at_head,
blk_mq_req_flags_t flags);
@ -297,10 +297,10 @@ index 279f9f0197b0..cb474338f39d 100644
static ssize_t link_state_show(struct device *dev,
struct device_attribute *attr,
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 2517492dd185..d96343cd5c99 100644
index 2fda9893962d..ec6c48ecd7d5 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1489,8 +1489,10 @@ extern bool pcie_ports_native;
@@ -1488,8 +1488,10 @@ extern bool pcie_ports_native;
#ifdef CONFIG_PCIEASPM
bool pcie_aspm_support_enabled(void);

View file

@ -1,4 +1,4 @@
From ca6e2a2cdca89d1ce2cdf42d8b3f94e9b4820576 Mon Sep 17 00:00:00 2001
From 20a6793e87c224e0bc2d594ed5b6ecaba482deab Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 28 Sep 2019 17:58:17 +0200
Subject: [PATCH 06/10] ipts

View file

@ -1,16 +1,33 @@
From 97f5aaa63227eb08d994efa4bb3b618f1a6455fc Mon Sep 17 00:00:00 2001
From 88d4bd00fbd0d90bd746f89658f5a6930b69758e Mon Sep 17 00:00:00 2001
From: kitakar5525 <34676735+kitakar5525@users.noreply.github.com>
Date: Thu, 20 Feb 2020 16:51:11 +0900
Subject: [PATCH 07/10] wifi
---
.../net/wireless/marvell/mwifiex/cfg80211.c | 26 ++++++
drivers/net/wireless/marvell/mwifiex/fw.h | 2 +-
drivers/net/wireless/marvell/mwifiex/pcie.c | 86 +++++++++++--------
.../net/wireless/marvell/mwifiex/sta_cmd.c | 31 ++-----
.../wireless/marvell/mwifiex/sta_cmdresp.c | 4 +-
5 files changed, 86 insertions(+), 63 deletions(-)
drivers/net/wireless/marvell/mwifiex/Makefile | 1 +
.../net/wireless/marvell/mwifiex/cfg80211.c | 26 ++
drivers/net/wireless/marvell/mwifiex/main.c | 6 +-
drivers/net/wireless/marvell/mwifiex/pcie.c | 92 +++++--
drivers/net/wireless/marvell/mwifiex/pcie.h | 3 +
.../wireless/marvell/mwifiex/pcie_quirks.c | 255 ++++++++++++++++++
.../wireless/marvell/mwifiex/pcie_quirks.h | 17 ++
.../net/wireless/marvell/mwifiex/sta_cmd.c | 14 +-
8 files changed, 376 insertions(+), 38 deletions(-)
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 fdfd9bf15ed4..8a1e7c5b9c6e 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/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 650191db25cb..dd487fc9c1a1 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@ -55,143 +72,143 @@ index 650191db25cb..dd487fc9c1a1 100644
return mwifiex_drv_set_power(priv, &ps_mode);
}
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 1fb76d2f5d3f..8b9d0809daf6 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -953,7 +953,7 @@ struct mwifiex_tkip_param {
struct mwifiex_aes_param {
u8 pn[WPA_PN_SIZE];
__le16 key_len;
- u8 key[WLAN_KEY_LEN_CCMP];
+ u8 key[WLAN_KEY_LEN_CCMP_256];
} __packed;
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index e48b47f42554..55b71e3d0127 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1458,7 +1458,7 @@ static void mwifiex_uninit_sw(struct mwifiex_adapter *adapter)
}
struct mwifiex_wapi_param {
/*
- * This function gets called during PCIe function level reset.
+ * This function can be used for shutting down the adapter SW.
*/
int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
{
@@ -1474,6 +1474,8 @@ int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
mwifiex_deauthenticate(priv, NULL);
+ mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
+
mwifiex_uninit_sw(adapter);
if (adapter->if_ops.down_dev)
@@ -1483,7 +1485,7 @@ int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter)
}
EXPORT_SYMBOL_GPL(mwifiex_shutdown_sw);
-/* This function gets called during PCIe function level reset. Required
+/* This function can be used for reinitting the adapter SW. Required
* code is extracted from mwifiex_add_card()
*/
int
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 991b9cc18000..2464f536192c 100644
index 991b9cc18000..30cd52c2485f 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -146,40 +146,45 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
@@ -27,12 +27,18 @@
#include "wmm.h"
#include "11n.h"
#include "pcie.h"
+#include "pcie_quirks.h"
#define PCIE_VERSION "1.0"
#define DRV_NAME "Marvell mwifiex PCIe"
static struct mwifiex_if_ops pcie_ops;
+static bool enable_device_dump;
+module_param(enable_device_dump, bool, 0644);
+MODULE_PARM_DESC(enable_device_dump,
+ "enable device_dump (default: disabled)");
+
static const struct of_device_id mwifiex_pcie_of_match_table[] = {
{ .compatible = "pci11ab,2b42" },
{ .compatible = "pci1b4b,2b42" },
@@ -144,19 +150,13 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
* registered functions must have drivers with suspend and resume
* methods. Failing that the kernel simply removes the whole card.
*
* If already not suspended, this function allocates and sends a host
* sleep activate request to the firmware and turns off the traffic.
+ *
+ * XXX: ignoring all the above comment and just removes the card to
+ * fix S0ix and "AP scanning (sometimes) not working after suspend".
+ * Required code is extracted from mwifiex_pcie_remove().
- * If already not suspended, this function allocates and sends a host
- * sleep activate request to the firmware and turns off the traffic.
+ * This function shuts down the adapter.
*/
static int mwifiex_pcie_suspend(struct device *dev)
{
- struct mwifiex_adapter *adapter;
struct mwifiex_adapter *adapter;
- struct pcie_service_card *card;
struct pci_dev *pdev = to_pci_dev(dev);
-
- card = pci_get_drvdata(pdev);
+ struct pcie_service_card *card = pci_get_drvdata(pdev);
+ struct mwifiex_adapter *adapter;
+ struct mwifiex_private *priv;
+ const struct mwifiex_pcie_card_reg *reg;
+ u32 fw_status;
+ int ret;
- struct pci_dev *pdev = to_pci_dev(dev);
+ struct pcie_service_card *card = dev_get_drvdata(dev);
/* Might still be loading firmware */
wait_for_completion(&card->fw_done);
- card = pci_get_drvdata(pdev);
-
- /* Might still be loading firmware */
- wait_for_completion(&card->fw_done);
adapter = card->adapter;
- if (!adapter) {
- dev_err(dev, "adapter is not valid\n");
+ if (!adapter || !adapter->priv_num)
if (!adapter) {
@@ -164,22 +164,15 @@ static int mwifiex_pcie_suspend(struct device *dev)
return 0;
- }
}
- mwifiex_enable_wake(adapter);
+ reg = card->pcie.reg;
+ if (reg)
+ ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
+ else
+ fw_status = -1;
-
- /* Enable the Host Sleep */
- if (!mwifiex_enable_hs(adapter)) {
- mwifiex_dbg(adapter, ERROR,
- "cmd: failed to suspend\n");
+ /* Shut down SW */
+ if (mwifiex_shutdown_sw(adapter)) {
mwifiex_dbg(adapter, ERROR,
"cmd: failed to suspend\n");
- clear_bit(MWIFIEX_IS_HS_ENABLING, &adapter->work_flags);
- mwifiex_disable_wake(adapter);
- return -EFAULT;
- }
+ if (fw_status == FIRMWARE_READY_PCIE && !adapter->mfg_mode) {
+ mwifiex_deauthenticate_all(adapter);
return -EFAULT;
}
- flush_workqueue(adapter->workqueue);
+ priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
- /* Indicate device suspended */
- set_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags);
-
/* Indicate device suspended */
set_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags);
- clear_bit(MWIFIEX_IS_HS_ENABLING, &adapter->work_flags);
+ mwifiex_disable_auto_ds(priv);
+
+ mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
+ }
+
+ mwifiex_remove_card(adapter);
return 0;
}
@@ -191,33 +196,35 @@ static int mwifiex_pcie_suspend(struct device *dev)
@@ -189,16 +182,14 @@ static int mwifiex_pcie_suspend(struct device *dev)
* registered functions must have drivers with suspend and resume
* methods. Failing that the kernel simply removes the whole card.
*
* If already not resumed, this function turns on the traffic and
* sends a host sleep cancel request to the firmware.
+ *
+ * XXX: ignoring all the above comment and probes the card that was
+ * removed on suspend. Required code is extracted from mwifiex_pcie_probe().
- * If already not resumed, this function turns on the traffic and
- * sends a host sleep cancel request to the firmware.
+ * If already not resumed, this function reinits the adapter.
*/
static int mwifiex_pcie_resume(struct device *dev)
{
- struct mwifiex_adapter *adapter;
struct mwifiex_adapter *adapter;
- struct pcie_service_card *card;
struct pci_dev *pdev = to_pci_dev(dev);
+ struct pcie_service_card *card = pci_get_drvdata(pdev);
- struct pci_dev *pdev = to_pci_dev(dev);
+ struct pcie_service_card *card = dev_get_drvdata(dev);
+ int ret;
- card = pci_get_drvdata(pdev);
+ pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
+ pdev->vendor, pdev->device, pdev->revision);
- if (!card->adapter) {
- dev_err(dev, "adapter structure is not valid\n");
- return 0;
- }
+ init_completion(&card->fw_done);
if (!card->adapter) {
dev_err(dev, "adapter structure is not valid\n");
@@ -215,9 +206,11 @@ static int mwifiex_pcie_resume(struct device *dev)
- adapter = card->adapter;
+ card->dev = pdev;
clear_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags);
- if (!test_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags)) {
- mwifiex_dbg(adapter, WARN,
- "Device already resumed\n");
- return 0;
+ /* device tree node parsing and platform specific configuration */
+ if (pdev->dev.of_node) {
+ ret = mwifiex_pcie_probe_of(&pdev->dev);
+ if (ret)
+ return ret;
}
- clear_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags);
-
- mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
- MWIFIEX_ASYNC_CMD);
- mwifiex_disable_wake(adapter);
+ if (mwifiex_add_card(card, &card->fw_done, &pcie_ops,
+ MWIFIEX_PCIE, &pdev->dev)) {
+ pr_err("%s failed\n", __func__);
+ return -1;
+ }
+ ret = mwifiex_reinit_sw(adapter);
+ if (ret)
+ dev_err(dev, "reinit failed: %d\n", ret);
+ else
+ mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
return 0;
}
@@ -233,8 +240,13 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
@@ -233,8 +226,13 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct pcie_service_card *card;
@ -205,27 +222,396 @@ index 991b9cc18000..2464f536192c 100644
pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
pdev->vendor, pdev->device, pdev->revision);
@@ -265,6 +263,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__);
@@ -380,7 +381,16 @@ 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);
+
+ /* For Surface gen4+ devices, we need to put wifi into D3cold right
+ * before performing FLR
+ */
+ 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;
}
/*
@@ -409,6 +419,8 @@ static void mwifiex_pcie_reset_done(struct pci_dev *pdev)
dev_err(&pdev->dev, "reinit failed: %d\n", ret);
else
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
+
+ card->pci_reset_ongoing = false;
}
static const struct pci_error_handlers mwifiex_pcie_err_handler = {
@@ -2789,6 +2801,12 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
{
+ if (!enable_device_dump) {
+ mwifiex_dbg(adapter, MSG,
+ "device_dump is disabled by module parameter\n");
+ return;
+ }
+
adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
if (!adapter->devdump_data) {
mwifiex_dbg(adapter, ERROR,
@@ -2806,6 +2824,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.
*/
@@ -3000,7 +3028,19 @@ static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter)
int ret;
u32 fw_status;
- cancel_work_sync(&card->work);
+ /* Perform the cancel_work_sync() only when we're not resetting
+ * the card. It's because that function never returns if we're
+ * in reset path. If we're here when resetting the card, it means
+ * that we failed to reset the card (reset failure path).
+ */
+ if (!card->pci_reset_ongoing) {
+ mwifiex_dbg(adapter, MSG, "performing cancel_work_sync()...\n");
+ cancel_work_sync(&card->work);
+ mwifiex_dbg(adapter, MSG, "cancel_work_sync() done\n");
+ } else {
+ mwifiex_dbg(adapter, MSG,
+ "skipped cancel_work_sync() because we're in card reset failure path\n");
+ }
ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
if (fw_status == FIRMWARE_READY_PCIE) {
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h
index f7ce9b6db6b4..f7e968306a0c 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
@@ -391,6 +391,9 @@ struct pcie_service_card {
struct mwifiex_msix_context share_irq_ctx;
struct work_struct work;
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..34dcd84f02a6
--- /dev/null
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
@@ -0,0 +1,255 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * File for PCIe quirks.
+ */
+
+/* The low-level PCI operations will be performed in this file. Therefore,
+ * let's use dev_*() instead of mwifiex_dbg() here to avoid troubles (e.g.
+ * to avoid using mwifiex_adapter struct before init or wifi is powered
+ * down, or causes NULL ptr deref).
+ */
+
+#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[] = {
+ {
+ .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,
+ },
+ {
+ .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,
+ },
+ {
+ .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,
+ },
+ {
+ .ident = "Surface Pro 3",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 3"),
+ },
+ .driver_data = 0,
+ },
+ {}
+};
+
+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");
+ 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)
+{
+ 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;
+}
+
+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
new file mode 100644
index 000000000000..3ef7440418e3
--- /dev/null
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for PCIe quirks.
+ */
+
+#include "pcie.h"
+
+/* quirks */
+#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);
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index 4ed10cf82f9a..410bef3d6a6e 100644
index 4ed10cf82f9a..bd735eb04981 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -2254,7 +2254,6 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
* - Function init (for first interface only)
* - Read MAC address (for first interface only)
* - Reconfigure Tx buffer size (for first interface only)
- * - Enable auto deep sleep (for first interface only)
* - Get Tx rate
* - Get Tx power
* - Set IBSS coalescing status
@@ -2267,7 +2266,6 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
struct mwifiex_adapter *adapter = priv->adapter;
int ret;
struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
- struct mwifiex_ds_auto_ds auto_ds;
enum state_11d_t state_11d;
struct mwifiex_ds_11n_tx_cfg tx_cfg;
u8 sdio_sp_rx_aggr_enable;
@@ -2339,16 +2337,10 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
@@ -2339,16 +2339,10 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
if (ret)
return -1;
@ -246,50 +632,6 @@ index 4ed10cf82f9a..410bef3d6a6e 100644
if (drcs) {
adapter->drcs_enabled = true;
@@ -2395,17 +2387,10 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
if (ret)
return -1;
- if (!disable_auto_ds && first_sta &&
- priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
- /* Enable auto deep sleep */
- auto_ds.auto_ds = DEEP_SLEEP_ON;
- auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME;
- ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH,
- EN_AUTO_PS, BITMAP_AUTO_DS,
- &auto_ds, true);
- if (ret)
- return -1;
- }
+ /* Not enabling auto deep sleep (auto_ds) by default. Enabling
+ * this reportedly causes "suspend/resume fails when not connected
+ * to an Access Point." Therefore, the relevant code was removed
+ * from here. */
if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
/* Send cmd to FW to enable/disable 11D function */
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
index 797c2e978394..7003767eef42 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
@@ -620,7 +620,7 @@ static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
key_v2 = &resp->params.key_material_v2;
len = le16_to_cpu(key_v2->key_param_set.key_params.aes.key_len);
- if (len > WLAN_KEY_LEN_CCMP)
+ if (len > sizeof(key_v2->key_param_set.key_params.aes.key))
return -EINVAL;
if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) {
@@ -636,7 +636,7 @@ static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
return 0;
memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0,
- WLAN_KEY_LEN_CCMP);
+ sizeof(key_v2->key_param_set.key_params.aes.key));
priv->aes_key_v2.key_param_set.key_params.aes.key_len =
cpu_to_le16(len);
memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key,
--
2.28.0

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
From 95aa3f10f7d013f94e54adb3ed9e33c7f7c6af7e Mon Sep 17 00:00:00 2001
From 2520c5a968888ed72838d339157eee1dae13e91f Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 25 Jul 2020 17:19:53 +0200
Subject: [PATCH 09/10] surface-sam-over-hid

View file

@ -1,4 +1,4 @@
From 28e5139674f970b7288ce1619631afd0194f8051 Mon Sep 17 00:00:00 2001
From 1de7ef5a41806dfe6cae0a31e842b8a32faceff1 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sun, 16 Aug 2020 23:39:56 +0200
Subject: [PATCH 10/10] surface-gpe

View file

@ -40,17 +40,17 @@ sha256sums=('355a0ce67229f96b142e1ea2ecf593c3d355a40b34d10144d7e05f37a63f814a'
'SKIP'
'4e68572e7cc4c5368f0236e0792660ae8498373988625dca46e509399a7eaea6'
'a13581d3c6dc595206e4fe7fcf6b542e7a1bdbe96101f0f010fc5be49f99baf2'
'38b30ff73eeb4f09089d4321fa537f9c2a7c41d6b807b80d1ae6a413bf0e50ef'
'155db81a4cbc461447fbe7dd1747b9be1b390f51624c4d791f451ac7ccf4cfce'
'30e915ec17474098b3c585de7d607bae5f0b50d2b21fcf84c66ed5fbd216433c'
'e4987d684854a7a254ae206de52f4fa070ecbecdd77fb273c42b28196280ae30'
'e3320867c62cfc9ff5bc7941f815c9e64a283bf20d3d67957d34a9654c63035a'
'f57711a13160591f32998806c720db2b07d2423d38400db4d0e11bc47ad61d61'
'b503f3a88f9dfdf6da509f26c6dc40bb3ee44bfa021bda2c3f69b9b02948e5aa'
'0f5bd61aeb2e821a28f4ad20975960f11bb6875ecc36572200776513b92fb390'
'30be3aa77bfb48cf19cb1251f7c500a4165f3a778d3b6017ba4ea9dc9c36e83e'
'657a4a0a98cf283e8497ea885af0bdd4df71ef427e1064ae03d014c3c5aa7dfe'
'f7d33c2ebf0618a8976bcd92bfd8b43203076931c8aa5cd83c4cc52135ba3e83')
'e34d7cd57431f26d6da83f7b71f66116c81089fd3d5fc149d1020be54bb6ec72'
'9d9737408ba4437a694e9c96adb7f6a2b8cc9157d9d0a99c41617d026bd036c1'
'1340f431df42611eab3b55dffd0fa63dfd96ca003424f0f7cd810e32a0763ed2'
'b42a349dc39366364ecd28d331bbe5f13fca9bd4259884a7a7e91d3bb5315c35'
'ba04721fd68b09548ab4373a80b413e9a187d19d5b14ce18c4816ab0b1066e8a'
'e6819b1e84ad115b2d05a45467e4d152ae6b64a4ebb5f5cbc441d9380683312a'
'2e5f424560e16e44f2f7fbf1b94bb565f09e09663ac9d471fff511134f5e9d8f'
'c189ade326b6db542dce82c3c9d78abe4812fd6acec3855b52545378ba555ae8'
'a24801e21f43e2ccda3aa034b9df2febde5f9a722969c5adc8f4a16fecbd83d5'
'9d82329a029bedb9b95722d648d009cac657ddfa5fd2b3fb86255fc4459551fe'
'352e8328e71d3068dc47b089a3d6fd94f20e4362337bef537a3987e02dbfdfe4')
export KBUILD_BUILD_HOST=archlinux
export KBUILD_BUILD_USER=$pkgbase