aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBorislav Petkov <petkovbb@gmail.com>2009-07-22 02:08:23 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-07 13:42:57 -0400
commit6f3848ac2399faac0be3f26648bf1d7a644a8242 (patch)
treefa265664488af88238ea88f712ae0827e124b877 /drivers
parente972d7027c0fb7055f5f2fe02d662c9528063bef (diff)
ide-tape: fix handling of postponed rqs
ide-tape used to hit [ 58.614854] ide-tape: ht0: BUG: Two DSC requests queued! due to the fact that another rq was being issued while the driver was waiting for DSC to get set for the device executing ATAPI commands which set the DSC to 1 to indicate completion. Here's a sample output of that case: issue REZERO_UNIT [ 143.088505] ide-tape: ide_tape_issue_pc: retry #0, cmd: 0x01 [ 143.095122] ide: Enter ide_pc_intr - interrupt handler [ 143.096118] ide: Packet command completed, 0 bytes transferred [ 143.106319] ide-tape: ide_tape_callback: cmd: 0x1, dsc: 1, err: 0 [ 143.112601] ide-tape: idetape_postpone_request: cmd: 0x1, dsc_poll_freq: 2000 we stall the ide-tape queue here waiting for DSC [ 143.119936] ide-tape: ide_tape_read_position: enter [ 145.119019] ide-tape: idetape_do_request: sector: 4294967295, nr_sectors: 0 and issue the new READ_POSITION rq and hit the check. [ 145.126247] ide-tape: ht0: BUG: Two DSC requests queued! [ 145.131748] ide-tape: ide_tape_read_position: BOP - No [ 145.137059] ide-tape: ide_tape_read_position: EOP - No Also, ->postponed_rq used to point to that postponed request. To make things worse, in certain circumstances the rq it was pointing to got replaced unterneath it by swiftly reusing the same rq from the mempool of the block layer practically confusing stuff even more. However, we don't need to keep a pointer to that rq but simply wait for DSC to be set first before issuing the follow-up request in the drive's queue. In order to do that, we make idetape_do_request() first check the DSC and if not set, we stall the drive queue giving the other device on that IDE channel a chance. Signed-off-by: Borislav Petkov <petkovbb@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/ide-tape.c33
1 files changed, 11 insertions, 22 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 3468ece98496..7b2032bc357b 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -155,7 +155,8 @@ typedef struct ide_tape_obj {
155 * other device. Note that at most we will have only one DSC (usually 155 * other device. Note that at most we will have only one DSC (usually
156 * data transfer) request in the device request queue. 156 * data transfer) request in the device request queue.
157 */ 157 */
158 struct request *postponed_rq; 158 bool postponed_rq;
159
159 /* The time in which we started polling for DSC */ 160 /* The time in which we started polling for DSC */
160 unsigned long dsc_polling_start; 161 unsigned long dsc_polling_start;
161 /* Timer used to poll for dsc */ 162 /* Timer used to poll for dsc */
@@ -372,15 +373,14 @@ static int ide_tape_callback(ide_drive_t *drive, int dsc)
372 * Postpone the current request so that ide.c will be able to service requests 373 * Postpone the current request so that ide.c will be able to service requests
373 * from another device on the same port while we are polling for DSC. 374 * from another device on the same port while we are polling for DSC.
374 */ 375 */
375static void idetape_postpone_request(ide_drive_t *drive) 376static void ide_tape_stall_queue(ide_drive_t *drive)
376{ 377{
377 idetape_tape_t *tape = drive->driver_data; 378 idetape_tape_t *tape = drive->driver_data;
378 struct request *rq = drive->hwif->rq;
379 379
380 ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%x, dsc_poll_freq: %lu", 380 ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%x, dsc_poll_freq: %lu",
381 rq->cmd[0], tape->dsc_poll_freq); 381 drive->hwif->rq->cmd[0], tape->dsc_poll_freq);
382 382
383 tape->postponed_rq = rq; 383 tape->postponed_rq = true;
384 384
385 ide_stall_queue(drive, tape->dsc_poll_freq); 385 ide_stall_queue(drive, tape->dsc_poll_freq);
386} 386}
@@ -394,7 +394,7 @@ static void ide_tape_handle_dsc(ide_drive_t *drive)
394 tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST; 394 tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST;
395 tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT; 395 tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT;
396 /* Allow ide.c to handle other requests */ 396 /* Allow ide.c to handle other requests */
397 idetape_postpone_request(drive); 397 ide_tape_stall_queue(drive);
398} 398}
399 399
400/* 400/*
@@ -567,7 +567,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
567 ide_hwif_t *hwif = drive->hwif; 567 ide_hwif_t *hwif = drive->hwif;
568 idetape_tape_t *tape = drive->driver_data; 568 idetape_tape_t *tape = drive->driver_data;
569 struct ide_atapi_pc *pc = NULL; 569 struct ide_atapi_pc *pc = NULL;
570 struct request *postponed_rq = tape->postponed_rq;
571 struct ide_cmd cmd; 570 struct ide_cmd cmd;
572 u8 stat; 571 u8 stat;
573 572
@@ -583,18 +582,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
583 goto out; 582 goto out;
584 } 583 }
585 584
586 if (postponed_rq != NULL)
587 if (rq != postponed_rq) {
588 printk(KERN_ERR "ide-tape: ide-tape.c bug - "
589 "Two DSC requests were queued\n");
590 drive->failed_pc = NULL;
591 rq->errors = 0;
592 ide_complete_rq(drive, 0, blk_rq_bytes(rq));
593 return ide_stopped;
594 }
595
596 tape->postponed_rq = NULL;
597
598 /* 585 /*
599 * If the tape is still busy, postpone our request and service 586 * If the tape is still busy, postpone our request and service
600 * the other device meanwhile. 587 * the other device meanwhile.
@@ -612,7 +599,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
612 599
613 if (!(drive->atapi_flags & IDE_AFLAG_IGNORE_DSC) && 600 if (!(drive->atapi_flags & IDE_AFLAG_IGNORE_DSC) &&
614 !(stat & ATA_DSC)) { 601 !(stat & ATA_DSC)) {
615 if (postponed_rq == NULL) { 602 if (!tape->postponed_rq) {
616 tape->dsc_polling_start = jiffies; 603 tape->dsc_polling_start = jiffies;
617 tape->dsc_poll_freq = tape->best_dsc_rw_freq; 604 tape->dsc_poll_freq = tape->best_dsc_rw_freq;
618 tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT; 605 tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT;
@@ -629,10 +616,12 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
629 tape->dsc_polling_start + 616 tape->dsc_polling_start +
630 IDETAPE_DSC_MA_THRESHOLD)) 617 IDETAPE_DSC_MA_THRESHOLD))
631 tape->dsc_poll_freq = IDETAPE_DSC_MA_SLOW; 618 tape->dsc_poll_freq = IDETAPE_DSC_MA_SLOW;
632 idetape_postpone_request(drive); 619 ide_tape_stall_queue(drive);
633 return ide_stopped; 620 return ide_stopped;
634 } else 621 } else {
635 drive->atapi_flags &= ~IDE_AFLAG_IGNORE_DSC; 622 drive->atapi_flags &= ~IDE_AFLAG_IGNORE_DSC;
623 tape->postponed_rq = false;
624 }
636 625
637 if (rq->cmd[13] & REQ_IDETAPE_READ) { 626 if (rq->cmd[13] & REQ_IDETAPE_READ) {
638 pc = &tape->queued_pc; 627 pc = &tape->queued_pc;