Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa56d4cb authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz Committed by David S. Miller
Browse files

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: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2d5abced
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -102,7 +102,7 @@ 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,
int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad,
		    unsigned long timeout, u8 *rstat)
{
	ide_hwif_t *hwif = drive->hwif;
@@ -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)
+21 −10
Original line number Diff line number Diff line
@@ -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,6 +264,9 @@ 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 */
	if (irq_ctx)
		mdelay(50);
	else
		msleep(50);

	if (io_ports->ctl_addr &&
@@ -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))
	/* wait for IRQ and ATA_DRQ */
	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;

	/* wait for IRQ and ATA_DRQ */
		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 */
+2 −1
Original line number Diff line number Diff line
@@ -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);