From: Mac Lin <redacted>
CNS3xxx override the softreset function of ahci_platform ahci_softreset by
cns3xxx_ahci_softreset, which would retry ahci_do_softreset again with pmp=0 if
pmp=15 failed, for the controller has problem receiving D2H Reg FIS of the
different PMP setting of the previous sent H2D Reg FIS.
Following describe the isssue with original ahci_platform driver on
linux-2.6.37-rc3, arm/cns3xxx.
If CONFIG_SATA_PMP is enabled, while not using multiplier and connect the disks
directly to the board, the disk cannot be found due to software reset always
failed.
? ?ahci ahci.0: forcing PORTS_IMPL to 0x3
? ?ahci ahci.0: AHCI 0001.0100 32 slots 2 ports 3 Gbps 0x3 impl platform mode
? ?ahci ahci.0: flags: ncq sntf pm led clo only pmp pio slum part ccc
? ?scsi0 : ahci_platform
? ?scsi1 : ahci_platform
? ?ata1: SATA max UDMA/133 irq_stat 0x00400040, connection status changed irq 65
? ?ata2: SATA max UDMA/133 mmio [mem 0x83000000-0x83ffffff] port 0x180 irq 65
? ?ata2: SATA link down (SStatus 0 SControl 300)
? ?ata1: link is slow to respond, please be patient (ready=0)
? ?ata1: softreset failed (device not ready)
? ?ata1: link is slow to respond, please be patient (ready=0)
? ?ata1: softreset failed (device not ready)
? ?ata1: link is slow to respond, please be patient (ready=0)
? ?ata1: softreset failed (device not ready)
? ?ata1: limiting SATA link speed to 1.5 Gbps
? ?ata1: SATA link down (SStatus 1 SControl 310)
While using multiplier with CONFIG_SATA_PMP enabled, or using disks directly
without CONFIG_SATA_PMP have no issue. It seems the device is sending D2H Reg
FIS, but controller is not reflecting it on any known means.
Signed-off-by: Mac Lin <redacted>
---
?arch/arm/mach-cns3xxx/devices.c | ? ?2 +-
?drivers/ata/Kconfig ? ? ? ? ? ? | ? 11 +++++++++++
?drivers/ata/ahci_platform.c ? ? | ? 39 +++++++++++++++++++++++++++++++++++++++
?3 files changed, 51 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-cns3xxx/devices.c b/arch/arm/mach-cns3xxx/devices.c
index 50b4d31..b496f02 100644
--- a/arch/arm/mach-cns3xxx/devices.c
+++ b/arch/arm/mach-cns3xxx/devices.c
@@ -40,7 +40,7 @@ static struct resource cns3xxx_ahci_resource[] = {?static u64 cns3xxx_ahci_dmamask = DMA_BIT_MASK(32);
?static struct platform_device cns3xxx_ahci_pdev = {
- ? ? ? .name ? ? ? ? ? = "ahci",
+ ? ? ? .name ? ? ? ? ? = "ahci-cns3xxx",
? ? ? ?.id ? ? ? ? ? ? = 0,
? ? ? ?.resource ? ? ? = cns3xxx_ahci_resource,
? ? ? ?.num_resources ?= ARRAY_SIZE(cns3xxx_ahci_resource),diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 36e2319..5d8b1a3 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -75,6 +75,17 @@ config SATA_AHCI_PLATFORM
? ? ? ? ?If unsure, say N.
+config SATA_AHCI_CNS3XXX
+ ? ? ? bool "AHCI Support on the Cavium Networks CNS3xxx SOC"
+ ? ? ? depends on ARCH_CNS3XXX
+ ? ? ? depends on SATA_AHCI_PLATFORM
+ ? ? ? help
+ ? ? ? ? This option enables AHCI platform driver to support CNS3xxx
+ ? ? ? ? System-on-Chip devices. This is only needed when using CNS3xxx AHCI
+ ? ? ? ? controller.
+
+ ? ? ? ? If unsure, say N.
+
?config SATA_FSL
? ? ? ?tristate "Freescale 3.0Gbps SATA support"
? ? ? ?depends on FSL_SOC
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 25d98c8..7d6957f 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -176,8 +176,47 @@ static int __devexit ahci_remove(struct platform_device *pdev)
? ? ? ?return 0;
?}
+#ifdef CONFIG_SATA_AHCI_CNS3XXX
+/*
+ * TODO: move cns3xxx_ahci_init to here after cns3xxx_pwr*() calls are
+ * thread-safe
+ */
+
+static int cns3xxx_ahci_softreset(struct ata_link *link, unsigned int *class,
+ ? ? ? ? ? ? ? ? ? ? ? ? unsigned long deadline)
+{
+ ? ? ? int pmp = sata_srst_pmp(link);
+ ? ? ? int ret;
+
+ ? ? ? ret = ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
+ ? ? ? if (pmp && ret)
+ ? ? ? ? ? ? ? return ahci_do_softreset(link, class, 0, deadline,
+ ? ? ? ? ? ? ? ? ? ? ? ahci_check_ready);
+ ? ? ? return ret;
+}
+
+static struct ata_port_operations cns3xxx_ahci_ops = {
+ ? ? ? .inherits ? ? ? ? ? ? ? = &ahci_ops,
+ ? ? ? .softreset ? ? ? ? ? ? ?= cns3xxx_ahci_softreset,
+};
+
+static const struct ata_port_info cns3xxx_ata_port_info = {
+ ? ? ? .flags ? ? ? ? ?= AHCI_FLAG_COMMON,
+ ? ? ? .pio_mask ? ? ? = ATA_PIO4,
+ ? ? ? .udma_mask ? ? ?= ATA_UDMA6,
+ ? ? ? .port_ops ? ? ? = &cns3xxx_ahci_ops,
+};
+
+struct ahci_platform_data cns3xxx_ahci_platform_data = {
+ ? ? ? .ata_port_info ?= &cns3xxx_ata_port_info,
+};
+#endif
+
?static const struct platform_device_id ahci_pltfm_ids[] = {
? ? ? ?{ "ahci", },
+#ifdef CONFIG_SATA_AHCI_CNS3XXX
+ ? ? ? { "ahci-cns3xxx", (kernel_ulong_t)&cns3xxx_ahci_platform_data},
+#endif
? ? ? ?{ },
?};
?MODULE_DEVICE_TABLE(platform, ahci_pltfm_ids);
--
1.7.3