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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJZaJNDAAoJEP4mhCVzWIwppB4P/26FpKILyBp+HiVBW4FdBHLQ VYOdJ/S3jiqWWtDCLj3HUb+I/D1E4C2+mPOdKGx63+igwHu6IO+j9ZprGKRbLtf4 cB8BmMkHoqww0WzxVkXnrUwdkgMBwpR60UYggM51HPrtwMT9o7juppuG7/RHUPdM 0p2+eTxTGpVgcKsM+FtISxYzFBC94B4oAAx6hFfWZpHyEdZl+ntRQmveHpA1sCkF KvbEPDOaL5UZcXBUKNK9bvyAK3HlwVKq9kF26VSa8sYrd9u/Gt5YmI4fnjzSbjpf OjZNMoMxND6daKZiR8obbiAMlKnzMUZyFHyllRG7mMRiWaGOP3/ScHnwbebpVv0O Xst9ZjSZir8VLiNCu0M/rxJ2wE3g/QM1J0JngduEoX85NzbIRWTXNNVwPoDk994a ex86kqScF4Z9jUH4Iew0RJImlza60RVfLASm7XOBdODyoHwu1zTi2ZAL4a1YKdXx ROjOldZDlqn0oNTiv/JGJ4rBfJGPKNQByyvH5QpGmMRM8yYx6X7srdjGYC+vJ6j3 nPg/k1xYXwxvdZU88Pxvt8uRMSIFEHL6SMdS+KQDPOTRcWgs/yJO3GmrVysUUvup MQ+glvkEF22pPGtOU9uNua2jNgD3CxbCDu7Spp/W+Q+DSuJ7jXZHm1vaqtjB79X7 qfb1kYe1GlxHDROts0s+ =zgfL -----END PGP SIGNATURE----- Merge tag 'mmc-v4.13-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc 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
This commit is contained in:
commit
907afe5923
3 changed files with 78 additions and 17 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue