diff options
author | Tejun Heo <htejun@gmail.com> | 2007-02-02 02:22:30 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-21 04:58:16 -0500 |
commit | 458337dbb120d33f326e2b19d54eca8cf179b5c0 (patch) | |
tree | 91bc5284430b5a8856ec1b2fd4c277c4eb3f8827 /drivers/ata/libata-core.c | |
parent | a619f981b477035027dd27dfbee6148b4cd4a83c (diff) |
libata: improve ata_down_xfermask_limit()
Make ata_down_xfermask_limit() accept @sel instead of @force_pio0.
@sel selects how the xfermask limit will be adjusted. The following
selectors are defined.
* ATA_DNXFER_PIO : only speed down PIO
* ATA_DNXFER_DMA : only speed down DMA, don't cause transfer mode change
* ATA_DNXFER_40C : apply 40c cable limit
* ATA_DNXFER_FORCE_PIO : force PIO
* ATA_DNXFER_FORCE_PIO0 : force PIO0 (same as original with @force_pio0 == 1)
* ATA_DNXFER_ANY : same as original with @force_pio0 == 0
Currently, only ANY and FORCE_PIO0 are used to maintain the original
behavior. Other selectors will be used later to improve EH speed down
sequence.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r-- | drivers/ata/libata-core.c | 105 |
1 files changed, 79 insertions, 26 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9c54de5addff..249d487c091e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -1780,6 +1780,7 @@ int ata_bus_probe(struct ata_port *ap) | |||
1780 | int tries[ATA_MAX_DEVICES]; | 1780 | int tries[ATA_MAX_DEVICES]; |
1781 | int i, rc, down_xfermask; | 1781 | int i, rc, down_xfermask; |
1782 | struct ata_device *dev; | 1782 | struct ata_device *dev; |
1783 | int dnxfer_sel; | ||
1783 | 1784 | ||
1784 | ata_port_probe(ap); | 1785 | ata_port_probe(ap); |
1785 | 1786 | ||
@@ -1861,13 +1862,15 @@ int ata_bus_probe(struct ata_port *ap) | |||
1861 | /* fall through */ | 1862 | /* fall through */ |
1862 | default: | 1863 | default: |
1863 | tries[dev->devno]--; | 1864 | tries[dev->devno]--; |
1864 | if (down_xfermask && | 1865 | dnxfer_sel = ATA_DNXFER_ANY; |
1865 | ata_down_xfermask_limit(dev, tries[dev->devno] == 1)) | 1866 | if (tries[dev->devno] == 1) |
1867 | dnxfer_sel = ATA_DNXFER_FORCE_PIO0; | ||
1868 | if (down_xfermask && ata_down_xfermask_limit(dev, dnxfer_sel)) | ||
1866 | tries[dev->devno] = 0; | 1869 | tries[dev->devno] = 0; |
1867 | } | 1870 | } |
1868 | 1871 | ||
1869 | if (!tries[dev->devno]) { | 1872 | if (!tries[dev->devno]) { |
1870 | ata_down_xfermask_limit(dev, 1); | 1873 | ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0); |
1871 | ata_dev_disable(dev); | 1874 | ata_dev_disable(dev); |
1872 | } | 1875 | } |
1873 | 1876 | ||
@@ -2300,7 +2303,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, | |||
2300 | /** | 2303 | /** |
2301 | * ata_down_xfermask_limit - adjust dev xfer masks downward | 2304 | * ata_down_xfermask_limit - adjust dev xfer masks downward |
2302 | * @dev: Device to adjust xfer masks | 2305 | * @dev: Device to adjust xfer masks |
2303 | * @force_pio0: Force PIO0 | 2306 | * @sel: ATA_DNXFER_* selector |
2304 | * | 2307 | * |
2305 | * Adjust xfer masks of @dev downward. Note that this function | 2308 | * Adjust xfer masks of @dev downward. Note that this function |
2306 | * does not apply the change. Invoking ata_set_mode() afterwards | 2309 | * does not apply the change. Invoking ata_set_mode() afterwards |
@@ -2312,37 +2315,87 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, | |||
2312 | * RETURNS: | 2315 | * RETURNS: |
2313 | * 0 on success, negative errno on failure | 2316 | * 0 on success, negative errno on failure |
2314 | */ | 2317 | */ |
2315 | int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0) | 2318 | int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel) |
2316 | { | 2319 | { |
2317 | unsigned long xfer_mask; | 2320 | char buf[32]; |
2318 | int highbit; | 2321 | unsigned int orig_mask, xfer_mask; |
2322 | unsigned int pio_mask, mwdma_mask, udma_mask; | ||
2323 | int quiet, highbit; | ||
2319 | 2324 | ||
2320 | xfer_mask = ata_pack_xfermask(dev->pio_mask, dev->mwdma_mask, | 2325 | quiet = !!(sel & ATA_DNXFER_QUIET); |
2321 | dev->udma_mask); | 2326 | sel &= ~ATA_DNXFER_QUIET; |
2322 | 2327 | ||
2323 | if (!xfer_mask) | 2328 | xfer_mask = orig_mask = ata_pack_xfermask(dev->pio_mask, |
2324 | goto fail; | 2329 | dev->mwdma_mask, |
2325 | /* don't gear down to MWDMA from UDMA, go directly to PIO */ | 2330 | dev->udma_mask); |
2326 | if (xfer_mask & ATA_MASK_UDMA) | 2331 | ata_unpack_xfermask(xfer_mask, &pio_mask, &mwdma_mask, &udma_mask); |
2327 | xfer_mask &= ~ATA_MASK_MWDMA; | ||
2328 | 2332 | ||
2329 | highbit = fls(xfer_mask) - 1; | 2333 | switch (sel) { |
2330 | xfer_mask &= ~(1 << highbit); | 2334 | case ATA_DNXFER_PIO: |
2331 | if (force_pio0) | 2335 | highbit = fls(pio_mask) - 1; |
2332 | xfer_mask &= 1 << ATA_SHIFT_PIO; | 2336 | pio_mask &= ~(1 << highbit); |
2333 | if (!xfer_mask) | 2337 | break; |
2334 | goto fail; | 2338 | |
2339 | case ATA_DNXFER_DMA: | ||
2340 | if (udma_mask) { | ||
2341 | highbit = fls(udma_mask) - 1; | ||
2342 | udma_mask &= ~(1 << highbit); | ||
2343 | if (!udma_mask) | ||
2344 | return -ENOENT; | ||
2345 | } else if (mwdma_mask) { | ||
2346 | highbit = fls(mwdma_mask) - 1; | ||
2347 | mwdma_mask &= ~(1 << highbit); | ||
2348 | if (!mwdma_mask) | ||
2349 | return -ENOENT; | ||
2350 | } | ||
2351 | break; | ||
2352 | |||
2353 | case ATA_DNXFER_40C: | ||
2354 | udma_mask &= ATA_UDMA_MASK_40C; | ||
2355 | break; | ||
2356 | |||
2357 | case ATA_DNXFER_FORCE_PIO0: | ||
2358 | pio_mask &= 1; | ||
2359 | case ATA_DNXFER_FORCE_PIO: | ||
2360 | mwdma_mask = 0; | ||
2361 | udma_mask = 0; | ||
2362 | break; | ||
2363 | |||
2364 | case ATA_DNXFER_ANY: | ||
2365 | /* don't gear down to MWDMA from UDMA, go directly to PIO */ | ||
2366 | if (xfer_mask & ATA_MASK_UDMA) | ||
2367 | xfer_mask &= ~ATA_MASK_MWDMA; | ||
2368 | |||
2369 | highbit = fls(xfer_mask) - 1; | ||
2370 | xfer_mask &= ~(1 << highbit); | ||
2371 | break; | ||
2372 | |||
2373 | default: | ||
2374 | BUG(); | ||
2375 | } | ||
2376 | |||
2377 | xfer_mask &= ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask); | ||
2378 | |||
2379 | if (!(xfer_mask & ATA_MASK_PIO) || xfer_mask == orig_mask) | ||
2380 | return -ENOENT; | ||
2381 | |||
2382 | if (!quiet) { | ||
2383 | if (xfer_mask & (ATA_MASK_MWDMA | ATA_MASK_UDMA)) | ||
2384 | snprintf(buf, sizeof(buf), "%s:%s", | ||
2385 | ata_mode_string(xfer_mask), | ||
2386 | ata_mode_string(xfer_mask & ATA_MASK_PIO)); | ||
2387 | else | ||
2388 | snprintf(buf, sizeof(buf), "%s", | ||
2389 | ata_mode_string(xfer_mask)); | ||
2390 | |||
2391 | ata_dev_printk(dev, KERN_WARNING, | ||
2392 | "limiting speed to %s\n", buf); | ||
2393 | } | ||
2335 | 2394 | ||
2336 | ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, | 2395 | ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, |
2337 | &dev->udma_mask); | 2396 | &dev->udma_mask); |
2338 | 2397 | ||
2339 | ata_dev_printk(dev, KERN_WARNING, "limiting speed to %s\n", | ||
2340 | ata_mode_string(xfer_mask)); | ||
2341 | |||
2342 | return 0; | 2398 | return 0; |
2343 | |||
2344 | fail: | ||
2345 | return -EINVAL; | ||
2346 | } | 2399 | } |
2347 | 2400 | ||
2348 | static int ata_dev_set_mode(struct ata_device *dev) | 2401 | static int ata_dev_set_mode(struct ata_device *dev) |