diff options
-rw-r--r-- | sys/dev/pci/if_vmx.c | 90 | ||||
-rw-r--r-- | sys/dev/pci/if_vmxreg.h | 159 |
2 files changed, 148 insertions, 101 deletions
diff --git a/sys/dev/pci/if_vmx.c b/sys/dev/pci/if_vmx.c index 24f0ef75494..24d6997877b 100644 --- a/sys/dev/pci/if_vmx.c +++ b/sys/dev/pci/if_vmx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vmx.c,v 1.11 2013/06/22 00:28:10 uebayasi Exp $ */ +/* $OpenBSD: if_vmx.c,v 1.12 2013/08/28 10:19:19 reyk Exp $ */ /* * Copyright (c) 2013 Tsubai Masanari @@ -645,7 +645,9 @@ vmxnet3_txintr(struct vmxnet3_softc *sc, struct vmxnet3_txqueue *tq) for (;;) { txcd = &comp_ring->txcd[comp_ring->next]; - if (txcd->gen != comp_ring->gen) + + if (letoh32((txcd->txc_word3 >> VMXNET3_TXC_GEN_S) & + VMXNET3_TXC_GEN_M) != comp_ring->gen) break; comp_ring->next++; @@ -660,7 +662,9 @@ vmxnet3_txintr(struct vmxnet3_softc *sc, struct vmxnet3_txqueue *tq) m_freem(ring->m[sop]); ring->m[sop] = NULL; bus_dmamap_unload(sc->sc_dmat, ring->dmap[sop]); - ring->next = (txcd->eop_idx + 1) % NTXDESC; + ring->next = (letoh32((txcd->txc_word0 >> + VMXNET3_TXC_EOPIDX_S) & VMXNET3_TXC_EOPIDX_M) + 1) + % NTXDESC; ifp->if_flags &= ~IFF_OACTIVE; } @@ -682,7 +686,8 @@ vmxnet3_rxintr(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq) for (;;) { rxcd = &comp_ring->rxcd[comp_ring->next]; - if (rxcd->gen != comp_ring->gen) + if (letoh32((rxcd->rxc_word3 >> VMXNET3_RXC_GEN_S) & + VMXNET3_RXC_GEN_M) != comp_ring->gen) break; comp_ring->next++; @@ -691,13 +696,16 @@ vmxnet3_rxintr(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq) comp_ring->gen ^= 1; } - idx = rxcd->rxd_idx; - if (rxcd->qid < NRXQUEUE) + idx = letoh32((rxcd->rxc_word0 >> VMXNET3_RXC_IDX_S) & + VMXNET3_RXC_IDX_M); + if (letoh32((rxcd->rxc_word0 >> VMXNET3_RXC_QID_S) & + VMXNET3_RXC_QID_M) < NRXQUEUE) ring = &rq->cmd_ring[0]; else ring = &rq->cmd_ring[1]; rxd = &ring->rxd[idx]; - len = rxcd->len; + len = letoh32((rxcd->rxc_word2 >> VMXNET3_RXC_LEN_S) & + VMXNET3_RXC_LEN_M); m = ring->m[idx]; ring->m[idx] = NULL; bus_dmamap_unload(sc->sc_dmat, ring->dmap[idx]); @@ -705,11 +713,12 @@ vmxnet3_rxintr(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq) if (m == NULL) panic("NULL mbuf"); - if (rxd->btype != VMXNET3_BTYPE_HEAD) { + if (letoh32((rxd->rx_word2 >> VMXNET3_RX_BTYPE_S) & + VMXNET3_RX_BTYPE_M) != VMXNET3_BTYPE_HEAD) { m_freem(m); goto skip_buffer; } - if (rxcd->error) { + if (letoh32(rxcd->rxc_word2 & VMXNET3_RXC_ERROR)) { ifp->if_ierrors++; m_freem(m); goto skip_buffer; @@ -726,9 +735,10 @@ vmxnet3_rxintr(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq) vmxnet3_rx_csum(rxcd, m); m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = len; - if (rxcd->vlan) { + if (letoh32(rxcd->rxc_word2 & VMXNET3_RXC_VLAN)) { m->m_flags |= M_VLANTAG; - m->m_pkthdr.ether_vtag = rxcd->vtag; + m->m_pkthdr.ether_vtag = letoh32((rxcd->rxc_word2 >> + VMXNET3_RXC_VLANTAG_S) & VMXNET3_RXC_VLANTAG_M); } #if NBPFILTER > 0 @@ -742,7 +752,8 @@ skip_buffer: vmxstat.rxdone = idx; #endif if (rq->rs->update_rxhead) { - u_int qid = rxcd->qid; + u_int qid = letoh32((rxcd->rxc_word0 >> + VMXNET3_RXC_QID_S) & VMXNET3_RXC_QID_M); idx = (idx + 1) % NRXDESC; if (qid < NRXQUEUE) { @@ -811,23 +822,24 @@ vmxnet3_iff(struct vmxnet3_softc *sc) void vmxnet3_rx_csum(struct vmxnet3_rxcompdesc *rxcd, struct mbuf *m) { - if (rxcd->no_csum) + if (letoh32(rxcd->rxc_word0 & VMXNET3_RXC_NOCSUM)) return; - if (rxcd->ipv4 && rxcd->ipcsum_ok) + if ((rxcd->rxc_word3 & (VMXNET3_RXC_IPV4|VMXNET3_RXC_IPSUM_OK)) == + (VMXNET3_RXC_IPV4|VMXNET3_RXC_IPSUM_OK)) m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; - if (rxcd->fragment) + if (rxcd->rxc_word3 & VMXNET3_RXC_FRAGMENT) return; - if (rxcd->tcp) { - if (rxcd->csum_ok) + if (rxcd->rxc_word3 & VMXNET3_RXC_TCP) { + if (rxcd->rxc_word3 & VMXNET3_RXC_CSUM_OK) m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK; else m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_BAD; } - if (rxcd->udp) { - if (rxcd->csum_ok) + if (rxcd->rxc_word3 & VMXNET3_RXC_UDP) { + if (rxcd->rxc_word3 & VMXNET3_RXC_CSUM_OK) m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK; else m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_BAD; @@ -873,10 +885,11 @@ vmxnet3_getbuf(struct vmxnet3_softc *sc, struct vmxnet3_rxring *ring) if (bus_dmamap_load_mbuf(sc->sc_dmat, ring->dmap[idx], m, BUS_DMA_NOWAIT)) panic("load mbuf"); - rxd->addr = DMAADDR(ring->dmap[idx]); - rxd->btype = btype; - rxd->len = m->m_pkthdr.len; - rxd->gen = ring->gen; + rxd->rx_addr = htole64(DMAADDR(ring->dmap[idx])); + rxd->rx_word2 = htole32(((m->m_pkthdr.len & VMXNET3_RX_LEN_M) << + VMXNET3_RX_LEN_S) | ((btype & VMXNET3_RX_BTYPE_M) << + VMXNET3_RX_BTYPE_S) | ((ring->gen & VMXNET3_RX_GEN_M) << + VMXNET3_RX_GEN_S)); idx++; if (idx == NRXDESC) { idx = 0; @@ -1118,14 +1131,11 @@ vmxnet3_load_mbuf(struct vmxnet3_softc *sc, struct mbuf *m) gen = ring->gen ^ 1; /* owned by cpu (yet) */ for (i = 0; i < map->dm_nsegs; i++) { txd = &ring->txd[ring->head]; - txd->addr = map->dm_segs[i].ds_addr; - txd->len = map->dm_segs[i].ds_len; - txd->gen = gen; - txd->dtype = 0; - txd->offload_mode = VMXNET3_OM_NONE; - txd->offload_pos = txd->hlen = 0; - txd->eop = txd->compreq = 0; - txd->vtag_mode = txd->vtag = 0; + txd->tx_addr = htole64(map->dm_segs[i].ds_addr); + txd->tx_word2 = htole32(((map->dm_segs[i].ds_len & + VMXNET3_TX_LEN_M) << VMXNET3_TX_LEN_S) | + ((gen & VMXNET3_TX_GEN_M) << VMXNET3_TX_GEN_S)); + txd->tx_word3 = 0; ring->head++; if (ring->head == NTXDESC) { ring->head = 0; @@ -1133,20 +1143,22 @@ vmxnet3_load_mbuf(struct vmxnet3_softc *sc, struct mbuf *m) } gen = ring->gen; } - txd->eop = txd->compreq = 1; + txd->tx_word3 |= htole32(VMXNET3_TX_EOP | VMXNET3_TX_COMPREQ); if (m->m_flags & M_VLANTAG) { - sop->vtag_mode = 1; - sop->vtag = m->m_pkthdr.ether_vtag; + sop->tx_word3 |= htole32(VMXNET3_TX_VTAG_MODE); + sop->tx_word3 |= htole32((m->m_pkthdr.ether_vtag & + VMXNET3_TX_VLANTAG_M) << VMXNET3_TX_VLANTAG_S); } if (m->m_pkthdr.csum_flags & (M_TCP_CSUM_OUT|M_UDP_CSUM_OUT)) { - sop->offload_mode = VMXNET3_OM_CSUM; - sop->hlen = hlen; - sop->offload_pos = hlen + csum_off; + sop->tx_word2 |= htole32(((hlen + csum_off) & + VMXNET3_TX_OP_M) << VMXNET3_TX_OP_S); + sop->tx_word3 |= htole32(((hlen & VMXNET3_TX_HLEN_M) << + VMXNET3_TX_HLEN_S) | (VMXNET3_OM_CSUM << VMXNET3_TX_OM_S)); } - /* Change the ownership. */ - sop->gen ^= 1; + /* Change the ownership by flipping the "generation" bit */ + sop->tx_word2 ^= htole32(VMXNET3_TX_GEN_M << VMXNET3_TX_GEN_S); return (0); } diff --git a/sys/dev/pci/if_vmxreg.h b/sys/dev/pci/if_vmxreg.h index efb4d65a9d0..7f47851964e 100644 --- a/sys/dev/pci/if_vmxreg.h +++ b/sys/dev/pci/if_vmxreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vmxreg.h,v 1.2 2013/06/12 01:07:33 uebayasi Exp $ */ +/* $OpenBSD: if_vmxreg.h,v 1.3 2013/08/28 10:19:19 reyk Exp $ */ /* * Copyright (c) 2013 Tsubai Masanari @@ -79,23 +79,33 @@ struct UPT1_RxStats { #define VMXNET3_DMADESC_ALIGN 128 +/* All descriptors are in little-endian format. */ struct vmxnet3_txdesc { - u_int64_t addr; - - u_int len:14; - u_int gen:1; /* generation */ - u_int :1; - u_int dtype:1; /* descriptor type */ - u_int :1; - u_int offload_pos:14; /* offloading position */ - - u_int hlen:10; /* header len */ - u_int offload_mode:2; /* offloading mode */ - u_int eop:1; /* end of packet */ - u_int compreq:1; /* completion request */ - u_int :1; - u_int vtag_mode:1; /* VLAN tag insertion mode */ - u_int vtag:16; /* VLAN tag */ + u_int64_t tx_addr; + + u_int32_t tx_word2; +#define VMXNET3_TX_LEN_M 0x00003fff +#define VMXNET3_TX_LEN_S 0 +#define VMXNET3_TX_GEN_M 0x00000001 /* generation */ +#define VMXNET3_TX_GEN_S 14 +#define VMXNET3_TX_RES0 0x00008000 +#define VMXNET3_TX_DTYPE_M 0x00000001 /* descriptor type */ +#define VMXNET3_TX_DTYPE_S 16 /* descriptor type */ +#define VMXNET3_TX_RES1 0x00000002 +#define VMXNET3_TX_OP_M 0x00003fff /* offloading position */ +#define VMXNET3_TX_OP_S 18 + + u_int32_t tx_word3; +#define VMXNET3_TX_HLEN_M 0x000003ff /* header len */ +#define VMXNET3_TX_HLEN_S 0 +#define VMXNET3_TX_OM_M 0x00000003 /* offloading mode */ +#define VMXNET3_TX_OM_S 10 +#define VMXNET3_TX_EOP 0x00001000 /* end of packet */ +#define VMXNET3_TX_COMPREQ 0x00002000 /* completion request */ +#define VMXNET3_TX_RES2 0x00004000 +#define VMXNET3_TX_VTAG_MODE 0x00008000 /* VLAN tag insertion mode */ +#define VMXNET3_TX_VLANTAG_M 0x0000ffff +#define VMXNET3_TX_VLANTAG_S 16 } __packed; /* offloading modes */ @@ -104,27 +114,39 @@ struct vmxnet3_txdesc { #define VMXNET3_OM_TSO 3 struct vmxnet3_txcompdesc { - u_int eop_idx:12; /* eop index in Tx ring */ - u_int :20; - - u_int :32; - u_int :32; - - u_int :24; - u_int type:7; - u_int gen:1; + u_int32_t txc_word0; +#define VMXNET3_TXC_EOPIDX_M 0x00000fff /* eop index in Tx ring */ +#define VMXNET3_TXC_EOPIDX_S 0 +#define VMXNET3_TXC_RES0_M 0x000fffff +#define VMXNET3_TXC_RES0_S 12 + + u_int32_t txc_word1; + u_int32_t txc_word2; + + u_int32_t txc_word3; +#define VMXNET3_TXC_RES2_M 0x00ffffff +#define VMXNET3_TXC_TYPE_M 0x0000007f +#define VMXNET3_TXC_TYPE_S 24 +#define VMXNET3_TXC_GEN_M 0x00000001 +#define VMXNET3_TXC_GEN_S 31 } __packed; struct vmxnet3_rxdesc { - u_int64_t addr; - - u_int len:14; - u_int btype:1; /* buffer type */ - u_int dtype:1; /* descriptor type */ - u_int :15; - u_int gen:1; - - u_int :32; + u_int64_t rx_addr; + + u_int32_t rx_word2; +#define VMXNET3_RX_LEN_M 0x00003fff +#define VMXNET3_RX_LEN_S 0 +#define VMXNET3_RX_BTYPE_M 0x00000001 /* buffer type */ +#define VMXNET3_RX_BTYPE_S 14 +#define VMXNET3_RX_DTYPE_M 0x00000001 /* descriptor type */ +#define VMXNET3_RX_DTYPE_S 15 +#define VMXNET3_RX_RES0_M 0x00007fff +#define VMXNET3_RX_RES0_S 16 +#define VMXNET3_RX_GEN_M 0x00000001 +#define VMXNET3_RX_GEN_S 31 + + u_int32_t rx_word3; } __packed; /* buffer types */ @@ -132,33 +154,46 @@ struct vmxnet3_rxdesc { #define VMXNET3_BTYPE_BODY 1 /* body only */ struct vmxnet3_rxcompdesc { - u_int rxd_idx:12; /* Rx descriptor index */ - u_int :2; - u_int eop:1; /* end of packet */ - u_int sop:1; /* start of packet */ - u_int qid:10; - u_int rss_type:4; - u_int no_csum:1; /* no checksum calculated */ - u_int :1; - - u_int rss_hash:32; /* RSS hash value */ - - u_int len:14; - u_int error:1; - u_int vlan:1; /* 802.1Q VLAN frame */ - u_int vtag:16; /* VLAN tag */ - - u_int csum:16; - u_int csum_ok:1; /* TCP/UDP checksum ok */ - u_int udp:1; - u_int tcp:1; - u_int ipcsum_ok:1; /* IP checksum ok */ - u_int ipv6:1; - u_int ipv4:1; - u_int fragment:1; /* IP fragment */ - u_int fcs:1; /* frame CRC correct */ - u_int type:7; - u_int gen:1; + u_int32_t rxc_word0; +#define VMXNET3_RXC_IDX_M 0x00000fff /* Rx descriptor index */ +#define VMXNET3_RXC_IDX_S 0 +#define VMXNET3_RXC_RES0_M 0x00000003 +#define VMXNET3_RXC_RES0_S 12 +#define VMXNET3_RXC_EOP 0x00004000 /* end of packet */ +#define VMXNET3_RXC_SOP 0x00008000 /* start of packet */ +#define VMXNET3_RXC_QID_M 0x000003ff +#define VMXNET3_RXC_QID_S 16 +#define VMXNET3_RXC_RSSTYPE_M 0x0000000f +#define VMXNET3_RXC_RSSTYPE_S 26 +#define VMXNET3_RXC_NOCSUM 0x40000000 /* no checksum calculated */ +#define VMXNET3_RXC_RES1 0x80000000 + + u_int32_t rxc_word1; +#define VMXNET3_RXC_RSSHASH_M 0xffffffff /* RSS hash value */ +#define VMXNET3_RXC_RSSHASH_S 0 + + u_int32_t rxc_word2; +#define VMXNET3_RXC_LEN_M 0x00003fff +#define VMXNET3_RXC_LEN_S 0 +#define VMXNET3_RXC_ERROR 0x00004000 +#define VMXNET3_RXC_VLAN 0x00008000 /* 802.1Q VLAN frame */ +#define VMXNET3_RXC_VLANTAG_M 0x0000ffff /* VLAN tag */ +#define VMXNET3_RXC_VLANTAG_S 16 + + u_int32_t rxc_word3; +#define VMXNET3_RXC_CSUM_M 0x0000ffff /* TCP/UDP checksum */ +#define VMXNET3_RXC_CSUM_S 16 +#define VMXNET3_RXC_CSUM_OK 0x00010000 /* TCP/UDP checksum ok */ +#define VMXNET3_RXC_UDP 0x00020000 +#define VMXNET3_RXC_TCP 0x00040000 +#define VMXNET3_RXC_IPSUM_OK 0x00080000 /* IP checksum ok */ +#define VMXNET3_RXC_IPV6 0x00100000 +#define VMXNET3_RXC_IPV4 0x00200000 +#define VMXNET3_RXC_FRAGMENT 0x00400000 /* IP fragment */ +#define VMXNET3_RXC_FCS 0x00800000 /* frame CRC correct */ +#define VMXNET3_RXC_TYPE_M 0x7f000000 +#define VMXNET3_RXC_GEN_M 0x00000001 +#define VMXNET3_RXC_GEN_S 31 } __packed; #define VMXNET3_REV1_MAGIC 0xbabefee1 |