Index: sys/dev/virtio/network/if_vtnet.c =================================================================== --- sys/dev/virtio/network/if_vtnet.c +++ sys/dev/virtio/network/if_vtnet.c @@ -210,6 +210,7 @@ static void vtnet_register_vlan(void *, struct ifnet *, uint16_t); static void vtnet_unregister_vlan(void *, struct ifnet *, uint16_t); +static void vtnet_update_speed_duplex(struct vtnet_softc *); static int vtnet_is_link_up(struct vtnet_softc *); static void vtnet_update_link_status(struct vtnet_softc *); static int vtnet_ifmedia_upd(struct ifnet *); @@ -987,7 +988,6 @@ } if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - ifp->if_baudrate = IF_Gbps(10); /* Approx. */ ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_KNOWSEPOCH; @@ -1005,10 +1005,19 @@ IFQ_SET_READY(&ifp->if_snd); #endif - ifmedia_init(&sc->vtnet_media, IFM_IMASK, vtnet_ifmedia_upd, - vtnet_ifmedia_sts); - ifmedia_add(&sc->vtnet_media, VTNET_MEDIATYPE, 0, NULL); - ifmedia_set(&sc->vtnet_media, VTNET_MEDIATYPE); + if (virtio_with_feature(dev, VIRTIO_NET_F_SPEED_DUPLEX)) { + uint32_t speed = virtio_read_dev_config_4(dev, + offsetof(struct virtio_net_config, speed)); + if (speed != -1) + ifp->if_baudrate = IF_Mbps(speed); + else + ifp->if_baudrate = IF_Gbps(10); /* Approx. */ + } else + ifp->if_baudrate = IF_Gbps(10); /* Approx. */ + + ifmedia_init(&sc->vtnet_media, 0, vtnet_ifmedia_upd, vtnet_ifmedia_sts); + ifmedia_add(&sc->vtnet_media, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_set(&sc->vtnet_media, IFM_ETHER | IFM_AUTO); vtnet_get_hwaddr(sc); ether_ifattach(ifp, sc->vtnet_hwaddr); @@ -3588,6 +3597,27 @@ vtnet_update_vlan_filter(arg, 0, tag); } +static void +vtnet_update_speed_duplex(struct vtnet_softc *sc) +{ + device_t dev; + struct ifnet *ifp; + uint32_t speed; + + dev = sc->vtnet_dev; + ifp = sc->vtnet_ifp; + + /* BMV: Ignore duplex. */ + if ((sc->vtnet_features & VIRTIO_NET_F_SPEED_DUPLEX) == 0) + speed = -1; + else + speed = virtio_read_dev_config_4(dev, + offsetof(struct virtio_net_config, speed)); + + if (speed != -1) + ifp->if_baudrate = IF_Mbps(speed); +} + static int vtnet_is_link_up(struct vtnet_softc *sc) { @@ -3614,12 +3644,12 @@ int link; ifp = sc->vtnet_ifp; - VTNET_CORE_LOCK_ASSERT(sc); link = vtnet_is_link_up(sc); /* Notify if the link status has changed. */ if (link != 0 && sc->vtnet_link_active == 0) { + vtnet_update_speed_duplex(sc); sc->vtnet_link_active = 1; if_link_state_change(ifp, LINK_STATE_UP); } else if (link == 0 && sc->vtnet_link_active != 0) { @@ -3631,16 +3661,7 @@ static int vtnet_ifmedia_upd(struct ifnet *ifp) { - struct vtnet_softc *sc; - struct ifmedia *ifm; - - sc = ifp->if_softc; - ifm = &sc->vtnet_media; - - if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) - return (EINVAL); - - return (0); + return (EOPNOTSUPP); } static void @@ -3656,7 +3677,7 @@ VTNET_CORE_LOCK(sc); if (vtnet_is_link_up(sc) != 0) { ifmr->ifm_status |= IFM_ACTIVE; - ifmr->ifm_active |= VTNET_MEDIATYPE; + ifmr->ifm_active |= IFM_10G_T | IFM_FDX; } else ifmr->ifm_active |= IFM_NONE; VTNET_CORE_UNLOCK(sc); Index: sys/dev/virtio/network/if_vtnetvar.h =================================================================== --- sys/dev/virtio/network/if_vtnetvar.h +++ sys/dev/virtio/network/if_vtnetvar.h @@ -211,12 +211,6 @@ */ #define VTNET_NOTIFY_RETRIES 4 -/* - * Fake the media type. The host does not provide us with any real media - * information. - */ -#define VTNET_MEDIATYPE (IFM_ETHER | IFM_10G_T | IFM_FDX) - /* * Number of words to allocate for the VLAN shadow table. There is one * bit for each VLAN. @@ -313,6 +307,7 @@ VIRTIO_NET_F_GUEST_ECN | \ VIRTIO_NET_F_MRG_RXBUF | \ VIRTIO_NET_F_MQ | \ + VIRTIO_NET_F_SPEED_DUPLEX | \ VIRTIO_RING_F_EVENT_IDX | \ VIRTIO_RING_F_INDIRECT_DESC)