diff mbox series

lewisburg map/pcs register handling

Message ID CAF2xp_HuE+aV3ZhrC0E9CQopYgTQ4AHcK15v248AVgxXn8A0pA@mail.gmail.com
State Not Applicable
Delegated to: David Miller
Headers show
Series lewisburg map/pcs register handling | expand

Commit Message

Peter Chang Nov. 14, 2017, 11:55 p.m. UTC
mostly, intel made the registers wider so that the offsets aren't
right. it only matters if you don't populate all the ports and aren't
using the first port.

\p

Comments

Tejun Heo Nov. 27, 2017, 7:25 p.m. UTC | #1
Hello, Peter.

On Tue, Nov 14, 2017 at 03:55:12PM -0800, Peter Chang wrote:
> From 62ccc6118960204769809a1ea9d162cf2c1c95e1 Mon Sep 17 00:00:00 2001
> From: peter chang <dpf@google.com>
> Date: Tue, 14 Nov 2017 13:43:15 -0800
> Subject: [PATCH] ahci: lewisburg MAP / PCS register handling
> 
> registers are now 32-bits and the existing offsets mean that the
> wrong registers are being updated.
> 
> Change-Id: I992b31bc9e789f9dfbeb29afeb0b7777e325ea71

Can you please drop Change-Id and add Signed-off-by?  Also, the
earlier part of the email where you explained what's going on was
actually easier to understand.  Maybe put that in the description?

> -		pci_read_config_word(pdev, 0x92, &tmp16);
> -		if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
> -			tmp16 |= hpriv->port_map;
> -			pci_write_config_word(pdev, 0x92, tmp16);
> +		if (hpriv->flags & AHCI_HFLAG_32BIT_MAP_PCS)
> +			pci_read_config_dword(pdev, 0x94, &tmp32);
> +		else {
> +			pci_read_config_word(pdev, 0x92, &tmp16);
> +			tmp32 = tmp16;
> +		}

The coding style says that we always add {} to both if and else bodies.

> +		if ((tmp32 & hpriv->port_map) != hpriv->port_map) {
> +			tmp32 |= hpriv->port_map;
> +			if (hpriv->flags & AHCI_HFLAG_32BIT_MAP_PCS)
> +				pci_write_config_dword(pdev, 0x94, tmp32);
> +			else {
> +				tmp16 = tmp32;
> +				pci_write_config_word(pdev, 0x92, tmp16);
> +			}

@@ -523,6 +524,24 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
>  		port_map &= hpriv->mask_port_map;
>  	}
>  
> +	if (hpriv->flags & AHCI_HFLAG_PCI_PORT_MAP) {
> +		struct pci_dev *pdev = to_pci_dev(dev);
> +		u16 disabled;
> +
> +		if (hpriv->flags & AHCI_HFLAG_32BIT_MAP_PCS) {
> +			u32 tmp;
> +
> +			pci_read_config_dword(pdev, 0x90, &tmp);
> +			disabled = (tmp >> 16) & 0xffff;
> +		} else {
> +			pci_read_config_word(pdev, 0x90, &disabled);
> +			disabled = (disabled >> 8) & 0xff;
> +		}
> +
> +		dev_info(dev, "port_map:%x disabled:%x\n", port_map, disabled);
> +		port_map &= ~disabled;
> +	}

And the patch description doesn't explain the above chunk.  Can you
please explain this part too?

Thanks.
diff mbox series

Patch

From 62ccc6118960204769809a1ea9d162cf2c1c95e1 Mon Sep 17 00:00:00 2001
From: peter chang <dpf@google.com>
Date: Tue, 14 Nov 2017 13:43:15 -0800
Subject: [PATCH] ahci: lewisburg MAP / PCS register handling

registers are now 32-bits and the existing offsets mean that the
wrong registers are being updated.

Change-Id: I992b31bc9e789f9dfbeb29afeb0b7777e325ea71
---
 drivers/ata/ahci.c    | 34 +++++++++++++++++++++++++++-------
 drivers/ata/ahci.h    |  4 ++++
 drivers/ata/libahci.c | 19 +++++++++++++++++++
 3 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 9f78bb03bb76..16b0fac9f0ae 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -71,6 +71,7 @@  enum board_ids {
 
 	/* board IDs for specific chipsets in alphabetical order */
 	board_ahci_avn,
+	board_ahci_lbg,
 	board_ahci_mcp65,
 	board_ahci_mcp77,
 	board_ahci_mcp89,
@@ -174,6 +175,14 @@  static const struct ata_port_info ahci_port_info[] = {
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_avn_ops,
 	},
+	[board_ahci_lbg] = {
+		AHCI_HFLAGS	(AHCI_HFLAG_32BIT_MAP_PCS |
+				 AHCI_HFLAG_PCI_PORT_MAP),
+		.flags		= AHCI_FLAG_COMMON,
+		.pio_mask	= ATA_PIO4,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_ops,
+	},
 	[board_ahci_mcp65] = {
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
 				 AHCI_HFLAG_YES_NCQ),
@@ -374,14 +383,14 @@  static const struct pci_device_id ahci_pci_tbl[] = {
 	{ PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
 	{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
-	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/
+	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci_lbg }, /* Lewisburg AHCI*/
 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
 	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/
-	{ PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
+	{ PCI_VDEVICE(INTEL, 0xa182), board_ahci_lbg }, /* Lewisburg AHCI*/
 	{ PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
 	{ PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
 	{ PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
-	{ PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
+	{ PCI_VDEVICE(INTEL, 0xa202), board_ahci_lbg }, /* Lewisburg AHCI*/
 	{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
 	{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
 	{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
@@ -630,12 +639,23 @@  static int ahci_pci_reset_controller(struct ata_host *host)
 	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
 		struct ahci_host_priv *hpriv = host->private_data;
 		u16 tmp16;
+		u32 tmp32;
 
 		/* configure PCS */
-		pci_read_config_word(pdev, 0x92, &tmp16);
-		if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
-			tmp16 |= hpriv->port_map;
-			pci_write_config_word(pdev, 0x92, tmp16);
+		if (hpriv->flags & AHCI_HFLAG_32BIT_MAP_PCS)
+			pci_read_config_dword(pdev, 0x94, &tmp32);
+		else {
+			pci_read_config_word(pdev, 0x92, &tmp16);
+			tmp32 = tmp16;
+		}
+		if ((tmp32 & hpriv->port_map) != hpriv->port_map) {
+			tmp32 |= hpriv->port_map;
+			if (hpriv->flags & AHCI_HFLAG_32BIT_MAP_PCS)
+				pci_write_config_dword(pdev, 0x94, tmp32);
+			else {
+				tmp16 = tmp32;
+				pci_write_config_word(pdev, 0x92, tmp16);
+			}
 		}
 	}
 
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 8b61123d2c3c..a649107027de 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -251,6 +251,10 @@  enum {
 	AHCI_HFLAG_YES_ALPM		= (1 << 23), /* force ALPM cap on */
 	AHCI_HFLAG_NO_WRITE_TO_RO	= (1 << 24), /* don't write to read
 							only registers */
+        AHCI_HFLAG_32BIT_MAP_PCS	= (1 << 25), /* MAP/PCS register
+                                                        32-bits wide */
+        AHCI_HFLAG_PCI_PORT_MAP		= (1 << 26), /* port map in pci
+                                                        config space */
 
 	/* ap->flags bits */
 
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 3e286d86ab42..e65481d8e362 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -40,6 +40,7 @@ 
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
+#include <linux/pci.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
@@ -523,6 +524,24 @@  void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 		port_map &= hpriv->mask_port_map;
 	}
 
+	if (hpriv->flags & AHCI_HFLAG_PCI_PORT_MAP) {
+		struct pci_dev *pdev = to_pci_dev(dev);
+		u16 disabled;
+
+		if (hpriv->flags & AHCI_HFLAG_32BIT_MAP_PCS) {
+			u32 tmp;
+
+			pci_read_config_dword(pdev, 0x90, &tmp);
+			disabled = (tmp >> 16) & 0xffff;
+		} else {
+			pci_read_config_word(pdev, 0x90, &disabled);
+			disabled = (disabled >> 8) & 0xff;
+		}
+
+		dev_info(dev, "port_map:%x disabled:%x\n", port_map, disabled);
+		port_map &= ~disabled;
+	}
+
 	/* cross check port_map and cap.n_ports */
 	if (port_map) {
 		int map_ports = 0;
-- 
2.15.0.448.gf294e3d99a-goog