From 78869618a886d33d8cdfcb78cf9b245b5250e465 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Mon, 11 Jul 2011 13:27:11 +0800 Subject: [PATCH 01/17] mmc: sdhci: fix retuning timer wrongly deleted in sdhci_tasklet_finish Currently, the retuning timer for retuning mode 1 will be deleted in function sdhci_tasklet_finish after a mmc request done, which will make retuning timing never trigger again. This patch fixed this problem. Signed-off-by: Aaron Lu Reviewed-by: Philip Rakity Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index c31a3343340d..262985a1a952 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1867,9 +1867,6 @@ static void sdhci_tasklet_finish(unsigned long param) del_timer(&host->timer); - if (host->version >= SDHCI_SPEC_300) - del_timer(&host->tuning_timer); - mrq = host->mrq; /* From 606a15e475880157dd2336f2dc220eacc9eaf36b Mon Sep 17 00:00:00 2001 From: Philip Rakity Date: Mon, 11 Jul 2011 14:47:54 -0700 Subject: [PATCH 02/17] mmc: sdhci: pxav3: controller needs 32 bit ADMA addressing Enable the quirk. (Best used in conjunction with patch downgrading ADMA to SDMA when transfer is not aligned.) Signed-off-by: Philip Rakity Acked-by: Zhangfei Gao Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-pxav3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 4198dbbc5c20..fc7e4a515629 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -195,7 +195,8 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) clk_enable(clk); host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL - | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; + | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC + | SDHCI_QUIRK_32BIT_ADMA_SIZE; /* enable 1/8V DDR capable */ host->mmc->caps |= MMC_CAP_1_8V_DDR; From 7199e2b61d715c5e8901ff32513d2b80db8d3737 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Tue, 12 Jul 2011 17:30:47 +0900 Subject: [PATCH 03/17] mmc: sdhci-s3c: add BROKEN_ADMA_ZEROLEN_DESC quirk Samsung SoCs need to set BROKEN_ADMA_ZEROLEN_DESC. (If ADMA operation is more than 65535, maybe set by zero.) Signed-off-by: Jaehoon Chung Signed-off-by: Kyungmin Park Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-s3c.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 460ffaf0f6d7..03da44a1b2ab 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -502,6 +502,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) /* This host supports the Auto CMD12 */ host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; + /* Samsung SoCs need BROKEN_ADMA_ZEROLEN_DESC */ + host->quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC; + if (pdata->cd_type == S3C_SDHCI_CD_NONE || pdata->cd_type == S3C_SDHCI_CD_PERMANENT) host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; From d5a5bd1c3f7e8d010393530d60df8da75218a488 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 22 Jul 2011 16:13:36 +0300 Subject: [PATCH 04/17] mmc: mmc_test: avoid stalled file in debugfs During card removal and inserting cycle the test file in the debugfs could be stalled until the host driver removes it. Let's keep the file in the linked list and destroy it when card is removed. Signed-off-by: Andy Shevchenko Acked-by: Per Forlin Signed-off-by: Chris Ball --- drivers/mmc/card/mmc_test.c | 56 ++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 006a5e9f8ab8..742dc98a034c 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -2900,7 +2900,7 @@ static const struct file_operations mmc_test_fops_testlist = { .release = single_release, }; -static void mmc_test_free_file_test(struct mmc_card *card) +static void mmc_test_free_dbgfs_file(struct mmc_card *card) { struct mmc_test_dbgfs_file *df, *dfs; @@ -2917,34 +2917,21 @@ static void mmc_test_free_file_test(struct mmc_card *card) mutex_unlock(&mmc_test_lock); } -static int mmc_test_register_file_test(struct mmc_card *card) +static int __mmc_test_register_dbgfs_file(struct mmc_card *card, + const char *name, mode_t mode, const struct file_operations *fops) { struct dentry *file = NULL; struct mmc_test_dbgfs_file *df; - int ret = 0; - - mutex_lock(&mmc_test_lock); if (card->debugfs_root) - file = debugfs_create_file("test", S_IWUSR | S_IRUGO, - card->debugfs_root, card, &mmc_test_fops_test); + file = debugfs_create_file(name, mode, card->debugfs_root, + card, fops); if (IS_ERR_OR_NULL(file)) { dev_err(&card->dev, - "Can't create test. Perhaps debugfs is disabled.\n"); - ret = -ENODEV; - goto err; - } - - if (card->debugfs_root) - file = debugfs_create_file("testlist", S_IRUGO, - card->debugfs_root, card, &mmc_test_fops_testlist); - - if (IS_ERR_OR_NULL(file)) { - dev_err(&card->dev, - "Can't create testlist. Perhaps debugfs is disabled.\n"); - ret = -ENODEV; - goto err; + "Can't create %s. Perhaps debugfs is disabled.\n", + name); + return -ENODEV; } df = kmalloc(sizeof(struct mmc_test_dbgfs_file), GFP_KERNEL); @@ -2952,14 +2939,31 @@ static int mmc_test_register_file_test(struct mmc_card *card) debugfs_remove(file); dev_err(&card->dev, "Can't allocate memory for internal usage.\n"); - ret = -ENOMEM; - goto err; + return -ENOMEM; } df->card = card; df->file = file; list_add(&df->link, &mmc_test_file_test); + return 0; +} + +static int mmc_test_register_dbgfs_file(struct mmc_card *card) +{ + int ret; + + mutex_lock(&mmc_test_lock); + + ret = __mmc_test_register_dbgfs_file(card, "test", S_IWUSR | S_IRUGO, + &mmc_test_fops_test); + if (ret) + goto err; + + ret = __mmc_test_register_dbgfs_file(card, "testlist", S_IRUGO, + &mmc_test_fops_testlist); + if (ret) + goto err; err: mutex_unlock(&mmc_test_lock); @@ -2974,7 +2978,7 @@ static int mmc_test_probe(struct mmc_card *card) if (!mmc_card_mmc(card) && !mmc_card_sd(card)) return -ENODEV; - ret = mmc_test_register_file_test(card); + ret = mmc_test_register_dbgfs_file(card); if (ret) return ret; @@ -2986,7 +2990,7 @@ static int mmc_test_probe(struct mmc_card *card) static void mmc_test_remove(struct mmc_card *card) { mmc_test_free_result(card); - mmc_test_free_file_test(card); + mmc_test_free_dbgfs_file(card); } static struct mmc_driver mmc_driver = { @@ -3006,7 +3010,7 @@ static void __exit mmc_test_exit(void) { /* Clear stalled data if card is still plugged */ mmc_test_free_result(NULL); - mmc_test_free_file_test(NULL); + mmc_test_free_dbgfs_file(NULL); mmc_unregister_driver(&mmc_driver); } From 38ca285044be88a0fb47b6eb91deeeb729435fd0 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Tue, 26 Jul 2011 17:12:37 +0900 Subject: [PATCH 05/17] mmc: core: Detect eMMC v4.5 ext_csd entries The eMMC v4.5 Spec is released now: EXT_CSD_REV Extended CSD Revision 255-7 Reserved 6 Revision 1.6 (for MMC v4.5) 5 Revision 1.5 (for MMV v4.41) ... Signed-off-by: Kyungmin Park Signed-off-by: Chris Ball --- drivers/mmc/core/mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index aa7d1d79b8c5..5700b1cbdfec 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -259,7 +259,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) } card->ext_csd.rev = ext_csd[EXT_CSD_REV]; - if (card->ext_csd.rev > 5) { + if (card->ext_csd.rev > 6) { printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n", mmc_hostname(card->host), card->ext_csd.rev); err = -EINVAL; From 1ccd4b7bfdcfcc8cc7ffc4a9c11d3ac5b6da8ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Date: Thu, 28 Jul 2011 20:55:27 +0200 Subject: [PATCH 06/17] mmc: cb710: fix possible pci_dev leak in cb710_pci_configure() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Julia Lawall Signed-off-by: Michał Mirosław Signed-off-by: Chris Ball --- drivers/misc/cb710/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c index efec4139c3f6..68cd05b6d829 100644 --- a/drivers/misc/cb710/core.c +++ b/drivers/misc/cb710/core.c @@ -33,7 +33,7 @@ EXPORT_SYMBOL_GPL(cb710_pci_update_config_reg); static int __devinit cb710_pci_configure(struct pci_dev *pdev) { unsigned int devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0); - struct pci_dev *pdev0 = pci_get_slot(pdev->bus, devfn); + struct pci_dev *pdev0; u32 val; cb710_pci_update_config_reg(pdev, 0x48, @@ -43,6 +43,7 @@ static int __devinit cb710_pci_configure(struct pci_dev *pdev) if (val & 0x80000000) return 0; + pdev0 = pci_get_slot(pdev->bus, devfn); if (!pdev0) return -ENODEV; From 9b7bbe1085eb2b0f2d5d81f4116772cb2af497a4 Mon Sep 17 00:00:00 2001 From: Shashidhar Hiremath Date: Fri, 29 Jul 2011 08:49:50 -0400 Subject: [PATCH 07/17] mmc: dw_mmc: Fix mask in IDMAC_SET_BUFFER1_SIZE macro The mask used inside this macro was assuming Buffer_Size1's [BS1's] width to be 14 bits, it is actually 13 bits. Modify masks used in IDMAC_SET_BUFFER1_SIZE such that they use only 13 bits instead of current 14. Signed-off-by: Shashidhar Hiremath Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 77f0b6b1681d..f13bb49dbc71 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -62,7 +62,7 @@ struct idmac_desc { u32 des1; /* Buffer sizes */ #define IDMAC_SET_BUFFER1_SIZE(d, s) \ - ((d)->des1 = ((d)->des1 & 0x03ffc000) | ((s) & 0x3fff)) + ((d)->des1 = ((d)->des1 & 0x03ffe000) | ((s) & 0x1fff)) u32 des2; /* buffer 1 physical address */ From 55156d240a4d41d47310278c5139e24517f1c65b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Jul 2011 15:35:00 +0100 Subject: [PATCH 08/17] mmc: sdhci-s3c: Fix build for header change A header change has removed an implicit inclusion of module.h, breaking the build due to the use of THIS_MODULE. Fix that. Signed-off-by: Mark Brown Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-s3c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 03da44a1b2ab..2bd7bf4fece7 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -19,6 +19,7 @@ #include #include #include +#include #include From 0d58864bf3472f8390e0c0a33bd875c7eec868bd Mon Sep 17 00:00:00 2001 From: Tony Lin Date: Thu, 11 Aug 2011 16:45:59 -0400 Subject: [PATCH 09/17] mmc: esdhc-imx: fix card interrupt loss on freescale eSDHC Apply a workaround for the imx eSDHC controller to avoid missing card interrupts. This makes SDIO work. Signed-off-by: Tony Lin Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-esdhc-imx.c | 38 +++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 9ebfb4b482f5..0e9780f5a4a9 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -27,6 +27,7 @@ #include "sdhci-pltfm.h" #include "sdhci-esdhc.h" +#define SDHCI_CTRL_D3CD 0x08 /* VENDOR SPEC register */ #define SDHCI_VENDOR_SPEC 0xC0 #define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002 @@ -141,13 +142,32 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct pltfm_imx_data *imx_data = pltfm_host->priv; struct esdhc_platform_data *boarddata = &imx_data->boarddata; + u32 data; - if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE) - && (boarddata->cd_type == ESDHC_CD_GPIO))) - /* - * these interrupts won't work with a custom card_detect gpio - */ - val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); + if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) { + if (boarddata->cd_type == ESDHC_CD_GPIO) + /* + * These interrupts won't work with a custom + * card_detect gpio (only applied to mx25/35) + */ + val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); + + if (val & SDHCI_INT_CARD_INT) { + /* + * Clear and then set D3CD bit to avoid missing the + * card interrupt. This is a eSDHC controller problem + * so we need to apply the following workaround: clear + * and set D3CD bit will make eSDHC re-sample the card + * interrupt. In case a card interrupt was lost, + * re-sample it by the following steps. + */ + data = readl(host->ioaddr + SDHCI_HOST_CONTROL); + data &= ~SDHCI_CTRL_D3CD; + writel(data, host->ioaddr + SDHCI_HOST_CONTROL); + data |= SDHCI_CTRL_D3CD; + writel(data, host->ioaddr + SDHCI_HOST_CONTROL); + } + } if (unlikely((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT) && (reg == SDHCI_INT_STATUS) @@ -217,8 +237,10 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) */ return; case SDHCI_HOST_CONTROL: - /* FSL messed up here, so we can just keep those two */ - new_val = val & (SDHCI_CTRL_LED | SDHCI_CTRL_4BITBUS); + /* FSL messed up here, so we can just keep those three */ + new_val = val & (SDHCI_CTRL_LED | \ + SDHCI_CTRL_4BITBUS | \ + SDHCI_CTRL_D3CD); /* ensure the endianess */ new_val |= ESDHC_HOST_CONTROL_LE; /* DMA mode bits are shifted */ From 4906baf080623b4971bdeeac0a9fec5b8885d3ac Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 3 Aug 2011 14:48:58 +0800 Subject: [PATCH 10/17] mmc: tmio: eliminate unused variable 'mmc' warning Fix below compile warning: CC drivers/mmc/host/tmio_mmc.o drivers/mmc/host/tmio_mmc.c: In function 'tmio_mmc_suspend': drivers/mmc/host/tmio_mmc.c:30: warning: unused variable 'mmc' drivers/mmc/host/tmio_mmc.c: In function 'tmio_mmc_resume': drivers/mmc/host/tmio_mmc.c:45: warning: unused variable 'mmc' Signed-off-by: Axel Lin Acked-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 8d185de90d20..44a9668c4b7a 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -27,7 +27,6 @@ static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) { const struct mfd_cell *cell = mfd_get_cell(dev); - struct mmc_host *mmc = platform_get_drvdata(dev); int ret; ret = tmio_mmc_host_suspend(&dev->dev); @@ -42,7 +41,6 @@ static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) static int tmio_mmc_resume(struct platform_device *dev) { const struct mfd_cell *cell = mfd_get_cell(dev); - struct mmc_host *mmc = platform_get_drvdata(dev); int ret = 0; /* Tell the MFD core we are ready to be enabled */ From 83cbcd93a1be803ccda53e7acbdc9a937c8f6375 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 3 Aug 2011 18:35:58 +0300 Subject: [PATCH 11/17] mmc: Revert "mmc: sdhci: Fix SDHCI_QUIRK_TIMEOUT_USES_SDCLK" This reverts commit 4b01681c7764, which introduced a new potential divide by zero in the process of fixing one. The subsequent commits attempt to fix the issue properly. Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 262985a1a952..11d031b8708c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -632,9 +632,6 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) target_timeout = data->timeout_ns / 1000 + data->timeout_clks / host->clock; - if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) - host->timeout_clk = host->clock / 1000; - /* * Figure out needed cycles. * We do this in steps in order to fit inside a 32 bit int. @@ -645,7 +642,6 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) * => * (1) / (2) > 2^6 */ - BUG_ON(!host->timeout_clk); count = 0; current_timeout = (1 << 13) * 1000 / host->timeout_clk; while (current_timeout < target_timeout) { @@ -2474,6 +2470,9 @@ int sdhci_add_host(struct sdhci_host *host) if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT) host->timeout_clk *= 1000; + if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) + host->timeout_clk = host->clock / 1000; + /* * In case of Host Controller v3.00, find out whether clock * multiplier is supported. From 78a2ca2727a9b992901c715bc881b6ddb4ec6a4e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 3 Aug 2011 18:35:59 +0300 Subject: [PATCH 12/17] mmc: sdhci: check host->clock before using it as a denominator Sometimes host->clock could be zero which is a legal situation. This patch checks host->clock before usage as a denominator when timeout is calculated. A similar patch is applied for mmc core (see commit e9b8684, "mmc: fix division by zero in MMC core"). Without this patch, the execution of the sdhci_calc_timeout could end up with a backtrace: <0>[ 4.014319] divide error: 0000 [#1] PREEMPT SMP <4>[ 4.014352] Modules linked in: g_ether <4>[ 4.014376] <4>[ 4.014393] Pid: 33, comm: kworker/u:2 Not tainted 3.0.0+ #646 <4>[ 4.014421] EIP: 0060:[] EFLAGS: 00010046 CPU: 1 <4>[ 4.014449] EIP is at sdhci_calc_timeout+0x2e/0x100 <4>[ 4.014468] EAX: 00000000 EBX: f5930fc8 ECX: 00000000 EDX: 00000000 <4>[ 4.014488] ESI: f5291de8 EDI: f5291db8 EBP: f5291c6c ESP: f5291c50 <4>[ 4.014508] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 <0>[ 4.014529] Process kworker/u:2 (pid: 33, ti=f5290000 task=f53065a0 task.ti=f5290000) <0>[ 4.014546] Stack: <4>[ 4.014557] 00000082 c1054fdd f5291c78 04000000 f5930fc8 f5291de8 f5291db8 f5291cac <4>[ 4.014611] c12fab7c c107a98b f5291c88 c13b6d3f f593109c f5882000 f5291cac c1054fdd <4>[ 4.014663] 00000000 00000000 f5882000 00000082 f5930fc8 f5291db8 0000000a f5291ccc <0>[ 4.014716] Call Trace: <4>[ 4.014743] [] ? mod_timer+0x11d/0x380 <4>[ 4.014770] [] sdhci_prepare_data+0x2c/0x3a0 <4>[ 4.014798] [] ? trace_hardirqs_off+0xb/0x10 <4>[ 4.014827] [] ? _raw_spin_unlock_irqrestore+0x2f/0x60 <4>[ 4.014854] [] ? mod_timer+0x11d/0x380 <4>[ 4.014880] [] sdhci_send_command+0xdb/0x210 <4>[ 4.014906] [] sdhci_request+0xc3/0x150 <4>[ 4.014932] [] mmc_start_request+0xda/0x200 <4>[ 4.014960] [] ? __raw_spin_lock_init+0x32/0x60 <4>[ 4.014989] [] ? __init_waitqueue_head+0x35/0x50 <4>[ 4.015015] [] mmc_wait_for_req+0x7b/0x90 <4>[ 4.015045] [] mmc_send_cxd_data+0xf7/0x130 <4>[ 4.015076] [] ? mmc_erase+0x140/0x140 <4>[ 4.015102] [] mmc_send_ext_csd+0x1d/0x20 <4>[ 4.015125] [] mmc_get_ext_csd+0x70/0x140 <4>[ 4.015151] [] mmc_compare_ext_csds+0x28/0x190 <4>[ 4.015176] [] mmc_init_card+0x24f/0x650 <4>[ 4.015201] [] ? _raw_spin_unlock_irqrestore+0x4d/0x60 <4>[ 4.015226] [] ? trace_hardirqs_on_caller+0x11c/0x160 <4>[ 4.015255] [] mmc_attach_mmc+0xa4/0x190 <4>[ 4.015282] [] mmc_rescan+0x210/0x240 <4>[ 4.015311] [] process_one_work+0x176/0x550 <4>[ 4.015336] [] ? process_one_work+0xfa/0x550 <4>[ 4.015360] [] ? mmc_init_erase+0x140/0x140 <4>[ 4.015385] [] worker_thread+0x12a/0x2c0 <4>[ 4.015410] [] ? manage_workers.clone.18+0x100/0x100 <4>[ 4.015437] [] kthread+0x74/0x80 <4>[ 4.015463] [] ? __init_kthread_worker+0x60/0x60 <4>[ 4.015490] [] kernel_thread_helper+0x6/0xd <0>[ 4.015507] Code: 57 89 d7 56 53 89 c3 83 ec 10 8b 40 04 8b 72 28 f6 c4 10 89 45 f0 0f 85 91 00 00 00 85 f6 0f 84 c1 00 00 00 8b 4e 04 31 d2 89 c8 73 58 ba d3 4d 62 10 89 c1 8b 06 f7 e2 c1 ea 06 01 d1 f7 45 <0>[ 4.015829] EIP: [] sdhci_calc_timeout+0x2e/0x100 SS:ESP 0068:f5291c50 Reported-by: Alexander Shishkin Signed-off-by: Andy Shevchenko Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 11d031b8708c..89ba4516cb8c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -628,9 +628,11 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) /* timeout in us */ if (!data) target_timeout = cmd->cmd_timeout_ms * 1000; - else - target_timeout = data->timeout_ns / 1000 + - data->timeout_clks / host->clock; + else { + target_timeout = data->timeout_ns / 1000; + if (host->clock) + target_timeout += data->timeout_clks / host->clock; + } /* * Figure out needed cycles. From 272308caaa6c0f2b1500a3660b9fa75f17a45cc4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 3 Aug 2011 18:36:00 +0300 Subject: [PATCH 13/17] mmc: sdhci: move timeout_clk calculation farther down This moves the calculation below the assignment of mmc->f_max, which we need for calculating timeout_clk in the next patch in this series. Signed-off-by: Andy Shevchenko Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 89ba4516cb8c..afa26bdcfa46 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2456,25 +2456,6 @@ int sdhci_add_host(struct sdhci_host *host) host->max_clk = host->ops->get_max_clock(host); } - host->timeout_clk = - (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; - if (host->timeout_clk == 0) { - if (host->ops->get_timeout_clock) { - host->timeout_clk = host->ops->get_timeout_clock(host); - } else if (!(host->quirks & - SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { - printk(KERN_ERR - "%s: Hardware doesn't specify timeout clock " - "frequency.\n", mmc_hostname(mmc)); - return -ENODEV; - } - } - if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT) - host->timeout_clk *= 1000; - - if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) - host->timeout_clk = host->clock / 1000; - /* * In case of Host Controller v3.00, find out whether clock * multiplier is supported. @@ -2507,6 +2488,25 @@ int sdhci_add_host(struct sdhci_host *host) } else mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; + host->timeout_clk = + (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; + if (host->timeout_clk == 0) { + if (host->ops->get_timeout_clock) { + host->timeout_clk = host->ops->get_timeout_clock(host); + } else if (!(host->quirks & + SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { + printk(KERN_ERR + "%s: Hardware doesn't specify timeout clock " + "frequency.\n", mmc_hostname(mmc)); + return -ENODEV; + } + } + if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT) + host->timeout_clk *= 1000; + + if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) + host->timeout_clk = host->clock / 1000; + if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) mmc->max_discard_to = (1 << 27) / (mmc->f_max / 1000); else From 65be3fef930beb3e282e7f23dfba63289971430c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 3 Aug 2011 18:36:01 +0300 Subject: [PATCH 14/17] mmc: sdhci: use f_max instead of host->clock for timeouts When timeout_clk is calculated the host->clock could be zero. So, instead of host->clock the calculation now uses mmc->f_max. Signed-off-by: Andy Shevchenko Cc: Mark Brown Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index afa26bdcfa46..0e02cc1df12e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2505,12 +2505,9 @@ int sdhci_add_host(struct sdhci_host *host) host->timeout_clk *= 1000; if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) - host->timeout_clk = host->clock / 1000; + host->timeout_clk = mmc->f_max / 1000; - if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) - mmc->max_discard_to = (1 << 27) / (mmc->f_max / 1000); - else - mmc->max_discard_to = (1 << 27) / host->timeout_clk; + mmc->max_discard_to = (1 << 27) / host->timeout_clk; mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; From 7435bb7950ba8a3cbfa6d0c01e92588562533a3f Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Wed, 10 Aug 2011 18:46:28 +0900 Subject: [PATCH 15/17] mmc: core: use defined R1_STATE_PRG macro for card status Signed-off-by: Jaehoon Chung Signed-off-by: Kyungmin Park Signed-off-by: Chris Ball --- drivers/mmc/card/mmc_test.c | 2 +- drivers/mmc/core/core.c | 2 +- drivers/mmc/core/mmc_ops.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 742dc98a034c..2bf229acd3b8 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -224,7 +224,7 @@ static void mmc_test_prepare_mrq(struct mmc_test_card *test, static int mmc_test_busy(struct mmc_command *cmd) { return !(cmd->resp[0] & R1_READY_FOR_DATA) || - (R1_CURRENT_STATE(cmd->resp[0]) == 7); + (R1_CURRENT_STATE(cmd->resp[0]) == R1_STATE_PRG); } /* diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 89bdeaec7182..91a0a7460ebb 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1502,7 +1502,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, goto out; } } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || - R1_CURRENT_STATE(cmd.resp[0]) == 7); + R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG); out: return err; } diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 845ce7c533b9..770c3d06f5dc 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -407,7 +407,7 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, break; if (mmc_host_is_spi(card->host)) break; - } while (R1_CURRENT_STATE(status) == 7); + } while (R1_CURRENT_STATE(status) == R1_STATE_PRG); if (mmc_host_is_spi(card->host)) { if (status & R1_SPI_ILLEGAL_COMMAND) From 6daa777866569fc48fe3cfcd6fd01aba37ac06a5 Mon Sep 17 00:00:00 2001 From: Seungwon Jeon Date: Fri, 5 Aug 2011 12:35:03 +0900 Subject: [PATCH 16/17] mmc: dw_mmc: Fix DDR mode support. Host driver can't get a hint of DDR mode through ios->ddr flag anymore. ios->timing is currently used to inform DDR mode as a substitute. And capability of MMC_CAP_MMC_HIGHSPEED is added for DDR support. Signed-off-by: Seungwon Jeon Acked-by: Will Newton Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index f13bb49dbc71..ff0f714b012c 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -699,7 +699,7 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } /* DDR mode set */ - if (ios->ddr) { + if (ios->timing == MMC_TIMING_UHS_DDR50) { regs = mci_readl(slot->host, UHS_REG); regs |= (0x1 << slot->id) << 16; mci_writel(slot->host, UHS_REG, regs); @@ -1646,7 +1646,7 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) mmc->caps |= MMC_CAP_4_BIT_DATA; if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED) - mmc->caps |= MMC_CAP_SD_HIGHSPEED; + mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; #ifdef CONFIG_MMC_DW_IDMAC mmc->max_segs = host->ring_size; From 7fd781e8f9b72544a1c7f04456eb33d5ffaed592 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Mon, 8 Aug 2011 18:10:52 +0900 Subject: [PATCH 17/17] mmc: remove unused "ddr" parameter in struct mmc_ios "mmc: dw_mmc: Fix DDR mode support" removed the last user. Signed-off-by: Jaehoon Chung Signed-off-by: Kyungmin Park Signed-off-by: Chris Ball --- include/linux/mmc/host.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 0f83858147a6..1d09562ccf73 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -56,8 +56,6 @@ struct mmc_ios { #define MMC_TIMING_UHS_SDR104 4 #define MMC_TIMING_UHS_DDR50 5 - unsigned char ddr; /* dual data rate used */ - #define MMC_SDR_MODE 0 #define MMC_1_2V_DDR_MODE 1 #define MMC_1_8V_DDR_MODE 2