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>