Skip to content

Commit

Permalink
serverworks: fix CSB6 tuning logic
Browse files Browse the repository at this point in the history
Problem noticed by Joe Zbiciak, see

	http://kerneltrap.org/node/8252

for details.

On CSB6 the driver is using BIOS settings and not programming DMA/PIO timings
itself.  However the logic was completely broken and resulted in wrong timings
being silently allowed (instead of being corrected by the driver).

This bug would explain some data corruption/timeout issues with Serverworks
MegaIDE in RAID mode that Alan Cox has fixed recently with:

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=2074a106f52b6371885afbd714e929d60d0e3f64

For 2.6.23 we may be better off with completely switching the driver to always
programming timings (libata pata_serverworks.c driver is doing things this way
and there were no problems reported so far) but for 2.6.22 lets fix the bug
in the simplest and the least intrusive way.

Cc: Alan Cox <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
  • Loading branch information
bzolnier committed Jun 8, 2007
1 parent ed84fad commit 1abb8a8
Showing 1 changed file with 27 additions and 13 deletions.
40 changes: 27 additions & 13 deletions drivers/ide/pci/serverworks.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* linux/drivers/ide/pci/serverworks.c Version 0.10 Jun 2 2007
* linux/drivers/ide/pci/serverworks.c Version 0.11 Jun 2 2007
*
* Copyright (C) 1998-2000 Michel Aubry
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz
Expand Down Expand Up @@ -176,35 +176,49 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
return 0;
} else if ((dma_timing) &&
((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) {
u8 dmaspeed = dma_timing;
u8 dmaspeed;

if ((dmaspeed & 0x20) == 0x20)
switch (dma_timing & 0x77) {
case 0x20:
dmaspeed = XFER_MW_DMA_2;
else if ((dmaspeed & 0x21) == 0x21)
break;
case 0x21:
dmaspeed = XFER_MW_DMA_1;
else if ((dmaspeed & 0x77) == 0x77)
break;
case 0x77:
dmaspeed = XFER_MW_DMA_0;
else
break;
default:
goto dma_pio;
}

drive->current_speed = drive->init_speed = dmaspeed;
return 0;
}
dma_pio:
if (pio_timing) {
u8 piospeed = pio_timing;
u8 piospeed;

if ((piospeed & 0x20) == 0x20)
switch (pio_timing & 0x7f) {
case 0x20:
piospeed = XFER_PIO_4;
else if ((piospeed & 0x22) == 0x22)
break;
case 0x22:
piospeed = XFER_PIO_3;
else if ((piospeed & 0x34) == 0x34)
break;
case 0x34:
piospeed = XFER_PIO_2;
else if ((piospeed & 0x47) == 0x47)
break;
case 0x47:
piospeed = XFER_PIO_1;
else if ((piospeed & 0x5d) == 0x5d)
break;
case 0x5d:
piospeed = XFER_PIO_0;
else
break;
default:
goto oem_setup_failed;
}

drive->current_speed = drive->init_speed = piospeed;
return 0;
}
Expand Down

0 comments on commit 1abb8a8

Please sign in to comment.