Mon Sep 12 07:26:04 2022 UTC ()
Uniform vioif's link status to if_link_state.  Implemented by yamaguchi@n.o.

Let vioif(4) know LINK_STATE_UNKNOWN.


(knakahara)
diff -r1.81 -r1.82 src/sys/dev/pci/if_vioif.c

cvs diff -r1.81 -r1.82 src/sys/dev/pci/if_vioif.c (expand / switch to unified diff)

--- src/sys/dev/pci/if_vioif.c 2022/05/04 02:38:27 1.81
+++ src/sys/dev/pci/if_vioif.c 2022/09/12 07:26:04 1.82
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_vioif.c,v 1.81 2022/05/04 02:38:27 simonb Exp $ */ 1/* $NetBSD: if_vioif.c,v 1.82 2022/09/12 07:26:04 knakahara Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 2020 The NetBSD Foundation, Inc.
5 * Copyright (c) 2010 Minoura Makoto. 5 * Copyright (c) 2010 Minoura Makoto.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -17,27 +17,27 @@ @@ -17,27 +17,27 @@
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.81 2022/05/04 02:38:27 simonb Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.82 2022/09/12 07:26:04 knakahara Exp $");
31 31
32#ifdef _KERNEL_OPT 32#ifdef _KERNEL_OPT
33#include "opt_net_mpsafe.h" 33#include "opt_net_mpsafe.h"
34#endif 34#endif
35 35
36#include <sys/param.h> 36#include <sys/param.h>
37#include <sys/systm.h> 37#include <sys/systm.h>
38#include <sys/kernel.h> 38#include <sys/kernel.h>
39#include <sys/atomic.h> 39#include <sys/atomic.h>
40#include <sys/bus.h> 40#include <sys/bus.h>
41#include <sys/condvar.h> 41#include <sys/condvar.h>
42#include <sys/device.h> 42#include <sys/device.h>
43#include <sys/evcnt.h> 43#include <sys/evcnt.h>
@@ -309,27 +309,27 @@ struct vioif_softc { @@ -309,27 +309,27 @@ struct vioif_softc {
309 kmutex_t sc_lock; 309 kmutex_t sc_lock;
310 struct sysctllog *sc_sysctllog; 310 struct sysctllog *sc_sysctllog;
311 311
312 struct virtio_softc *sc_virtio; 312 struct virtio_softc *sc_virtio;
313 struct virtqueue *sc_vqs; 313 struct virtqueue *sc_vqs;
314 u_int sc_hdr_size; 314 u_int sc_hdr_size;
315 315
316 int sc_max_nvq_pairs; 316 int sc_max_nvq_pairs;
317 int sc_req_nvq_pairs; 317 int sc_req_nvq_pairs;
318 int sc_act_nvq_pairs; 318 int sc_act_nvq_pairs;
319 319
320 uint8_t sc_mac[ETHER_ADDR_LEN]; 320 uint8_t sc_mac[ETHER_ADDR_LEN];
321 struct ethercom sc_ethercom; 321 struct ethercom sc_ethercom;
322 bool sc_link_active; 322 int sc_link_state;
323 323
324 struct vioif_txqueue *sc_txq; 324 struct vioif_txqueue *sc_txq;
325 struct vioif_rxqueue *sc_rxq; 325 struct vioif_rxqueue *sc_rxq;
326 326
327 bool sc_has_ctrl; 327 bool sc_has_ctrl;
328 struct vioif_ctrlqueue sc_ctrlq; 328 struct vioif_ctrlqueue sc_ctrlq;
329 329
330 bus_dma_segment_t sc_hdr_segs[1]; 330 bus_dma_segment_t sc_hdr_segs[1];
331 void *sc_dmamem; 331 void *sc_dmamem;
332 void *sc_kmem; 332 void *sc_kmem;
333 333
334 void *sc_ctl_softint; 334 void *sc_ctl_softint;
335 335
@@ -339,26 +339,28 @@ struct vioif_softc { @@ -339,26 +339,28 @@ struct vioif_softc {
339 u_int sc_tx_process_limit; 339 u_int sc_tx_process_limit;
340 u_int sc_rx_intr_process_limit; 340 u_int sc_rx_intr_process_limit;
341 u_int sc_rx_process_limit; 341 u_int sc_rx_process_limit;
342}; 342};
343#define VIRTIO_NET_TX_MAXNSEGS (16) /* XXX */ 343#define VIRTIO_NET_TX_MAXNSEGS (16) /* XXX */
344#define VIRTIO_NET_CTRL_MAC_MAXENTRIES (64) /* XXX */ 344#define VIRTIO_NET_CTRL_MAC_MAXENTRIES (64) /* XXX */
345 345
346#define VIOIF_TX_INTR_PROCESS_LIMIT 256 346#define VIOIF_TX_INTR_PROCESS_LIMIT 256
347#define VIOIF_TX_PROCESS_LIMIT 256 347#define VIOIF_TX_PROCESS_LIMIT 256
348#define VIOIF_RX_INTR_PROCESS_LIMIT 0U 348#define VIOIF_RX_INTR_PROCESS_LIMIT 0U
349#define VIOIF_RX_PROCESS_LIMIT 256 349#define VIOIF_RX_PROCESS_LIMIT 256
350 350
351#define VIOIF_WORKQUEUE_PRI PRI_SOFTNET 351#define VIOIF_WORKQUEUE_PRI PRI_SOFTNET
 352#define VIOIF_IS_LINK_ACTIVE(_sc) ((_sc)->sc_link_state == LINK_STATE_UP ? \
 353 true : false)
352 354
353/* cfattach interface functions */ 355/* cfattach interface functions */
354static int vioif_match(device_t, cfdata_t, void *); 356static int vioif_match(device_t, cfdata_t, void *);
355static void vioif_attach(device_t, device_t, void *); 357static void vioif_attach(device_t, device_t, void *);
356static int vioif_finalize_teardown(device_t); 358static int vioif_finalize_teardown(device_t);
357 359
358/* ifnet interface functions */ 360/* ifnet interface functions */
359static int vioif_init(struct ifnet *); 361static int vioif_init(struct ifnet *);
360static void vioif_stop(struct ifnet *, int); 362static void vioif_stop(struct ifnet *, int);
361static void vioif_start(struct ifnet *); 363static void vioif_start(struct ifnet *);
362static void vioif_start_locked(struct ifnet *, struct vioif_txqueue *); 364static void vioif_start_locked(struct ifnet *, struct vioif_txqueue *);
363static int vioif_transmit(struct ifnet *, struct mbuf *); 365static int vioif_transmit(struct ifnet *, struct mbuf *);
364static void vioif_transmit_locked(struct ifnet *, struct vioif_txqueue *); 366static void vioif_transmit_locked(struct ifnet *, struct vioif_txqueue *);
@@ -391,27 +393,27 @@ static bool vioif_tx_deq_locked(struct v @@ -391,27 +393,27 @@ static bool vioif_tx_deq_locked(struct v
391static void vioif_tx_drain(struct vioif_txqueue *); 393static void vioif_tx_drain(struct vioif_txqueue *);
392static void vioif_deferred_transmit(void *); 394static void vioif_deferred_transmit(void *);
393 395
394/* workqueue */ 396/* workqueue */
395static struct workqueue* 397static struct workqueue*
396 vioif_workq_create(const char *, pri_t, int, int); 398 vioif_workq_create(const char *, pri_t, int, int);
397static void vioif_workq_destroy(struct workqueue *); 399static void vioif_workq_destroy(struct workqueue *);
398static void vioif_workq_work(struct work *, void *); 400static void vioif_workq_work(struct work *, void *);
399static void vioif_work_set(struct vioif_work *, void(*)(void *), void *); 401static void vioif_work_set(struct vioif_work *, void(*)(void *), void *);
400static void vioif_work_add(struct workqueue *, struct vioif_work *); 402static void vioif_work_add(struct workqueue *, struct vioif_work *);
401static void vioif_work_wait(struct workqueue *, struct vioif_work *); 403static void vioif_work_wait(struct workqueue *, struct vioif_work *);
402 404
403/* other control */ 405/* other control */
404static bool vioif_is_link_up(struct vioif_softc *); 406static int vioif_get_link_status(struct vioif_softc *);
405static void vioif_update_link_status(struct vioif_softc *); 407static void vioif_update_link_status(struct vioif_softc *);
406static int vioif_ctrl_rx(struct vioif_softc *, int, bool); 408static int vioif_ctrl_rx(struct vioif_softc *, int, bool);
407static int vioif_set_promisc(struct vioif_softc *, bool); 409static int vioif_set_promisc(struct vioif_softc *, bool);
408static int vioif_set_allmulti(struct vioif_softc *, bool); 410static int vioif_set_allmulti(struct vioif_softc *, bool);
409static int vioif_set_rx_filter(struct vioif_softc *); 411static int vioif_set_rx_filter(struct vioif_softc *);
410static int vioif_rx_filter(struct vioif_softc *); 412static int vioif_rx_filter(struct vioif_softc *);
411static int vioif_set_mac_addr(struct vioif_softc *); 413static int vioif_set_mac_addr(struct vioif_softc *);
412static int vioif_ctrl_intr(void *); 414static int vioif_ctrl_intr(void *);
413static int vioif_config_change(struct virtio_softc *); 415static int vioif_config_change(struct virtio_softc *);
414static void vioif_ctl_softint(void *); 416static void vioif_ctl_softint(void *);
415static int vioif_ctrl_mq_vq_pairs_set(struct vioif_softc *, int); 417static int vioif_ctrl_mq_vq_pairs_set(struct vioif_softc *, int);
416static void vioif_enable_interrupt_vqpairs(struct vioif_softc *); 418static void vioif_enable_interrupt_vqpairs(struct vioif_softc *);
417static void vioif_disable_interrupt_vqpairs(struct vioif_softc *); 419static void vioif_disable_interrupt_vqpairs(struct vioif_softc *);
@@ -820,27 +822,27 @@ vioif_attach(device_t parent, device_t s @@ -820,27 +822,27 @@ vioif_attach(device_t parent, device_t s
820 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 822 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
821 u_int softint_flags; 823 u_int softint_flags;
822 int r, i, nvqs = 0, req_flags; 824 int r, i, nvqs = 0, req_flags;
823 char xnamebuf[MAXCOMLEN]; 825 char xnamebuf[MAXCOMLEN];
824 826
825 if (virtio_child(vsc) != NULL) { 827 if (virtio_child(vsc) != NULL) {
826 aprint_normal(": child already attached for %s; " 828 aprint_normal(": child already attached for %s; "
827 "something wrong...\n", device_xname(parent)); 829 "something wrong...\n", device_xname(parent));
828 return; 830 return;
829 } 831 }
830 832
831 sc->sc_dev = self; 833 sc->sc_dev = self;
832 sc->sc_virtio = vsc; 834 sc->sc_virtio = vsc;
833 sc->sc_link_active = false; 835 sc->sc_link_state = LINK_STATE_UNKNOWN;
834 836
835 sc->sc_max_nvq_pairs = 1; 837 sc->sc_max_nvq_pairs = 1;
836 sc->sc_req_nvq_pairs = 1; 838 sc->sc_req_nvq_pairs = 1;
837 sc->sc_act_nvq_pairs = 1; 839 sc->sc_act_nvq_pairs = 1;
838 sc->sc_txrx_workqueue_sysctl = true; 840 sc->sc_txrx_workqueue_sysctl = true;
839 sc->sc_tx_intr_process_limit = VIOIF_TX_INTR_PROCESS_LIMIT; 841 sc->sc_tx_intr_process_limit = VIOIF_TX_INTR_PROCESS_LIMIT;
840 sc->sc_tx_process_limit = VIOIF_TX_PROCESS_LIMIT; 842 sc->sc_tx_process_limit = VIOIF_TX_PROCESS_LIMIT;
841 sc->sc_rx_intr_process_limit = VIOIF_RX_INTR_PROCESS_LIMIT; 843 sc->sc_rx_intr_process_limit = VIOIF_RX_INTR_PROCESS_LIMIT;
842 sc->sc_rx_process_limit = VIOIF_RX_PROCESS_LIMIT; 844 sc->sc_rx_process_limit = VIOIF_RX_PROCESS_LIMIT;
843 845
844 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 846 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
845 847
846 snprintf(xnamebuf, sizeof(xnamebuf), "%s_txrx", device_xname(self)); 848 snprintf(xnamebuf, sizeof(xnamebuf), "%s_txrx", device_xname(self));
@@ -973,27 +975,27 @@ vioif_attach(device_t parent, device_t s @@ -973,27 +975,27 @@ vioif_attach(device_t parent, device_t s
973 aprint_error_dev(self, "cannot establish tx softint\n"); 975 aprint_error_dev(self, "cannot establish tx softint\n");
974 goto err; 976 goto err;
975 } 977 }
976 978
977 snprintf(qname, sizeof(qname), "tx%d", i); 979 snprintf(qname, sizeof(qname), "tx%d", i);
978 r = virtio_alloc_vq(vsc, txq->txq_vq, nvqs, 980 r = virtio_alloc_vq(vsc, txq->txq_vq, nvqs,
979 sc->sc_hdr_size + (ETHER_MAX_LEN - ETHER_HDR_LEN), 981 sc->sc_hdr_size + (ETHER_MAX_LEN - ETHER_HDR_LEN),
980 VIRTIO_NET_TX_MAXNSEGS + 1, qname); 982 VIRTIO_NET_TX_MAXNSEGS + 1, qname);
981 if (r != 0) 983 if (r != 0)
982 goto err; 984 goto err;
983 nvqs++; 985 nvqs++;
984 txq->txq_vq->vq_intrhand = vioif_tx_intr; 986 txq->txq_vq->vq_intrhand = vioif_tx_intr;
985 txq->txq_vq->vq_intrhand_arg = (void *)txq; 987 txq->txq_vq->vq_intrhand_arg = (void *)txq;
986 txq->txq_link_active = sc->sc_link_active; 988 txq->txq_link_active = VIOIF_IS_LINK_ACTIVE(sc);
987 txq->txq_stopping = false; 989 txq->txq_stopping = false;
988 txq->txq_intrq = pcq_create(txq->txq_vq->vq_num, KM_SLEEP); 990 txq->txq_intrq = pcq_create(txq->txq_vq->vq_num, KM_SLEEP);
989 vioif_work_set(&txq->txq_work, vioif_tx_handle, txq); 991 vioif_work_set(&txq->txq_work, vioif_tx_handle, txq);
990 } 992 }
991 993
992 if (sc->sc_has_ctrl) { 994 if (sc->sc_has_ctrl) {
993 /* 995 /*
994 * Allocating a virtqueue for control channel 996 * Allocating a virtqueue for control channel
995 */ 997 */
996 r = virtio_alloc_vq(vsc, ctrlq->ctrlq_vq, nvqs, 998 r = virtio_alloc_vq(vsc, ctrlq->ctrlq_vq, nvqs,
997 NBPG, 1, "control"); 999 NBPG, 1, "control");
998 if (r != 0) { 1000 if (r != 0) {
999 aprint_error_dev(self, "failed to allocate " 1001 aprint_error_dev(self, "failed to allocate "
@@ -1247,34 +1249,31 @@ vioif_stop(struct ifnet *ifp, int disabl @@ -1247,34 +1249,31 @@ vioif_stop(struct ifnet *ifp, int disabl
1247 mutex_exit(txq->txq_lock); 1249 mutex_exit(txq->txq_lock);
1248 vioif_work_wait(sc->sc_txrx_workqueue, &txq->txq_work); 1250 vioif_work_wait(sc->sc_txrx_workqueue, &txq->txq_work);
1249 } 1251 }
1250 1252
1251 /* only way to stop I/O and DMA is resetting... */ 1253 /* only way to stop I/O and DMA is resetting... */
1252 virtio_reset(vsc); 1254 virtio_reset(vsc);
1253 1255
1254 for (i = 0; i < sc->sc_act_nvq_pairs; i++) { 1256 for (i = 0; i < sc->sc_act_nvq_pairs; i++) {
1255 vioif_rx_queue_clear(&sc->sc_rxq[i]); 1257 vioif_rx_queue_clear(&sc->sc_rxq[i]);
1256 vioif_tx_queue_clear(&sc->sc_txq[i]); 1258 vioif_tx_queue_clear(&sc->sc_txq[i]);
1257 } 1259 }
1258 1260
1259 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 1261 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1260 sc->sc_link_active = false; 
1261 1262
1262 for (i = 0; i < sc->sc_act_nvq_pairs; i++) { 1263 for (i = 0; i < sc->sc_act_nvq_pairs; i++) {
1263 txq = &sc->sc_txq[i]; 1264 txq = &sc->sc_txq[i];
1264 rxq = &sc->sc_rxq[i]; 1265 rxq = &sc->sc_rxq[i];
1265 1266
1266 txq->txq_link_active = false; 
1267 
1268 if (disable) 1267 if (disable)
1269 vioif_rx_drain(rxq); 1268 vioif_rx_drain(rxq);
1270 1269
1271 vioif_tx_drain(txq); 1270 vioif_tx_drain(txq);
1272 } 1271 }
1273} 1272}
1274 1273
1275static void 1274static void
1276vioif_send_common_locked(struct ifnet *ifp, struct vioif_txqueue *txq, 1275vioif_send_common_locked(struct ifnet *ifp, struct vioif_txqueue *txq,
1277 bool is_transmit) 1276 bool is_transmit)
1278{ 1277{
1279 struct vioif_softc *sc = ifp->if_softc; 1278 struct vioif_softc *sc = ifp->if_softc;
1280 struct virtio_softc *vsc = sc->sc_virtio; 1279 struct virtio_softc *vsc = sc->sc_virtio;
@@ -2383,81 +2382,74 @@ vioif_rx_filter(struct vioif_softc *sc) @@ -2383,81 +2382,74 @@ vioif_rx_filter(struct vioif_softc *sc)
2383 ifp->if_xname); 2382 ifp->if_xname);
2384 /* what to do on failure? */ 2383 /* what to do on failure? */
2385 } 2384 }
2386 2385
2387 ifp->if_flags |= IFF_ALLMULTI; 2386 ifp->if_flags |= IFF_ALLMULTI;
2388 } 2387 }
2389 2388
2390set_ifflags: 2389set_ifflags:
2391 r = vioif_ifflags(sc); 2390 r = vioif_ifflags(sc);
2392 2391
2393 return r; 2392 return r;
2394} 2393}
2395 2394
2396static bool 2395static int
2397vioif_is_link_up(struct vioif_softc *sc) 2396vioif_get_link_status(struct vioif_softc *sc)
2398{ 2397{
2399 struct virtio_softc *vsc = sc->sc_virtio; 2398 struct virtio_softc *vsc = sc->sc_virtio;
2400 uint16_t status; 2399 uint16_t status;
2401 2400
2402 if (virtio_features(vsc) & VIRTIO_NET_F_STATUS) 2401 if (virtio_features(vsc) & VIRTIO_NET_F_STATUS)
2403 status = virtio_read_device_config_2(vsc, 2402 status = virtio_read_device_config_2(vsc,
2404 VIRTIO_NET_CONFIG_STATUS); 2403 VIRTIO_NET_CONFIG_STATUS);
2405 else 2404 else
2406 status = VIRTIO_NET_S_LINK_UP; 2405 status = VIRTIO_NET_S_LINK_UP;
2407 2406
2408 return ((status & VIRTIO_NET_S_LINK_UP) != 0); 2407 if ((status & VIRTIO_NET_S_LINK_UP) != 0)
 2408 return LINK_STATE_UP;
 2409
 2410 return LINK_STATE_DOWN;
2409} 2411}
2410 2412
2411/* change link status */ 2413/* change link status */
2412static void 2414static void
2413vioif_update_link_status(struct vioif_softc *sc) 2415vioif_update_link_status(struct vioif_softc *sc)
2414{ 2416{
2415 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 2417 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
2416 struct vioif_txqueue *txq; 2418 struct vioif_txqueue *txq;
2417 bool active, changed; 2419 bool active;
2418 int link, i; 2420 int link, i;
2419 2421
2420 mutex_enter(&sc->sc_lock); 2422 mutex_enter(&sc->sc_lock);
2421 2423
2422 active = vioif_is_link_up(sc); 2424 link = vioif_get_link_status(sc);
2423 changed = false; 
2424 2425
2425 if (active) { 2426 if (link == sc->sc_link_state)
2426 if (!sc->sc_link_active) 2427 goto done;
2427 changed = true; 
2428 2428
2429 link = LINK_STATE_UP; 2429 sc->sc_link_state = link;
2430 sc->sc_link_active = true; 
2431 } else { 
2432 if (sc->sc_link_active) 
2433 changed = true; 
2434 
2435 link = LINK_STATE_DOWN; 
2436 sc->sc_link_active = false; 
2437 } 
2438 2430
2439 if (changed) { 2431 active = VIOIF_IS_LINK_ACTIVE(sc);
2440 for (i = 0; i < sc->sc_act_nvq_pairs; i++) { 2432 for (i = 0; i < sc->sc_act_nvq_pairs; i++) {
2441 txq = &sc->sc_txq[i]; 2433 txq = &sc->sc_txq[i];
2442 
2443 mutex_enter(txq->txq_lock); 
2444 txq->txq_link_active = sc->sc_link_active; 
2445 mutex_exit(txq->txq_lock); 
2446 } 
2447 2434
2448 if_link_state_change(ifp, link); 2435 mutex_enter(txq->txq_lock);
 2436 txq->txq_link_active = active;
 2437 mutex_exit(txq->txq_lock);
2449 } 2438 }
2450 2439
 2440 if_link_state_change(ifp, sc->sc_link_state);
 2441
 2442done:
2451 mutex_exit(&sc->sc_lock); 2443 mutex_exit(&sc->sc_lock);
2452} 2444}
2453 2445
2454static int 2446static int
2455vioif_config_change(struct virtio_softc *vsc) 2447vioif_config_change(struct virtio_softc *vsc)
2456{ 2448{
2457 struct vioif_softc *sc = device_private(virtio_child(vsc)); 2449 struct vioif_softc *sc = device_private(virtio_child(vsc));
2458 2450
2459 softint_schedule(sc->sc_ctl_softint); 2451 softint_schedule(sc->sc_ctl_softint);
2460 return 0; 2452 return 0;
2461} 2453}
2462 2454
2463static void 2455static void