ide: allow ide_dev_read_id() to be called from the IRQ context
* Un-static __ide_wait_stat(). * Allow ide_dev_read_id() helper to be called from the IRQ context by adding irq_ctx flag and using mdelay()/__ide_wait_stat() when needed. * Switch ide_driveid_update() to set irq_ctx flag. This change is needed for the consecutive patch which fixes races in handling of user-space SET XFER commands but for improved bisectability and clarity it is better to do it in a separate patch. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2d5abcedeb
commit
fa56d4cb40
3 changed files with 26 additions and 14 deletions
|
@ -102,8 +102,8 @@ EXPORT_SYMBOL(ide_fixstring);
|
|||
* setting a timer to wake up at half second intervals thereafter,
|
||||
* until timeout is achieved, before timing out.
|
||||
*/
|
||||
static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad,
|
||||
unsigned long timeout, u8 *rstat)
|
||||
int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad,
|
||||
unsigned long timeout, u8 *rstat)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
|
||||
|
@ -316,7 +316,7 @@ int ide_driveid_update(ide_drive_t *drive)
|
|||
return 0;
|
||||
|
||||
SELECT_MASK(drive, 1);
|
||||
rc = ide_dev_read_id(drive, ATA_CMD_ID_ATA, id);
|
||||
rc = ide_dev_read_id(drive, ATA_CMD_ID_ATA, id, 1);
|
||||
SELECT_MASK(drive, 0);
|
||||
|
||||
if (rc)
|
||||
|
|
|
@ -238,6 +238,7 @@ static void do_identify(ide_drive_t *drive, u8 cmd, u16 *id)
|
|||
* @drive: drive to identify
|
||||
* @cmd: command to use
|
||||
* @id: buffer for IDENTIFY data
|
||||
* @irq_ctx: flag set when called from the IRQ context
|
||||
*
|
||||
* Sends an ATA(PI) IDENTIFY request to a drive and waits for a response.
|
||||
*
|
||||
|
@ -246,7 +247,7 @@ static void do_identify(ide_drive_t *drive, u8 cmd, u16 *id)
|
|||
* 2 device aborted the command (refused to identify itself)
|
||||
*/
|
||||
|
||||
int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id)
|
||||
int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id, int irq_ctx)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct ide_io_ports *io_ports = &hwif->io_ports;
|
||||
|
@ -263,7 +264,10 @@ int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id)
|
|||
tp_ops->write_devctl(hwif, ATA_NIEN | ATA_DEVCTL_OBS);
|
||||
|
||||
/* take a deep breath */
|
||||
msleep(50);
|
||||
if (irq_ctx)
|
||||
mdelay(50);
|
||||
else
|
||||
msleep(50);
|
||||
|
||||
if (io_ports->ctl_addr &&
|
||||
(hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) {
|
||||
|
@ -295,12 +299,19 @@ int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id)
|
|||
|
||||
timeout = ((cmd == ATA_CMD_ID_ATA) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
|
||||
|
||||
if (ide_busy_sleep(drive, timeout, use_altstatus))
|
||||
return 1;
|
||||
|
||||
/* wait for IRQ and ATA_DRQ */
|
||||
msleep(50);
|
||||
s = tp_ops->read_status(hwif);
|
||||
if (irq_ctx) {
|
||||
rc = __ide_wait_stat(drive, ATA_DRQ, BAD_R_STAT, timeout, &s);
|
||||
if (rc)
|
||||
return 1;
|
||||
} else {
|
||||
rc = ide_busy_sleep(drive, timeout, use_altstatus);
|
||||
if (rc)
|
||||
return 1;
|
||||
|
||||
msleep(50);
|
||||
s = tp_ops->read_status(hwif);
|
||||
}
|
||||
|
||||
if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) {
|
||||
/* drive returned ID */
|
||||
|
@ -406,10 +417,10 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
|
|||
|
||||
if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) ||
|
||||
present || cmd == ATA_CMD_ID_ATAPI) {
|
||||
rc = ide_dev_read_id(drive, cmd, id);
|
||||
rc = ide_dev_read_id(drive, cmd, id, 0);
|
||||
if (rc)
|
||||
/* failed: try again */
|
||||
rc = ide_dev_read_id(drive, cmd, id);
|
||||
rc = ide_dev_read_id(drive, cmd, id, 0);
|
||||
|
||||
stat = tp_ops->read_status(hwif);
|
||||
|
||||
|
@ -424,7 +435,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
|
|||
msleep(50);
|
||||
tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
|
||||
(void)ide_busy_sleep(drive, WAIT_WORSTCASE, 0);
|
||||
rc = ide_dev_read_id(drive, cmd, id);
|
||||
rc = ide_dev_read_id(drive, cmd, id, 0);
|
||||
}
|
||||
|
||||
/* ensure drive IRQ is clear */
|
||||
|
|
|
@ -1081,6 +1081,7 @@ extern void ide_fixstring(u8 *, const int, const int);
|
|||
|
||||
int ide_busy_sleep(ide_drive_t *, unsigned long, int);
|
||||
|
||||
int __ide_wait_stat(ide_drive_t *, u8, u8, unsigned long, u8 *);
|
||||
int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long);
|
||||
|
||||
ide_startstop_t ide_do_park_unpark(ide_drive_t *, struct request *);
|
||||
|
@ -1169,7 +1170,7 @@ int ide_no_data_taskfile(ide_drive_t *, struct ide_cmd *);
|
|||
|
||||
int ide_taskfile_ioctl(ide_drive_t *, unsigned long);
|
||||
|
||||
int ide_dev_read_id(ide_drive_t *, u8, u16 *);
|
||||
int ide_dev_read_id(ide_drive_t *, u8, u16 *, int);
|
||||
|
||||
extern int ide_driveid_update(ide_drive_t *);
|
||||
extern int ide_config_drive_speed(ide_drive_t *, u8);
|
||||
|
|
Loading…
Reference in a new issue