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
					
				| @ -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 New Issue
	
	Block a user