aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorSuman Tripathi <stripathi@apm.com>2014-08-28 05:21:22 -0400
committerTejun Heo <tj@kernel.org>2014-09-05 22:27:15 -0400
commit0babe614b6b4c7d1d8e12d7a6dbdac6e2f0df8e2 (patch)
tree9b8a3801e8c01a369ea4d81e1486cf7ce7b3b40d /drivers/ata
parent0bed13bebd6c99d097796d2ca6c4f10fb5b2eabc (diff)
ahci_xgene: Fix the link down in first attempt for the APM X-Gene SoC AHCI SATA host controller driver.
Due to HW errata the APM X-Gene AHCI SATA host controller reports link down even if the device presence is detected. This issue is due to speed negotiation failure. This patch implements the algorithm to retry the COMRESET if PxSTAT register reports device presence detected but PHY communication not established. The maximum retry attempts are 3. This patch also fixes the code to match the algorithm for the printing a warning message if the disparity error still exists after link up. Signed-off-by: Loc Ho <lho@apm.com> Signed-off-by: Suman Tripathi <stripathi@apm.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci_xgene.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index 37501fd0973d..f03aab187f4d 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -78,6 +78,9 @@
78#define CFG_MEM_RAM_SHUTDOWN 0x00000070 78#define CFG_MEM_RAM_SHUTDOWN 0x00000070
79#define BLOCK_MEM_RDY 0x00000074 79#define BLOCK_MEM_RDY 0x00000074
80 80
81/* Max retry for link down */
82#define MAX_LINK_DOWN_RETRY 3
83
81struct xgene_ahci_context { 84struct xgene_ahci_context {
82 struct ahci_host_priv *hpriv; 85 struct ahci_host_priv *hpriv;
83 struct device *dev; 86 struct device *dev;
@@ -237,8 +240,11 @@ static void xgene_ahci_set_phy_cfg(struct xgene_ahci_context *ctx, int channel)
237 * and Gen1 (1.5Gbps). Otherwise during long IO stress test, the PHY will 240 * and Gen1 (1.5Gbps). Otherwise during long IO stress test, the PHY will
238 * report disparity error and etc. In addition, during COMRESET, there can 241 * report disparity error and etc. In addition, during COMRESET, there can
239 * be error reported in the register PORT_SCR_ERR. For SERR_DISPARITY and 242 * be error reported in the register PORT_SCR_ERR. For SERR_DISPARITY and
240 * SERR_10B_8B_ERR, the PHY receiver line must be reseted. The following 243 * SERR_10B_8B_ERR, the PHY receiver line must be reseted. Also during long
241 * algorithm is followed to proper configure the hardware PHY during COMRESET: 244 * reboot cycle regression, sometimes the PHY reports link down even if the
245 * device is present because of speed negotiation failure. so need to retry
246 * the COMRESET to get the link up. The following algorithm is followed to
247 * proper configure the hardware PHY during COMRESET:
242 * 248 *
243 * Alg Part 1: 249 * Alg Part 1:
244 * 1. Start the PHY at Gen3 speed (default setting) 250 * 1. Start the PHY at Gen3 speed (default setting)
@@ -254,9 +260,15 @@ static void xgene_ahci_set_phy_cfg(struct xgene_ahci_context *ctx, int channel)
254 * Alg Part 2: 260 * Alg Part 2:
255 * 1. On link up, if there are any SERR_DISPARITY and SERR_10B_8B_ERR error 261 * 1. On link up, if there are any SERR_DISPARITY and SERR_10B_8B_ERR error
256 * reported in the register PORT_SCR_ERR, then reset the PHY receiver line 262 * reported in the register PORT_SCR_ERR, then reset the PHY receiver line
257 * 2. Go to Alg Part 3 263 * 2. Go to Alg Part 4
258 * 264 *
259 * Alg Part 3: 265 * Alg Part 3:
266 * 1. Check the PORT_SCR_STAT to see whether device presence detected but PHY
267 * communication establishment failed and maximum link down attempts are
268 * less than Max attempts 3 then goto Alg Part 1.
269 * 2. Go to Alg Part 4.
270 *
271 * Alg Part 4:
260 * 1. Clear any pending from register PORT_SCR_ERR. 272 * 1. Clear any pending from register PORT_SCR_ERR.
261 * 273 *
262 * NOTE: For the initial version, we will NOT support Gen1/Gen2. In addition 274 * NOTE: For the initial version, we will NOT support Gen1/Gen2. In addition
@@ -275,19 +287,27 @@ static int xgene_ahci_do_hardreset(struct ata_link *link,
275 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 287 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
276 void __iomem *port_mmio = ahci_port_base(ap); 288 void __iomem *port_mmio = ahci_port_base(ap);
277 struct ata_taskfile tf; 289 struct ata_taskfile tf;
290 int link_down_retry = 0;
278 int rc; 291 int rc;
279 u32 val; 292 u32 val, sstatus;
280 293
281 /* clear D2H reception area to properly wait for D2H FIS */ 294 do {
282 ata_tf_init(link->device, &tf); 295 /* clear D2H reception area to properly wait for D2H FIS */
283 tf.command = ATA_BUSY; 296 ata_tf_init(link->device, &tf);
284 ata_tf_to_fis(&tf, 0, 0, d2h_fis); 297 tf.command = ATA_BUSY;
285 rc = sata_link_hardreset(link, timing, deadline, online, 298 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
299 rc = sata_link_hardreset(link, timing, deadline, online,
286 ahci_check_ready); 300 ahci_check_ready);
287 301 if (*online) {
288 val = readl(port_mmio + PORT_SCR_ERR); 302 val = readl(port_mmio + PORT_SCR_ERR);
289 if (val & (SERR_DISPARITY | SERR_10B_8B_ERR)) 303 if (val & (SERR_DISPARITY | SERR_10B_8B_ERR))
290 dev_warn(ctx->dev, "link has error\n"); 304 dev_warn(ctx->dev, "link has error\n");
305 break;
306 }
307
308 sata_scr_read(link, SCR_STATUS, &sstatus);
309 } while (link_down_retry++ < MAX_LINK_DOWN_RETRY &&
310 (sstatus & 0xff) == 0x1);
291 311
292 /* clear all errors if any pending */ 312 /* clear all errors if any pending */
293 val = readl(port_mmio + PORT_SCR_ERR); 313 val = readl(port_mmio + PORT_SCR_ERR);