diff options
-rw-r--r-- | drivers/ide/ide-dma.c | 32 | ||||
-rw-r--r-- | drivers/ide/ide-lib.c | 29 | ||||
-rw-r--r-- | drivers/ide/pci/cs5520.c | 2 | ||||
-rw-r--r-- | drivers/ide/pci/hpt366.c | 8 | ||||
-rw-r--r-- | include/linux/ide.h | 10 |
5 files changed, 39 insertions, 42 deletions
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index f073ea35da00..6000c08f51ba 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -653,7 +653,7 @@ static const u8 xfer_mode_bases[] = { XFER_SW_DMA_0, }; -static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base) +static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = drive->hwif; @@ -670,8 +670,13 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base) mask = hwif->ultra_mask; mask &= id->dma_ultra; - if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) - mask &= 0x07; + /* + * avoid false cable warning from eighty_ninty_three() + */ + if (req_mode > XFER_UDMA_2) { + if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) + mask &= 0x07; + } break; case XFER_MW_DMA_0: if ((id->field_valid & 2) == 0) @@ -709,15 +714,18 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base) } /** - * ide_max_dma_mode - compute DMA speed + * ide_find_dma_mode - compute DMA speed * @drive: IDE device + * @req_mode: requested mode + * + * Checks the drive/host capabilities and finds the speed to use for + * the DMA transfer. The speed is then limited by the requested mode. * - * Checks the drive capabilities and returns the speed to use - * for the DMA transfer. Returns 0 if the drive is incapable - * of DMA transfers. + * Returns 0 if the drive/host combination is incapable of DMA transfers + * or if the requested mode is not a DMA mode. */ -u8 ide_max_dma_mode(ide_drive_t *drive) +u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode) { ide_hwif_t *hwif = drive->hwif; unsigned int mask; @@ -728,7 +736,9 @@ u8 ide_max_dma_mode(ide_drive_t *drive) return 0; for (i = 0; i < ARRAY_SIZE(xfer_mode_bases); i++) { - mask = ide_get_mode_mask(drive, xfer_mode_bases[i]); + if (req_mode < xfer_mode_bases[i]) + continue; + mask = ide_get_mode_mask(drive, xfer_mode_bases[i], req_mode); x = fls(mask) - 1; if (x >= 0) { mode = xfer_mode_bases[i] + x; @@ -738,10 +748,10 @@ u8 ide_max_dma_mode(ide_drive_t *drive) printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode); - return mode; + return min(mode, req_mode); } -EXPORT_SYMBOL_GPL(ide_max_dma_mode); +EXPORT_SYMBOL_GPL(ide_find_dma_mode); int ide_tune_dma(ide_drive_t *drive) { diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 92a6c7bcf527..41a128f52112 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -76,37 +76,24 @@ EXPORT_SYMBOL(ide_xfer_verbose); * Given the available transfer modes this function returns * the best available speed at or below the speed requested. * - * FIXME: filter also PIO/SWDMA/MWDMA modes + * TODO: check device PIO capabilities */ u8 ide_rate_filter(ide_drive_t *drive, u8 speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA ide_hwif_t *hwif = drive->hwif; - u8 mask = hwif->ultra_mask, mode = XFER_MW_DMA_2; - - if (hwif->udma_filter) - mask = hwif->udma_filter(drive); - - /* - * TODO: speed > XFER_UDMA_2 extra check is needed to avoid false - * cable warning from eighty_ninty_three(), moving ide_rate_filter() - * calls from ->speedproc to core code will make this hack go away - */ - if (speed > XFER_UDMA_2) { - if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) - mask &= 0x07; - } + u8 mode = ide_find_dma_mode(drive, speed); - if (mask) - mode = fls(mask) - 1 + XFER_UDMA_0; + if (mode == 0) { + if (hwif->pio_mask) + mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0; + else + mode = XFER_PIO_4; + } // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); return min(speed, mode); -#else /* !CONFIG_BLK_DEV_IDEDMA */ - return min(speed, (u8)XFER_PIO_4); -#endif /* CONFIG_BLK_DEV_IDEDMA */ } EXPORT_SYMBOL(ide_rate_filter); diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c index b89e81656875..507981042c82 100644 --- a/drivers/ide/pci/cs5520.c +++ b/drivers/ide/pci/cs5520.c @@ -70,7 +70,7 @@ static int cs5520_tune_chipset(ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *pdev = hwif->pci_dev; - u8 speed = min((u8)XFER_PIO_4, xferspeed); + u8 speed = ide_rate_filter(drive, xferspeed); int pio = speed; u8 reg; int controller = drive->dn > 1 ? 1 : 0; diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 3d8d6b2ee41a..18c8ad091eb3 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -610,10 +610,6 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) u32 old_itr = 0; u32 itr_mask, new_itr; - /* TODO: move this to ide_rate_filter() [ check ->atapi_dma ] */ - if (drive->media != ide_disk) - speed = min_t(u8, speed, XFER_PIO_4); - itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); @@ -642,10 +638,6 @@ static int hpt37x_tune_chipset(ide_drive_t *drive, u8 xferspeed) u32 old_itr = 0; u32 itr_mask, new_itr; - /* TODO: move this to ide_rate_filter() [ check ->atapi_dma ] */ - if (drive->media != ide_disk) - speed = min_t(u8, speed, XFER_PIO_4); - itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); diff --git a/include/linux/ide.h b/include/linux/ide.h index 80ea946282d7..a3f9c216615e 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1296,7 +1296,14 @@ int ide_in_drive_list(struct hd_driveid *, const struct drive_list_entry *); #ifdef CONFIG_BLK_DEV_IDEDMA int __ide_dma_bad_drive(ide_drive_t *); int __ide_dma_good_drive(ide_drive_t *); -u8 ide_max_dma_mode(ide_drive_t *); + +u8 ide_find_dma_mode(ide_drive_t *, u8); + +static inline u8 ide_max_dma_mode(ide_drive_t *drive) +{ + return ide_find_dma_mode(drive, XFER_UDMA_6); +} + int ide_tune_dma(ide_drive_t *); void ide_dma_off(ide_drive_t *); void ide_dma_verbose(ide_drive_t *); @@ -1322,6 +1329,7 @@ extern void ide_dma_timeout(ide_drive_t *); #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ #else +static inline u8 ide_find_dma_mode(ide_drive_t *drive, u8 speed) { return 0; } static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; } static inline int ide_tune_dma(ide_drive_t *drive) { return 0; } static inline void ide_dma_off(ide_drive_t *drive) { ; } |