Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 22 Sep 2009 11:47:21 +0000 (UTC)
From:      Marius Strobl <marius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r197402 - head/sys/dev/ata/chipsets
Message-ID:  <200909221147.n8MBlLFC019462@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marius
Date: Tue Sep 22 11:47:21 2009
New Revision: 197402
URL: http://svn.freebsd.org/changeset/base/197402

Log:
  - Add missing bus_dmamap_sync(9) calls for the work DMA map. Previously
    the work area was totally unsynchronized which means this driver only
    had a chance of working on x86 when no bounce buffers were involved,
    which isn't that likely given that support for 64-bit DMA is currently
    broken throughout ata(4).
  - Add necessary little-endian conversion of accesses to the work area,
    making this driver work on big-endian hosts. While at it, use the
    alignment-agnostic byte order encoders in order to be on the safe side.
  - Clear the reserved member of the SG list entries in order to be on the
    safe side. [1]
  
  Submitted by:	yongari [1]
  Reviewed by:	yongari
  MFC after:	3 days

Modified:
  head/sys/dev/ata/chipsets/ata-marvell.c

Modified: head/sys/dev/ata/chipsets/ata-marvell.c
==============================================================================
--- head/sys/dev/ata/chipsets/ata-marvell.c	Tue Sep 22 11:38:45 2009	(r197401)
+++ head/sys/dev/ata/chipsets/ata-marvell.c	Tue Sep 22 11:47:21 2009	(r197402)
@@ -227,6 +227,8 @@ ata_marvell_edma_ch_attach(device_t dev)
     work = ch->dma.work_bus;
     /* clear work area */
     bzero(ch->dma.work, 1024+256);
+    bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
+	BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
     /* set legacy ATA resources */
     for (i = ATA_DATA; i <= ATA_COMMAND; i++) {
@@ -310,7 +312,11 @@ ata_marvell_edma_ch_attach(device_t dev)
 static int
 ata_marvell_edma_ch_detach(device_t dev)
 {
+    struct ata_channel *ch = device_get_softc(dev);
 
+    if (ch->dma.work_tag && ch->dma.work_map)
+	bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
+	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
     ata_dmafini(dev);
     return (0);
 }
@@ -344,8 +350,6 @@ ata_marvell_edma_begin_transaction(struc
     struct ata_channel *ch = device_get_softc(request->parent);
     u_int32_t req_in;
     u_int8_t *bytep;
-    u_int16_t *wordp;
-    u_int32_t *quadp;
     int i;
     int error, slot;
 
@@ -374,13 +378,14 @@ ata_marvell_edma_begin_transaction(struc
     slot = (((req_in & ~0xfffffc00) >> 5) + 0) & 0x1f;
     bytep = (u_int8_t *)(ch->dma.work);
     bytep += (slot << 5);
-    wordp = (u_int16_t *)bytep;
-    quadp = (u_int32_t *)bytep;
 
     /* fill in this request */
-    quadp[0] = (long)request->dma->sg_bus & 0xffffffff;
-    quadp[1] = (u_int64_t)request->dma->sg_bus >> 32;
-    wordp[4] = (request->flags & ATA_R_READ ? 0x01 : 0x00) | (request->tag<<1);
+    le32enc(bytep + 0 * sizeof(u_int32_t),
+	request->dma->sg_bus & 0xffffffff);
+    le32enc(bytep + 1 * sizeof(u_int32_t),
+	(u_int64_t)request->dma->sg_bus >> 32);
+    le16enc(bytep + 4 * sizeof(u_int16_t),
+	(request->flags & ATA_R_READ ? 0x01 : 0x00) | (request->tag << 1));
 
     i = 10;
     bytep[i++] = (request->u.ata.count >> 8) & 0xff;
@@ -409,6 +414,9 @@ ata_marvell_edma_begin_transaction(struc
     bytep[i++] = request->u.ata.command;
     bytep[i++] = 0x90 | ATA_COMMAND;
 
+    bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
+	BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
     /* enable EDMA machinery if needed */
     if (!(ATA_INL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch)) & 0x00000001)) {
 	ATA_OUTL(ctlr->r_res1, 0x02028 + ATA_MV_EDMA_BASE(ch), 0x00000001);
@@ -451,6 +459,8 @@ ata_marvell_edma_end_transaction(struct 
 	slot = (((rsp_in & ~0xffffff00) >> 3)) & 0x1f;
 	rsp_out &= 0xffffff00;
 	rsp_out += (slot << 3);
+	bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
+	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 	response = (struct ata_marvell_response *)
 		   (ch->dma.work + 1024 + (slot << 3));
 
@@ -525,6 +535,7 @@ ata_marvell_edma_dmasetprd(void *xsc, bu
 	prd[i].addrlo = htole32(segs[i].ds_addr);
 	prd[i].count = htole32(segs[i].ds_len);
 	prd[i].addrhi = htole32((u_int64_t)segs[i].ds_addr >> 32);
+	prd[i].reserved = 0;
     }
     prd[i - 1].count |= htole32(ATA_DMA_EOT);
     KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n"));



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