From c6303c5d52d5ec3e5bce2e6a5480fa2a1baa45e6 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 25 Jul 2019 11:14:22 +0800 Subject: mmc: sdhci-sprd: Fix the incorrect soft reset operation when runtime resuming The SD host controller specification defines 3 types software reset: software reset for data line, software reset for command line and software reset for all. Software reset for all means this reset affects the entire Host controller except for the card detection circuit. In sdhci_runtime_resume_host() we always do a software "reset for all", which causes the Spreadtrum variant controller to work abnormally after resuming. To fix the problem, let's do a software reset for the data and the command part, rather than "for all". However, as sdhci_runtime_resume() is a common sdhci function and we don't want to change the behaviour for other variants, let's introduce a new in-parameter for it. This enables the caller to decide if a "reset for all" shall be done or not. Signed-off-by: Baolin Wang Fixes: fb8bd90f83c4 ("mmc: sdhci-sprd: Add Spreadtrum's initial host controller") Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-acpi.c | 2 +- drivers/mmc/host/sdhci-esdhc-imx.c | 2 +- drivers/mmc/host/sdhci-of-at91.c | 2 +- drivers/mmc/host/sdhci-pci-core.c | 4 ++-- drivers/mmc/host/sdhci-pxav3.c | 2 +- drivers/mmc/host/sdhci-s3c.c | 2 +- drivers/mmc/host/sdhci-sprd.c | 2 +- drivers/mmc/host/sdhci-xenon.c | 2 +- drivers/mmc/host/sdhci.c | 4 ++-- drivers/mmc/host/sdhci.h | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index b3a130a9ee23..1604f512c7bd 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -883,7 +883,7 @@ static int sdhci_acpi_runtime_resume(struct device *dev) sdhci_acpi_byt_setting(&c->pdev->dev); - return sdhci_runtime_resume_host(c->host); + return sdhci_runtime_resume_host(c->host, 0); } #endif diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index c391510e9ef4..776a94216248 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1705,7 +1705,7 @@ static int sdhci_esdhc_runtime_resume(struct device *dev) esdhc_pltfm_set_clock(host, imx_data->actual_clock); } - err = sdhci_runtime_resume_host(host); + err = sdhci_runtime_resume_host(host, 0); if (err) goto disable_ipg_clk; diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c index e377b9bc55a4..d4e7e8b7be77 100644 --- a/drivers/mmc/host/sdhci-of-at91.c +++ b/drivers/mmc/host/sdhci-of-at91.c @@ -289,7 +289,7 @@ static int sdhci_at91_runtime_resume(struct device *dev) } out: - return sdhci_runtime_resume_host(host); + return sdhci_runtime_resume_host(host, 0); } #endif /* CONFIG_PM */ diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 4041878eb0f3..7d06e2860c36 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -167,7 +167,7 @@ static int sdhci_pci_runtime_suspend_host(struct sdhci_pci_chip *chip) err_pci_runtime_suspend: while (--i >= 0) - sdhci_runtime_resume_host(chip->slots[i]->host); + sdhci_runtime_resume_host(chip->slots[i]->host, 0); return ret; } @@ -181,7 +181,7 @@ static int sdhci_pci_runtime_resume_host(struct sdhci_pci_chip *chip) if (!slot) continue; - ret = sdhci_runtime_resume_host(slot->host); + ret = sdhci_runtime_resume_host(slot->host, 0); if (ret) return ret; } diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 3ddecf479295..e55037ceda73 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -554,7 +554,7 @@ static int sdhci_pxav3_runtime_resume(struct device *dev) if (!IS_ERR(pxa->clk_core)) clk_prepare_enable(pxa->clk_core); - return sdhci_runtime_resume_host(host); + return sdhci_runtime_resume_host(host, 0); } #endif diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 8e4a8ba33f05..f5753aef7151 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -745,7 +745,7 @@ static int sdhci_s3c_runtime_resume(struct device *dev) clk_prepare_enable(busclk); if (ourhost->cur_clk >= 0) clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]); - ret = sdhci_runtime_resume_host(host); + ret = sdhci_runtime_resume_host(host, 0); return ret; } #endif diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 603a5d9f045a..83a4767ca680 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -696,7 +696,7 @@ static int sdhci_sprd_runtime_resume(struct device *dev) if (ret) goto clk_disable; - sdhci_runtime_resume_host(host); + sdhci_runtime_resume_host(host, 1); return 0; clk_disable: diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index 8a18f14cf842..1dea1ba66f7b 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c @@ -638,7 +638,7 @@ static int xenon_runtime_resume(struct device *dev) priv->restore_needed = false; } - ret = sdhci_runtime_resume_host(host); + ret = sdhci_runtime_resume_host(host, 0); if (ret) goto out; return 0; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 59acf8e3331e..a5dc5aae973e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -3320,7 +3320,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) } EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host); -int sdhci_runtime_resume_host(struct sdhci_host *host) +int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset) { struct mmc_host *mmc = host->mmc; unsigned long flags; @@ -3331,7 +3331,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) host->ops->enable_dma(host); } - sdhci_init(host, 0); + sdhci_init(host, soft_reset); if (mmc->ios.power_mode != MMC_POWER_UNDEFINED && mmc->ios.power_mode != MMC_POWER_OFF) { diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 89fd96596a1f..902f855efe8f 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -781,7 +781,7 @@ void sdhci_adma_write_desc(struct sdhci_host *host, void **desc, int sdhci_suspend_host(struct sdhci_host *host); int sdhci_resume_host(struct sdhci_host *host); int sdhci_runtime_suspend_host(struct sdhci_host *host); -int sdhci_runtime_resume_host(struct sdhci_host *host); +int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset); #endif void sdhci_cqe_enable(struct mmc_host *mmc); -- cgit v1.2.3 From fa25eba6993b3750f417baabba169afaba076178 Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Fri, 26 Jul 2019 10:30:48 +0800 Subject: mmc: cavium: Set the correct dma max segment size for mmc_host We have set the mmc_host.max_seg_size to 8M, but the dma max segment size of PCI device is set to 64K by default in function pci_device_add(). The mmc_host.max_seg_size is used to set the max segment size of the blk queue. Then this mismatch will trigger a calltrace like below when a bigger than 64K segment request arrives at mmc dev. So we should consider the limitation of the cvm_mmc_host when setting the mmc_host.max_seg_size. DMA-API: thunderx_mmc 0000:01:01.4: mapping sg segment longer than device claims to support [len=131072] [max=65536] WARNING: CPU: 6 PID: 238 at kernel/dma/debug.c:1221 debug_dma_map_sg+0x2b8/0x350 Modules linked in: CPU: 6 PID: 238 Comm: kworker/6:1H Not tainted 5.3.0-rc1-next-20190724-yocto-standard+ #62 Hardware name: Marvell OcteonTX CN96XX board (DT) Workqueue: kblockd blk_mq_run_work_fn pstate: 80c00009 (Nzcv daif +PAN +UAO) pc : debug_dma_map_sg+0x2b8/0x350 lr : debug_dma_map_sg+0x2b8/0x350 sp : ffff00001770f9e0 x29: ffff00001770f9e0 x28: ffffffff00000000 x27: 00000000ffffffff x26: ffff800bc2c73180 x25: ffff000010e83700 x24: 0000000000000002 x23: 0000000000000001 x22: 0000000000000001 x21: 0000000000000000 x20: ffff800bc48ba0b0 x19: ffff800bc97e8c00 x18: ffffffffffffffff x17: 0000000000000000 x16: 0000000000000000 x15: ffff000010e835c8 x14: 6874207265676e6f x13: 6c20746e656d6765 x12: 7320677320676e69 x11: 7070616d203a342e x10: 31303a31303a3030 x9 : 303020636d6d5f78 x8 : 35363d78616d5b20 x7 : 00000000000002fd x6 : ffff000010fd57dc x5 : 0000000000000000 x4 : ffff0000106c61f0 x3 : 00000000ffffffff x2 : 0000800bee060000 x1 : 7010678df3041a00 x0 : 0000000000000000 Call trace: debug_dma_map_sg+0x2b8/0x350 cvm_mmc_request+0x3c4/0x988 __mmc_start_request+0x9c/0x1f8 mmc_start_request+0x7c/0xb0 mmc_blk_mq_issue_rq+0x5c4/0x7b8 mmc_mq_queue_rq+0x11c/0x278 blk_mq_dispatch_rq_list+0xb0/0x568 blk_mq_do_dispatch_sched+0x6c/0x108 blk_mq_sched_dispatch_requests+0x110/0x1b8 __blk_mq_run_hw_queue+0xb0/0x118 blk_mq_run_work_fn+0x28/0x38 process_one_work+0x210/0x490 worker_thread+0x48/0x458 kthread+0x130/0x138 ret_from_fork+0x10/0x1c Signed-off-by: Kevin Hao Fixes: ba3869ff32e4 ("mmc: cavium: Add core MMC driver for Cavium SOCs") Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/cavium.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c index ed5cefb83768..c956813bc6bd 100644 --- a/drivers/mmc/host/cavium.c +++ b/drivers/mmc/host/cavium.c @@ -1046,7 +1046,8 @@ int cvm_mmc_of_slot_probe(struct device *dev, struct cvm_mmc_host *host) mmc->max_segs = 1; /* DMA size field can address up to 8 MB */ - mmc->max_seg_size = 8 * 1024 * 1024; + mmc->max_seg_size = min_t(unsigned int, 8 * 1024 * 1024, + dma_get_max_seg_size(host->dev)); mmc->max_req_size = mmc->max_seg_size; /* External DMA is in 512 byte blocks */ mmc->max_blk_size = 512; -- cgit v1.2.3 From b803974a86039913d5280add083d730b2b9ed8ec Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Fri, 26 Jul 2019 10:30:49 +0800 Subject: mmc: cavium: Add the missing dma unmap when the dma has finished. This fixes the below calltrace when the CONFIG_DMA_API_DEBUG is enabled. DMA-API: thunderx_mmc 0000:01:01.4: cpu touching an active dma mapped cacheline [cln=0x000000002fdf9800] WARNING: CPU: 21 PID: 1 at kernel/dma/debug.c:596 debug_dma_assert_idle+0x1f8/0x270 Modules linked in: CPU: 21 PID: 1 Comm: init Not tainted 5.3.0-rc1-next-20190725-yocto-standard+ #64 Hardware name: Marvell OcteonTX CN96XX board (DT) pstate: 80400009 (Nzcv daif +PAN -UAO) pc : debug_dma_assert_idle+0x1f8/0x270 lr : debug_dma_assert_idle+0x1f8/0x270 sp : ffff0000113cfc10 x29: ffff0000113cfc10 x28: 0000ffff8c880000 x27: ffff800bc72a0000 x26: ffff000010ff8000 x25: ffff000010ff8940 x24: ffff000010ff8968 x23: 0000000000000000 x22: ffff000010e83700 x21: ffff000010ea2000 x20: ffff000010e835c8 x19: ffff800bc2c73300 x18: ffffffffffffffff x17: 0000000000000000 x16: 0000000000000000 x15: ffff000010e835c8 x14: 6d20616d64206576 x13: 69746361206e6120 x12: 676e696863756f74 x11: 20757063203a342e x10: 31303a31303a3030 x9 : 303020636d6d5f78 x8 : 3230303030303030 x7 : 00000000000002fd x6 : ffff000010fd57d0 x5 : 0000000000000000 x4 : ffff0000106c5210 x3 : 00000000ffffffff x2 : 0000800bee9c0000 x1 : 57d5843f4aa62800 x0 : 0000000000000000 Call trace: debug_dma_assert_idle+0x1f8/0x270 wp_page_copy+0xb0/0x688 do_wp_page+0xa8/0x5b8 __handle_mm_fault+0x600/0xd00 handle_mm_fault+0x118/0x1e8 do_page_fault+0x200/0x500 do_mem_abort+0x50/0xb0 el0_da+0x20/0x24 ---[ end trace a005534bd23e109f ]--- DMA-API: Mapped at: debug_dma_map_sg+0x94/0x350 cvm_mmc_request+0x3c4/0x988 __mmc_start_request+0x9c/0x1f8 mmc_start_request+0x7c/0xb0 mmc_blk_mq_issue_rq+0x5c4/0x7b8 Signed-off-by: Kevin Hao Fixes: ba3869ff32e4 ("mmc: cavium: Add core MMC driver for Cavium SOCs") Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/cavium.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c index c956813bc6bd..89deb451e0ac 100644 --- a/drivers/mmc/host/cavium.c +++ b/drivers/mmc/host/cavium.c @@ -374,6 +374,7 @@ static int finish_dma_single(struct cvm_mmc_host *host, struct mmc_data *data) { data->bytes_xfered = data->blocks * data->blksz; data->error = 0; + dma_unmap_sg(host->dev, data->sg, data->sg_len, get_dma_dir(data)); return 1; } -- cgit v1.2.3