lkml.org 
[lkml]   [2000]   [Sep]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[patch - critical] Fixes for VIA IDE driver
Hi!

I have found a couple bugs in the VIA IDE kernel I'm now maintaining
that manifest themselves on hardware I don't have:

1) On old SWDMA devices the timing is programmed incorrectly. This will
result in DMA timeouts or data corruption.

2) On UDMA devices used with vt82c596a (old buggy VIA MobileSouth), the
chip will get confused, which will result in DMA timeouts and UDMA
being disabled. No data corruption here, just very poor performance.

3) One extra sprintf was forgotten in the via_display_info function.
This is harmless, but a bug nevertheless.

Here goes a detailed description of the patch that fixes the above three
bugs:

Chunk1:
Changes version number
Chunk2:
Removes UDMA66 unknown southbridge entry. We can't try to program
unknown southbridges to UDMA66, because that can result in crashes
(as shown by vt82c596a). UDMA33 should be safe, because the only
southbridge that doesn't support it is vt82c586.
Chunk3:
Fix SWDMA modes. By a typo there were 0's everywhere. This is
important, without this fix SWDMA devices will be programmed
incorrectly.
Chunk4:
Change version number in /proc
Chunk5:
Remove the sprintf().
Chunk6:
Don't program UDMA66 enable bit on UDMA33 controllers. They *should*
ignore it, but 596a doesn't, resulting in timeouts on boot. This is
critical. Also don't program UDMA at all on the old vt82c586.
Chunk7:
The correct way to check for 596a.
Chunk8:
Remove the old check for 596a. It doesn't work, because the 596a doesn't
ignore the UDMA66 bits as it should. Don't set UDMA66 on 596a at
all, it causes crashes. Critical.

I hope this will get into test9-pre6, because otherwise it's quite
unusable for vt82c596a users.

TIA.

--
Vojtech Pavlik
SuSE Labs
--- linux-old/drivers/ide/via82cxxx.c Wed Sep 6 17:07:56 2000
+++ linux/drivers/ide/via82cxxx.c Wed Sep 20 23:33:08 2000
@@ -1,5 +1,5 @@
/*
- * $Id: via82cxxx.c,v 2.1 2000/08/29 01:34:60 vojtech Exp $
+ * $Id: via82cxxx.c,v 2.1b 2000/09/20 23:19:60 vojtech Exp $
*
* Copyright (c) 2000 Vojtech Pavlik
*
@@ -97,7 +97,6 @@
{ "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, XFER_UDMA_2 },
{ "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, XFER_UDMA_2 },
{ "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, XFER_MW_DMA_2 },
- { "Unknown SouthBridge", 0, XFER_UDMA_4 },
{ "Unknown SouthBridge", 0, XFER_UDMA_2 },
};

@@ -140,8 +139,8 @@
{ XFER_MW_DMA_1, "MDMA1", 45, 80, 50, 150, 0 },
{ XFER_MW_DMA_0, "MDMA0", 60, 215, 215, 480, 0 },

- { XFER_SW_DMA_0, "SDMA0", 60, 120, 120, 240, 0 },
- { XFER_SW_DMA_0, "SDMA0", 90, 240, 240, 480, 0 },
+ { XFER_SW_DMA_2, "SDMA2", 60, 120, 120, 240, 0 },
+ { XFER_SW_DMA_1, "SDMA1", 90, 240, 240, 480, 0 },
{ XFER_SW_DMA_0, "SDMA0",120, 480, 480, 960, 0 },

{ XFER_PIO_5, "PIO5", 20, 50, 30, 100, 0 },
@@ -193,7 +192,7 @@

via_print("----------VIA BusMastering IDE Configuration----------------");

- via_print("Driver Version: 2.1");
+ via_print("Driver Version: 2.1b");

pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t);
via_print("South Bridge: VIA %s rev %#x", via_isa_bridges[via_config].name, t);
@@ -213,9 +212,6 @@
via_print("FIFO Output Data 1/2 Clock Advance: %s", (t & 16) ? "on" : "off" );
via_print("BM IDE Status Register Read Retry: %s", (t & 8) ? "on" : "off" );

- pci_read_config_byte(dev, VIA_MISC_2, &t);
- sprintf(p, "Interrupt Steering Swap: %s", (t & 64) ? "on" : "off");
-
pci_read_config_byte(dev, VIA_MISC_3, &t);
via_print("Max DRDY Pulse Width: %s%s", via_control3[(t & 0x03)], (t & 0x03) ? "PCI clocks" : "");

@@ -337,15 +333,13 @@
* UDMA cycle
*/

- if (via_timing[i].udma) {
- t = 0xe8;
- if (via_isa_bridges[via_config].speed >= XFER_UDMA_4)
- t |= FIT(ENOUGH(via_timing[i].udma, T >> 1) - 2, 0, 7);
- else
- t |= FIT(ENOUGH(via_timing[i].udma, T ) - 2, 0, 3);
- } else t = 0x0b;
+ switch(via_isa_bridges[via_config].speed) {
+ case XFER_UDMA_2: t = via_timing[i].udma ? (0x60 | (FIT(via_timing[i].udma, 2, 5) - 2)) : 0x03; break;
+ case XFER_UDMA_4: t = via_timing[i].udma ? (0xe8 | (FIT(via_timing[i].udma, 2, 9) - 2)) : 0x0f; break;
+ }

- via_write_config_byte(dev, VIA_UDMA_TIMING + (3 - drive->dn), t);
+ if (via_isa_bridges[via_config].speed != XFER_MW_DMA_2)
+ via_write_config_byte(dev, VIA_UDMA_TIMING + (3 - drive->dn), t);

/*
* Drive init
@@ -511,6 +505,11 @@
if (t < 0x20) via_config++; /* vt82c586 */
}

+ if (via_isa_bridges[via_config].id == PCI_DEVICE_ID_VIA_82C596) {
+ pci_read_config_byte(isa, PCI_REVISION_ID, &t);
+ if (t < 0x10) via_config++; /* vt82c596a */
+ }
+
/*
* Check UDMA66 mode set by BIOS.
*/
@@ -530,13 +529,8 @@
/*
* Set UDMA66 double clock bits.
*/
-
- pci_write_config_dword(dev, VIA_UDMA_TIMING, u | 0x80008);
- pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
-
- if ((via_isa_bridges[via_config].id == PCI_DEVICE_ID_VIA_82C596 || !isa)
- && (u & 0x80008) != 0x80008)
- via_config++; /* vt82c596a / Unknown UDMA33 */
+ if (via_isa_bridges[via_config].speed == XFER_UDMA_4)
+ pci_write_config_dword(dev, VIA_UDMA_TIMING, u | 0x80008);

/*
* Set up FIFO, flush, prefetch and post-writes.
\
 
 \ /
  Last update: 2005-03-22 12:45    [W:0.029 / U:0.248 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site