aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-03-22 07:07:03 -0500
committerJeff Garzik <jeff@garzik.org>2006-03-22 19:56:53 -0500
commit4658f79bec0b51222e769e328c2923f39f3bda77 (patch)
tree3b09b794cde1164adc606861ddd3df6ddeb94ce2 /drivers/scsi
parentf0c8bbfa154f4481623a4478b0ae94a6ceeaa026 (diff)
[PATCH] ahci: add softreset
Now that libata is smart enought to handle both soft and hard resets, add softreset method. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ahci.c135
1 files changed, 134 insertions, 1 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index a1ddbba2cbdf..ffba65656a83 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -513,6 +513,138 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts)
513 pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); 513 pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16);
514} 514}
515 515
516static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val,
517 unsigned long interval_msec,
518 unsigned long timeout_msec)
519{
520 unsigned long timeout;
521 u32 tmp;
522
523 timeout = jiffies + (timeout_msec * HZ) / 1000;
524 do {
525 tmp = readl(reg);
526 if ((tmp & mask) == val)
527 return 0;
528 msleep(interval_msec);
529 } while (time_before(jiffies, timeout));
530
531 return -1;
532}
533
534static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
535{
536 struct ahci_host_priv *hpriv = ap->host_set->private_data;
537 struct ahci_port_priv *pp = ap->private_data;
538 void __iomem *mmio = ap->host_set->mmio_base;
539 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
540 const u32 cmd_fis_len = 5; /* five dwords */
541 const char *reason = NULL;
542 struct ata_taskfile tf;
543 u8 *fis;
544 int rc;
545
546 DPRINTK("ENTER\n");
547
548 /* prepare for SRST (AHCI-1.1 10.4.1) */
549 rc = ahci_stop_engine(ap);
550 if (rc) {
551 reason = "failed to stop engine";
552 goto fail_restart;
553 }
554
555 /* check BUSY/DRQ, perform Command List Override if necessary */
556 ahci_tf_read(ap, &tf);
557 if (tf.command & (ATA_BUSY | ATA_DRQ)) {
558 u32 tmp;
559
560 if (!(hpriv->cap & HOST_CAP_CLO)) {
561 rc = -EIO;
562 reason = "port busy but no CLO";
563 goto fail_restart;
564 }
565
566 tmp = readl(port_mmio + PORT_CMD);
567 tmp |= PORT_CMD_CLO;
568 writel(tmp, port_mmio + PORT_CMD);
569 readl(port_mmio + PORT_CMD); /* flush */
570
571 if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0,
572 1, 500)) {
573 rc = -EIO;
574 reason = "CLO failed";
575 goto fail_restart;
576 }
577 }
578
579 /* restart engine */
580 ahci_start_engine(ap);
581
582 ata_tf_init(ap, &tf, 0);
583 fis = pp->cmd_tbl;
584
585 /* issue the first D2H Register FIS */
586 ahci_fill_cmd_slot(pp, cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY);
587
588 tf.ctl |= ATA_SRST;
589 ata_tf_to_fis(&tf, fis, 0);
590 fis[1] &= ~(1 << 7); /* turn off Command FIS bit */
591
592 writel(1, port_mmio + PORT_CMD_ISSUE);
593 readl(port_mmio + PORT_CMD_ISSUE); /* flush */
594
595 if (ahci_poll_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x0, 1, 500)) {
596 rc = -EIO;
597 reason = "1st FIS failed";
598 goto fail;
599 }
600
601 /* spec says at least 5us, but be generous and sleep for 1ms */
602 msleep(1);
603
604 /* issue the second D2H Register FIS */
605 ahci_fill_cmd_slot(pp, cmd_fis_len);
606
607 tf.ctl &= ~ATA_SRST;
608 ata_tf_to_fis(&tf, fis, 0);
609 fis[1] &= ~(1 << 7); /* turn off Command FIS bit */
610
611 writel(1, port_mmio + PORT_CMD_ISSUE);
612 readl(port_mmio + PORT_CMD_ISSUE); /* flush */
613
614 /* spec mandates ">= 2ms" before checking status.
615 * We wait 150ms, because that was the magic delay used for
616 * ATAPI devices in Hale Landis's ATADRVR, for the period of time
617 * between when the ATA command register is written, and then
618 * status is checked. Because waiting for "a while" before
619 * checking status is fine, post SRST, we perform this magic
620 * delay here as well.
621 */
622 msleep(150);
623
624 *class = ATA_DEV_NONE;
625 if (sata_dev_present(ap)) {
626 if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
627 rc = -EIO;
628 reason = "device not ready";
629 goto fail;
630 }
631 *class = ahci_dev_classify(ap);
632 }
633
634 DPRINTK("EXIT, class=%u\n", *class);
635 return 0;
636
637 fail_restart:
638 ahci_start_engine(ap);
639 fail:
640 if (verbose)
641 printk(KERN_ERR "ata%u: softreset failed (%s)\n",
642 ap->id, reason);
643 else
644 DPRINTK("EXIT, rc=%d reason=\"%s\"\n", rc, reason);
645 return rc;
646}
647
516static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class) 648static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
517{ 649{
518 int rc; 650 int rc;
@@ -553,7 +685,8 @@ static void ahci_postreset(struct ata_port *ap, unsigned int *class)
553 685
554static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes) 686static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes)
555{ 687{
556 return ata_drive_probe_reset(ap, NULL, NULL, ahci_hardreset, 688 return ata_drive_probe_reset(ap, ata_std_probeinit,
689 ahci_softreset, ahci_hardreset,
557 ahci_postreset, classes); 690 ahci_postreset, classes);
558} 691}
559 692