Skip to content

Commit

Permalink
[PATCH] sata_sil24: reimplement hardreset
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tejun Heo authored and Jeff Garzik committed Apr 11, 2006
1 parent 0eaa605 commit ecc2e2b
Showing 1 changed file with 40 additions and 3 deletions.
43 changes: 40 additions & 3 deletions drivers/scsi/sata_sil24.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit ecc2e2b

Please sign in to comment.