diff options
Diffstat (limited to 'drivers/scsi/ahci.c')
-rw-r--r-- | drivers/scsi/ahci.c | 31 |
1 files changed, 6 insertions, 25 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 0e7fb9bf2cd1..1b8429cb3c96 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c | |||
@@ -516,24 +516,6 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) | |||
516 | pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); | 516 | pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); |
517 | } | 517 | } |
518 | 518 | ||
519 | static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val, | ||
520 | unsigned long interval_msec, | ||
521 | unsigned long timeout_msec) | ||
522 | { | ||
523 | unsigned long timeout; | ||
524 | u32 tmp; | ||
525 | |||
526 | timeout = jiffies + (timeout_msec * HZ) / 1000; | ||
527 | do { | ||
528 | tmp = readl(reg); | ||
529 | if ((tmp & mask) == val) | ||
530 | return 0; | ||
531 | msleep(interval_msec); | ||
532 | } while (time_before(jiffies, timeout)); | ||
533 | |||
534 | return -1; | ||
535 | } | ||
536 | |||
537 | static int ahci_softreset(struct ata_port *ap, unsigned int *class) | 519 | static int ahci_softreset(struct ata_port *ap, unsigned int *class) |
538 | { | 520 | { |
539 | struct ahci_host_priv *hpriv = ap->host_set->private_data; | 521 | struct ahci_host_priv *hpriv = ap->host_set->private_data; |
@@ -543,6 +525,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) | |||
543 | const u32 cmd_fis_len = 5; /* five dwords */ | 525 | const u32 cmd_fis_len = 5; /* five dwords */ |
544 | const char *reason = NULL; | 526 | const char *reason = NULL; |
545 | struct ata_taskfile tf; | 527 | struct ata_taskfile tf; |
528 | u32 tmp; | ||
546 | u8 *fis; | 529 | u8 *fis; |
547 | int rc; | 530 | int rc; |
548 | 531 | ||
@@ -564,8 +547,6 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) | |||
564 | /* check BUSY/DRQ, perform Command List Override if necessary */ | 547 | /* check BUSY/DRQ, perform Command List Override if necessary */ |
565 | ahci_tf_read(ap, &tf); | 548 | ahci_tf_read(ap, &tf); |
566 | if (tf.command & (ATA_BUSY | ATA_DRQ)) { | 549 | if (tf.command & (ATA_BUSY | ATA_DRQ)) { |
567 | u32 tmp; | ||
568 | |||
569 | if (!(hpriv->cap & HOST_CAP_CLO)) { | 550 | if (!(hpriv->cap & HOST_CAP_CLO)) { |
570 | rc = -EIO; | 551 | rc = -EIO; |
571 | reason = "port busy but no CLO"; | 552 | reason = "port busy but no CLO"; |
@@ -575,10 +556,10 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) | |||
575 | tmp = readl(port_mmio + PORT_CMD); | 556 | tmp = readl(port_mmio + PORT_CMD); |
576 | tmp |= PORT_CMD_CLO; | 557 | tmp |= PORT_CMD_CLO; |
577 | writel(tmp, port_mmio + PORT_CMD); | 558 | writel(tmp, port_mmio + PORT_CMD); |
578 | readl(port_mmio + PORT_CMD); /* flush */ | ||
579 | 559 | ||
580 | if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0, | 560 | tmp = ata_wait_register(port_mmio + PORT_CMD, |
581 | 1, 500)) { | 561 | PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); |
562 | if (tmp & PORT_CMD_CLO) { | ||
582 | rc = -EIO; | 563 | rc = -EIO; |
583 | reason = "CLO failed"; | 564 | reason = "CLO failed"; |
584 | goto fail_restart; | 565 | goto fail_restart; |
@@ -599,9 +580,9 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) | |||
599 | fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ | 580 | fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ |
600 | 581 | ||
601 | writel(1, port_mmio + PORT_CMD_ISSUE); | 582 | writel(1, port_mmio + PORT_CMD_ISSUE); |
602 | readl(port_mmio + PORT_CMD_ISSUE); /* flush */ | ||
603 | 583 | ||
604 | if (ahci_poll_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x0, 1, 500)) { | 584 | tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, 1, 500); |
585 | if (tmp & 0x1) { | ||
605 | rc = -EIO; | 586 | rc = -EIO; |
606 | reason = "1st FIS failed"; | 587 | reason = "1st FIS failed"; |
607 | goto fail; | 588 | goto fail; |