Module Name:    src
Committed By:   snj
Date:           Thu Apr 23 20:00:09 UTC 2015

Modified Files:
        src/sys/arch/arm/amlogic [netbsd-7]: amlogic_sdhc.c
        src/sys/arch/evbarm/conf [netbsd-7]: ODROID-C1

Log Message:
Pull up following revision(s) (requested by jmcneill in ticket #714):
        sys/arch/arm/amlogic/amlogic_sdhc.c: revisions 1.4-1.6
        sys/arch/evbarm/conf/ODROID-C1: revision 1.17
port number is required
--
The Amlogic SDHC controller doesn't support SG DMA. When we advertise
DMA but not SG DMA support, the sdmmc layer breaks up transfers into
multiple PAGE_SIZE (8KB here) transfers.

Remove the DMA capability flag and do transfers through a MAXPHYS-sized
buffer instead. This lets us do larger transfers and even with the memcpy,
still a significant win for performance.

Before: 134217728 bytes transferred in 15.301 secs (8771827 bytes/sec)
After:  134217728 bytes transferred in 8.834 secs (15193313 bytes/sec)
--
fix size of dmamem map


To generate a diff of this commit:
cvs rdiff -u -r1.3.2.2 -r1.3.2.3 src/sys/arch/arm/amlogic/amlogic_sdhc.c
cvs rdiff -u -r1.12.2.4 -r1.12.2.5 src/sys/arch/evbarm/conf/ODROID-C1

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/amlogic/amlogic_sdhc.c
diff -u src/sys/arch/arm/amlogic/amlogic_sdhc.c:1.3.2.2 src/sys/arch/arm/amlogic/amlogic_sdhc.c:1.3.2.3
--- src/sys/arch/arm/amlogic/amlogic_sdhc.c:1.3.2.2	Sat Mar 21 08:51:17 2015
+++ src/sys/arch/arm/amlogic/amlogic_sdhc.c	Thu Apr 23 20:00:09 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: amlogic_sdhc.c,v 1.3.2.2 2015/03/21 08:51:17 snj Exp $ */
+/* $NetBSD: amlogic_sdhc.c,v 1.3.2.3 2015/04/23 20:00:09 snj Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -29,7 +29,7 @@
 #include "locators.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amlogic_sdhc.c,v 1.3.2.2 2015/03/21 08:51:17 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amlogic_sdhc.c,v 1.3.2.3 2015/04/23 20:00:09 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -64,6 +64,10 @@ struct amlogic_sdhc_softc {
 	kcondvar_t		sc_intr_cv;
 
 	uint32_t		sc_intr_ista;
+
+	bus_dmamap_t		sc_dmamap;
+	bus_dma_segment_t	sc_segs[1];
+	void			*sc_bbuf;
 };
 
 CFATTACH_DECL_NEW(amlogic_sdhc, sizeof(struct amlogic_sdhc_softc),
@@ -87,6 +91,8 @@ static int	amlogic_sdhc_set_clock(struct
 static int	amlogic_sdhc_wait_idle(struct amlogic_sdhc_softc *);
 static int	amlogic_sdhc_wait_ista(struct amlogic_sdhc_softc *, uint32_t, int);
 
+static void	amlogic_sdhc_dmainit(struct amlogic_sdhc_softc *);
+
 static struct sdmmc_chip_functions amlogic_sdhc_chip_functions = {
 	.host_reset = amlogic_sdhc_host_reset,
 	.host_ocr = amlogic_sdhc_host_ocr,
@@ -110,6 +116,12 @@ static struct sdmmc_chip_functions amlog
 static int
 amlogic_sdhc_match(device_t parent, cfdata_t cf, void *aux)
 {
+	struct amlogicio_attach_args * const aio = aux;
+	const struct amlogic_locators * const loc = &aio->aio_loc;
+
+	if (loc->loc_port == AMLOGICIOCF_PORT_DEFAULT)
+		return 0;
+
 	return 1;
 }
 
@@ -146,6 +158,8 @@ amlogic_sdhc_attach(device_t parent, dev
 	}
 	aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr);
 
+	amlogic_sdhc_dmainit(sc);
+
 	config_interrupts(self, amlogic_sdhc_attach_i);
 }
 
@@ -165,12 +179,12 @@ amlogic_sdhc_attach_i(device_t self)
 	saa.saa_sch = sc;
 	saa.saa_clkmin = 400;
 	saa.saa_clkmax = 50000;
+	/* Do not advertise DMA capabilities, we handle DMA ourselves */
 	saa.saa_caps = SMC_CAPS_4BIT_MODE|
 		       SMC_CAPS_8BIT_MODE|
 		       SMC_CAPS_SD_HIGHSPEED|
 		       SMC_CAPS_MMC_HIGHSPEED|
-		       SMC_CAPS_AUTO_STOP|
-		       SMC_CAPS_DMA;
+		       SMC_CAPS_AUTO_STOP;
 
 	sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
 }
@@ -199,6 +213,35 @@ amlogic_sdhc_intr(void *priv)
 	return 1;
 }
 
+static void
+amlogic_sdhc_dmainit(struct amlogic_sdhc_softc *sc)
+{
+	int error, rseg;
+
+	error = bus_dmamem_alloc(sc->sc_dmat, MAXPHYS, PAGE_SIZE, MAXPHYS,
+	    sc->sc_segs, 1, &rseg, BUS_DMA_WAITOK);
+	if (error) {
+		device_printf(sc->sc_dev, "bus_dmamem_alloc failed: %d\n", error);
+		return;
+	}
+	KASSERT(rseg == 1);
+
+	error = bus_dmamem_map(sc->sc_dmat, sc->sc_segs, rseg, MAXPHYS,
+	    &sc->sc_bbuf, BUS_DMA_WAITOK);
+	if (error) {
+		device_printf(sc->sc_dev, "bus_dmamem_map failed\n");
+		return;
+	}
+
+	error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1, MAXPHYS, 0,
+	    BUS_DMA_WAITOK, &sc->sc_dmamap);
+	if (error) {
+		device_printf(sc->sc_dev, "bus_dmamap_create failed\n");
+		return;
+	}
+
+}
+
 static int
 amlogic_sdhc_set_clock(struct amlogic_sdhc_softc *sc, u_int freq)
 {
@@ -431,6 +474,7 @@ amlogic_sdhc_exec_command(sdmmc_chipset_
 {
 	struct amlogic_sdhc_softc *sc = sch;
 	uint32_t cmdval = 0, cntl, srst, pdma, ictl;
+	bool use_bbuf = false;
 	int i;
 
 	KASSERT(cmd->c_blklen <= 512);
@@ -510,9 +554,22 @@ amlogic_sdhc_exec_command(sdmmc_chipset_
 	}
 
 	if (cmd->c_datalen > 0) {
-		KASSERT(cmd->c_dmamap->dm_nsegs == 1);
-		KASSERT(cmd->c_dmamap->dm_segs[0].ds_len >= cmd->c_datalen);
-		SDHC_WRITE(sc, SD_ADDR_REG, cmd->c_dmamap->dm_segs[0].ds_addr);
+		cmd->c_error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap,
+		    sc->sc_bbuf, MAXPHYS, NULL, BUS_DMA_WAITOK);
+		if (cmd->c_error) {
+			device_printf(sc->sc_dev, "bus_dmamap_load failed\n");
+			goto done;
+		}
+		if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
+			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
+			    MAXPHYS, BUS_DMASYNC_PREREAD);
+		} else {
+			memcpy(sc->sc_bbuf, cmd->c_data, cmd->c_datalen);
+			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
+			    MAXPHYS, BUS_DMASYNC_PREWRITE);
+		}
+		SDHC_WRITE(sc, SD_ADDR_REG, sc->sc_dmamap->dm_segs[0].ds_addr);
+		use_bbuf = true;
 	}
 
 	cmd->c_resid = cmd->c_datalen;
@@ -576,6 +633,20 @@ amlogic_sdhc_exec_command(sdmmc_chipset_
 	}
 
 done:
+	if (use_bbuf) {
+		if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
+			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
+			    MAXPHYS, BUS_DMASYNC_POSTREAD);
+		} else {
+			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
+			    MAXPHYS, BUS_DMASYNC_POSTWRITE);
+		}
+		bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap);
+		if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
+			memcpy(cmd->c_data, sc->sc_bbuf, cmd->c_datalen);
+		}
+	}
+
 	cmd->c_flags |= SCF_ITSDONE;
 
 	SDHC_WRITE(sc, SD_ISTA_REG, SD_INT_CLEAR);

Index: src/sys/arch/evbarm/conf/ODROID-C1
diff -u src/sys/arch/evbarm/conf/ODROID-C1:1.12.2.4 src/sys/arch/evbarm/conf/ODROID-C1:1.12.2.5
--- src/sys/arch/evbarm/conf/ODROID-C1:1.12.2.4	Mon Apr  6 01:46:34 2015
+++ src/sys/arch/evbarm/conf/ODROID-C1	Thu Apr 23 20:00:09 2015
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: ODROID-C1,v 1.12.2.4 2015/04/06 01:46:34 snj Exp $
+#	$NetBSD: ODROID-C1,v 1.12.2.5 2015/04/23 20:00:09 snj Exp $
 #
 #	Odroid-C1 (Amlogic S805) based SBC (Single Board Computer)
 #
@@ -200,7 +200,7 @@ amlogicrng0	at amlogicio0
 amlogicrtc0	at amlogicio0
 
 # SDHC controller
-amlogicsdhc0	at amlogicio0
+amlogicsdhc0	at amlogicio0 port 1
 sdmmc*		at amlogicsdhc?
 ld*		at sdmmc?
 

Reply via email to