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>
Cette révision appartient à :
Bartlomiej Zolnierkiewicz
2009-06-23 11:29:11 +00:00
révisé par David S. Miller
Parent 2d5abcedeb
révision fa56d4cb40
3 fichiers modifiés avec 26 ajouts et 14 suppressions

Voir le fichier

@@ -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 */