0001
0002
0003
0004 #include <linux/dmi.h>
0005
0006 #include "pcie_quirks.h"
0007
0008
0009 static const struct dmi_system_id mwifiex_quirk_table[] = {
0010 {
0011 .ident = "Surface Pro 4",
0012 .matches = {
0013 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
0014 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 4"),
0015 },
0016 .driver_data = (void *)QUIRK_FW_RST_D3COLD,
0017 },
0018 {
0019 .ident = "Surface Pro 5",
0020 .matches = {
0021
0022 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
0023 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1796"),
0024 },
0025 .driver_data = (void *)QUIRK_FW_RST_D3COLD,
0026 },
0027 {
0028 .ident = "Surface Pro 5 (LTE)",
0029 .matches = {
0030
0031 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
0032 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "Surface_Pro_1807"),
0033 },
0034 .driver_data = (void *)QUIRK_FW_RST_D3COLD,
0035 },
0036 {
0037 .ident = "Surface Pro 6",
0038 .matches = {
0039 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
0040 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 6"),
0041 },
0042 .driver_data = (void *)QUIRK_FW_RST_D3COLD,
0043 },
0044 {
0045 .ident = "Surface Book 1",
0046 .matches = {
0047 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
0048 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book"),
0049 },
0050 .driver_data = (void *)QUIRK_FW_RST_D3COLD,
0051 },
0052 {
0053 .ident = "Surface Book 2",
0054 .matches = {
0055 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
0056 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Book 2"),
0057 },
0058 .driver_data = (void *)QUIRK_FW_RST_D3COLD,
0059 },
0060 {
0061 .ident = "Surface Laptop 1",
0062 .matches = {
0063 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
0064 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop"),
0065 },
0066 .driver_data = (void *)QUIRK_FW_RST_D3COLD,
0067 },
0068 {
0069 .ident = "Surface Laptop 2",
0070 .matches = {
0071 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
0072 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Laptop 2"),
0073 },
0074 .driver_data = (void *)QUIRK_FW_RST_D3COLD,
0075 },
0076 {}
0077 };
0078
0079 void mwifiex_initialize_quirks(struct pcie_service_card *card)
0080 {
0081 struct pci_dev *pdev = card->dev;
0082 const struct dmi_system_id *dmi_id;
0083
0084 dmi_id = dmi_first_match(mwifiex_quirk_table);
0085 if (dmi_id)
0086 card->quirks = (uintptr_t)dmi_id->driver_data;
0087
0088 if (!card->quirks)
0089 dev_info(&pdev->dev, "no quirks enabled\n");
0090 if (card->quirks & QUIRK_FW_RST_D3COLD)
0091 dev_info(&pdev->dev, "quirk reset_d3cold enabled\n");
0092 }
0093
0094 static void mwifiex_pcie_set_power_d3cold(struct pci_dev *pdev)
0095 {
0096 dev_info(&pdev->dev, "putting into D3cold...\n");
0097
0098 pci_save_state(pdev);
0099 if (pci_is_enabled(pdev))
0100 pci_disable_device(pdev);
0101 pci_set_power_state(pdev, PCI_D3cold);
0102 }
0103
0104 static int mwifiex_pcie_set_power_d0(struct pci_dev *pdev)
0105 {
0106 int ret;
0107
0108 dev_info(&pdev->dev, "putting into D0...\n");
0109
0110 pci_set_power_state(pdev, PCI_D0);
0111 ret = pci_enable_device(pdev);
0112 if (ret) {
0113 dev_err(&pdev->dev, "pci_enable_device failed\n");
0114 return ret;
0115 }
0116 pci_restore_state(pdev);
0117
0118 return 0;
0119 }
0120
0121 int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev)
0122 {
0123 struct pci_dev *parent_pdev = pci_upstream_bridge(pdev);
0124 int ret;
0125
0126
0127 dev_info(&pdev->dev, "Using reset_d3cold quirk to perform FW reset\n");
0128
0129
0130
0131
0132
0133
0134
0135
0136 mwifiex_pcie_set_power_d3cold(pdev);
0137 mwifiex_pcie_set_power_d3cold(parent_pdev);
0138
0139 ret = mwifiex_pcie_set_power_d0(parent_pdev);
0140 if (ret)
0141 return ret;
0142 ret = mwifiex_pcie_set_power_d0(pdev);
0143 if (ret)
0144 return ret;
0145
0146 return 0;
0147 }