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>
This commit is contained in:
Родитель
9f5af4d667
Коммит
d93bc4521c
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
if (write)
|
unsigned int bleft;
|
||||||
idetape_output_buffers(drive, pc, bcount);
|
|
||||||
else
|
|
||||||
idetape_input_buffers(drive, pc, bcount);
|
|
||||||
|
|
||||||
return bcount;
|
if (write)
|
||||||
|
bleft = idetape_output_buffers(drive, pc, bcount);
|
||||||
|
else
|
||||||
|
bleft = idetape_input_buffers(drive, pc, bcount);
|
||||||
|
|
||||||
|
return bcount - bleft;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче