From 87fc2a45ad81705dc8559e93d608720c963f334c Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Wed, 12 Jul 2017 10:22:44 +0100 Subject: add missing patches from the 4.12 GA commit --- ...cpi-Workaround-conflict-with-PCI-wifi-on-.patch | 143 +++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 0014-mmc-sdhci-acpi-Workaround-conflict-with-PCI-wifi-on-.patch (limited to '0014-mmc-sdhci-acpi-Workaround-conflict-with-PCI-wifi-on-.patch') diff --git a/0014-mmc-sdhci-acpi-Workaround-conflict-with-PCI-wifi-on-.patch b/0014-mmc-sdhci-acpi-Workaround-conflict-with-PCI-wifi-on-.patch new file mode 100644 index 000000000..b5c717c64 --- /dev/null +++ b/0014-mmc-sdhci-acpi-Workaround-conflict-with-PCI-wifi-on-.patch @@ -0,0 +1,143 @@ +From 51eb7454942c68c84b82782e47637de3ba37f113 Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Wed, 21 Jun 2017 15:08:39 +0300 +Subject: [PATCH 14/16] mmc: sdhci-acpi: Workaround conflict with PCI wifi on + GPD Win handheld + +GPDwin uses PCI wifi which conflicts with SDIO's use of +acpi_device_fix_up_power() on child device nodes. Specifically +acpi_device_fix_up_power() causes the wifi module to get turned off. +Identifying GPDwin is problematic, but since SDIO is only used for wifi, +the presence of the PCI wifi card in the expected slot with an ACPI +companion node, is used to indicate that acpi_device_fix_up_power() should +be avoided. + +Signed-off-by: Adrian Hunter +Acked-by: Hans de Goede +Tested-by: Hans de Goede +Cc: stable@vger.kernel.org +--- + drivers/mmc/host/sdhci-acpi.c | 70 +++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 64 insertions(+), 6 deletions(-) + +diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c +index c6a9a1bfaa22..b3fb155f50e4 100644 +--- a/drivers/mmc/host/sdhci-acpi.c ++++ b/drivers/mmc/host/sdhci-acpi.c +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + #endif + + #include "sdhci.h" +@@ -134,6 +135,16 @@ static bool sdhci_acpi_byt(void) + return x86_match_cpu(byt); + } + ++static bool sdhci_acpi_cht(void) ++{ ++ static const struct x86_cpu_id cht[] = { ++ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, ++ {} ++ }; ++ ++ return x86_match_cpu(cht); ++} ++ + #define BYT_IOSF_SCCEP 0x63 + #define BYT_IOSF_OCP_NETCTRL0 0x1078 + #define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8) +@@ -178,6 +189,45 @@ static bool sdhci_acpi_byt_defer(struct device *dev) + return false; + } + ++static bool sdhci_acpi_cht_pci_wifi(unsigned int vendor, unsigned int device, ++ unsigned int slot, unsigned int parent_slot) ++{ ++ struct pci_dev *dev, *parent, *from = NULL; ++ ++ while (1) { ++ dev = pci_get_device(vendor, device, from); ++ pci_dev_put(from); ++ if (!dev) ++ break; ++ parent = pci_upstream_bridge(dev); ++ if (ACPI_COMPANION(&dev->dev) && PCI_SLOT(dev->devfn) == slot && ++ parent && PCI_SLOT(parent->devfn) == parent_slot && ++ !pci_upstream_bridge(parent)) { ++ pci_dev_put(dev); ++ return true; ++ } ++ from = dev; ++ } ++ ++ return false; ++} ++ ++/* ++ * GPDwin uses PCI wifi which conflicts with SDIO's use of ++ * acpi_device_fix_up_power() on child device nodes. Identifying GPDwin is ++ * problematic, but since SDIO is only used for wifi, the presence of the PCI ++ * wifi card in the expected slot with an ACPI companion node, is used to ++ * indicate that acpi_device_fix_up_power() should be avoided. ++ */ ++static inline bool sdhci_acpi_no_fixup_child_power(const char *hid, ++ const char *uid) ++{ ++ return sdhci_acpi_cht() && ++ !strcmp(hid, "80860F14") && ++ !strcmp(uid, "2") && ++ sdhci_acpi_cht_pci_wifi(0x14e4, 0x43ec, 0, 28); ++} ++ + #else + + static inline void sdhci_acpi_byt_setting(struct device *dev) +@@ -189,6 +239,12 @@ static inline bool sdhci_acpi_byt_defer(struct device *dev) + return false; + } + ++static inline bool sdhci_acpi_no_fixup_child_power(const char *hid, ++ const char *uid) ++{ ++ return false; ++} ++ + #endif + + static int bxt_get_cd(struct mmc_host *mmc) +@@ -390,11 +446,16 @@ static int sdhci_acpi_probe(struct platform_device *pdev) + if (acpi_bus_get_device(handle, &device)) + return -ENODEV; + ++ hid = acpi_device_hid(device); ++ uid = device->pnp.unique_id; ++ + /* Power on the SDHCI controller and its children */ + acpi_device_fix_up_power(device); +- list_for_each_entry(child, &device->children, node) +- if (child->status.present && child->status.enabled) +- acpi_device_fix_up_power(child); ++ if (!sdhci_acpi_no_fixup_child_power(hid, uid)) { ++ list_for_each_entry(child, &device->children, node) ++ if (child->status.present && child->status.enabled) ++ acpi_device_fix_up_power(child); ++ } + + if (acpi_bus_get_status(device) || !device->status.present) + return -ENODEV; +@@ -402,9 +463,6 @@ static int sdhci_acpi_probe(struct platform_device *pdev) + if (sdhci_acpi_byt_defer(dev)) + return -EPROBE_DEFER; + +- hid = acpi_device_hid(device); +- uid = device->pnp.unique_id; +- + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!iomem) + return -ENOMEM; +-- +2.13.0 + -- cgit