aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-10-11 17:53:59 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-10-11 17:53:59 -0400
commit7670df73fba373d19471a2ebedb3302ea0607be0 (patch)
treea47b896a9d9a652ca71cc33709f0f73253ea5f9c
parenta8028fcb485522c0d7de9c5423812de9224b37c9 (diff)
ide: mode limiting fixes for user requested speed changes
* Add an extra argument to ide_max_dma_mode() for passing requested transfer mode. Use it as an upper limit when finding the best DMA for device/host. * Rename ide_max_dma_mode() to ide_find_dma_mode() and at the same time add ide_max_dma_mode() wrapper which passes XFER_UDMA_6 as a requested mode to ide_find_dma_mode(). Also add inline ide_find_dma_mode() version for CONFIG_BLK_DEV_IDEDMA=n case. * Pass requested transfer mode from ide_find_dma_mode() to ide_get_mode_mask() to avoid false warning from eighty_ninty_three(). * Use ide_find_dma_mode() to limit the user requested transfer mode in ide_rate_filter(). Also limit the requested mode by host max PIO mode. Above changes make ide_rate_filter() to: * Clip desired transfer mode down if it is invalid (values 0x0F, 0x13-0x19 and 0x25-0x39, values > 0x46 were already clipped down, same for values 0x25-0x39 but iff UDMA was not supported by the host). * Clip desired transfer mode down if it is currently unsupported by IDE core (PIO6 and MWDMA3-4, the latter were already clipped down but iff UDMA was not supported by the host). * Clip desired transfer mode down according to the host capabilities (UDMA modes were already clipped down but MWDMA/SWDMA/PIO weren't, also ->atapi_dma flag was not respected). * Clip desired transfer mode down according to the device capabilities (except PIO modes for now which require mode work) - shouldn't be a problem since ide_set_xfer_rate() is called _after_ device has accepted given transfer mode. and also result in a number of host driver specific bugfixes: * icside - clip unsupported PIO5 mode down - fix unsupported/invalid modes being set in drive->current_speed * ide-cris - clip unsupported PIO5 and SWDMA0-2 modes down - clip DMA modes down for ATAPI devices - fix BUG() on unsupported/invalid modes * au1xxx-ide - clip unsupported PIO5, SWDMA0-2 and MWDMA0-2 (if BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA=n) modes down * aec62xx - clip unsupported PIO5 and SWDMA0-2 modes down - clip DMA modes down for ATAPI devices - fix 0x00 being programmed as PIO timing for unsupported/invalid modes - fix unsupported/invalid modes being set on the device * alim15x3 - clip DMA modes down for ATAPI devices (chipset revision == 0x20 only) - fix theoretical OOPS for 0x0F mode - fix unsupported/invalid modes being set on the device * amd74xx - clip unsupported SWDMA0-2 (on COBRA_7401 revs <= 7) modes down - fix random PIO timings being set for unsupported/invalid modes - fix unsupported/invalid modes being set on the device * atiixp - clip unsupported PIO5 and SWDMA0-2 modes down - fix cached MWDMA mode being cleared for unsupported/invalid modes - fix PIO{0,2} timings being programmed for unsupported/invalid modes - fix theoretical OOPS for PIO5-6 and 0x0F modes - fix unsupported/invalid modes being set on the device * cmd64x - clip unsupported SWDMA0-2 modes down * cs5530 - clip unsupported PIO5 and SWDMA0-2 modes down - fix unsupported/invalid modes being set on the device - fix BUG() on unsupported/invalid modes (which happened if the device accepted the setting) * cs5535 - clip unsupported PIO5 and SWDMA0-2 modes down - fix unsupported/invalid modes being set on the device - fix theoretical OOPS for PIO5-6 and 0x0F modes * hpt34x - clip DMA modes down for ATAPI devices - fix invalid timings being programmed for unsupported/invalid modes - fix unsupported/invalid modes being set on the device * hpt366 - clip unsupported PIO5 and SWDMA0-2 modes down - fix PIO0 timings being programmed for unsupported/invalid modes - fix DMA timings being cleared for MWDMA3-4 and 0x25-0x39 modes - fix unsupported/invalid modes being set on the device * it8213 - clip unsupported PIO5, SWDMA0-1 and MWDMA0 modes down * it821x - clip unsupported PIO5 and SWDMA0-2 modes down - clip DMA modes down for ATAPI devices (chipset in smart mode and revision 0x10 in pass-through mode) * jmicron - clip unsupported SWDMA0-2 modes down - fix unsupported/invalid modes being set on the device * pdc202xx_new - clip unsupported PIO5 and SWDMA0-2 modes down - fix unsupported/invalid modes being set on the device * pdc202xx_old - clip unsupported PIO5 mode down - fix incorrect timings being set for unsupported/invalid modes - fix unsupported/invalid modes being set on the device * piix - clip unsupported PIO5, SWDMA0-1 and MWDMA0 modes down * sc1200 - clip unsupported PIO5 and SWDMA0-2 modes down - fix unsupported/invalid modes being set on the device - fix BUG() on unsupported/invalid modes (which happened if the device accepted the setting) * scc_pata - clip unsupported PIO5, SWDMA0-2 and MWDMA0-2 modes down * serverworks - clip unsupported PIO5 and SWDMA0-2 modes down - fix DMA/UDMA timings/settings being cleared for unsupported/invalid modes - fix unsupported/invalid modes being set on the device * siimage - clip unsupported PIO5 and SWDMA0-2 modes down - clip DMA modes down for ATAPI devices (SATA chipsets) * sis5513 - clip unsupported PIO5 mode down - fix BUG() on unsupported/invalid modes * sl82c105 - clip unsupported SWDMA0-2 modes down * slc90e66 - clip unsupported PIO5, SWDMA0-1 and MWDMA0 modes down * tc86c001 - clip unsupported PIO5 and SWDMA0-2 modes down - fix PIO0 timings being programmed for PIO5/0x0F/SWDMA0-2/0x13-0x19 modes - fix invalid 0x00 DMA timing being programmed for MWDMA3-4/0x25-0x39 modes - fix unsupported/invalid modes being set on the device * triflex - clip unsupported PIO5 mode down * via82cxxx - fix random PIO timings being set for unsupported/invalid modes - fix unsupported/invalid modes being set on the device * pmac - clip unsupported PIO5 and SWDMA0-2 modes down * cmd640/ht6560b - clip DMA modes down (if CONFIG_BLK_DEV_IDEDMA=y) - fix PIO5 being clipped to PIO4 (if CONFIG_BLK_DEV_IDEDMA=n) * opti621 - clip DMA modes down (if CONFIG_BLK_DEV_IDEDMA=y) - clip unsupported PIO4 to PIO3 (if CONFIG_BLK_DEV_IDEDMA=n) While at it: * Use ide_rate_filter() in cs5520.c::cs5520_tune_chipset(). * Remove no longer needed checks from hpt366.c::hpt3{6,7}x_tune_chipset(). Acked-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-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 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[] = {
653 XFER_SW_DMA_0, 653 XFER_SW_DMA_0,
654}; 654};
655 655
656static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base) 656static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
657{ 657{
658 struct hd_driveid *id = drive->id; 658 struct hd_driveid *id = drive->id;
659 ide_hwif_t *hwif = drive->hwif; 659 ide_hwif_t *hwif = drive->hwif;
@@ -670,8 +670,13 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base)
670 mask = hwif->ultra_mask; 670 mask = hwif->ultra_mask;
671 mask &= id->dma_ultra; 671 mask &= id->dma_ultra;
672 672
673 if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) 673 /*
674 mask &= 0x07; 674 * avoid false cable warning from eighty_ninty_three()
675 */
676 if (req_mode > XFER_UDMA_2) {
677 if ((mask & 0x78) && (eighty_ninty_three(drive) == 0))
678 mask &= 0x07;
679 }
675 break; 680 break;
676 case XFER_MW_DMA_0: 681 case XFER_MW_DMA_0:
677 if ((id->field_valid & 2) == 0) 682 if ((id->field_valid & 2) == 0)
@@ -709,15 +714,18 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base)
709} 714}
710 715
711/** 716/**
712 * ide_max_dma_mode - compute DMA speed 717 * ide_find_dma_mode - compute DMA speed
713 * @drive: IDE device 718 * @drive: IDE device
719 * @req_mode: requested mode
720 *
721 * Checks the drive/host capabilities and finds the speed to use for
722 * the DMA transfer. The speed is then limited by the requested mode.
714 * 723 *
715 * Checks the drive capabilities and returns the speed to use 724 * Returns 0 if the drive/host combination is incapable of DMA transfers
716 * for the DMA transfer. Returns 0 if the drive is incapable 725 * or if the requested mode is not a DMA mode.
717 * of DMA transfers.
718 */ 726 */
719 727
720u8 ide_max_dma_mode(ide_drive_t *drive) 728u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
721{ 729{
722 ide_hwif_t *hwif = drive->hwif; 730 ide_hwif_t *hwif = drive->hwif;
723 unsigned int mask; 731 unsigned int mask;
@@ -728,7 +736,9 @@ u8 ide_max_dma_mode(ide_drive_t *drive)
728 return 0; 736 return 0;
729 737
730 for (i = 0; i < ARRAY_SIZE(xfer_mode_bases); i++) { 738 for (i = 0; i < ARRAY_SIZE(xfer_mode_bases); i++) {
731 mask = ide_get_mode_mask(drive, xfer_mode_bases[i]); 739 if (req_mode < xfer_mode_bases[i])
740 continue;
741 mask = ide_get_mode_mask(drive, xfer_mode_bases[i], req_mode);
732 x = fls(mask) - 1; 742 x = fls(mask) - 1;
733 if (x >= 0) { 743 if (x >= 0) {
734 mode = xfer_mode_bases[i] + x; 744 mode = xfer_mode_bases[i] + x;
@@ -738,10 +748,10 @@ u8 ide_max_dma_mode(ide_drive_t *drive)
738 748
739 printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode); 749 printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode);
740 750
741 return mode; 751 return min(mode, req_mode);
742} 752}
743 753
744EXPORT_SYMBOL_GPL(ide_max_dma_mode); 754EXPORT_SYMBOL_GPL(ide_find_dma_mode);
745 755
746int ide_tune_dma(ide_drive_t *drive) 756int ide_tune_dma(ide_drive_t *drive)
747{ 757{
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);
76 * Given the available transfer modes this function returns 76 * Given the available transfer modes this function returns
77 * the best available speed at or below the speed requested. 77 * the best available speed at or below the speed requested.
78 * 78 *
79 * FIXME: filter also PIO/SWDMA/MWDMA modes 79 * TODO: check device PIO capabilities
80 */ 80 */
81 81
82u8 ide_rate_filter(ide_drive_t *drive, u8 speed) 82u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
83{ 83{
84#ifdef CONFIG_BLK_DEV_IDEDMA
85 ide_hwif_t *hwif = drive->hwif; 84 ide_hwif_t *hwif = drive->hwif;
86 u8 mask = hwif->ultra_mask, mode = XFER_MW_DMA_2; 85 u8 mode = ide_find_dma_mode(drive, speed);
87
88 if (hwif->udma_filter)
89 mask = hwif->udma_filter(drive);
90
91 /*
92 * TODO: speed > XFER_UDMA_2 extra check is needed to avoid false
93 * cable warning from eighty_ninty_three(), moving ide_rate_filter()
94 * calls from ->speedproc to core code will make this hack go away
95 */
96 if (speed > XFER_UDMA_2) {
97 if ((mask & 0x78) && (eighty_ninty_three(drive) == 0))
98 mask &= 0x07;
99 }
100 86
101 if (mask) 87 if (mode == 0) {
102 mode = fls(mask) - 1 + XFER_UDMA_0; 88 if (hwif->pio_mask)
89 mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0;
90 else
91 mode = XFER_PIO_4;
92 }
103 93
104// printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); 94// printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed);
105 95
106 return min(speed, mode); 96 return min(speed, mode);
107#else /* !CONFIG_BLK_DEV_IDEDMA */
108 return min(speed, (u8)XFER_PIO_4);
109#endif /* CONFIG_BLK_DEV_IDEDMA */
110} 97}
111 98
112EXPORT_SYMBOL(ide_rate_filter); 99EXPORT_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)
70{ 70{
71 ide_hwif_t *hwif = HWIF(drive); 71 ide_hwif_t *hwif = HWIF(drive);
72 struct pci_dev *pdev = hwif->pci_dev; 72 struct pci_dev *pdev = hwif->pci_dev;
73 u8 speed = min((u8)XFER_PIO_4, xferspeed); 73 u8 speed = ide_rate_filter(drive, xferspeed);
74 int pio = speed; 74 int pio = speed;
75 u8 reg; 75 u8 reg;
76 int controller = drive->dn > 1 ? 1 : 0; 76 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)
610 u32 old_itr = 0; 610 u32 old_itr = 0;
611 u32 itr_mask, new_itr; 611 u32 itr_mask, new_itr;
612 612
613 /* TODO: move this to ide_rate_filter() [ check ->atapi_dma ] */
614 if (drive->media != ide_disk)
615 speed = min_t(u8, speed, XFER_PIO_4);
616
617 itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : 613 itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 :
618 (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); 614 (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff);
619 615
@@ -642,10 +638,6 @@ static int hpt37x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
642 u32 old_itr = 0; 638 u32 old_itr = 0;
643 u32 itr_mask, new_itr; 639 u32 itr_mask, new_itr;
644 640
645 /* TODO: move this to ide_rate_filter() [ check ->atapi_dma ] */
646 if (drive->media != ide_disk)
647 speed = min_t(u8, speed, XFER_PIO_4);
648
649 itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : 641 itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 :
650 (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); 642 (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff);
651 643
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 *);
1296#ifdef CONFIG_BLK_DEV_IDEDMA 1296#ifdef CONFIG_BLK_DEV_IDEDMA
1297int __ide_dma_bad_drive(ide_drive_t *); 1297int __ide_dma_bad_drive(ide_drive_t *);
1298int __ide_dma_good_drive(ide_drive_t *); 1298int __ide_dma_good_drive(ide_drive_t *);
1299u8 ide_max_dma_mode(ide_drive_t *); 1299
1300u8 ide_find_dma_mode(ide_drive_t *, u8);
1301
1302static inline u8 ide_max_dma_mode(ide_drive_t *drive)
1303{
1304 return ide_find_dma_mode(drive, XFER_UDMA_6);
1305}
1306
1300int ide_tune_dma(ide_drive_t *); 1307int ide_tune_dma(ide_drive_t *);
1301void ide_dma_off(ide_drive_t *); 1308void ide_dma_off(ide_drive_t *);
1302void ide_dma_verbose(ide_drive_t *); 1309void ide_dma_verbose(ide_drive_t *);
@@ -1322,6 +1329,7 @@ extern void ide_dma_timeout(ide_drive_t *);
1322#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ 1329#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
1323 1330
1324#else 1331#else
1332static inline u8 ide_find_dma_mode(ide_drive_t *drive, u8 speed) { return 0; }
1325static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; } 1333static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; }
1326static inline int ide_tune_dma(ide_drive_t *drive) { return 0; } 1334static inline int ide_tune_dma(ide_drive_t *drive) { return 0; }
1327static inline void ide_dma_off(ide_drive_t *drive) { ; } 1335static inline void ide_dma_off(ide_drive_t *drive) { ; }