diff options
author | Tejun Heo <tj@kernel.org> | 2009-05-07 22:54:02 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-05-11 03:52:15 -0400 |
commit | 8a12c4a456c7ee261a85c2cbec835601e6aae05a (patch) | |
tree | 90142ec5d30b1a74ded14ac013408c7390caeb1b /drivers/block/hd.c | |
parent | 5b36ad6000ddea390aca3c3b67ead7616ace2ffc (diff) |
hd: dequeue and track in-flight request
hd has at most single request in flight. Till now, whenever it needs
to access the in-flight request it called elv_next_request(). This
patch makes hd track the in-flight request directly and dequeue it
when processing starts. The added complexity is minimal and this will
help future block layer changes.
[ Impact: dequeue in-flight request, one elv_next_request() per request ]
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/block/hd.c')
-rw-r--r-- | drivers/block/hd.c | 63 |
1 files changed, 40 insertions, 23 deletions
diff --git a/drivers/block/hd.c b/drivers/block/hd.c index a3b39940ce02..288ab63c1029 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c | |||
@@ -98,10 +98,9 @@ | |||
98 | 98 | ||
99 | static DEFINE_SPINLOCK(hd_lock); | 99 | static DEFINE_SPINLOCK(hd_lock); |
100 | static struct request_queue *hd_queue; | 100 | static struct request_queue *hd_queue; |
101 | static struct request *hd_req; | ||
101 | 102 | ||
102 | #define MAJOR_NR HD_MAJOR | 103 | #define MAJOR_NR HD_MAJOR |
103 | #define QUEUE (hd_queue) | ||
104 | #define CURRENT elv_next_request(hd_queue) | ||
105 | 104 | ||
106 | #define TIMEOUT_VALUE (6*HZ) | 105 | #define TIMEOUT_VALUE (6*HZ) |
107 | #define HD_DELAY 0 | 106 | #define HD_DELAY 0 |
@@ -195,11 +194,24 @@ static void __init hd_setup(char *str, int *ints) | |||
195 | NR_HD = hdind+1; | 194 | NR_HD = hdind+1; |
196 | } | 195 | } |
197 | 196 | ||
197 | static bool hd_end_request(int err, unsigned int bytes) | ||
198 | { | ||
199 | if (__blk_end_request(hd_req, err, bytes)) | ||
200 | return true; | ||
201 | hd_req = NULL; | ||
202 | return false; | ||
203 | } | ||
204 | |||
205 | static bool hd_end_request_cur(int err) | ||
206 | { | ||
207 | return hd_end_request(err, blk_rq_cur_bytes(hd_req)); | ||
208 | } | ||
209 | |||
198 | static void dump_status(const char *msg, unsigned int stat) | 210 | static void dump_status(const char *msg, unsigned int stat) |
199 | { | 211 | { |
200 | char *name = "hd?"; | 212 | char *name = "hd?"; |
201 | if (CURRENT) | 213 | if (hd_req) |
202 | name = CURRENT->rq_disk->disk_name; | 214 | name = hd_req->rq_disk->disk_name; |
203 | 215 | ||
204 | #ifdef VERBOSE_ERRORS | 216 | #ifdef VERBOSE_ERRORS |
205 | printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff); | 217 | printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff); |
@@ -227,8 +239,8 @@ static void dump_status(const char *msg, unsigned int stat) | |||
227 | if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { | 239 | if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { |
228 | printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), | 240 | printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), |
229 | inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); | 241 | inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); |
230 | if (CURRENT) | 242 | if (hd_req) |
231 | printk(", sector=%ld", blk_rq_pos(CURRENT)); | 243 | printk(", sector=%ld", blk_rq_pos(hd_req)); |
232 | } | 244 | } |
233 | printk("\n"); | 245 | printk("\n"); |
234 | } | 246 | } |
@@ -406,11 +418,12 @@ static void unexpected_hd_interrupt(void) | |||
406 | */ | 418 | */ |
407 | static void bad_rw_intr(void) | 419 | static void bad_rw_intr(void) |
408 | { | 420 | { |
409 | struct request *req = CURRENT; | 421 | struct request *req = hd_req; |
422 | |||
410 | if (req != NULL) { | 423 | if (req != NULL) { |
411 | struct hd_i_struct *disk = req->rq_disk->private_data; | 424 | struct hd_i_struct *disk = req->rq_disk->private_data; |
412 | if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { | 425 | if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { |
413 | __blk_end_request_cur(req, -EIO); | 426 | hd_end_request_cur(-EIO); |
414 | disk->special_op = disk->recalibrate = 1; | 427 | disk->special_op = disk->recalibrate = 1; |
415 | } else if (req->errors % RESET_FREQ == 0) | 428 | } else if (req->errors % RESET_FREQ == 0) |
416 | reset = 1; | 429 | reset = 1; |
@@ -454,14 +467,14 @@ static void read_intr(void) | |||
454 | return; | 467 | return; |
455 | 468 | ||
456 | ok_to_read: | 469 | ok_to_read: |
457 | req = CURRENT; | 470 | req = hd_req; |
458 | insw(HD_DATA, req->buffer, 256); | 471 | insw(HD_DATA, req->buffer, 256); |
459 | #ifdef DEBUG | 472 | #ifdef DEBUG |
460 | printk("%s: read: sector %ld, remaining = %u, buffer=%p\n", | 473 | printk("%s: read: sector %ld, remaining = %u, buffer=%p\n", |
461 | req->rq_disk->disk_name, blk_rq_pos(req) + 1, | 474 | req->rq_disk->disk_name, blk_rq_pos(req) + 1, |
462 | blk_rq_sectors(req) - 1, req->buffer+512); | 475 | blk_rq_sectors(req) - 1, req->buffer+512); |
463 | #endif | 476 | #endif |
464 | if (__blk_end_request(req, 0, 512)) { | 477 | if (hd_end_request(0, 512)) { |
465 | SET_HANDLER(&read_intr); | 478 | SET_HANDLER(&read_intr); |
466 | return; | 479 | return; |
467 | } | 480 | } |
@@ -475,7 +488,7 @@ ok_to_read: | |||
475 | 488 | ||
476 | static void write_intr(void) | 489 | static void write_intr(void) |
477 | { | 490 | { |
478 | struct request *req = CURRENT; | 491 | struct request *req = hd_req; |
479 | int i; | 492 | int i; |
480 | int retries = 100000; | 493 | int retries = 100000; |
481 | 494 | ||
@@ -494,7 +507,7 @@ static void write_intr(void) | |||
494 | return; | 507 | return; |
495 | 508 | ||
496 | ok_to_write: | 509 | ok_to_write: |
497 | if (__blk_end_request(req, 0, 512)) { | 510 | if (hd_end_request(0, 512)) { |
498 | SET_HANDLER(&write_intr); | 511 | SET_HANDLER(&write_intr); |
499 | outsw(HD_DATA, req->buffer, 256); | 512 | outsw(HD_DATA, req->buffer, 256); |
500 | return; | 513 | return; |
@@ -525,18 +538,18 @@ static void hd_times_out(unsigned long dummy) | |||
525 | 538 | ||
526 | do_hd = NULL; | 539 | do_hd = NULL; |
527 | 540 | ||
528 | if (!CURRENT) | 541 | if (!hd_req) |
529 | return; | 542 | return; |
530 | 543 | ||
531 | spin_lock_irq(hd_queue->queue_lock); | 544 | spin_lock_irq(hd_queue->queue_lock); |
532 | reset = 1; | 545 | reset = 1; |
533 | name = CURRENT->rq_disk->disk_name; | 546 | name = hd_req->rq_disk->disk_name; |
534 | printk("%s: timeout\n", name); | 547 | printk("%s: timeout\n", name); |
535 | if (++CURRENT->errors >= MAX_ERRORS) { | 548 | if (++hd_req->errors >= MAX_ERRORS) { |
536 | #ifdef DEBUG | 549 | #ifdef DEBUG |
537 | printk("%s: too many errors\n", name); | 550 | printk("%s: too many errors\n", name); |
538 | #endif | 551 | #endif |
539 | __blk_end_request_cur(CURRENT, -EIO); | 552 | hd_end_request_cur(-EIO); |
540 | } | 553 | } |
541 | hd_request(); | 554 | hd_request(); |
542 | spin_unlock_irq(hd_queue->queue_lock); | 555 | spin_unlock_irq(hd_queue->queue_lock); |
@@ -551,7 +564,7 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req) | |||
551 | } | 564 | } |
552 | if (disk->head > 16) { | 565 | if (disk->head > 16) { |
553 | printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name); | 566 | printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name); |
554 | __blk_end_request_cur(req, -EIO); | 567 | hd_end_request_cur(-EIO); |
555 | } | 568 | } |
556 | disk->special_op = 0; | 569 | disk->special_op = 0; |
557 | return 1; | 570 | return 1; |
@@ -578,11 +591,15 @@ static void hd_request(void) | |||
578 | repeat: | 591 | repeat: |
579 | del_timer(&device_timer); | 592 | del_timer(&device_timer); |
580 | 593 | ||
581 | req = CURRENT; | 594 | if (!hd_req) { |
582 | if (!req) { | 595 | hd_req = elv_next_request(hd_queue); |
583 | do_hd = NULL; | 596 | if (!hd_req) { |
584 | return; | 597 | do_hd = NULL; |
598 | return; | ||
599 | } | ||
600 | blkdev_dequeue_request(hd_req); | ||
585 | } | 601 | } |
602 | req = hd_req; | ||
586 | 603 | ||
587 | if (reset) { | 604 | if (reset) { |
588 | reset_hd(); | 605 | reset_hd(); |
@@ -595,7 +612,7 @@ repeat: | |||
595 | ((block+nsect) > get_capacity(req->rq_disk))) { | 612 | ((block+nsect) > get_capacity(req->rq_disk))) { |
596 | printk("%s: bad access: block=%d, count=%d\n", | 613 | printk("%s: bad access: block=%d, count=%d\n", |
597 | req->rq_disk->disk_name, block, nsect); | 614 | req->rq_disk->disk_name, block, nsect); |
598 | __blk_end_request_cur(req, -EIO); | 615 | hd_end_request_cur(-EIO); |
599 | goto repeat; | 616 | goto repeat; |
600 | } | 617 | } |
601 | 618 | ||
@@ -635,7 +652,7 @@ repeat: | |||
635 | break; | 652 | break; |
636 | default: | 653 | default: |
637 | printk("unknown hd-command\n"); | 654 | printk("unknown hd-command\n"); |
638 | __blk_end_request_cur(req, -EIO); | 655 | hd_end_request_cur(-EIO); |
639 | break; | 656 | break; |
640 | } | 657 | } |
641 | } | 658 | } |