aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/ide/ide-dma.c32
-rw-r--r--drivers/ide/ide-lib.c29
-rw-r--r--drivers/ide/pci/cs5520.c2
-rw-r--r--drivers/ide/pci/hpt366.c8
-rw-r--r--include/linux/ide.h10
5 files changed, 39 insertions, 42 deletions
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index f073ea35da0..6000c08f51b 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 92a6c7bcf52..41a128f5211 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 b89e8165687..507981042c8 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 3d8d6b2ee41..18c8ad091eb 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 80ea946282d..a3f9c216615 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) { ; }