diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-14 16:10:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-14 16:10:06 -0400 |
commit | 907afe5923b4f89b3c377e8ce3b495124321659c (patch) | |
tree | 52863c208a4a0bb1d19e53c834edaef58da41a2d | |
parent | 0a264b6db702e0e9bdf8b037c61c951f87785bfc (diff) | |
parent | 9c284c41c0886f09e75c323a16278b6d353b0b4a (diff) |
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
-rw-r--r-- | drivers/mmc/core/block.c | 6 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-acpi.c | 70 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc_core.c | 19 |
3 files changed, 78 insertions, 17 deletions
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 0cfac2d39107..8ac59dc80f23 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c | |||
@@ -637,6 +637,9 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev, | |||
637 | sizeof(num_of_cmds))) | 637 | sizeof(num_of_cmds))) |
638 | return -EFAULT; | 638 | return -EFAULT; |
639 | 639 | ||
640 | if (!num_of_cmds) | ||
641 | return 0; | ||
642 | |||
640 | if (num_of_cmds > MMC_IOC_MAX_CMDS) | 643 | if (num_of_cmds > MMC_IOC_MAX_CMDS) |
641 | return -EINVAL; | 644 | return -EINVAL; |
642 | 645 | ||
@@ -1182,7 +1185,7 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req) | |||
1182 | 1185 | ||
1183 | switch (mq_rq->drv_op) { | 1186 | switch (mq_rq->drv_op) { |
1184 | case MMC_DRV_OP_IOCTL: | 1187 | case MMC_DRV_OP_IOCTL: |
1185 | for (i = 0; i < mq_rq->ioc_count; i++) { | 1188 | for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) { |
1186 | ret = __mmc_blk_ioctl_cmd(card, md, mq_rq->idata[i]); | 1189 | ret = __mmc_blk_ioctl_cmd(card, md, mq_rq->idata[i]); |
1187 | if (ret) | 1190 | if (ret) |
1188 | break; | 1191 | break; |
@@ -2167,6 +2170,7 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md) | |||
2167 | * from being accepted. | 2170 | * from being accepted. |
2168 | */ | 2171 | */ |
2169 | card = md->queue.card; | 2172 | card = md->queue.card; |
2173 | blk_set_queue_dying(md->queue.queue); | ||
2170 | mmc_cleanup_queue(&md->queue); | 2174 | mmc_cleanup_queue(&md->queue); |
2171 | if (md->disk->flags & GENHD_FL_UP) { | 2175 | if (md->disk->flags & GENHD_FL_UP) { |
2172 | device_remove_file(disk_to_dev(md->disk), &md->force_ro); | 2176 | device_remove_file(disk_to_dev(md->disk), &md->force_ro); |
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index cf66a3db71b8..ac678e9fb19a 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <asm/cpu_device_id.h> | 45 | #include <asm/cpu_device_id.h> |
46 | #include <asm/intel-family.h> | 46 | #include <asm/intel-family.h> |
47 | #include <asm/iosf_mbi.h> | 47 | #include <asm/iosf_mbi.h> |
48 | #include <linux/pci.h> | ||
48 | #endif | 49 | #endif |
49 | 50 | ||
50 | #include "sdhci.h" | 51 | #include "sdhci.h" |
@@ -134,6 +135,16 @@ static bool sdhci_acpi_byt(void) | |||
134 | return x86_match_cpu(byt); | 135 | return x86_match_cpu(byt); |
135 | } | 136 | } |
136 | 137 | ||
138 | static bool sdhci_acpi_cht(void) | ||
139 | { | ||
140 | static const struct x86_cpu_id cht[] = { | ||
141 | { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, | ||
142 | {} | ||
143 | }; | ||
144 | |||
145 | return x86_match_cpu(cht); | ||
146 | } | ||
147 | |||
137 | #define BYT_IOSF_SCCEP 0x63 | 148 | #define BYT_IOSF_SCCEP 0x63 |
138 | #define BYT_IOSF_OCP_NETCTRL0 0x1078 | 149 | #define BYT_IOSF_OCP_NETCTRL0 0x1078 |
139 | #define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8) | 150 | #define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8) |
@@ -178,6 +189,45 @@ static bool sdhci_acpi_byt_defer(struct device *dev) | |||
178 | return false; | 189 | return false; |
179 | } | 190 | } |
180 | 191 | ||
192 | static bool sdhci_acpi_cht_pci_wifi(unsigned int vendor, unsigned int device, | ||
193 | unsigned int slot, unsigned int parent_slot) | ||
194 | { | ||
195 | struct pci_dev *dev, *parent, *from = NULL; | ||
196 | |||
197 | while (1) { | ||
198 | dev = pci_get_device(vendor, device, from); | ||
199 | pci_dev_put(from); | ||
200 | if (!dev) | ||
201 | break; | ||
202 | parent = pci_upstream_bridge(dev); | ||
203 | if (ACPI_COMPANION(&dev->dev) && PCI_SLOT(dev->devfn) == slot && | ||
204 | parent && PCI_SLOT(parent->devfn) == parent_slot && | ||
205 | !pci_upstream_bridge(parent)) { | ||
206 | pci_dev_put(dev); | ||
207 | return true; | ||
208 | } | ||
209 | from = dev; | ||
210 | } | ||
211 | |||
212 | return false; | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * GPDwin uses PCI wifi which conflicts with SDIO's use of | ||
217 | * acpi_device_fix_up_power() on child device nodes. Identifying GPDwin is | ||
218 | * problematic, but since SDIO is only used for wifi, the presence of the PCI | ||
219 | * wifi card in the expected slot with an ACPI companion node, is used to | ||
220 | * indicate that acpi_device_fix_up_power() should be avoided. | ||
221 | */ | ||
222 | static inline bool sdhci_acpi_no_fixup_child_power(const char *hid, | ||
223 | const char *uid) | ||
224 | { | ||
225 | return sdhci_acpi_cht() && | ||
226 | !strcmp(hid, "80860F14") && | ||
227 | !strcmp(uid, "2") && | ||
228 | sdhci_acpi_cht_pci_wifi(0x14e4, 0x43ec, 0, 28); | ||
229 | } | ||
230 | |||
181 | #else | 231 | #else |
182 | 232 | ||
183 | static inline void sdhci_acpi_byt_setting(struct device *dev) | 233 | static inline void sdhci_acpi_byt_setting(struct device *dev) |
@@ -189,6 +239,12 @@ static inline bool sdhci_acpi_byt_defer(struct device *dev) | |||
189 | return false; | 239 | return false; |
190 | } | 240 | } |
191 | 241 | ||
242 | static inline bool sdhci_acpi_no_fixup_child_power(const char *hid, | ||
243 | const char *uid) | ||
244 | { | ||
245 | return false; | ||
246 | } | ||
247 | |||
192 | #endif | 248 | #endif |
193 | 249 | ||
194 | static int bxt_get_cd(struct mmc_host *mmc) | 250 | static int bxt_get_cd(struct mmc_host *mmc) |
@@ -389,18 +445,20 @@ static int sdhci_acpi_probe(struct platform_device *pdev) | |||
389 | if (acpi_bus_get_device(handle, &device)) | 445 | if (acpi_bus_get_device(handle, &device)) |
390 | return -ENODEV; | 446 | return -ENODEV; |
391 | 447 | ||
448 | hid = acpi_device_hid(device); | ||
449 | uid = device->pnp.unique_id; | ||
450 | |||
392 | /* Power on the SDHCI controller and its children */ | 451 | /* Power on the SDHCI controller and its children */ |
393 | acpi_device_fix_up_power(device); | 452 | acpi_device_fix_up_power(device); |
394 | list_for_each_entry(child, &device->children, node) | 453 | if (!sdhci_acpi_no_fixup_child_power(hid, uid)) { |
395 | if (child->status.present && child->status.enabled) | 454 | list_for_each_entry(child, &device->children, node) |
396 | acpi_device_fix_up_power(child); | 455 | if (child->status.present && child->status.enabled) |
456 | acpi_device_fix_up_power(child); | ||
457 | } | ||
397 | 458 | ||
398 | if (sdhci_acpi_byt_defer(dev)) | 459 | if (sdhci_acpi_byt_defer(dev)) |
399 | return -EPROBE_DEFER; | 460 | return -EPROBE_DEFER; |
400 | 461 | ||
401 | hid = acpi_device_hid(device); | ||
402 | uid = device->pnp.unique_id; | ||
403 | |||
404 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 462 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
405 | if (!iomem) | 463 | if (!iomem) |
406 | return -ENOMEM; | 464 | return -ENOMEM; |
diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 82b80d42f7ae..88a94355ac90 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c | |||
@@ -409,30 +409,29 @@ static void tmio_mmc_transfer_data(struct tmio_mmc_host *host, | |||
409 | * Transfer the data | 409 | * Transfer the data |
410 | */ | 410 | */ |
411 | if (host->pdata->flags & TMIO_MMC_32BIT_DATA_PORT) { | 411 | if (host->pdata->flags & TMIO_MMC_32BIT_DATA_PORT) { |
412 | u8 data[4] = { }; | 412 | u32 data = 0; |
413 | u32 *buf32 = (u32 *)buf; | ||
413 | 414 | ||
414 | if (is_read) | 415 | if (is_read) |
415 | sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, (u32 *)buf, | 416 | sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, buf32, |
416 | count >> 2); | 417 | count >> 2); |
417 | else | 418 | else |
418 | sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, (u32 *)buf, | 419 | sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, buf32, |
419 | count >> 2); | 420 | count >> 2); |
420 | 421 | ||
421 | /* if count was multiple of 4 */ | 422 | /* if count was multiple of 4 */ |
422 | if (!(count & 0x3)) | 423 | if (!(count & 0x3)) |
423 | return; | 424 | return; |
424 | 425 | ||
425 | buf8 = (u8 *)(buf + (count >> 2)); | 426 | buf32 += count >> 2; |
426 | count %= 4; | 427 | count %= 4; |
427 | 428 | ||
428 | if (is_read) { | 429 | if (is_read) { |
429 | sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, | 430 | sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, &data, 1); |
430 | (u32 *)data, 1); | 431 | memcpy(buf32, &data, count); |
431 | memcpy(buf8, data, count); | ||
432 | } else { | 432 | } else { |
433 | memcpy(data, buf8, count); | 433 | memcpy(&data, buf32, count); |
434 | sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, | 434 | sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, &data, 1); |
435 | (u32 *)data, 1); | ||
436 | } | 435 | } |
437 | 436 | ||
438 | return; | 437 | return; |