mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-29 22:06:39 +07:00
serverworks: always tune PIO
* Always set ->autotune so PIO gets correctly auto-tuned (previously ->autotune was only set when ->dma_base wasn't available, however ->ide_dma_check()/->speedproc() was always trying to tune PIO when tuning DMA). * Move code responsible for programming chipset for PIO mode from svwks_tune_chipset() to svwks_tune_pio(). Don't tune PIO when tuning DMA (this is no longer needed since ->autotune is always set now). * Handle PIO modes early in svwks_tune_chipset() so DMA configuration registers don't get cleared when programming PIO mode. * Bump driver version. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
This commit is contained in:
parent
a5d8c5c834
commit
1880a8d7f2
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* linux/drivers/ide/pci/serverworks.c Version 0.20 Jun 3 2007
|
||||
* linux/drivers/ide/pci/serverworks.c Version 0.21 Jun 16 2007
|
||||
*
|
||||
* Copyright (C) 1998-2000 Michel Aubry
|
||||
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz
|
||||
@ -123,23 +123,45 @@ static u8 svwks_csb_check (struct pci_dev *dev)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void svwks_tune_pio(ide_drive_t *drive, const u8 pio)
|
||||
{
|
||||
static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
|
||||
static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 };
|
||||
|
||||
struct pci_dev *dev = drive->hwif->pci_dev;
|
||||
|
||||
pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]);
|
||||
|
||||
if (svwks_csb_check(dev)) {
|
||||
u16 csb_pio = 0;
|
||||
|
||||
pci_read_config_word(dev, 0x4a, &csb_pio);
|
||||
|
||||
csb_pio &= ~(0x0f << (4 * drive->dn));
|
||||
csb_pio |= (pio << (4 * drive->dn));
|
||||
|
||||
pci_write_config_word(dev, 0x4a, csb_pio);
|
||||
}
|
||||
}
|
||||
|
||||
static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
|
||||
{
|
||||
static const u8 udma_modes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
|
||||
static const u8 dma_modes[] = { 0x77, 0x21, 0x20 };
|
||||
static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
|
||||
static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 };
|
||||
static const u8 drive_pci2[] = { 0x45, 0x44, 0x47, 0x46 };
|
||||
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct pci_dev *dev = hwif->pci_dev;
|
||||
u8 speed = ide_rate_filter(drive, xferspeed);
|
||||
u8 pio = ide_get_best_pio_mode(drive, 255, 4, NULL);
|
||||
u8 unit = (drive->select.b.unit & 0x01);
|
||||
u8 csb5 = svwks_csb_check(dev);
|
||||
u8 ultra_enable = 0, ultra_timing = 0;
|
||||
u8 dma_timing = 0, pio_timing = 0;
|
||||
u16 csb5_pio = 0;
|
||||
|
||||
u8 ultra_enable = 0, ultra_timing = 0, dma_timing = 0;
|
||||
|
||||
if (speed >= XFER_PIO_0 && speed <= XFER_PIO_4) {
|
||||
svwks_tune_pio(drive, speed - XFER_PIO_0);
|
||||
return ide_config_drive_speed(drive, speed);
|
||||
}
|
||||
|
||||
/* If we are about to put a disk into UDMA mode we screwed up.
|
||||
Our code assumes we never _ever_ do this on an OSB4 */
|
||||
@ -149,31 +171,15 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
|
||||
BUG();
|
||||
|
||||
pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
|
||||
pci_read_config_word(dev, 0x4A, &csb5_pio);
|
||||
pci_read_config_byte(dev, 0x54, &ultra_enable);
|
||||
|
||||
ultra_timing &= ~(0x0F << (4*unit));
|
||||
ultra_enable &= ~(0x01 << drive->dn);
|
||||
csb5_pio &= ~(0x0F << (4*drive->dn));
|
||||
|
||||
switch(speed) {
|
||||
case XFER_PIO_4:
|
||||
case XFER_PIO_3:
|
||||
case XFER_PIO_2:
|
||||
case XFER_PIO_1:
|
||||
case XFER_PIO_0:
|
||||
pio_timing |= pio_modes[speed - XFER_PIO_0];
|
||||
csb5_pio |= ((speed - XFER_PIO_0) << (4*drive->dn));
|
||||
break;
|
||||
|
||||
case XFER_MW_DMA_2:
|
||||
case XFER_MW_DMA_1:
|
||||
case XFER_MW_DMA_0:
|
||||
/*
|
||||
* TODO: always setup PIO mode so this won't be needed
|
||||
*/
|
||||
pio_timing |= pio_modes[pio];
|
||||
csb5_pio |= (pio << (4*drive->dn));
|
||||
dma_timing |= dma_modes[speed - XFER_MW_DMA_0];
|
||||
break;
|
||||
|
||||
@ -183,11 +189,6 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
|
||||
case XFER_UDMA_2:
|
||||
case XFER_UDMA_1:
|
||||
case XFER_UDMA_0:
|
||||
/*
|
||||
* TODO: always setup PIO mode so this won't be needed
|
||||
*/
|
||||
pio_timing |= pio_modes[pio];
|
||||
csb5_pio |= (pio << (4*drive->dn));
|
||||
dma_timing |= dma_modes[2];
|
||||
ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit));
|
||||
ultra_enable |= (0x01 << drive->dn);
|
||||
@ -195,10 +196,6 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
|
||||
break;
|
||||
}
|
||||
|
||||
pci_write_config_byte(dev, drive_pci[drive->dn], pio_timing);
|
||||
if (csb5)
|
||||
pci_write_config_word(dev, 0x4A, csb5_pio);
|
||||
|
||||
pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing);
|
||||
pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing);
|
||||
pci_write_config_byte(dev, 0x54, ultra_enable);
|
||||
@ -209,7 +206,8 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
|
||||
static void svwks_tune_drive (ide_drive_t *drive, u8 pio)
|
||||
{
|
||||
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
|
||||
(void)svwks_tune_chipset(drive, XFER_PIO_0 + pio);
|
||||
svwks_tune_pio(drive, pio);
|
||||
(void)ide_config_drive_speed(drive, XFER_PIO_0 + pio);
|
||||
}
|
||||
|
||||
static int svwks_config_drive_xfer_rate (ide_drive_t *drive)
|
||||
@ -407,11 +405,11 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
|
||||
|
||||
hwif->autodma = 0;
|
||||
|
||||
if (!hwif->dma_base) {
|
||||
hwif->drives[0].autotune = 1;
|
||||
hwif->drives[1].autotune = 1;
|
||||
hwif->drives[0].autotune = 1;
|
||||
hwif->drives[1].autotune = 1;
|
||||
|
||||
if (!hwif->dma_base)
|
||||
return;
|
||||
}
|
||||
|
||||
hwif->ide_dma_check = &svwks_config_drive_xfer_rate;
|
||||
if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
|
||||
@ -424,8 +422,6 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
|
||||
dma_stat = inb(hwif->dma_status);
|
||||
hwif->drives[0].autodma = (dma_stat & 0x20);
|
||||
hwif->drives[1].autodma = (dma_stat & 0x40);
|
||||
hwif->drives[0].autotune = (!(dma_stat & 0x20));
|
||||
hwif->drives[1].autotune = (!(dma_stat & 0x40));
|
||||
}
|
||||
|
||||
static int __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d)
|
||||
|
Loading…
Reference in New Issue
Block a user