Messages in this thread Patch in this message | ![/](/images/icornerl.gif) | | Date | Wed, 23 Apr 2003 17:02:22 -0700 | From | Duncan Laurie <> | Subject | Re: problem with a cobalt RaQ550 system and DMA (Serverworks OSB4 in impossible state) |
| |
Olivier Bornet wrote: > Hello, > > I'm trying to install Debian on 4 RaQ550 with each 2 80GB disks. All > seems OK with 3 of RaQ, but with one, it crash when I put the two disks > in a RAID1 meta device. In fact, it as crash at about 6% before the 70GB > partition is fully synchronized. >
Hi Olivier,
There is an interaction problem between the Serverworks IDE controller and some Seagate BlockPoint drives. They aren't handling the bus throttling correctly on ATA bus writes and are sometimes overflowing their FIFOs.
The CSB5 in UDMA mode 5 sends 3 words after the drive de-asserts DDMARDY- (per ATA spec section 9.14.3.2) but these drives sometimes have problems when the three extra words are sent and overflows its FIFO. Other IDE controllers only send 2 extra words and don't cause this to happen.
The only work around we have found is to limit these drives to ATA mode 4. Supposedly newer Seagate firmware for these drives will report only UDMA mode 4 capable, but for earlier drives (like those probably found in your raq550) try this patch against 2.4.20.
-duncan --- serverworks.c 2002-08-02 17:39:44.000000000 -0700 +++ /home/duncan/cvs/linux-2.4/drivers/ide/serverworks.c 2003-04-23 16:37:45.000000000 -0700 @@ -100,6 +100,12 @@ #include <linux/stat.h> #include <linux/proc_fs.h> +const char *bad_ata100[] = { + "ST340016A", + "ST380021A", + NULL +}; + static struct pci_dev *bmide_dev; static byte svwks_revision = 0; @@ -107,6 +113,14 @@ extern int (*svwks_display_info)(char *, char **, off_t, int); /* ide-proc.c */ extern char *ide_media_verbose(ide_drive_t *); +static int check_in_drive_lists (ide_drive_t *drive, const char **list) +{ + while (*list) + if (!strcmp(*list++, drive->id->model)) + return 1; + return 0; +} + static int svwks_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; @@ -420,7 +434,8 @@ int ultra100 = (ultra66 && svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 1 : 0; byte speed; - if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) { + if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100) && + !check_in_drive_lists(drive, bad_ata100)) { speed = XFER_UDMA_5; } else if (id->dma_ultra & 0x0010) { speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2; | ![\](/images/icornerr.gif) |