Index: if_msk.c =================================================================== RCS file: /cvsroot/src/sys/dev/pci/if_msk.c,v retrieving revision 1.76 diff -p -u -r1.76 if_msk.c --- if_msk.c 23 Aug 2018 11:53:15 -0000 1.76 +++ if_msk.c 10 Sep 2018 09:10:45 -0000 @@ -134,12 +134,14 @@ void msk_tick(void *); static void msk_fill_rx_tick(void *); /* #define MSK_DEBUG 1 */ +#define MSK_DEBUG 0 #ifdef MSK_DEBUG #define DPRINTF(x) if (mskdebug) printf x #define DPRINTFN(n,x) if (mskdebug >= (n)) printf x int mskdebug = MSK_DEBUG; void msk_dump_txdesc(struct msk_tx_desc *, int); +void msk_dump_rxdesc(struct msk_rx_desc *, int); void msk_dump_mbuf(struct mbuf *); void msk_dump_bytes(const char *, int); #else @@ -150,6 +152,9 @@ void msk_dump_bytes(const char *, int); static int msk_sysctl_handler(SYSCTLFN_PROTO); static int msk_root_num; +#define MSK_ADDR_LO(x) ((uint64_t) (x) & 0xffffffffUL) +#define MSK_ADDR_HI(x) ((uint64_t) (x) >> 32) + /* supported device vendors */ static const struct msk_product { pci_vendor_id_t msk_vendor; @@ -409,6 +414,7 @@ msk_init_rx_ring(struct sk_if_softc *sc_ { struct msk_chain_data *cd = &sc_if->sk_cdata; struct msk_ring_data *rd = sc_if->sk_rdata; + struct msk_rx_desc *r; int i, nexti; memset(rd->sk_rx_ring, 0, sizeof(struct msk_rx_desc) * MSK_RX_RING_CNT); @@ -422,9 +428,16 @@ msk_init_rx_ring(struct sk_if_softc *sc_ cd->sk_rx_chain[i].sk_next = &cd->sk_rx_chain[nexti]; } - sc_if->sk_cdata.sk_rx_prod = 0; + /* Mark the first ring element to clear the high address. */ + r = &rd->sk_rx_ring[0]; + r->sk_addr = htole32(0); + r->sk_opcode = SK_Y2_RXOPC_OWN | SK_Y2_ADDR64; + r->sk_len = r->sk_ctl = 0; + + sc_if->sk_cdata.sk_rx_prod = 1; sc_if->sk_cdata.sk_rx_cons = 0; - sc_if->sk_cdata.sk_rx_cnt = 0; + sc_if->sk_cdata.sk_rx_cnt = 1; + sc_if->sk_cdata.sk_rx_hiaddr = 0; msk_fill_rx_ring(sc_if); return (0); @@ -436,6 +449,7 @@ msk_init_tx_ring(struct sk_if_softc *sc_ struct sk_softc *sc = sc_if->sk_softc; struct msk_chain_data *cd = &sc_if->sk_cdata; struct msk_ring_data *rd = sc_if->sk_rdata; + struct msk_tx_desc *t; bus_dmamap_t dmamap; struct sk_txmap_entry *entry; int i, nexti; @@ -464,9 +478,15 @@ msk_init_tx_ring(struct sk_if_softc *sc_ SIMPLEQ_INSERT_HEAD(&sc_if->sk_txmap_head, entry, link); } - sc_if->sk_cdata.sk_tx_prod = 0; + /* Mark the first ring element to clear the high address. */ + t = &rd->sk_tx_ring[0]; + t->sk_addr = htole32(0); + t->sk_opcode = SK_Y2_TXOPC_OWN | SK_Y2_ADDR64; + + sc_if->sk_cdata.sk_tx_prod = 1; sc_if->sk_cdata.sk_tx_cons = 0; sc_if->sk_cdata.sk_tx_cnt = 0; + sc_if->sk_cdata.sk_tx_hiaddr = 0; MSK_CDTXSYNC(sc_if, 0, MSK_TX_RING_CNT, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); @@ -480,7 +500,12 @@ msk_newbuf(struct sk_if_softc *sc_if, bu struct mbuf *m_new = NULL; struct sk_chain *c; struct msk_rx_desc *r; - void *buf = NULL; + void *buf = NULL; + bus_addr_t addr; + unsigned hiaddr; +#ifdef MSK_DEBUG + unsigned prod = sc_if->sk_cdata.sk_rx_prod; +#endif MGETHDR(m_new, M_DONTWAIT, MT_DATA); if (m_new == NULL) @@ -501,12 +526,35 @@ msk_newbuf(struct sk_if_softc *sc_if, bu m_adj(m_new, ETHER_ALIGN); + addr = dmamap->dm_segs[0].ds_addr + + ((vaddr_t)m_new->m_data - + (vaddr_t)sc_if->sk_cdata.sk_jumbo_buf); + + hiaddr = MSK_ADDR_HI(addr); + if (1 || sc_if->sk_cdata.sk_rx_hiaddr != hiaddr) { + 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(hiaddr); + r->sk_len = 0; + r->sk_ctl = 0; + r->sk_opcode = SK_Y2_ADDR64 | SK_Y2_RXOPC_OWN; + sc_if->sk_cdata.sk_rx_hiaddr = hiaddr; + + 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++; + + DPRINTFN(3, ("%s: highaddr %#x (low %#x)\n", __func__, + hiaddr, (unsigned)MSK_ADDR_LO(addr))); + } + c = &sc_if->sk_cdata.sk_rx_chain[sc_if->sk_cdata.sk_rx_prod]; r = c->sk_le; c->sk_mbuf = m_new; - r->sk_addr = htole32(dmamap->dm_segs[0].ds_addr + - (((vaddr_t)m_new->m_data - - (vaddr_t)sc_if->sk_cdata.sk_jumbo_buf))); + r->sk_addr = htole32(MSK_ADDR_LO(addr)); r->sk_len = htole16(SK_JLEN); r->sk_ctl = 0; r->sk_opcode = SK_Y2_RXOPC_PACKET | SK_Y2_RXOPC_OWN; @@ -517,6 +565,24 @@ msk_newbuf(struct sk_if_softc *sc_if, bu SK_INC(sc_if->sk_cdata.sk_rx_prod, MSK_RX_RING_CNT); sc_if->sk_cdata.sk_rx_cnt++; +#ifdef MSK_DEBUG + if (mskdebug >= 2) { + struct msk_rx_desc *le; + u_int32_t idx; + static int first = 0; + + for (idx = prod; + idx != sc_if->sk_cdata.sk_rx_prod; + SK_INC(idx, MSK_TX_RING_CNT)) { + le = &sc_if->sk_rdata->sk_rx_ring[idx]; + if (mskdebug >= 3 || prod < 8 || (first && idx == prod)) + msk_dump_rxdesc(le, idx); + } + if (idx == 511) + first = 0; + } +#endif + return (0); } @@ -702,7 +768,7 @@ msk_ioctl(struct ifnet *ifp, u_long cmd, s = splnet(); - DPRINTFN(2, ("msk_ioctl ETHER\n")); + DPRINTFN(2, ("msk_ioctl ETHER cmd %lx\n", cmd)); switch (cmd) { case SIOCSIFFLAGS: if ((error = ifioctl_common(ifp, cmd, data)) != 0) @@ -973,9 +1039,9 @@ mskc_reset(struct sk_softc *sc) sk_win_write_2(sc, SK_STAT_BMU_LIDX, MSK_STATUS_RING_CNT - 1); sk_win_write_4(sc, SK_STAT_BMU_ADDRLO, - sc->sk_status_map->dm_segs[0].ds_addr); + MSK_ADDR_LO(sc->sk_status_map->dm_segs[0].ds_addr)); sk_win_write_4(sc, SK_STAT_BMU_ADDRHI, - (u_int64_t)sc->sk_status_map->dm_segs[0].ds_addr >> 32); + MSK_ADDR_HI(sc->sk_status_map->dm_segs[0].ds_addr)); if (sc->sk_type == SK_YUKON_EC && sc->sk_rev == SK_YUKON_EC_REV_A1) { /* WA for dev. #4.3 */ @@ -1101,12 +1167,19 @@ msk_attach(device_t parent, device_t sel * give the receiver 2/3 of the memory (rounded down), and the * transmitter whatever remains. */ - chunk = (2 * (sc->sk_ramsize / sizeof(u_int64_t)) / 3) & ~0xff; - sc_if->sk_rx_ramstart = 0; - sc_if->sk_rx_ramend = sc_if->sk_rx_ramstart + chunk - 1; - chunk = (sc->sk_ramsize / sizeof(u_int64_t)) - chunk; - sc_if->sk_tx_ramstart = sc_if->sk_rx_ramend + 1; - sc_if->sk_tx_ramend = sc_if->sk_tx_ramstart + chunk - 1; + if (sc->sk_ramsize) { + chunk = (2 * (sc->sk_ramsize / sizeof(u_int64_t)) / 3) & ~0xff; + sc_if->sk_rx_ramstart = 0; + sc_if->sk_rx_ramend = sc_if->sk_rx_ramstart + chunk - 1; + chunk = (sc->sk_ramsize / sizeof(u_int64_t)) - chunk; + sc_if->sk_tx_ramstart = sc_if->sk_rx_ramend + 1; + sc_if->sk_tx_ramend = sc_if->sk_tx_ramstart + chunk - 1; + } else { + sc_if->sk_rx_ramstart = 0; + sc_if->sk_rx_ramend = 0; + sc_if->sk_tx_ramstart = 0; + sc_if->sk_tx_ramend = 0; + } DPRINTFN(2, ("msk_attach: rx_ramstart=%#x rx_ramend=%#x\n" " tx_ramstart=%#x tx_ramend=%#x\n", @@ -1361,7 +1434,10 @@ mskc_attach(device_t parent, device_t se return; } - sc->sc_dmatag = pa->pa_dmat; + if (pci_dma64_available(pa)) + sc->sc_dmatag = pa->pa_dmat64; + else + sc->sc_dmatag = pa->pa_dmat; command = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); command |= PCI_COMMAND_MASTER_ENABLE; @@ -1386,6 +1462,7 @@ mskc_attach(device_t parent, device_t se intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); sc->sk_intrhand = pci_intr_establish_xname(pc, ih, IPL_NET, msk_intr, sc, device_xname(sc->sk_dev)); + if (sc->sk_intrhand == NULL) { aprint_error(": couldn't establish interrupt"); if (intrstr != NULL) @@ -1689,6 +1766,7 @@ mskc_detach(device_t self, int flags) if (sc->sk_intrhand) pci_intr_disestablish(sc->sk_pc, sc->sk_intrhand); + sc->sk_intrhand = NULL; rv = config_detach_children(self, flags); if (rv != 0) @@ -1713,10 +1791,12 @@ msk_encap(struct sk_if_softc *sc_if, str { struct sk_softc *sc = sc_if->sk_softc; struct msk_tx_desc *f = NULL; - u_int32_t frag, cur; - int i; + u_int32_t frag, cur, hiaddr, total; + u_int32_t entries = 0; + size_t i; struct sk_txmap_entry *entry; bus_dmamap_t txmap; + bus_addr_t addr; DPRINTFN(2, ("msk_encap\n")); @@ -1745,21 +1825,51 @@ msk_encap(struct sk_if_softc *sc_if, str return (ENOBUFS); } - if (txmap->dm_nsegs > (MSK_TX_RING_CNT - sc_if->sk_cdata.sk_tx_cnt - 2)) { + /* Count how many tx descriptors needed. */ + hiaddr = sc_if->sk_cdata.sk_tx_hiaddr; + for (total = i = 0; i < txmap->dm_nsegs; i++) { + if (hiaddr != MSK_ADDR_HI(txmap->dm_segs[i].ds_addr)) { + hiaddr = MSK_ADDR_HI(txmap->dm_segs[i].ds_addr); + total++; + } + total++; + } + + if (total > 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); } - DPRINTFN(2, ("msk_encap: dm_nsegs=%d\n", txmap->dm_nsegs)); + DPRINTFN(2, ("msk_encap: dm_nsegs=%d total desc=%u\n", + txmap->dm_nsegs, total)); /* Sync the DMA map. */ bus_dmamap_sync(sc->sc_dmatag, txmap, 0, txmap->dm_mapsize, BUS_DMASYNC_PREWRITE); for (i = 0; i < txmap->dm_nsegs; i++) { + addr = txmap->dm_segs[i].ds_addr; + DPRINTFN(2, ("msk_encap: addr %llx\n", + (unsigned long long)addr)); + hiaddr = MSK_ADDR_HI(addr); + + if (sc_if->sk_cdata.sk_tx_hiaddr != hiaddr) { + f = &sc_if->sk_rdata->sk_tx_ring[frag]; + f->sk_addr = htole32(hiaddr); + f->sk_len = 0; + f->sk_ctl = 0; + f->sk_opcode = SK_Y2_ADDR64; + if (i != 0) + f->sk_opcode |= SK_Y2_TXOPC_OWN; + sc_if->sk_cdata.sk_tx_hiaddr = hiaddr; + SK_INC(frag, MSK_TX_RING_CNT); + entries++; + DPRINTFN(2, ("msk_encap: highaddr %#x\n", hiaddr)); + } + f = &sc_if->sk_rdata->sk_tx_ring[frag]; - f->sk_addr = htole32(txmap->dm_segs[i].ds_addr); + f->sk_addr = htole32(MSK_ADDR_LO(addr)); f->sk_len = htole16(txmap->dm_segs[i].ds_len); f->sk_ctl = 0; if (i == 0) @@ -1768,7 +1878,9 @@ msk_encap(struct sk_if_softc *sc_if, str f->sk_opcode = SK_Y2_TXOPC_BUFFER | SK_Y2_TXOPC_OWN; cur = frag; SK_INC(frag, MSK_TX_RING_CNT); + entries++; } + KASSERTMSG(entries == total, "entries %u total %u", entries, total); sc_if->sk_cdata.sk_tx_chain[cur].sk_mbuf = m_head; SIMPLEQ_REMOVE_HEAD(&sc_if->sk_txmap_head, link); @@ -1777,19 +1889,25 @@ msk_encap(struct sk_if_softc *sc_if, str 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; + if (sc_if->sk_rdata->sk_tx_ring[*txidx].sk_opcode & SK_Y2_ADDR64) { + u_int32_t first = *txidx; + + SK_INC(first, MSK_TX_RING_CNT); + sc_if->sk_rdata->sk_tx_ring[first].sk_opcode |= SK_Y2_TXOPC_OWN; + } - /* Sync first descriptor to hand it off */ + /* Sync first descriptor(s) to hand it off */ 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) { + if (mskdebug >= 3) { struct msk_tx_desc *le; u_int32_t idx; for (idx = *txidx; idx != frag; SK_INC(idx, MSK_TX_RING_CNT)) { @@ -1801,7 +1919,7 @@ msk_encap(struct sk_if_softc *sc_if, str *txidx = frag; - DPRINTFN(2, ("msk_encap: completed successfully\n")); + DPRINTFN(2, ("msk_encap: successful: %u entries\n", entries)); return (0); } @@ -1919,33 +2037,53 @@ void msk_rxeof(struct sk_if_softc *sc_if, u_int16_t len, u_int32_t rxstat) { struct sk_softc *sc = sc_if->sk_softc; + struct msk_ring_data *rd = sc_if->sk_rdata; struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; struct mbuf *m; - struct sk_chain *cur_rx; - int cur, total_len = len; + unsigned cur, prod, tail, total_len = len; bus_dmamap_t dmamap; - DPRINTFN(2, ("msk_rxeof\n")); - cur = sc_if->sk_cdata.sk_rx_cons; + prod = sc_if->sk_cdata.sk_rx_prod; - /* Sync the descriptor */ - MSK_CDRXSYNC(sc_if, cur, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + DPRINTFN(2, ("msk_rxeof: cur %u prod %u rx_cnt %u\n", cur, prod, sc_if->sk_cdata.sk_rx_cnt)); - cur_rx = &sc_if->sk_cdata.sk_rx_chain[cur]; - if (cur_rx->sk_mbuf == NULL) + while (prod != cur) { + tail = cur; + SK_INC(cur, MSK_RX_RING_CNT); + + sc_if->sk_cdata.sk_rx_cnt--; + m = sc_if->sk_cdata.sk_rx_chain[tail].sk_mbuf; + sc_if->sk_cdata.sk_rx_chain[tail].sk_mbuf = NULL; + if (m != NULL) + break; /* found it */ + } + sc_if->sk_cdata.sk_rx_cons = cur; + DPRINTFN(2, ("msk_rxeof: cur %u rx_cnt %u m %p\n", cur, sc_if->sk_cdata.sk_rx_cnt, m)); + + if (m == NULL) return; + /* Sync the descriptor */ + //MSK_CDRXSYNC(sc_if, tail, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + +#ifdef MSK_DEBUG + if (mskdebug >= 2) { + unsigned pcur = (cur - 1) % MSK_RX_RING_CNT; + unsigned ncur = cur; + + SK_INC(ncur, MSK_RX_RING_CNT); + msk_dump_rxdesc(&rd->sk_rx_ring[pcur], pcur); + msk_dump_rxdesc(&rd->sk_rx_ring[cur], cur); + msk_dump_rxdesc(&rd->sk_rx_ring[ncur], ncur); + } +#endif + dmamap = sc_if->sk_cdata.sk_rx_jumbo_map; - SK_INC(sc_if->sk_cdata.sk_rx_cons, MSK_RX_RING_CNT); - sc_if->sk_cdata.sk_rx_cnt--; bus_dmamap_sync(sc_if->sk_softc->sc_dmatag, dmamap, 0, dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); - m = cur_rx->sk_mbuf; - cur_rx->sk_mbuf = NULL; - if (total_len < SK_MIN_FRAMELEN || total_len > ETHER_MAX_LEN_JUMBO || msk_rxvalid(sc, rxstat, total_len) == 0) { @@ -1967,7 +2105,7 @@ msk_txeof(struct sk_if_softc *sc_if) struct sk_softc *sc = sc_if->sk_softc; struct msk_tx_desc *cur_tx; struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; - u_int32_t idx, reg, sk_ctl; + u_int32_t idx, prod, reg, sk_ctl; struct sk_txmap_entry *entry; DPRINTFN(2, ("msk_txeof\n")); @@ -1982,6 +2120,11 @@ msk_txeof(struct sk_if_softc *sc_if) * frames that have been sent. */ idx = sc_if->sk_cdata.sk_tx_cons; + prod = sk_win_read_2(sc, reg); + + if (idx == prod) + return; + while (idx != sk_win_read_2(sc, reg)) { MSK_CDTXSYNC(sc_if, idx, 1, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); @@ -2134,6 +2277,7 @@ msk_intr(void *xsc) cur_st->sk_opcode &= ~SK_Y2_STOPC_OWN; switch (cur_st->sk_opcode) { case SK_Y2_STOPC_RXSTAT: +DPRINTFN(2, ("%s: len=%#x status=%#x\n", __func__, letoh16(cur_st->sk_len), letoh32(cur_st->sk_status))); sc_if = sc->sk_if[cur_st->sk_link & 0x01]; msk_rxeof(sc_if, letoh16(cur_st->sk_len), letoh32(cur_st->sk_status)); @@ -2560,6 +2704,21 @@ msk_dump_txdesc(struct msk_tx_desc *le, } void +msk_dump_rxdesc(struct msk_rx_desc *le, int idx) +{ +#define DESC_PRINT(X) \ + if (X) \ + printf("rxdesc[%d]." #X "=%#x\n", \ + idx, X); + + DESC_PRINT(letoh32(le->sk_addr)); + DESC_PRINT(letoh16(le->sk_len)); + DESC_PRINT(le->sk_ctl); + DESC_PRINT(le->sk_opcode); +#undef DESC_PRINT +} + +void msk_dump_bytes(const char *data, int len) { int c, i, j; @@ -2601,7 +2760,8 @@ msk_dump_mbuf(struct mbuf *m) while (count > 0 && m) { printf("m=%p, m->m_data=%p, m->m_len=%d\n", m, m->m_data, m->m_len); - msk_dump_bytes(mtod(m, char *), m->m_len); + if (mskdebug >= 3) + msk_dump_bytes(mtod(m, char *), m->m_len); count -= m->m_len; m = m->m_next; Index: if_mskvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/pci/if_mskvar.h,v retrieving revision 1.18 diff -p -u -r1.18 if_mskvar.h --- if_mskvar.h 10 Jul 2018 18:42:37 -0000 1.18 +++ if_mskvar.h 10 Sep 2018 09:10:45 -0000 @@ -114,12 +114,14 @@ struct msk_chain_data { struct sk_txmap_entry *sk_tx_map[MSK_TX_RING_CNT]; bus_dmamap_t sk_rx_map[MSK_RX_RING_CNT]; bus_dmamap_t sk_rx_jumbo_map; - int sk_tx_prod; - int sk_tx_cons; - int sk_tx_cnt; - int sk_rx_prod; - int sk_rx_cons; - int sk_rx_cnt; + unsigned sk_tx_prod; + unsigned sk_tx_cons; + unsigned sk_tx_cnt; + u_int32_t sk_tx_hiaddr; + unsigned sk_rx_prod; + unsigned sk_rx_cons; + unsigned sk_rx_cnt; + u_int32_t sk_rx_hiaddr; /* Stick the jumbo mem management stuff here too. */ void * sk_jslots[MSK_JSLOTS]; void *sk_jumbo_buf; @@ -195,7 +197,6 @@ struct sk_softc { u_int8_t sk_fibertype; u_int8_t sk_type; u_int8_t sk_rev; - u_int32_t sk_workaround; u_int8_t sk_macs; /* # of MACs */ const char *sk_name; u_int32_t sk_ramsize; /* amount of RAM on NIC */