diff options
Diffstat (limited to 'drivers/block/hd.c')
-rw-r--r-- | drivers/block/hd.c | 106 |
1 files changed, 55 insertions, 51 deletions
diff --git a/drivers/block/hd.c b/drivers/block/hd.c index baaa9e486e50..f65b3f369eb0 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", CURRENT->sector); | 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 | end_request(req, 0); | 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; |
@@ -452,37 +465,30 @@ static void read_intr(void) | |||
452 | bad_rw_intr(); | 465 | bad_rw_intr(); |
453 | hd_request(); | 466 | hd_request(); |
454 | return; | 467 | return; |
468 | |||
455 | ok_to_read: | 469 | ok_to_read: |
456 | req = CURRENT; | 470 | req = hd_req; |
457 | insw(HD_DATA, req->buffer, 256); | 471 | insw(HD_DATA, req->buffer, 256); |
458 | req->sector++; | ||
459 | req->buffer += 512; | ||
460 | req->errors = 0; | ||
461 | i = --req->nr_sectors; | ||
462 | --req->current_nr_sectors; | ||
463 | #ifdef DEBUG | 472 | #ifdef DEBUG |
464 | printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n", | 473 | printk("%s: read: sector %ld, remaining = %u, buffer=%p\n", |
465 | req->rq_disk->disk_name, req->sector, req->nr_sectors, | 474 | req->rq_disk->disk_name, blk_rq_pos(req) + 1, |
466 | req->buffer+512); | 475 | blk_rq_sectors(req) - 1, req->buffer+512); |
467 | #endif | 476 | #endif |
468 | if (req->current_nr_sectors <= 0) | 477 | if (hd_end_request(0, 512)) { |
469 | end_request(req, 1); | ||
470 | if (i > 0) { | ||
471 | SET_HANDLER(&read_intr); | 478 | SET_HANDLER(&read_intr); |
472 | return; | 479 | return; |
473 | } | 480 | } |
481 | |||
474 | (void) inb_p(HD_STATUS); | 482 | (void) inb_p(HD_STATUS); |
475 | #if (HD_DELAY > 0) | 483 | #if (HD_DELAY > 0) |
476 | last_req = read_timer(); | 484 | last_req = read_timer(); |
477 | #endif | 485 | #endif |
478 | if (elv_next_request(QUEUE)) | 486 | hd_request(); |
479 | hd_request(); | ||
480 | return; | ||
481 | } | 487 | } |
482 | 488 | ||
483 | static void write_intr(void) | 489 | static void write_intr(void) |
484 | { | 490 | { |
485 | struct request *req = CURRENT; | 491 | struct request *req = hd_req; |
486 | int i; | 492 | int i; |
487 | int retries = 100000; | 493 | int retries = 100000; |
488 | 494 | ||
@@ -492,30 +498,25 @@ static void write_intr(void) | |||
492 | continue; | 498 | continue; |
493 | if (!OK_STATUS(i)) | 499 | if (!OK_STATUS(i)) |
494 | break; | 500 | break; |
495 | if ((req->nr_sectors <= 1) || (i & DRQ_STAT)) | 501 | if ((blk_rq_sectors(req) <= 1) || (i & DRQ_STAT)) |
496 | goto ok_to_write; | 502 | goto ok_to_write; |
497 | } while (--retries > 0); | 503 | } while (--retries > 0); |
498 | dump_status("write_intr", i); | 504 | dump_status("write_intr", i); |
499 | bad_rw_intr(); | 505 | bad_rw_intr(); |
500 | hd_request(); | 506 | hd_request(); |
501 | return; | 507 | return; |
508 | |||
502 | ok_to_write: | 509 | ok_to_write: |
503 | req->sector++; | 510 | if (hd_end_request(0, 512)) { |
504 | i = --req->nr_sectors; | ||
505 | --req->current_nr_sectors; | ||
506 | req->buffer += 512; | ||
507 | if (!i || (req->bio && req->current_nr_sectors <= 0)) | ||
508 | end_request(req, 1); | ||
509 | if (i > 0) { | ||
510 | SET_HANDLER(&write_intr); | 511 | SET_HANDLER(&write_intr); |
511 | outsw(HD_DATA, req->buffer, 256); | 512 | outsw(HD_DATA, req->buffer, 256); |
512 | } else { | 513 | return; |
514 | } | ||
515 | |||
513 | #if (HD_DELAY > 0) | 516 | #if (HD_DELAY > 0) |
514 | last_req = read_timer(); | 517 | last_req = read_timer(); |
515 | #endif | 518 | #endif |
516 | hd_request(); | 519 | hd_request(); |
517 | } | ||
518 | return; | ||
519 | } | 520 | } |
520 | 521 | ||
521 | static void recal_intr(void) | 522 | static void recal_intr(void) |
@@ -537,18 +538,18 @@ static void hd_times_out(unsigned long dummy) | |||
537 | 538 | ||
538 | do_hd = NULL; | 539 | do_hd = NULL; |
539 | 540 | ||
540 | if (!CURRENT) | 541 | if (!hd_req) |
541 | return; | 542 | return; |
542 | 543 | ||
543 | spin_lock_irq(hd_queue->queue_lock); | 544 | spin_lock_irq(hd_queue->queue_lock); |
544 | reset = 1; | 545 | reset = 1; |
545 | name = CURRENT->rq_disk->disk_name; | 546 | name = hd_req->rq_disk->disk_name; |
546 | printk("%s: timeout\n", name); | 547 | printk("%s: timeout\n", name); |
547 | if (++CURRENT->errors >= MAX_ERRORS) { | 548 | if (++hd_req->errors >= MAX_ERRORS) { |
548 | #ifdef DEBUG | 549 | #ifdef DEBUG |
549 | printk("%s: too many errors\n", name); | 550 | printk("%s: too many errors\n", name); |
550 | #endif | 551 | #endif |
551 | end_request(CURRENT, 0); | 552 | hd_end_request_cur(-EIO); |
552 | } | 553 | } |
553 | hd_request(); | 554 | hd_request(); |
554 | spin_unlock_irq(hd_queue->queue_lock); | 555 | spin_unlock_irq(hd_queue->queue_lock); |
@@ -563,7 +564,7 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req) | |||
563 | } | 564 | } |
564 | if (disk->head > 16) { | 565 | if (disk->head > 16) { |
565 | 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); |
566 | end_request(req, 0); | 567 | hd_end_request_cur(-EIO); |
567 | } | 568 | } |
568 | disk->special_op = 0; | 569 | disk->special_op = 0; |
569 | return 1; | 570 | return 1; |
@@ -590,24 +591,27 @@ static void hd_request(void) | |||
590 | repeat: | 591 | repeat: |
591 | del_timer(&device_timer); | 592 | del_timer(&device_timer); |
592 | 593 | ||
593 | req = CURRENT; | 594 | if (!hd_req) { |
594 | if (!req) { | 595 | hd_req = blk_fetch_request(hd_queue); |
595 | do_hd = NULL; | 596 | if (!hd_req) { |
596 | return; | 597 | do_hd = NULL; |
598 | return; | ||
599 | } | ||
597 | } | 600 | } |
601 | req = hd_req; | ||
598 | 602 | ||
599 | if (reset) { | 603 | if (reset) { |
600 | reset_hd(); | 604 | reset_hd(); |
601 | return; | 605 | return; |
602 | } | 606 | } |
603 | disk = req->rq_disk->private_data; | 607 | disk = req->rq_disk->private_data; |
604 | block = req->sector; | 608 | block = blk_rq_pos(req); |
605 | nsect = req->nr_sectors; | 609 | nsect = blk_rq_sectors(req); |
606 | if (block >= get_capacity(req->rq_disk) || | 610 | if (block >= get_capacity(req->rq_disk) || |
607 | ((block+nsect) > get_capacity(req->rq_disk))) { | 611 | ((block+nsect) > get_capacity(req->rq_disk))) { |
608 | printk("%s: bad access: block=%d, count=%d\n", | 612 | printk("%s: bad access: block=%d, count=%d\n", |
609 | req->rq_disk->disk_name, block, nsect); | 613 | req->rq_disk->disk_name, block, nsect); |
610 | end_request(req, 0); | 614 | hd_end_request_cur(-EIO); |
611 | goto repeat; | 615 | goto repeat; |
612 | } | 616 | } |
613 | 617 | ||
@@ -647,7 +651,7 @@ repeat: | |||
647 | break; | 651 | break; |
648 | default: | 652 | default: |
649 | printk("unknown hd-command\n"); | 653 | printk("unknown hd-command\n"); |
650 | end_request(req, 0); | 654 | hd_end_request_cur(-EIO); |
651 | break; | 655 | break; |
652 | } | 656 | } |
653 | } | 657 | } |
@@ -720,7 +724,7 @@ static int __init hd_init(void) | |||
720 | blk_queue_max_sectors(hd_queue, 255); | 724 | blk_queue_max_sectors(hd_queue, 255); |
721 | init_timer(&device_timer); | 725 | init_timer(&device_timer); |
722 | device_timer.function = hd_times_out; | 726 | device_timer.function = hd_times_out; |
723 | blk_queue_hardsect_size(hd_queue, 512); | 727 | blk_queue_logical_block_size(hd_queue, 512); |
724 | 728 | ||
725 | if (!NR_HD) { | 729 | if (!NR_HD) { |
726 | /* | 730 | /* |