diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-11-24 14:18:22 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-11-24 14:18:22 +0000 |
commit | 6ef1778ae44a1c584fffb4f07604262b2596f010 (patch) | |
tree | db1ab4fee466a2353983047668dd87b70a68a617 /sys | |
parent | cb43f1ab6533ceee44191260f6ed9d47b19cf001 (diff) |
msk_newbuf() had an off by one when putting the packet onto the cluster
and cleared the mbuf pointer of the next element, causing a mbuf leak.
While there also ensure that the valid bit of the first buffer is only set
when the full chain got assembled.
Tested by jmc@, ok kettenis@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/if_msk.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/sys/dev/pci/if_msk.c b/sys/dev/pci/if_msk.c index 44e0af57b5d..b61bfe13cff 100644 --- a/sys/dev/pci/if_msk.c +++ b/sys/dev/pci/if_msk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_msk.c,v 1.79 2009/10/15 17:54:56 deraadt Exp $ */ +/* $OpenBSD: if_msk.c,v 1.80 2009/11/24 14:18:21 claudio Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -501,7 +501,7 @@ msk_newbuf(struct sk_if_softc *sc_if) struct mbuf *m; bus_dmamap_t dmamap; int error; - int opcode, i; + int i, head; m = MCLGETI(NULL, M_DONTWAIT, &sc_if->arpcom.ac_if, sc_if->sk_pktlen); if (!m) @@ -528,26 +528,38 @@ msk_newbuf(struct sk_if_softc *sc_if) dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); c = &sc_if->sk_cdata.sk_rx_chain[sc_if->sk_cdata.sk_rx_prod]; + head = sc_if->sk_cdata.sk_rx_prod; r = c->sk_le; c->sk_mbuf = m; - opcode = SK_Y2_RXOPC_PACKET; - for (i = 0; i < dmamap->dm_nsegs; i++) { + r->sk_addr = htole32(dmamap->dm_segs[0].ds_addr); + r->sk_len = htole16(dmamap->dm_segs[0].ds_len); + r->sk_ctl = 0; + + SK_INC(sc_if->sk_cdata.sk_rx_prod, MSK_RX_RING_CNT); + sc_if->sk_cdata.sk_rx_cnt++; + + for (i = 1; i < dmamap->dm_nsegs; i++) { + c = &sc_if->sk_cdata.sk_rx_chain[sc_if->sk_cdata.sk_rx_prod]; + r = c->sk_le; + c->sk_mbuf = NULL; + r->sk_addr = htole32(dmamap->dm_segs[i].ds_addr); r->sk_len = htole16(dmamap->dm_segs[i].ds_len); r->sk_ctl = 0; - r->sk_opcode = opcode | SK_Y2_RXOPC_OWN; - opcode = SK_Y2_RXOPC_BUFFER; + r->sk_opcode = SK_Y2_RXOPC_BUFFER | SK_Y2_RXOPC_OWN; + MSK_CDRXSYNC(sc_if, sc_if->sk_cdata.sk_rx_prod, + BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); SK_INC(sc_if->sk_cdata.sk_rx_prod, MSK_RX_RING_CNT); sc_if->sk_cdata.sk_rx_cnt++; - - c = &sc_if->sk_cdata.sk_rx_chain[sc_if->sk_cdata.sk_rx_prod]; - r = c->sk_le; - c->sk_mbuf = NULL; } - MSK_CDRXSYNC(sc_if, i, BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); + c = &sc_if->sk_cdata.sk_rx_chain[head]; + r = c->sk_le; + r->sk_opcode = SK_Y2_RXOPC_PACKET | SK_Y2_RXOPC_OWN; + + MSK_CDRXSYNC(sc_if, head, BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); return (0); } |