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 | |
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')
-rw-r--r-- | drivers/ata/libata-core.c | 105 | ||||
-rw-r--r-- | drivers/ata/libata-eh.c | 9 | ||||
-rw-r--r-- | drivers/ata/libata.h | 12 |
3 files changed, 96 insertions, 30 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) |
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 52c85af7fe99..7b61562cdd40 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -1276,7 +1276,7 @@ static int ata_eh_speed_down(struct ata_device *dev, int is_io, | |||
1276 | return ATA_EH_HARDRESET; | 1276 | return ATA_EH_HARDRESET; |
1277 | 1277 | ||
1278 | /* lower transfer mode */ | 1278 | /* lower transfer mode */ |
1279 | if (ata_down_xfermask_limit(dev, 0) == 0) | 1279 | if (ata_down_xfermask_limit(dev, ATA_DNXFER_ANY) == 0) |
1280 | return ATA_EH_SOFTRESET; | 1280 | return ATA_EH_SOFTRESET; |
1281 | 1281 | ||
1282 | ata_dev_printk(dev, KERN_ERR, | 1282 | ata_dev_printk(dev, KERN_ERR, |
@@ -1965,6 +1965,7 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
1965 | struct ata_eh_context *ehc = &ap->eh_context; | 1965 | struct ata_eh_context *ehc = &ap->eh_context; |
1966 | struct ata_device *dev; | 1966 | struct ata_device *dev; |
1967 | int down_xfermask, i, rc; | 1967 | int down_xfermask, i, rc; |
1968 | int dnxfer_sel; | ||
1968 | 1969 | ||
1969 | DPRINTK("ENTER\n"); | 1970 | DPRINTK("ENTER\n"); |
1970 | 1971 | ||
@@ -2064,8 +2065,10 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
2064 | sata_down_spd_limit(ap); | 2065 | sata_down_spd_limit(ap); |
2065 | default: | 2066 | default: |
2066 | ehc->tries[dev->devno]--; | 2067 | ehc->tries[dev->devno]--; |
2067 | if (down_xfermask && | 2068 | dnxfer_sel = ATA_DNXFER_ANY; |
2068 | ata_down_xfermask_limit(dev, ehc->tries[dev->devno] == 1)) | 2069 | if (ehc->tries[dev->devno] == 1) |
2070 | dnxfer_sel = ATA_DNXFER_FORCE_PIO0; | ||
2071 | if (down_xfermask && ata_down_xfermask_limit(dev, dnxfer_sel)) | ||
2069 | ehc->tries[dev->devno] = 0; | 2072 | ehc->tries[dev->devno] = 0; |
2070 | } | 2073 | } |
2071 | 2074 | ||
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 0ad7781d72a3..8533de67d87e 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h | |||
@@ -41,6 +41,16 @@ struct ata_scsi_args { | |||
41 | enum { | 41 | enum { |
42 | /* flags for ata_dev_read_id() */ | 42 | /* flags for ata_dev_read_id() */ |
43 | ATA_READID_POSTRESET = (1 << 0), /* reading ID after reset */ | 43 | ATA_READID_POSTRESET = (1 << 0), /* reading ID after reset */ |
44 | |||
45 | /* selector for ata_down_xfermask_limit() */ | ||
46 | ATA_DNXFER_PIO = 0, /* speed down PIO */ | ||
47 | ATA_DNXFER_DMA = 1, /* speed down DMA */ | ||
48 | ATA_DNXFER_40C = 2, /* apply 40c cable limit */ | ||
49 | ATA_DNXFER_FORCE_PIO = 3, /* force PIO */ | ||
50 | ATA_DNXFER_FORCE_PIO0 = 4, /* force PIO0 */ | ||
51 | ATA_DNXFER_ANY = 5, /* speed down any */ | ||
52 | |||
53 | ATA_DNXFER_QUIET = (1 << 31), | ||
44 | }; | 54 | }; |
45 | 55 | ||
46 | extern struct workqueue_struct *ata_aux_wq; | 56 | extern struct workqueue_struct *ata_aux_wq; |
@@ -69,7 +79,7 @@ extern int ata_dev_revalidate(struct ata_device *dev, unsigned int flags); | |||
69 | extern int ata_dev_configure(struct ata_device *dev); | 79 | extern int ata_dev_configure(struct ata_device *dev); |
70 | extern int sata_down_spd_limit(struct ata_port *ap); | 80 | extern int sata_down_spd_limit(struct ata_port *ap); |
71 | extern int sata_set_spd_needed(struct ata_port *ap); | 81 | extern int sata_set_spd_needed(struct ata_port *ap); |
72 | extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0); | 82 | extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); |
73 | extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); | 83 | extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); |
74 | extern void ata_sg_clean(struct ata_queued_cmd *qc); | 84 | extern void ata_sg_clean(struct ata_queued_cmd *qc); |
75 | extern void ata_qc_free(struct ata_queued_cmd *qc); | 85 | extern void ata_qc_free(struct ata_queued_cmd *qc); |