From 7de427d088a967d2173739e21e744921d5496a8b Mon Sep 17 00:00:00 2001 From: Jorg Schummer Date: Thu, 19 Feb 2009 13:17:03 +0200 Subject: mmc: delayed_work was never cancelled The delayed work item mmc_host.detect is now cancelled before flushing the work queue. This takes care of cases when delayed_work was scheduled for mmc_host.detect, but not yet placed in the work queue. Signed-off-by: Jorg Schummer Signed-off-by: Pierre Ossman --- drivers/mmc/core/core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index df6ce4a06cf..b5899e33b68 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -815,6 +815,7 @@ void mmc_stop_host(struct mmc_host *host) spin_unlock_irqrestore(&host->lock, flags); #endif + cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); mmc_bus_get(host); @@ -842,6 +843,7 @@ void mmc_stop_host(struct mmc_host *host) */ int mmc_suspend_host(struct mmc_host *host, pm_message_t state) { + cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); mmc_bus_get(host); -- cgit v1.2.3 From 6b0b62853b2553be375033776902640320970846 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Mon, 23 Feb 2009 12:38:41 +0000 Subject: mmc: add MODALIAS linkage for MMC/SD devices Currently we are using an explicit udev rule to trigger loading of the mmc-block module when an MMC or SD card is detected: SUBSYSTEM=="mmc", RUN+="/sbin/modprobe -Qba mmc-block" It makes much more sense for the mmc bus driver and the mmc-block module to share MODALIAS information so that they are linked automatically. There is no real information of use in the MMC system at the current time. All devices inserted require us to load the mmc-block device. Until such time as useful parameters exist simply reflect the module linkage via the module alias below: mmc:block Signed-off-by: Andy Whitcroft Signed-off-by: Pierre Ossman --- drivers/mmc/core/bus.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index f210a8ee686..bdb165f9304 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -84,6 +84,14 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) } retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); + if (retval) + return retval; + + /* + * Request the mmc_block device. Note: that this is a direct request + * for the module it carries no information as to what is inserted. + */ + retval = add_uevent_var(env, "MODALIAS=mmc:block"); return retval; } -- cgit v1.2.3 From 736bb6bb01a2a180b6f062e792bd03658d57ab7e Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 11 Feb 2009 14:52:20 +0200 Subject: mmc: Add Extended CSD register to debugfs Extended CSD is a MMC card register. As increasingly interesting fields are being added to Extended CSD, it is helpful to see its value. Note that SD cards do not have an Extended CSD register, so it is MMC only. Signed-off-by: Adrian Hunter Signed-off-by: Pierre Ossman --- drivers/mmc/core/debugfs.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 1237bb4c722..610dbd1fcc8 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -184,6 +184,68 @@ static int mmc_dbg_card_status_get(void *data, u64 *val) DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, NULL, "%08llx\n"); +#define EXT_CSD_STR_LEN 1025 + +static int mmc_ext_csd_open(struct inode *inode, struct file *filp) +{ + struct mmc_card *card = inode->i_private; + char *buf; + ssize_t n = 0; + u8 *ext_csd; + int err, i; + + buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ext_csd = kmalloc(512, GFP_KERNEL); + if (!ext_csd) { + err = -ENOMEM; + goto out_free; + } + + mmc_claim_host(card->host); + err = mmc_send_ext_csd(card, ext_csd); + mmc_release_host(card->host); + if (err) + goto out_free; + + for (i = 511; i >= 0; i--) + n += sprintf(buf + n, "%02x", ext_csd[i]); + n += sprintf(buf + n, "\n"); + BUG_ON(n != EXT_CSD_STR_LEN); + + filp->private_data = buf; + kfree(ext_csd); + return 0; + +out_free: + kfree(buf); + kfree(ext_csd); + return err; +} + +static ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + char *buf = filp->private_data; + + return simple_read_from_buffer(ubuf, cnt, ppos, + buf, EXT_CSD_STR_LEN); +} + +static int mmc_ext_csd_release(struct inode *inode, struct file *file) +{ + kfree(file->private_data); + return 0; +} + +static struct file_operations mmc_dbg_ext_csd_fops = { + .open = mmc_ext_csd_open, + .read = mmc_ext_csd_read, + .release = mmc_ext_csd_release, +}; + void mmc_add_card_debugfs(struct mmc_card *card) { struct mmc_host *host = card->host; @@ -211,6 +273,11 @@ void mmc_add_card_debugfs(struct mmc_card *card) &mmc_dbg_card_status_fops)) goto err; + if (mmc_card_mmc(card)) + if (!debugfs_create_file("ext_csd", S_IRUSR, root, card, + &mmc_dbg_ext_csd_fops)) + goto err; + return; err: -- cgit v1.2.3 From 0d6132ba0b006dd2bea9ba0c7b6b2f690cd95c40 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 5 Mar 2009 19:37:28 +0100 Subject: sdio: handle cis end marker in link field Signed-off-by: Pierre Ossman --- drivers/mmc/core/sdio_cis.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index 956bd767750..6ba93f59928 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c @@ -227,6 +227,10 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) if (ret) break; + /* a size of 0xff also means we're done */ + if (tpl_link == 0xff) + break; + this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL); if (!this) return -ENOMEM; -- cgit v1.2.3 From c8d718f1037950107f13607ff0b696ffe63df76a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 5 Mar 2009 19:38:38 +0100 Subject: sdio: handle null tuples Signed-off-by: Pierre Ossman --- drivers/mmc/core/sdio_cis.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index 6ba93f59928..963f2937c5e 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c @@ -223,6 +223,10 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) if (tpl_code == 0xff) break; + /* null entries have no link field or data */ + if (tpl_code == 0x00) + continue; + ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link); if (ret) break; -- cgit v1.2.3 From be6f19fc24c937112d251232b3dae7e05e96aad1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 5 Mar 2009 19:40:27 +0100 Subject: sdio: check that addresses are within the address space Signed-off-by: Pierre Ossman --- drivers/mmc/core/sdio_ops.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c index c8fa095a448..4eb7825fd1a 100644 --- a/drivers/mmc/core/sdio_ops.c +++ b/drivers/mmc/core/sdio_ops.c @@ -76,6 +76,10 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, BUG_ON(!card); BUG_ON(fn > 7); + /* sanity check */ + if (addr & ~0x1FFFF) + return -EINVAL; + memset(&cmd, 0, sizeof(struct mmc_command)); cmd.opcode = SD_IO_RW_DIRECT; @@ -125,6 +129,10 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, WARN_ON(blocks == 0); WARN_ON(blksz == 0); + /* sanity check */ + if (addr & ~0x1FFFF) + return -EINVAL; + memset(&mrq, 0, sizeof(struct mmc_request)); memset(&cmd, 0, sizeof(struct mmc_command)); memset(&data, 0, sizeof(struct mmc_data)); -- cgit v1.2.3 From d3096f88ac4596a509fc5fbe6fa7e7a5497eb399 Mon Sep 17 00:00:00 2001 From: Balaji Rao Date: Wed, 25 Feb 2009 15:28:09 +0530 Subject: mmc: During unsafe resume, select the right volatge for the card During mmc unsafe resume, choose the right voltage for the card after powerup. Although this has not seen to cause trouble, it's the wrong behaviour. Signed-off-by: Balaji Rao Signed-off-by: Pierre Ossman --- drivers/mmc/core/core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index b5899e33b68..4a18d90556d 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -877,6 +877,7 @@ int mmc_resume_host(struct mmc_host *host) mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { mmc_power_up(host); + mmc_select_voltage(host, host->ocr); BUG_ON(!host->bus_ops->resume); host->bus_ops->resume(host); } -- cgit v1.2.3 From c0c88871574ccb4ee53dde1bbb678931b38ed47b Mon Sep 17 00:00:00 2001 From: Wolfgang Muees Date: Wed, 11 Mar 2009 14:28:39 +0100 Subject: mmc_spi: allow higher timeouts for SPI mode Some SD cards have very high timeouts in SPI mode. So adjust the timeouts from theory to practice. Signed-off-by: Wolfgang Muees Acked-by: David Brownell Signed-off-by: Pierre Ossman --- drivers/mmc/core/core.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/mmc/core') diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 4a18d90556d..5c83c67b186 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -297,6 +297,21 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) data->timeout_clks = 0; } } + /* + * Some cards need very high timeouts if driven in SPI mode. + * The worst observed timeout was 900ms after writing a + * continuous stream of data until the internal logic + * overflowed. + */ + if (mmc_host_is_spi(card->host)) { + if (data->flags & MMC_DATA_WRITE) { + if (data->timeout_ns < 1000000000) + data->timeout_ns = 1000000000; /* 1s */ + } else { + if (data->timeout_ns < 100000000) + data->timeout_ns = 100000000; /* 100ms */ + } + } } EXPORT_SYMBOL(mmc_set_data_timeout); -- cgit v1.2.3