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: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent 9f5af4d6
...@@ -110,13 +110,6 @@ int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, ...@@ -110,13 +110,6 @@ int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
} }
} }
if (bcount) {
printk(KERN_ERR "%s: %d leftover bytes, %s\n", drive->name,
bcount, write ? "padding with zeros"
: "discarding data");
ide_pad_transfer(drive, write, bcount);
}
return done; return done;
} }
EXPORT_SYMBOL_GPL(ide_io_buffers); EXPORT_SYMBOL_GPL(ide_io_buffers);
...@@ -330,9 +323,10 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) ...@@ -330,9 +323,10 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
struct request *rq = hwif->rq; struct request *rq = hwif->rq;
const struct ide_tp_ops *tp_ops = hwif->tp_ops; const struct ide_tp_ops *tp_ops = hwif->tp_ops;
xfer_func_t *xferfunc; xfer_func_t *xferfunc;
unsigned int timeout, temp; unsigned int timeout, done;
u16 bcount; u16 bcount;
u8 stat, ireason, dsc = 0; u8 stat, ireason, dsc = 0;
u8 write = !!(pc->flags & PC_FLAG_WRITING);
debug_log("Enter %s - interrupt handler\n", __func__); debug_log("Enter %s - interrupt handler\n", __func__);
...@@ -441,8 +435,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) ...@@ -441,8 +435,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
return ide_do_reset(drive); return ide_do_reset(drive);
} }
if (((ireason & ATAPI_IO) == ATAPI_IO) == if (((ireason & ATAPI_IO) == ATAPI_IO) == write) {
!!(pc->flags & PC_FLAG_WRITING)) {
/* Hopefully, we will never get here */ /* Hopefully, we will never get here */
printk(KERN_ERR "%s: We wanted to %s, but the device wants us " printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
"to %s!\n", drive->name, "to %s!\n", drive->name,
...@@ -451,45 +444,33 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) ...@@ -451,45 +444,33 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
return ide_do_reset(drive); return ide_do_reset(drive);
} }
if (!(pc->flags & PC_FLAG_WRITING)) { xferfunc = write ? tp_ops->output_data : tp_ops->input_data;
/* Reading - Check that we have enough space */
temp = pc->xferred + bcount;
if (temp > pc->req_xfer) {
if (temp > pc->buf_size) {
printk(KERN_ERR "%s: The device wants to send "
"us more data than expected - "
"discarding data\n",
drive->name);
ide_pad_transfer(drive, 0, bcount);
goto next_irq;
}
debug_log("The device wants to send us more data than "
"expected - allowing transfer\n");
}
xferfunc = tp_ops->input_data;
} else
xferfunc = tp_ops->output_data;
if ((drive->media == ide_floppy && !pc->buf) || if ((drive->media == ide_floppy && !pc->buf) ||
(drive->media == ide_tape && pc->bh)) { (drive->media == ide_tape && pc->bh)) {
int done = drive->pc_io_buffers(drive, pc, bcount, done = drive->pc_io_buffers(drive, pc, bcount, write);
!!(pc->flags & PC_FLAG_WRITING));
/* FIXME: don't do partial completions */ /* FIXME: don't do partial completions */
if (drive->media == ide_floppy) if (drive->media == ide_floppy)
ide_complete_rq(drive, 0, ide_complete_rq(drive, 0,
done ? done : ide_rq_bytes(rq)); done ? done : ide_rq_bytes(rq));
} else } else {
xferfunc(drive, NULL, pc->cur_pos, bcount); done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred);
xferfunc(drive, NULL, pc->cur_pos, done);
}
/* Update the current position */ /* Update the current position */
pc->xferred += bcount; pc->xferred += done;
pc->cur_pos += bcount; pc->cur_pos += done;
bcount -= done;
if (bcount)
ide_pad_transfer(drive, write, bcount);
debug_log("[cmd %x] transferred %d bytes, padded %d bytes\n",
rq->cmd[0], done, bcount);
debug_log("[cmd %x] transferred %d bytes on that intr.\n",
rq->cmd[0], bcount);
next_irq:
/* And set the interrupt handler again */ /* And set the interrupt handler again */
ide_set_handler(drive, ide_pc_intr, timeout); ide_set_handler(drive, ide_pc_intr, timeout);
return ide_started; return ide_started;
......
...@@ -297,19 +297,15 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) ...@@ -297,19 +297,15 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
return tape; return tape;
} }
static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, static int idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
unsigned int bcount) unsigned int bcount)
{ {
struct idetape_bh *bh = pc->bh; struct idetape_bh *bh = pc->bh;
int count; int count;
while (bcount) { while (bcount) {
if (bh == NULL) { if (bh == NULL)
printk(KERN_ERR "ide-tape: bh == NULL in " break;
"idetape_input_buffers\n");
ide_pad_transfer(drive, 0, bcount);
return;
}
count = min( count = min(
(unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
bcount); bcount);
...@@ -323,21 +319,21 @@ static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, ...@@ -323,21 +319,21 @@ static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
atomic_set(&bh->b_count, 0); atomic_set(&bh->b_count, 0);
} }
} }
pc->bh = bh; pc->bh = bh;
return bcount;
} }
static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, static int idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
unsigned int bcount) unsigned int bcount)
{ {
struct idetape_bh *bh = pc->bh; struct idetape_bh *bh = pc->bh;
int count; int count;
while (bcount) { while (bcount) {
if (bh == NULL) { if (bh == NULL)
printk(KERN_ERR "ide-tape: bh == NULL in %s\n", break;
__func__);
return;
}
count = min((unsigned int)pc->b_count, (unsigned int)bcount); count = min((unsigned int)pc->b_count, (unsigned int)bcount);
drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count); drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count);
bcount -= count; bcount -= count;
...@@ -352,6 +348,8 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, ...@@ -352,6 +348,8 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
} }
} }
} }
return bcount;
} }
static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) 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,12 +561,14 @@ static void ide_tape_handle_dsc(ide_drive_t *drive)
static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
unsigned int bcount, int write) unsigned int bcount, int write)
{ {
unsigned int bleft;
if (write) if (write)
idetape_output_buffers(drive, pc, bcount); bleft = idetape_output_buffers(drive, pc, bcount);
else else
idetape_input_buffers(drive, pc, bcount); bleft = idetape_input_buffers(drive, pc, bcount);
return bcount; return bcount - bleft;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment