diff options
Diffstat (limited to 'drivers/scsi/ahci.c')
-rw-r--r-- | drivers/scsi/ahci.c | 52 |
1 files changed, 18 insertions, 34 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index b4f8fb1d628b..1b8429cb3c96 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -48,7 +48,7 @@ #include <asm/io.h> #define DRV_NAME "ahci" -#define DRV_VERSION "1.2" +#define DRV_VERSION "1.3" enum { @@ -516,25 +516,7 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); } -static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val, - unsigned long interval_msec, - unsigned long timeout_msec) -{ - unsigned long timeout; - u32 tmp; - - timeout = jiffies + (timeout_msec * HZ) / 1000; - do { - tmp = readl(reg); - if ((tmp & mask) == val) - return 0; - msleep(interval_msec); - } while (time_before(jiffies, timeout)); - - return -1; -} - -static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) +static int ahci_softreset(struct ata_port *ap, unsigned int *class) { struct ahci_host_priv *hpriv = ap->host_set->private_data; struct ahci_port_priv *pp = ap->private_data; @@ -543,11 +525,18 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) const u32 cmd_fis_len = 5; /* five dwords */ const char *reason = NULL; struct ata_taskfile tf; + u32 tmp; u8 *fis; int rc; DPRINTK("ENTER\n"); + if (!sata_dev_present(ap)) { + DPRINTK("PHY reports no device\n"); + *class = ATA_DEV_NONE; + return 0; + } + /* prepare for SRST (AHCI-1.1 10.4.1) */ rc = ahci_stop_engine(ap); if (rc) { @@ -558,8 +547,6 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) /* check BUSY/DRQ, perform Command List Override if necessary */ ahci_tf_read(ap, &tf); if (tf.command & (ATA_BUSY | ATA_DRQ)) { - u32 tmp; - if (!(hpriv->cap & HOST_CAP_CLO)) { rc = -EIO; reason = "port busy but no CLO"; @@ -569,10 +556,10 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) tmp = readl(port_mmio + PORT_CMD); tmp |= PORT_CMD_CLO; writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ - if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0, - 1, 500)) { + tmp = ata_wait_register(port_mmio + PORT_CMD, + PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); + if (tmp & PORT_CMD_CLO) { rc = -EIO; reason = "CLO failed"; goto fail_restart; @@ -593,9 +580,9 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ writel(1, port_mmio + PORT_CMD_ISSUE); - readl(port_mmio + PORT_CMD_ISSUE); /* flush */ - if (ahci_poll_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x0, 1, 500)) { + tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, 1, 500); + if (tmp & 0x1) { rc = -EIO; reason = "1st FIS failed"; goto fail; @@ -640,22 +627,19 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) fail_restart: ahci_start_engine(ap); fail: - if (verbose) - printk(KERN_ERR "ata%u: softreset failed (%s)\n", - ap->id, reason); - else - DPRINTK("EXIT, rc=%d reason=\"%s\"\n", rc, reason); + printk(KERN_ERR "ata%u: softreset failed (%s)\n", + ap->id, reason); return rc; } -static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class) +static int ahci_hardreset(struct ata_port *ap, unsigned int *class) { int rc; DPRINTK("ENTER\n"); ahci_stop_engine(ap); - rc = sata_std_hardreset(ap, verbose, class); + rc = sata_std_hardreset(ap, class); ahci_start_engine(ap); if (rc == 0) |