From nobody Mon Apr 27 11:38:56 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4g41mk23Pjz6ZwZt for ; Mon, 27 Apr 2026 11:39:02 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4g41mj6ZhSz3f8x for ; Mon, 27 Apr 2026 11:39:01 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1777289941; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nzd8DZ9YztC+dLqy4yT3isEYjXMpz33zkKb8KdUzF1s=; b=NraYmzjjR/WtFsNcSrSYSk3Q5PUBm+SYfl1lPnwQHhqSdCmhe6gh2MHBL0x3SMy6c4u+pW ePo9pHEHrJIeBc3hfA9vBcsGWJnDJp1izW4Y3CIOULNNCx1Ym/dMPFg3sFk2QPD2LKPL/5 SpghadkU6JL5OMsZJicp/in4ouyw1tyE8b4xcUsQ310gA4xtrqaWToGkjxarHVV6RpeZQ/ 467IvtChX8qIKB9y9Y2XfbMt15z0SziJfb05oKlGAUOGkug4Jpnhp20ovywSXPiHLiL2EZ +tcAa+X0fptOjwwE9JqQDMPXoeowmOpN79GWn7akPfRBBTzl1KBT1fGS3l2l1A== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1777289941; a=rsa-sha256; cv=none; b=wvguO4qRuENK4d3hitNJ2D+CNsm0jw07uaeCzcl26NHIyQAL/mKf3sxKD+SBhcasZrGdzy Wb2iQJWNPHQpeLkkXct5YX4cGau7tCc23zGvdX/TGJe2YU2Qlav/okmyqrjSOYjgBU49ta vtCdQcxLdmnWYlxSYwWOXQ81YM1oJYxsjbW6CY3/HDHAy8EtNMnVGFtO6wuAKbZD6295HF D4WOw07XXOE4VZIipJ4lJdvG3Gq3V0aT57LskCj0GcAlf2/FXEy6y9ksjDnntWPg1RbFf5 Sp5X0zbvTgo7biMnxmiEAdW2MP4HwuxPuquKjPDoDrAppU5nT2NvGR6C2HHCQA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1777289941; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nzd8DZ9YztC+dLqy4yT3isEYjXMpz33zkKb8KdUzF1s=; b=wyKb7vvTSNjkAXMu/GmZlO571uIO/P9E0scbplPD5yYCJ9s8Xd/7FawMcvZDMi4QbgsPg0 TSoZCokylEy3zt3DVXINx7xQPWHtRXxWRISRmIGE4NaRbbjYo3WCqOHSvXuX2Pd6Qa+YXQ X8VZJcxh142PXVg2PND2/YdZuSJBQlmj9pi6pwd+LaHWn9OccY4STFlCieWKf6kJ8huakH VespBZ/eroYHkP2iI9EXFP6AZ2fkaAUQI0OLCrj3bmE5HQ4dvC8T9L9+aBtwMOhbzTvMDt CQXW42BwVUISonfu+ae5s+xaS/i107iMxF0+82w9dS1xMCnCzqjH5DCZ3GXElA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4g41mj674lz14kK for ; Mon, 27 Apr 2026 11:39:01 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1f221 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 27 Apr 2026 11:38:56 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Sarah Walker From: Andrew Turner Subject: git: b5bad6df467c - main - virtio_net: Use bus_dma for command/ack buffers List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: andrew X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: b5bad6df467cc95bea641afe674c55cd5b9f1510 Auto-Submitted: auto-generated Date: Mon, 27 Apr 2026 11:38:56 +0000 Message-Id: <69ef4ad0.1f221.796b75f@gitrepo.freebsd.org> The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=b5bad6df467cc95bea641afe674c55cd5b9f1510 commit b5bad6df467cc95bea641afe674c55cd5b9f1510 Author: Sarah Walker AuthorDate: 2026-02-27 14:17:15 +0000 Commit: Andrew Turner CommitDate: 2026-04-27 11:37:53 +0000 virtio_net: Use bus_dma for command/ack buffers While the majority of virtio platforms will be fully coherent, some may require cache maintenance or other specific device memory handling (eg for secure partitioning). Using bus_dma allows for these usecases. The virtio buffers are marked as coherent; this should ensure that sync calls are no-ops in the common cases. Reviewed by: andrew Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D55564 --- sys/dev/virtio/network/if_vtnet.c | 336 +++++++++++++++++++++++++++++------ sys/dev/virtio/network/if_vtnetvar.h | 6 + 2 files changed, 284 insertions(+), 58 deletions(-) diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c index e88602a44664..40792482672c 100644 --- a/sys/dev/virtio/network/if_vtnet.c +++ b/sys/dev/virtio/network/if_vtnet.c @@ -219,7 +219,7 @@ static void vtnet_init_locked(struct vtnet_softc *, int); static void vtnet_init(void *); static void vtnet_free_ctrl_vq(struct vtnet_softc *); -static void vtnet_exec_ctrl_cmd(struct vtnet_softc *, void *, +static int vtnet_exec_ctrl_cmd(struct vtnet_softc *, uint8_t *, struct sglist *, int, int); static int vtnet_ctrl_mac_cmd(struct vtnet_softc *, uint8_t *); static int vtnet_ctrl_guest_offloads(struct vtnet_softc *, uint64_t); @@ -523,6 +523,50 @@ vtnet_attach(device_t dev) goto fail; } + mtx_init(&sc->vtnet_hdr_mtx, device_get_nameunit(dev), + "VirtIO Net header lock", MTX_DEF); + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + sizeof(uint16_t), /* alignment */ + 0, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + PAGE_SIZE, /* max request size */ + 1, /* max # segments */ + PAGE_SIZE, /* maxsegsize */ + BUS_DMA_COHERENT, /* flags */ + busdma_lock_mutex, /* lockfunc */ + &sc->vtnet_hdr_mtx, /* lockarg */ + &sc->vtnet_hdr_dmat); + if (error) { + device_printf(dev, "cannot create bus_dma_tag\n"); + goto fail; + } + + mtx_init(&sc->vtnet_ack_mtx, device_get_nameunit(dev), + "VirtIO Net ACK lock", MTX_DEF); + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + sizeof(uint8_t), /* alignment */ + 0, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + sizeof(uint8_t), /* max request size */ + 1, /* max # segments */ + sizeof(uint8_t), /* maxsegsize */ + BUS_DMA_COHERENT, /* flags */ + busdma_lock_mutex, /* lockfunc */ + &sc->vtnet_ack_mtx, /* lockarg */ + &sc->vtnet_ack_dmat); + if (error) { + device_printf(dev, "cannot create bus_dma_tag\n"); + goto fail; + } + #ifdef __powerpc__ /* * Virtio uses physical addresses rather than bus addresses, so we @@ -531,6 +575,8 @@ vtnet_attach(device_t dev) */ bus_dma_tag_set_iommu(sc->vtnet_rx_dmat, NULL, NULL); bus_dma_tag_set_iommu(sc->vtnet_tx_dmat, NULL, NULL); + bus_dma_tag_set_iommu(sc->vtnet_hdr_dmat, NULL, NULL); + bus_dma_tag_set_iommu(sc->vtnet_ack_dmat, NULL, NULL); #endif error = vtnet_alloc_rx_filters(sc); @@ -3751,10 +3797,43 @@ vtnet_free_ctrl_vq(struct vtnet_softc *sc) } static void -vtnet_exec_ctrl_cmd(struct vtnet_softc *sc, void *cookie, - struct sglist *sg, int readable, int writable) +vtnet_load_callback(void *arg, bus_dma_segment_t *segs, int nsegs, + int error) { + bus_addr_t *paddr; + + if (error != 0) + return; + + KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); + + paddr = (bus_addr_t *)arg; + *paddr = segs[0].ds_addr; +} + +static int +vtnet_exec_ctrl_cmd(struct vtnet_softc *sc, uint8_t *ack, struct sglist *sg, + int readable, int writable) +{ + bus_dmamap_t ack_dmap; + bus_addr_t ack_paddr; struct virtqueue *vq; + int error; + + error = bus_dmamap_create(sc->vtnet_ack_dmat, 0, &ack_dmap); + if (error) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_ack_dmat, ack_dmap, ack, + sizeof(uint8_t), vtnet_load_callback, &ack_paddr, BUS_DMA_NOWAIT); + if (error) + goto error_destroy; + + bus_dmamap_sync(sc->vtnet_ack_dmat, ack_dmap, BUS_DMASYNC_PREWRITE); + + error = sglist_append_phys(sg, ack_paddr, sizeof(uint8_t)); + if (error) + goto error_unload; vq = sc->vtnet_ctrl_vq; @@ -3762,152 +3841,237 @@ vtnet_exec_ctrl_cmd(struct vtnet_softc *sc, void *cookie, VTNET_CORE_LOCK_ASSERT(sc); if (!virtqueue_empty(vq)) - return; + goto error_unload; /* * Poll for the response, but the command is likely completed before * returning from the notify. */ - if (virtqueue_enqueue(vq, cookie, sg, readable, writable) == 0) { + if (virtqueue_enqueue(vq, (void *)ack, sg, readable, writable) == 0) { virtqueue_notify(vq); virtqueue_poll(vq, NULL); } + + bus_dmamap_sync(sc->vtnet_ack_dmat, ack_dmap, BUS_DMASYNC_POSTREAD); + +error_unload: + bus_dmamap_unload(sc->vtnet_ack_dmat, ack_dmap); +error_destroy: + bus_dmamap_destroy(sc->vtnet_ack_dmat, ack_dmap); +error_out: + return (error); } static int vtnet_ctrl_mac_cmd(struct vtnet_softc *sc, uint8_t *hwaddr) { struct sglist_seg segs[3]; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; struct sglist sg; struct { struct virtio_net_ctrl_hdr hdr __aligned(2); uint8_t pad1; uint8_t addr[ETHER_ADDR_LEN] __aligned(8); uint8_t pad2; - uint8_t ack; } s; + uint8_t ack; int error; - error = 0; + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s, + sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error) + goto error_destroy_hdr; + MPASS(sc->vtnet_flags & VTNET_FLAG_CTRL_MAC); s.hdr.class = VIRTIO_NET_CTRL_MAC; s.hdr.cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET; bcopy(hwaddr, &s.addr[0], ETHER_ADDR_LEN); - s.ack = VIRTIO_NET_ERR; + ack = VIRTIO_NET_ERR; + bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE); sglist_init(&sg, nitems(segs), segs); - error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr)); - error |= sglist_append(&sg, &s.addr[0], ETHER_ADDR_LEN); - error |= sglist_append(&sg, &s.ack, sizeof(uint8_t)); - MPASS(error == 0 && sg.sg_nseg == nitems(segs)); + error |= sglist_append_phys(&sg, hdr_paddr, + sizeof(struct virtio_net_ctrl_hdr)); + error |= sglist_append_phys(&sg, + hdr_paddr + ((uintptr_t)&s.addr - (uintptr_t)&s), + ETHER_ADDR_LEN); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); if (error == 0) - vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1); + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); - return (s.ack == VIRTIO_NET_OK ? 0 : EIO); + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +error_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +error_out: + return (error); } static int vtnet_ctrl_guest_offloads(struct vtnet_softc *sc, uint64_t offloads) { struct sglist_seg segs[3]; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; struct sglist sg; struct { struct virtio_net_ctrl_hdr hdr __aligned(2); uint8_t pad1; uint64_t offloads __aligned(8); uint8_t pad2; - uint8_t ack; } s; + uint8_t ack; int error; - error = 0; + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s, + sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error) + goto error_destroy_hdr; + MPASS(sc->vtnet_features & VIRTIO_NET_F_CTRL_GUEST_OFFLOADS); s.hdr.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS; s.hdr.cmd = VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET; s.offloads = vtnet_gtoh64(sc, offloads); - s.ack = VIRTIO_NET_ERR; + ack = VIRTIO_NET_ERR; + bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE); sglist_init(&sg, nitems(segs), segs); - error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr)); - error |= sglist_append(&sg, &s.offloads, sizeof(uint64_t)); - error |= sglist_append(&sg, &s.ack, sizeof(uint8_t)); - MPASS(error == 0 && sg.sg_nseg == nitems(segs)); + error |= sglist_append_phys(&sg, hdr_paddr, + sizeof(struct virtio_net_ctrl_hdr)); + error |= sglist_append_phys(&sg, + hdr_paddr + ((uintptr_t)&s.offloads - (uintptr_t)&s), + sizeof(uint64_t)); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); if (error == 0) - vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1); + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); - return (s.ack == VIRTIO_NET_OK ? 0 : EIO); + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +error_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +error_out: + return (error); } static int vtnet_ctrl_mq_cmd(struct vtnet_softc *sc, uint16_t npairs) { struct sglist_seg segs[3]; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; struct sglist sg; struct { struct virtio_net_ctrl_hdr hdr __aligned(2); uint8_t pad1; struct virtio_net_ctrl_mq mq __aligned(2); uint8_t pad2; - uint8_t ack; } s; + uint8_t ack; int error; - error = 0; + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s, + sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error) + goto error_destroy_hdr; + MPASS(sc->vtnet_flags & VTNET_FLAG_MQ); s.hdr.class = VIRTIO_NET_CTRL_MQ; s.hdr.cmd = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET; s.mq.virtqueue_pairs = vtnet_gtoh16(sc, npairs); - s.ack = VIRTIO_NET_ERR; + ack = VIRTIO_NET_ERR; + bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE); sglist_init(&sg, nitems(segs), segs); - error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr)); - error |= sglist_append(&sg, &s.mq, sizeof(struct virtio_net_ctrl_mq)); - error |= sglist_append(&sg, &s.ack, sizeof(uint8_t)); - MPASS(error == 0 && sg.sg_nseg == nitems(segs)); + error |= sglist_append_phys(&sg, hdr_paddr, + sizeof(struct virtio_net_ctrl_hdr)); + error |= sglist_append_phys(&sg, + hdr_paddr + ((uintptr_t)&s.mq - (uintptr_t)&s), + sizeof(struct virtio_net_ctrl_mq)); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); if (error == 0) - vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1); + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); - return (s.ack == VIRTIO_NET_OK ? 0 : EIO); + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +error_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +error_out: + return (error); } static int vtnet_ctrl_rx_cmd(struct vtnet_softc *sc, uint8_t cmd, bool on) { struct sglist_seg segs[3]; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; struct sglist sg; struct { struct virtio_net_ctrl_hdr hdr __aligned(2); uint8_t pad1; uint8_t onoff; uint8_t pad2; - uint8_t ack; } s; + uint8_t ack; int error; - error = 0; + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s, + sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error) + goto error_destroy_hdr; + MPASS(sc->vtnet_flags & VTNET_FLAG_CTRL_RX); s.hdr.class = VIRTIO_NET_CTRL_RX; s.hdr.cmd = cmd; s.onoff = on; - s.ack = VIRTIO_NET_ERR; + ack = VIRTIO_NET_ERR; + bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE); sglist_init(&sg, nitems(segs), segs); - error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr)); - error |= sglist_append(&sg, &s.onoff, sizeof(uint8_t)); - error |= sglist_append(&sg, &s.ack, sizeof(uint8_t)); - MPASS(error == 0 && sg.sg_nseg == nitems(segs)); + error |= sglist_append_phys(&sg, hdr_paddr, + sizeof(struct virtio_net_ctrl_hdr)); + error |= sglist_append_phys(&sg, + hdr_paddr + ((uintptr_t)&s.onoff - (uintptr_t)&s), + sizeof(uint8_t)); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); if (error == 0) - vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1); + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); - return (s.ack == VIRTIO_NET_OK ? 0 : EIO); + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +error_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +error_out: + return (error); } static int @@ -3978,6 +4142,10 @@ vtnet_rx_filter_mac(struct vtnet_softc *sc) struct virtio_net_ctrl_hdr hdr __aligned(2); struct vtnet_mac_filter *filter; struct sglist_seg segs[4]; + bus_dmamap_t filter_dmap; + bus_addr_t filter_paddr; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; struct sglist sg; if_t ifp; bool promisc, allmulti; @@ -4017,6 +4185,25 @@ vtnet_rx_filter_mac(struct vtnet_softc *sc) if (promisc && allmulti) goto out; + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error) + goto out_error; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &hdr, + sizeof(hdr), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error) + goto out_destroy_hdr; + + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &filter_dmap); + if (error) + goto out_unload_hdr; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, filter, + sizeof(*filter), vtnet_load_callback, &filter_paddr, + BUS_DMA_NOWAIT); + if (error) + goto out_destroy_filter; + filter->vmf_unicast.nentries = vtnet_gtoh32(sc, ucnt); filter->vmf_multicast.nentries = vtnet_gtoh32(sc, mcnt); @@ -4025,19 +4212,33 @@ vtnet_rx_filter_mac(struct vtnet_softc *sc) ack = VIRTIO_NET_ERR; sglist_init(&sg, nitems(segs), segs); - error |= sglist_append(&sg, &hdr, sizeof(struct virtio_net_ctrl_hdr)); - error |= sglist_append(&sg, &filter->vmf_unicast, + error |= sglist_append_phys(&sg, hdr_paddr, + sizeof(struct virtio_net_ctrl_hdr)); + error |= sglist_append_phys(&sg, + filter_paddr + ((uintptr_t)&filter->vmf_unicast - + (uintptr_t)filter), sizeof(uint32_t) + ucnt * ETHER_ADDR_LEN); - error |= sglist_append(&sg, &filter->vmf_multicast, + error |= sglist_append_phys(&sg, + filter_paddr + ((uintptr_t)&filter->vmf_multicast - + (uintptr_t)filter), sizeof(uint32_t) + mcnt * ETHER_ADDR_LEN); - error |= sglist_append(&sg, &ack, sizeof(uint8_t)); - MPASS(error == 0 && sg.sg_nseg == nitems(segs)); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); if (error == 0) - vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg - 1, 1); - if (ack != VIRTIO_NET_OK) + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); + + bus_dmamap_unload(sc->vtnet_hdr_dmat, filter_dmap); +out_destroy_filter: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, filter_dmap); +out_unload_hdr: + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +out_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +out_error: + if (error != 0) if_printf(ifp, "error setting host MAC filter table\n"); - out: if (promisc && vtnet_set_promisc(sc, true) != 0) if_printf(ifp, "cannot enable promiscuous mode\n"); @@ -4049,34 +4250,53 @@ static int vtnet_exec_vlan_filter(struct vtnet_softc *sc, int add, uint16_t tag) { struct sglist_seg segs[3]; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; struct sglist sg; struct { struct virtio_net_ctrl_hdr hdr __aligned(2); uint8_t pad1; uint16_t tag __aligned(2); uint8_t pad2; - uint8_t ack; } s; + uint8_t ack; int error; - error = 0; + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s, + sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error) + goto error_destroy_hdr; + MPASS(sc->vtnet_flags & VTNET_FLAG_VLAN_FILTER); s.hdr.class = VIRTIO_NET_CTRL_VLAN; s.hdr.cmd = add ? VIRTIO_NET_CTRL_VLAN_ADD : VIRTIO_NET_CTRL_VLAN_DEL; s.tag = vtnet_gtoh16(sc, tag); - s.ack = VIRTIO_NET_ERR; + ack = VIRTIO_NET_ERR; + bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE); sglist_init(&sg, nitems(segs), segs); - error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr)); - error |= sglist_append(&sg, &s.tag, sizeof(uint16_t)); - error |= sglist_append(&sg, &s.ack, sizeof(uint8_t)); - MPASS(error == 0 && sg.sg_nseg == nitems(segs)); + error |= sglist_append_phys(&sg, hdr_paddr, + sizeof(struct virtio_net_ctrl_hdr)); + error |= sglist_append_phys(&sg, + hdr_paddr + ((uintptr_t)&s.tag - (uintptr_t)&s), + sizeof(uint16_t)); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); if (error == 0) - vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1); + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); - return (s.ack == VIRTIO_NET_OK ? 0 : EIO); + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +error_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +error_out: + return (error); } static void diff --git a/sys/dev/virtio/network/if_vtnetvar.h b/sys/dev/virtio/network/if_vtnetvar.h index 6cafe827d733..e445bdf6d6cb 100644 --- a/sys/dev/virtio/network/if_vtnetvar.h +++ b/sys/dev/virtio/network/if_vtnetvar.h @@ -196,6 +196,12 @@ struct vtnet_softc { bus_dma_tag_t vtnet_tx_dmat; struct mtx vtnet_tx_mtx; + + bus_dma_tag_t vtnet_hdr_dmat; + struct mtx vtnet_hdr_mtx; + + bus_dma_tag_t vtnet_ack_dmat; + struct mtx vtnet_ack_mtx; }; /* vtnet flag descriptions for use with printf(9) %b identifier. */ #define VTNET_FLAGS_BITS \