From d198f101989d9bb950327f0d043f6203bb862343 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 2 Nov 2007 18:21:13 +0100 Subject: [PATCH 1/3] mmc_block: check card state after write Some cards have been reported to signal that they're ready prematurely. Checking both the busy bit and card state solves the issue. Signed-off-by: Pierre Ossman --- drivers/mmc/card/block.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index e38d5a3b2a89..acaa05200ae7 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -321,7 +321,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) req->rq_disk->disk_name, err); goto cmd_err; } - } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); + /* + * Some cards mishandle the status bits, + * so make sure to check both the busy + * indication and the card state. + */ + } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || + (R1_CURRENT_STATE(cmd.resp[0]) == 7)); #if 0 if (cmd.resp[0] & ~0x00000900) From b37a05069b9ab9fb1e52393a3448d710c50c54d5 Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Wed, 14 Nov 2007 23:55:36 +1100 Subject: [PATCH 2/3] tifm_sd: handle non-power-of-2 block sizes It is possible to handle arbitrary block sizes with tifm card reader by conditionally switching to PIO in case such block has to be delivered. At the beginning of each request, DMA is either disabled (non-power-of-2 block size) or set to load time user preference. Signed-off-by: Alex Dubov Signed-off-by: Pierre Ossman --- drivers/mmc/host/tifm_sd.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index c11a3d256051..20d5c7bd940a 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #define DRIVER_NAME "tifm_sd" @@ -638,17 +637,15 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) goto err_out; } - if (mrq->data && !is_power_of_2(mrq->data->blksz)) { - printk(KERN_ERR "%s: Unsupported block size (%d bytes)\n", - sock->dev.bus_id, mrq->data->blksz); - mrq->cmd->error = -EINVAL; - goto err_out; - } - host->cmd_flags = 0; host->block_pos = 0; host->sg_pos = 0; + if (mrq->data && !is_power_of_2(mrq->data->blksz)) + host->no_dma = 1; + else + host->no_dma = no_dma ? 1 : 0; + if (r_data) { tifm_sd_set_data_timeout(host, r_data); @@ -676,7 +673,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) : PCI_DMA_FROMDEVICE)) { printk(KERN_ERR "%s : scatterlist map failed\n", sock->dev.bus_id); - spin_unlock_irqrestore(&sock->lock, flags); + mrq->cmd->error = -ENOMEM; goto err_out; } host->sg_len = tifm_map_sg(sock, r_data->sg, @@ -692,7 +689,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) r_data->flags & MMC_DATA_WRITE ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - spin_unlock_irqrestore(&sock->lock, flags); + mrq->cmd->error = -ENOMEM; goto err_out; } @@ -966,7 +963,6 @@ static int tifm_sd_probe(struct tifm_dev *sock) return -ENOMEM; host = mmc_priv(mmc); - host->no_dma = no_dma; tifm_set_drvdata(sock, mmc); host->dev = sock; host->timeout_jiffies = msecs_to_jiffies(1000); From 1dff314451fa24d6b107aa05393d3169e56a7e0a Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 21 Nov 2007 18:45:12 +0100 Subject: [PATCH 3/3] mmc: Avoid re-using minor numbers before the original device is closed. Move the code which marks the minor number as free to mmc_blk_put() so that it happens on the final close() (or removal), instead of doing it at removal even when the device is still logically open. Signed-off-by: David Woodhouse Signed-off-by: Pierre Ossman --- drivers/mmc/card/block.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index acaa05200ae7..aeb32a93f6a0 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -44,6 +44,9 @@ * max 8 partitions per card */ #define MMC_SHIFT 3 +#define MMC_NUM_MINORS (256 >> MMC_SHIFT) + +static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))]; /* * There is one mmc_blk_data per slot. @@ -80,6 +83,9 @@ static void mmc_blk_put(struct mmc_blk_data *md) mutex_lock(&open_lock); md->usage--; if (md->usage == 0) { + int devidx = md->disk->first_minor >> MMC_SHIFT; + __clear_bit(devidx, dev_use); + put_disk(md->disk); kfree(md); } @@ -406,9 +412,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) return 0; } -#define MMC_NUM_MINORS (256 >> MMC_SHIFT) - -static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))]; static inline int mmc_blk_readonly(struct mmc_card *card) { @@ -574,17 +577,12 @@ static void mmc_blk_remove(struct mmc_card *card) struct mmc_blk_data *md = mmc_get_drvdata(card); if (md) { - int devidx; - /* Stop new requests from getting into the queue */ del_gendisk(md->disk); /* Then flush out any already in there */ mmc_cleanup_queue(&md->queue); - devidx = md->disk->first_minor >> MMC_SHIFT; - __clear_bit(devidx, dev_use); - mmc_blk_put(md); } mmc_set_drvdata(card, NULL);