Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

it821x: PIO mode setup fixes

* limit max PIO mode to PIO4, this driver doesn't support PIO5 and attempt
to setup PIO5 by it821x_tuneproc() could result in incorrect PIO timings
+ incorrect base clock being set for controller in the passthrough mode

* move code limiting max PIO according to the pair device capabilities from
config_it821x_chipset_for_pio() to it821x_tuneproc() so the check is also
applied for mode change requests coming through ->tuneproc and ->speedproc
interfaces

* set device speed in it821x_tuneproc()

* in it821x_tune_chipset() call it821x_tuneproc() also if the controller is
in the smart mode (so the check for pair device max PIO is done)

* rename it821x_tuneproc() to it821x_tune_pio(), then add it821x_tuneproc()
wrapper which does the max PIO mode check; it worked by the pure luck
previously, pio[4] and pio_want[4] arrays were used with index == 255
so random PIO timings and base clock were set for the controller in the
passthrough mode, thankfully PIO timings and base clock were corrected
later by config_it821x_chipset_for_pio() call (but it was not called for
PIO-only devices during resume and for user requested PIO autotuning)

* remove config_it821x_chipset_for_pio() call from config_chipset_for_dma()
as the driver sets ->autotune to 1 and ->tuneproc does the proper job now

* convert the last user of config_it821x_chipset_for_pio() to use
it821x_tuneproc(drive, 255) and remove no longer needed function

While at it:

* fix few comments

* bump driver version

Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>

+58 -68
+58 -68
drivers/ide/pci/it821x.c
··· 1 1 2 2 /* 3 - * linux/drivers/ide/pci/it821x.c Version 0.09 December 2004 3 + * linux/drivers/ide/pci/it821x.c Version 0.10 Mar 10 2007 4 4 * 5 5 * Copyright (C) 2004 Red Hat <alan@redhat.com> 6 + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz 6 7 * 7 8 * May be copied or modified under the terms of the GNU General Public License 8 9 * Based in part on the ITE vendor provided SCSI driver. ··· 105 104 /** 106 105 * it821x_program - program the PIO/MWDMA registers 107 106 * @drive: drive to tune 107 + * @timing: timing info 108 108 * 109 109 * Program the PIO/MWDMA timing for this channel according to the 110 110 * current clock. ··· 129 127 /** 130 128 * it821x_program_udma - program the UDMA registers 131 129 * @drive: drive to tune 130 + * @timing: timing info 132 131 * 133 132 * Program the UDMA timing for this drive according to the 134 133 * current clock. ··· 156 153 } 157 154 } 158 155 159 - 160 156 /** 161 157 * it821x_clock_strategy 162 - * @hwif: hardware interface 158 + * @drive: drive to set up 163 159 * 164 160 * Select between the 50 and 66Mhz base clocks to get the best 165 161 * results for this interface. ··· 184 182 altclock = itdev->want[0][1]; 185 183 } 186 184 187 - /* Master doesn't care does the slave ? */ 188 - if(clock == ATA_ANY) 185 + /* 186 + * if both clocks can be used for the mode with the higher priority 187 + * use the clock needed by the mode with the lower priority 188 + */ 189 + if (clock == ATA_ANY) 189 190 clock = altclock; 190 191 191 192 /* Nobody cares - keep the same clock */ ··· 245 240 } 246 241 247 242 /** 248 - * it821x_tuneproc - tune a drive 243 + * it821x_tunepio - tune a drive 249 244 * @drive: drive to tune 250 - * @mode_wanted: the target operating mode 245 + * @pio: the desired PIO mode 251 246 * 252 - * Load the timing settings for this device mode into the 253 - * controller. By the time we are called the mode has been 254 - * modified as neccessary to handle the absence of seperate 255 - * master/slave timers for MWDMA/PIO. 256 - * 257 - * This code is only used in pass through mode. 247 + * Try to tune the drive/host to the desired PIO mode taking into 248 + * the consideration the maximum PIO mode supported by the other 249 + * device on the cable. 258 250 */ 259 251 260 - static void it821x_tuneproc (ide_drive_t *drive, byte mode_wanted) 252 + static int it821x_tunepio(ide_drive_t *drive, u8 set_pio) 261 253 { 262 254 ide_hwif_t *hwif = drive->hwif; 263 255 struct it821x_dev *itdev = ide_get_hwifdata(hwif); 264 256 int unit = drive->select.b.unit; 257 + ide_drive_t *pair = &hwif->drives[1 - unit]; 265 258 266 259 /* Spec says 89 ref driver uses 88 */ 267 260 static u16 pio[] = { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 }; 268 261 static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY }; 269 262 270 - if(itdev->smart) 271 - return; 263 + /* 264 + * Compute the best PIO mode we can for a given device. We must 265 + * pick a speed that does not cause problems with the other device 266 + * on the cable. 267 + */ 268 + if (pair) { 269 + u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4, NULL); 270 + /* trim PIO to the slowest of the master/slave */ 271 + if (pair_pio < set_pio) 272 + set_pio = pair_pio; 273 + } 274 + 275 + if (itdev->smart) 276 + goto set_drive_speed; 272 277 273 278 /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */ 274 - itdev->want[unit][1] = pio_want[mode_wanted]; 279 + itdev->want[unit][1] = pio_want[set_pio]; 275 280 itdev->want[unit][0] = 1; /* PIO is lowest priority */ 276 - itdev->pio[unit] = pio[mode_wanted]; 281 + itdev->pio[unit] = pio[set_pio]; 277 282 it821x_clock_strategy(drive); 278 283 it821x_program(drive, itdev->pio[unit]); 284 + 285 + set_drive_speed: 286 + return ide_config_drive_speed(drive, XFER_PIO_0 + set_pio); 287 + } 288 + 289 + static void it821x_tuneproc(ide_drive_t *drive, u8 pio) 290 + { 291 + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); 292 + (void)it821x_tunepio(drive, pio); 279 293 } 280 294 281 295 /** ··· 378 354 } 379 355 380 356 /** 381 - * config_it821x_chipset_for_pio - set drive timings 382 - * @drive: drive to tune 383 - * @speed we want 384 - * 385 - * Compute the best pio mode we can for a given device. We must 386 - * pick a speed that does not cause problems with the other device 387 - * on the cable. 388 - */ 389 - 390 - static void config_it821x_chipset_for_pio (ide_drive_t *drive, byte set_speed) 391 - { 392 - u8 unit = drive->select.b.unit; 393 - ide_hwif_t *hwif = drive->hwif; 394 - ide_drive_t *pair = &hwif->drives[1-unit]; 395 - u8 speed = 0, set_pio = ide_get_best_pio_mode(drive, 255, 5, NULL); 396 - u8 pair_pio; 397 - 398 - /* We have to deal with this mess in pairs */ 399 - if(pair != NULL) { 400 - pair_pio = ide_get_best_pio_mode(pair, 255, 5, NULL); 401 - /* Trim PIO to the slowest of the master/slave */ 402 - if(pair_pio < set_pio) 403 - set_pio = pair_pio; 404 - } 405 - it821x_tuneproc(drive, set_pio); 406 - speed = XFER_PIO_0 + set_pio; 407 - /* XXX - We trim to the lowest of the pair so the other drive 408 - will always be fine at this point until we do hotplug passthru */ 409 - 410 - if (set_speed) 411 - (void) ide_config_drive_speed(drive, speed); 412 - } 413 - 414 - /** 415 357 * it821x_dma_read - DMA hook 416 358 * @drive: drive for DMA 417 359 * ··· 440 450 struct it821x_dev *itdev = ide_get_hwifdata(hwif); 441 451 u8 speed = ide_rate_filter(it821x_ratemask(drive), xferspeed); 442 452 443 - if(!itdev->smart) { 444 - switch(speed) { 445 - case XFER_PIO_4: 446 - case XFER_PIO_3: 447 - case XFER_PIO_2: 448 - case XFER_PIO_1: 449 - case XFER_PIO_0: 450 - it821x_tuneproc(drive, (speed - XFER_PIO_0)); 451 - break; 453 + switch (speed) { 454 + case XFER_PIO_4: 455 + case XFER_PIO_3: 456 + case XFER_PIO_2: 457 + case XFER_PIO_1: 458 + case XFER_PIO_0: 459 + return it821x_tunepio(drive, speed - XFER_PIO_0); 460 + } 461 + 462 + if (itdev->smart == 0) { 463 + switch (speed) { 452 464 /* MWDMA tuning is really hard because our MWDMA and PIO 453 465 timings are kept in the same place. We can switch in the 454 466 host dma on/off callbacks */ ··· 490 498 { 491 499 u8 speed = ide_dma_speed(drive, it821x_ratemask(drive)); 492 500 493 - if (speed) { 494 - config_it821x_chipset_for_pio(drive, 0); 495 - it821x_tune_chipset(drive, speed); 501 + if (speed == 0) 502 + return 0; 496 503 497 - return ide_dma_enable(drive); 498 - } 504 + it821x_tune_chipset(drive, speed); 499 505 500 - return 0; 506 + return ide_dma_enable(drive); 501 507 } 502 508 503 509 /** ··· 513 523 if (ide_use_dma(drive) && config_chipset_for_dma(drive)) 514 524 return 0; 515 525 516 - config_it821x_chipset_for_pio(drive, 1); 526 + it821x_tuneproc(drive, 255); 517 527 518 528 return -1; 519 529 }