Module Name: src
Committed By: skrll
Date: Sun Jun 12 07:18:52 UTC 2016
Modified Files:
src/sys/arch/arm/allwinner [nick-nhusb]: awin_gige.c
src/sys/arch/arm/amlogic [nick-nhusb]: amlogic_gmac.c
src/sys/dev/ic [nick-nhusb]: dwc_gmac.c dwc_gmac_var.h
Log Message:
First pass at making this driver and attachments NET_MPSAFE aware.
I've not tested this yet.
To generate a diff of this commit:
cvs rdiff -u -r1.19.2.1 -r1.19.2.2 src/sys/arch/arm/allwinner/awin_gige.c
cvs rdiff -u -r1.2.4.2 -r1.2.4.3 src/sys/arch/arm/amlogic/amlogic_gmac.c
cvs rdiff -u -r1.28.2.3 -r1.28.2.4 src/sys/dev/ic/dwc_gmac.c
cvs rdiff -u -r1.6 -r1.6.2.1 src/sys/dev/ic/dwc_gmac_var.h
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/allwinner/awin_gige.c
diff -u src/sys/arch/arm/allwinner/awin_gige.c:1.19.2.1 src/sys/arch/arm/allwinner/awin_gige.c:1.19.2.2
--- src/sys/arch/arm/allwinner/awin_gige.c:1.19.2.1 Mon Apr 6 15:17:51 2015
+++ src/sys/arch/arm/allwinner/awin_gige.c Sun Jun 12 07:18:52 2016
@@ -34,7 +34,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: awin_gige.c,v 1.19.2.1 2015/04/06 15:17:51 skrll Exp $");
+__KERNEL_RCSID(1, "$NetBSD: awin_gige.c,v 1.19.2.2 2016/06/12 07:18:52 skrll Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -153,7 +153,11 @@ awin_gige_attach(device_t parent, device
/*
* Interrupt handler
*/
- sc->sc_ih = intr_establish(loc->loc_intr, IPL_NET, IST_LEVEL,
+ int mpsafe = 0;
+#ifdef NET_MPSAFE
+ mpsafe |= IST_MPSAFE;
+#endif
+ sc->sc_ih = intr_establish(loc->loc_intr, IPL_NET, IST_LEVEL | mpsafe,
awin_gige_intr, sc);
if (sc->sc_ih == NULL) {
aprint_error_dev(self, "failed to establish interrupt %d\n",
Index: src/sys/arch/arm/amlogic/amlogic_gmac.c
diff -u src/sys/arch/arm/amlogic/amlogic_gmac.c:1.2.4.2 src/sys/arch/arm/amlogic/amlogic_gmac.c:1.2.4.3
--- src/sys/arch/arm/amlogic/amlogic_gmac.c:1.2.4.2 Mon Apr 6 15:17:51 2015
+++ src/sys/arch/arm/amlogic/amlogic_gmac.c Sun Jun 12 07:18:52 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: amlogic_gmac.c,v 1.2.4.2 2015/04/06 15:17:51 skrll Exp $ */
+/* $NetBSD: amlogic_gmac.c,v 1.2.4.3 2016/06/12 07:18:52 skrll Exp $ */
/*-
* Copyright (c) 2013, 2014, 2015 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: amlogic_gmac.c,v 1.2.4.2 2015/04/06 15:17:51 skrll Exp $");
+__KERNEL_RCSID(1, "$NetBSD: amlogic_gmac.c,v 1.2.4.3 2016/06/12 07:18:52 skrll Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -92,7 +92,11 @@ amlogic_gmac_attach(device_t parent, dev
/*
* Interrupt handler
*/
- sc->sc_ih = intr_establish(loc->loc_intr, IPL_NET, IST_EDGE,
+ int mpsafe = 0;
+#ifdef NET_MPSAFE
+ mpsafe |= IST_MPSAFE;
+#endif
+ sc->sc_ih = intr_establish(loc->loc_intr, IPL_NET, IST_EDGE | mpsafe,
amlogic_gmac_intr, sc);
if (sc->sc_ih == NULL) {
aprint_error_dev(self, "failed to establish interrupt %d\n",
Index: src/sys/dev/ic/dwc_gmac.c
diff -u src/sys/dev/ic/dwc_gmac.c:1.28.2.3 src/sys/dev/ic/dwc_gmac.c:1.28.2.4
--- src/sys/dev/ic/dwc_gmac.c:1.28.2.3 Sat Mar 19 11:30:09 2016
+++ src/sys/dev/ic/dwc_gmac.c Sun Jun 12 07:18:52 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac.c,v 1.28.2.3 2016/03/19 11:30:09 skrll Exp $ */
+/* $NetBSD: dwc_gmac.c,v 1.28.2.4 2016/06/12 07:18:52 skrll Exp $ */
/*-
* Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
@@ -41,11 +41,14 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.28.2.3 2016/03/19 11:30:09 skrll Exp $");
+__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.28.2.4 2016/06/12 07:18:52 skrll Exp $");
/* #define DWC_GMAC_DEBUG 1 */
+#ifdef _KERNEL_OPT
#include "opt_inet.h"
+#include "opt_net_mpsafe.h"
+#endif
#include <sys/param.h>
#include <sys/bus.h>
@@ -85,8 +88,11 @@ static void dwc_gmac_reset_tx_ring(struc
static void dwc_gmac_free_tx_ring(struct dwc_gmac_softc *sc, struct dwc_gmac_tx_ring *);
static void dwc_gmac_txdesc_sync(struct dwc_gmac_softc *sc, int start, int end, int ops);
static int dwc_gmac_init(struct ifnet *ifp);
+static int dwc_gmac_init_locked(struct ifnet *ifp);
static void dwc_gmac_stop(struct ifnet *ifp, int disable);
+static void dwc_gmac_stop_locked(struct ifnet *ifp, int disable);
static void dwc_gmac_start(struct ifnet *ifp);
+static void dwc_gmac_start_locked(struct ifnet *ifp);
static int dwc_gmac_queue(struct dwc_gmac_softc *sc, struct mbuf *m0);
static int dwc_gmac_ioctl(struct ifnet *, u_long, void *);
static void dwc_gmac_tx_intr(struct dwc_gmac_softc *sc);
@@ -128,6 +134,10 @@ static void dwc_dump_status(struct dwc_g
static void dwc_gmac_dump_ffilt(struct dwc_gmac_softc *sc, uint32_t ffilt);
#endif
+#ifdef NET_MPSAFE
+#define DWCGMAC_MPSAFE 1
+#endif
+
void
dwc_gmac_attach(struct dwc_gmac_softc *sc, uint32_t mii_clk)
{
@@ -136,7 +146,6 @@ dwc_gmac_attach(struct dwc_gmac_softc *s
struct mii_data * const mii = &sc->sc_mii;
struct ifnet * const ifp = &sc->sc_ec.ec_if;
prop_dictionary_t dict;
- int s;
mutex_init(&sc->sc_mdio_lock, MUTEX_DEFAULT, IPL_NET);
sc->sc_mii_clk = mii_clk & 7;
@@ -198,12 +207,15 @@ dwc_gmac_attach(struct dwc_gmac_softc *s
goto fail;
}
- mutex_init(&sc->sc_rxq.r_mtx, MUTEX_DEFAULT, IPL_NET);
if (dwc_gmac_alloc_rx_ring(sc, &sc->sc_rxq) != 0) {
aprint_error_dev(sc->sc_dev, "could not allocate Rx ring\n");
goto fail;
}
+ sc->sc_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
+ mutex_init(&sc->sc_txq.t_mtx, MUTEX_DEFAULT, IPL_NET);
+ mutex_init(&sc->sc_rxq.r_mtx, MUTEX_DEFAULT, IPL_NET);
+
/*
* Prepare interface data
*/
@@ -245,19 +257,22 @@ dwc_gmac_attach(struct dwc_gmac_softc *s
/*
* Ready, attach interface
*/
- if_attach(ifp);
+ /* Attach the interface. */
+ if_initialize(ifp);
+ sc->sc_ipq = if_percpuq_create(&sc->sc_ec.ec_if);
ether_ifattach(ifp, enaddr);
ether_set_ifflags_cb(&sc->sc_ec, dwc_gmac_ifflags_cb);
+ if_register(ifp);
/*
* Enable interrupts
*/
- s = splnet();
+ mutex_enter(sc->sc_lock);
bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_INTMASK,
AWIN_DEF_MAC_INTRMASK);
bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_INTENABLE,
GMAC_DEF_DMA_INT_MASK);
- splx(s);
+ mutex_exit(sc->sc_lock);
return;
@@ -439,6 +454,7 @@ dwc_gmac_reset_rx_ring(struct dwc_gmac_s
struct dwc_gmac_dev_dmadesc *desc;
int i;
+ mutex_enter(&ring->r_mtx);
for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
desc = &sc->sc_rxq.r_desc[i];
desc->ddesc_cntl = htole32(
@@ -455,6 +471,7 @@ dwc_gmac_reset_rx_ring(struct dwc_gmac_s
/* reset DMA address to start of ring */
bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RX_ADDR,
sc->sc_rxq.r_physaddr);
+ mutex_exit(&ring->r_mtx);
}
static int
@@ -618,6 +635,7 @@ dwc_gmac_reset_tx_ring(struct dwc_gmac_s
{
int i;
+ mutex_enter(&ring->t_mtx);
for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
struct dwc_gmac_tx_data *data = &ring->t_data[i];
@@ -640,6 +658,7 @@ dwc_gmac_reset_tx_ring(struct dwc_gmac_s
ring->t_queued = 0;
ring->t_cur = ring->t_next = 0;
+ mutex_exit(&ring->t_mtx);
}
static void
@@ -729,6 +748,18 @@ static int
dwc_gmac_init(struct ifnet *ifp)
{
struct dwc_gmac_softc *sc = ifp->if_softc;
+
+ mutex_enter(sc->sc_lock);
+ int ret = dwc_gmac_init_locked(ifp);
+ mutex_exit(sc->sc_lock);
+
+ return ret;
+}
+
+static int
+dwc_gmac_init_locked(struct ifnet *ifp)
+{
+ struct dwc_gmac_softc *sc = ifp->if_softc;
uint32_t ffilt;
if (ifp->if_flags & IFF_RUNNING)
@@ -781,6 +812,8 @@ dwc_gmac_init(struct ifnet *ifp)
AWIN_GMAC_DMA_OPMODE, GMAC_DMA_OP_RXSTART | GMAC_DMA_OP_TXSTART |
GMAC_DMA_OP_RXSTOREFORWARD | GMAC_DMA_OP_TXSTOREFORWARD);
+ sc->sc_stopping = false;
+
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
@@ -791,6 +824,20 @@ static void
dwc_gmac_start(struct ifnet *ifp)
{
struct dwc_gmac_softc *sc = ifp->if_softc;
+
+ mutex_enter(sc->sc_lock);
+ if (!sc->sc_stopping) {
+ mutex_enter(&sc->sc_txq.t_mtx);
+ dwc_gmac_start_locked(ifp);
+ mutex_exit(&sc->sc_txq.t_mtx);
+ }
+ mutex_exit(sc->sc_lock);
+}
+
+static void
+dwc_gmac_start_locked(struct ifnet *ifp)
+{
+ struct dwc_gmac_softc *sc = ifp->if_softc;
int old = sc->sc_txq.t_queued;
int start = sc->sc_txq.t_cur;
struct mbuf *m0;
@@ -832,6 +879,18 @@ dwc_gmac_stop(struct ifnet *ifp, int dis
{
struct dwc_gmac_softc *sc = ifp->if_softc;
+ mutex_enter(sc->sc_lock);
+ dwc_gmac_stop_locked(ifp, disable);
+ mutex_exit(sc->sc_lock);
+}
+
+static void
+dwc_gmac_stop_locked(struct ifnet *ifp, int disable)
+{
+ struct dwc_gmac_softc *sc = ifp->if_softc;
+
+ sc->sc_stopping = true;
+
bus_space_write_4(sc->sc_bst, sc->sc_bsh,
AWIN_GMAC_DMA_OPMODE,
bus_space_read_4(sc->sc_bst, sc->sc_bsh,
@@ -940,8 +999,11 @@ dwc_gmac_ifflags_cb(struct ethercom *ec)
if ((change & ~(IFF_CANTCHANGE|IFF_DEBUG)) != 0)
return ENETRESET;
- if ((change & IFF_PROMISC) != 0)
+ if ((change & IFF_PROMISC) != 0) {
+ mutex_enter(sc->sc_lock);
dwc_gmac_setmulti(sc);
+ mutex_exit(sc->sc_lock);
+ }
return 0;
}
@@ -949,11 +1011,16 @@ static int
dwc_gmac_ioctl(struct ifnet *ifp, u_long cmd, void *data)
{
struct dwc_gmac_softc *sc = ifp->if_softc;
- int s, error = 0;
+ int error = 0;
- s = splnet();
+ int s = splnet();
+ error = ether_ioctl(ifp, cmd, data);
- if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
+#ifdef DWCGMAC_MPSAFE
+ splx(s);
+#endif
+
+ if (error == ENETRESET) {
error = 0;
if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
;
@@ -962,7 +1029,9 @@ dwc_gmac_ioctl(struct ifnet *ifp, u_long
* Multicast list has changed; set the hardware filter
* accordingly.
*/
+ mutex_enter(sc->sc_lock);
dwc_gmac_setmulti(sc);
+ mutex_exit(sc->sc_lock);
}
}
@@ -970,7 +1039,11 @@ dwc_gmac_ioctl(struct ifnet *ifp, u_long
if (ifp->if_flags & IFF_UP)
dwc_gmac_start(ifp);
sc->sc_if_flags = sc->sc_ec.ec_if.if_flags;
+
+#ifndef DWCGMAC_MPSAFE
splx(s);
+#endif
+
return error;
}
@@ -983,6 +1056,8 @@ dwc_gmac_tx_intr(struct dwc_gmac_softc *
uint32_t status;
int i, nsegs;
+ mutex_enter(&sc->sc_txq.t_mtx);
+
for (i = sc->sc_txq.t_next; sc->sc_txq.t_queued > 0; i = TX_NEXT(i)) {
#ifdef DWC_GMAC_DEBUG
aprint_normal_dev(sc->sc_dev,
@@ -1030,6 +1105,7 @@ dwc_gmac_tx_intr(struct dwc_gmac_softc *
if (sc->sc_txq.t_queued < AWGE_TX_RING_COUNT) {
ifp->if_flags &= ~IFF_OACTIVE;
}
+ mutex_exit(&sc->sc_txq.t_mtx);
}
static void
@@ -1043,6 +1119,7 @@ dwc_gmac_rx_intr(struct dwc_gmac_softc *
struct mbuf *m, *mnew;
int i, len, error;
+ mutex_enter(&sc->sc_rxq.r_mtx);
for (i = sc->sc_rxq.r_cur; ; i = RX_NEXT(i)) {
bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
RX_DESC_OFFSET(i), sizeof(*desc),
@@ -1098,7 +1175,7 @@ dwc_gmac_rx_intr(struct dwc_gmac_softc *
error = bus_dmamap_load(sc->sc_dmat, data->rd_map,
mtod(mnew, void*), MCLBYTES, NULL,
BUS_DMA_READ | BUS_DMA_NOWAIT);
- if (error != 0) {
+ if (error != 0) {
m_freem(mnew);
/* try to reload old mbuf */
error = bus_dmamap_load(sc->sc_dmat, data->rd_map,
@@ -1125,10 +1202,15 @@ dwc_gmac_rx_intr(struct dwc_gmac_softc *
m->m_pkthdr.rcvif = ifp;
m->m_flags |= M_HASFCS;
- bpf_mtap(ifp, m);
ifp->if_ipackets++;
+
+ mutex_exit(&sc->sc_rxq.r_mtx);
+
+ bpf_mtap(ifp, m);
if_percpuq_enqueue(ifp->if_percpuq, m);
+ mutex_enter(&sc->sc_rxq.r_mtx);
+
skip:
bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
data->rd_map->dm_mapsize, BUS_DMASYNC_PREREAD);
@@ -1144,6 +1226,7 @@ skip:
/* update RX pointer */
sc->sc_rxq.r_cur = i;
+ mutex_exit(&sc->sc_rxq.r_mtx);
}
/*
@@ -1168,9 +1251,9 @@ dwc_gmac_setmulti(struct dwc_gmac_softc
struct ether_multistep step;
uint32_t hashes[2] = { 0, 0 };
uint32_t ffilt, h;
- int mcnt, s;
+ int mcnt;
- s = splnet();
+ KASSERT(mutex_owned(sc->sc_lock));
ffilt = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT);
@@ -1216,8 +1299,6 @@ dwc_gmac_setmulti(struct dwc_gmac_softc
hashes[1]);
sc->sc_if_flags = sc->sc_ec.ec_if.if_flags;
- splx(s);
-
#ifdef DWC_GMAC_DEBUG
dwc_gmac_dump_ffilt(sc, ffilt);
#endif
@@ -1235,7 +1316,6 @@ special_filter:
bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH,
0xffffffff);
sc->sc_if_flags = sc->sc_ec.ec_if.if_flags;
- splx(s);
}
int
@@ -1244,6 +1324,9 @@ dwc_gmac_intr(struct dwc_gmac_softc *sc)
uint32_t status, dma_status;
int rv = 0;
+ if (sc->sc_stopping)
+ return 0;
+
status = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_INTR);
if (status & AWIN_GMAC_MII_IRQ) {
(void)bus_space_read_4(sc->sc_bst, sc->sc_bsh,
Index: src/sys/dev/ic/dwc_gmac_var.h
diff -u src/sys/dev/ic/dwc_gmac_var.h:1.6 src/sys/dev/ic/dwc_gmac_var.h:1.6.2.1
--- src/sys/dev/ic/dwc_gmac_var.h:1.6 Sat Nov 22 18:31:03 2014
+++ src/sys/dev/ic/dwc_gmac_var.h Sun Jun 12 07:18:52 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac_var.h,v 1.6 2014/11/22 18:31:03 jmcneill Exp $ */
+/* $NetBSD: dwc_gmac_var.h,v 1.6.2.1 2016/06/12 07:18:52 skrll Exp $ */
/*-
* Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
@@ -64,6 +64,7 @@ struct dwc_gmac_tx_ring {
struct dwc_gmac_dev_dmadesc *t_desc; /* VA of TX ring start */
struct dwc_gmac_tx_data t_data[AWGE_TX_RING_COUNT];
int t_cur, t_next, t_queued;
+ kmutex_t t_mtx;
};
struct dwc_gmac_rx_ring {
@@ -88,6 +89,11 @@ struct dwc_gmac_softc {
struct dwc_gmac_tx_ring sc_txq;
short sc_if_flags; /* shadow of ether flags */
uint16_t sc_mii_clk;
+ bool sc_stopping;
+
+ kmutex_t *sc_lock; /* lock for softc operations */
+
+ struct if_percpuq *sc_ipq; /* softint-based input queues */
};
void dwc_gmac_attach(struct dwc_gmac_softc*, uint32_t /*mii_clk*/);