From owner-freebsd-current@FreeBSD.ORG Fri Nov 2 10:27:37 2007 Return-Path: Delivered-To: freebsd-current@FreeBSD.ORG Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 81CCD16A417; Fri, 2 Nov 2007 10:27:37 +0000 (UTC) (envelope-from sos@deepcore.dk) Received: from spider.deepcore.dk (cpe.atm2-0-70484.0x50a6c9a6.abnxx16.customer.tele.dk [80.166.201.166]) by mx1.freebsd.org (Postfix) with ESMTP id 0307D13C4A8; Fri, 2 Nov 2007 10:27:36 +0000 (UTC) (envelope-from sos@deepcore.dk) Received: from ws.local (ws.deepcore.dk [194.192.25.137]) by spider.deepcore.dk (8.13.8/8.13.8) with ESMTP id lA2AR1sA063797; Fri, 2 Nov 2007 11:27:01 +0100 (CET) (envelope-from sos@deepcore.dk) Message-ID: <472AFB75.1070207@deepcore.dk> Date: Fri, 02 Nov 2007 11:27:01 +0100 From: =?ISO-8859-1?Q?S=F8ren_Schmidt?= User-Agent: Thunderbird 2.0.0.6 (Macintosh/20070728) MIME-Version: 1.0 To: Alexander Sabourenkov References: <472A548B.50406@lxnt.info> In-Reply-To: <472A548B.50406@lxnt.info> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: quoted-printable Cc: freebsd-hackers@FreeBSD.ORG, sos@FreeBSD.ORG, freebsd-current@FreeBSD.ORG, "Matthew D. Fuller" , Thierry Herbelot Subject: Re: Patch RFC: Promise SATA300 TX4 hardware bug workaround. X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 02 Nov 2007 10:27:37 -0000 Alexander Sabourenkov wrote: > Hello. > > I have ported the workaround for the hardware bug that causes data > corruption on Promise SATA300 TX4 cards to RELENG_7. > > Bug description: > SATA300 TX4 hardware chokes if last PRD entry (in a dma transfer) is > larger than 164 bytes. This was found while analysing vendor-supplied > linux driver. > > Workaround: > Split trailing PRD entry if it's larger that 164 bytes. > > Two supplied patches do fix problem on my machine. > > There is, however, a style problem with them. It seems like PRD entry > count is limited at 256. I have not found a good way to guarantee that > one entry is always available to do the split, thus the ugly solution o= f > patching ata-dma.c. > =20 Good catch! However from my quick glimpse at the Promise sources the limit seems to=20 be 32 Dwords ie 32*4 =3D 128bytes. I'll investigate further and ask Promise for the gory details, stay tuned= =2E.. I dont think the PRD count limitation is a real problem, I've newer seen = that long a list and IIRC we newer do more than 64K transfers in one go=20 (yet). Anyhow I need to get checks in for that not just here... Give me a few days and I'll get this figured out for 7-rel... -S=F8ren > > Patches, patched and original files are at http://lxnt.info/tx4/freebsd= /. > > > --- ata-chipset.c.orig 2007-11-02 01:05:49.000000000 +0300 > +++ ata-chipset.c 2007-11-02 01:05:49.000000000 +0300 > @@ -142,6 +142,7 @@ > static int ata_promise_mio_command(struct ata_request *request); > static void ata_promise_mio_reset(device_t dev); > static void ata_promise_mio_dmainit(device_t dev); > +static void ata_promise_mio_dmasetprd(void *xsc, bus_dma_segment_t > *segs, int nsegs, int error); > static void ata_promise_mio_setmode(device_t dev, int mode); > static void ata_promise_sx4_intr(void *data); > static int ata_promise_sx4_command(struct ata_request *request); > @@ -185,7 +186,6 @@ > static int ata_check_80pin(device_t dev, int mode); > static int ata_mode2idx(int mode); > > - > /* > * generic ATA support functions > */ > @@ -3759,8 +3759,44 @@ > static void > ata_promise_mio_dmainit(device_t dev) > { > + struct ata_channel *ch =3D device_get_softc(dev); > +=09 > /* note start and stop are not used here */ > ata_dmainit(dev); > + > + if (ch->dma) > + ch->dma->setprd =3D ata_promise_mio_dmasetprd; > +} > + > +static void > +ata_promise_mio_dmasetprd(void *xsc, bus_dma_segment_t *segs, int > nsegs, int error) > +{ > + #define PDC_MAXLASTSGSIZE 41*4 > + struct ata_dmasetprd_args *args =3D xsc; > + struct ata_dma_prdentry *prd =3D args->dmatab; > + int i; > + > + if ((args->error =3D error)) > + return; > + > + for (i =3D 0; i < nsegs; i++) { > + prd[i].addr =3D htole32(segs[i].ds_addr); > + prd[i].count =3D htole32(segs[i].ds_len); > + } > + > + if (segs[i - 1].ds_len > PDC_MAXLASTSGSIZE) { > + /* > + printf("splitting trailing PRD of %ld (limit %d)\n", segs[i - > 1].ds_len, PDC_MAXLASTSGSIZE); > + */ > + prd[i - 1].count =3D htole32(segs[i - 1].ds_len - PDC_MAXLASTSGSIZE);= > + prd[i].count =3D htole32(PDC_MAXLASTSGSIZE); > + prd[i].addr =3D htole32(segs[i - 1].ds_addr + PDC_MAXLASTSGSIZE); > + i ++; > + nsegs ++; > + } > + > + prd[i - 1].count |=3D htole32(ATA_DMA_EOT); > + args->nsegs =3D nsegs; > } > > static void > > --- ata-dma.c.orig 2007-11-02 01:05:53.000000000 +0300 > +++ ata-dma.c 2007-11-02 01:05:53.000000000 +0300 > @@ -113,7 +113,7 @@ > if > (bus_dma_tag_create(ch->dma->dmatag,ch->dma->alignment,ch->dma->boundar= y, > ch->dma->max_address, BUS_SPACE_MAXADDR, > NULL, NULL, ch->dma->max_iosize, > - ATA_DMA_ENTRIES, ch->dma->segsize, > + ATA_DMA_ENTRIES - 1, ch->dma->segsize, > 0, NULL, NULL, &ch->dma->data_tag)) > goto error; > > > =20