diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-03-31 14:15:26 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-03-31 14:15:26 -0400 |
commit | d93bc4521c80e9d87767779814e88f6d725453d7 (patch) | |
tree | 6c373208132f687e4ffb31db6c60e2a8638f6080 /drivers/ide/ide-atapi.c | |
parent | 9f5af4d667a6d4ebd66019b4b26b445ddbae6d6c (diff) |
ide-{floppy,tape}: fix padding for PIO transfers
* Return number of bytes left to transfer from idetape_{in,out}put_buffers()
and number of bytes done from ide_tape_io_buffers().
* Fix padding for PIO transfers in ide_pc_intr() so read/write buffers are
always completely processed and then the transfer is padded if necessary.
* Remove invalid error messages.
* Remove now superfluous padding from ide{_io_buffers,tape_input_buffers}().
While at it:
* Set pc->bh to NULL in idetape_input_buffers() after all bh-s are done.
* Cache !!(pc->flags & PC_FLAG_WRITING) in local variable in ide_pc_intr().
Cc: Borislav Petkov <petkovbb@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-atapi.c')
-rw-r--r-- | drivers/ide/ide-atapi.c | 57 |
1 files changed, 19 insertions, 38 deletions
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 3f3fc7c7b2fe..40f413b20bd8 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c | |||
@@ -110,13 +110,6 @@ int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | |||
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
113 | if (bcount) { | ||
114 | printk(KERN_ERR "%s: %d leftover bytes, %s\n", drive->name, | ||
115 | bcount, write ? "padding with zeros" | ||
116 | : "discarding data"); | ||
117 | ide_pad_transfer(drive, write, bcount); | ||
118 | } | ||
119 | |||
120 | return done; | 113 | return done; |
121 | } | 114 | } |
122 | EXPORT_SYMBOL_GPL(ide_io_buffers); | 115 | EXPORT_SYMBOL_GPL(ide_io_buffers); |
@@ -330,9 +323,10 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
330 | struct request *rq = hwif->rq; | 323 | struct request *rq = hwif->rq; |
331 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | 324 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; |
332 | xfer_func_t *xferfunc; | 325 | xfer_func_t *xferfunc; |
333 | unsigned int timeout, temp; | 326 | unsigned int timeout, done; |
334 | u16 bcount; | 327 | u16 bcount; |
335 | u8 stat, ireason, dsc = 0; | 328 | u8 stat, ireason, dsc = 0; |
329 | u8 write = !!(pc->flags & PC_FLAG_WRITING); | ||
336 | 330 | ||
337 | debug_log("Enter %s - interrupt handler\n", __func__); | 331 | debug_log("Enter %s - interrupt handler\n", __func__); |
338 | 332 | ||
@@ -441,8 +435,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
441 | return ide_do_reset(drive); | 435 | return ide_do_reset(drive); |
442 | } | 436 | } |
443 | 437 | ||
444 | if (((ireason & ATAPI_IO) == ATAPI_IO) == | 438 | if (((ireason & ATAPI_IO) == ATAPI_IO) == write) { |
445 | !!(pc->flags & PC_FLAG_WRITING)) { | ||
446 | /* Hopefully, we will never get here */ | 439 | /* Hopefully, we will never get here */ |
447 | printk(KERN_ERR "%s: We wanted to %s, but the device wants us " | 440 | printk(KERN_ERR "%s: We wanted to %s, but the device wants us " |
448 | "to %s!\n", drive->name, | 441 | "to %s!\n", drive->name, |
@@ -451,45 +444,33 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
451 | return ide_do_reset(drive); | 444 | return ide_do_reset(drive); |
452 | } | 445 | } |
453 | 446 | ||
454 | if (!(pc->flags & PC_FLAG_WRITING)) { | 447 | xferfunc = write ? tp_ops->output_data : tp_ops->input_data; |
455 | /* Reading - Check that we have enough space */ | ||
456 | temp = pc->xferred + bcount; | ||
457 | if (temp > pc->req_xfer) { | ||
458 | if (temp > pc->buf_size) { | ||
459 | printk(KERN_ERR "%s: The device wants to send " | ||
460 | "us more data than expected - " | ||
461 | "discarding data\n", | ||
462 | drive->name); | ||
463 | |||
464 | ide_pad_transfer(drive, 0, bcount); | ||
465 | goto next_irq; | ||
466 | } | ||
467 | debug_log("The device wants to send us more data than " | ||
468 | "expected - allowing transfer\n"); | ||
469 | } | ||
470 | xferfunc = tp_ops->input_data; | ||
471 | } else | ||
472 | xferfunc = tp_ops->output_data; | ||
473 | 448 | ||
474 | if ((drive->media == ide_floppy && !pc->buf) || | 449 | if ((drive->media == ide_floppy && !pc->buf) || |
475 | (drive->media == ide_tape && pc->bh)) { | 450 | (drive->media == ide_tape && pc->bh)) { |
476 | int done = drive->pc_io_buffers(drive, pc, bcount, | 451 | done = drive->pc_io_buffers(drive, pc, bcount, write); |
477 | !!(pc->flags & PC_FLAG_WRITING)); | ||
478 | 452 | ||
479 | /* FIXME: don't do partial completions */ | 453 | /* FIXME: don't do partial completions */ |
480 | if (drive->media == ide_floppy) | 454 | if (drive->media == ide_floppy) |
481 | ide_complete_rq(drive, 0, | 455 | ide_complete_rq(drive, 0, |
482 | done ? done : ide_rq_bytes(rq)); | 456 | done ? done : ide_rq_bytes(rq)); |
483 | } else | 457 | } else { |
484 | xferfunc(drive, NULL, pc->cur_pos, bcount); | 458 | done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred); |
459 | xferfunc(drive, NULL, pc->cur_pos, done); | ||
460 | } | ||
485 | 461 | ||
486 | /* Update the current position */ | 462 | /* Update the current position */ |
487 | pc->xferred += bcount; | 463 | pc->xferred += done; |
488 | pc->cur_pos += bcount; | 464 | pc->cur_pos += done; |
465 | |||
466 | bcount -= done; | ||
467 | |||
468 | if (bcount) | ||
469 | ide_pad_transfer(drive, write, bcount); | ||
470 | |||
471 | debug_log("[cmd %x] transferred %d bytes, padded %d bytes\n", | ||
472 | rq->cmd[0], done, bcount); | ||
489 | 473 | ||
490 | debug_log("[cmd %x] transferred %d bytes on that intr.\n", | ||
491 | rq->cmd[0], bcount); | ||
492 | next_irq: | ||
493 | /* And set the interrupt handler again */ | 474 | /* And set the interrupt handler again */ |
494 | ide_set_handler(drive, ide_pc_intr, timeout); | 475 | ide_set_handler(drive, ide_pc_intr, timeout); |
495 | return ide_started; | 476 | return ide_started; |