diff options
author | harti <harti@FreeBSD.org> | 2003-08-05 13:39:36 +0000 |
---|---|---|
committer | harti <harti@FreeBSD.org> | 2003-08-05 13:39:36 +0000 |
commit | 22492bf3763e945fb1f4396d2a49500724e707aa (patch) | |
tree | 6f531966414e9f7281085aee69a2a451d5b5e8e2 /sys/dev/en | |
parent | 6750c552fbd053be3a5d71013df548cb5a4796c7 (diff) | |
download | FreeBSD-src-22492bf3763e945fb1f4396d2a49500724e707aa.zip FreeBSD-src-22492bf3763e945fb1f4396d2a49500724e707aa.tar.gz |
Implement the ATMIOCOPENVCC and ATMIOCCLOSEVCC ioctls(). This was the
last driver that did not know about those.
Diffstat (limited to 'sys/dev/en')
-rw-r--r-- | sys/dev/en/if_en_pci.c | 1 | ||||
-rw-r--r-- | sys/dev/en/midway.c | 119 | ||||
-rw-r--r-- | sys/dev/en/midwayvar.h | 3 |
3 files changed, 86 insertions, 37 deletions
diff --git a/sys/dev/en/if_en_pci.c b/sys/dev/en/if_en_pci.c index 47274c4..7be0804 100644 --- a/sys/dev/en/if_en_pci.c +++ b/sys/dev/en/if_en_pci.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/socket.h> #include <sys/sysctl.h> +#include <sys/condvar.h> #include <sys/bus.h> #include <machine/bus.h> diff --git a/sys/dev/en/midway.c b/sys/dev/en/midway.c index 8693ba9..f9bf95f 100644 --- a/sys/dev/en/midway.c +++ b/sys/dev/en/midway.c @@ -135,6 +135,7 @@ enum { #include <sys/stdint.h> #include <sys/lock.h> #include <sys/mutex.h> +#include <sys/condvar.h> #include <vm/uma.h> #include <net/if.h> @@ -1168,24 +1169,22 @@ en_loadvc(struct en_softc *sc, struct en_vcc *vc) } /* + * Open the given vcc. + * * LOCK: unlocked, needed */ static int -en_open_vcc(struct en_softc *sc, struct atm_pseudoioctl *pi) +en_open_vcc(struct en_softc *sc, struct atmio_openvcc *op) { - u_int vci, flags; uint32_t oldmode, newmode; struct en_rxslot *slot; struct en_vcc *vc; int error = 0; - vci = ATM_PH_VCI(&pi->aph); - flags = ATM_PH_FLAGS(&pi->aph); - DBG(sc, IOCTL, ("enable vpi=%d, vci=%d, flags=%#x", - ATM_PH_VPI(&pi->aph), vci, flags)); + op->param.vpi, op->param.vci, op->param.flags)); - if (ATM_PH_VPI(&pi->aph) || vci >= MID_N_VC) + if (op->param.vpi != 0 || op->param.vci >= MID_N_VC) return (EINVAL); vc = uma_zalloc(en_vcc_zone, M_NOWAIT | M_ZERO); @@ -1194,7 +1193,7 @@ en_open_vcc(struct en_softc *sc, struct atm_pseudoioctl *pi) EN_LOCK(sc); - if (sc->vccs[vci] != NULL) { + if (sc->vccs[op->param.vci] != NULL) { error = EBUSY; goto done; } @@ -1209,13 +1208,11 @@ en_open_vcc(struct en_softc *sc, struct atm_pseudoioctl *pi) } vc->rxslot = slot; - vc->rxhand = pi->rxhand; - vc->vcc.vci = vci; - vc->vcc.traffic = ATMIO_TRAFFIC_UBR; - vc->vcc.flags = flags; + vc->rxhand = op->rxhand; + vc->vcc = op->param; oldmode = slot->mode; - newmode = (flags & ATM_PH_AAL5) ? MIDV_AAL5 : MIDV_NOAAL; + newmode = (op->param.aal == ATMIO_AAL_5) ? MIDV_AAL5 : MIDV_NOAAL; slot->mode = MIDV_SETMODE(oldmode, newmode); slot->vcc = vc; @@ -1230,8 +1227,9 @@ en_open_vcc(struct en_softc *sc, struct atm_pseudoioctl *pi) en_loadvc(sc, vc); /* does debug printf for us */ /* don't free below */ - sc->vccs[vci] = vc; + sc->vccs[vc->vcc.vci] = vc; vc = NULL; + sc->vccs_open++; done: if (vc != NULL) @@ -1253,33 +1251,28 @@ en_close_finish(struct en_softc *sc, struct en_vcc *vc) DBG(sc, VC, ("vci: %u free (%p)", vc->vcc.vci, vc)); - /* XXX wakeup */ sc->vccs[vc->vcc.vci] = NULL; uma_zfree(en_vcc_zone, vc); + sc->vccs_open--; } /* * LOCK: unlocked, needed */ static int -en_close_vcc(struct en_softc *sc, struct atm_pseudoioctl *pi) +en_close_vcc(struct en_softc *sc, struct atmio_closevcc *cl, int wait) { - u_int vci, flags; uint32_t oldmode, newmode; struct en_vcc *vc; int error = 0; - vci = ATM_PH_VCI(&pi->aph); - flags = ATM_PH_FLAGS(&pi->aph); - - DBG(sc, IOCTL, ("disable vpi=%d, vci=%d, flags=%#x", - ATM_PH_VPI(&pi->aph), vci, flags)); + DBG(sc, IOCTL, ("disable vpi=%d, vci=%d", cl->vpi, cl->vci)); - if (ATM_PH_VPI(&pi->aph) || vci >= MID_N_VC) + if (cl->vpi != 0 || cl->vci >= MID_N_VC) return (EINVAL); EN_LOCK(sc); - if ((vc = sc->vccs[vci]) == NULL) { + if ((vc = sc->vccs[cl->vci]) == NULL) { error = ENOTCONN; goto done; } @@ -1296,9 +1289,9 @@ en_close_vcc(struct en_softc *sc, struct atm_pseudoioctl *pi) goto done; } - oldmode = en_read(sc, MID_VC(vci)); + oldmode = en_read(sc, MID_VC(cl->vci)); newmode = MIDV_SETMODE(oldmode, MIDV_TRASH) & ~MIDV_INSERVICE; - en_write(sc, MID_VC(vci), (newmode | (oldmode & MIDV_INSERVICE))); + en_write(sc, MID_VC(cl->vci), (newmode | (oldmode & MIDV_INSERVICE))); /* halt in tracks, be careful to preserve inservice bit */ DELAY(27); @@ -1311,12 +1304,29 @@ en_close_vcc(struct en_softc *sc, struct atm_pseudoioctl *pi) _IF_QLEN(&vc->rxslot->q) == 0 && (vc->vflags & VCC_SWSL) == 0) { en_close_finish(sc, vc); - DBG(sc, IOCTL, ("VCI %u now free", vci)); - } else { - vc->vflags |= VCC_DRAIN; - DBG(sc, IOCTL, ("VCI %u now draining", vci)); + goto done; + } + + vc->vflags |= VCC_DRAIN; + DBG(sc, IOCTL, ("VCI %u now draining", cl->vci)); + + if (!wait) { + vc->vflags |= VCC_ASYNC; + goto done; + } + + vc->vflags |= VCC_CLOSE_RX; + while ((sc->ifatm.ifnet.if_flags & IFF_RUNNING) && + (vc->vflags & VCC_DRAIN)) + cv_wait(&sc->cv_close, &sc->en_mtx); + + en_close_finish(sc, vc); + if (!(sc->ifatm.ifnet.if_flags & IFF_RUNNING)) { + error = EIO; + goto done; } + done: EN_UNLOCK(sc); return (error); @@ -1342,8 +1352,6 @@ en_reset_ul(struct en_softc *sc) int lcv; if_printf(&sc->ifatm.ifnet, "reset\n"); - backtrace(); - sc->ifatm.ifnet.if_flags &= ~IFF_RUNNING; if (sc->en_busreset) @@ -1398,6 +1406,14 @@ en_reset_ul(struct en_softc *sc) } sc->txslot[lcv].mbsize = 0; } + + /* + * Unstop all waiters + */ + while (!cv_waitq_empty(&sc->cv_close)) { + cv_broadcast(&sc->cv_close); + DELAY(100); + } } /* @@ -1528,18 +1544,32 @@ en_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct en_softc *sc = (struct en_softc *)ifp->if_softc; struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *)data; - struct atm_pseudoioctl *api = (struct atm_pseudoioctl *)data; + struct atm_pseudoioctl *pa = (struct atm_pseudoioctl *)data; struct atmio_vcctable *vtab; + struct atmio_openvcc ena; + struct atmio_closevcc dis; int error = 0; switch (cmd) { case SIOCATMENA: /* enable circuit for recv */ - error = en_open_vcc(sc, api); + bzero(&ena, sizeof(ena)); + ena.param.flags = ATM_PH_FLAGS(&pa->aph) & + (ATM_PH_AAL5 | ATM_PH_LLCSNAP); + ena.param.vpi = ATM_PH_VPI(&pa->aph); + ena.param.vci = ATM_PH_VCI(&pa->aph); + ena.param.aal = (ATM_PH_FLAGS(&pa->aph) & ATM_PH_AAL5) ? + ATMIO_AAL_5 : ATMIO_AAL_0; + ena.param.traffic = ATMIO_TRAFFIC_UBR; + ena.rxhand = pa->rxhand; + error = en_open_vcc(sc, &ena); break; case SIOCATMDIS: /* disable circuit for recv */ - error = en_close_vcc(sc, api); + bzero(&dis, sizeof(dis)); + dis.vpi = ATM_PH_VPI(&pa->aph); + dis.vci = ATM_PH_VCI(&pa->aph); + error = en_close_vcc(sc, &dis, 0); break; case SIOCSIFADDR: @@ -1592,6 +1622,14 @@ en_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = ifmedia_ioctl(ifp, ifr, &sc->media, cmd); break; + case SIOCATMOPENVCC: /* netgraph/harp internal use */ + error = en_open_vcc(sc, (struct atmio_openvcc *)data); + break; + + case SIOCATMCLOSEVCC: /* netgraph and HARP internal use */ + error = en_close_vcc(sc, (struct atmio_closevcc *)data, 1); + break; + case SIOCATMGETVCCS: /* internal netgraph use */ vtab = atm_getvccs((struct atmio_vcc **)sc->vccs, MID_N_VC, sc->vccs_open, &sc->en_mtx, 0); @@ -1828,8 +1866,13 @@ en_rx_drain(struct en_softc *sc, u_int drq) m_freem(m); if (_IF_QLEN(&slot->indma) == 0 && _IF_QLEN(&slot->q) == 0 && (en_read(sc, MID_VC(vc->vcc.vci)) & MIDV_INSERVICE) == 0 && - (vc->vflags & VCC_SWSL) == 0) - en_close_finish(sc, vc); + (vc->vflags & VCC_SWSL) == 0) { + vc->vflags &= ~VCC_CLOSE_RX; + if (vc->vflags & VCC_ASYNC) + en_close_finish(sc, vc); + else + cv_signal(&sc->cv_close); + } return; } @@ -2888,6 +2931,7 @@ en_attach(struct en_softc *sc) mtx_init(&sc->en_mtx, device_get_nameunit(sc->dev), MTX_NETWORK_LOCK, MTX_DEF); + cv_init(&sc->cv_close, "VC close"); /* * Make the sysctl tree @@ -3068,6 +3112,7 @@ en_destroy(struct en_softc *sc) (void)sysctl_ctx_free(&sc->sysctl_ctx); + cv_destroy(&sc->cv_close); mtx_destroy(&sc->en_mtx); } diff --git a/sys/dev/en/midwayvar.h b/sys/dev/en/midwayvar.h index f95414c..78ed634 100644 --- a/sys/dev/en/midwayvar.h +++ b/sys/dev/en/midwayvar.h @@ -148,6 +148,8 @@ struct en_vcc { }; #define VCC_DRAIN 0x0001 /* closed, but draining rx */ #define VCC_SWSL 0x0002 /* on rx software service list */ +#define VCC_CLOSE_RX 0x0004 /* currently closing */ +#define VCC_ASYNC 0x0008 /* async close */ /* * softc @@ -195,6 +197,7 @@ struct en_softc { /* vccs */ struct en_vcc **vccs; u_int vccs_open; + struct cv cv_close; /* close CV */ /* stats */ struct en_stats stats; |