Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 02 Nov 2007 11:27:01 +0100
From:      =?ISO-8859-1?Q?S=F8ren_Schmidt?= <sos@deepcore.dk>
To:        Alexander Sabourenkov <screwdriver@lxnt.info>
Cc:        freebsd-hackers@FreeBSD.ORG, sos@FreeBSD.ORG, freebsd-current@FreeBSD.ORG, "Matthew D. Fuller" <fullermd@over-yonder.net>, Thierry Herbelot <thierry@herbelot.com>
Subject:   Re: Patch RFC:  Promise SATA300 TX4 hardware bug workaround.
Message-ID:  <472AFB75.1070207@deepcore.dk>
In-Reply-To: <472A548B.50406@lxnt.info>
References:  <472A548B.50406@lxnt.info>

next in thread | previous in thread | raw e-mail | index | archive | help
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





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?472AFB75.1070207>