aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-05-07 22:54:02 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-05-11 03:52:15 -0400
commit8a12c4a456c7ee261a85c2cbec835601e6aae05a (patch)
tree90142ec5d30b1a74ded14ac013408c7390caeb1b /drivers
parent5b36ad6000ddea390aca3c3b67ead7616ace2ffc (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')
-rw-r--r--drivers/block/hd.c63
1 files changed, 40 insertions, 23 deletions
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index a3b39940ce0..288ab63c102 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -98,10 +98,9 @@
98 98
99static DEFINE_SPINLOCK(hd_lock); 99static DEFINE_SPINLOCK(hd_lock);
100static struct request_queue *hd_queue; 100static struct request_queue *hd_queue;
101static 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
197static 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
205static bool hd_end_request_cur(int err)
206{
207 return hd_end_request(err, blk_rq_cur_bytes(hd_req));
208}
209
198static void dump_status(const char *msg, unsigned int stat) 210static 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 */
407static void bad_rw_intr(void) 419static 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
456ok_to_read: 469ok_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
476static void write_intr(void) 489static 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
496ok_to_write: 509ok_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)
578repeat: 591repeat:
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 }