linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2 #upstream] ahci: preserve PORTS_IMPL over host resets
@ 2006-11-02  3:17 Tejun Heo
  2006-11-02  3:20 ` [PATCH 2/2 #upstream] ahci: honor PORTS_IMPL on ICH8s Tejun Heo
  2006-11-07  9:46 ` [PATCH 1/2 #upstream] ahci: preserve PORTS_IMPL over host resets Jeff Garzik
  0 siblings, 2 replies; 8+ messages in thread
From: Tejun Heo @ 2006-11-02  3:17 UTC (permalink / raw)
  To: Jeff Garzik, robbat2; +Cc: linux-ide

Instead of writing 0xf blindly, preserve the content of write-once
PORTS_IMPL register over host resets.

This patch is taken from Jeff Garzik's AHCI init update patch.

Signed-off-by: Tejun Heo <htejun@gmail.com>
---
Protection against 0 PI is added as suggested in the following
message.

    http://article.gmane.org/gmane.linux.ide/13365

 drivers/ata/ahci.c |   23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

Index: work/drivers/ata/ahci.c
===================================================================
--- work.orig/drivers/ata/ahci.c
+++ work/drivers/ata/ahci.c
@@ -389,6 +389,11 @@ static struct pci_driver ahci_pci_driver
 };
 
 
+static inline int ahci_nr_ports(u32 cap)
+{
+	return (cap & 0x1f) + 1;
+}
+
 static inline unsigned long ahci_port_base_ul (unsigned long base, unsigned int port)
 {
 	return base + 0x100 + (port * 0x80);
@@ -598,11 +603,12 @@ static int ahci_deinit_port(void __iomem
 
 static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev)
 {
-	u32 cap_save, tmp;
+	u32 cap_save, impl_save, tmp;
 
 	cap_save = readl(mmio + HOST_CAP);
 	cap_save &= ( (1<<28) | (1<<17) );
 	cap_save |= (1 << 27);
+	impl_save = readl(mmio + HOST_PORTS_IMPL);
 
 	/* global controller reset */
 	tmp = readl(mmio + HOST_CTL);
@@ -623,10 +629,21 @@ static int ahci_reset_controller(void __
 		return -EIO;
 	}
 
+	/* turn on AHCI mode */
 	writel(HOST_AHCI_EN, mmio + HOST_CTL);
 	(void) readl(mmio + HOST_CTL);	/* flush */
+
+	/* These write-once registers are normally cleared on reset.
+	 * Restore BIOS values... which we HOPE were present before
+	 * reset.
+	 */
+	if (!impl_save) {
+		impl_save = (1 << ahci_nr_ports(cap_save)) - 1;
+		dev_printk(KERN_WARNING, &pdev->dev,
+			   "PORTS_IMPL is zero, forcing 0x%x\n", impl_save);
+	}
 	writel(cap_save, mmio + HOST_CAP);
-	writel(0xf, mmio + HOST_PORTS_IMPL);
+	writel(impl_save, mmio + HOST_PORTS_IMPL);
 	(void) readl(mmio + HOST_PORTS_IMPL);	/* flush */
 
 	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
@@ -1431,7 +1448,7 @@ static int ahci_host_init(struct ata_pro
 
 	hpriv->cap = readl(mmio + HOST_CAP);
 	hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
-	probe_ent->n_ports = (hpriv->cap & 0x1f) + 1;
+	probe_ent->n_ports = ahci_nr_ports(hpriv->cap);
 
 	VPRINTK("cap 0x%x  port_map 0x%x  n_ports %d\n",
 		hpriv->cap, hpriv->port_map, probe_ent->n_ports);

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

* [PATCH 2/2 #upstream] ahci: honor PORTS_IMPL on ICH8s
  2006-11-02  3:17 [PATCH 1/2 #upstream] ahci: preserve PORTS_IMPL over host resets Tejun Heo
@ 2006-11-02  3:20 ` Tejun Heo
  2006-11-06  1:05   ` Robin H. Johnson
  2006-11-07  9:46 ` [PATCH 1/2 #upstream] ahci: preserve PORTS_IMPL over host resets Jeff Garzik
  1 sibling, 1 reply; 8+ messages in thread
From: Tejun Heo @ 2006-11-02  3:20 UTC (permalink / raw)
  To: Jeff Garzik, robbat2; +Cc: linux-ide

Some ICH8s use non-linear port mapping.  ahci driver didn't use to
honor PORTS_IMPL and this made ports after hole nonfunctional.  This
patch makes ahci mark those ports as dummy and properly initialize all
the implemented ports after the dummies.

As it's unknown whether other AHCIs implement PORTS_IMPL register
properly, new board id board_ahci_pi is added and selectively applied
to ICH8s.  All other AHCIs continue to use linear mapping regardless
of PORTS_IMPL value.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Cc: Robin H. Johnson <robbat2@gentoo.org>
---
Updated to mark unimplemented ports as dummies.  Tested on ICH7
(consecutive mapping) and ICH8 (inconsecutive mapping).  Error paths
are tested too.

Thanks.

 drivers/ata/ahci.c |   71 +++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 55 insertions(+), 16 deletions(-)

Index: work/drivers/ata/ahci.c
===================================================================
--- work.orig/drivers/ata/ahci.c
+++ work/drivers/ata/ahci.c
@@ -53,6 +53,7 @@
 
 enum {
 	AHCI_PCI_BAR		= 5,
+	AHCI_MAX_PORTS		= 32,
 	AHCI_MAX_SG		= 168, /* hardware max is 64K */
 	AHCI_DMA_BOUNDARY	= 0xffffffff,
 	AHCI_USE_CLUSTERING	= 0,
@@ -77,7 +78,8 @@ enum {
 	RX_FIS_UNK		= 0x60, /* offset of Unknown FIS data */
 
 	board_ahci		= 0,
-	board_ahci_vt8251	= 1,
+	board_ahci_pi		= 1,
+	board_ahci_vt8251	= 2,
 
 	/* global controller registers */
 	HOST_CAP		= 0x00, /* host capabilities */
@@ -166,6 +168,7 @@ enum {
 	AHCI_FLAG_MSI		= (1 << 0),
 
 	/* ap->flags bits */
+	AHCI_FLAG_HONOR_PI		= (1 << 23), /* honor PORTS_IMPL */
 	AHCI_FLAG_NO_NCQ		= (1 << 24),
 };
 
@@ -315,6 +318,16 @@ static const struct ata_port_info ahci_p
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &ahci_ops,
 	},
+	/* board_ahci_pi */
+	{
+		.sht		= &ahci_sht,
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+				  ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI,
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.port_ops	= &ahci_ops,
+	},
 	/* board_ahci_vt8251 */
 	{
 		.sht		= &ahci_sht,
@@ -340,11 +353,11 @@ static const struct pci_device_id ahci_p
 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
-	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
-	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
-	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
-	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
-	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
+	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci_pi }, /* ICH8 */
+	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_pi }, /* ICH8 */
+	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci_pi }, /* ICH8 */
+	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci_pi }, /* ICH8M */
+	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci_pi }, /* ICH8M */
 
 	/* JMicron */
 	{ PCI_VDEVICE(JMICRON, 0x2360), board_ahci }, /* JMicron JMB360 */
@@ -659,7 +672,8 @@ static int ahci_reset_controller(void __
 }
 
 static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
-				 int n_ports, u32 cap)
+				 int n_ports, unsigned int port_flags,
+				 struct ahci_host_priv *hpriv)
 {
 	int i, rc;
 	u32 tmp;
@@ -668,13 +682,12 @@ static void ahci_init_controller(void __
 		void __iomem *port_mmio = ahci_port_base(mmio, i);
 		const char *emsg = NULL;
 
-#if 0 /* BIOSen initialize this incorrectly */
-		if (!(hpriv->port_map & (1 << i)))
+		if ((port_flags & AHCI_FLAG_HONOR_PI) &&
+		    !(hpriv->port_map & (1 << i)))
 			continue;
-#endif
 
 		/* make sure port is not active */
-		rc = ahci_deinit_port(port_mmio, cap, &emsg);
+		rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
 		if (rc)
 			dev_printk(KERN_WARNING, &pdev->dev,
 				   "%s (%d)\n", emsg, rc);
@@ -1327,7 +1340,8 @@ static int ahci_pci_device_resume(struct
 		if (rc)
 			return rc;
 
-		ahci_init_controller(mmio, pdev, host->n_ports, hpriv->cap);
+		ahci_init_controller(mmio, pdev, host->n_ports,
+				     host->ports[0]->flags, hpriv);
 	}
 
 	ata_host_resume(host);
@@ -1439,7 +1453,7 @@ static int ahci_host_init(struct ata_pro
 	struct ahci_host_priv *hpriv = probe_ent->private_data;
 	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
 	void __iomem *mmio = probe_ent->mmio_base;
-	unsigned int i, using_dac;
+	unsigned int i, cap_n_ports, using_dac;
 	int rc;
 
 	rc = ahci_reset_controller(mmio, pdev);
@@ -1448,10 +1462,34 @@ static int ahci_host_init(struct ata_pro
 
 	hpriv->cap = readl(mmio + HOST_CAP);
 	hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
-	probe_ent->n_ports = ahci_nr_ports(hpriv->cap);
+	cap_n_ports = ahci_nr_ports(hpriv->cap);
 
 	VPRINTK("cap 0x%x  port_map 0x%x  n_ports %d\n",
-		hpriv->cap, hpriv->port_map, probe_ent->n_ports);
+		hpriv->cap, hpriv->port_map, n_ports);
+
+	if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) {
+		unsigned int n_ports = cap_n_ports;
+		u32 port_map = hpriv->port_map;
+		int max_port = 0;
+
+		for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {
+			if (port_map & (1 << i)) {
+				n_ports--;
+				port_map &= ~(1 << i);
+				max_port = i;
+			} else
+				probe_ent->dummy_port_mask |= 1 << i;
+		}
+
+		if (n_ports || port_map)
+			dev_printk(KERN_WARNING, &pdev->dev,
+				   "nr_ports (%u) and implemented port map "
+				   "(0x%x) don't match\n",
+				   cap_n_ports, hpriv->port_map);
+
+		probe_ent->n_ports = max_port + 1;
+	} else
+		probe_ent->n_ports = cap_n_ports;
 
 	using_dac = hpriv->cap & HOST_CAP_64;
 	if (using_dac &&
@@ -1483,7 +1521,8 @@ static int ahci_host_init(struct ata_pro
 	for (i = 0; i < probe_ent->n_ports; i++)
 		ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i);
 
-	ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap);
+	ahci_init_controller(mmio, pdev, probe_ent->n_ports,
+			     probe_ent->port_flags, hpriv);
 
 	pci_set_master(pdev);
 

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

* Re: [PATCH 2/2 #upstream] ahci: honor PORTS_IMPL on ICH8s
  2006-11-02  3:20 ` [PATCH 2/2 #upstream] ahci: honor PORTS_IMPL on ICH8s Tejun Heo
@ 2006-11-06  1:05   ` Robin H. Johnson
  2006-11-07  9:54     ` Tejun Heo
  2006-11-09  6:08     ` Tejun Heo
  0 siblings, 2 replies; 8+ messages in thread
From: Robin H. Johnson @ 2006-11-06  1:05 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Jeff Garzik, robbat2, linux-ide

[-- Attachment #1: Type: text/plain, Size: 1095 bytes --]

On Thu, Nov 02, 2006 at 12:20:59PM +0900, Tejun Heo wrote:
> @@ -1439,7 +1453,7 @@ static int ahci_host_init(struct ata_pro
>  	struct ahci_host_priv *hpriv = probe_ent->private_data;
>  	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
>  	void __iomem *mmio = probe_ent->mmio_base;
> -	unsigned int i, using_dac;
> +	unsigned int i, cap_n_ports, using_dac;
>  	int rc;
>  
>  	rc = ahci_reset_controller(mmio, pdev);
> @@ -1448,10 +1462,34 @@ static int ahci_host_init(struct ata_pro
>  
>  	hpriv->cap = readl(mmio + HOST_CAP);
>  	hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
> -	probe_ent->n_ports = ahci_nr_ports(hpriv->cap);
> +	cap_n_ports = ahci_nr_ports(hpriv->cap);
>  
>  	VPRINTK("cap 0x%x  port_map 0x%x  n_ports %d\n",
> -		hpriv->cap, hpriv->port_map, probe_ent->n_ports);
> +		hpriv->cap, hpriv->port_map, n_ports);
n_ports is undefined here. Should be cap_n_ports instead.

Other than that, the two patches work perfectly.

-- 
Robin Hugh Johnson
E-Mail     : robbat2@gentoo.org
GnuPG FP   : 11AC BA4F 4778 E3F6 E4ED  F38E B27B 944E 3488 4E85

[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]

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

* Re: [PATCH 1/2 #upstream] ahci: preserve PORTS_IMPL over host resets
  2006-11-02  3:17 [PATCH 1/2 #upstream] ahci: preserve PORTS_IMPL over host resets Tejun Heo
  2006-11-02  3:20 ` [PATCH 2/2 #upstream] ahci: honor PORTS_IMPL on ICH8s Tejun Heo
@ 2006-11-07  9:46 ` Jeff Garzik
  1 sibling, 0 replies; 8+ messages in thread
From: Jeff Garzik @ 2006-11-07  9:46 UTC (permalink / raw)
  To: Tejun Heo; +Cc: robbat2, linux-ide

Tejun Heo wrote:
> Instead of writing 0xf blindly, preserve the content of write-once
> PORTS_IMPL register over host resets.
> 
> This patch is taken from Jeff Garzik's AHCI init update patch.
> 
> Signed-off-by: Tejun Heo <htejun@gmail.com>

applied



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

* Re: [PATCH 2/2 #upstream] ahci: honor PORTS_IMPL on ICH8s
  2006-11-06  1:05   ` Robin H. Johnson
@ 2006-11-07  9:54     ` Tejun Heo
  2006-11-09  6:08     ` Tejun Heo
  1 sibling, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2006-11-07  9:54 UTC (permalink / raw)
  To: Robin H. Johnson; +Cc: Jeff Garzik, linux-ide

Robin H. Johnson wrote:
> On Thu, Nov 02, 2006 at 12:20:59PM +0900, Tejun Heo wrote:
>> @@ -1439,7 +1453,7 @@ static int ahci_host_init(struct ata_pro
>>  	struct ahci_host_priv *hpriv = probe_ent->private_data;
>>  	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
>>  	void __iomem *mmio = probe_ent->mmio_base;
>> -	unsigned int i, using_dac;
>> +	unsigned int i, cap_n_ports, using_dac;
>>  	int rc;
>>  
>>  	rc = ahci_reset_controller(mmio, pdev);
>> @@ -1448,10 +1462,34 @@ static int ahci_host_init(struct ata_pro
>>  
>>  	hpriv->cap = readl(mmio + HOST_CAP);
>>  	hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
>> -	probe_ent->n_ports = ahci_nr_ports(hpriv->cap);
>> +	cap_n_ports = ahci_nr_ports(hpriv->cap);
>>  
>>  	VPRINTK("cap 0x%x  port_map 0x%x  n_ports %d\n",
>> -		hpriv->cap, hpriv->port_map, probe_ent->n_ports);
>> +		hpriv->cap, hpriv->port_map, n_ports);
> n_ports is undefined here. Should be cap_n_ports instead.
> 
> Other than that, the two patches work perfectly.

Thanks.  Forgot to drop that part again.  I'll post updated patch in a 
few hours.

-- 
tejun

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

* [PATCH 2/2 #upstream] ahci: honor PORTS_IMPL on ICH8s
  2006-11-06  1:05   ` Robin H. Johnson
  2006-11-07  9:54     ` Tejun Heo
@ 2006-11-09  6:08     ` Tejun Heo
  2006-11-11  2:37       ` Tejun Heo
  2006-11-14 18:45       ` Jeff Garzik
  1 sibling, 2 replies; 8+ messages in thread
From: Tejun Heo @ 2006-11-09  6:08 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Robin H. Johnson, linux-ide

Some ICH8s use non-linear port mapping.  ahci driver didn't use to
honor PORTS_IMPL and this made ports after hole nonfunctional.  This
patch makes ahci mark those ports as dummy and properly initialize all
the implemented ports after the dummies.

As it's unknown whether other AHCIs implement PORTS_IMPL register
properly, new board id board_ahci_pi is added and selectively applied
to ICH8s.  All other AHCIs continue to use linear mapping regardless
of PORTS_IMPL value.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Cc: Robin H. Johnson <robbat2@gentoo.org>
---

Two changes.

* AHCI_FLAG_HONOR_PI was changed to 1<<25.  1<<23 is not for LLD
  specific flags.

* VPRINTK() fixed as Robin H. Johnson pointed out.

Please apply.  Thanks.

 drivers/ata/ahci.c |   71 ++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index f24d197..b05e22f 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -53,6 +53,7 @@
 
 enum {
 	AHCI_PCI_BAR		= 5,
+	AHCI_MAX_PORTS		= 32,
 	AHCI_MAX_SG		= 168, /* hardware max is 64K */
 	AHCI_DMA_BOUNDARY	= 0xffffffff,
 	AHCI_USE_CLUSTERING	= 0,
@@ -77,7 +78,8 @@ enum {
 	RX_FIS_UNK		= 0x60, /* offset of Unknown FIS data */
 
 	board_ahci		= 0,
-	board_ahci_vt8251	= 1,
+	board_ahci_pi		= 1,
+	board_ahci_vt8251	= 2,
 
 	/* global controller registers */
 	HOST_CAP		= 0x00, /* host capabilities */
@@ -167,6 +169,7 @@ enum {
 
 	/* ap->flags bits */
 	AHCI_FLAG_NO_NCQ		= (1 << 24),
+	AHCI_FLAG_HONOR_PI		= (1 << 25), /* honor PORTS_IMPL */
 };
 
 struct ahci_cmd_hdr {
@@ -315,6 +318,16 @@ static const struct ata_port_info ahci_p
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &ahci_ops,
 	},
+	/* board_ahci_pi */
+	{
+		.sht		= &ahci_sht,
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+				  ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI,
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.port_ops	= &ahci_ops,
+	},
 	/* board_ahci_vt8251 */
 	{
 		.sht		= &ahci_sht,
@@ -340,11 +353,11 @@ static const struct pci_device_id ahci_p
 	{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
-	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
-	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
-	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
-	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
-	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
+	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci_pi }, /* ICH8 */
+	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_pi }, /* ICH8 */
+	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci_pi }, /* ICH8 */
+	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci_pi }, /* ICH8M */
+	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci_pi }, /* ICH8M */
 
 	/* JMicron */
 	{ PCI_VDEVICE(JMICRON, 0x2360), board_ahci }, /* JMicron JMB360 */
@@ -667,7 +680,8 @@ static int ahci_reset_controller(void __
 }
 
 static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
-				 int n_ports, u32 cap)
+				 int n_ports, unsigned int port_flags,
+				 struct ahci_host_priv *hpriv)
 {
 	int i, rc;
 	u32 tmp;
@@ -676,13 +690,12 @@ static void ahci_init_controller(void __
 		void __iomem *port_mmio = ahci_port_base(mmio, i);
 		const char *emsg = NULL;
 
-#if 0 /* BIOSen initialize this incorrectly */
-		if (!(hpriv->port_map & (1 << i)))
+		if ((port_flags & AHCI_FLAG_HONOR_PI) &&
+		    !(hpriv->port_map & (1 << i)))
 			continue;
-#endif
 
 		/* make sure port is not active */
-		rc = ahci_deinit_port(port_mmio, cap, &emsg);
+		rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
 		if (rc)
 			dev_printk(KERN_WARNING, &pdev->dev,
 				   "%s (%d)\n", emsg, rc);
@@ -1335,7 +1348,8 @@ static int ahci_pci_device_resume(struct
 		if (rc)
 			return rc;
 
-		ahci_init_controller(mmio, pdev, host->n_ports, hpriv->cap);
+		ahci_init_controller(mmio, pdev, host->n_ports,
+				     host->ports[0]->flags, hpriv);
 	}
 
 	ata_host_resume(host);
@@ -1447,7 +1461,7 @@ static int ahci_host_init(struct ata_pro
 	struct ahci_host_priv *hpriv = probe_ent->private_data;
 	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
 	void __iomem *mmio = probe_ent->mmio_base;
-	unsigned int i, using_dac;
+	unsigned int i, cap_n_ports, using_dac;
 	int rc;
 
 	rc = ahci_reset_controller(mmio, pdev);
@@ -1456,10 +1470,34 @@ static int ahci_host_init(struct ata_pro
 
 	hpriv->cap = readl(mmio + HOST_CAP);
 	hpriv->port_map = readl(mmio + HOST_PORTS_IMPL);
-	probe_ent->n_ports = ahci_nr_ports(hpriv->cap);
+	cap_n_ports = ahci_nr_ports(hpriv->cap);
 
 	VPRINTK("cap 0x%x  port_map 0x%x  n_ports %d\n",
-		hpriv->cap, hpriv->port_map, probe_ent->n_ports);
+		hpriv->cap, hpriv->port_map, cap_n_ports);
+
+	if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) {
+		unsigned int n_ports = cap_n_ports;
+		u32 port_map = hpriv->port_map;
+		int max_port = 0;
+
+		for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {
+			if (port_map & (1 << i)) {
+				n_ports--;
+				port_map &= ~(1 << i);
+				max_port = i;
+			} else
+				probe_ent->dummy_port_mask |= 1 << i;
+		}
+
+		if (n_ports || port_map)
+			dev_printk(KERN_WARNING, &pdev->dev,
+				   "nr_ports (%u) and implemented port map "
+				   "(0x%x) don't match\n",
+				   cap_n_ports, hpriv->port_map);
+
+		probe_ent->n_ports = max_port + 1;
+	} else
+		probe_ent->n_ports = cap_n_ports;
 
 	using_dac = hpriv->cap & HOST_CAP_64;
 	if (using_dac &&
@@ -1491,7 +1529,8 @@ static int ahci_host_init(struct ata_pro
 	for (i = 0; i < probe_ent->n_ports; i++)
 		ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i);
 
-	ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap);
+	ahci_init_controller(mmio, pdev, probe_ent->n_ports,
+			     probe_ent->port_flags, hpriv);
 
 	pci_set_master(pdev);
 
-- 
1.4.3.3


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

* Re: [PATCH 2/2 #upstream] ahci: honor PORTS_IMPL on ICH8s
  2006-11-09  6:08     ` Tejun Heo
@ 2006-11-11  2:37       ` Tejun Heo
  2006-11-14 18:45       ` Jeff Garzik
  1 sibling, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2006-11-11  2:37 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Jeff Garzik, Robin H. Johnson, linux-ide

Tejun Heo wrote:
> Some ICH8s use non-linear port mapping.  ahci driver didn't use to
> honor PORTS_IMPL and this made ports after hole nonfunctional.  This
> patch makes ahci mark those ports as dummy and properly initialize all
> the implemented ports after the dummies.
> 
> As it's unknown whether other AHCIs implement PORTS_IMPL register
> properly, new board id board_ahci_pi is added and selectively applied
> to ICH8s.  All other AHCIs continue to use linear mapping regardless
> of PORTS_IMPL value.
> 
> Signed-off-by: Tejun Heo <htejun@gmail.com>
> Cc: Robin H. Johnson <robbat2@gentoo.org>
> ---
> 
> Two changes.
> 
> * AHCI_FLAG_HONOR_PI was changed to 1<<25.  1<<23 is not for LLD
>   specific flags.
> 
> * VPRINTK() fixed as Robin H. Johnson pointed out.

Jeff, I think this should go into #upstream-fixes too.  It's not as dumb 
as adding a PCI ID but it's adding support for a highly popular hardware 
and "wait for 2.6.20 for ICH8 support" just sucks.

Thanks.

-- 
tejun

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

* Re: [PATCH 2/2 #upstream] ahci: honor PORTS_IMPL on ICH8s
  2006-11-09  6:08     ` Tejun Heo
  2006-11-11  2:37       ` Tejun Heo
@ 2006-11-14 18:45       ` Jeff Garzik
  1 sibling, 0 replies; 8+ messages in thread
From: Jeff Garzik @ 2006-11-14 18:45 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Robin H. Johnson, linux-ide

Tejun Heo wrote:
> Some ICH8s use non-linear port mapping.  ahci driver didn't use to
> honor PORTS_IMPL and this made ports after hole nonfunctional.  This
> patch makes ahci mark those ports as dummy and properly initialize all
> the implemented ports after the dummies.
> 
> As it's unknown whether other AHCIs implement PORTS_IMPL register
> properly, new board id board_ahci_pi is added and selectively applied
> to ICH8s.  All other AHCIs continue to use linear mapping regardless
> of PORTS_IMPL value.
> 
> Signed-off-by: Tejun Heo <htejun@gmail.com>
> Cc: Robin H. Johnson <robbat2@gentoo.org>
> ---
> 
> Two changes.
> 
> * AHCI_FLAG_HONOR_PI was changed to 1<<25.  1<<23 is not for LLD
>   specific flags.
> 
> * VPRINTK() fixed as Robin H. Johnson pointed out.

applied



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

end of thread, other threads:[~2006-11-14 18:46 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-02  3:17 [PATCH 1/2 #upstream] ahci: preserve PORTS_IMPL over host resets Tejun Heo
2006-11-02  3:20 ` [PATCH 2/2 #upstream] ahci: honor PORTS_IMPL on ICH8s Tejun Heo
2006-11-06  1:05   ` Robin H. Johnson
2006-11-07  9:54     ` Tejun Heo
2006-11-09  6:08     ` Tejun Heo
2006-11-11  2:37       ` Tejun Heo
2006-11-14 18:45       ` Jeff Garzik
2006-11-07  9:46 ` [PATCH 1/2 #upstream] ahci: preserve PORTS_IMPL over host resets Jeff Garzik

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).