Browse Source

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc:
  mmc: Avoid re-using minor numbers before the original device is closed.
  tifm_sd: handle non-power-of-2 block sizes
  mmc_block: check card state after write
Linus Torvalds 17 years ago
parent
commit
64d0793109
2 changed files with 20 additions and 20 deletions
  1. 13 9
      drivers/mmc/card/block.c
  2. 7 11
      drivers/mmc/host/tifm_sd.c

+ 13 - 9
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);
 	}
@@ -321,7 +327,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)
@@ -400,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)
 {
@@ -568,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);

+ 7 - 11
drivers/mmc/host/tifm_sd.c

@@ -16,7 +16,6 @@
 #include <linux/mmc/host.h>
 #include <linux/highmem.h>
 #include <linux/scatterlist.h>
-#include <linux/log2.h>
 #include <asm/io.h>
 
 #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);