[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: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
0eaa6058a6
commit
ecc2e2b9c9
|
@ -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)
|
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 doesn't report device signature after hard reset */
|
/* sil24 does the right thing(tm) without any protection */
|
||||||
return sata_std_hardreset(ap, &dummy_class);
|
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 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)
|
static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes)
|
||||||
|
|
Loading…
Reference in New Issue