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
|
@ -637,6 +637,9 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
|
||||||
sizeof(num_of_cmds)))
|
sizeof(num_of_cmds)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
if (!num_of_cmds)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (num_of_cmds > MMC_IOC_MAX_CMDS)
|
if (num_of_cmds > MMC_IOC_MAX_CMDS)
|
||||||
return -EINVAL;
|
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) {
|
switch (mq_rq->drv_op) {
|
||||||
case MMC_DRV_OP_IOCTL:
|
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]);
|
ret = __mmc_blk_ioctl_cmd(card, md, mq_rq->idata[i]);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
|
@ -2167,6 +2170,7 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
|
||||||
* from being accepted.
|
* from being accepted.
|
||||||
*/
|
*/
|
||||||
card = md->queue.card;
|
card = md->queue.card;
|
||||||
|
blk_set_queue_dying(md->queue.queue);
|
||||||
mmc_cleanup_queue(&md->queue);
|
mmc_cleanup_queue(&md->queue);
|
||||||
if (md->disk->flags & GENHD_FL_UP) {
|
if (md->disk->flags & GENHD_FL_UP) {
|
||||||
device_remove_file(disk_to_dev(md->disk), &md->force_ro);
|
device_remove_file(disk_to_dev(md->disk), &md->force_ro);
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include <asm/cpu_device_id.h>
|
#include <asm/cpu_device_id.h>
|
||||||
#include <asm/intel-family.h>
|
#include <asm/intel-family.h>
|
||||||
#include <asm/iosf_mbi.h>
|
#include <asm/iosf_mbi.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "sdhci.h"
|
#include "sdhci.h"
|
||||||
|
@ -134,6 +135,16 @@ static bool sdhci_acpi_byt(void)
|
||||||
return x86_match_cpu(byt);
|
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_SCCEP 0x63
|
||||||
#define BYT_IOSF_OCP_NETCTRL0 0x1078
|
#define BYT_IOSF_OCP_NETCTRL0 0x1078
|
||||||
#define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8)
|
#define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8)
|
||||||
|
@ -178,6 +189,45 @@ static bool sdhci_acpi_byt_defer(struct device *dev)
|
||||||
return false;
|
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
|
#else
|
||||||
|
|
||||||
static inline void sdhci_acpi_byt_setting(struct device *dev)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool sdhci_acpi_no_fixup_child_power(const char *hid,
|
||||||
|
const char *uid)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int bxt_get_cd(struct mmc_host *mmc)
|
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))
|
if (acpi_bus_get_device(handle, &device))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
hid = acpi_device_hid(device);
|
||||||
|
uid = device->pnp.unique_id;
|
||||||
|
|
||||||
/* Power on the SDHCI controller and its children */
|
/* Power on the SDHCI controller and its children */
|
||||||
acpi_device_fix_up_power(device);
|
acpi_device_fix_up_power(device);
|
||||||
|
if (!sdhci_acpi_no_fixup_child_power(hid, uid)) {
|
||||||
list_for_each_entry(child, &device->children, node)
|
list_for_each_entry(child, &device->children, node)
|
||||||
if (child->status.present && child->status.enabled)
|
if (child->status.present && child->status.enabled)
|
||||||
acpi_device_fix_up_power(child);
|
acpi_device_fix_up_power(child);
|
||||||
|
}
|
||||||
|
|
||||||
if (sdhci_acpi_byt_defer(dev))
|
if (sdhci_acpi_byt_defer(dev))
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
|
|
||||||
hid = acpi_device_hid(device);
|
|
||||||
uid = device->pnp.unique_id;
|
|
||||||
|
|
||||||
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (!iomem)
|
if (!iomem)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -409,30 +409,29 @@ static void tmio_mmc_transfer_data(struct tmio_mmc_host *host,
|
||||||
* Transfer the data
|
* Transfer the data
|
||||||
*/
|
*/
|
||||||
if (host->pdata->flags & TMIO_MMC_32BIT_DATA_PORT) {
|
if (host->pdata->flags & TMIO_MMC_32BIT_DATA_PORT) {
|
||||||
u8 data[4] = { };
|
u32 data = 0;
|
||||||
|
u32 *buf32 = (u32 *)buf;
|
||||||
|
|
||||||
if (is_read)
|
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);
|
count >> 2);
|
||||||
else
|
else
|
||||||
sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, (u32 *)buf,
|
sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, buf32,
|
||||||
count >> 2);
|
count >> 2);
|
||||||
|
|
||||||
/* if count was multiple of 4 */
|
/* if count was multiple of 4 */
|
||||||
if (!(count & 0x3))
|
if (!(count & 0x3))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
buf8 = (u8 *)(buf + (count >> 2));
|
buf32 += count >> 2;
|
||||||
count %= 4;
|
count %= 4;
|
||||||
|
|
||||||
if (is_read) {
|
if (is_read) {
|
||||||
sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT,
|
sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, &data, 1);
|
||||||
(u32 *)data, 1);
|
memcpy(buf32, &data, count);
|
||||||
memcpy(buf8, data, count);
|
|
||||||
} else {
|
} else {
|
||||||
memcpy(data, buf8, count);
|
memcpy(&data, buf32, count);
|
||||||
sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT,
|
sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, &data, 1);
|
||||||
(u32 *)data, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue