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 | |
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')
-rw-r--r-- | drivers/ide/ide-atapi.c | 57 | ||||
-rw-r--r-- | drivers/ide/ide-tape.c | 32 |
2 files changed, 35 insertions, 54 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; |
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index cafc67d9e2e8..cb942a9b580f 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -297,19 +297,15 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) | |||
297 | return tape; | 297 | return tape; |
298 | } | 298 | } |
299 | 299 | ||
300 | static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | 300 | static int idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, |
301 | unsigned int bcount) | 301 | unsigned int bcount) |
302 | { | 302 | { |
303 | struct idetape_bh *bh = pc->bh; | 303 | struct idetape_bh *bh = pc->bh; |
304 | int count; | 304 | int count; |
305 | 305 | ||
306 | while (bcount) { | 306 | while (bcount) { |
307 | if (bh == NULL) { | 307 | if (bh == NULL) |
308 | printk(KERN_ERR "ide-tape: bh == NULL in " | 308 | break; |
309 | "idetape_input_buffers\n"); | ||
310 | ide_pad_transfer(drive, 0, bcount); | ||
311 | return; | ||
312 | } | ||
313 | count = min( | 309 | count = min( |
314 | (unsigned int)(bh->b_size - atomic_read(&bh->b_count)), | 310 | (unsigned int)(bh->b_size - atomic_read(&bh->b_count)), |
315 | bcount); | 311 | bcount); |
@@ -323,21 +319,21 @@ static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | |||
323 | atomic_set(&bh->b_count, 0); | 319 | atomic_set(&bh->b_count, 0); |
324 | } | 320 | } |
325 | } | 321 | } |
322 | |||
326 | pc->bh = bh; | 323 | pc->bh = bh; |
324 | |||
325 | return bcount; | ||
327 | } | 326 | } |
328 | 327 | ||
329 | static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | 328 | static int idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, |
330 | unsigned int bcount) | 329 | unsigned int bcount) |
331 | { | 330 | { |
332 | struct idetape_bh *bh = pc->bh; | 331 | struct idetape_bh *bh = pc->bh; |
333 | int count; | 332 | int count; |
334 | 333 | ||
335 | while (bcount) { | 334 | while (bcount) { |
336 | if (bh == NULL) { | 335 | if (bh == NULL) |
337 | printk(KERN_ERR "ide-tape: bh == NULL in %s\n", | 336 | break; |
338 | __func__); | ||
339 | return; | ||
340 | } | ||
341 | count = min((unsigned int)pc->b_count, (unsigned int)bcount); | 337 | count = min((unsigned int)pc->b_count, (unsigned int)bcount); |
342 | drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count); | 338 | drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count); |
343 | bcount -= count; | 339 | bcount -= count; |
@@ -352,6 +348,8 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | |||
352 | } | 348 | } |
353 | } | 349 | } |
354 | } | 350 | } |
351 | |||
352 | return bcount; | ||
355 | } | 353 | } |
356 | 354 | ||
357 | static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) | 355 | static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) |
@@ -563,12 +561,14 @@ static void ide_tape_handle_dsc(ide_drive_t *drive) | |||
563 | static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | 561 | static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, |
564 | unsigned int bcount, int write) | 562 | unsigned int bcount, int write) |
565 | { | 563 | { |
564 | unsigned int bleft; | ||
565 | |||
566 | if (write) | 566 | if (write) |
567 | idetape_output_buffers(drive, pc, bcount); | 567 | bleft = idetape_output_buffers(drive, pc, bcount); |
568 | else | 568 | else |
569 | idetape_input_buffers(drive, pc, bcount); | 569 | bleft = idetape_input_buffers(drive, pc, bcount); |
570 | 570 | ||
571 | return bcount; | 571 | return bcount - bleft; |
572 | } | 572 | } |
573 | 573 | ||
574 | /* | 574 | /* |