]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge tag 'mmc-v4.13-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 14 Jul 2017 20:10:06 +0000 (13:10 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 14 Jul 2017 20:10:06 +0000 (13:10 -0700)
Pull MMC fixes from Ulf Hansson:
 "Here are a couple of mmc fixes intended for v4.13 rc1.

  MMC core:
   - Restore some behaviour of MMC_IOC_MULTI_CMD commands
   - Fix using un-initialized variable in mmc_blk_issue_drv_op()
   - Fix mmc block queue cleanup

  MMC host:
   - sdhci-acpi: Workaround conflict with PCI wifi on GPD Win handheld
   - tmio-mmc: Fix bad pointer math"

* tag 'mmc-v4.13-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: tmio-mmc: fix bad pointer math
  mmc: block: Prevent new req entering queue after its cleanup
  mmc: block: Let MMC_IOC_MULTI_CMD return zero again for zero entries
  mmc: block: Initialize ret in mmc_blk_issue_drv_op() for MMC_DRV_OP_IOCTL
  mmc: sdhci-acpi: Workaround conflict with PCI wifi on GPD Win handheld

drivers/mmc/core/block.c
drivers/mmc/host/sdhci-acpi.c
drivers/mmc/host/tmio_mmc_core.c

index 0cfac2d3910739228b18cca0ed5f4f11fa51608b..8ac59dc80f23e51b8449c884611396376000e5a4 100644 (file)
@@ -637,6 +637,9 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
                           sizeof(num_of_cmds)))
                return -EFAULT;
 
+       if (!num_of_cmds)
+               return 0;
+
        if (num_of_cmds > MMC_IOC_MAX_CMDS)
                return -EINVAL;
 
@@ -1182,7 +1185,7 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
 
        switch (mq_rq->drv_op) {
        case MMC_DRV_OP_IOCTL:
-               for (i = 0; i < mq_rq->ioc_count; i++) {
+               for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) {
                        ret = __mmc_blk_ioctl_cmd(card, md, mq_rq->idata[i]);
                        if (ret)
                                break;
@@ -2167,6 +2170,7 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
                 * from being accepted.
                 */
                card = md->queue.card;
+               blk_set_queue_dying(md->queue.queue);
                mmc_cleanup_queue(&md->queue);
                if (md->disk->flags & GENHD_FL_UP) {
                        device_remove_file(disk_to_dev(md->disk), &md->force_ro);
index cf66a3db71b815f934bf295d54c24e15aec9e19c..ac678e9fb19abb67c8094919c98ad36a34579127 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/cpu_device_id.h>
 #include <asm/intel-family.h>
 #include <asm/iosf_mbi.h>
+#include <linux/pci.h>
 #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)
@@ -389,18 +445,20 @@ 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 (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;
index 82b80d42f7ae92cc9bc48d74262af2ad0eb3f90a..88a94355ac90166c09286537151ce1b004ddb4d6 100644 (file)
@@ -409,30 +409,29 @@ static void tmio_mmc_transfer_data(struct tmio_mmc_host *host,
         * Transfer the data
         */
        if (host->pdata->flags & TMIO_MMC_32BIT_DATA_PORT) {
-               u8 data[4] = { };
+               u32 data = 0;
+               u32 *buf32 = (u32 *)buf;
 
                if (is_read)
-                       sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, (u32 *)buf,
+                       sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, buf32,
                                           count >> 2);
                else
-                       sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, (u32 *)buf,
+                       sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, buf32,
                                            count >> 2);
 
                /* if count was multiple of 4 */
                if (!(count & 0x3))
                        return;
 
-               buf8 = (u8 *)(buf + (count >> 2));
+               buf32 += count >> 2;
                count %= 4;
 
                if (is_read) {
-                       sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT,
-                                          (u32 *)data, 1);
-                       memcpy(buf8, data, count);
+                       sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, &data, 1);
+                       memcpy(buf32, &data, count);
                } else {
-                       memcpy(data, buf8, count);
-                       sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT,
-                                           (u32 *)data, 1);
+                       memcpy(&data, buf32, count);
+                       sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, &data, 1);
                }
 
                return;