summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-01-07 21:12:36 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-01-07 21:12:36 +0000
commitbc6003da3f34e9f1662e6941edeca975ece693d1 (patch)
tree43837ce524517d19103ac0ee524c68e319519c6c
parent025e0ce35f4f429c2a7285b5e69ba9973a4807ab (diff)
Set IFF_OACTIVE when we run out of resources transmitting packets.
-rw-r--r--sys/arch/sparc64/dev/vnet.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/sys/arch/sparc64/dev/vnet.c b/sys/arch/sparc64/dev/vnet.c
index 67138317c30..5c2fc28d2c8 100644
--- a/sys/arch/sparc64/dev/vnet.c
+++ b/sys/arch/sparc64/dev/vnet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vnet.c,v 1.3 2009/01/06 22:49:46 kettenis Exp $ */
+/* $OpenBSD: vnet.c,v 1.4 2009/01/07 21:12:35 kettenis Exp $ */
/*
* Copyright (c) 2009 Mark Kettenis
*
@@ -99,11 +99,6 @@ struct ldc_queue {
int lq_nentries;
};
-struct ldc_chan {
- struct ldc_queue lc_txq;
- struct ldc_queue lc_rxq;
-};
-
struct ldc_cookie {
uint64_t addr;
uint64_t size;
@@ -309,11 +304,10 @@ struct vnet_softc {
uint64_t sc_dring_ident;
uint64_t sc_seq_no;
+ int sc_tx_cnt;
int sc_tx_prod;
int sc_tx_cons;
- int sc_state;
-
struct ldc_map *sc_lm;
struct vnet_dring *sc_vd;
struct vnet_soft_desc *sc_vsd;
@@ -517,7 +511,7 @@ vnet_rx_intr(void *arg)
}
if (rx_state != sc->sc_rx_state) {
- sc->sc_tx_prod = sc->sc_tx_cons = 0;
+ sc->sc_tx_cnt = sc->sc_tx_prod = sc->sc_tx_cons = 0;
sc->sc_tx_seqid = 0;
sc->sc_ldc_state = 0;
ifp->if_flags &= ~IFF_RUNNING;
@@ -1030,8 +1024,14 @@ vnet_rx_vio_dring_data(struct vnet_softc *sc, struct vio_msg_tag *tag)
sc->sc_vd->vd_desc[cons++].hdr.dstate = VIO_DESC_FREE;
cons &= (sc->sc_vd->vd_nentries - 1);
+ sc->sc_tx_cnt--;
}
sc->sc_tx_cons = cons;
+
+ if (sc->sc_tx_cnt < sc->sc_vd->vd_nentries)
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ vnet_start(ifp);
break;
}
@@ -1302,8 +1302,8 @@ void
vnet_start(struct ifnet *ifp)
{
struct vnet_softc *sc = ifp->if_softc;
+ struct ldc_map *map = sc->sc_lm;
struct vnet_dring_msg dm;
- struct ldc_map *map;
struct mbuf *m;
paddr_t pa;
caddr_t buf;
@@ -1328,9 +1328,17 @@ vnet_start(struct ifnet *ifp)
if (m == NULL)
break;
+ if (sc->sc_tx_cnt >= sc->sc_vd->vd_nentries ||
+ map->lm_count >= map->lm_nentries) {
+ ifp->if_flags |= IFF_OACTIVE;
+ break;
+ }
+
buf = pool_get(&sc->sc_pool, PR_NOWAIT|PR_ZERO);
- if (buf == NULL)
+ if (buf == NULL) {
+ ifp->if_flags |= IFF_OACTIVE;
break;
+ }
m_copydata(m, 0, m->m_pkthdr.len, buf + VNET_ETHER_ALIGN);
IFQ_DEQUEUE(&ifp->if_snd, m);
@@ -1343,11 +1351,8 @@ vnet_start(struct ifnet *ifp)
bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
#endif
- map = sc->sc_lm;
pmap_extract(pmap_kernel(), (vaddr_t)buf, &pa);
KASSERT((pa & ~PAGE_MASK) == (pa & LDC_MTE_RA_MASK));
- if (map->lm_count == map->lm_nentries)
- panic("out of LDC map entries\n");
while (map->lm_slot[map->lm_next].entry != 0) {
map->lm_next++;
map->lm_next &= (map->lm_nentries - 1);
@@ -1372,6 +1377,7 @@ vnet_start(struct ifnet *ifp)
desc++;
desc &= (sc->sc_vd->vd_nentries - 1);
+ sc->sc_tx_cnt++;
m_freem(m);
}
@@ -1512,6 +1518,7 @@ vnet_init(struct ifnet *ifp)
ldc_send_vers(sc);
ifp->if_flags |= IFF_RUNNING;
+ ifp->if_flags &= ~IFF_OACTIVE;
}
void
@@ -1519,7 +1526,7 @@ vnet_stop(struct ifnet *ifp)
{
struct vnet_softc *sc = ifp->if_softc;
- ifp->if_flags &= ~IFF_RUNNING;
+ ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
hv_ldc_tx_qconf(sc->sc_id, 0, 0);
hv_ldc_rx_qconf(sc->sc_id, 0, 0);