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 @@ | |||
48 | #include <asm/io.h> | 48 | #include <asm/io.h> |
49 | 49 | ||
50 | #define DRV_NAME "ahci" | 50 | #define DRV_NAME "ahci" |
51 | #define DRV_VERSION "1.2" | 51 | #define DRV_VERSION "1.3" |
52 | 52 | ||
53 | 53 | ||
54 | enum { | 54 | enum { |
@@ -516,25 +516,7 @@ 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, | 519 | static int ahci_softreset(struct ata_port *ap, unsigned int *class) |
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, int verbose, 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; |
540 | struct ahci_port_priv *pp = ap->private_data; | 522 | 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) | |||
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 | ||
549 | DPRINTK("ENTER\n"); | 532 | DPRINTK("ENTER\n"); |
550 | 533 | ||
534 | if (!sata_dev_present(ap)) { | ||
535 | DPRINTK("PHY reports no device\n"); | ||
536 | *class = ATA_DEV_NONE; | ||
537 | return 0; | ||
538 | } | ||
539 | |||
551 | /* prepare for SRST (AHCI-1.1 10.4.1) */ | 540 | /* prepare for SRST (AHCI-1.1 10.4.1) */ |
552 | rc = ahci_stop_engine(ap); | 541 | rc = ahci_stop_engine(ap); |
553 | if (rc) { | 542 | if (rc) { |
@@ -558,8 +547,6 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) | |||
558 | /* check BUSY/DRQ, perform Command List Override if necessary */ | 547 | /* check BUSY/DRQ, perform Command List Override if necessary */ |
559 | ahci_tf_read(ap, &tf); | 548 | ahci_tf_read(ap, &tf); |
560 | if (tf.command & (ATA_BUSY | ATA_DRQ)) { | 549 | if (tf.command & (ATA_BUSY | ATA_DRQ)) { |
561 | u32 tmp; | ||
562 | |||
563 | if (!(hpriv->cap & HOST_CAP_CLO)) { | 550 | if (!(hpriv->cap & HOST_CAP_CLO)) { |
564 | rc = -EIO; | 551 | rc = -EIO; |
565 | reason = "port busy but no CLO"; | 552 | reason = "port busy but no CLO"; |
@@ -569,10 +556,10 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) | |||
569 | tmp = readl(port_mmio + PORT_CMD); | 556 | tmp = readl(port_mmio + PORT_CMD); |
570 | tmp |= PORT_CMD_CLO; | 557 | tmp |= PORT_CMD_CLO; |
571 | writel(tmp, port_mmio + PORT_CMD); | 558 | writel(tmp, port_mmio + PORT_CMD); |
572 | readl(port_mmio + PORT_CMD); /* flush */ | ||
573 | 559 | ||
574 | if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0, | 560 | tmp = ata_wait_register(port_mmio + PORT_CMD, |
575 | 1, 500)) { | 561 | PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); |
562 | if (tmp & PORT_CMD_CLO) { | ||
576 | rc = -EIO; | 563 | rc = -EIO; |
577 | reason = "CLO failed"; | 564 | reason = "CLO failed"; |
578 | goto fail_restart; | 565 | goto fail_restart; |
@@ -593,9 +580,9 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) | |||
593 | fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ | 580 | fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ |
594 | 581 | ||
595 | writel(1, port_mmio + PORT_CMD_ISSUE); | 582 | writel(1, port_mmio + PORT_CMD_ISSUE); |
596 | readl(port_mmio + PORT_CMD_ISSUE); /* flush */ | ||
597 | 583 | ||
598 | 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) { | ||
599 | rc = -EIO; | 586 | rc = -EIO; |
600 | reason = "1st FIS failed"; | 587 | reason = "1st FIS failed"; |
601 | goto fail; | 588 | goto fail; |
@@ -640,22 +627,19 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) | |||
640 | fail_restart: | 627 | fail_restart: |
641 | ahci_start_engine(ap); | 628 | ahci_start_engine(ap); |
642 | fail: | 629 | fail: |
643 | if (verbose) | 630 | printk(KERN_ERR "ata%u: softreset failed (%s)\n", |
644 | printk(KERN_ERR "ata%u: softreset failed (%s)\n", | 631 | ap->id, reason); |
645 | ap->id, reason); | ||
646 | else | ||
647 | DPRINTK("EXIT, rc=%d reason=\"%s\"\n", rc, reason); | ||
648 | return rc; | 632 | return rc; |
649 | } | 633 | } |
650 | 634 | ||
651 | static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class) | 635 | static int ahci_hardreset(struct ata_port *ap, unsigned int *class) |
652 | { | 636 | { |
653 | int rc; | 637 | int rc; |
654 | 638 | ||
655 | DPRINTK("ENTER\n"); | 639 | DPRINTK("ENTER\n"); |
656 | 640 | ||
657 | ahci_stop_engine(ap); | 641 | ahci_stop_engine(ap); |
658 | rc = sata_std_hardreset(ap, verbose, class); | 642 | rc = sata_std_hardreset(ap, class); |
659 | ahci_start_engine(ap); | 643 | ahci_start_engine(ap); |
660 | 644 | ||
661 | if (rc == 0) | 645 | if (rc == 0) |