linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/6] The definition of ahci_start_engine() and ahci_stop_engine()
@ 2006-06-02  7:49 zhao, forrest
  2006-06-03 12:46 ` Tejun Heo
  0 siblings, 1 reply; 6+ messages in thread
From: zhao, forrest @ 2006-06-02  7:49 UTC (permalink / raw)
  To: jeff, hare, axboe, htejun, jeremy, lkml; +Cc: linux-ide

1 Make ahci_start_engine() and ahci_stop_engine more consistent with AHCI
 spec 1.1
2 Change their input parameter from ap to port_mmio


Signed-off-by: Forrest Zhao <forrest.zhao@intel.com>


---

 drivers/scsi/ahci.c |   51 +++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 45 insertions(+), 6 deletions(-)

9ba56ff63c5f01f0a7280f15189c952f2fd7f2a1
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 45fd71d..d2b35c4 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -200,6 +200,8 @@ static void ahci_scr_write (struct ata_p
 static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
 static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static int ahci_start_engine(void __iomem *port_mmio);
+static int ahci_stop_engine(void __iomem *port_mmio);
 static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes);
 static void ahci_irq_clear(struct ata_port *ap);
 static int ahci_port_start(struct ata_port *ap);
@@ -482,14 +484,18 @@ static void ahci_scr_write (struct ata_p
 	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
-static int ahci_stop_engine(struct ata_port *ap)
+static int ahci_stop_engine(void __iomem *port_mmio)
 {
-	void __iomem *mmio = ap->host_set->mmio_base;
-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	int work;
 	u32 tmp;
 
 	tmp = readl(port_mmio + PORT_CMD);
+
+	/* Check if the HBA is idle */
+	if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
+		return 0;
+
+	/* Setting HBA to idle */
 	tmp &= ~PORT_CMD_START;
 	writel(tmp, port_mmio + PORT_CMD);
 
@@ -507,16 +513,49 @@ static int ahci_stop_engine(struct ata_p
 	return -EIO;
 }
 
-static void ahci_start_engine(struct ata_port *ap)
+static int ahci_start_engine(void __iomem *port_mmio)
 {
-	void __iomem *mmio = ap->host_set->mmio_base;
-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	u32 tmp;
+	int work = 1000;
 
+	/*
+	 * Get current status
+	 */
 	tmp = readl(port_mmio + PORT_CMD);
+
+	/*
+	 * AHCI rev 1.1 section 10.3.1:
+	 * Software shall not set PxCMD.ST to '1' until it verifies
+	 * that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
+	 */
+	if ((tmp & PORT_CMD_FIS_RX) == 0)
+		return -EPERM;
+
+	/*
+	 * wait for engine to become idle.
+	 */
+	while (work-- > 0) {
+		tmp = readl(port_mmio + PORT_CMD);
+		if ((tmp & PORT_CMD_LIST_ON) == 0)
+			break;
+		udelay(10);
+	}
+
+	if (!work) {
+		/*
+		 * We need to do a port reset / HBA reset here
+		 */
+		return -EBUSY;
+	}
+
+	/*
+	 * Start DMA
+	 */
 	tmp |= PORT_CMD_START;
 	writel(tmp, port_mmio + PORT_CMD);
 	readl(port_mmio + PORT_CMD); /* flush */
+
+	return 0;
 }
 
 static unsigned int ahci_dev_classify(struct ata_port *ap)
-- 
1.2.6

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/6] The definition of ahci_start_engine() and ahci_stop_engine()
  2006-06-02  7:49 [PATCH 1/6] The definition of ahci_start_engine() and ahci_stop_engine() zhao, forrest
@ 2006-06-03 12:46 ` Tejun Heo
  0 siblings, 0 replies; 6+ messages in thread
From: Tejun Heo @ 2006-06-03 12:46 UTC (permalink / raw)
  To: zhao, forrest; +Cc: jeff, hare, axboe, jeremy, lkml, linux-ide

On Fri, Jun 02, 2006 at 03:49:59PM +0800, zhao, forrest wrote:
> -static int ahci_stop_engine(struct ata_port *ap)
> +static int ahci_stop_engine(void __iomem *port_mmio)
>  {
> -	void __iomem *mmio = ap->host_set->mmio_base;
> -	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
>  	int work;
>  	u32 tmp;
>  
>  	tmp = readl(port_mmio + PORT_CMD);
> +
> +	/* Check if the HBA is idle */
> +	if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
> +		return 0;

I'm not really sure whether this short circuiting is necessary.  I
think blindly turning the bit off is simpler and more robust.

> +
> +	/* Setting HBA to idle */
>  	tmp &= ~PORT_CMD_START;
>  	writel(tmp, port_mmio + PORT_CMD);
>  
> @@ -507,16 +513,49 @@ static int ahci_stop_engine(struct ata_p
>  	return -EIO;
>  }
>  
> -static void ahci_start_engine(struct ata_port *ap)
> +static int ahci_start_engine(void __iomem *port_mmio)
>  {
> -	void __iomem *mmio = ap->host_set->mmio_base;
> -	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
>  	u32 tmp;
> +	int work = 1000;
>  
> +	/*
> +	 * Get current status
> +	 */
>  	tmp = readl(port_mmio + PORT_CMD);
> +
> +	/*
> +	 * AHCI rev 1.1 section 10.3.1:
> +	 * Software shall not set PxCMD.ST to '1' until it verifies
> +	 * that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
> +	 */
> +	if ((tmp & PORT_CMD_FIS_RX) == 0)
> +		return -EPERM;

Here, again, I don't think this type of checking is necessary.  If the
controller is behaving correctly, above condition should be guaranteed
by driver control flow.  If the controller is acting weird, the driver
probably had chance to detect above condition earlier (when turning
off the engine) and determined to ignore it.

> +
> +	/*
> +	 * wait for engine to become idle.
> +	 */
> +	while (work-- > 0) {
> +		tmp = readl(port_mmio + PORT_CMD);
> +		if ((tmp & PORT_CMD_LIST_ON) == 0)
> +			break;
> +		udelay(10);
> +	}
> +
> +	if (!work) {
> +		/*
> +		 * We need to do a port reset / HBA reset here
> +		 */
> +		return -EBUSY;
> +	}

Please convert above to ata_wait_register().  It would be nice if you
can convert ahci_stop_engine(), too.

-- 
tejun

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/6] The definition of ahci_start_engine() and ahci_stop_engine()
@ 2006-06-06 10:15 zhao, forrest
  0 siblings, 0 replies; 6+ messages in thread
From: zhao, forrest @ 2006-06-06 10:15 UTC (permalink / raw)
  To: jeff, hare, axboe, htejun, jeremy, lkml; +Cc: linux-ide

1 Make ahci_start_engine() and ahci_stop_engine more consistent with AHCI
 spec 1.1
2 Change their input parameter from ap to port_mmio
3 Use ata_wait_register() to wait register bit.

Signed-off-by: Forrest Zhao <forrest.zhaot@intel.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Jens Axboe <axboe@suse.de>


---

 drivers/scsi/ahci.c |   57 +++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 41 insertions(+), 16 deletions(-)

4183c56a95717740b6ca9c06b22bb6377a2f23e7
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 45fd71d..be2cba8 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -200,6 +200,8 @@ static void ahci_scr_write (struct ata_p
 static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
 static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static int ahci_start_engine(void __iomem *port_mmio);
+static int ahci_stop_engine(void __iomem *port_mmio);
 static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes);
 static void ahci_irq_clear(struct ata_port *ap);
 static int ahci_port_start(struct ata_port *ap);
@@ -482,41 +484,64 @@ static void ahci_scr_write (struct ata_p
 	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
-static int ahci_stop_engine(struct ata_port *ap)
+static int ahci_stop_engine(void __iomem *port_mmio)
 {
-	void __iomem *mmio = ap->host_set->mmio_base;
-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-	int work;
 	u32 tmp;
 
 	tmp = readl(port_mmio + PORT_CMD);
+
+	/* Check if the HBA is idle */
+	if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
+		return 0;
+
+	/* Setting HBA to idle */
 	tmp &= ~PORT_CMD_START;
 	writel(tmp, port_mmio + PORT_CMD);
 
-	/* wait for engine to stop.  TODO: this could be
+	/* wait for engine to stop. This could be
 	 * as long as 500 msec
 	 */
-	work = 1000;
-	while (work-- > 0) {
-		tmp = readl(port_mmio + PORT_CMD);
-		if ((tmp & PORT_CMD_LIST_ON) == 0)
-			return 0;
-		udelay(10);
-	}
+	tmp = ata_wait_register(port_mmio + PORT_CMD,
+			        PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+	if(tmp & PORT_CMD_LIST_ON)
+		return -EIO;
 
-	return -EIO;
+	return 0;
 }
 
-static void ahci_start_engine(struct ata_port *ap)
+static int ahci_start_engine(void __iomem *port_mmio)
 {
-	void __iomem *mmio = ap->host_set->mmio_base;
-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	u32 tmp;
 
+	/*
+	 * Get current status
+	 */
 	tmp = readl(port_mmio + PORT_CMD);
+
+	/*
+	 * AHCI rev 1.1 section 10.3.1:
+	 * Software shall not set PxCMD.ST to '1' until it verifies
+	 * that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
+	 */
+	if ((tmp & PORT_CMD_FIS_RX) == 0)
+		return -EPERM;
+
+	/*
+	 * wait for engine to become idle.
+	 */
+	tmp = ata_wait_register(port_mmio + PORT_CMD,
+				PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1,500);
+	if(tmp & PORT_CMD_LIST_ON)
+		return -EBUSY;
+
+	/*
+	 * Start DMA
+	 */
 	tmp |= PORT_CMD_START;
 	writel(tmp, port_mmio + PORT_CMD);
 	readl(port_mmio + PORT_CMD); /* flush */
+
+	return 0;
 }
 
 static unsigned int ahci_dev_classify(struct ata_port *ap)
-- 
1.2.6

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 1/6]The definition of ahci_start_engine() and ahci_stop_engine()
@ 2006-06-29  8:18 zhao, forrest
  0 siblings, 0 replies; 6+ messages in thread
From: zhao, forrest @ 2006-06-29  8:18 UTC (permalink / raw)
  To: jgarzik, htejun, hare, axboe; +Cc: linux-ide

1 Make ahci_start_engine() and ahci_stop_engine more consistent with AHCI
 spec 1.1
2 Change their input parameter from ap to port_mmio

Signed-off-by: Forrest Zhao <forrest.zhaot@intel.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Jens Axboe <axboe@suse.de>


---

 drivers/scsi/ahci.c |   57 +++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 41 insertions(+), 16 deletions(-)

ca41463c59af1b90149c42101696b47d96c41d11
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index f059467..0ff8be1 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -205,6 +205,8 @@ static irqreturn_t ahci_interrupt (int i
 static void ahci_irq_clear(struct ata_port *ap);
 static int ahci_port_start(struct ata_port *ap);
 static void ahci_port_stop(struct ata_port *ap);
+static int ahci_start_engine(void __iomem *port_mmio);
+static int ahci_stop_engine(void __iomem *port_mmio);
 static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
 static void ahci_qc_prep(struct ata_queued_cmd *qc);
 static u8 ahci_check_status(struct ata_port *ap);
@@ -508,41 +510,64 @@ static void ahci_scr_write (struct ata_p
 	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
-static int ahci_stop_engine(struct ata_port *ap)
+static int ahci_stop_engine(void __iomem *port_mmio)
 {
-	void __iomem *mmio = ap->host_set->mmio_base;
-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-	int work;
 	u32 tmp;
 
 	tmp = readl(port_mmio + PORT_CMD);
+
+	/* Check if the HBA is idle */
+	if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
+		return 0;
+
+	/* Setting HBA to idle */
 	tmp &= ~PORT_CMD_START;
 	writel(tmp, port_mmio + PORT_CMD);
 
-	/* wait for engine to stop.  TODO: this could be
+	/* wait for engine to stop. This could be
 	 * as long as 500 msec
 	 */
-	work = 1000;
-	while (work-- > 0) {
-		tmp = readl(port_mmio + PORT_CMD);
-		if ((tmp & PORT_CMD_LIST_ON) == 0)
-			return 0;
-		udelay(10);
-	}
+	tmp = ata_wait_register(port_mmio + PORT_CMD,
+			        PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+	if(tmp & PORT_CMD_LIST_ON)
+		return -EIO;
 
-	return -EIO;
+	return 0;
 }
 
-static void ahci_start_engine(struct ata_port *ap)
+static int ahci_start_engine(void __iomem *port_mmio)
 {
-	void __iomem *mmio = ap->host_set->mmio_base;
-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	u32 tmp;
 
+	/*
+	 * Get current status
+	 */
 	tmp = readl(port_mmio + PORT_CMD);
+
+	/*
+	 * AHCI rev 1.1 section 10.3.1:
+	 * Software shall not set PxCMD.ST to '1' until it verifies
+	 * that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
+	 */
+	if ((tmp & PORT_CMD_FIS_RX) == 0)
+		return -EPERM;
+
+	/*
+	 * wait for engine to become idle.
+	 */
+	tmp = ata_wait_register(port_mmio + PORT_CMD,
+				PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1,500);
+	if(tmp & PORT_CMD_LIST_ON)
+		return -EBUSY;
+
+	/*
+	 * Start DMA
+	 */
 	tmp |= PORT_CMD_START;
 	writel(tmp, port_mmio + PORT_CMD);
 	readl(port_mmio + PORT_CMD); /* flush */
+
+	return 0;
 }
 
 static unsigned int ahci_dev_classify(struct ata_port *ap)
-- 
1.2.6

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 1/6]The definition of ahci_start_engine() and ahci_stop_engine()
@ 2006-07-10  3:34 zhao, forrest
  0 siblings, 0 replies; 6+ messages in thread
From: zhao, forrest @ 2006-07-10  3:34 UTC (permalink / raw)
  To: jgarzik, htejun, hare, axboe; +Cc: linux-ide

1 Make ahci_start_engine() and ahci_stop_engine more consistent with
AHCI
 spec 1.1
2 Change their input parameter from ap to port_mmio

Signed-off-by: Forrest Zhao <forrest.zhaot@intel.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Jens Axboe <axboe@suse.de>


---

 drivers/scsi/ahci.c |   57 ++++++++++++++++++++++++++++++++++++
+--------------
 1 files changed, 41 insertions(+), 16 deletions(-)

ca41463c59af1b90149c42101696b47d96c41d11
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index f059467..0ff8be1 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -205,6 +205,8 @@ static irqreturn_t ahci_interrupt (int i
 static void ahci_irq_clear(struct ata_port *ap);
 static int ahci_port_start(struct ata_port *ap);
 static void ahci_port_stop(struct ata_port *ap);
+static int ahci_start_engine(void __iomem *port_mmio);
+static int ahci_stop_engine(void __iomem *port_mmio);
 static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
 static void ahci_qc_prep(struct ata_queued_cmd *qc);
 static u8 ahci_check_status(struct ata_port *ap);
@@ -508,41 +510,64 @@ static void ahci_scr_write (struct ata_p
 	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
-static int ahci_stop_engine(struct ata_port *ap)
+static int ahci_stop_engine(void __iomem *port_mmio)
 {
-	void __iomem *mmio = ap->host_set->mmio_base;
-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-	int work;
 	u32 tmp;
 
 	tmp = readl(port_mmio + PORT_CMD);
+
+	/* Check if the HBA is idle */
+	if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
+		return 0;
+
+	/* Setting HBA to idle */
 	tmp &= ~PORT_CMD_START;
 	writel(tmp, port_mmio + PORT_CMD);
 
-	/* wait for engine to stop.  TODO: this could be
+	/* wait for engine to stop. This could be
 	 * as long as 500 msec
 	 */
-	work = 1000;
-	while (work-- > 0) {
-		tmp = readl(port_mmio + PORT_CMD);
-		if ((tmp & PORT_CMD_LIST_ON) == 0)
-			return 0;
-		udelay(10);
-	}
+	tmp = ata_wait_register(port_mmio + PORT_CMD,
+			        PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+	if(tmp & PORT_CMD_LIST_ON)
+		return -EIO;
 
-	return -EIO;
+	return 0;
 }
 
-static void ahci_start_engine(struct ata_port *ap)
+static int ahci_start_engine(void __iomem *port_mmio)
 {
-	void __iomem *mmio = ap->host_set->mmio_base;
-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	u32 tmp;
 
+	/*
+	 * Get current status
+	 */
 	tmp = readl(port_mmio + PORT_CMD);
+
+	/*
+	 * AHCI rev 1.1 section 10.3.1:
+	 * Software shall not set PxCMD.ST to '1' until it verifies
+	 * that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
+	 */
+	if ((tmp & PORT_CMD_FIS_RX) == 0)
+		return -EPERM;
+
+	/*
+	 * wait for engine to become idle.
+	 */
+	tmp = ata_wait_register(port_mmio + PORT_CMD,
+				PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1,500);
+	if(tmp & PORT_CMD_LIST_ON)
+		return -EBUSY;
+
+	/*
+	 * Start DMA
+	 */
 	tmp |= PORT_CMD_START;
 	writel(tmp, port_mmio + PORT_CMD);
 	readl(port_mmio + PORT_CMD); /* flush */
+
+	return 0;
 }
 
 static unsigned int ahci_dev_classify(struct ata_port *ap)
-- 
1.2.6

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 1/6]The definition of ahci_start_engine() and ahci_stop_engine()
@ 2006-07-11  6:37 zhao, forrest
  0 siblings, 0 replies; 6+ messages in thread
From: zhao, forrest @ 2006-07-11  6:37 UTC (permalink / raw)
  To: jgarzik, htejun, hare, axboe; +Cc: linux-ide

1 Make ahci_start_engine() and ahci_stop_engine more consistent with
AHCI
 spec 1.1
2 Change their input parameter from ap to port_mmio

Signed-off-by: Forrest Zhao <forrest.zhaot@intel.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Jens Axboe <axboe@suse.de>


---

 drivers/scsi/ahci.c |   57 ++++++++++++++++++++++++++++++++++++
+--------------
 1 files changed, 41 insertions(+), 16 deletions(-)

ca41463c59af1b90149c42101696b47d96c41d11
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index f059467..0ff8be1 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -205,6 +205,8 @@ static irqreturn_t ahci_interrupt (int i
 static void ahci_irq_clear(struct ata_port *ap);
 static int ahci_port_start(struct ata_port *ap);
 static void ahci_port_stop(struct ata_port *ap);
+static int ahci_start_engine(void __iomem *port_mmio);
+static int ahci_stop_engine(void __iomem *port_mmio);
 static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
 static void ahci_qc_prep(struct ata_queued_cmd *qc);
 static u8 ahci_check_status(struct ata_port *ap);
@@ -508,41 +510,64 @@ static void ahci_scr_write (struct ata_p
 	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
-static int ahci_stop_engine(struct ata_port *ap)
+static int ahci_stop_engine(void __iomem *port_mmio)
 {
-	void __iomem *mmio = ap->host_set->mmio_base;
-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-	int work;
 	u32 tmp;
 
 	tmp = readl(port_mmio + PORT_CMD);
+
+	/* Check if the HBA is idle */
+	if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
+		return 0;
+
+	/* Setting HBA to idle */
 	tmp &= ~PORT_CMD_START;
 	writel(tmp, port_mmio + PORT_CMD);
 
-	/* wait for engine to stop.  TODO: this could be
+	/* wait for engine to stop. This could be
 	 * as long as 500 msec
 	 */
-	work = 1000;
-	while (work-- > 0) {
-		tmp = readl(port_mmio + PORT_CMD);
-		if ((tmp & PORT_CMD_LIST_ON) == 0)
-			return 0;
-		udelay(10);
-	}
+	tmp = ata_wait_register(port_mmio + PORT_CMD,
+			        PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+	if(tmp & PORT_CMD_LIST_ON)
+		return -EIO;
 
-	return -EIO;
+	return 0;
 }
 
-static void ahci_start_engine(struct ata_port *ap)
+static int ahci_start_engine(void __iomem *port_mmio)
 {
-	void __iomem *mmio = ap->host_set->mmio_base;
-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	u32 tmp;
 
+	/*
+	 * Get current status
+	 */
 	tmp = readl(port_mmio + PORT_CMD);
+
+	/*
+	 * AHCI rev 1.1 section 10.3.1:
+	 * Software shall not set PxCMD.ST to '1' until it verifies
+	 * that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
+	 */
+	if ((tmp & PORT_CMD_FIS_RX) == 0)
+		return -EPERM;
+
+	/*
+	 * wait for engine to become idle.
+	 */
+	tmp = ata_wait_register(port_mmio + PORT_CMD,
+				PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1,500);
+	if(tmp & PORT_CMD_LIST_ON)
+		return -EBUSY;
+
+	/*
+	 * Start DMA
+	 */
 	tmp |= PORT_CMD_START;
 	writel(tmp, port_mmio + PORT_CMD);
 	readl(port_mmio + PORT_CMD); /* flush */
+
+	return 0;
 }
 
 static unsigned int ahci_dev_classify(struct ata_port *ap)
-- 
1.2.6


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2006-07-11  6:50 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-02  7:49 [PATCH 1/6] The definition of ahci_start_engine() and ahci_stop_engine() zhao, forrest
2006-06-03 12:46 ` Tejun Heo
  -- strict thread matches above, loose matches on Subject: below --
2006-06-06 10:15 zhao, forrest
2006-06-29  8:18 [PATCH 1/6]The " zhao, forrest
2006-07-10  3:34 zhao, forrest
2006-07-11  6:37 zhao, forrest

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).