Skip to contentSkip to conversation

ahci: enable GHC.AE bit before set GHC.HR

PATCH NAK Peer Chen 5 participants 12 messages Sep 21, 2007 – Sep 26, 2007 libata

lore
Share & tools
lore

Peer Chen

author
#0 lore raw

PATCH 1/1 ahci: enable GHC.AE bit before set GHC.HR

According to the description of section 5.2.2.1 and 10.1.2 of AHCI specification rev1_1/rev1_2, GHC.HR shall only be set to ¡®1¡¯ by software when GHC.AE is set to ¡®1¡¯.

---

drivers/ata/ahci.c renamed from drivers/ata/ahci.c.orig +4 -0
@@ -834,6 +834,10 @@ static int ahci_reset_controller(struct 
 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 	u32 tmp;
 
+        /* turn on AHCI mode before controller reset*/
+        writel(HOST_AHCI_EN, mmio + HOST_CTL);
+        (void) readl(mmio + HOST_CTL);  /* flush */
+
 	/* global controller reset */
 	tmp = readl(mmio + HOST_CTL);
 	if ((tmp & HOST_RESET) == 0) {

-

--------------
Peer Chen
2007-09-21

#1 lore raw
Quoted 2 lines · On Fri, 21 Sep 2007 13:28:01 +0800 "Peer Chen" <[email protected]> wrote:

According to the description of section 5.2.2.1 and 10.1.2 of AHCI specification rev1_1/rev1_2, GHC.HR shall only be set to __1__ by software when GHC.AE is set to __1__.

This text contained non-ascii garbage which came through as __1__.

I'll assume that you actually meant "1".

Quoted 4 lines

drivers/ata/ahci.c static int ahci_reset_controller(struct · line 843

Quoted 10 lines
drivers/ata/ahci.c renamed from drivers/ata/ahci.c.orig +4 -0
@@ -834,6 +834,10 @@ static int ahci_reset_controller(struct 
 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 	u32 tmp;
 
+        /* turn on AHCI mode before controller reset*/
+        writel(HOST_AHCI_EN, mmio + HOST_CTL);
+        (void) readl(mmio + HOST_CTL);  /* flush */
+
 	/* global controller reset */
 	tmp = readl(mmio + HOST_CTL);
 	if ((tmp & HOST_RESET) == 0) {

We don't normally do that (void) cast.

#2 lore raw
In reply to Peer Chen
Quoted 8 lines · Peer Chen

According to the description of section 5.2.2.1 and 10.1.2 of AHCI specification rev1_1/rev1_2, GHC.HR shall only be set to ¡®1¡¯ by software when GHC.AE is set to ¡®1¡¯.

---

drivers/ata/ahci.c static int ahci_reset_controller(struct · line 843

Quoted 10 lines
drivers/ata/ahci.c renamed from drivers/ata/ahci.c.orig +4 -0
@@ -834,6 +834,10 @@ static int ahci_reset_controller(struct 
 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 	u32 tmp;
 
+        /* turn on AHCI mode before controller reset*/
+        writel(HOST_AHCI_EN, mmio + HOST_CTL);
+        (void) readl(mmio + HOST_CTL);  /* flush */
+
 	/* global controller reset */
 	tmp = readl(mmio + HOST_CTL);
 	if ((tmp & HOST_RESET) == 0) {

I appreciate the readl() flushes, but in this particular case we end up reading the exact offset again below.

Signature · 1 line
Jens Axboe
#3 lore raw
Quoted 12 lines · On Fri, 21 Sep 2007 12:31:20 +0200 Jens Axboe <[email protected]> wrote:
Quoted 11 lines · Peer Chen

According to the description of section 5.2.2.1 and 10.1.2 of AHCI specification rev1_1/rev1_2, GHC.HR shall only be set to ¡®1¡¯ by software when GHC.AE is set to ¡®1¡¯.

---

drivers/ata/ahci.c renamed from drivers/ata/ahci.c.orig +0 -0
@@ -834,6 +834,10 @@ static int ahci_reset_controller(struct 
 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 	u32 tmp;
 
Quoted 10 lines

drivers/ata/ahci.c static int ahci_reset_controller(struct · line 843

Quoted 7 lines
drivers/ata/ahci.c renamed from drivers/ata/ahci.c.orig +4 -0
+        /* turn on AHCI mode before controller reset*/
+        writel(HOST_AHCI_EN, mmio + HOST_CTL);
+        (void) readl(mmio + HOST_CTL);  /* flush */
+
 	/* global controller reset */
 	tmp = readl(mmio + HOST_CTL);
 	if ((tmp & HOST_RESET) == 0) {

I appreciate the readl() flushes, but in this particular case we end up reading the exact offset again below.

The code above is wrong btw - it is an iomap so both the new and existing code should be using ioread* not readl

Alan

#4 lore raw
Quoted 26 lines · Alan Cox
Quoted 12 lines · On Fri, 21 Sep 2007 12:31:20 +0200 Jens Axboe <[email protected]> wrote:
Quoted 11 lines · Peer Chen

According to the description of section 5.2.2.1 and 10.1.2 of AHCI specification rev1_1/rev1_2, GHC.HR shall only be set to ¡®1¡¯ by software when GHC.AE is set to ¡®1¡¯.

---

drivers/ata/ahci.c renamed from drivers/ata/ahci.c.orig +0 -0
@@ -834,6 +834,10 @@ static int ahci_reset_controller(struct 
 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 	u32 tmp;
 
Quoted 10 lines

drivers/ata/ahci.c static int ahci_reset_controller(struct · line 843

Quoted 7 lines
drivers/ata/ahci.c renamed from drivers/ata/ahci.c.orig +4 -0
+        /* turn on AHCI mode before controller reset*/
+        writel(HOST_AHCI_EN, mmio + HOST_CTL);
+        (void) readl(mmio + HOST_CTL);  /* flush */
+
 	/* global controller reset */
 	tmp = readl(mmio + HOST_CTL);
 	if ((tmp & HOST_RESET) == 0) {

I appreciate the readl() flushes, but in this particular case we end up reading the exact offset again below.

Quoted 2 lines

The code above is wrong btw - it is an iomap so both the new and existing code should be using ioread* not readl

Happy converting :-)

Signature · 1 line
Jens Axboe
#5 lore raw
In reply to Peer Chen
Quoted 8 lines · Peer Chen

According to the description of section 5.2.2.1 and 10.1.2 of AHCI specification rev1_1/rev1_2, GHC.HR shall only be set to ¡®1¡¯ by software when GHC.AE is set to ¡®1¡¯.

---

drivers/ata/ahci.c static int ahci_reset_controller(struct · line 839

Quoted 6 lines
drivers/ata/ahci.c renamed from drivers/ata/ahci.c.orig +3 -0
@@ -834,6 +834,10 @@ static int ahci_reset_controller(struct 
 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 	u32 tmp;
 
+        /* turn on AHCI mode before controller reset*/
+        writel(HOST_AHCI_EN, mmio + HOST_CTL);
+        (void) readl(mmio + HOST_CTL);  /* flush */

applied the attached patch, inspired by yours.

commit 5fca365d6109b51cfeb3515ca660cd2dc6e8822c

Author: Jeff Garzik <[email protected]>
Date:   Wed Sep 26 00:02:41 2007 -0400

[libata] AHCI: enable AHCI mode, before using AHCI reset

AHCI spec says host-reset bit may only be set when the ahci-enable bit is also set.

Noticed by Peer Chen <[email protected]>

 drivers/ata/ahci.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

5fca365d6109b51cfeb3515ca660cd2dc6e8822c

drivers/ata/ahci.c +7 -1
index 9f3c591..b615390 100644
@@ -827,8 +827,14 @@ static int ahci_reset_controller(struct ata_host *host)
 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 	u32 tmp;
 
-	/* global controller reset */
+	/* we must be in AHCI mode, before using anything
+	 * AHCI-specific, such as HOST_RESET.
+	 */
 	tmp = readl(mmio + HOST_CTL);
+	if (!(tmp & HOST_AHCI_EN))
+		writel(tmp | HOST_AHCI_EN, mmio + HOST_CTL);
+
+	/* global controller reset */
 	if ((tmp & HOST_RESET) == 0) {
 		writel(tmp | HOST_RESET, mmio + HOST_CTL);
 		readl(mmio + HOST_CTL); /* flush */
#6 lore raw
Quoted 12 lines · On Wed, 26 Sep 2007 00:03:19 -0400 Jeff Garzik <[email protected]> wrote:
Quoted 11 lines · Peer Chen

According to the description of section 5.2.2.1 and 10.1.2 of AHCI specification rev1_1/rev1_2, GHC.HR shall only be set to ¡®1¡¯ by software when GHC.AE is set to ¡®1¡¯.

---

drivers/ata/ahci.c renamed from drivers/ata/ahci.c.orig +0 -0
@@ -834,6 +834,10 @@ static int ahci_reset_controller(struct 
 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 	u32 tmp;
 
Quoted 5 lines

drivers/ata/ahci.c static int ahci_reset_controller(struct · line 839

Quoted 3 lines
drivers/ata/ahci.c renamed from drivers/ata/ahci.c.orig +3 -0
+        /* turn on AHCI mode before controller reset*/
+        writel(HOST_AHCI_EN, mmio + HOST_CTL);
+        (void) readl(mmio + HOST_CTL);  /* flush */

applied the attached patch, inspired by yours.

NAK - mmio is an iomap so writel and readl are the wrong things to use

#7 lore raw
Quoted 15 lines · Alan Cox
Quoted 12 lines · On Wed, 26 Sep 2007 00:03:19 -0400 Jeff Garzik <[email protected]> wrote:
Quoted 11 lines · Peer Chen

According to the description of section 5.2.2.1 and 10.1.2 of AHCI specification rev1_1/rev1_2, GHC.HR shall only be set to ¡®1¡¯ by software when GHC.AE is set to ¡®1¡¯.

---

drivers/ata/ahci.c renamed from drivers/ata/ahci.c.orig +0 -0
@@ -834,6 +834,10 @@ static int ahci_reset_controller(struct 
 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
 	u32 tmp;
 
Quoted 7 lines
Quoted 4 lines

drivers/ata/ahci.c static int ahci_reset_controller(struct · line 839

Quoted 3 lines
drivers/ata/ahci.c renamed from drivers/ata/ahci.c.orig +3 -0
+        /* turn on AHCI mode before controller reset*/
+        writel(HOST_AHCI_EN, mmio + HOST_CTL);
+        (void) readl(mmio + HOST_CTL);  /* flush */

applied the attached patch, inspired by yours.

NAK - mmio is an iomap so writel and readl are the wrong things to use

The patch is consistent with the rest of the driver.

You are welcome to submit a patch to convert ahci to using ioremap.

Jeff

#8 lore raw
Quoted 4 lines
Quoted 1 line

NAK - mmio is an iomap so writel and readl are the wrong things to use

The patch is consistent with the rest of the driver.
You are welcome to submit a patch to convert ahci to using ioremap.

You could just flip the relevant function to use ioread while you are tidying it up, instead of spreading new bugs into the code.

Alan

#9 lore raw
Quoted 6 lines · Alan Cox
Quoted 3 lines
Quoted 1 line

NAK - mmio is an iomap so writel and readl are the wrong things to use

The patch is consistent with the rest of the driver.
You are welcome to submit a patch to convert ahci to using ioremap.

You could just flip the relevant function to use ioread while you are tidying it up, instead of spreading new bugs into the code.

No, as I just noted above, the proper fix for this driver is to use ioremap rather than pci_iomap.

Adding support to ahci for legacy PIO is completely pointless.

Jeff

#10 lore raw
Quoted 5 lines · On Wed, 26 Sep 2007 10:33:28 -0400 Jeff Garzik <[email protected]> wrote:
Quoted 4 lines · Alan Cox
Quoted 3 lines
Quoted 1 line

NAK - mmio is an iomap so writel and readl are the wrong things to use

The patch is consistent with the rest of the driver.
You are welcome to submit a patch to convert ahci to using ioremap.

Quoted 7 lines
Quoted 2 lines

You could just flip the relevant function to use ioread while you are tidying it up, instead of spreading new bugs into the code.

No, as I just noted above, the proper fix for this driver is to use ioremap rather than pci_iomap.

Adding support to ahci for legacy PIO is completely pointless.

iomap isn't just for legacy PIO. It allows us to handle future weird mappings in ways ioremap cannot.

#11 lore raw
Quoted 7 lines · Alan Cox
Quoted 4 lines · On Wed, 26 Sep 2007 10:33:28 -0400 Jeff Garzik <[email protected]> wrote:
Quoted 3 lines · Alan Cox
Quoted 3 lines
Quoted 1 line

NAK - mmio is an iomap so writel and readl are the wrong things to use

The patch is consistent with the rest of the driver.
You are welcome to submit a patch to convert ahci to using ioremap.

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

You could just flip the relevant function to use ioread while you are tidying it up, instead of spreading new bugs into the code.

No, as I just noted above, the proper fix for this driver is to use ioremap rather than pci_iomap.

Adding support to ahci for legacy PIO is completely pointless.

iomap isn't just for legacy PIO. It allows us to handle future weird mappings in ways ioremap cannot.

Well, when needs dictate, we can re-evaluate.

Until some future date arrives where it matters for all these MMIO-only drivers and hardware, it's just a bunch of pointless overhead for ahci and many other drivers. It's also just not the Linux way to punish everybody for some edge case that so far only exists in email conversations.

The beauty of libata is that you don't have to enforce such a pogrom across all libata drivers. The libata high level API is completely free from ioread/iowrite junk, leaving each driver to make its own decision.

Jeff