summaryrefslogtreecommitdiffstats
path: root/sys/dev/fatm/if_fatm.c
diff options
context:
space:
mode:
authorharti <harti@FreeBSD.org>2003-08-07 10:40:24 +0000
committerharti <harti@FreeBSD.org>2003-08-07 10:40:24 +0000
commit136c4125667d7ca587662848cea09e5a072b12e5 (patch)
tree1de73697bb5e021a064c2387aa7ac8f357305226 /sys/dev/fatm/if_fatm.c
parentcbe12b7936a6603cc9a631363f3470d81a08e05c (diff)
downloadFreeBSD-src-136c4125667d7ca587662848cea09e5a072b12e5.zip
FreeBSD-src-136c4125667d7ca587662848cea09e5a072b12e5.tar.gz
When configuring the interface down and up again try to re-open all
connections that have been open (and were not closing) when the interface was stopped. This makes the behaviour of fatm(4) more like the behaviour of en(4).
Diffstat (limited to 'sys/dev/fatm/if_fatm.c')
-rw-r--r--sys/dev/fatm/if_fatm.c109
1 files changed, 76 insertions, 33 deletions
diff --git a/sys/dev/fatm/if_fatm.c b/sys/dev/fatm/if_fatm.c
index db8f8d1..f21ee97 100644
--- a/sys/dev/fatm/if_fatm.c
+++ b/sys/dev/fatm/if_fatm.c
@@ -113,6 +113,8 @@ static const struct utopia_methods fatm_utopia_methods = {
(((VPI) & ~((1 << (SC)->ifatm.mib.vpi_bits) - 1)) == 0 && \
(VCI) != 0 && ((VCI) & ~((1 << (SC)->ifatm.mib.vci_bits) - 1)) == 0)
+static int fatm_load_vc(struct fatm_softc *sc, struct card_vcc *vc);
+
/*
* Probing is easy: step trough the list of known vendor and device
* ids and compare. If one is found - it's our.
@@ -449,7 +451,7 @@ fatm_reset(struct fatm_softc *sc)
/*
* Stop the card. Must be called WITH the lock held
- * Reset, free transmit and receive buffers. Wakeup everybody that may sleep.
+ * Reset, free transmit and receive buffers. Wakeup everybody who may sleep.
*/
static void
fatm_stop(struct fatm_softc *sc)
@@ -522,14 +524,21 @@ fatm_stop(struct fatm_softc *sc)
/* Reset vcc info */
if (sc->vccs != NULL) {
- for (i = 0; i < FORE_MAX_VCC + 1; i++)
+ sc->open_vccs = 0;
+ for (i = 0; i < FORE_MAX_VCC + 1; i++) {
if (sc->vccs[i] != NULL) {
- uma_zfree(sc->vcc_zone, sc->vccs[i]);
- sc->vccs[i] = NULL;
+ if ((sc->vccs[i]->vflags & (FATM_VCC_OPEN |
+ FATM_VCC_TRY_OPEN)) == 0) {
+ uma_zfree(sc->vcc_zone, sc->vccs[i]);
+ sc->vccs[i] = NULL;
+ } else {
+ sc->vccs[i]->vflags = 0;
+ sc->open_vccs++;
+ }
}
+ }
}
- sc->open_vccs = 0;
}
/*
@@ -1242,7 +1251,7 @@ static void
fatm_init_locked(struct fatm_softc *sc)
{
struct rxqueue *q;
- int i, c;
+ int i, c, error;
uint32_t start;
DBG(sc, INIT, ("initialize"));
@@ -1335,6 +1344,18 @@ fatm_init_locked(struct fatm_softc *sc)
ATMEV_SEND_IFSTATE_CHANGED(&sc->ifatm,
sc->utopia.carrier == UTP_CARR_OK);
+ /* start all channels */
+ for (i = 0; i < FORE_MAX_VCC + 1; i++)
+ if (sc->vccs[i] != NULL) {
+ sc->vccs[i]->vflags |= FATM_VCC_REOPEN;
+ error = fatm_load_vc(sc, sc->vccs[i]);
+ if (error != 0) {
+ if_printf(&sc->ifatm.ifnet, "reopening %u "
+ "failed: %d\n", i, error);
+ sc->vccs[i]->vflags &= ~FATM_VCC_REOPEN;
+ }
+ }
+
DBG(sc, INIT, ("done"));
}
@@ -2144,6 +2165,11 @@ fatm_open_finish(struct fatm_softc *sc, struct card_vcc *vc)
vc->vflags &= ~FATM_VCC_TRY_OPEN;
vc->vflags |= FATM_VCC_OPEN;
+ if (vc->vflags & FATM_VCC_REOPEN) {
+ vc->vflags &= ~FATM_VCC_REOPEN;
+ return;
+ }
+
/* inform management if this is not an NG
* VCC or it's an NG PVC. */
if (!(vc->param.flags & ATMIO_FLAG_NG) ||
@@ -2197,9 +2223,7 @@ fatm_waitvcc(struct fatm_softc *sc, struct cmdqueue *q)
static int
fatm_open_vcc(struct fatm_softc *sc, struct atmio_openvcc *op)
{
- uint32_t cmd;
int error;
- struct cmdqueue *q;
struct card_vcc *vc;
/*
@@ -2248,38 +2272,19 @@ fatm_open_vcc(struct fatm_softc *sc, struct atmio_openvcc *op)
default:
error = EINVAL;
goto done;
- return (EINVAL);
}
vc->ibytes = vc->obytes = 0;
vc->ipackets = vc->opackets = 0;
- /* Command and buffer strategy */
- cmd = FATM_OP_ACTIVATE_VCIN | FATM_OP_INTERRUPT_SEL | (0 << 16);
- if (op->param.aal == ATMIO_AAL_0)
- cmd |= (0 << 8);
- else
- cmd |= (5 << 8);
-
- q = fatm_start_vcc(sc, op->param.vpi, op->param.vci, cmd, 1,
- (op->param.flags & ATMIO_FLAG_ASYNC) ?
- fatm_open_complete : fatm_cmd_complete);
- if (q == NULL) {
- error = EIO;
- goto done;
- }
-
vc->vflags = FATM_VCC_TRY_OPEN;
sc->vccs[op->param.vci] = vc;
sc->open_vccs++;
- if (!(op->param.flags & ATMIO_FLAG_ASYNC)) {
- error = fatm_waitvcc(sc, q);
- if (error != 0) {
- sc->vccs[op->param.vci] = NULL;
- sc->open_vccs--;
- goto done;
- }
- fatm_open_finish(sc, vc);
+ error = fatm_load_vc(sc, vc);
+ if (error != NULL) {
+ sc->vccs[op->param.vci] = NULL;
+ sc->open_vccs--;
+ goto done;
}
/* don't free below */
@@ -2293,6 +2298,38 @@ fatm_open_vcc(struct fatm_softc *sc, struct atmio_openvcc *op)
}
/*
+ * Try to initialize the given VC
+ */
+static int
+fatm_load_vc(struct fatm_softc *sc, struct card_vcc *vc)
+{
+ uint32_t cmd;
+ struct cmdqueue *q;
+ int error;
+
+ /* Command and buffer strategy */
+ cmd = FATM_OP_ACTIVATE_VCIN | FATM_OP_INTERRUPT_SEL | (0 << 16);
+ if (vc->param.aal == ATMIO_AAL_0)
+ cmd |= (0 << 8);
+ else
+ cmd |= (5 << 8);
+
+ q = fatm_start_vcc(sc, vc->param.vpi, vc->param.vci, cmd, 1,
+ (vc->param.flags & ATMIO_FLAG_ASYNC) ?
+ fatm_open_complete : fatm_cmd_complete);
+ if (q == NULL)
+ return (EIO);
+
+ if (!(vc->param.flags & ATMIO_FLAG_ASYNC)) {
+ error = fatm_waitvcc(sc, q);
+ if (error != 0)
+ return (error);
+ fatm_open_finish(sc, vc);
+ }
+ return (0);
+}
+
+/*
* Finish close
*/
static void
@@ -2523,8 +2560,14 @@ fatm_detach(device_t dev)
if (sc->rbufs != NULL)
free(sc->rbufs, M_DEVBUF);
- if (sc->vccs != NULL)
+ if (sc->vccs != NULL) {
+ for (i = 0; i < FORE_MAX_VCC + 1; i++)
+ if (sc->vccs[i] != NULL) {
+ uma_zfree(sc->vcc_zone, sc->vccs[i]);
+ sc->vccs[i] = NULL;
+ }
free(sc->vccs, M_DEVBUF);
+ }
if (sc->vcc_zone != NULL)
uma_zdestroy(sc->vcc_zone);
OpenPOWER on IntegriCloud