vioif(4): register MAC address to a device

This commit is contained in:
yamaguchi 2022-03-24 07:57:10 +00:00
parent 1c9fb8cec4
commit f490bf1198
1 changed files with 73 additions and 10 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_vioif.c,v 1.73 2022/03/24 07:51:14 yamaguchi Exp $ */
/* $NetBSD: if_vioif.c,v 1.74 2022/03/24 07:57:10 yamaguchi Exp $ */
/*
* Copyright (c) 2020 The NetBSD Foundation, Inc.
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.73 2022/03/24 07:51:14 yamaguchi Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.74 2022/03/24 07:57:10 yamaguchi Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@ -56,6 +56,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.73 2022/03/24 07:51:14 yamaguchi Exp
#include <dev/pci/virtiovar.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_ether.h>
@ -157,6 +158,7 @@ struct virtio_net_ctrl_cmd {
#define VIRTIO_NET_CTRL_MAC 1
# define VIRTIO_NET_CTRL_MAC_TABLE_SET 0
# define VIRTIO_NET_CTRL_MAC_ADDR_SET 1
#define VIRTIO_NET_CTRL_VLAN 2
# define VIRTIO_NET_CTRL_VLAN_ADD 0
@ -182,6 +184,10 @@ struct virtio_net_ctrl_mac_tbl {
uint8_t macs[][ETHER_ADDR_LEN];
} __packed;
struct virtio_net_ctrl_mac_addr {
uint8_t mac[ETHER_ADDR_LEN];
} __packed;
struct virtio_net_ctrl_vlan {
uint16_t id;
} __packed;
@ -281,6 +287,7 @@ struct vioif_ctrlqueue {
struct virtio_net_ctrl_rx *ctrlq_rx;
struct virtio_net_ctrl_mac_tbl *ctrlq_mac_tbl_uc;
struct virtio_net_ctrl_mac_tbl *ctrlq_mac_tbl_mc;
struct virtio_net_ctrl_mac_addr *ctrlq_mac_addr;
struct virtio_net_ctrl_mq *ctrlq_mq;
bus_dmamap_t ctrlq_cmd_dmamap;
@ -288,6 +295,7 @@ struct vioif_ctrlqueue {
bus_dmamap_t ctrlq_rx_dmamap;
bus_dmamap_t ctrlq_tbl_uc_dmamap;
bus_dmamap_t ctrlq_tbl_mc_dmamap;
bus_dmamap_t ctrlq_mac_addr_dmamap;
bus_dmamap_t ctrlq_mq_dmamap;
struct evcnt ctrlq_cmd_load_failed;
@ -399,6 +407,7 @@ static int vioif_set_promisc(struct vioif_softc *, bool);
static int vioif_set_allmulti(struct vioif_softc *, bool);
static int vioif_set_rx_filter(struct vioif_softc *);
static int vioif_rx_filter(struct vioif_softc *);
static int vioif_set_mac_addr(struct vioif_softc *);
static int vioif_ctrl_intr(void *);
static int vioif_config_change(struct virtio_softc *);
static void vioif_ctl_softint(void *);
@ -579,13 +588,15 @@ vioif_alloc_mems(struct vioif_softc *sc)
(rxq->rxq_vq->vq_num + txq->txq_vq->vq_num);
}
if (sc->sc_has_ctrl) {
allocsize += sizeof(struct virtio_net_ctrl_cmd) * 1;
allocsize += sizeof(struct virtio_net_ctrl_status) * 1;
allocsize += sizeof(struct virtio_net_ctrl_rx) * 1;
allocsize += sizeof(struct virtio_net_ctrl_cmd);
allocsize += sizeof(struct virtio_net_ctrl_status);
allocsize += sizeof(struct virtio_net_ctrl_rx);
allocsize += sizeof(struct virtio_net_ctrl_mac_tbl)
+ ETHER_ADDR_LEN;
allocsize += sizeof(struct virtio_net_ctrl_mac_tbl)
+ sizeof(struct virtio_net_ctrl_mac_tbl)
+ ETHER_ADDR_LEN * VIRTIO_NET_CTRL_MAC_MAXENTRIES;
allocsize += sizeof(struct virtio_net_ctrl_mq) * 1;
allocsize += sizeof(struct virtio_net_ctrl_mac_addr);
allocsize += sizeof(struct virtio_net_ctrl_mq);
}
r = bus_dmamem_alloc(virtio_dmat(vsc), allocsize, 0, 0,
&sc->sc_hdr_segs[0], 1, &rsegs, BUS_DMA_NOWAIT);
@ -624,10 +635,13 @@ vioif_alloc_mems(struct vioif_softc *sc)
ctrlq->ctrlq_rx = vioif_assign_mem(&p,
sizeof(*ctrlq->ctrlq_rx));
ctrlq->ctrlq_mac_tbl_uc = vioif_assign_mem(&p,
sizeof(*ctrlq->ctrlq_mac_tbl_uc));
sizeof(*ctrlq->ctrlq_mac_tbl_uc)
+ ETHER_ADDR_LEN);
ctrlq->ctrlq_mac_tbl_mc = vioif_assign_mem(&p,
sizeof(*ctrlq->ctrlq_mac_tbl_mc)
+ ETHER_ADDR_LEN * VIRTIO_NET_CTRL_MAC_MAXENTRIES);
ctrlq->ctrlq_mac_addr = vioif_assign_mem(&p,
sizeof(*ctrlq->ctrlq_mac_addr));
ctrlq->ctrlq_mq = vioif_assign_mem(&p, sizeof(*ctrlq->ctrlq_mq));
}
@ -735,7 +749,8 @@ vioif_alloc_mems(struct vioif_softc *sc)
/* control vq MAC filter table for unicast */
/* do not load now since its length is variable */
r = vioif_dmamap_create(sc, &ctrlq->ctrlq_tbl_uc_dmamap,
sizeof(*ctrlq->ctrlq_mac_tbl_uc) + 0, 1,
sizeof(*ctrlq->ctrlq_mac_tbl_uc)
+ ETHER_ADDR_LEN, 1,
"unicast MAC address filter command");
if (r != 0)
goto err_reqs;
@ -747,6 +762,15 @@ vioif_alloc_mems(struct vioif_softc *sc)
"multicast MAC address filter command");
if (r != 0)
goto err_reqs;
/* control vq MAC address set command */
r = vioif_dmamap_create_load(sc,
&ctrlq->ctrlq_mac_addr_dmamap,
ctrlq->ctrlq_mac_addr,
sizeof(*ctrlq->ctrlq_mac_addr), 1,
BUS_DMA_WRITE, "mac addr set command");
if (r != 0)
goto err_reqs;
}
return 0;
@ -757,6 +781,7 @@ err_reqs:
vioif_dmamap_destroy(sc, &ctrlq->ctrlq_rx_dmamap);
vioif_dmamap_destroy(sc, &ctrlq->ctrlq_status_dmamap);
vioif_dmamap_destroy(sc, &ctrlq->ctrlq_cmd_dmamap);
vioif_dmamap_destroy(sc, &ctrlq->ctrlq_mac_addr_dmamap);
for (qid = 0; qid < sc->sc_max_nvq_pairs; qid++) {
rxq = &sc->sc_rxq[qid];
txq = &sc->sc_txq[qid];
@ -2168,6 +2193,35 @@ out:
return r;
}
static int
vioif_set_mac_addr(struct vioif_softc *sc)
{
struct virtio_net_ctrl_mac_addr *ma =
sc->sc_ctrlq.ctrlq_mac_addr;
struct vioif_ctrl_cmdspec specs[1];
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
int nspecs = __arraycount(specs);
int r;
if (!sc->sc_has_ctrl)
return ENOTSUP;
vioif_ctrl_acquire(sc);
memcpy(ma->mac, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
specs[0].dmamap = sc->sc_ctrlq.ctrlq_mac_addr_dmamap;
specs[0].buf = ma;
specs[0].bufsize = sizeof(*ma);
r = vioif_ctrl_send_command(sc,
VIRTIO_NET_CTRL_MAC, VIRTIO_NET_CTRL_MAC_ADDR_SET,
specs, nspecs);
vioif_ctrl_release(sc);
return r;
}
static int
vioif_ctrl_mq_vq_pairs_set(struct vioif_softc *sc, int nvq_pairs)
{
@ -2254,6 +2308,9 @@ vioif_rx_filter(struct vioif_softc *sc)
goto set;
}
memcpy(ctrlq->ctrlq_mac_tbl_uc->macs[0],
CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
nentries = -1;
ETHER_LOCK(ec);
ETHER_FIRST_MULTI(step, ec, enm);
@ -2276,8 +2333,14 @@ set_unlock:
ETHER_UNLOCK(ec);
set:
r = vioif_set_mac_addr(sc);
if (r != 0) {
log(LOG_WARNING, "%s: couldn't set MAC address\n",
ifp->if_xname);
}
if (rxfilter) {
ctrlq->ctrlq_mac_tbl_uc->nentries = virtio_rw32(vsc, 0);
ctrlq->ctrlq_mac_tbl_uc->nentries = virtio_rw32(vsc, 1);
ctrlq->ctrlq_mac_tbl_mc->nentries = virtio_rw32(vsc, nentries);
r = vioif_set_rx_filter(sc);
if (r != 0) {