diff options
author | Mark Lord <liml@rtr.ca> | 2008-04-16 14:56:12 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-04-17 15:56:05 -0400 |
commit | 0d8be5cbff8fd95da72d749a64e150b851f470c6 (patch) | |
tree | 2c7458b87aea315bb546053a0acc20839ab09a0f /drivers | |
parent | f3360ebffae254ab99a64bf97c7b4f8380b1e114 (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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/sata_mv.c | 160 |
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); | |||
478 | static void mv_qc_prep(struct ata_queued_cmd *qc); | 478 | static void mv_qc_prep(struct ata_queued_cmd *qc); |
479 | static void mv_qc_prep_iie(struct ata_queued_cmd *qc); | 479 | static void mv_qc_prep_iie(struct ata_queued_cmd *qc); |
480 | static unsigned int mv_qc_issue(struct ata_queued_cmd *qc); | 480 | static unsigned int mv_qc_issue(struct ata_queued_cmd *qc); |
481 | static int mv_prereset(struct ata_link *link, unsigned long deadline); | ||
482 | static int mv_hardreset(struct ata_link *link, unsigned int *class, | 481 | static int mv_hardreset(struct ata_link *link, unsigned int *class, |
483 | unsigned long deadline); | 482 | unsigned long deadline); |
484 | static void mv_postreset(struct ata_link *link, unsigned int *classes); | ||
485 | static void mv_eh_freeze(struct ata_port *ap); | 483 | static void mv_eh_freeze(struct ata_port *ap); |
486 | static void mv_eh_thaw(struct ata_port *ap); | 484 | static void mv_eh_thaw(struct ata_port *ap); |
487 | static void mv6_dev_config(struct ata_device *dev); | 485 | static 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 | */ | ||
2296 | static 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 */ | ||
2320 | comreset_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 | |||
2389 | static int mv_prereset(struct ata_link *link, unsigned long deadline) | ||
2390 | { | ||
2391 | mv_stop_edma(link->ap); | ||
2392 | return 0; | ||
2393 | } | ||
2394 | |||
2395 | static int mv_hardreset(struct ata_link *link, unsigned int *class, | 2280 | static 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 | |||
2410 | static 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 | ||
2432 | static void mv_eh_freeze(struct ata_port *ap) | 2316 | static void mv_eh_freeze(struct ata_port *ap) |