[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:
Tejun Heo 2006-04-11 22:32:19 +09:00 committed by Jeff Garzik
parent 0eaa6058a6
commit ecc2e2b9c9
1 changed files with 40 additions and 3 deletions

View File

@ -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 doesn't report device signature after hard reset */
return sata_std_hardreset(ap, &dummy_class);
/* 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 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)