summaryrefslogtreecommitdiffstats
path: root/sys/dev/en
diff options
context:
space:
mode:
authorharti <harti@FreeBSD.org>2003-08-05 13:39:36 +0000
committerharti <harti@FreeBSD.org>2003-08-05 13:39:36 +0000
commit22492bf3763e945fb1f4396d2a49500724e707aa (patch)
tree6f531966414e9f7281085aee69a2a451d5b5e8e2 /sys/dev/en
parent6750c552fbd053be3a5d71013df548cb5a4796c7 (diff)
downloadFreeBSD-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.c1
-rw-r--r--sys/dev/en/midway.c119
-rw-r--r--sys/dev/en/midwayvar.h3
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;
OpenPOWER on IntegriCloud