diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2013-08-28 10:19:20 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2013-08-28 10:19:20 +0000 |
commit | 49ddd37de470ab2606c1d32aa5ed2cc3e1d11fd3 (patch) | |
tree | b878179f9dc4b94ec636bb15fd9dedb2c8085fc3 /sys/dev/pci | |
parent | cf6631bf64eaa81a326cf4d7941b6d2d15243c38 (diff) |
vmx(4) uses 4 different types of 128bit descriptors in little-endian
format for Rx and Tx. Replace the bit fields in the descriptor
structs with 32bit words to access them with traditional bit
operations using shifts and masks. We try to avoid bit fields in
OpenBSD. For consistence with other drivers, this change also uses
letoh32/htole32 endianess conversions even if it is very unlikely that
vmx will ever run on a big-endian VM/host.
discussed with uebayasi@ and deraadt@
Diffstat (limited to 'sys/dev/pci')
-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 |