summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJonathan Matthew <jmatthew@cvs.openbsd.org>2017-04-08 03:36:51 +0000
committerJonathan Matthew <jmatthew@cvs.openbsd.org>2017-04-08 03:36:51 +0000
commit0ba1d214704ecb9cdb9ac079bf77030ca7e09169 (patch)
tree832997868ec17474151eac9253541cde758edfca /sys/dev
parente8e5dabe424f56e49b17b8b477f9b845fc3c5e6c (diff)
Use ADDR64 opcodes to specify 64bit DMA addresses for all buffers. This
consumes two ring entries per segment, halving the effective size of the rings, but keeps things simple. This is required for the onboard nic on the Overdrive 1000 to work. ok kettenis@, tested on i386 by jsg@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_msk.c79
-rw-r--r--sys/dev/pci/if_skreg.h4
2 files changed, 68 insertions, 15 deletions
diff --git a/sys/dev/pci/if_msk.c b/sys/dev/pci/if_msk.c
index caca0ceb95c..7d2f4c549d4 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.125 2017/01/22 10:17:38 dlg Exp $ */
+/* $OpenBSD: if_msk.c,v 1.126 2017/04/08 03:36:50 jmatthew Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000
@@ -425,7 +425,8 @@ msk_init_rx_ring(struct sk_if_softc *sc_if)
sc_if->sk_cdata.sk_rx_prod = 0;
sc_if->sk_cdata.sk_rx_cons = 0;
- if_rxr_init(&sc_if->sk_cdata.sk_rx_ring, 2, MSK_RX_RING_CNT);
+ /* two ring entries per packet, so the effective ring size is halved */
+ if_rxr_init(&sc_if->sk_cdata.sk_rx_ring, 2, MSK_RX_RING_CNT/2);
msk_fill_rx_ring(sc_if);
return (0);
@@ -485,6 +486,7 @@ msk_newbuf(struct sk_if_softc *sc_if)
bus_dmamap_t dmamap;
int error;
int i, head;
+ uint64_t addr;
m = MCLGETI(NULL, M_DONTWAIT, NULL, sc_if->sk_pktlen);
if (m == NULL)
@@ -509,11 +511,27 @@ msk_newbuf(struct sk_if_softc *sc_if)
r = c->sk_le;
c->sk_mbuf = m;
- r->sk_addr = htole32(dmamap->dm_segs[0].ds_addr);
+ /* high 32 bits of address */
+ addr = dmamap->dm_segs[0].ds_addr;
+ r->sk_addr = htole32(addr >> 32);
+ MSK_CDRXSYNC(sc_if, sc_if->sk_cdata.sk_rx_prod,
+ BUS_DMASYNC_PREWRITE);
+
+ SK_INC(sc_if->sk_cdata.sk_rx_prod, MSK_RX_RING_CNT);
+ c = &sc_if->sk_cdata.sk_rx_chain[sc_if->sk_cdata.sk_rx_prod];
+ r = c->sk_le;
+
+ /* low 32 bits of address + length */
+ r->sk_addr = htole32(addr & 0xffffffff);
r->sk_len = htole16(dmamap->dm_segs[0].ds_len);
r->sk_ctl = 0;
+ MSK_CDRXSYNC(sc_if, sc_if->sk_cdata.sk_rx_prod,
+ BUS_DMASYNC_PREWRITE);
- MSK_CDRXSYNC(sc_if, head, BUS_DMASYNC_PREWRITE);
+ r->sk_opcode = SK_Y2_RXOPC_PACKET | 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);
@@ -522,7 +540,24 @@ msk_newbuf(struct sk_if_softc *sc_if)
r = c->sk_le;
c->sk_mbuf = NULL;
- r->sk_addr = htole32(dmamap->dm_segs[i].ds_addr);
+ /* high 32 bits of address */
+ addr = dmamap->dm_segs[i].ds_addr;
+ r->sk_addr = htole32(addr >> 32);
+ MSK_CDRXSYNC(sc_if, sc_if->sk_cdata.sk_rx_prod,
+ BUS_DMASYNC_PREWRITE);
+
+ r->sk_opcode = SK_Y2_RXOPC_ADDR64 | 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);
+ c = &sc_if->sk_cdata.sk_rx_chain[sc_if->sk_cdata.sk_rx_prod];
+ c->sk_mbuf = NULL;
+ r = c->sk_le;
+
+ /* low 32 bits of address + length */
+ r->sk_addr = htole32(addr & 0xffffffff);
r->sk_len = htole16(dmamap->dm_segs[i].ds_len);
r->sk_ctl = 0;
@@ -539,7 +574,7 @@ msk_newbuf(struct sk_if_softc *sc_if)
c = &sc_if->sk_cdata.sk_rx_chain[head];
r = c->sk_le;
- r->sk_opcode = SK_Y2_RXOPC_PACKET | SK_Y2_RXOPC_OWN;
+ r->sk_opcode = SK_Y2_RXOPC_ADDR64 | SK_Y2_RXOPC_OWN;
MSK_CDRXSYNC(sc_if, head, BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
@@ -1436,11 +1471,12 @@ int
msk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx)
{
struct sk_softc *sc = sc_if->sk_softc;
- struct msk_tx_desc *f = NULL;
+ struct msk_tx_desc *f = NULL;
u_int32_t frag, cur;
- int i;
+ int i, entries;
struct sk_txmap_entry *entry;
bus_dmamap_t txmap;
+ uint64_t addr;
DPRINTFN(2, ("msk_encap\n"));
@@ -1469,7 +1505,8 @@ msk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx)
return (ENOBUFS);
}
- if (txmap->dm_nsegs > (MSK_TX_RING_CNT - sc_if->sk_cdata.sk_tx_cnt - 2)) {
+ entries = txmap->dm_nsegs * 2;
+ if (entries > (MSK_TX_RING_CNT - sc_if->sk_cdata.sk_tx_cnt - 2)) {
DPRINTFN(2, ("msk_encap: too few descriptors free\n"));
bus_dmamap_unload(sc->sc_dmatag, txmap);
return (ENOBUFS);
@@ -1482,12 +1519,24 @@ msk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx)
BUS_DMASYNC_PREWRITE);
for (i = 0; i < txmap->dm_nsegs; i++) {
+ /* high 32 bits of address */
+ addr = txmap->dm_segs[i].ds_addr;
f = &sc_if->sk_rdata->sk_tx_ring[frag];
- f->sk_addr = htole32(txmap->dm_segs[i].ds_addr);
+ f->sk_addr = htole32(addr >> 32);
+ if (i == 0)
+ f->sk_opcode = SK_Y2_TXOPC_ADDR64;
+ else
+ f->sk_opcode = SK_Y2_TXOPC_ADDR64 | SK_Y2_TXOPC_OWN;
+
+ SK_INC(frag, MSK_TX_RING_CNT);
+
+ /* low 32 bits of address + length */
+ f = &sc_if->sk_rdata->sk_tx_ring[frag];
+ f->sk_addr = htole32(addr & 0xffffffff);
f->sk_len = htole16(txmap->dm_segs[i].ds_len);
f->sk_ctl = 0;
if (i == 0)
- f->sk_opcode = SK_Y2_TXOPC_PACKET;
+ f->sk_opcode = SK_Y2_TXOPC_PACKET | SK_Y2_TXOPC_OWN;
else
f->sk_opcode = SK_Y2_TXOPC_BUFFER | SK_Y2_TXOPC_OWN;
cur = frag;
@@ -1501,7 +1550,7 @@ msk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx)
sc_if->sk_rdata->sk_tx_ring[cur].sk_ctl |= SK_Y2_TXCTL_LASTFRAG;
/* Sync descriptors before handing to chip */
- MSK_CDTXSYNC(sc_if, *txidx, txmap->dm_nsegs,
+ MSK_CDTXSYNC(sc_if, *txidx, entries,
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
sc_if->sk_rdata->sk_tx_ring[*txidx].sk_opcode |= SK_Y2_TXOPC_OWN;
@@ -1510,7 +1559,7 @@ msk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx)
MSK_CDTXSYNC(sc_if, *txidx, 1,
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
- sc_if->sk_cdata.sk_tx_cnt += txmap->dm_nsegs;
+ sc_if->sk_cdata.sk_tx_cnt += entries;
#ifdef MSK_DEBUG
if (mskdebug >= 2) {
@@ -1641,6 +1690,8 @@ msk_rxeof(struct sk_if_softc *sc_if, u_int16_t len, u_int32_t rxstat)
dmamap = sc_if->sk_cdata.sk_rx_map[cur];
for (i = 0; i < dmamap->dm_nsegs; i++) {
+ /* each segment consumes two slots on the ring */
+ SK_INC(sc_if->sk_cdata.sk_rx_cons, MSK_RX_RING_CNT);
SK_INC(sc_if->sk_cdata.sk_rx_cons, MSK_RX_RING_CNT);
}
if_rxr_put(&sc_if->sk_cdata.sk_rx_ring, dmamap->dm_nsegs);
@@ -1727,7 +1778,7 @@ msk_fill_rx_ring(struct sk_if_softc *sc_if)
{
u_int slots, used;
- slots = if_rxr_get(&sc_if->sk_cdata.sk_rx_ring, MSK_RX_RING_CNT);
+ slots = if_rxr_get(&sc_if->sk_cdata.sk_rx_ring, MSK_RX_RING_CNT/2);
while (slots > 0) {
used = msk_newbuf(sc_if);
if (used == 0)
diff --git a/sys/dev/pci/if_skreg.h b/sys/dev/pci/if_skreg.h
index ea7465f03a4..6caa99126a1 100644
--- a/sys/dev/pci/if_skreg.h
+++ b/sys/dev/pci/if_skreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_skreg.h,v 1.60 2014/11/04 07:36:47 brad Exp $ */
+/* $OpenBSD: if_skreg.h,v 1.61 2017/04/08 03:36:50 jmatthew Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000
@@ -1611,6 +1611,7 @@ struct msk_rx_desc {
u_int8_t sk_opcode;
} __packed;
+#define SK_Y2_RXOPC_ADDR64 0x21
#define SK_Y2_RXOPC_BUFFER 0x40
#define SK_Y2_RXOPC_PACKET 0x41
#define SK_Y2_RXOPC_OWN 0x80
@@ -1624,6 +1625,7 @@ struct msk_tx_desc {
#define SK_Y2_TXCTL_LASTFRAG 0x80
+#define SK_Y2_TXOPC_ADDR64 0x21
#define SK_Y2_TXOPC_BUFFER 0x40
#define SK_Y2_TXOPC_PACKET 0x41
#define SK_Y2_TXOPC_OWN 0x80