Pablo Greco 7b2c62
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Pablo Greco 7b2c62
From: Robert Richter <rrichter@redhat.com>
Pablo Greco 7b2c62
Date: Thu, 7 Jun 2018 22:59:33 -0400
Pablo Greco 7b2c62
Subject: [PATCH] ahci: thunderx2: Fix for errata that affects stop engine
Pablo Greco 7b2c62
Pablo Greco 7b2c62
Message-id: <1528412373-19128-3-git-send-email-rrichter@redhat.com>
Pablo Greco 7b2c62
Patchwork-id: 220952
Pablo Greco 7b2c62
O-Subject: [RHEL-8.0 BZ 1563590 v2 2/2] ahci: thunderx2: Fix for errata that affects stop engine
Pablo Greco 7b2c62
Bugzilla: 1563590
Pablo Greco 7b2c62
RH-Acked-by: Dean Nelson <dnelson@redhat.com>
Pablo Greco 7b2c62
RH-Acked-by: Mark Langsdorf <mlangsdo@redhat.com>
Pablo Greco 7b2c62
RH-Acked-by: Mark Salter <msalter@redhat.com>
Pablo Greco 7b2c62
Pablo Greco 7b2c62
From: Jayachandran C <jnair@caviumnetworks.com>
Pablo Greco 7b2c62
Pablo Greco 7b2c62
Apply workaround for this errata:
Pablo Greco 7b2c62
  Synopsis: Resetting PxCMD.ST may hang the SATA device
Pablo Greco 7b2c62
Pablo Greco 7b2c62
  Description: An internal ping-pong buffer state is not reset
Pablo Greco 7b2c62
  correctly for an PxCMD.ST=0 command for a SATA channel. This
Pablo Greco 7b2c62
  may cause the SATA interface to hang when a PxCMD.ST=0 command
Pablo Greco 7b2c62
  is received.
Pablo Greco 7b2c62
Pablo Greco 7b2c62
  Workaround: A SATA_BIU_CORE_ENABLE.sw_init_bsi must be asserted
Pablo Greco 7b2c62
  by the driver whenever the PxCMD.ST needs to be de-asserted. This
Pablo Greco 7b2c62
  will reset both the ports. So, it may not always work in a 2
Pablo Greco 7b2c62
  channel SATA system.
Pablo Greco 7b2c62
Pablo Greco 7b2c62
  Resolution: Fix in B0.
Pablo Greco 7b2c62
Pablo Greco 7b2c62
Add the code to ahci_stop_engine() to do this. It is not easy to
Pablo Greco 7b2c62
stop the other "port" since it is associated with a different AHCI
Pablo Greco 7b2c62
interface. Please note that with this fix, SATA reset does not
Pablo Greco 7b2c62
hang any more, but it can cause failures on the other interface
Pablo Greco 7b2c62
if that is in active use.
Pablo Greco 7b2c62
Pablo Greco 7b2c62
Unfortunately, we have nothing other the the CPU ID to check if the
Pablo Greco 7b2c62
SATA block has this issue.
Pablo Greco 7b2c62
Pablo Greco 7b2c62
RHEL-only:
Pablo Greco 7b2c62
Pablo Greco 7b2c62
Both patches are in RHEL-7.6 also. Inclusion of the patches into RHEL-8
Pablo Greco 7b2c62
was discussed. Since there are partners with Ax system configurations it
Pablo Greco 7b2c62
was decided to carry them in RHEL8 too. See:
Pablo Greco 7b2c62
Pablo Greco 7b2c62
 https://bugzilla.redhat.com/show_bug.cgi?id=1563590#c1
Pablo Greco 7b2c62
Pablo Greco 7b2c62
[v3 with new delays]
Pablo Greco 7b2c62
Signed-off-by: Jayachandran C <jnair@caviumnetworks.com>
Pablo Greco 7b2c62
Pablo Greco 7b2c62
Upstream Status: RHEL only
Pablo Greco 7b2c62
Signed-off-by: Robert Richter <rrichter@redhat.com>
Pablo Greco 7b2c62
Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
Pablo Greco 7b2c62
---
Pablo Greco 7b2c62
 drivers/ata/libahci.c | 18 ++++++++++++++++++
Pablo Greco 7b2c62
 1 file changed, 18 insertions(+)
Pablo Greco 7b2c62
Pablo Greco 7b2c62
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
Pablo Greco 7b2c62
index ea5bf5f4cbed..71c55cae27ac 100644
Pablo Greco 7b2c62
--- a/drivers/ata/libahci.c
Pablo Greco 7b2c62
+++ b/drivers/ata/libahci.c
Pablo Greco 7b2c62
@@ -666,6 +666,24 @@ int ahci_stop_engine(struct ata_port *ap)
Pablo Greco 7b2c62
 	tmp &= ~PORT_CMD_START;
Pablo Greco 7b2c62
 	writel(tmp, port_mmio + PORT_CMD);
Pablo Greco 7b2c62
Pablo Greco 7b2c62
+#ifdef CONFIG_ARM64
Pablo Greco 7b2c62
+	/* Rev Ax of Cavium CN99XX needs a hack for port stop */
Pablo Greco 7b2c62
+	if (dev_is_pci(ap->host->dev) &&
Pablo Greco 7b2c62
+	    to_pci_dev(ap->host->dev)->vendor == 0x14e4 &&
Pablo Greco 7b2c62
+	    to_pci_dev(ap->host->dev)->device == 0x9027 &&
Pablo Greco 7b2c62
+	    midr_is_cpu_model_range(read_cpuid_id(),
Pablo Greco 7b2c62
+			MIDR_CPU_MODEL(ARM_CPU_IMP_BRCM, BRCM_CPU_PART_VULCAN),
Pablo Greco 7b2c62
+			MIDR_CPU_VAR_REV(0, 0),
Pablo Greco 7b2c62
+			MIDR_CPU_VAR_REV(0, MIDR_REVISION_MASK))) {
Pablo Greco 7b2c62
+		tmp = readl(hpriv->mmio + 0x8000);
Pablo Greco 7b2c62
+		udelay(100);
Pablo Greco 7b2c62
+		writel(tmp | (1 << 26), hpriv->mmio + 0x8000);
Pablo Greco 7b2c62
+		udelay(100);
Pablo Greco 7b2c62
+		writel(tmp & ~(1 << 26), hpriv->mmio + 0x8000);
Pablo Greco 7b2c62
+		dev_warn(ap->host->dev, "CN99XX SATA reset workaround applied\n");
Pablo Greco 7b2c62
+	}
Pablo Greco 7b2c62
+#endif
Pablo Greco 7b2c62
+
Pablo Greco 7b2c62
 	/* wait for engine to stop. This could be as long as 500 msec */
Pablo Greco 7b2c62
 	tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
Pablo Greco 7b2c62
 				PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
Pablo Greco 7b2c62
-- 
Pablo Greco 7b2c62
2.28.0
Pablo Greco 7b2c62