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