at v2.6.22 233 lines 5.3 kB view raw
1/* 2 * linux/drivers/mmc/queue.c 3 * 4 * Copyright (C) 2003 Russell King, All Rights Reserved. 5 * Copyright 2006-2007 Pierre Ossman 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 */ 12#include <linux/module.h> 13#include <linux/blkdev.h> 14#include <linux/kthread.h> 15 16#include <linux/mmc/card.h> 17#include <linux/mmc/host.h> 18#include "queue.h" 19 20#define MMC_QUEUE_SUSPENDED (1 << 0) 21 22/* 23 * Prepare a MMC request. This just filters out odd stuff. 24 */ 25static int mmc_prep_request(struct request_queue *q, struct request *req) 26{ 27 /* 28 * We only like normal block requests. 29 */ 30 if (!blk_fs_request(req) && !blk_pc_request(req)) { 31 blk_dump_rq_flags(req, "MMC bad request"); 32 return BLKPREP_KILL; 33 } 34 35 req->cmd_flags |= REQ_DONTPREP; 36 37 return BLKPREP_OK; 38} 39 40static int mmc_queue_thread(void *d) 41{ 42 struct mmc_queue *mq = d; 43 struct request_queue *q = mq->queue; 44 45 /* 46 * Set iothread to ensure that we aren't put to sleep by 47 * the process freezing. We handle suspension ourselves. 48 */ 49 current->flags |= PF_MEMALLOC|PF_NOFREEZE; 50 51 down(&mq->thread_sem); 52 do { 53 struct request *req = NULL; 54 55 spin_lock_irq(q->queue_lock); 56 set_current_state(TASK_INTERRUPTIBLE); 57 if (!blk_queue_plugged(q)) 58 req = elv_next_request(q); 59 mq->req = req; 60 spin_unlock_irq(q->queue_lock); 61 62 if (!req) { 63 if (kthread_should_stop()) { 64 set_current_state(TASK_RUNNING); 65 break; 66 } 67 up(&mq->thread_sem); 68 schedule(); 69 down(&mq->thread_sem); 70 continue; 71 } 72 set_current_state(TASK_RUNNING); 73 74 mq->issue_fn(mq, req); 75 } while (1); 76 up(&mq->thread_sem); 77 78 return 0; 79} 80 81/* 82 * Generic MMC request handler. This is called for any queue on a 83 * particular host. When the host is not busy, we look for a request 84 * on any queue on this host, and attempt to issue it. This may 85 * not be the queue we were asked to process. 86 */ 87static void mmc_request(request_queue_t *q) 88{ 89 struct mmc_queue *mq = q->queuedata; 90 struct request *req; 91 int ret; 92 93 if (!mq) { 94 printk(KERN_ERR "MMC: killing requests for dead queue\n"); 95 while ((req = elv_next_request(q)) != NULL) { 96 do { 97 ret = end_that_request_chunk(req, 0, 98 req->current_nr_sectors << 9); 99 } while (ret); 100 } 101 return; 102 } 103 104 if (!mq->req) 105 wake_up_process(mq->thread); 106} 107 108/** 109 * mmc_init_queue - initialise a queue structure. 110 * @mq: mmc queue 111 * @card: mmc card to attach this queue 112 * @lock: queue lock 113 * 114 * Initialise a MMC card request queue. 115 */ 116int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock) 117{ 118 struct mmc_host *host = card->host; 119 u64 limit = BLK_BOUNCE_HIGH; 120 int ret; 121 122 if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) 123 limit = *mmc_dev(host)->dma_mask; 124 125 mq->card = card; 126 mq->queue = blk_init_queue(mmc_request, lock); 127 if (!mq->queue) 128 return -ENOMEM; 129 130 blk_queue_prep_rq(mq->queue, mmc_prep_request); 131 blk_queue_bounce_limit(mq->queue, limit); 132 blk_queue_max_sectors(mq->queue, host->max_req_size / 512); 133 blk_queue_max_phys_segments(mq->queue, host->max_phys_segs); 134 blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); 135 blk_queue_max_segment_size(mq->queue, host->max_seg_size); 136 137 mq->queue->queuedata = mq; 138 mq->req = NULL; 139 140 mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs, 141 GFP_KERNEL); 142 if (!mq->sg) { 143 ret = -ENOMEM; 144 goto cleanup_queue; 145 } 146 147 init_MUTEX(&mq->thread_sem); 148 149 mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd"); 150 if (IS_ERR(mq->thread)) { 151 ret = PTR_ERR(mq->thread); 152 goto free_sg; 153 } 154 155 return 0; 156 157 free_sg: 158 kfree(mq->sg); 159 mq->sg = NULL; 160 cleanup_queue: 161 blk_cleanup_queue(mq->queue); 162 return ret; 163} 164 165void mmc_cleanup_queue(struct mmc_queue *mq) 166{ 167 request_queue_t *q = mq->queue; 168 unsigned long flags; 169 170 /* Mark that we should start throwing out stragglers */ 171 spin_lock_irqsave(q->queue_lock, flags); 172 q->queuedata = NULL; 173 spin_unlock_irqrestore(q->queue_lock, flags); 174 175 /* Make sure the queue isn't suspended, as that will deadlock */ 176 mmc_queue_resume(mq); 177 178 /* Then terminate our worker thread */ 179 kthread_stop(mq->thread); 180 181 kfree(mq->sg); 182 mq->sg = NULL; 183 184 blk_cleanup_queue(mq->queue); 185 186 mq->card = NULL; 187} 188EXPORT_SYMBOL(mmc_cleanup_queue); 189 190/** 191 * mmc_queue_suspend - suspend a MMC request queue 192 * @mq: MMC queue to suspend 193 * 194 * Stop the block request queue, and wait for our thread to 195 * complete any outstanding requests. This ensures that we 196 * won't suspend while a request is being processed. 197 */ 198void mmc_queue_suspend(struct mmc_queue *mq) 199{ 200 request_queue_t *q = mq->queue; 201 unsigned long flags; 202 203 if (!(mq->flags & MMC_QUEUE_SUSPENDED)) { 204 mq->flags |= MMC_QUEUE_SUSPENDED; 205 206 spin_lock_irqsave(q->queue_lock, flags); 207 blk_stop_queue(q); 208 spin_unlock_irqrestore(q->queue_lock, flags); 209 210 down(&mq->thread_sem); 211 } 212} 213 214/** 215 * mmc_queue_resume - resume a previously suspended MMC request queue 216 * @mq: MMC queue to resume 217 */ 218void mmc_queue_resume(struct mmc_queue *mq) 219{ 220 request_queue_t *q = mq->queue; 221 unsigned long flags; 222 223 if (mq->flags & MMC_QUEUE_SUSPENDED) { 224 mq->flags &= ~MMC_QUEUE_SUSPENDED; 225 226 up(&mq->thread_sem); 227 228 spin_lock_irqsave(q->queue_lock, flags); 229 blk_start_queue(q); 230 spin_unlock_irqrestore(q->queue_lock, flags); 231 } 232} 233