summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJonathan Matthew <jmatthew@cvs.openbsd.org>2020-06-02 08:17:16 +0000
committerJonathan Matthew <jmatthew@cvs.openbsd.org>2020-06-02 08:17:16 +0000
commit336161a702d4770a5311111b53e973508dce1fc6 (patch)
tree45bc4f48f3003c58e2ef1ff28ab5472628bba4fa /sys/dev
parente903e923aac74939d38343efe370e519c277b7ed (diff)
Add support for hardware vlan tagging. Tag insertion here is actually
done by the driver, as it places the full L2 packet header inside the send queue entry, so it can insert the vlan tag there if required. ok dlg@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_mcx.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/sys/dev/pci/if_mcx.c b/sys/dev/pci/if_mcx.c
index a06028bafe2..b826c2cd45f 100644
--- a/sys/dev/pci/if_mcx.c
+++ b/sys/dev/pci/if_mcx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_mcx.c,v 1.48 2020/05/27 04:03:20 dlg Exp $ */
+/* $OpenBSD: if_mcx.c,v 1.49 2020/06/02 08:17:15 jmatthew Exp $ */
/*
* Copyright (c) 2017 David Gwynne <dlg@openbsd.org>
@@ -18,6 +18,7 @@
*/
#include "bpfilter.h"
+#include "vlan.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -92,6 +93,7 @@
((1 << MCX_LOG_FLOW_TABLE_SIZE) - MCX_NUM_STATIC_FLOWS)
#define MCX_SQ_INLINE_SIZE 18
+CTASSERT(ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN == MCX_SQ_INLINE_SIZE);
/* doorbell offsets */
#define MCX_CQ_DOORBELL_OFFSET 0
@@ -1258,6 +1260,8 @@ struct mcx_cq_entry {
#define MCX_CQ_ENTRY_FLAGS_L4_OK (1 << 26)
#define MCX_CQ_ENTRY_FLAGS_L3_OK (1 << 25)
#define MCX_CQ_ENTRY_FLAGS_L2_OK (1 << 24)
+#define MCX_CQ_ENTRY_FLAGS_CV (1 << 16)
+#define MCX_CQ_ENTRY_FLAGS_VLAN_MASK (0xffff)
uint32_t cq_lro_srqn;
uint32_t __reserved__[2];
@@ -2363,6 +2367,9 @@ mcx_attach(struct device *parent, struct device *self, void *aux)
ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_CSUM_IPv4 |
IFCAP_CSUM_UDPv4 | IFCAP_CSUM_UDPv6 | IFCAP_CSUM_TCPv4 |
IFCAP_CSUM_TCPv6;
+#if NVLAN > 0
+ ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
+#endif
IFQ_SET_MAXLEN(&ifp->if_snd, 1024);
ifmedia_init(&sc->sc_media, IFM_IMASK, mcx_media_change,
@@ -4013,6 +4020,7 @@ mcx_create_rq(struct mcx_softc *sc, int cqn)
struct mcx_rq_ctx *mbin;
int error;
uint64_t *pas;
+ uint32_t rq_flags;
uint8_t *doorbell;
int insize, npages, paslen, token;
@@ -4044,7 +4052,11 @@ mcx_create_rq(struct mcx_softc *sc, int cqn)
goto free;
}
mbin = (struct mcx_rq_ctx *)(((char *)mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0))) + 0x10);
- mbin->rq_flags = htobe32(MCX_RQ_CTX_RLKEY | MCX_RQ_CTX_VLAN_STRIP_DIS);
+ rq_flags = MCX_RQ_CTX_RLKEY;
+#if NVLAN == 0
+ rq_flags |= MCX_RQ_CTX_VLAN_STRIP_DIS;
+#endif
+ mbin->rq_flags = htobe32(rq_flags);
mbin->rq_cqn = htobe32(cqn);
mbin->rq_wq.wq_type = MCX_WQ_CTX_TYPE_CYCLIC;
mbin->rq_wq.wq_pd = htobe32(sc->sc_pd);
@@ -5697,6 +5709,13 @@ mcx_process_rx(struct mcx_softc *sc, struct mcx_cq_entry *cqe,
if (flags & MCX_CQ_ENTRY_FLAGS_L4_OK)
m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK |
M_UDP_CSUM_IN_OK;
+#if NVLAN > 0
+ if (flags & MCX_CQ_ENTRY_FLAGS_CV) {
+ m->m_pkthdr.ether_vtag = (flags &
+ MCX_CQ_ENTRY_FLAGS_VLAN_MASK);
+ m->m_flags |= M_VLANTAG;
+ }
+#endif
if (c->c_tdiff) {
uint64_t t = bemtoh64(&cqe->cq_timestamp) - c->c_timestamp;
@@ -6369,9 +6388,26 @@ mcx_start(struct ifqueue *ifq)
csum |= MCX_SQE_L4_CSUM;
sqe->sqe_mss_csum = htobe32(csum);
sqe->sqe_inline_header_size = htobe16(MCX_SQ_INLINE_SIZE);
- m_copydata(m, 0, MCX_SQ_INLINE_SIZE,
- (caddr_t)sqe->sqe_inline_headers);
- m_adj(m, MCX_SQ_INLINE_SIZE);
+#if NVLAN > 0
+ if (m->m_flags & M_VLANTAG) {
+ struct ether_vlan_header *evh;
+ evh = (struct ether_vlan_header *)
+ &sqe->sqe_inline_headers;
+
+ /* slightly cheaper vlan_inject() */
+ m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)evh);
+ evh->evl_proto = evh->evl_encap_proto;
+ evh->evl_encap_proto = htons(ETHERTYPE_VLAN);
+ evh->evl_tag = htons(m->m_pkthdr.ether_vtag);
+
+ m_adj(m, ETHER_HDR_LEN);
+ } else
+#endif
+ {
+ m_copydata(m, 0, MCX_SQ_INLINE_SIZE,
+ (caddr_t)sqe->sqe_inline_headers);
+ m_adj(m, MCX_SQ_INLINE_SIZE);
+ }
if (mcx_load_mbuf(sc, ms, m) != 0) {
m_freem(m);