aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2006-11-14 16:08:16 -0500
committerPierre Ossman <drzeus@drzeus.cx>2006-12-01 13:06:05 -0500
commit89b4e133afea9fce333054b94d89953583a55c19 (patch)
tree23502a0f8b2bd2ebe0b821a152711746b3457560 /drivers/mmc
parent077df884835ebf2b5db16aacd9a24691d89902a0 (diff)
mmc: Flush block queue when removing card
After mmc_block's remove function has exited, we must not touch the card structure in any way. This means we not only must remove the gendisk, we must also flush out any remaning requests already queued up. We previously removed the disk, but didn't flush it, causing oops:es when removing a card in the middle of a transfer. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/mmc_block.c8
-rw-r--r--drivers/mmc/mmc_queue.c22
2 files changed, 25 insertions, 5 deletions
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index f9027c8db792..5025abebfc82 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -83,7 +83,6 @@ static void mmc_blk_put(struct mmc_blk_data *md)
83 md->usage--; 83 md->usage--;
84 if (md->usage == 0) { 84 if (md->usage == 0) {
85 put_disk(md->disk); 85 put_disk(md->disk);
86 mmc_cleanup_queue(&md->queue);
87 kfree(md); 86 kfree(md);
88 } 87 }
89 mutex_unlock(&open_lock); 88 mutex_unlock(&open_lock);
@@ -553,12 +552,11 @@ static void mmc_blk_remove(struct mmc_card *card)
553 if (md) { 552 if (md) {
554 int devidx; 553 int devidx;
555 554
555 /* Stop new requests from getting into the queue */
556 del_gendisk(md->disk); 556 del_gendisk(md->disk);
557 557
558 /* 558 /* Then flush out any already in there */
559 * I think this is needed. 559 mmc_cleanup_queue(&md->queue);
560 */
561 md->disk->queue = NULL;
562 560
563 devidx = md->disk->first_minor >> MMC_SHIFT; 561 devidx = md->disk->first_minor >> MMC_SHIFT;
564 __clear_bit(devidx, dev_use); 562 __clear_bit(devidx, dev_use);
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c
index 4e6a534e91d0..5fa72ccb4feb 100644
--- a/drivers/mmc/mmc_queue.c
+++ b/drivers/mmc/mmc_queue.c
@@ -103,6 +103,19 @@ static int mmc_queue_thread(void *d)
103static void mmc_request(request_queue_t *q) 103static void mmc_request(request_queue_t *q)
104{ 104{
105 struct mmc_queue *mq = q->queuedata; 105 struct mmc_queue *mq = q->queuedata;
106 struct request *req;
107 int ret;
108
109 if (!mq) {
110 printk(KERN_ERR "MMC: killing requests for dead queue\n");
111 while ((req = elv_next_request(q)) != NULL) {
112 do {
113 ret = end_that_request_chunk(req, 0,
114 req->current_nr_sectors << 9);
115 } while (ret);
116 }
117 return;
118 }
106 119
107 if (!mq->req) 120 if (!mq->req)
108 wake_up_process(mq->thread); 121 wake_up_process(mq->thread);
@@ -168,6 +181,15 @@ EXPORT_SYMBOL(mmc_init_queue);
168 181
169void mmc_cleanup_queue(struct mmc_queue *mq) 182void mmc_cleanup_queue(struct mmc_queue *mq)
170{ 183{
184 request_queue_t *q = mq->queue;
185 unsigned long flags;
186
187 /* Mark that we should start throwing out stragglers */
188 spin_lock_irqsave(q->queue_lock, flags);
189 q->queuedata = NULL;
190 spin_unlock_irqrestore(q->queue_lock, flags);
191
192 /* Then terminate our worker thread */
171 kthread_stop(mq->thread); 193 kthread_stop(mq->thread);
172 194
173 kfree(mq->sg); 195 kfree(mq->sg);