This commit adds quirk implementation based on DMI matching with DMI
table for Microsoft Surface devices that uses mwifiex chip (currently,
all the devices that use mwifiex equip PCIe-88W8897 chip).

This implementation can be used for quirks later.

Signed-off-by: Tsuchiya Yuto <kita...@gmail.com>
---
 drivers/net/wireless/marvell/mwifiex/Makefile |   1 +
 drivers/net/wireless/marvell/mwifiex/pcie.c   |   4 +
 drivers/net/wireless/marvell/mwifiex/pcie.h   |   2 +
 .../wireless/marvell/mwifiex/pcie_quirks.c    | 114 ++++++++++++++++++
 .../wireless/marvell/mwifiex/pcie_quirks.h    |  11 ++
 5 files changed, 132 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 fdfd9bf15ed46..8a1e7c5b9c6e2 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 6a10ff0377a24..362cf10debfa0 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 843d57eda8201..09839a3bd1753 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
@@ -242,6 +242,8 @@ struct pcie_service_card {
        struct mwifiex_msix_context share_irq_ctx;
        struct work_struct work;
        unsigned long work_flags;
+
+       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 0000000000000..929aee2b0a60a
--- /dev/null
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.c
@@ -0,0 +1,114 @@
+// 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/dmi.h>
+
+#include "pcie_quirks.h"
+
+/* 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 = 0,
+       },
+       {
+               .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 = 0,
+       },
+       {
+               .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 = 0,
+       },
+       {
+               .ident = "Surface Pro 6",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft 
Corporation"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 6"),
+               },
+               .driver_data = 0,
+       },
+       {
+               .ident = "Surface Book 1",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft 
Corporation"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book"),
+               },
+               .driver_data = 0,
+       },
+       {
+               .ident = "Surface Book 2",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft 
Corporation"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book 2"),
+               },
+               .driver_data = 0,
+       },
+       {
+               .ident = "Surface Laptop 1",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft 
Corporation"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop"),
+               },
+               .driver_data = 0,
+       },
+       {
+               .ident = "Surface Laptop 2",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft 
Corporation"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop 2"),
+               },
+               .driver_data = 0,
+       },
+       {
+               .ident = "Surface 3",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft 
Corporation"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface 3"),
+               },
+               .driver_data = 0,
+       },
+       {
+               .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");
+}
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 0000000000000..5326ae7e56713
--- /dev/null
+++ b/drivers/net/wireless/marvell/mwifiex/pcie_quirks.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for PCIe quirks.
+ */
+
+#include "pcie.h"
+
+/* quirks */
+// quirk flags can be added here
+
+void mwifiex_initialize_quirks(struct pcie_service_card *card);
-- 
2.29.1

Reply via email to