lkml.org 
[lkml]   [2002]   [Jun]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
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
\
 
 \ /
  Last update: 2005-03-22 13:27    [W:0.046 / U:0.184 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site