aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-06-08 09:14:28 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-06-08 09:14:28 -0400
commit1abb8a8b841354e7a09ba2009376f0a6368b5cec (patch)
treee51070e52ab7e4490a1a45b4e1deebed4a24e031 /drivers/ide
parented84fad5002c00dfb318f797dbf591320eebc1c0 (diff)
serverworks: fix CSB6 tuning logic
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 <alan@lxorguk.ukuu.org.uk> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/pci/serverworks.c40
1 files changed, 27 insertions, 13 deletions
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index b04c99059c05..d9c4fd1ae996 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/drivers/ide/pci/serverworks.c Version 0.10 Jun 2 2007 2 * linux/drivers/ide/pci/serverworks.c Version 0.11 Jun 2 2007
3 * 3 *
4 * Copyright (C) 1998-2000 Michel Aubry 4 * Copyright (C) 1998-2000 Michel Aubry
5 * Copyright (C) 1998-2000 Andrzej Krzysztofowicz 5 * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
@@ -176,35 +176,49 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
176 return 0; 176 return 0;
177 } else if ((dma_timing) && 177 } else if ((dma_timing) &&
178 ((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) { 178 ((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) {
179 u8 dmaspeed = dma_timing; 179 u8 dmaspeed;
180 180
181 if ((dmaspeed & 0x20) == 0x20) 181 switch (dma_timing & 0x77) {
182 case 0x20:
182 dmaspeed = XFER_MW_DMA_2; 183 dmaspeed = XFER_MW_DMA_2;
183 else if ((dmaspeed & 0x21) == 0x21) 184 break;
185 case 0x21:
184 dmaspeed = XFER_MW_DMA_1; 186 dmaspeed = XFER_MW_DMA_1;
185 else if ((dmaspeed & 0x77) == 0x77) 187 break;
188 case 0x77:
186 dmaspeed = XFER_MW_DMA_0; 189 dmaspeed = XFER_MW_DMA_0;
187 else 190 break;
191 default:
188 goto dma_pio; 192 goto dma_pio;
193 }
194
189 drive->current_speed = drive->init_speed = dmaspeed; 195 drive->current_speed = drive->init_speed = dmaspeed;
190 return 0; 196 return 0;
191 } 197 }
192dma_pio: 198dma_pio:
193 if (pio_timing) { 199 if (pio_timing) {
194 u8 piospeed = pio_timing; 200 u8 piospeed;
195 201
196 if ((piospeed & 0x20) == 0x20) 202 switch (pio_timing & 0x7f) {
203 case 0x20:
197 piospeed = XFER_PIO_4; 204 piospeed = XFER_PIO_4;
198 else if ((piospeed & 0x22) == 0x22) 205 break;
206 case 0x22:
199 piospeed = XFER_PIO_3; 207 piospeed = XFER_PIO_3;
200 else if ((piospeed & 0x34) == 0x34) 208 break;
209 case 0x34:
201 piospeed = XFER_PIO_2; 210 piospeed = XFER_PIO_2;
202 else if ((piospeed & 0x47) == 0x47) 211 break;
212 case 0x47:
203 piospeed = XFER_PIO_1; 213 piospeed = XFER_PIO_1;
204 else if ((piospeed & 0x5d) == 0x5d) 214 break;
215 case 0x5d:
205 piospeed = XFER_PIO_0; 216 piospeed = XFER_PIO_0;
206 else 217 break;
218 default:
207 goto oem_setup_failed; 219 goto oem_setup_failed;
220 }
221
208 drive->current_speed = drive->init_speed = piospeed; 222 drive->current_speed = drive->init_speed = piospeed;
209 return 0; 223 return 0;
210 } 224 }