Messages in this thread Patch in this message | | | Date | Tue, 25 Jun 2002 21:13:54 +0200 (MET DST) | From | Bartlomiej Zolnierkiewicz <> | Subject | [PATCH] 2.5.24: generic ATA PCI auto-dma tuning (1/5) |
| |
Hi!
This is first of five patches implementing generic ATA host chips (U)DMA auto-tuning... against 2.5.24 but should also apply cleanly to 2.5.24 + Martin's ide-clean-94 patch...
Lot of duplicated code is removed and simple, coherent scheme is provided...
diffstat for 5 patches: 35 files changed, 338 insertions(+), 825 deletions(-)
- add int 'modes_map' and flag 'no_atapi_autodma' to struct ata_channel, initialise them in *_init_channel() functions
- add XFER_UDMA_ALL and XFER_UDMA_80W defines to ata-timing.h
- convert *_ratemask() functions to *_modes_map(), mark them with __init affected drivers: alim15x3.c, cmd64x.c, hpt366.c, pdc202xx.c, serverworks.c, sis5513.c
- split aec62xx_udma_setup() to aec62xx_udma_setup() and aec62xx_modes_map()
- move eighty_ninty_three(drive) check from *_ratemask() to driver specific config_chipset_for_dma()
-- Bartlomiej Zolnierkiewicz diff -ur linux-2.5.24/include/linux/ide.h linux/include/linux/ide.h --- linux-2.5.24/include/linux/ide.h Mon Jun 24 22:21:03 2002 +++ linux/include/linux/ide.h Mon Jun 24 22:24:30 2002 @@ -496,7 +496,9 @@ unsigned unmask : 1; /* flag: okay to unmask other irqs */ unsigned slow : 1; /* flag: slow data port */ unsigned io_32bit : 1; /* 0=16-bit, 1=32-bit */ + unsigned no_atapi_autodma : 1; /* flag: use auto DMA only for disks */ unsigned char bus_state; /* power state of the IDE bus */ + int modes_map; /* map of supported transfer modes */ }; /* diff -ur linux-2.5.24/drivers/ide/aec62xx.c linux/drivers/ide/aec62xx.c --- linux-2.5.24/drivers/ide/aec62xx.c Mon Jun 24 22:15:18 2002 +++ linux/drivers/ide/aec62xx.c Mon Jun 24 22:24:30 2002 @@ -162,14 +162,24 @@ #ifdef CONFIG_BLK_DEV_IDEDMA static int aec62xx_udma_setup(struct ata_device *drive) { - u32 bmide = pci_resource_start(drive->channel->pci_dev, 4); short speed; + + speed = ata_timing_mode(drive, drive->channel->modes_map); + aec_set_drive(drive, speed); + udma_enable(drive, drive->channel->autodma && (speed & XFER_MODE) != XFER_PIO, 0); + + return 0; +} + +static int __init aec62xx_modes_map(struct ata_channel *ch) +{ + u32 bmide = pci_resource_start(ch->pci_dev, 4); int map; - map = XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA | XFER_SWDMA | XFER_UDMA; + map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA | XFER_UDMA; - if (drive->channel->udma_four) - switch (drive->channel->pci_dev->device) { + if (ch->udma_four) + switch (ch->pci_dev->device) { case PCI_DEVICE_ID_ARTOP_ATP865R: case PCI_DEVICE_ID_ARTOP_ATP865: /* Can't use these modes simultaneously, @@ -180,11 +190,7 @@ map |= XFER_UDMA_66; } - speed = ata_timing_mode(drive, map); - aec_set_drive(drive, speed); - udma_enable(drive, drive->channel->autodma && (speed & XFER_MODE) != XFER_PIO, 0); - - return 0; + return map; } #endif @@ -269,6 +275,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA if (ch->dma_base) { ch->highmem = 1; + ch->modes_map = aec62xx_modes_map(ch); ch->udma_setup = aec62xx_udma_setup; #ifdef CONFIG_IDEDMA_AUTO if (!noautodma) diff -ur linux-2.5.24/drivers/ide/alim15x3.c linux/drivers/ide/alim15x3.c --- linux-2.5.24/drivers/ide/alim15x3.c Mon Jun 24 22:15:18 2002 +++ linux/drivers/ide/alim15x3.c Mon Jun 24 22:24:30 2002 @@ -99,6 +99,7 @@ __restore_flags(flags); } +/* FIXME: unfold --bkz */ static byte ali15x3_can_ultra(struct ata_device *drive) { if (m5229_revision <= 0x20) { @@ -116,26 +117,6 @@ } } -static int ali15x3_ratemask(struct ata_device *drive) -{ - int map = 0; - - if (!ali15x3_can_ultra(drive)) - return 0; - - map |= XFER_UDMA; - - if (!eighty_ninty_three(drive)) - return map; - - if (m5229_revision >= 0xC4) - map |= XFER_UDMA_100; - if (m5229_revision >= 0xC2) - map |= XFER_UDMA_66; - - return map; -} - static int ali15x3_tune_chipset(struct ata_device *drive, byte speed) { struct pci_dev *dev = drive->channel->pci_dev; @@ -156,6 +137,7 @@ if (speed < XFER_SW_DMA_0) ali15x3_tune_drive(drive, speed); #ifdef CONFIG_BLK_DEV_IDEDMA + /* FIXME: no support for MWDMA and SWDMA modes --bkz */ else if (speed >= XFER_UDMA_0) { pci_read_config_byte(dev, m5229_udma, &tmpbyte); tmpbyte &= (0x0f << ((1-unit) << 2)); @@ -178,15 +160,17 @@ #ifdef CONFIG_BLK_DEV_IDEDMA static int config_chipset_for_dma(struct ata_device *drive, u8 udma) { - int map; + int map = drive->channel->modes_map; u8 mode; - if (udma) - map = ali15x3_ratemask(drive); - else - map = XFER_SWDMA | XFER_MWDMA; + if (!eighty_ninty_three(drive)) + map &= ~XFER_UDMA_80W; + + if (!udma) + map &= ~XFER_UDMA_ALL; mode = ata_timing_mode(drive, map); + if (mode < XFER_SW_DMA_0) return 0; @@ -262,6 +246,24 @@ return udma_pci_init(drive, rq); } + +static int __init ali15x3_modes_map(struct ata_channel *ch) +{ + int map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA; + + if (!ali15x3_can_ultra(ch->drive)) + return map; + + map |= XFER_UDMA; + + if (m5229_revision >= 0xC2) { + map |= XFER_UDMA_66; + if (m5229_revision >= 0xC4) + map |= XFER_UDMA_100; + } + + return map; +} #endif static unsigned int __init ali15x3_init_chipset(struct pci_dev *dev) @@ -436,6 +438,7 @@ /* * M1543C or newer for DMAing */ + hwif->modes_map = ali15x3_modes_map(hwif); hwif->udma_init = ali15x3_udma_init; hwif->udma_setup = ali15x3_udma_setup; hwif->autodma = 1; diff -ur linux-2.5.24/drivers/ide/ata-timing.h linux/drivers/ide/ata-timing.h --- linux-2.5.24/drivers/ide/ata-timing.h Mon Jun 24 22:15:12 2002 +++ linux/drivers/ide/ata-timing.h Mon Jun 24 22:24:30 2002 @@ -69,6 +69,9 @@ #define XFER_EPIO 0x01 #define XFER_PIO 0x00 +#define XFER_UDMA_ALL 0x4e +#define XFER_UDMA_80W 0x0e + /* External interface to host chips channel timing setup. * * It's a bit elaborate due to the legacy we have to bear. diff -ur linux-2.5.24/drivers/ide/cmd64x.c linux/drivers/ide/cmd64x.c --- linux-2.5.24/drivers/ide/cmd64x.c Mon Jun 24 22:21:01 2002 +++ linux/drivers/ide/cmd64x.c Mon Jun 24 22:25:32 2002 @@ -217,10 +217,10 @@ ide_config_drive_speed(drive, speed); } -static int cmd64x_ratemask(struct ata_device *drive) +static int __init cmd6xx_modes_map(struct ata_channel *ch) { - struct pci_dev *dev = drive->channel->pci_dev; - int map = 0; + struct pci_dev *dev = ch->pci_dev; + int map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA; switch(dev->device) { case PCI_DEVICE_ID_CMD_680: @@ -234,10 +234,9 @@ break; case PCI_DEVICE_ID_CMD_646: { - u32 class_rev; - pci_read_config_dword(dev, - PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; + u32 rev; + pci_read_config_dword(dev, PCI_CLASS_REVISION, &rev); + rev &= 0xff; /* * UltraDMA only supported on PCI646U and PCI646U2, which * correspond to revisions 0x03, 0x05 and 0x07 respectively. @@ -250,7 +249,7 @@ * * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. */ - switch(class_rev) { + switch(rev) { case 0x07: case 0x05: map |= XFER_UDMA; @@ -260,11 +259,6 @@ } } - if (!eighty_ninty_three(drive)) { - if (map & XFER_UDMA) - return XFER_UDMA; - return 0; - } return map; } @@ -520,10 +514,13 @@ int map; u8 mode; - if (udma) - map = cmd64x_ratemask(drive); - else - map = XFER_SWDMA | XFER_MWDMA; + map = drive->channel->modes_map; + + if (!eighty_ninty_three(drive)) + map &= ~XFER_UDMA_80W; + + if (!udma) + map &= ~XFER_UDMA_ALL; mode = ata_timing_mode(drive, map); @@ -887,6 +884,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->highmem = 1; + hwif->modes_map = cmd6xx_modes_map(hwif); # ifdef CONFIG_IDEDMA_AUTO if (!noautodma) hwif->autodma = 1; diff -ur linux-2.5.24/drivers/ide/hpt366.c linux/drivers/ide/hpt366.c --- linux-2.5.24/drivers/ide/hpt366.c Mon Jun 24 22:21:01 2002 +++ linux/drivers/ide/hpt366.c Mon Jun 24 22:24:30 2002 @@ -493,37 +493,23 @@ return class_rev; } -static int hpt3xx_ratemask(struct ata_device *drive) +static int __init hpt3xx_modes_map(struct ata_channel *ch) { - u32 rev = hpt_revision(drive->channel->pci_dev); - int map = XFER_UDMA; + u32 rev = hpt_revision(ch->pci_dev); + int map = XFER_EPIO | XFER_MWDMA | XFER_UDMA | XFER_UDMA_66; if (rev >= 8) { /* HPT374 */ if (HPT374_ALLOW_ATA133_6) map |= XFER_UDMA_133; - map |= (XFER_UDMA_100 | XFER_UDMA_66); + map |= XFER_UDMA_100; } else if (rev >= 5) { /* HPT372 */ if (HPT372_ALLOW_ATA133_6) map |= XFER_UDMA_133; - map |= (XFER_UDMA_100 | XFER_UDMA_66); - } else if (rev >= 4) { /* HPT370A */ + map |= XFER_UDMA_100; + } else if (rev >= 3) { /* HPT370A / HPT370 */ if (HPT370_ALLOW_ATA100_5) map |= XFER_UDMA_100; - map |= XFER_UDMA_66; - } else if (rev >= 3) { /* HPT370 */ - if (HPT370_ALLOW_ATA100_5) - map |= XFER_UDMA_100; - map |= XFER_UDMA_66; - if (check_in_drive_lists(drive, bad_ata33)) - return 0; - } else { /* HPT366 and HPT368 */ - map |= XFER_UDMA_66; - if (check_in_drive_lists(drive, bad_ata33)) - return 0; - } - - if (!eighty_ninty_three(drive)) - return XFER_UDMA; + } /* HPT366 / HPT368 */ return map; } @@ -679,8 +665,11 @@ rev = hpt_revision(drive->channel->pci_dev); - /* FIXME: check SWDMA modes --bkz */ - map = hpt3xx_ratemask(drive) | XFER_MWDMA; + map = drive->channel->modes_map; + + if (!eighty_ninty_three(drive)) + map &= ~XFER_UDMA_80W; + mode = ata_timing_mode(drive, map); /* FIXME: badlists need futher investigation --bkz @@ -1272,6 +1261,7 @@ // ch->resetproc = hpt3xx_reset; // ch->busproc = hpt3xx_tristate; } + ch->modes_map = hpt3xx_modes_map(ch); ch->udma_setup = hpt3xx_udma_setup; if (!noautodma) diff -ur linux-2.5.24/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c --- linux-2.5.24/drivers/ide/pdc202xx.c Mon Jun 24 22:21:01 2002 +++ linux/drivers/ide/pdc202xx.c Mon Jun 24 22:24:30 2002 @@ -129,21 +129,18 @@ return 0; } -static int pdc202xx_ratemask(struct ata_device *drive) +static int __init pdc202xx_modes_map(struct ata_channel *ch) { - struct pci_dev *dev = drive->channel->pci_dev; - int map = 0; - - if (!eighty_ninty_three(drive)) - return XFER_UDMA; + int map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA; - switch(dev->device) { + switch(ch->pci_dev->device) { case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20275: case PCI_DEVICE_ID_PROMISE_20269: map |= XFER_UDMA_133; case PCI_DEVICE_ID_PROMISE_20268R: case PCI_DEVICE_ID_PROMISE_20268: + map &= ~XFER_SWDMA; case PCI_DEVICE_ID_PROMISE_20267: case PCI_DEVICE_ID_PROMISE_20265: map |= XFER_UDMA_100; @@ -152,6 +149,7 @@ case PCI_DEVICE_ID_PROMISE_20246: map |= XFER_UDMA; } + return map; } @@ -479,14 +477,13 @@ pci_write_config_byte(dev, drive_pci, AP|PREFETCH_EN); } - if (udma) { - map = pdc202xx_ratemask(drive); - } else { - if (!jumpbit) - map = XFER_SWDMA | XFER_MWDMA; - else - map = XFER_MWDMA; - } + map = hwif->modes_map; + + if (!eighty_ninty_three(drive)) + map &= ~XFER_UDMA_80W; + + if (!udma) + map &= ~XFER_UDMA_ALL; mode = ata_timing_mode(drive, map); if (mode < XFER_SW_DMA_0) { @@ -748,6 +745,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { + hwif->modes_map = pdc202xx_modes_map(hwif); hwif->udma_irq_lost = pdc202xx_bug; hwif->udma_timeout = pdc202xx_bug; hwif->udma_setup = pdc202xx_udma_setup; diff -ur linux-2.5.24/drivers/ide/serverworks.c linux/drivers/ide/serverworks.c --- linux-2.5.24/drivers/ide/serverworks.c Mon Jun 24 22:21:01 2002 +++ linux/drivers/ide/serverworks.c Mon Jun 24 22:26:55 2002 @@ -103,15 +103,11 @@ static struct pci_dev *isa_dev; -static int svwks_ratemask(struct ata_device *drive) +static int __init svwks_modes_map(struct ata_channel *ch) { - struct pci_dev *dev = drive->channel->pci_dev; - int map = 0; + int map = XFER_EPIO | XFER_MWDMA; - if (!eighty_ninty_three(drive)) - return XFER_UDMA; - - switch(dev->device) { + switch(ch->pci_dev->device) { case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) map |= XFER_UDMA_100; @@ -120,6 +116,7 @@ map |= XFER_UDMA; break; } + return map; } @@ -176,6 +173,7 @@ csb5_pio |= ((speed - XFER_PIO_0) << (4*drive->dn)); break; + /* FIXME: check SWDMA modes --bkz */ #ifdef CONFIG_BLK_DEV_IDEDMA case XFER_MW_DMA_2: case XFER_MW_DMA_1: @@ -232,11 +230,12 @@ #ifdef CONFIG_BLK_DEV_IDEDMA static int config_chipset_for_dma(struct ata_device *drive) { - int map; + int map = drive->channel->modes_map; u8 mode; - /* FIXME: check SWDMA modes --bkz */ - map = XFER_MWDMA | svwks_ratemask(drive); + if (!eighty_ninty_three(drive)) + map &= ~XFER_UDMA_80W; + mode = ata_timing_mode(drive, map); return !svwks_tune_chipset(drive, mode); @@ -450,6 +449,7 @@ if (!noautodma) hwif->autodma = 1; #endif + hwif->modes_map = svwks_modes_map(hwif); hwif->udma_stop = svwks_udma_stop; hwif->udma_setup = svwks_udma_setup; hwif->highmem = 1; diff -ur linux-2.5.24/drivers/ide/sis5513.c linux/drivers/ide/sis5513.c --- linux-2.5.24/drivers/ide/sis5513.c Mon Jun 24 22:15:18 2002 +++ linux/drivers/ide/sis5513.c Mon Jun 24 22:24:30 2002 @@ -207,9 +207,9 @@ static struct pci_dev *host_dev = NULL; -static int sis5513_ratemask(struct ata_device *drive) +static int __init sis5513_modes_map(struct ata_channel *ch) { - int map = 0; + int map = XFER_EPIO | XFER_SWDMA | XFER_MWDMA; switch(chipset_family) { case ATA_133: /* map |= XFER_UDMA_133; */ @@ -221,15 +221,8 @@ case ATA_33: map |= XFER_UDMA; break; - case ATA_16: - case ATA_00: - default: - return 0; } - if (!eighty_ninty_three(drive)) - return XFER_UDMA; - return map; } @@ -407,7 +400,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA static int config_chipset_for_dma(struct ata_device *drive, u8 udma) { - int map; + int map = drive->channel->modes_map; u8 mode; #ifdef DEBUG @@ -415,10 +408,11 @@ drive->dn, udma); #endif - if (udma) - map = sis5513_ratemask(drive); - else - map = XFER_SWDMA | XFER_MWDMA; + if (!eighty_ninty_three(drive)) + map &= ~XFER_UDMA_80W; + + if (!udma) + map &= ~XFER_UDMA_ALL; mode = ata_timing_mode(drive, map); if (mode < XFER_SW_DMA_0) @@ -587,6 +581,7 @@ if (chipset_family > ATA_16) { hwif->autodma = noautodma ? 0 : 1; hwif->highmem = 1; + hwif->modes_map = sis5513_modes_map(hwif); hwif->udma_setup = sis5513_udma_setup; } else { #endif
| |