aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2014-02-10 06:24:40 -0500
committerJens Axboe <axboe@fb.com>2014-02-10 11:27:31 -0500
commitce2c350b2cfe5b5ca5023a6b1ec4d21821d39add (patch)
treec074778d490c8a45dc6e52d8161dcd6517906a61 /drivers/block
parent5124c285797aa33d5fdb909fbe808a61bcc5eb9d (diff)
null_blk: use blk_complete_request and blk_mq_complete_request
Use the block layer helpers for CPU-local completions instead of reimplementing them locally. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/null_blk.c97
1 files changed, 32 insertions, 65 deletions
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c
index cc801cde5cfa..091b9ea14feb 100644
--- a/drivers/block/null_blk.c
+++ b/drivers/block/null_blk.c
@@ -60,7 +60,9 @@ enum {
60 NULL_IRQ_NONE = 0, 60 NULL_IRQ_NONE = 0,
61 NULL_IRQ_SOFTIRQ = 1, 61 NULL_IRQ_SOFTIRQ = 1,
62 NULL_IRQ_TIMER = 2, 62 NULL_IRQ_TIMER = 2,
63};
63 64
65enum {
64 NULL_Q_BIO = 0, 66 NULL_Q_BIO = 0,
65 NULL_Q_RQ = 1, 67 NULL_Q_RQ = 1,
66 NULL_Q_MQ = 2, 68 NULL_Q_MQ = 2,
@@ -172,18 +174,20 @@ static struct nullb_cmd *alloc_cmd(struct nullb_queue *nq, int can_wait)
172 174
173static void end_cmd(struct nullb_cmd *cmd) 175static void end_cmd(struct nullb_cmd *cmd)
174{ 176{
175 if (cmd->rq) { 177 switch (queue_mode) {
176 if (queue_mode == NULL_Q_MQ) 178 case NULL_Q_MQ:
177 blk_mq_end_io(cmd->rq, 0); 179 blk_mq_end_io(cmd->rq, 0);
178 else { 180 return;
179 INIT_LIST_HEAD(&cmd->rq->queuelist); 181 case NULL_Q_RQ:
180 blk_end_request_all(cmd->rq, 0); 182 INIT_LIST_HEAD(&cmd->rq->queuelist);
181 } 183 blk_end_request_all(cmd->rq, 0);
182 } else if (cmd->bio) 184 break;
185 case NULL_Q_BIO:
183 bio_endio(cmd->bio, 0); 186 bio_endio(cmd->bio, 0);
187 break;
188 }
184 189
185 if (queue_mode != NULL_Q_MQ) 190 free_cmd(cmd);
186 free_cmd(cmd);
187} 191}
188 192
189static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer) 193static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer)
@@ -222,62 +226,31 @@ static void null_cmd_end_timer(struct nullb_cmd *cmd)
222 226
223static void null_softirq_done_fn(struct request *rq) 227static void null_softirq_done_fn(struct request *rq)
224{ 228{
225 blk_end_request_all(rq, 0); 229 end_cmd(rq->special);
226}
227
228#ifdef CONFIG_SMP
229
230static void null_ipi_cmd_end_io(void *data)
231{
232 struct completion_queue *cq;
233 struct llist_node *entry, *next;
234 struct nullb_cmd *cmd;
235
236 cq = &per_cpu(completion_queues, smp_processor_id());
237
238 entry = llist_del_all(&cq->list);
239 entry = llist_reverse_order(entry);
240
241 while (entry) {
242 next = entry->next;
243 cmd = llist_entry(entry, struct nullb_cmd, ll_list);
244 end_cmd(cmd);
245 entry = next;
246 }
247}
248
249static void null_cmd_end_ipi(struct nullb_cmd *cmd)
250{
251 struct call_single_data *data = &cmd->csd;
252 int cpu = get_cpu();
253 struct completion_queue *cq = &per_cpu(completion_queues, cpu);
254
255 cmd->ll_list.next = NULL;
256
257 if (llist_add(&cmd->ll_list, &cq->list)) {
258 data->func = null_ipi_cmd_end_io;
259 data->flags = 0;
260 __smp_call_function_single(cpu, data, 0);
261 }
262
263 put_cpu();
264} 230}
265 231
266#endif /* CONFIG_SMP */
267
268static inline void null_handle_cmd(struct nullb_cmd *cmd) 232static inline void null_handle_cmd(struct nullb_cmd *cmd)
269{ 233{
270 /* Complete IO by inline, softirq or timer */ 234 /* Complete IO by inline, softirq or timer */
271 switch (irqmode) { 235 switch (irqmode) {
272 case NULL_IRQ_NONE:
273 end_cmd(cmd);
274 break;
275 case NULL_IRQ_SOFTIRQ: 236 case NULL_IRQ_SOFTIRQ:
276#ifdef CONFIG_SMP 237 switch (queue_mode) {
277 null_cmd_end_ipi(cmd); 238 case NULL_Q_MQ:
278#else 239 blk_mq_complete_request(cmd->rq);
240 break;
241 case NULL_Q_RQ:
242 blk_complete_request(cmd->rq);
243 break;
244 case NULL_Q_BIO:
245 /*
246 * XXX: no proper submitting cpu information available.
247 */
248 end_cmd(cmd);
249 break;
250 }
251 break;
252 case NULL_IRQ_NONE:
279 end_cmd(cmd); 253 end_cmd(cmd);
280#endif
281 break; 254 break;
282 case NULL_IRQ_TIMER: 255 case NULL_IRQ_TIMER:
283 null_cmd_end_timer(cmd); 256 null_cmd_end_timer(cmd);
@@ -413,6 +386,7 @@ static struct blk_mq_ops null_mq_ops = {
413 .queue_rq = null_queue_rq, 386 .queue_rq = null_queue_rq,
414 .map_queue = blk_mq_map_queue, 387 .map_queue = blk_mq_map_queue,
415 .init_hctx = null_init_hctx, 388 .init_hctx = null_init_hctx,
389 .complete = null_softirq_done_fn,
416}; 390};
417 391
418static struct blk_mq_reg null_mq_reg = { 392static struct blk_mq_reg null_mq_reg = {
@@ -611,13 +585,6 @@ static int __init null_init(void)
611{ 585{
612 unsigned int i; 586 unsigned int i;
613 587
614#if !defined(CONFIG_SMP)
615 if (irqmode == NULL_IRQ_SOFTIRQ) {
616 pr_warn("null_blk: softirq completions not available.\n");
617 pr_warn("null_blk: using direct completions.\n");
618 irqmode = NULL_IRQ_NONE;
619 }
620#endif
621 if (bs > PAGE_SIZE) { 588 if (bs > PAGE_SIZE) {
622 pr_warn("null_blk: invalid block size\n"); 589 pr_warn("null_blk: invalid block size\n");
623 pr_warn("null_blk: defaults block size to %lu\n", PAGE_SIZE); 590 pr_warn("null_blk: defaults block size to %lu\n", PAGE_SIZE);