aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ahci.c
diff options
context:
space:
mode:
authorzhao, forrest <forrest.zhao@intel.com>2006-07-13 01:38:32 -0400
committerJeff Garzik <jeff@garzik.org>2006-07-19 16:45:42 -0400
commit5457f2194ad198a0aba4190ec99a6a81846fdca5 (patch)
tree2daf5c3cc82bc7c0aea2dea04bfc1dde9287c5ef /drivers/scsi/ahci.c
parent13abf50df209008b5d44075bafeeab42ace56aa6 (diff)
[PATCH] The redefinition of ahci_start_engine() and ahci_stop_engine()
- Make ahci_start_engine() and ahci_stop_engine() more consistent with AHCI spec 1.1 - Change their input parameter from ap to port_mmio - Update the existing users of ahci_start_engine() and ahci_stop_engine() Signed-off-by: Forrest Zhao <forrest.zhao@intel.com> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Jens Axboe <axboe@suse.de> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/scsi/ahci.c')
-rw-r--r--drivers/scsi/ahci.c82
1 files changed, 57 insertions, 25 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 77e7202a0eba..f1516ca2c52a 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -205,6 +205,8 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
205static void ahci_irq_clear(struct ata_port *ap); 205static void ahci_irq_clear(struct ata_port *ap);
206static int ahci_port_start(struct ata_port *ap); 206static int ahci_port_start(struct ata_port *ap);
207static void ahci_port_stop(struct ata_port *ap); 207static void ahci_port_stop(struct ata_port *ap);
208static int ahci_start_engine(void __iomem *port_mmio);
209static int ahci_stop_engine(void __iomem *port_mmio);
208static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf); 210static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
209static void ahci_qc_prep(struct ata_queued_cmd *qc); 211static void ahci_qc_prep(struct ata_queued_cmd *qc);
210static u8 ahci_check_status(struct ata_port *ap); 212static u8 ahci_check_status(struct ata_port *ap);
@@ -508,41 +510,64 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
508 writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); 510 writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
509} 511}
510 512
511static int ahci_stop_engine(struct ata_port *ap) 513static int ahci_stop_engine(void __iomem *port_mmio)
512{ 514{
513 void __iomem *mmio = ap->host_set->mmio_base;
514 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
515 int work;
516 u32 tmp; 515 u32 tmp;
517 516
518 tmp = readl(port_mmio + PORT_CMD); 517 tmp = readl(port_mmio + PORT_CMD);
518
519 /* Check if the HBA is idle */
520 if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
521 return 0;
522
523 /* Setting HBA to idle */
519 tmp &= ~PORT_CMD_START; 524 tmp &= ~PORT_CMD_START;
520 writel(tmp, port_mmio + PORT_CMD); 525 writel(tmp, port_mmio + PORT_CMD);
521 526
522 /* wait for engine to stop. TODO: this could be 527 /* wait for engine to stop. This could be
523 * as long as 500 msec 528 * as long as 500 msec
524 */ 529 */
525 work = 1000; 530 tmp = ata_wait_register(port_mmio + PORT_CMD,
526 while (work-- > 0) { 531 PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
527 tmp = readl(port_mmio + PORT_CMD); 532 if(tmp & PORT_CMD_LIST_ON)
528 if ((tmp & PORT_CMD_LIST_ON) == 0) 533 return -EIO;
529 return 0;
530 udelay(10);
531 }
532 534
533 return -EIO; 535 return 0;
534} 536}
535 537
536static void ahci_start_engine(struct ata_port *ap) 538static int ahci_start_engine(void __iomem *port_mmio)
537{ 539{
538 void __iomem *mmio = ap->host_set->mmio_base;
539 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
540 u32 tmp; 540 u32 tmp;
541 541
542 /*
543 * Get current status
544 */
542 tmp = readl(port_mmio + PORT_CMD); 545 tmp = readl(port_mmio + PORT_CMD);
546
547 /*
548 * AHCI rev 1.1 section 10.3.1:
549 * Software shall not set PxCMD.ST to '1' until it verifies
550 * that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
551 */
552 if ((tmp & PORT_CMD_FIS_RX) == 0)
553 return -EPERM;
554
555 /*
556 * wait for engine to become idle.
557 */
558 tmp = ata_wait_register(port_mmio + PORT_CMD,
559 PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1,500);
560 if(tmp & PORT_CMD_LIST_ON)
561 return -EBUSY;
562
563 /*
564 * Start DMA
565 */
543 tmp |= PORT_CMD_START; 566 tmp |= PORT_CMD_START;
544 writel(tmp, port_mmio + PORT_CMD); 567 writel(tmp, port_mmio + PORT_CMD);
545 readl(port_mmio + PORT_CMD); /* flush */ 568 readl(port_mmio + PORT_CMD); /* flush */
569
570 return 0;
546} 571}
547 572
548static unsigned int ahci_dev_classify(struct ata_port *ap) 573static unsigned int ahci_dev_classify(struct ata_port *ap)
@@ -626,7 +651,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
626 } 651 }
627 652
628 /* prepare for SRST (AHCI-1.1 10.4.1) */ 653 /* prepare for SRST (AHCI-1.1 10.4.1) */
629 rc = ahci_stop_engine(ap); 654 rc = ahci_stop_engine(port_mmio);
630 if (rc) { 655 if (rc) {
631 reason = "failed to stop engine"; 656 reason = "failed to stop engine";
632 goto fail_restart; 657 goto fail_restart;
@@ -647,7 +672,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
647 } 672 }
648 673
649 /* restart engine */ 674 /* restart engine */
650 ahci_start_engine(ap); 675 ahci_start_engine(port_mmio);
651 676
652 ata_tf_init(ap->device, &tf); 677 ata_tf_init(ap->device, &tf);
653 fis = pp->cmd_tbl; 678 fis = pp->cmd_tbl;
@@ -706,7 +731,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
706 return 0; 731 return 0;
707 732
708 fail_restart: 733 fail_restart:
709 ahci_start_engine(ap); 734 ahci_start_engine(port_mmio);
710 fail: 735 fail:
711 ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); 736 ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
712 return rc; 737 return rc;
@@ -717,11 +742,13 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
717 struct ahci_port_priv *pp = ap->private_data; 742 struct ahci_port_priv *pp = ap->private_data;
718 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 743 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
719 struct ata_taskfile tf; 744 struct ata_taskfile tf;
745 void __iomem *mmio = ap->host_set->mmio_base;
746 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
720 int rc; 747 int rc;
721 748
722 DPRINTK("ENTER\n"); 749 DPRINTK("ENTER\n");
723 750
724 ahci_stop_engine(ap); 751 ahci_stop_engine(port_mmio);
725 752
726 /* clear D2H reception area to properly wait for D2H FIS */ 753 /* clear D2H reception area to properly wait for D2H FIS */
727 ata_tf_init(ap->device, &tf); 754 ata_tf_init(ap->device, &tf);
@@ -730,7 +757,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
730 757
731 rc = sata_std_hardreset(ap, class); 758 rc = sata_std_hardreset(ap, class);
732 759
733 ahci_start_engine(ap); 760 ahci_start_engine(port_mmio);
734 761
735 if (rc == 0 && ata_port_online(ap)) 762 if (rc == 0 && ata_port_online(ap))
736 *class = ahci_dev_classify(ap); 763 *class = ahci_dev_classify(ap);
@@ -1052,10 +1079,13 @@ static void ahci_thaw(struct ata_port *ap)
1052 1079
1053static void ahci_error_handler(struct ata_port *ap) 1080static void ahci_error_handler(struct ata_port *ap)
1054{ 1081{
1082 void __iomem *mmio = ap->host_set->mmio_base;
1083 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
1084
1055 if (!(ap->pflags & ATA_PFLAG_FROZEN)) { 1085 if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
1056 /* restart engine */ 1086 /* restart engine */
1057 ahci_stop_engine(ap); 1087 ahci_stop_engine(port_mmio);
1058 ahci_start_engine(ap); 1088 ahci_start_engine(port_mmio);
1059 } 1089 }
1060 1090
1061 /* perform recovery */ 1091 /* perform recovery */
@@ -1066,14 +1096,16 @@ static void ahci_error_handler(struct ata_port *ap)
1066static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) 1096static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
1067{ 1097{
1068 struct ata_port *ap = qc->ap; 1098 struct ata_port *ap = qc->ap;
1099 void __iomem *mmio = ap->host_set->mmio_base;
1100 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
1069 1101
1070 if (qc->flags & ATA_QCFLAG_FAILED) 1102 if (qc->flags & ATA_QCFLAG_FAILED)
1071 qc->err_mask |= AC_ERR_OTHER; 1103 qc->err_mask |= AC_ERR_OTHER;
1072 1104
1073 if (qc->err_mask) { 1105 if (qc->err_mask) {
1074 /* make DMA engine forget about the failed command */ 1106 /* make DMA engine forget about the failed command */
1075 ahci_stop_engine(ap); 1107 ahci_stop_engine(port_mmio);
1076 ahci_start_engine(ap); 1108 ahci_start_engine(port_mmio);
1077 } 1109 }
1078} 1110}
1079 1111