xref: /kernel/linux/linux-5.10/drivers/ide/ide-eh.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci#include <linux/kernel.h>
48c2ecf20Sopenharmony_ci#include <linux/export.h>
58c2ecf20Sopenharmony_ci#include <linux/ide.h>
68c2ecf20Sopenharmony_ci#include <linux/delay.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_cistatic ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq,
98c2ecf20Sopenharmony_ci				     u8 stat, u8 err)
108c2ecf20Sopenharmony_ci{
118c2ecf20Sopenharmony_ci	ide_hwif_t *hwif = drive->hwif;
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci	if ((stat & ATA_BUSY) ||
148c2ecf20Sopenharmony_ci	    ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
158c2ecf20Sopenharmony_ci		/* other bits are useless when BUSY */
168c2ecf20Sopenharmony_ci		scsi_req(rq)->result |= ERROR_RESET;
178c2ecf20Sopenharmony_ci	} else if (stat & ATA_ERR) {
188c2ecf20Sopenharmony_ci		/* err has different meaning on cdrom and tape */
198c2ecf20Sopenharmony_ci		if (err == ATA_ABORTED) {
208c2ecf20Sopenharmony_ci			if ((drive->dev_flags & IDE_DFLAG_LBA) &&
218c2ecf20Sopenharmony_ci			    /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
228c2ecf20Sopenharmony_ci			    hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
238c2ecf20Sopenharmony_ci				return ide_stopped;
248c2ecf20Sopenharmony_ci		} else if ((err & BAD_CRC) == BAD_CRC) {
258c2ecf20Sopenharmony_ci			/* UDMA crc error, just retry the operation */
268c2ecf20Sopenharmony_ci			drive->crc_count++;
278c2ecf20Sopenharmony_ci		} else if (err & (ATA_BBK | ATA_UNC)) {
288c2ecf20Sopenharmony_ci			/* retries won't help these */
298c2ecf20Sopenharmony_ci			scsi_req(rq)->result = ERROR_MAX;
308c2ecf20Sopenharmony_ci		} else if (err & ATA_TRK0NF) {
318c2ecf20Sopenharmony_ci			/* help it find track zero */
328c2ecf20Sopenharmony_ci			scsi_req(rq)->result |= ERROR_RECAL;
338c2ecf20Sopenharmony_ci		}
348c2ecf20Sopenharmony_ci	}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ &&
378c2ecf20Sopenharmony_ci	    (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) {
388c2ecf20Sopenharmony_ci		int nsect = drive->mult_count ? drive->mult_count : 1;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci		ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE);
418c2ecf20Sopenharmony_ci	}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	if (scsi_req(rq)->result >= ERROR_MAX || blk_noretry_request(rq)) {
448c2ecf20Sopenharmony_ci		ide_kill_rq(drive, rq);
458c2ecf20Sopenharmony_ci		return ide_stopped;
468c2ecf20Sopenharmony_ci	}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
498c2ecf20Sopenharmony_ci		scsi_req(rq)->result |= ERROR_RESET;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	if ((scsi_req(rq)->result & ERROR_RESET) == ERROR_RESET) {
528c2ecf20Sopenharmony_ci		++scsi_req(rq)->result;
538c2ecf20Sopenharmony_ci		return ide_do_reset(drive);
548c2ecf20Sopenharmony_ci	}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	if ((scsi_req(rq)->result & ERROR_RECAL) == ERROR_RECAL)
578c2ecf20Sopenharmony_ci		drive->special_flags |= IDE_SFLAG_RECALIBRATE;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	++scsi_req(rq)->result;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	return ide_stopped;
628c2ecf20Sopenharmony_ci}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_cistatic ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq,
658c2ecf20Sopenharmony_ci				       u8 stat, u8 err)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	ide_hwif_t *hwif = drive->hwif;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	if ((stat & ATA_BUSY) ||
708c2ecf20Sopenharmony_ci	    ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
718c2ecf20Sopenharmony_ci		/* other bits are useless when BUSY */
728c2ecf20Sopenharmony_ci		scsi_req(rq)->result |= ERROR_RESET;
738c2ecf20Sopenharmony_ci	} else {
748c2ecf20Sopenharmony_ci		/* add decoding error stuff */
758c2ecf20Sopenharmony_ci	}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
788c2ecf20Sopenharmony_ci		/* force an abort */
798c2ecf20Sopenharmony_ci		hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	if (scsi_req(rq)->result >= ERROR_MAX) {
828c2ecf20Sopenharmony_ci		ide_kill_rq(drive, rq);
838c2ecf20Sopenharmony_ci	} else {
848c2ecf20Sopenharmony_ci		if ((scsi_req(rq)->result & ERROR_RESET) == ERROR_RESET) {
858c2ecf20Sopenharmony_ci			++scsi_req(rq)->result;
868c2ecf20Sopenharmony_ci			return ide_do_reset(drive);
878c2ecf20Sopenharmony_ci		}
888c2ecf20Sopenharmony_ci		++scsi_req(rq)->result;
898c2ecf20Sopenharmony_ci	}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	return ide_stopped;
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic ide_startstop_t __ide_error(ide_drive_t *drive, struct request *rq,
958c2ecf20Sopenharmony_ci				   u8 stat, u8 err)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	if (drive->media == ide_disk)
988c2ecf20Sopenharmony_ci		return ide_ata_error(drive, rq, stat, err);
998c2ecf20Sopenharmony_ci	return ide_atapi_error(drive, rq, stat, err);
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci/**
1038c2ecf20Sopenharmony_ci *	ide_error	-	handle an error on the IDE
1048c2ecf20Sopenharmony_ci *	@drive: drive the error occurred on
1058c2ecf20Sopenharmony_ci *	@msg: message to report
1068c2ecf20Sopenharmony_ci *	@stat: status bits
1078c2ecf20Sopenharmony_ci *
1088c2ecf20Sopenharmony_ci *	ide_error() takes action based on the error returned by the drive.
1098c2ecf20Sopenharmony_ci *	For normal I/O that may well include retries. We deal with
1108c2ecf20Sopenharmony_ci *	both new-style (taskfile) and old style command handling here.
1118c2ecf20Sopenharmony_ci *	In the case of taskfile command handling there is work left to
1128c2ecf20Sopenharmony_ci *	do
1138c2ecf20Sopenharmony_ci */
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ciide_startstop_t ide_error(ide_drive_t *drive, const char *msg, u8 stat)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	struct request *rq;
1188c2ecf20Sopenharmony_ci	u8 err;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	err = ide_dump_status(drive, msg, stat);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	rq = drive->hwif->rq;
1238c2ecf20Sopenharmony_ci	if (rq == NULL)
1248c2ecf20Sopenharmony_ci		return ide_stopped;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	/* retry only "normal" I/O: */
1278c2ecf20Sopenharmony_ci	if (blk_rq_is_passthrough(rq)) {
1288c2ecf20Sopenharmony_ci		if (ata_taskfile_request(rq)) {
1298c2ecf20Sopenharmony_ci			struct ide_cmd *cmd = ide_req(rq)->special;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci			if (cmd)
1328c2ecf20Sopenharmony_ci				ide_complete_cmd(drive, cmd, stat, err);
1338c2ecf20Sopenharmony_ci		} else if (ata_pm_request(rq)) {
1348c2ecf20Sopenharmony_ci			scsi_req(rq)->result = 1;
1358c2ecf20Sopenharmony_ci			ide_complete_pm_rq(drive, rq);
1368c2ecf20Sopenharmony_ci			return ide_stopped;
1378c2ecf20Sopenharmony_ci		}
1388c2ecf20Sopenharmony_ci		scsi_req(rq)->result = err;
1398c2ecf20Sopenharmony_ci		ide_complete_rq(drive, err ? BLK_STS_IOERR : BLK_STS_OK, blk_rq_bytes(rq));
1408c2ecf20Sopenharmony_ci		return ide_stopped;
1418c2ecf20Sopenharmony_ci	}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	return __ide_error(drive, rq, stat, err);
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ide_error);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistatic inline void ide_complete_drive_reset(ide_drive_t *drive, blk_status_t err)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	struct request *rq = drive->hwif->rq;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	if (rq && ata_misc_request(rq) &&
1528c2ecf20Sopenharmony_ci	    scsi_req(rq)->cmd[0] == REQ_DRIVE_RESET) {
1538c2ecf20Sopenharmony_ci		if (err <= 0 && scsi_req(rq)->result == 0)
1548c2ecf20Sopenharmony_ci			scsi_req(rq)->result = -EIO;
1558c2ecf20Sopenharmony_ci		ide_complete_rq(drive, err, blk_rq_bytes(rq));
1568c2ecf20Sopenharmony_ci	}
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci/* needed below */
1608c2ecf20Sopenharmony_cistatic ide_startstop_t do_reset1(ide_drive_t *, int);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci/*
1638c2ecf20Sopenharmony_ci * atapi_reset_pollfunc() gets invoked to poll the interface for completion
1648c2ecf20Sopenharmony_ci * every 50ms during an atapi drive reset operation.  If the drive has not yet
1658c2ecf20Sopenharmony_ci * responded, and we have not yet hit our maximum waiting time, then the timer
1668c2ecf20Sopenharmony_ci * is restarted for another 50ms.
1678c2ecf20Sopenharmony_ci */
1688c2ecf20Sopenharmony_cistatic ide_startstop_t atapi_reset_pollfunc(ide_drive_t *drive)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	ide_hwif_t *hwif = drive->hwif;
1718c2ecf20Sopenharmony_ci	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
1728c2ecf20Sopenharmony_ci	u8 stat;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	tp_ops->dev_select(drive);
1758c2ecf20Sopenharmony_ci	udelay(10);
1768c2ecf20Sopenharmony_ci	stat = tp_ops->read_status(hwif);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	if (OK_STAT(stat, 0, ATA_BUSY))
1798c2ecf20Sopenharmony_ci		printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name);
1808c2ecf20Sopenharmony_ci	else {
1818c2ecf20Sopenharmony_ci		if (time_before(jiffies, hwif->poll_timeout)) {
1828c2ecf20Sopenharmony_ci			ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20);
1838c2ecf20Sopenharmony_ci			/* continue polling */
1848c2ecf20Sopenharmony_ci			return ide_started;
1858c2ecf20Sopenharmony_ci		}
1868c2ecf20Sopenharmony_ci		/* end of polling */
1878c2ecf20Sopenharmony_ci		hwif->polling = 0;
1888c2ecf20Sopenharmony_ci		printk(KERN_ERR "%s: ATAPI reset timed-out, status=0x%02x\n",
1898c2ecf20Sopenharmony_ci			drive->name, stat);
1908c2ecf20Sopenharmony_ci		/* do it the old fashioned way */
1918c2ecf20Sopenharmony_ci		return do_reset1(drive, 1);
1928c2ecf20Sopenharmony_ci	}
1938c2ecf20Sopenharmony_ci	/* done polling */
1948c2ecf20Sopenharmony_ci	hwif->polling = 0;
1958c2ecf20Sopenharmony_ci	ide_complete_drive_reset(drive, BLK_STS_OK);
1968c2ecf20Sopenharmony_ci	return ide_stopped;
1978c2ecf20Sopenharmony_ci}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cistatic void ide_reset_report_error(ide_hwif_t *hwif, u8 err)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	static const char *err_master_vals[] =
2028c2ecf20Sopenharmony_ci		{ NULL, "passed", "formatter device error",
2038c2ecf20Sopenharmony_ci		  "sector buffer error", "ECC circuitry error",
2048c2ecf20Sopenharmony_ci		  "controlling MPU error" };
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	u8 err_master = err & 0x7f;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	printk(KERN_ERR "%s: reset: master: ", hwif->name);
2098c2ecf20Sopenharmony_ci	if (err_master && err_master < 6)
2108c2ecf20Sopenharmony_ci		printk(KERN_CONT "%s", err_master_vals[err_master]);
2118c2ecf20Sopenharmony_ci	else
2128c2ecf20Sopenharmony_ci		printk(KERN_CONT "error (0x%02x?)", err);
2138c2ecf20Sopenharmony_ci	if (err & 0x80)
2148c2ecf20Sopenharmony_ci		printk(KERN_CONT "; slave: failed");
2158c2ecf20Sopenharmony_ci	printk(KERN_CONT "\n");
2168c2ecf20Sopenharmony_ci}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci/*
2198c2ecf20Sopenharmony_ci * reset_pollfunc() gets invoked to poll the interface for completion every 50ms
2208c2ecf20Sopenharmony_ci * during an ide reset operation. If the drives have not yet responded,
2218c2ecf20Sopenharmony_ci * and we have not yet hit our maximum waiting time, then the timer is restarted
2228c2ecf20Sopenharmony_ci * for another 50ms.
2238c2ecf20Sopenharmony_ci */
2248c2ecf20Sopenharmony_cistatic ide_startstop_t reset_pollfunc(ide_drive_t *drive)
2258c2ecf20Sopenharmony_ci{
2268c2ecf20Sopenharmony_ci	ide_hwif_t *hwif = drive->hwif;
2278c2ecf20Sopenharmony_ci	const struct ide_port_ops *port_ops = hwif->port_ops;
2288c2ecf20Sopenharmony_ci	u8 tmp;
2298c2ecf20Sopenharmony_ci	blk_status_t err = BLK_STS_OK;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	if (port_ops && port_ops->reset_poll) {
2328c2ecf20Sopenharmony_ci		err = port_ops->reset_poll(drive);
2338c2ecf20Sopenharmony_ci		if (err) {
2348c2ecf20Sopenharmony_ci			printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
2358c2ecf20Sopenharmony_ci				hwif->name, drive->name);
2368c2ecf20Sopenharmony_ci			goto out;
2378c2ecf20Sopenharmony_ci		}
2388c2ecf20Sopenharmony_ci	}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	tmp = hwif->tp_ops->read_status(hwif);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	if (!OK_STAT(tmp, 0, ATA_BUSY)) {
2438c2ecf20Sopenharmony_ci		if (time_before(jiffies, hwif->poll_timeout)) {
2448c2ecf20Sopenharmony_ci			ide_set_handler(drive, &reset_pollfunc, HZ/20);
2458c2ecf20Sopenharmony_ci			/* continue polling */
2468c2ecf20Sopenharmony_ci			return ide_started;
2478c2ecf20Sopenharmony_ci		}
2488c2ecf20Sopenharmony_ci		printk(KERN_ERR "%s: reset timed-out, status=0x%02x\n",
2498c2ecf20Sopenharmony_ci			hwif->name, tmp);
2508c2ecf20Sopenharmony_ci		drive->failures++;
2518c2ecf20Sopenharmony_ci		err = BLK_STS_IOERR;
2528c2ecf20Sopenharmony_ci	} else  {
2538c2ecf20Sopenharmony_ci		tmp = ide_read_error(drive);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci		if (tmp == 1) {
2568c2ecf20Sopenharmony_ci			printk(KERN_INFO "%s: reset: success\n", hwif->name);
2578c2ecf20Sopenharmony_ci			drive->failures = 0;
2588c2ecf20Sopenharmony_ci		} else {
2598c2ecf20Sopenharmony_ci			ide_reset_report_error(hwif, tmp);
2608c2ecf20Sopenharmony_ci			drive->failures++;
2618c2ecf20Sopenharmony_ci			err = BLK_STS_IOERR;
2628c2ecf20Sopenharmony_ci		}
2638c2ecf20Sopenharmony_ci	}
2648c2ecf20Sopenharmony_ciout:
2658c2ecf20Sopenharmony_ci	hwif->polling = 0;	/* done polling */
2668c2ecf20Sopenharmony_ci	ide_complete_drive_reset(drive, err);
2678c2ecf20Sopenharmony_ci	return ide_stopped;
2688c2ecf20Sopenharmony_ci}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_cistatic void ide_disk_pre_reset(ide_drive_t *drive)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	drive->special_flags =
2758c2ecf20Sopenharmony_ci		legacy ? (IDE_SFLAG_SET_GEOMETRY | IDE_SFLAG_RECALIBRATE) : 0;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	drive->mult_count = 0;
2788c2ecf20Sopenharmony_ci	drive->dev_flags &= ~IDE_DFLAG_PARKED;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 &&
2818c2ecf20Sopenharmony_ci	    (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0)
2828c2ecf20Sopenharmony_ci		drive->mult_req = 0;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	if (drive->mult_req != drive->mult_count)
2858c2ecf20Sopenharmony_ci		drive->special_flags |= IDE_SFLAG_SET_MULTMODE;
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_cistatic void pre_reset(ide_drive_t *drive)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci	const struct ide_port_ops *port_ops = drive->hwif->port_ops;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	if (drive->media == ide_disk)
2938c2ecf20Sopenharmony_ci		ide_disk_pre_reset(drive);
2948c2ecf20Sopenharmony_ci	else
2958c2ecf20Sopenharmony_ci		drive->dev_flags |= IDE_DFLAG_POST_RESET;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	if (drive->dev_flags & IDE_DFLAG_USING_DMA) {
2988c2ecf20Sopenharmony_ci		if (drive->crc_count)
2998c2ecf20Sopenharmony_ci			ide_check_dma_crc(drive);
3008c2ecf20Sopenharmony_ci		else
3018c2ecf20Sopenharmony_ci			ide_dma_off(drive);
3028c2ecf20Sopenharmony_ci	}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) {
3058c2ecf20Sopenharmony_ci		if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) {
3068c2ecf20Sopenharmony_ci			drive->dev_flags &= ~IDE_DFLAG_UNMASK;
3078c2ecf20Sopenharmony_ci			drive->io_32bit = 0;
3088c2ecf20Sopenharmony_ci		}
3098c2ecf20Sopenharmony_ci		return;
3108c2ecf20Sopenharmony_ci	}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	if (port_ops && port_ops->pre_reset)
3138c2ecf20Sopenharmony_ci		port_ops->pre_reset(drive);
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	if (drive->current_speed != 0xff)
3168c2ecf20Sopenharmony_ci		drive->desired_speed = drive->current_speed;
3178c2ecf20Sopenharmony_ci	drive->current_speed = 0xff;
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci/*
3218c2ecf20Sopenharmony_ci * do_reset1() attempts to recover a confused drive by resetting it.
3228c2ecf20Sopenharmony_ci * Unfortunately, resetting a disk drive actually resets all devices on
3238c2ecf20Sopenharmony_ci * the same interface, so it can really be thought of as resetting the
3248c2ecf20Sopenharmony_ci * interface rather than resetting the drive.
3258c2ecf20Sopenharmony_ci *
3268c2ecf20Sopenharmony_ci * ATAPI devices have their own reset mechanism which allows them to be
3278c2ecf20Sopenharmony_ci * individually reset without clobbering other devices on the same interface.
3288c2ecf20Sopenharmony_ci *
3298c2ecf20Sopenharmony_ci * Unfortunately, the IDE interface does not generate an interrupt to let
3308c2ecf20Sopenharmony_ci * us know when the reset operation has finished, so we must poll for this.
3318c2ecf20Sopenharmony_ci * Equally poor, though, is the fact that this may a very long time to complete,
3328c2ecf20Sopenharmony_ci * (up to 30 seconds worstcase).  So, instead of busy-waiting here for it,
3338c2ecf20Sopenharmony_ci * we set a timer to poll at 50ms intervals.
3348c2ecf20Sopenharmony_ci */
3358c2ecf20Sopenharmony_cistatic ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi)
3368c2ecf20Sopenharmony_ci{
3378c2ecf20Sopenharmony_ci	ide_hwif_t *hwif = drive->hwif;
3388c2ecf20Sopenharmony_ci	struct ide_io_ports *io_ports = &hwif->io_ports;
3398c2ecf20Sopenharmony_ci	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
3408c2ecf20Sopenharmony_ci	const struct ide_port_ops *port_ops;
3418c2ecf20Sopenharmony_ci	ide_drive_t *tdrive;
3428c2ecf20Sopenharmony_ci	unsigned long flags, timeout;
3438c2ecf20Sopenharmony_ci	int i;
3448c2ecf20Sopenharmony_ci	DEFINE_WAIT(wait);
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	spin_lock_irqsave(&hwif->lock, flags);
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	/* We must not reset with running handlers */
3498c2ecf20Sopenharmony_ci	BUG_ON(hwif->handler != NULL);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	/* For an ATAPI device, first try an ATAPI SRST. */
3528c2ecf20Sopenharmony_ci	if (drive->media != ide_disk && !do_not_try_atapi) {
3538c2ecf20Sopenharmony_ci		pre_reset(drive);
3548c2ecf20Sopenharmony_ci		tp_ops->dev_select(drive);
3558c2ecf20Sopenharmony_ci		udelay(20);
3568c2ecf20Sopenharmony_ci		tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
3578c2ecf20Sopenharmony_ci		ndelay(400);
3588c2ecf20Sopenharmony_ci		hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
3598c2ecf20Sopenharmony_ci		hwif->polling = 1;
3608c2ecf20Sopenharmony_ci		__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20);
3618c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&hwif->lock, flags);
3628c2ecf20Sopenharmony_ci		return ide_started;
3638c2ecf20Sopenharmony_ci	}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	/* We must not disturb devices in the IDE_DFLAG_PARKED state. */
3668c2ecf20Sopenharmony_ci	do {
3678c2ecf20Sopenharmony_ci		unsigned long now;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci		prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE);
3708c2ecf20Sopenharmony_ci		timeout = jiffies;
3718c2ecf20Sopenharmony_ci		ide_port_for_each_present_dev(i, tdrive, hwif) {
3728c2ecf20Sopenharmony_ci			if ((tdrive->dev_flags & IDE_DFLAG_PARKED) &&
3738c2ecf20Sopenharmony_ci			    time_after(tdrive->sleep, timeout))
3748c2ecf20Sopenharmony_ci				timeout = tdrive->sleep;
3758c2ecf20Sopenharmony_ci		}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci		now = jiffies;
3788c2ecf20Sopenharmony_ci		if (time_before_eq(timeout, now))
3798c2ecf20Sopenharmony_ci			break;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&hwif->lock, flags);
3828c2ecf20Sopenharmony_ci		timeout = schedule_timeout_uninterruptible(timeout - now);
3838c2ecf20Sopenharmony_ci		spin_lock_irqsave(&hwif->lock, flags);
3848c2ecf20Sopenharmony_ci	} while (timeout);
3858c2ecf20Sopenharmony_ci	finish_wait(&ide_park_wq, &wait);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	/*
3888c2ecf20Sopenharmony_ci	 * First, reset any device state data we were maintaining
3898c2ecf20Sopenharmony_ci	 * for any of the drives on this interface.
3908c2ecf20Sopenharmony_ci	 */
3918c2ecf20Sopenharmony_ci	ide_port_for_each_dev(i, tdrive, hwif)
3928c2ecf20Sopenharmony_ci		pre_reset(tdrive);
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	if (io_ports->ctl_addr == 0) {
3958c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&hwif->lock, flags);
3968c2ecf20Sopenharmony_ci		ide_complete_drive_reset(drive, BLK_STS_IOERR);
3978c2ecf20Sopenharmony_ci		return ide_stopped;
3988c2ecf20Sopenharmony_ci	}
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	/*
4018c2ecf20Sopenharmony_ci	 * Note that we also set nIEN while resetting the device,
4028c2ecf20Sopenharmony_ci	 * to mask unwanted interrupts from the interface during the reset.
4038c2ecf20Sopenharmony_ci	 * However, due to the design of PC hardware, this will cause an
4048c2ecf20Sopenharmony_ci	 * immediate interrupt due to the edge transition it produces.
4058c2ecf20Sopenharmony_ci	 * This single interrupt gives us a "fast poll" for drives that
4068c2ecf20Sopenharmony_ci	 * recover from reset very quickly, saving us the first 50ms wait time.
4078c2ecf20Sopenharmony_ci	 */
4088c2ecf20Sopenharmony_ci	/* set SRST and nIEN */
4098c2ecf20Sopenharmony_ci	tp_ops->write_devctl(hwif, ATA_SRST | ATA_NIEN | ATA_DEVCTL_OBS);
4108c2ecf20Sopenharmony_ci	/* more than enough time */
4118c2ecf20Sopenharmony_ci	udelay(10);
4128c2ecf20Sopenharmony_ci	/* clear SRST, leave nIEN (unless device is on the quirk list) */
4138c2ecf20Sopenharmony_ci	tp_ops->write_devctl(hwif,
4148c2ecf20Sopenharmony_ci		((drive->dev_flags & IDE_DFLAG_NIEN_QUIRK) ? 0 : ATA_NIEN) |
4158c2ecf20Sopenharmony_ci		 ATA_DEVCTL_OBS);
4168c2ecf20Sopenharmony_ci	/* more than enough time */
4178c2ecf20Sopenharmony_ci	udelay(10);
4188c2ecf20Sopenharmony_ci	hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
4198c2ecf20Sopenharmony_ci	hwif->polling = 1;
4208c2ecf20Sopenharmony_ci	__ide_set_handler(drive, &reset_pollfunc, HZ/20);
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	/*
4238c2ecf20Sopenharmony_ci	 * Some weird controller like resetting themselves to a strange
4248c2ecf20Sopenharmony_ci	 * state when the disks are reset this way. At least, the Winbond
4258c2ecf20Sopenharmony_ci	 * 553 documentation says that
4268c2ecf20Sopenharmony_ci	 */
4278c2ecf20Sopenharmony_ci	port_ops = hwif->port_ops;
4288c2ecf20Sopenharmony_ci	if (port_ops && port_ops->resetproc)
4298c2ecf20Sopenharmony_ci		port_ops->resetproc(drive);
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&hwif->lock, flags);
4328c2ecf20Sopenharmony_ci	return ide_started;
4338c2ecf20Sopenharmony_ci}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci/*
4368c2ecf20Sopenharmony_ci * ide_do_reset() is the entry point to the drive/interface reset code.
4378c2ecf20Sopenharmony_ci */
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ciide_startstop_t ide_do_reset(ide_drive_t *drive)
4408c2ecf20Sopenharmony_ci{
4418c2ecf20Sopenharmony_ci	return do_reset1(drive, 0);
4428c2ecf20Sopenharmony_ci}
4438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ide_do_reset);
444