diff --git a/sys/arch/arm/omap/if_cpsw.c b/sys/arch/arm/omap/if_cpsw.c index e377dd0..4930ac3 100644 --- a/sys/arch/arm/omap/if_cpsw.c +++ b/sys/arch/arm/omap/if_cpsw.c @@ -572,6 +572,7 @@ cpsw_attach(device_t parent, device_t self, void *aux) } if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->sc_enaddr); /* The attach is successful. */ @@ -1303,7 +1304,7 @@ next: ifp->if_timer = 0; if (handled) - cpsw_start(ifp); + if_schedule_deferred_start(ifp); return handled; } diff --git a/sys/arch/emips/ebus/if_le_ebus.c b/sys/arch/emips/ebus/if_le_ebus.c index 85ede58..3314b03 100644 --- a/sys/arch/emips/ebus/if_le_ebus.c +++ b/sys/arch/emips/ebus/if_le_ebus.c @@ -216,6 +216,7 @@ enic_attach(device_t parent, device_t self, void *aux) /* Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->sc_enaddr); sc->sc_sh = shutdownhook_establish(enic_shutdown, ifp); @@ -540,7 +541,7 @@ enic_init(struct ifnet *ifp) printf("enic_init <- %x\n",ctl); #endif - enic_start(ifp); + if_schedule_deferred_start(ifp); return 0; } @@ -819,7 +820,7 @@ void enic_tint(struct enic_softc *sc, uint32_t saf, paddr_t phys) ifp->if_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; - enic_start(ifp); + if_schedule_deferred_start(ifp); #if DEBUG sc->it = 1; #endif diff --git a/sys/arch/macppc/dev/if_bm.c b/sys/arch/macppc/dev/if_bm.c index 1c845a1..cffa51e4 100644 --- a/sys/arch/macppc/dev/if_bm.c +++ b/sys/arch/macppc/dev/if_bm.c @@ -260,6 +260,7 @@ bmac_attach(device_t parent, device_t self, void *aux) bmac_reset_chip(sc); if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->sc_enaddr); } @@ -441,7 +442,7 @@ bmac_intr(void *v) sc->sc_if.if_flags &= ~IFF_OACTIVE; sc->sc_if.if_timer = 0; sc->sc_if.if_opackets++; - bmac_start(&sc->sc_if); + if_schedule_deferred_start(&sc->sc_if); } /* XXX should do more! */ diff --git a/sys/arch/macppc/dev/if_gm.c b/sys/arch/macppc/dev/if_gm.c index 95518cc..8ceafd4 100644 --- a/sys/arch/macppc/dev/if_gm.c +++ b/sys/arch/macppc/dev/if_gm.c @@ -247,6 +247,7 @@ gmac_attach(device_t parent, device_t self, void *aux) ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO); if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, laddr); rnd_attach_source(&sc->sc_rnd_source, xname, RND_TYPE_NET, RND_FLAG_DEFAULT); @@ -343,7 +344,7 @@ gmac_tint(struct gmac_softc *sc) ifp->if_flags &= ~IFF_OACTIVE; ifp->if_timer = 0; - gmac_start(ifp); + if_schedule_deferred_start(ifp); } void diff --git a/sys/arch/mips/adm5120/dev/if_admsw.c b/sys/arch/mips/adm5120/dev/if_admsw.c index 0fac2e6..f7b9bf3 100644 --- a/sys/arch/mips/adm5120/dev/if_admsw.c +++ b/sys/arch/mips/adm5120/dev/if_admsw.c @@ -480,6 +480,7 @@ admsw_attach(device_t parent, device_t self, void *aux) /* Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, enaddr); enaddr[5]++; } @@ -886,7 +887,7 @@ admsw_txintr(struct admsw_softc *sc, int prio) ifp = &sc->sc_ethercom[0].ec_if; /* Try to queue more packets. */ - admsw_start(ifp); + if_schedule_deferred_start(ifp); /* * If there are no more pending transmissions, diff --git a/sys/arch/mips/alchemy/dev/if_aumac.c b/sys/arch/mips/alchemy/dev/if_aumac.c index 8be6234..1d9543d 100644 --- a/sys/arch/mips/alchemy/dev/if_aumac.c +++ b/sys/arch/mips/alchemy/dev/if_aumac.c @@ -338,6 +338,7 @@ aumac_attach(device_t parent, device_t self, void *aux) /* Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, enaddr); rnd_attach_source(&sc->rnd_source, device_xname(self), @@ -578,7 +579,7 @@ aumac_txintr(struct aumac_softc *sc) ifp->if_flags &= ~IFF_OACTIVE; /* Try to queue more packets. */ - aumac_start(ifp); + if_schedule_deferred_start(ifp); } if (pkts) diff --git a/sys/arch/mips/atheros/dev/if_ae.c b/sys/arch/mips/atheros/dev/if_ae.c index c55b13b..f3fd53e 100644 --- a/sys/arch/mips/atheros/dev/if_ae.c +++ b/sys/arch/mips/atheros/dev/if_ae.c @@ -383,6 +383,7 @@ ae_attach(device_t parent, device_t self, void *aux) * Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, enaddr); ether_set_ifflags_cb(&sc->sc_ethercom, ae_ifflags_cb); @@ -993,7 +994,7 @@ ae_intr(void *arg) } /* Try to get more packets going. */ - ae_start(ifp); + if_schedule_deferred_start(ifp); if (handled) rnd_add_uint32(&sc->sc_rnd_source, status); diff --git a/sys/arch/playstation2/dev/if_smap.c b/sys/arch/playstation2/dev/if_smap.c index f708454..41b9296 100644 --- a/sys/arch/playstation2/dev/if_smap.c +++ b/sys/arch/playstation2/dev/if_smap.c @@ -246,6 +246,7 @@ smap_attach(struct device *parent, struct device *self, void *aux) } if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, emac3->eaddr); spd_intr_establish(SPD_NIC, smap_intr, sc); @@ -321,8 +322,7 @@ smap_intr(void *arg) /* if transmission is pending, start here */ ifp = &sc->ethercom.ec_if; - if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) - smap_start(ifp); + if_schedule_deferred_start(ifp); rnd_add_uint32(&sc->rnd_source, cause | sc->tx_fifo_ptr << 16); return (1); diff --git a/sys/arch/powerpc/ibm4xx/dev/if_emac.c b/sys/arch/powerpc/ibm4xx/dev/if_emac.c index d33a1d3..2fda655 100644 --- a/sys/arch/powerpc/ibm4xx/dev/if_emac.c +++ b/sys/arch/powerpc/ibm4xx/dev/if_emac.c @@ -550,6 +550,7 @@ emac_attach(device_t parent, device_t self, void *aux) * Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, enaddr); #ifdef EMAC_EVENT_COUNTERS @@ -1559,7 +1560,7 @@ emac_txeob_intr(void *arg) handled |= emac_txreap(sc); /* try to get more packets going */ - emac_start(&sc->sc_ethercom.ec_if); + if_schedule_deferred_start(&sc->sc_ethercom.ec_if); return handled; } diff --git a/sys/arch/sgimips/hpc/if_sq.c b/sys/arch/sgimips/hpc/if_sq.c index 14afb1b..e2786ec 100644 --- a/sys/arch/sgimips/hpc/if_sq.c +++ b/sys/arch/sgimips/hpc/if_sq.c @@ -324,6 +324,7 @@ sq_attach(device_t parent, device_t self, void *aux) IFQ_SET_READY(&ifp->if_snd); if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->sc_enaddr); memset(&sc->sq_trace, 0, sizeof(sc->sq_trace)); @@ -1110,7 +1111,7 @@ sq_txintr(struct sq_softc *sc) ifp->if_timer = 0; SQ_TRACE(SQ_TXINTR_EXIT, sc, sc->sc_prevtx, status); - sq_start(ifp); + if_schedule_deferred_start(ifp); return 1; } diff --git a/sys/arch/sgimips/mace/if_mec.c b/sys/arch/sgimips/mace/if_mec.c index d35cb72..3cee66e 100644 --- a/sys/arch/sgimips/mace/if_mec.c +++ b/sys/arch/sgimips/mace/if_mec.c @@ -614,6 +614,7 @@ mec_attach(device_t parent, device_t self, void *aux) /* attach the interface */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->sc_enaddr); /* establish interrupt */ @@ -1607,9 +1608,9 @@ mec_intr(void *arg) } } - if (sent && !IFQ_IS_EMPTY(&ifp->if_snd)) { + if (sent) { /* try to get more packets going */ - mec_start(ifp); + if_schedule_deferred_start(ifp); } if (handled) diff --git a/sys/arch/sun2/dev/if_ec.c b/sys/arch/sun2/dev/if_ec.c index 9b6b6c2..1ff2dee 100644 --- a/sys/arch/sun2/dev/if_ec.c +++ b/sys/arch/sun2/dev/if_ec.c @@ -232,6 +232,7 @@ ec_attach(device_t parent, device_t self, void *aux) /* Now we can attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); idprom_etheraddr(myaddr); ether_ifattach(ifp, myaddr); aprint_normal_dev(self, "address %s\n", ether_sprintf(myaddr)); @@ -434,9 +435,7 @@ ec_intr(void *arg) sc->sc_ethercom.ec_if.if_opackets++; sc->sc_jammed = 0; ifp->if_flags &= ~IFF_OACTIVE; - IFQ_POLL(&ifp->if_snd, m0); - if (m0 != NULL) - ec_start(ifp); + if_schedule_deferred_start(ifp); } } else { @@ -656,9 +655,7 @@ ec_coll(struct ec_softc *sc) sc->sc_jammed = 1; sc->sc_colliding = 0; ifp->if_flags &= ~IFF_OACTIVE; - IFQ_POLL(&ifp->if_snd, m0); - if (m0 != NULL) - ec_start(ifp); + if_schedule_deferred_start(ifp); } else { jams = MAX(sc->sc_colliding, EC_BACKOFF_PRNG_COLL_MAX); sc->sc_backoff_seed = diff --git a/sys/arch/x86/pci/if_vmx.c b/sys/arch/x86/pci/if_vmx.c index b89f9ca..e9f9b42 100644 --- a/sys/arch/x86/pci/if_vmx.c +++ b/sys/arch/x86/pci/if_vmx.c @@ -1717,6 +1717,7 @@ vmxnet3_setup_interface(struct vmxnet3_softc *sc) ifmedia_set(&sc->vmx_media, IFM_ETHER|IFM_AUTO); if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->vmx_lladdr); ether_set_ifflags_cb(&sc->vmx_ethercom, vmxnet3_ifflags_cb); vmxnet3_link_status(sc); @@ -1747,7 +1748,7 @@ vmxnet3_evintr(struct vmxnet3_softc *sc) if (event & VMXNET3_EVENT_LINK) { vmxnet3_link_status(sc); if (sc->vmx_link_active != 0) - vmxnet3_start(&sc->vmx_ethercom.ec_if); + if_schedule_deferred_start(&sc->vmx_ethercom.ec_if); } if (event & (VMXNET3_EVENT_TQERROR | VMXNET3_EVENT_RQERROR)) { diff --git a/sys/dev/marvell/if_mvgbe.c b/sys/dev/marvell/if_mvgbe.c index 77b45f0..a411b3a 100644 --- a/sys/dev/marvell/if_mvgbe.c +++ b/sys/dev/marvell/if_mvgbe.c @@ -909,6 +909,7 @@ mvgbe_attach(device_t parent, device_t self, void *aux) * Call MI attach routines. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->sc_enaddr); ether_set_ifflags_cb(&sc->sc_ethercom, mvgbe_ifflags_cb); @@ -1050,8 +1051,7 @@ mvgbe_intr(void *arg) mvgbe_txeof(sc); } - if (!IFQ_IS_EMPTY(&ifp->if_snd)) - mvgbe_start(ifp); + if_schedule_deferred_start(ifp); rnd_add_uint32(&sc->sc_rnd_source, datum); diff --git a/sys/dev/marvell/if_mvxpe.c b/sys/dev/marvell/if_mvxpe.c index 5ce019d..a38515d 100644 --- a/sys/dev/marvell/if_mvxpe.c +++ b/sys/dev/marvell/if_mvxpe.c @@ -503,6 +503,7 @@ mvxpe_attach(device_t parent, device_t self, void *aux) * Call MI attach routines. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->sc_enaddr); ether_set_ifflags_cb(&sc->sc_ethercom, mvxpe_ifflags_cb); @@ -1479,8 +1480,7 @@ mvxpe_rxtxth_intr(void *arg) } mvxpe_sc_unlock(sc); - if (!IFQ_IS_EMPTY(&ifp->if_snd)) - mvxpe_start(ifp); + if_schedule_deferred_start(ifp); rnd_add_uint32(&sc->sc_rnd_source, datum); diff --git a/sys/dev/pci/if_age.c b/sys/dev/pci/if_age.c index 5a24574..67a29f2 100644 --- a/sys/dev/pci/if_age.c +++ b/sys/dev/pci/if_age.c @@ -285,6 +285,7 @@ age_attach(device_t parent, device_t self, void *aux) ifmedia_set(&sc->sc_miibus.mii_media, IFM_ETHER | IFM_AUTO); if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->sc_enaddr); if (pmf_device_register1(self, NULL, age_resume, age_shutdown)) @@ -535,7 +536,7 @@ age_intr(void *arg) age_init(ifp); } - age_start(ifp); + if_schedule_deferred_start(ifp); if (status & INTR_SMB) age_stats_update(sc); diff --git a/sys/dev/pci/if_alc.c b/sys/dev/pci/if_alc.c index d0be34b..a82f0ac 100644 --- a/sys/dev/pci/if_alc.c +++ b/sys/dev/pci/if_alc.c @@ -1466,6 +1466,7 @@ alc_attach(device_t parent, device_t self, void *aux) ifmedia_set(&sc->sc_miibus.mii_media, IFM_ETHER | IFM_AUTO); if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->alc_eaddr); if (!pmf_device_register(self, NULL, NULL)) @@ -2300,8 +2301,7 @@ alc_intr(void *arg) } alc_txeof(sc); - if (!IFQ_IS_EMPTY(&ifp->if_snd)) - alc_start(ifp); + if_schedule_deferred_start(ifp); } /* Re-enable interrupts. */ diff --git a/sys/dev/pci/if_bce.c b/sys/dev/pci/if_bce.c index 252d768..11cb818 100644 --- a/sys/dev/pci/if_bce.c +++ b/sys/dev/pci/if_bce.c @@ -445,6 +445,7 @@ bce_attach(device_t parent, device_t self, void *aux) /* Attach the interface */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); sc->enaddr[0] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET0); sc->enaddr[1] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, @@ -713,7 +714,7 @@ bce_intr(void *xsc) bce_init(ifp); rnd_add_uint32(&sc->rnd_source, intstatus); /* Try to get more packets going. */ - bce_start(ifp); + if_schedule_deferred_start(ifp); } return (handled); } diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c index d07a5fd..d855975 100644 --- a/sys/dev/pci/if_bge.c +++ b/sys/dev/pci/if_bge.c @@ -4061,6 +4061,7 @@ alloc_retry: */ DPRINTFN(5, ("if_attach\n")); if_attach(ifp); + if_deferred_start_init(ifp, NULL); DPRINTFN(5, ("ether_ifattach\n")); ether_ifattach(ifp, eaddr); ether_set_ifflags_cb(&sc->ethercom, bge_ifflags_cb); @@ -4788,8 +4789,8 @@ bge_intr(void *xsc) /* Re-enable interrupts. */ bge_writembx_flush(sc, BGE_MBX_IRQ0_LO, statustag); - if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd)) - bge_start(ifp); + if (ifp->if_flags & IFF_RUNNING) + if_schedule_deferred_start(ifp); return 1; } diff --git a/sys/dev/pci/if_bnx.c b/sys/dev/pci/if_bnx.c index a51490c..0f20423 100644 --- a/sys/dev/pci/if_bnx.c +++ b/sys/dev/pci/if_bnx.c @@ -846,6 +846,7 @@ bnx_attach(device_t parent, device_t self, void *aux) /* Attach to the Ethernet interface list. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp,sc->eaddr); callout_init(&sc->bnx_timeout, 0); @@ -5384,8 +5385,7 @@ bnx_intr(void *xsc) BNX_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx); /* Handle any frames that arrived while handling the interrupt. */ - if (!IFQ_IS_EMPTY(&ifp->if_snd)) - bnx_start(ifp); + if_schedule_deferred_start(ifp); return 1; } diff --git a/sys/dev/pci/if_cas.c b/sys/dev/pci/if_cas.c index de3b20b..84f1213 100644 --- a/sys/dev/pci/if_cas.c +++ b/sys/dev/pci/if_cas.c @@ -609,6 +609,7 @@ cas_config(struct cas_softc *sc, const uint8_t *enaddr) /* Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, enaddr); rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), @@ -2016,7 +2017,7 @@ cas_tint(struct cas_softc *sc, u_int32_t status) if (sc->sc_tx_cnt == 0) ifp->if_timer = 0; - cas_start(ifp); + if_schedule_deferred_start(ifp); return (1); } diff --git a/sys/dev/pci/if_de.c b/sys/dev/pci/if_de.c index eb8ef36..8faf1c2 100644 --- a/sys/dev/pci/if_de.c +++ b/sys/dev/pci/if_de.c @@ -4111,7 +4111,7 @@ tulip_intr_handler( if (sc->tulip_flags & (TULIP_WANTTXSTART|TULIP_TXPROBE_ACTIVE|TULIP_DOINGSETUP|TULIP_PROMISC)) { tulip_tx_intr(sc); if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0) - tulip_ifstart(&sc->tulip_if); + if_schedule_deferred_start(&sc->tulip_if); } } if (sc->tulip_flags & TULIP_NEEDRESET) { @@ -5136,6 +5136,7 @@ tulip_attach( TULIP_ETHER_IFATTACH(sc); #else if_attach(ifp); + if_deferred_start_init(ifp, NULL); #if defined(__NetBSD__) || (defined(__FreeBSD__) && BSD >= 199506) TULIP_ETHER_IFATTACH(sc); #endif diff --git a/sys/dev/pci/if_dge.c b/sys/dev/pci/if_dge.c index b39a27b..5341eeb 100644 --- a/sys/dev/pci/if_dge.c +++ b/sys/dev/pci/if_dge.c @@ -943,6 +943,7 @@ dge_attach(device_t parent, device_t self, void *aux) * Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, enaddr); rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), RND_TYPE_NET, RND_FLAG_DEFAULT); @@ -1578,7 +1579,7 @@ dge_intr(void *arg) dge_init(ifp); /* Try to get more packets going. */ - dge_start(ifp); + if_schedule_deferred_start(ifp); } return (handled); diff --git a/sys/dev/pci/if_et.c b/sys/dev/pci/if_et.c index a9ff3e8..021d85b 100644 --- a/sys/dev/pci/if_et.c +++ b/sys/dev/pci/if_et.c @@ -284,6 +284,7 @@ et_attach(device_t parent, device_t self, void *aux) ifmedia_set(&sc->sc_miibus.mii_media, IFM_ETHER | IFM_AUTO); if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->sc_enaddr); callout_init(&sc->sc_tick, 0); @@ -1971,7 +1972,7 @@ et_txeof(struct et_softc *sc) if (tbd->tbd_used + ET_NSEG_SPARE <= ET_TX_NDESC) ifp->if_flags &= ~IFF_OACTIVE; - et_start(ifp); + if_schedule_deferred_start(ifp); } void diff --git a/sys/dev/pci/if_ipw.c b/sys/dev/pci/if_ipw.c index 72d526b..0c0a6e4 100644 --- a/sys/dev/pci/if_ipw.c +++ b/sys/dev/pci/if_ipw.c @@ -297,6 +297,7 @@ ipw_attach(device_t parent, device_t self, void *aux) ether_sprintf(ic->ic_myaddr)); if_attach(ifp); + if_deferred_start_init(ifp, NULL); ieee80211_ifattach(ic); /* override state transition machine */ @@ -1215,7 +1216,7 @@ ipw_tx_intr(struct ipw_softc *sc) /* Call start() since some buffer descriptors have been released */ ifp->if_flags &= ~IFF_OACTIVE; - (*ifp->if_start)(ifp); + if_schedule_deferred_start(ifp); } static int diff --git a/sys/dev/pci/if_iwi.c b/sys/dev/pci/if_iwi.c index 7576f0a..c8a578f 100644 --- a/sys/dev/pci/if_iwi.c +++ b/sys/dev/pci/if_iwi.c @@ -355,6 +355,7 @@ iwi_attach(device_t parent, device_t self, void *aux) memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); if_attach(ifp); + if_deferred_start_init(ifp, NULL); ieee80211_ifattach(ic); /* override default methods */ ic->ic_node_alloc = iwi_node_alloc; @@ -1444,7 +1445,7 @@ iwi_tx_intr(struct iwi_softc *sc, struct iwi_tx_ring *txq) ifp->if_flags &= ~IFF_OACTIVE; /* Call start() since some buffer descriptors have been released */ - (*ifp->if_start)(ifp); + if_schedule_deferred_start(ifp); } static int diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c index ac404f3..9b6d665 100644 --- a/sys/dev/pci/if_iwm.c +++ b/sys/dev/pci/if_iwm.c @@ -3330,7 +3330,7 @@ iwm_mvm_rx_tx_cmd(struct iwm_softc *sc, * I guess net80211 does all sorts of stunts in * interrupt context, so maybe this is no biggie. */ - (*ifp->if_start)(ifp); + if_schedule_deferred_start(ifp); } } } @@ -6831,9 +6831,10 @@ iwm_attach(device_t parent, device_t self, void *aux) #else ether_ifattach(ifp, ic->ic_myaddr); /* XXX */ #endif - if_register(ifp); /* Use common softint-based if_input */ ifp->if_percpuq = if_percpuq_create(ifp); + if_deferred_start_init(ifp, NULL); + if_register(ifp); callout_init(&sc->sc_calib_to, 0); callout_setfunc(&sc->sc_calib_to, iwm_calib_timeout, sc); diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c index 3d20ba9..db65d3e 100644 --- a/sys/dev/pci/if_iwn.c +++ b/sys/dev/pci/if_iwn.c @@ -593,6 +593,7 @@ iwn_attach(device_t parent __unused, device_t self, void *aux) memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); if_attach(ifp); + if_deferred_start_init(ifp, NULL); ieee80211_ifattach(ic); ic->ic_node_alloc = iwn_node_alloc; ic->ic_newassoc = iwn_newassoc; @@ -2341,7 +2342,7 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt, sc->qfullmsk &= ~(1 << ring->qid); if (sc->qfullmsk == 0 && (ifp->if_flags & IFF_OACTIVE)) { ifp->if_flags &= ~IFF_OACTIVE; - (*ifp->if_start)(ifp); + if_schedule_deferred_start(ifp); } } } diff --git a/sys/dev/pci/if_lii.c b/sys/dev/pci/if_lii.c index b4e3f76..659dc25 100644 --- a/sys/dev/pci/if_lii.c +++ b/sys/dev/pci/if_lii.c @@ -336,6 +336,7 @@ lii_attach(device_t parent, device_t self, void *aux) sc->sc_ec.ec_capabilities = ETHERCAP_VLAN_MTU; if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, eaddr); if (pmf_device_register(self, NULL, NULL)) @@ -1048,7 +1049,7 @@ lii_txintr(struct lii_softc *sc) } if (sc->sc_free_tx_slots) - lii_start(ifp); + if_schedule_deferred_start(ifp); } static int diff --git a/sys/dev/pci/if_msk.c b/sys/dev/pci/if_msk.c index 309ecea..dc39e3b 100644 --- a/sys/dev/pci/if_msk.c +++ b/sys/dev/pci/if_msk.c @@ -1135,6 +1135,7 @@ msk_attach(device_t parent, device_t self, void *aux) * Call MI attach routines. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc_if->sk_enaddr); if (pmf_device_register(self, NULL, msk_resume)) @@ -1972,10 +1973,10 @@ msk_intr(void *xsc) CSR_WRITE_4(sc, SK_Y2_ICR, 2); - if (ifp0 != NULL && !IFQ_IS_EMPTY(&ifp0->if_snd)) - msk_start(ifp0); - if (ifp1 != NULL && !IFQ_IS_EMPTY(&ifp1->if_snd)) - msk_start(ifp1); + if (ifp0 != NULL) + if_schedule_deferred_start(ifp0); + if (ifp1 != NULL) + if_schedule_deferred_start(ifp1); rnd_add_uint32(&sc->rnd_source, status); diff --git a/sys/dev/pci/if_nfe.c b/sys/dev/pci/if_nfe.c index d7c1ca6..6b43729 100644 --- a/sys/dev/pci/if_nfe.c +++ b/sys/dev/pci/if_nfe.c @@ -409,6 +409,7 @@ nfe_attach(device_t parent, device_t self, void *aux) ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO); if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->sc_enaddr); ether_set_ifflags_cb(&sc->sc_ethercom, nfe_ifflags_cb); @@ -631,8 +632,8 @@ nfe_intr(void *arg) } } - if (handled && !IF_IS_EMPTY(&ifp->if_snd)) - nfe_start(ifp); + if (handled) + if_schedule_deferred_start(ifp); return handled; } diff --git a/sys/dev/pci/if_pcn.c b/sys/dev/pci/if_pcn.c index 7a8499f..c662efd 100644 --- a/sys/dev/pci/if_pcn.c +++ b/sys/dev/pci/if_pcn.c @@ -812,6 +812,7 @@ pcn_attach(device_t parent, device_t self, void *aux) /* Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, enaddr); rnd_attach_source(&sc->rnd_source, device_xname(self), RND_TYPE_NET, RND_FLAG_DEFAULT); @@ -1288,7 +1289,7 @@ pcn_intr(void *arg) pcn_init(ifp); /* Try to get more packets going. */ - pcn_start(ifp); + if_schedule_deferred_start(ifp); } return (handled); diff --git a/sys/dev/pci/if_rtwn.c b/sys/dev/pci/if_rtwn.c index f6d00d7..148977d 100644 --- a/sys/dev/pci/if_rtwn.c +++ b/sys/dev/pci/if_rtwn.c @@ -357,9 +357,10 @@ rtwn_attach(device_t parent, device_t self, void *aux) if_initialize(ifp); ieee80211_ifattach(ic); - if_register(ifp); /* Use common softint-based if_input */ ifp->if_percpuq = if_percpuq_create(ifp); + ifp->if_deferred_start = if_deferred_start_create(ifp, NULL); + if_register(ifp); /* override default methods */ ic->ic_newassoc = rtwn_newassoc; @@ -3519,7 +3520,7 @@ rtwn_intr(void *xsc) if ((status & RTWN_INT_ENABLE_TX) && sc->qfullmsk == 0) { struct ifnet *ifp = GET_IFP(sc); ifp->if_flags &= ~IFF_OACTIVE; - rtwn_start(ifp); + if_schedule_deferred_start(ifp); } /* Enable interrupts. */ diff --git a/sys/dev/pci/if_sip.c b/sys/dev/pci/if_sip.c index d587ad7..ad2734e 100644 --- a/sys/dev/pci/if_sip.c +++ b/sys/dev/pci/if_sip.c @@ -1283,6 +1283,7 @@ sipcom_attach(device_t parent, device_t self, void *aux) * Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, enaddr); ether_set_ifflags_cb(&sc->sc_ethercom, sip_ifflags_cb); sc->sc_prev.ec_capenable = sc->sc_ethercom.ec_capenable; @@ -1952,7 +1953,7 @@ sipcom_intr(void *arg) bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IER, IER_IE); /* Try to get more packets going. */ - sipcom_start(ifp); + if_schedule_deferred_start(ifp); return (handled); } diff --git a/sys/dev/pci/if_sk.c b/sys/dev/pci/if_sk.c index cc43889..291533a 100644 --- a/sys/dev/pci/if_sk.c +++ b/sys/dev/pci/if_sk.c @@ -1458,6 +1458,7 @@ sk_attach(device_t parent, device_t self, void *aux) * Call MI attach routines. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc_if->sk_enaddr); @@ -2397,10 +2398,10 @@ sk_intr(void *xsc) CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask); - if (ifp0 != NULL && !IFQ_IS_EMPTY(&ifp0->if_snd)) - sk_start(ifp0); - if (ifp1 != NULL && !IFQ_IS_EMPTY(&ifp1->if_snd)) - sk_start(ifp1); + if (ifp0 != NULL) + if_schedule_deferred_start(ifp0); + if (ifp1 != NULL) + if_schedule_deferred_start(ifp1); rnd_add_uint32(&sc->rnd_source, status); diff --git a/sys/dev/pci/if_ste.c b/sys/dev/pci/if_ste.c index 1159fe6..f2fd198 100644 --- a/sys/dev/pci/if_ste.c +++ b/sys/dev/pci/if_ste.c @@ -505,6 +505,7 @@ ste_attach(device_t parent, device_t self, void *aux) * Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, enaddr); /* @@ -912,7 +913,7 @@ ste_intr(void *arg) sc->sc_IntEnable); /* Try to get more packets going. */ - ste_start(ifp); + if_schedule_deferred_start(ifp); return (1); } diff --git a/sys/dev/pci/if_stge.c b/sys/dev/pci/if_stge.c index 4f5d189..b5c6b58 100644 --- a/sys/dev/pci/if_stge.c +++ b/sys/dev/pci/if_stge.c @@ -658,6 +658,7 @@ stge_attach(device_t parent, device_t self, void *aux) * Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, enaddr); #ifdef STGE_EVENT_COUNTERS @@ -1141,7 +1142,7 @@ stge_intr(void *arg) sc->sc_IntEnable); /* Try to get more packets going. */ - stge_start(ifp); + if_schedule_deferred_start(ifp); return (1); } diff --git a/sys/dev/pci/if_ti.c b/sys/dev/pci/if_ti.c index 317ed3c..b2d8df7 100644 --- a/sys/dev/pci/if_ti.c +++ b/sys/dev/pci/if_ti.c @@ -1866,6 +1866,7 @@ ti_attach(device_t parent, device_t self, void *aux) * Call MI attach routines. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, eaddr); /* @@ -2180,9 +2181,8 @@ ti_intr(void *xsc) /* Re-enable interrupts. */ CSR_WRITE_4(sc, TI_MB_HOSTINTR, 0); - if ((ifp->if_flags & IFF_RUNNING) != 0 && - IFQ_IS_EMPTY(&ifp->if_snd) == 0) - ti_start(ifp); + if ((ifp->if_flags & IFF_RUNNING) != 0) + if_schedule_deferred_start(ifp); return (1); } diff --git a/sys/dev/pci/if_txp.c b/sys/dev/pci/if_txp.c index b74c108..14ef3a8 100644 --- a/sys/dev/pci/if_txp.c +++ b/sys/dev/pci/if_txp.c @@ -343,6 +343,7 @@ txp_attach(device_t parent, device_t self, void *aux) * Attach us everywhere */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, enaddr); if (pmf_device_register1(self, NULL, NULL, txp_shutdown)) @@ -652,7 +653,7 @@ txp_intr(void *vsc) /* unmask all interrupts */ WRITE_REG(sc, TXP_IMR, TXP_INT_A2H_3); - txp_start(&sc->sc_arpcom.ec_if); + if_schedule_deferred_start(&sc->sc_arpcom.ec_if); return (claimed); } diff --git a/sys/dev/pci/if_vge.c b/sys/dev/pci/if_vge.c index 206ac68..990c0c4 100644 --- a/sys/dev/pci/if_vge.c +++ b/sys/dev/pci/if_vge.c @@ -1067,6 +1067,7 @@ vge_attach(device_t parent, device_t self, void *aux) * Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, eaddr); ether_set_ifflags_cb(&sc->sc_ethercom, vge_ifflags_cb); @@ -1529,8 +1530,8 @@ vge_intr(void *arg) /* Re-enable interrupts */ CSR_WRITE_1(sc, VGE_CRS3, VGE_CR3_INT_GMSK); - if (claim && !IFQ_IS_EMPTY(&ifp->if_snd)) - vge_start(ifp); + if (claim) + if_schedule_deferred_start(ifp); return claim; } diff --git a/sys/dev/pci/if_vioif.c b/sys/dev/pci/if_vioif.c index ed89412..c2568a2 100644 --- a/sys/dev/pci/if_vioif.c +++ b/sys/dev/pci/if_vioif.c @@ -672,6 +672,7 @@ skip: sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->sc_mac); return; @@ -1130,7 +1131,7 @@ vioif_tx_vq_done(struct virtqueue *vq) out: VIOIF_TX_UNLOCK(sc); if (r) - vioif_start(ifp); + if_schedule_deferred_start(ifp); return r; } diff --git a/sys/dev/pci/if_vr.c b/sys/dev/pci/if_vr.c index 331f28b..4dd82e5 100644 --- a/sys/dev/pci/if_vr.c +++ b/sys/dev/pci/if_vr.c @@ -987,7 +987,7 @@ vr_intr(void *arg) CSR_WRITE_2(sc, VR_IMR, VR_INTRS); if (dotx) - vr_start(ifp); + if_schedule_deferred_start(ifp); return (handled); } @@ -1745,6 +1745,7 @@ vr_attach(device_t parent, device_t self, void *aux) * Call MI attach routines. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, sc->vr_enaddr); rnd_attach_source(&sc->rnd_source, device_xname(self), diff --git a/sys/dev/pci/if_wm.c b/sys/dev/pci/if_wm.c index 1fdc9ae..49e28f8 100644 --- a/sys/dev/pci/if_wm.c +++ b/sys/dev/pci/if_wm.c @@ -696,6 +696,7 @@ static void wm_nq_start_locked(struct ifnet *); static int wm_nq_transmit(struct ifnet *, struct mbuf *); static void wm_nq_transmit_locked(struct ifnet *, struct wm_txqueue *); static void wm_nq_send_common_locked(struct ifnet *, struct wm_txqueue *, bool); +static void wm_deferred_start(struct ifnet *); /* Interrupt */ static int wm_txeof(struct wm_softc *, struct wm_txqueue *); static void wm_rxeof(struct wm_rxqueue *); @@ -1612,6 +1613,7 @@ wm_attach(device_t parent, device_t self, void *aux) bool force_clear_smbi; uint32_t link_mode; uint32_t reg; + void (*deferred_start_func)(struct ifnet *) = NULL; sc->sc_dev = self; callout_init(&sc->sc_tick_ch, CALLOUT_FLAGS); @@ -2514,12 +2516,16 @@ alloc_retry: ifp->if_ioctl = wm_ioctl; if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) { ifp->if_start = wm_nq_start; - if (sc->sc_nqueues > 1) + if (sc->sc_nqueues > 1) { ifp->if_transmit = wm_nq_transmit; + deferred_start_func = wm_deferred_start; + } } else { ifp->if_start = wm_start; - if (sc->sc_nqueues > 1) + if (sc->sc_nqueues > 1) { ifp->if_transmit = wm_transmit; + deferred_start_func = wm_deferred_start; + } } ifp->if_watchdog = wm_watchdog; ifp->if_init = wm_init; @@ -2620,6 +2626,7 @@ alloc_retry: /* Attach the interface. */ if_initialize(ifp); sc->sc_ipq = if_percpuq_create(&sc->sc_ethercom.ec_if); + if_deferred_start_init(ifp, deferred_start_func); ether_ifattach(ifp, enaddr); if_register(ifp); ether_set_ifflags_cb(&sc->sc_ethercom, wm_ifflags_cb); @@ -7245,6 +7252,53 @@ wm_nq_send_common_locked(struct ifnet *ifp, struct wm_txqueue *txq, } } +static void +wm_deferred_start(struct ifnet *ifp) +{ + struct wm_softc *sc = ifp->if_softc; + int qid = 0; + + /* + * Try to transmit on all Tx queues. Passing a txq somehow and + * transmitting only on the txq may be better. + */ +restart: + WM_CORE_LOCK(sc); + if (sc->sc_core_stopping) + goto out; + + for (; qid < sc->sc_nqueues; qid++) { + struct wm_txqueue *txq = &sc->sc_queue[qid].wmq_txq; + + if (!mutex_tryenter(txq->txq_lock)) + continue; + + if (txq->txq_stopping) { + mutex_exit(txq->txq_lock); + continue; + } + WM_CORE_UNLOCK(sc); + + if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) { + /* XXX need for ALTQ */ + if (qid == 0) + wm_nq_start_locked(ifp); + wm_nq_transmit_locked(ifp, txq); + } else { + /* XXX need for ALTQ */ + if (qid == 0) + wm_start_locked(ifp); + wm_transmit_locked(ifp, txq); + } + mutex_exit(txq->txq_lock); + + qid++; + goto restart; + } +out: + WM_CORE_UNLOCK(sc); +} + /* Interrupt */ /* @@ -7926,7 +7980,7 @@ wm_intr_legacy(void *arg) if (handled) { /* Try to get more packets going. */ - ifp->if_start(ifp); + if_schedule_deferred_start(ifp); } return handled; @@ -7965,15 +8019,13 @@ wm_txrxintr_msix(void *arg) /* Try to get more packets going. */ if (pcq_peek(txq->txq_interq) != NULL) - wm_nq_transmit_locked(ifp, txq); + if_schedule_deferred_start(ifp); /* * There are still some upper layer processing which call * ifp->if_start(). e.g. ALTQ */ - if (wmq->wmq_id == 0) { - if (!IFQ_IS_EMPTY(&ifp->if_snd)) - wm_nq_start_locked(ifp); - } + if (wmq->wmq_id == 0) + if_schedule_deferred_start(ifp); mutex_exit(txq->txq_lock); diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c index cabe7bf..b8a510b 100644 --- a/sys/dev/pci/if_wpi.c +++ b/sys/dev/pci/if_wpi.c @@ -359,6 +359,7 @@ wpi_attach(device_t parent __unused, device_t self, void *aux) memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); if_attach(ifp); + if_deferred_start_init(ifp, NULL); ieee80211_ifattach(ic); /* override default methods */ ic->ic_node_alloc = wpi_node_alloc; @@ -1630,7 +1631,7 @@ wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc) sc->sc_tx_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; - wpi_start(ifp); + if_schedule_deferred_start(ifp); } static void diff --git a/sys/dev/pci/if_xge.c b/sys/dev/pci/if_xge.c index 27acb76..18477a4 100644 --- a/sys/dev/pci/if_xge.c +++ b/sys/dev/pci/if_xge.c @@ -553,6 +553,7 @@ xge_attach(device_t parent, device_t self, void *aux) * Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, enaddr); /* @@ -750,7 +751,7 @@ xge_intr(void *pv) if (sc->sc_lasttx != lasttx) ifp->if_flags &= ~IFF_OACTIVE; - xge_start(ifp); /* Try to get more packets on the wire */ + if_schedule_deferred_start(ifp); /* Try to get more packets on the wire */ if ((val = PIF_RCSR(RX_TRAFFIC_INT))) { XGE_EVCNT_INCR(&sc->sc_rxintr); diff --git a/sys/dev/pcmcia/if_cnw.c b/sys/dev/pcmcia/if_cnw.c index 355a2f0..d7b5d20 100644 --- a/sys/dev/pcmcia/if_cnw.c +++ b/sys/dev/pcmcia/if_cnw.c @@ -558,6 +558,7 @@ cnw_attach(device_t parent, device_t self, void *aux) /* Attach the interface */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, macaddr); sc->sc_resource |= CNW_RES_NET; @@ -975,7 +976,7 @@ cnw_intr(void *arg) ifp->if_flags &= ~IFF_OACTIVE; /* Continue to send packets from the queue */ - cnw_start(&sc->sc_ethercom.ec_if); + if_schedule_deferred_start(&sc->sc_ethercom.ec_if); } } diff --git a/sys/dev/pcmcia/if_malo_pcmcia.c b/sys/dev/pcmcia/if_malo_pcmcia.c index b0d2b77..bfd46a0 100644 --- a/sys/dev/pcmcia/if_malo_pcmcia.c +++ b/sys/dev/pcmcia/if_malo_pcmcia.c @@ -356,6 +356,7 @@ cmalo_attach(void *arg) /* attach interface */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ieee80211_ifattach(ic); sc->sc_newstate = ic->ic_newstate; @@ -1070,7 +1071,7 @@ cmalo_tx_done(struct malo_softc *sc) ifp->if_opackets++; ifp->if_flags &= ~IFF_OACTIVE; ifp->if_timer = 0; - cmalo_start(ifp); + if_schedule_deferred_start(ifp); } static void diff --git a/sys/dev/pcmcia/if_xi.c b/sys/dev/pcmcia/if_xi.c index d3b177a..66b06c1 100644 --- a/sys/dev/pcmcia/if_xi.c +++ b/sys/dev/pcmcia/if_xi.c @@ -219,6 +219,7 @@ xi_attach(struct xi_softc *sc, u_int8_t *myea) /* Attach the interface. */ if_attach(ifp); + if_deferred_start_init(ifp, NULL); ether_ifattach(ifp, myea); /* @@ -360,8 +361,7 @@ xi_intr(void *arg) } /* Try to start more packets transmitting. */ - if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) - xi_start(ifp); + if_schedule_deferred_start(ifp); /* Detected excessive collisions? */ if ((tx_status & EXCESSIVE_COLL) && ifp->if_opackets > 0) { diff --git a/sys/net/if.c b/sys/net/if.c index c9c1bfd..1894640 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -223,6 +223,16 @@ static int sysctl_percpuq_drops_handler(SYSCTLFN_PROTO); static void sysctl_percpuq_setup(struct sysctllog **, const char *, struct if_percpuq *); +struct if_deferred_start { + struct ifnet *ids_ifp; + void (*ids_if_start)(struct ifnet *); + void *ids_si; +}; + +static void if_deferred_start_softint(void *); +static void if_deferred_start_common(struct ifnet *); +static void if_deferred_start_destroy(struct ifnet *); + #if defined(INET) || defined(INET6) static void sysctl_net_pktq_setup(struct sysctllog **, int); #endif @@ -953,6 +963,99 @@ bad: return; } +/* + * The deferred if_start framework + * + * The common APIs to defer if_start to softint when if_start is requested + * from a device driver running in hardware interrupt context. + */ +/* + * Call ifp->if_start (or equivalent) in a dedicated softint for + * deferred if_start. + */ +static void +if_deferred_start_softint(void *arg) +{ + struct if_deferred_start *ids = arg; + struct ifnet *ifp = ids->ids_ifp; + +#ifdef DEBUG + log(LOG_DEBUG, "%s: deferred start on %s\n", __func__, + ifp->if_xname); +#endif + + ids->ids_if_start(ifp); +} + +/* + * The default callback function for deferred if_start. + */ +static void +if_deferred_start_common(struct ifnet *ifp) +{ + + if_start_lock(ifp); +} + +static inline bool +if_snd_is_used(struct ifnet *ifp) +{ + + return ifp->if_transmit == NULL || ifp->if_transmit == if_nulltransmit || + ALTQ_IS_ENABLED(&ifp->if_snd); +} + +/* + * Schedule deferred if_start. + */ +void +if_schedule_deferred_start(struct ifnet *ifp) +{ + + KASSERT(ifp->if_deferred_start != NULL); + + if (if_snd_is_used(ifp) && IFQ_IS_EMPTY(&ifp->if_snd)) + return; + + softint_schedule(ifp->if_deferred_start->ids_si); +} + +/* + * Create an instance of deferred if_start. A driver should call the function + * only if the driver needs deferred if_start. Drivers can setup their own + * deferred if_start function via 2nd argument. + */ +void +if_deferred_start_init(struct ifnet *ifp, void (*func)(struct ifnet *)) +{ + struct if_deferred_start *ids; + + ids = kmem_zalloc(sizeof(*ids), KM_SLEEP); + if (ids == NULL) + panic("kmem_zalloc failed"); + + ids->ids_ifp = ifp; + ids->ids_si = softint_establish(SOFTINT_NET|SOFTINT_MPSAFE, + if_deferred_start_softint, ids); + if (func != NULL) + ids->ids_if_start = func; + else + ids->ids_if_start = if_deferred_start_common; + + ifp->if_deferred_start = ids; +} + +static void +if_deferred_start_destroy(struct ifnet *ifp) +{ + + if (ifp->if_deferred_start == NULL) + return; + + softint_disestablish(ifp->if_deferred_start->ids_si); + kmem_free(ifp->if_deferred_start, sizeof(*ifp->if_deferred_start)); + ifp->if_deferred_start = NULL; +} /* * The common interface input routine that is called by device drivers, @@ -1194,6 +1297,7 @@ if_detach(struct ifnet *ifp) callout_destroy(ifp->if_slowtimo_ch); kmem_free(ifp->if_slowtimo_ch, sizeof(*ifp->if_slowtimo_ch)); } + if_deferred_start_destroy(ifp); /* * Do an if_down() to give protocols a chance to do something. diff --git a/sys/net/if.h b/sys/net/if.h index 0599d1e..fd1b259 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -230,6 +230,7 @@ struct bridge_iflist; struct callout; struct krwlock; struct if_percpuq; +struct if_deferred_start; typedef unsigned short if_index_t; @@ -342,6 +343,7 @@ typedef struct ifnet { struct pslist_entry if_pslist_entry; struct psref_target if_psref; struct pslist_head if_addr_pslist; + struct if_deferred_start *if_deferred_start; #endif } ifnet_t; @@ -989,6 +991,9 @@ void if_percpuq_destroy(struct if_percpuq *); void if_percpuq_enqueue(struct if_percpuq *, struct mbuf *); +void if_deferred_start_init(struct ifnet *, void (*)(struct ifnet *)); +void if_schedule_deferred_start(struct ifnet *); + void ifa_insert(struct ifnet *, struct ifaddr *); void ifa_remove(struct ifnet *, struct ifaddr *);