summaryrefslogtreecommitdiff
path: root/sys/arch/sparc64
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-12-14 20:01:12 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-12-14 20:01:12 +0000
commit9ae7398d6607159c031a809acdc8aa174f39cf3a (patch)
tree6629779ca1510c4cb20e6b593aaf057113afe77f /sys/arch/sparc64
parentd10d7838359de90a58fce12620122b6a54802957 (diff)
Make sure interrupts are disabled when we don't have queues configured. This
prevents interrupt storms I'm hitting when running OpenBSD as a control domain.
Diffstat (limited to 'sys/arch/sparc64')
-rw-r--r--sys/arch/sparc64/dev/vnet.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/sys/arch/sparc64/dev/vnet.c b/sys/arch/sparc64/dev/vnet.c
index c7cac05fbf9..9c803369225 100644
--- a/sys/arch/sparc64/dev/vnet.c
+++ b/sys/arch/sparc64/dev/vnet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vnet.c,v 1.17 2009/08/09 11:40:58 deraadt Exp $ */
+/* $OpenBSD: vnet.c,v 1.18 2009/12/14 20:01:11 kettenis Exp $ */
/*
* Copyright (c) 2009 Mark Kettenis
*
@@ -125,6 +125,8 @@ struct vnet_softc {
bus_space_tag_t sc_bustag;
bus_dma_tag_t sc_dmatag;
+ uint64_t sc_tx_sysino;
+ uint64_t sc_rx_sysino;
void *sc_tx_ih;
void *sc_rx_ih;
@@ -231,7 +233,6 @@ vnet_attach(struct device *parent, struct device *self, void *aux)
struct cbus_attach_args *ca = aux;
struct ldc_conn *lc;
struct ifnet *ifp;
- uint64_t sysino[2];
sc->sc_bustag = ca->ca_bustag;
sc->sc_dmatag = ca->ca_dmatag;
@@ -240,12 +241,12 @@ vnet_attach(struct device *parent, struct device *self, void *aux)
ETHER_ADDR_LEN) <= 0)
myetheraddr(sc->sc_ac.ac_enaddr);
- if (cbus_intr_map(ca->ca_node, ca->ca_tx_ino, &sysino[0]) ||
- cbus_intr_map(ca->ca_node, ca->ca_rx_ino, &sysino[1])) {
+ if (cbus_intr_map(ca->ca_node, ca->ca_tx_ino, &sc->sc_tx_sysino) ||
+ cbus_intr_map(ca->ca_node, ca->ca_rx_ino, &sc->sc_rx_sysino)) {
printf(": can't map interrupt\n");
return;
}
- printf(": ivec 0x%lx, 0x%lx", sysino[0], sysino[1]);
+ printf(": ivec 0x%lx, 0x%lx", sc->sc_tx_sysino, sc->sc_tx_sysino);
/*
* Un-configure queues before registering interrupt handlers,
@@ -254,15 +255,23 @@ vnet_attach(struct device *parent, struct device *self, void *aux)
hv_ldc_tx_qconf(ca->ca_id, 0, 0);
hv_ldc_rx_qconf(ca->ca_id, 0, 0);
- sc->sc_tx_ih = bus_intr_establish(ca->ca_bustag, sysino[0], IPL_NET,
- 0, vnet_tx_intr, sc, sc->sc_dv.dv_xname);
- sc->sc_rx_ih = bus_intr_establish(ca->ca_bustag, sysino[1], IPL_NET,
- 0, vnet_rx_intr, sc, sc->sc_dv.dv_xname);
+ sc->sc_tx_ih = bus_intr_establish(ca->ca_bustag, sc->sc_tx_sysino,
+ IPL_NET, 0, vnet_tx_intr, sc, sc->sc_dv.dv_xname);
+ sc->sc_rx_ih = bus_intr_establish(ca->ca_bustag, sc->sc_rx_sysino,
+ IPL_NET, 0, vnet_rx_intr, sc, sc->sc_dv.dv_xname);
if (sc->sc_tx_ih == NULL || sc->sc_rx_ih == NULL) {
printf(", can't establish interrupt\n");
return;
}
+ /*
+ * Disable interrupts while we have no queues allocated.
+ * Otherwise we may end up with an interrupt storm as soon as
+ * our peer places a packet in their transmit queue.
+ */
+ cbus_intr_setenabled(sc->sc_tx_sysino, INTR_DISABLED);
+ cbus_intr_setenabled(sc->sc_rx_sysino, INTR_DISABLED);
+
lc = &sc->sc_lc;
lc->lc_id = ca->ca_id;
lc->lc_sc = sc;
@@ -1174,6 +1183,9 @@ vnet_init(struct ifnet *ifp)
if (err != H_EOK)
printf("hv_ldc_rx_qconf %d\n", err);
+ cbus_intr_setenabled(sc->sc_tx_sysino, INTR_ENABLED);
+ cbus_intr_setenabled(sc->sc_rx_sysino, INTR_ENABLED);
+
ldc_send_vers(lc);
ifp->if_flags |= IFF_RUNNING;
@@ -1188,6 +1200,9 @@ vnet_stop(struct ifnet *ifp)
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+ cbus_intr_setenabled(sc->sc_tx_sysino, INTR_DISABLED);
+ cbus_intr_setenabled(sc->sc_rx_sysino, INTR_DISABLED);
+
hv_ldc_tx_qconf(lc->lc_id, 0, 0);
hv_ldc_rx_qconf(lc->lc_id, 0, 0);
lc->lc_tx_state = lc->lc_rx_state = LDC_CHANNEL_DOWN;