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

Commit ecc2e2b9 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik
Browse files

[PATCH] sata_sil24: reimplement hardreset



Reimplement hardreset according to the datasheet.  The old hardreset
didn't reset controller status and the controller might not be ready
after reset.  Also, as SStatus is a bit flakey after hardreset,
sata_std_hardrset() didn't use to wait long enough before proceeding.

Note that as we're not depending on SStatus, DET==1 condition cannot
be used to wait for link, so use shorter timeout for no device case.

Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 0eaa6058
Loading
Loading
Loading
Loading
+40 −3
Original line number Diff line number Diff line
@@ -521,10 +521,47 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class)

static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
{
	unsigned int dummy_class;
	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
	const char *reason;
	int tout_msec;
	u32 tmp;

	/* sil24 does the right thing(tm) without any protection */
	ata_set_sata_spd(ap);

	tout_msec = 100;
	if (sata_dev_present(ap))
		tout_msec = 5000;

	writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
	tmp = ata_wait_register(port + PORT_CTRL_STAT,
				PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec);

	/* SStatus oscillates between zero and valid status for short
	 * duration after DEV_RST, give it time to settle.
	 */
	msleep(100);

	if (tmp & PORT_CS_DEV_RST) {
		if (!sata_dev_present(ap))
			return 0;
		reason = "link not ready";
		goto err;
	}

	if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
		reason = "device not ready";
		goto err;
	}

	/* sil24 doesn't report device signature after hard reset */
	return sata_std_hardreset(ap, &dummy_class);
	/* sil24 doesn't report device class code after hardreset,
	 * leave *class alone.
	 */
	return 0;

 err:
	printk(KERN_ERR "ata%u: hardreset failed (%s)\n", ap->id, reason);
	return -EIO;
}

static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes)