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