svn commit: r362394 - stable/12/sys/dev/mmc/host

Emmanuel Vadot manu at FreeBSD.org
Fri Jun 19 17:52:49 UTC 2020


Author: manu
Date: Fri Jun 19 17:52:48 2020
New Revision: 362394
URL: https://svnweb.freebsd.org/changeset/base/362394

Log:
  MFC r358450, r358635
  
  r358450:
  mmc: dwmmc: Fix off by one error
  
  The IVAR_MAX_DATA is supposed to have the number of descriptor X the mmc
  block size and desc_count contain all this information + 1.
  
  Reported by:	phk
  
  r358635:
  dwmmc: Rework the DMA engine
  
  Each segment can be up to 4096 bytes in chain structure according to the
  RK3399 TRM Part 2.
  Set the buffers in full ring where the last one point to the first one.
  Correctly reports the MMC_IVAR_MAX_DATA.
  Use CACHE_LINE_SIZE for bus_dma alignment.

Modified:
  stable/12/sys/dev/mmc/host/dwmmc.c
  stable/12/sys/dev/mmc/host/dwmmc_hisi.c
  stable/12/sys/dev/mmc/host/dwmmc_var.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/dev/mmc/host/dwmmc.c
==============================================================================
--- stable/12/sys/dev/mmc/host/dwmmc.c	Fri Jun 19 17:49:49 2020	(r362393)
+++ stable/12/sys/dev/mmc/host/dwmmc.c	Fri Jun 19 17:52:48 2020	(r362394)
@@ -99,16 +99,15 @@ __FBSDID("$FreeBSD$");
 #define	DWMMC_ERR_FLAGS		(DWMMC_DATA_ERR_FLAGS | DWMMC_CMD_ERR_FLAGS \
 				|SDMMC_INTMASK_HLE)
 
-#define	DES0_DIC	(1 << 1)
-#define	DES0_LD		(1 << 2)
-#define	DES0_FS		(1 << 3)
-#define	DES0_CH		(1 << 4)
-#define	DES0_ER		(1 << 5)
-#define	DES0_CES	(1 << 30)
-#define	DES0_OWN	(1 << 31)
+#define	DES0_DIC	(1 << 1)	/* Disable Interrupt on Completion */
+#define	DES0_LD		(1 << 2)	/* Last Descriptor */
+#define	DES0_FS		(1 << 3)	/* First Descriptor */
+#define	DES0_CH		(1 << 4)	/* second address CHained */
+#define	DES0_ER		(1 << 5)	/* End of Ring */
+#define	DES0_CES	(1 << 30)	/* Card Error Summary */
+#define	DES0_OWN	(1 << 31)	/* OWN */
 
-#define	DES1_BS1_MASK	0xfff
-#define	DES1_BS1_SHIFT	0
+#define	DES1_BS1_MASK	0x1fff
 
 struct idmac_desc {
 	uint32_t	des0;	/* control */
@@ -117,9 +116,10 @@ struct idmac_desc {
 	uint32_t	des3;	/* buf2 phys addr or next descr */
 };
 
-#define	DESC_MAX	256
-#define	DESC_SIZE	(sizeof(struct idmac_desc) * DESC_MAX)
+#define	IDMAC_DESC_SEGS	(PAGE_SIZE / (sizeof(struct idmac_desc)))
+#define	IDMAC_DESC_SIZE	(sizeof(struct idmac_desc) * IDMAC_DESC_SEGS)
 #define	DEF_MSIZE	0x2	/* Burst size of multiple transaction */
+#define	IDMAC_MAX_SIZE	4096
 
 static void dwmmc_next_operation(struct dwmmc_softc *);
 static int dwmmc_setup_bus(struct dwmmc_softc *, int);
@@ -162,7 +162,7 @@ dwmmc_ring_setup(void *arg, bus_dma_segment_t *segs, i
 
 	for (idx = 0; idx < nsegs; idx++) {
 		sc->desc_ring[idx].des0 = (DES0_OWN | DES0_DIC | DES0_CH);
-		sc->desc_ring[idx].des1 = segs[idx].ds_len;
+		sc->desc_ring[idx].des1 = segs[idx].ds_len & DES1_BS1_MASK;
 		sc->desc_ring[idx].des2 = segs[idx].ds_addr;
 
 		if (idx == 0)
@@ -213,8 +213,8 @@ dma_setup(struct dwmmc_softc *sc)
 	    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
 	    BUS_SPACE_MAXADDR,		/* highaddr */
 	    NULL, NULL,			/* filter, filterarg */
-	    DESC_SIZE, 1, 		/* maxsize, nsegments */
-	    DESC_SIZE,			/* maxsegsize */
+	    IDMAC_DESC_SIZE, 1,		/* maxsize, nsegments */
+	    IDMAC_DESC_SIZE,		/* maxsegsize */
 	    0,				/* flags */
 	    NULL, NULL,			/* lockfunc, lockarg */
 	    &sc->desc_tag);
@@ -234,7 +234,7 @@ dma_setup(struct dwmmc_softc *sc)
 	}
 
 	error = bus_dmamap_load(sc->desc_tag, sc->desc_map,
-	    sc->desc_ring, DESC_SIZE, dwmmc_get1paddr,
+	    sc->desc_ring, IDMAC_DESC_SIZE, dwmmc_get1paddr,
 	    &sc->desc_ring_paddr, 0);
 	if (error != 0) {
 		device_printf(sc->dev,
@@ -242,23 +242,25 @@ dma_setup(struct dwmmc_softc *sc)
 		return (1);
 	}
 
-	for (idx = 0; idx < sc->desc_count; idx++) {
+	for (idx = 0; idx < IDMAC_DESC_SEGS; idx++) {
 		sc->desc_ring[idx].des0 = DES0_CH;
 		sc->desc_ring[idx].des1 = 0;
-		nidx = (idx + 1) % sc->desc_count;
+		nidx = (idx + 1) % IDMAC_DESC_SEGS;
 		sc->desc_ring[idx].des3 = sc->desc_ring_paddr + \
 		    (nidx * sizeof(struct idmac_desc));
 	}
+	sc->desc_ring[idx - 1].des3 = sc->desc_ring_paddr;
+	sc->desc_ring[idx - 1].des0 |= DES0_ER;
 
 	error = bus_dma_tag_create(
 	    bus_get_dma_tag(sc->dev),	/* Parent tag. */
-	    4096, 0,			/* alignment, boundary */
+	    CACHE_LINE_SIZE, 0,		/* alignment, boundary */
 	    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
 	    BUS_SPACE_MAXADDR,		/* highaddr */
 	    NULL, NULL,			/* filter, filterarg */
-	    sc->desc_count * MMC_SECTOR_SIZE, /* maxsize */
-	    sc->desc_count,		/* nsegments */
-	    MMC_SECTOR_SIZE,		/* maxsegsize */
+	    IDMAC_MAX_SIZE * IDMAC_DESC_SEGS,	/* maxsize */
+	    IDMAC_DESC_SEGS,		/* nsegments */
+	    IDMAC_MAX_SIZE,		/* maxsegsize */
 	    0,				/* flags */
 	    NULL, NULL,			/* lockfunc, lockarg */
 	    &sc->buf_tag);
@@ -664,9 +666,6 @@ dwmmc_attach(device_t dev)
 	device_printf(dev, "Hardware version ID is %04x\n",
 		READ4(sc, SDMMC_VERID) & 0xffff);
 
-	if (sc->desc_count == 0)
-		sc->desc_count = DESC_MAX;
-
 	/* XXX: we support operation for slot index 0 only */
 	slot = 0;
 	if (sc->pwren_inverted) {
@@ -1278,7 +1277,7 @@ dwmmc_read_ivar(device_t bus, device_t child, int whic
 		*(int *)result = sc->host.caps;
 		break;
 	case MMCBR_IVAR_MAX_DATA:
-		*(int *)result = sc->desc_count;
+		*(int *)result = (IDMAC_MAX_SIZE * IDMAC_DESC_SEGS) / MMC_SECTOR_SIZE;
 		break;
 	case MMCBR_IVAR_TIMING:
 		*(int *)result = sc->host.ios.timing;

Modified: stable/12/sys/dev/mmc/host/dwmmc_hisi.c
==============================================================================
--- stable/12/sys/dev/mmc/host/dwmmc_hisi.c	Fri Jun 19 17:49:49 2020	(r362393)
+++ stable/12/sys/dev/mmc/host/dwmmc_hisi.c	Fri Jun 19 17:52:48 2020	(r362394)
@@ -79,7 +79,6 @@ hisi_dwmmc_attach(device_t dev)
 	 * DMA when the controller is not cache-coherent on arm64.
 	 */
 	sc->use_pio = 1;
-	sc->desc_count = 1;
 
 	return (dwmmc_attach(dev));
 }

Modified: stable/12/sys/dev/mmc/host/dwmmc_var.h
==============================================================================
--- stable/12/sys/dev/mmc/host/dwmmc_var.h	Fri Jun 19 17:49:49 2020	(r362393)
+++ stable/12/sys/dev/mmc/host/dwmmc_var.h	Fri Jun 19 17:52:48 2020	(r362394)
@@ -60,7 +60,6 @@ struct dwmmc_softc {
 	uint32_t		use_auto_stop;
 	uint32_t		use_pio;
 	uint32_t		pwren_inverted;
-	u_int			desc_count;
 	device_t		child;
 	struct task		card_task;	/* Card presence check task */
 	struct timeout_task	card_delayed_task;/* Card insert delayed task */


More information about the svn-src-all mailing list