diff options
author | Tejun Heo <htejun@gmail.com> | 2008-01-26 14:13:10 -0500 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-01-26 14:13:10 -0500 |
commit | 35cf2b94d0ecb7034cfa05dd725721538bbb83fc (patch) | |
tree | 6c3681f06b078626aeeb8de1e28bbdd458f95c70 /drivers/ide | |
parent | 63c4467805c9b23231d8bc9b61305b2013f9fea2 (diff) |
ide: fix ->io_32bit race in ide_taskfile_ioctl()
In ide_taskfile_ioctl(), there was a race condition involving
drive->io_32bit. It was cleared and restored during ioctl
requests but there was no synchronization with other requests.
So, other requests could execute with the altered ->io_32bit
setting or updated drive->io_32bit could be overwritten by
ide_taskfile_ioctl().
This patch adds IDE_TFLAG_IO_16BIT flag to indicate to
ide_pio_datablock() that 16-bit I/O is needed regardless of
drive->io_32bit settting.
Bart:
- ported it over recent IDE changes
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide')
-rw-r--r-- | drivers/ide/ide-taskfile.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 3ecafab8f54e..b72a9aea7a51 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
@@ -346,9 +346,18 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write) | |||
346 | static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, | 346 | static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, |
347 | unsigned int write) | 347 | unsigned int write) |
348 | { | 348 | { |
349 | u8 saved_io_32bit = drive->io_32bit; | ||
350 | |||
349 | if (rq->bio) /* fs request */ | 351 | if (rq->bio) /* fs request */ |
350 | rq->errors = 0; | 352 | rq->errors = 0; |
351 | 353 | ||
354 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { | ||
355 | ide_task_t *task = rq->special; | ||
356 | |||
357 | if (task->tf_flags & IDE_TFLAG_IO_16BIT) | ||
358 | drive->io_32bit = 0; | ||
359 | } | ||
360 | |||
352 | touch_softlockup_watchdog(); | 361 | touch_softlockup_watchdog(); |
353 | 362 | ||
354 | switch (drive->hwif->data_phase) { | 363 | switch (drive->hwif->data_phase) { |
@@ -360,6 +369,8 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, | |||
360 | ide_pio_sector(drive, write); | 369 | ide_pio_sector(drive, write); |
361 | break; | 370 | break; |
362 | } | 371 | } |
372 | |||
373 | drive->io_32bit = saved_io_32bit; | ||
363 | } | 374 | } |
364 | 375 | ||
365 | static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, | 376 | static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, |
@@ -555,7 +566,6 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) | |||
555 | unsigned int taskin = 0; | 566 | unsigned int taskin = 0; |
556 | unsigned int taskout = 0; | 567 | unsigned int taskout = 0; |
557 | u16 nsect = 0; | 568 | u16 nsect = 0; |
558 | u8 io_32bit = drive->io_32bit; | ||
559 | char __user *buf = (char __user *)arg; | 569 | char __user *buf = (char __user *)arg; |
560 | 570 | ||
561 | // printk("IDE Taskfile ...\n"); | 571 | // printk("IDE Taskfile ...\n"); |
@@ -608,7 +618,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) | |||
608 | 618 | ||
609 | args.data_phase = req_task->data_phase; | 619 | args.data_phase = req_task->data_phase; |
610 | 620 | ||
611 | args.tf_flags = IDE_TFLAG_OUT_DEVICE; | 621 | args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_OUT_DEVICE; |
612 | if (drive->addressing == 1) | 622 | if (drive->addressing == 1) |
613 | args.tf_flags |= IDE_TFLAG_LBA48; | 623 | args.tf_flags |= IDE_TFLAG_LBA48; |
614 | 624 | ||
@@ -646,7 +656,6 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) | |||
646 | if (req_task->in_flags.b.data) | 656 | if (req_task->in_flags.b.data) |
647 | args.tf_flags |= IDE_TFLAG_IN_DATA; | 657 | args.tf_flags |= IDE_TFLAG_IN_DATA; |
648 | 658 | ||
649 | drive->io_32bit = 0; | ||
650 | switch(req_task->data_phase) { | 659 | switch(req_task->data_phase) { |
651 | case TASKFILE_MULTI_OUT: | 660 | case TASKFILE_MULTI_OUT: |
652 | if (!drive->mult_count) { | 661 | if (!drive->mult_count) { |
@@ -742,8 +751,6 @@ abort: | |||
742 | 751 | ||
743 | // printk("IDE Taskfile ioctl ended. rc = %i\n", err); | 752 | // printk("IDE Taskfile ioctl ended. rc = %i\n", err); |
744 | 753 | ||
745 | drive->io_32bit = io_32bit; | ||
746 | |||
747 | return err; | 754 | return err; |
748 | } | 755 | } |
749 | #endif | 756 | #endif |