aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Lord <liml@rtr.ca>2008-04-16 14:56:12 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-04-17 15:56:05 -0400
commit0d8be5cbff8fd95da72d749a64e150b851f470c6 (patch)
tree2c7458b87aea315bb546053a0acc20839ab09a0f
parentf3360ebffae254ab99a64bf97c7b4f8380b1e114 (diff)
sata_mv hardreset rework
Rework and simplify sata_mv's hardreset code to take advantage of libata improvements since it was first coded. Also, get rid of the now unnecessary prereset, postreset, and phy_reset functions. This patch also paves the way for subsequent pmp support patches, which will follow once this one passes muster. Signed-off-by: Mark Lord <mlord@pobox.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/ata/sata_mv.c160
1 files changed, 22 insertions, 138 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index fa75df634c75..3e2f779ae9c6 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -478,10 +478,8 @@ static void mv_port_stop(struct ata_port *ap);
478static void mv_qc_prep(struct ata_queued_cmd *qc); 478static void mv_qc_prep(struct ata_queued_cmd *qc);
479static void mv_qc_prep_iie(struct ata_queued_cmd *qc); 479static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
480static unsigned int mv_qc_issue(struct ata_queued_cmd *qc); 480static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
481static int mv_prereset(struct ata_link *link, unsigned long deadline);
482static int mv_hardreset(struct ata_link *link, unsigned int *class, 481static int mv_hardreset(struct ata_link *link, unsigned int *class,
483 unsigned long deadline); 482 unsigned long deadline);
484static void mv_postreset(struct ata_link *link, unsigned int *classes);
485static void mv_eh_freeze(struct ata_port *ap); 483static void mv_eh_freeze(struct ata_port *ap);
486static void mv_eh_thaw(struct ata_port *ap); 484static void mv_eh_thaw(struct ata_port *ap);
487static void mv6_dev_config(struct ata_device *dev); 485static void mv6_dev_config(struct ata_device *dev);
@@ -545,9 +543,7 @@ static struct ata_port_operations mv5_ops = {
545 543
546 .freeze = mv_eh_freeze, 544 .freeze = mv_eh_freeze,
547 .thaw = mv_eh_thaw, 545 .thaw = mv_eh_thaw,
548 .prereset = mv_prereset,
549 .hardreset = mv_hardreset, 546 .hardreset = mv_hardreset,
550 .postreset = mv_postreset,
551 .error_handler = ata_std_error_handler, /* avoid SFF EH */ 547 .error_handler = ata_std_error_handler, /* avoid SFF EH */
552 .post_internal_cmd = ATA_OP_NULL, 548 .post_internal_cmd = ATA_OP_NULL,
553 549
@@ -1904,7 +1900,6 @@ static void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
1904 * (but doesn't say what the problem might be). So we first try 1900 * (but doesn't say what the problem might be). So we first try
1905 * to disable the EDMA engine before doing the ATA_RST operation. 1901 * to disable the EDMA engine before doing the ATA_RST operation.
1906 */ 1902 */
1907 mv_stop_edma_engine(port_mmio);
1908 mv_reset_channel(hpriv, mmio, port); 1903 mv_reset_channel(hpriv, mmio, port);
1909 1904
1910 ZERO(0x028); /* command */ 1905 ZERO(0x028); /* command */
@@ -2184,7 +2179,6 @@ static void mv_soc_reset_hc_port(struct mv_host_priv *hpriv,
2184 * (but doesn't say what the problem might be). So we first try 2179 * (but doesn't say what the problem might be). So we first try
2185 * to disable the EDMA engine before doing the ATA_RST operation. 2180 * to disable the EDMA engine before doing the ATA_RST operation.
2186 */ 2181 */
2187 mv_stop_edma_engine(port_mmio);
2188 mv_reset_channel(hpriv, mmio, port); 2182 mv_reset_channel(hpriv, mmio, port);
2189 2183
2190 ZERO(0x028); /* command */ 2184 ZERO(0x028); /* command */
@@ -2261,6 +2255,7 @@ static void mv_reset_channel(struct mv_host_priv *hpriv, void __iomem *mmio,
2261{ 2255{
2262 void __iomem *port_mmio = mv_port_base(mmio, port_no); 2256 void __iomem *port_mmio = mv_port_base(mmio, port_no);
2263 2257
2258 mv_stop_edma_engine(port_mmio);
2264 writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS); 2259 writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
2265 2260
2266 if (!IS_GEN_I(hpriv)) { 2261 if (!IS_GEN_I(hpriv)) {
@@ -2282,116 +2277,6 @@ static void mv_reset_channel(struct mv_host_priv *hpriv, void __iomem *mmio,
2282 mdelay(1); 2277 mdelay(1);
2283} 2278}
2284 2279
2285/**
2286 * mv_phy_reset - Perform eDMA reset followed by COMRESET
2287 * @ap: ATA channel to manipulate
2288 *
2289 * Part of this is taken from __sata_phy_reset and modified to
2290 * not sleep since this routine gets called from interrupt level.
2291 *
2292 * LOCKING:
2293 * Inherited from caller. This is coded to safe to call at
2294 * interrupt level, i.e. it does not sleep.
2295 */
2296static void mv_phy_reset(struct ata_port *ap, unsigned int *class,
2297 unsigned long deadline)
2298{
2299 struct mv_port_priv *pp = ap->private_data;
2300 struct mv_host_priv *hpriv = ap->host->private_data;
2301 void __iomem *port_mmio = mv_ap_base(ap);
2302 int retry = 5;
2303 u32 sstatus;
2304
2305 VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
2306
2307#ifdef DEBUG
2308 {
2309 u32 sstatus, serror, scontrol;
2310
2311 mv_scr_read(ap, SCR_STATUS, &sstatus);
2312 mv_scr_read(ap, SCR_ERROR, &serror);
2313 mv_scr_read(ap, SCR_CONTROL, &scontrol);
2314 DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
2315 "SCtrl 0x%08x\n", sstatus, serror, scontrol);
2316 }
2317#endif
2318
2319 /* Issue COMRESET via SControl */
2320comreset_retry:
2321 sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x301);
2322 msleep(1);
2323
2324 sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x300);
2325 msleep(20);
2326
2327 do {
2328 sata_scr_read(&ap->link, SCR_STATUS, &sstatus);
2329 if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
2330 break;
2331
2332 msleep(1);
2333 } while (time_before(jiffies, deadline));
2334
2335 /* work around errata */
2336 if (IS_GEN_II(hpriv) &&
2337 (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
2338 (retry-- > 0))
2339 goto comreset_retry;
2340
2341#ifdef DEBUG
2342 {
2343 u32 sstatus, serror, scontrol;
2344
2345 mv_scr_read(ap, SCR_STATUS, &sstatus);
2346 mv_scr_read(ap, SCR_ERROR, &serror);
2347 mv_scr_read(ap, SCR_CONTROL, &scontrol);
2348 DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
2349 "SCtrl 0x%08x\n", sstatus, serror, scontrol);
2350 }
2351#endif
2352
2353 if (ata_link_offline(&ap->link)) {
2354 *class = ATA_DEV_NONE;
2355 return;
2356 }
2357
2358 /* even after SStatus reflects that device is ready,
2359 * it seems to take a while for link to be fully
2360 * established (and thus Status no longer 0x80/0x7F),
2361 * so we poll a bit for that, here.
2362 */
2363 retry = 20;
2364 while (1) {
2365 u8 drv_stat = ata_sff_check_status(ap);
2366 if ((drv_stat != 0x80) && (drv_stat != 0x7f))
2367 break;
2368 msleep(500);
2369 if (retry-- <= 0)
2370 break;
2371 if (time_after(jiffies, deadline))
2372 break;
2373 }
2374
2375 /* FIXME: if we passed the deadline, the following
2376 * code probably produces an invalid result
2377 */
2378
2379 /* finally, read device signature from TF registers */
2380 *class = ata_sff_dev_classify(ap->link.device, 1, NULL);
2381
2382 writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
2383
2384 WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN);
2385
2386 VPRINTK("EXIT\n");
2387}
2388
2389static int mv_prereset(struct ata_link *link, unsigned long deadline)
2390{
2391 mv_stop_edma(link->ap);
2392 return 0;
2393}
2394
2395static int mv_hardreset(struct ata_link *link, unsigned int *class, 2280static int mv_hardreset(struct ata_link *link, unsigned int *class,
2396 unsigned long deadline) 2281 unsigned long deadline)
2397{ 2282{
@@ -2399,34 +2284,33 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class,
2399 struct mv_host_priv *hpriv = ap->host->private_data; 2284 struct mv_host_priv *hpriv = ap->host->private_data;
2400 struct mv_port_priv *pp = ap->private_data; 2285 struct mv_port_priv *pp = ap->private_data;
2401 void __iomem *mmio = hpriv->base; 2286 void __iomem *mmio = hpriv->base;
2287 int rc, attempts = 0, extra = 0;
2288 u32 sstatus;
2289 bool online;
2402 2290
2403 mv_reset_channel(hpriv, mmio, ap->port_no); 2291 mv_reset_channel(hpriv, mmio, ap->port_no);
2404 pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 2292 pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
2405 mv_phy_reset(ap, class, deadline);
2406
2407 return 0;
2408}
2409
2410static void mv_postreset(struct ata_link *link, unsigned int *classes)
2411{
2412 struct ata_port *ap = link->ap;
2413 u32 serr;
2414 2293
2415 /* print link status */ 2294 /* Workaround for errata FEr SATA#10 (part 2) */
2416 sata_print_link_status(link); 2295 do {
2417 2296 const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
2418 /* clear SError */
2419 sata_scr_read(link, SCR_ERROR, &serr);
2420 sata_scr_write_flush(link, SCR_ERROR, serr);
2421 2297
2422 /* bail out if no device is present */ 2298 rc = sata_link_hardreset(link, timing, deadline + extra, &online, NULL);
2423 if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) { 2299 if (rc) {
2424 DPRINTK("EXIT, no device\n"); 2300 ata_link_printk(link, KERN_ERR,
2425 return; 2301 "COMRESET failed (errno=%d)\n", rc);
2426 } 2302 return rc;
2303 }
2304 sata_scr_read(link, SCR_STATUS, &sstatus);
2305 if (!IS_GEN_I(hpriv) && ++attempts >= 5 && sstatus == 0x121) {
2306 /* Force 1.5gb/s link speed and try again */
2307 mv_setup_ifctl(mv_ap_base(ap), 0);
2308 if (time_after(jiffies + HZ, deadline))
2309 extra = HZ; /* only extend it once, max */
2310 }
2311 } while (sstatus != 0x0 && sstatus != 0x113 && sstatus != 0x123);
2427 2312
2428 /* set up device control */ 2313 return online ? -EAGAIN : rc;
2429 iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
2430} 2314}
2431 2315
2432static void mv_eh_freeze(struct ata_port *ap) 2316static void mv_eh_freeze(struct ata_port *ap)