Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 Oct 2017 19:08:06 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r325061 - head/sys/dev/ffec
Message-ID:  <201710281908.v9SJ86GT013237@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sat Oct 28 19:08:06 2017
New Revision: 325061
URL: https://svnweb.freebsd.org/changeset/base/325061

Log:
  Support up to 3 IRQs in the ffec driver.
  
  Newer hardware splits the interrupts onto 3 different irq lines, but the
  docs barely mention that there are multiple interrupts, and do not detail
  how they're split up.  The code now supports 1-3 irqs, and uses the same
  interrupt service routine to handle all of them.
  
  I modified the submitted changes to use bus_alloc_resources() instead of
  using loops to allocate each irq separately.  Thus, blame any bugs on me (I
  can't actually test on imx7 hardware).
  
  PR:		222634
  Submitted by:	sebastian.huber@embedded-brains.de

Modified:
  head/sys/dev/ffec/if_ffec.c

Modified: head/sys/dev/ffec/if_ffec.c
==============================================================================
--- head/sys/dev/ffec/if_ffec.c	Sat Oct 28 18:56:27 2017	(r325060)
+++ head/sys/dev/ffec/if_ffec.c	Sat Oct 28 19:08:06 2017	(r325061)
@@ -133,6 +133,8 @@ static struct ofw_compat_data compat_data[] = {
 
 #define	WATCHDOG_TIMEOUT_SECS	5
 
+#define	MAX_IRQ_COUNT 3
+
 struct ffec_bufmap {
 	struct mbuf	*mbuf;
 	bus_dmamap_t	map;
@@ -145,9 +147,9 @@ struct ffec_softc {
 	struct ifnet		*ifp;
 	int			if_flags;
 	struct mtx		mtx;
-	struct resource		*irq_res;
+	struct resource		*irq_res[MAX_IRQ_COUNT];
 	struct resource		*mem_res;
-	void *			intr_cookie;
+	void *			intr_cookie[MAX_IRQ_COUNT];
 	struct callout		ffec_callout;
 	mii_contype_t		phy_conn_type;
 	uintptr_t		fectype;
@@ -177,6 +179,13 @@ struct ffec_softc {
 	int			txcount;
 };
 
+static struct resource_spec irq_res_spec[MAX_IRQ_COUNT + 1] = {
+	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
+	{ SYS_RES_IRQ,		1,	RF_ACTIVE | RF_OPTIONAL },
+	{ SYS_RES_IRQ,		2,	RF_ACTIVE | RF_OPTIONAL },
+	RESOURCE_SPEC_END
+};
+
 #define	FFEC_LOCK(sc)			mtx_lock(&(sc)->mtx)
 #define	FFEC_UNLOCK(sc)			mtx_unlock(&(sc)->mtx)
 #define	FFEC_LOCK_INIT(sc)		mtx_init(&(sc)->mtx, \
@@ -1364,7 +1373,7 @@ ffec_detach(device_t dev)
 {
 	struct ffec_softc *sc;
 	bus_dmamap_t map;
-	int idx;
+	int idx, irq;
 
 	/*
 	 * NB: This function can be called internally to unwind a failure to
@@ -1415,15 +1424,17 @@ ffec_detach(device_t dev)
 		bus_dmamap_destroy(sc->txdesc_tag, sc->txdesc_map);
 	}
 	if (sc->txdesc_tag != NULL)
-	bus_dma_tag_destroy(sc->txdesc_tag);
+		bus_dma_tag_destroy(sc->txdesc_tag);
 
 	/* Release bus resources. */
-	if (sc->intr_cookie)
-		bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie);
+	for (irq = 0; irq < MAX_IRQ_COUNT; ++irq) {
+		if (sc->intr_cookie[irq] != NULL) {
+			bus_teardown_intr(dev, sc->irq_res[irq],
+			    sc->intr_cookie[irq]);
+		}
+	}
+	bus_release_resources(dev, irq_res_spec, sc->irq_res);
 
-	if (sc->irq_res != NULL)
-		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
-
 	if (sc->mem_res != NULL)
 		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
 
@@ -1439,7 +1450,7 @@ ffec_attach(device_t dev)
 	struct mbuf *m;
 	void *dummy;
 	phandle_t ofw_node;
-	int error, phynum, rid;
+	int error, phynum, rid, irq;
 	uint8_t eaddr[ETHER_ADDR_LEN];
 	uint32_t idx, mscr;
 
@@ -1490,12 +1501,10 @@ ffec_attach(device_t dev)
 		error = ENOMEM;
 		goto out;
 	}
-	rid = 0;
-	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
-	    RF_ACTIVE);
-	if (sc->irq_res == NULL) {
-		device_printf(dev, "could not allocate interrupt resources.\n");
-		error = ENOMEM;
+
+	error = bus_alloc_resources(dev, irq_res_spec, sc->irq_res);
+	if (error != 0) {
+		device_printf(dev, "could not allocate interrupt resources\n");
 		goto out;
 	}
 
@@ -1656,11 +1665,17 @@ ffec_attach(device_t dev)
 		WR4(sc, FEC_ECR_REG, FEC_ECR_RESET);
 
 	/* Setup interrupt handler. */
-	error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
-	    NULL, ffec_intr, sc, &sc->intr_cookie);
-	if (error != 0) {
-		device_printf(dev, "could not setup interrupt handler.\n");
-		goto out;
+	for (irq = 0; irq < MAX_IRQ_COUNT; ++irq) {
+		if (sc->irq_res[irq] != NULL) {
+			error = bus_setup_intr(dev, sc->irq_res[irq],
+			    INTR_TYPE_NET | INTR_MPSAFE, NULL, ffec_intr, sc,
+			    &sc->intr_cookie[irq]);
+			if (error != 0) {
+				device_printf(dev,
+				    "could not setup interrupt handler.\n");
+				goto out;
+			}
+		}
 	}
 
 	/*



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