From: Sepherosa Ziehau Date: Sun, 13 Jan 2013 09:10:32 +0000 (+0800) Subject: if: Multiple TX queue support step 2 of many X-Git-Tag: v3.4.0rc~508 X-Git-Url: https://gitweb.dragonflybsd.org/~tuxillo/dragonfly.git/commitdiff_plain/3c4cd924641f7b338d83dfbd07947615c61f0c12 if: Multiple TX queue support step 2 of many ifnet_{serialize,deserialize,tryserialize}_tx and hardware TX serializer asserion macros now require subqueue, so the proper hardware TX queue's serializer could be held, released and asserted. --- diff --git a/sys/net/altq/altq_cbq.c b/sys/net/altq/altq_cbq.c index f0e52a3172..24c221275f 100644 --- a/sys/net/altq/altq_cbq.c +++ b/sys/net/altq/altq_cbq.c @@ -614,10 +614,10 @@ cbqrestart(struct ifaltq *ifq) /* Release the altq lock to avoid deadlock */ CBQ_UNLOCK(ifq); - ifnet_serialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); if (ifp->if_start && !ifsq_is_oactive(ifsq)) (*ifp->if_start)(ifp, ifsq); - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); CBQ_LOCK(ifq); } diff --git a/sys/net/altq/altq_subr.c b/sys/net/altq/altq_subr.c index 864f513b27..9cd3cf6ff1 100644 --- a/sys/net/altq/altq_subr.c +++ b/sys/net/altq/altq_subr.c @@ -342,16 +342,17 @@ tbr_timeout(void *arg) active = 0; crit_enter(); for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) { - struct ifaltq_subque *ifsq = - &ifp->if_snd.altq_subq[ALTQ_SUBQ_INDEX_DEFAULT]; + struct ifaltq_subque *ifsq; if (ifp->if_snd.altq_tbr == NULL) continue; + + ifsq = &ifp->if_snd.altq_subq[ALTQ_SUBQ_INDEX_DEFAULT]; active++; if (!ifsq_is_empty(ifsq) && ifp->if_start != NULL) { - ifnet_serialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); (*ifp->if_start)(ifp, ifsq); - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); } } crit_exit(); diff --git a/sys/net/bridge/if_bridge.c b/sys/net/bridge/if_bridge.c index 1389b33bd3..3faaae0e65 100644 --- a/sys/net/bridge/if_bridge.c +++ b/sys/net/bridge/if_bridge.c @@ -2302,7 +2302,7 @@ bridge_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) struct bridge_softc *sc = ifp->if_softc; ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - ASSERT_IFNET_SERIALIZED_TX(ifp); + ASSERT_IFNET_SERIALIZED_TX(ifp, ifsq); ifsq_set_oactive(ifsq); for (;;) { diff --git a/sys/net/gif/if_gif.c b/sys/net/gif/if_gif.c index 636c27bfac..c0ce39c411 100644 --- a/sys/net/gif/if_gif.c +++ b/sys/net/gif/if_gif.c @@ -395,11 +395,12 @@ int gif_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { + const struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); int error; - ifnet_serialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); error = gif_output_serialized(ifp, m, dst, rt); - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); return error; } diff --git a/sys/net/gre/if_gre.c b/sys/net/gre/if_gre.c index 88287b659b..73431a54ec 100644 --- a/sys/net/gre/if_gre.c +++ b/sys/net/gre/if_gre.c @@ -399,11 +399,12 @@ static int gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { + const struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); int error; - ifnet_serialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); error = gre_output_serialized(ifp, m, dst, rt); - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); return error; } diff --git a/sys/net/if.c b/sys/net/if.c index f20b1c0af0..ee4f4b09c7 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -332,14 +332,14 @@ ifsq_ifstart_dispatch(netmsg_t msg) return; } - ifnet_serialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); if ((ifp->if_flags & IFF_RUNNING) && !ifsq_is_oactive(ifsq)) { ifp->if_start(ifp, ifsq); if ((ifp->if_flags & IFF_RUNNING) && !ifsq_is_oactive(ifsq)) running = 1; } need_sched = ifsq_ifstart_need_schedule(ifsq, running); - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); if (need_sched) { /* @@ -358,7 +358,7 @@ ifsq_devstart(struct ifaltq_subque *ifsq) struct ifnet *ifp = ifsq_get_ifp(ifsq); int running = 0; - ASSERT_IFNET_SERIALIZED_TX(ifp); + ASSERT_IFNET_SERIALIZED_TX(ifp, ifsq); ALTQ_SQ_LOCK(ifsq); if (ifsq_is_started(ifsq) || !ifsq_data_ready(ifsq)) { @@ -2508,7 +2508,7 @@ ifsq_ifstart_try(struct ifaltq_subque *ifsq, int force_sched) * contention on ifnet's serializer, ifnet.if_start will * be scheduled on ifnet's CPU. */ - if (!ifnet_tryserialize_tx(ifp)) { + if (!ifnet_tryserialize_tx(ifp, ifsq)) { /* * ifnet serializer contention happened, * ifnet.if_start is scheduled on ifnet's @@ -2525,7 +2525,7 @@ ifsq_ifstart_try(struct ifaltq_subque *ifsq, int force_sched) } need_sched = ifsq_ifstart_need_schedule(ifsq, running); - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); if (need_sched) { /* @@ -2585,7 +2585,7 @@ ifq_dispatch(struct ifnet *ifp, struct mbuf *m, struct altq_pktattr *pa) /* TODO find qid here */ ifsq = &ifq->altq_subq[qid]; - ASSERT_IFNET_NOT_SERIALIZED_TX(ifp); + ASSERT_IFNET_NOT_SERIALIZED_TX(ifp, ifsq); len = m->m_pkthdr.len; if (m->m_flags & M_MCAST) diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c index b90bbce1ec..2599182e27 100644 --- a/sys/net/if_loop.c +++ b/sys/net/if_loop.c @@ -226,10 +226,8 @@ rel: * a simplex interface). */ if (ifq_is_enabled(&ifp->if_snd) && ifp->if_start == lo_altqstart) { - struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); struct altq_pktattr pktattr; int32_t *afp; - int error; /* * if the queueing discipline needs packet classification, @@ -243,18 +241,7 @@ rel: afp = mtod(m, int32_t *); *afp = (int32_t)af; - /* - * A critical section is needed for subsystems protected by - * the MP lock, and the serializer is assumed to already - * be held for MPSAFE subsystems. - */ - crit_enter(); - error = ifsq_enqueue(ifsq, m, &pktattr); - ifnet_serialize_tx(ifp); - ifp->if_start(ifp, ifsq); - ifnet_deserialize_tx(ifp); - crit_exit(); - return (error); + return ifq_dispatch(ifp, m, &pktattr); } #endif /* ALTQ */ diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 5ec5b512bf..4fc3bc9d01 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -138,7 +138,7 @@ enum ifnet_serialize { IFNET_SERIALIZE_TX_BASE = 0x10000000, IFNET_SERIALIZE_RX_BASE = 0x20000000 }; -#define IFNET_SERIALIZE_TX IFNET_SERIALIZE_TX_BASE +#define IFNET_SERIALIZE_TX(i) (IFNET_SERIALIZE_TX_BASE + (i)) #define IFNET_SERIALIZE_RX(i) (IFNET_SERIALIZE_RX_BASE + (i)) #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES) @@ -362,10 +362,12 @@ EVENTHANDLER_DECLARE(iflladdr_event, iflladdr_event_handler_t); #define ASSERT_IFNET_NOT_SERIALIZED_ALL(ifp) \ (ifp)->if_serialize_assert((ifp), IFNET_SERIALIZE_ALL, FALSE) -#define ASSERT_IFNET_SERIALIZED_TX(ifp) \ - (ifp)->if_serialize_assert((ifp), IFNET_SERIALIZE_TX, TRUE) -#define ASSERT_IFNET_NOT_SERIALIZED_TX(ifp) \ - (ifp)->if_serialize_assert((ifp), IFNET_SERIALIZE_TX, FALSE) +#define ASSERT_IFNET_SERIALIZED_TX(ifp, ifsq) \ + (ifp)->if_serialize_assert((ifp), \ + IFNET_SERIALIZE_TX((ifsq)->ifsq_index), TRUE) +#define ASSERT_IFNET_NOT_SERIALIZED_TX(ifp, ifsq) \ + (ifp)->if_serialize_assert((ifp), \ + IFNET_SERIALIZE_TX((ifsq)->ifsq_index), FALSE) #define ASSERT_IFNET_SERIALIZED_MAIN(ifp) \ (ifp)->if_serialize_assert((ifp), IFNET_SERIALIZE_MAIN, TRUE) @@ -374,8 +376,8 @@ EVENTHANDLER_DECLARE(iflladdr_event, iflladdr_event_handler_t); #else #define ASSERT_IFNET_SERIALIZED_ALL(ifp) ((void)0) #define ASSERT_IFNET_NOT_SERIALIZED_ALL(ifp) ((void)0) -#define ASSERT_IFNET_SERIALIZED_TX(ifp) ((void)0) -#define ASSERT_IFNET_NOT_SERIALIZED_TX(ifp) ((void)0) +#define ASSERT_IFNET_SERIALIZED_TX(ifp, ifsq) ((void)0) +#define ASSERT_IFNET_NOT_SERIALIZED_TX(ifp, ifsq) ((void)0) #define ASSERT_IFNET_SERIALIZED_MAIN(ifp) ((void)0) #define ASSERT_IFNET_NOT_SERIALIZED_MAIN(ifp) ((void)0) #endif @@ -399,21 +401,22 @@ ifnet_tryserialize_all(struct ifnet *_ifp) } static __inline void -ifnet_serialize_tx(struct ifnet *_ifp) +ifnet_serialize_tx(struct ifnet *_ifp, const struct ifaltq_subque *_ifsq) { - _ifp->if_serialize(_ifp, IFNET_SERIALIZE_TX); + _ifp->if_serialize(_ifp, IFNET_SERIALIZE_TX(_ifsq->ifsq_index)); } static __inline void -ifnet_deserialize_tx(struct ifnet *_ifp) +ifnet_deserialize_tx(struct ifnet *_ifp, const struct ifaltq_subque *_ifsq) { - _ifp->if_deserialize(_ifp, IFNET_SERIALIZE_TX); + _ifp->if_deserialize(_ifp, IFNET_SERIALIZE_TX(_ifsq->ifsq_index)); } static __inline int -ifnet_tryserialize_tx(struct ifnet *_ifp) +ifnet_tryserialize_tx(struct ifnet *_ifp, const struct ifaltq_subque *_ifsq) { - return _ifp->if_tryserialize(_ifp, IFNET_SERIALIZE_TX); + return _ifp->if_tryserialize(_ifp, + IFNET_SERIALIZE_TX(_ifsq->ifsq_index)); } static __inline void diff --git a/sys/net/ifq_var.h b/sys/net/ifq_var.h index d6c1e55991..bd9f908b02 100644 --- a/sys/net/ifq_var.h +++ b/sys/net/ifq_var.h @@ -357,7 +357,7 @@ ifq_handoff(struct ifnet *_ifp, struct mbuf *_m, struct altq_pktattr *_pa) _ifsq = &_ifp->if_snd.altq_subq[_qid]; - ASSERT_IFNET_SERIALIZED_TX(_ifp); + ASSERT_IFNET_SERIALIZED_TX(_ifp, _ifsq); _error = ifsq_enqueue(_ifsq, _m, _pa); if (_error == 0) { _ifp->if_obytes += _m->m_pkthdr.len; diff --git a/sys/net/ppp/if_ppp.c b/sys/net/ppp/if_ppp.c index c9119b2fff..66b1404132 100644 --- a/sys/net/ppp/if_ppp.c +++ b/sys/net/ppp/if_ppp.c @@ -711,8 +711,8 @@ pppsioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) * Called at splnet from pppwrite(). */ static int -pppoutput_serialized(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, - struct rtentry *rtp) +pppoutput_serialized(struct ifnet *ifp, struct ifaltq_subque *ifsq, + struct mbuf *m0, struct sockaddr *dst, struct rtentry *rtp) { struct ppp_softc *sc = &ppp_softc[ifp->if_dunit]; int protocol, address, control; @@ -877,9 +877,8 @@ pppoutput_serialized(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, error = 0; } } else { - ASSERT_IFNET_SERIALIZED_TX(&sc->sc_if); - error = ifsq_enqueue(ifq_get_subq_default(&sc->sc_if.if_snd), m0, - &pktattr); + ASSERT_IFNET_SERIALIZED_TX(&sc->sc_if, ifsq); + error = ifsq_enqueue(ifsq, m0, &pktattr); } if (error) { crit_exit(); @@ -905,11 +904,12 @@ int pppoutput(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, struct rtentry *rtp) { + struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); int error; - ifnet_serialize_tx(ifp); - error = pppoutput_serialized(ifp, m0, dst, rtp); - ifnet_deserialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); + error = pppoutput_serialized(ifp, ifsq, m0, dst, rtp); + ifnet_deserialize_tx(ifp, ifsq); return error; } diff --git a/sys/net/sl/if_sl.c b/sys/net/sl/if_sl.c index 1e97b95a83..766806c814 100644 --- a/sys/net/sl/if_sl.c +++ b/sys/net/sl/if_sl.c @@ -459,8 +459,8 @@ sltioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct ucred *cred) * ordering gets trashed. It can be done for all packets in slstart. */ static int -sloutput_serialized(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, - struct rtentry *rtp) +sloutput_serialized(struct ifnet *ifp, struct ifaltq_subque *ifsq, + struct mbuf *m, struct sockaddr *dst, struct rtentry *rtp) { struct sl_softc *sc = &sl_softc[ifp->if_dunit]; struct ip *ip; @@ -507,8 +507,7 @@ sloutput_serialized(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, error = 0; } } else { - error = ifsq_enqueue(ifq_get_subq_default(&sc->sc_if.if_snd), - m, &pktattr); + error = ifsq_enqueue(ifsq, m, &pktattr); } if (error) { sc->sc_if.if_oerrors++; @@ -525,11 +524,12 @@ static int sloutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rtp) { + struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); int error; - ifnet_serialize_tx(ifp); - error = sloutput_serialized(ifp, m, dst, rtp); - ifnet_deserialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); + error = sloutput_serialized(ifp, ifsq, m, dst, rtp); + ifnet_deserialize_tx(ifp, ifsq); return error; } diff --git a/sys/net/sppp/if_spppsubr.c b/sys/net/sppp/if_spppsubr.c index aa0ee3f45a..6e915dcdbb 100644 --- a/sys/net/sppp/if_spppsubr.c +++ b/sys/net/sppp/if_spppsubr.c @@ -722,11 +722,10 @@ drop2: * Enqueue transmit packet. */ static int -sppp_output_serialized(struct ifnet *ifp, struct mbuf *m, - struct sockaddr *dst, struct rtentry *rt) +sppp_output_serialized(struct ifnet *ifp, struct ifaltq_subque *ifsq, + struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { struct sppp *sp = (struct sppp*) ifp; - struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); struct ppp_header *h; struct ifqueue *ifq = NULL; int rv = 0; @@ -976,11 +975,12 @@ static int sppp_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { + struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); int error; - ifnet_serialize_tx(ifp); - error = sppp_output_serialized(ifp, m, dst, rt); - ifnet_deserialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); + error = sppp_output_serialized(ifp, ifsq, m, dst, rt); + ifnet_deserialize_tx(ifp, ifsq); return error; } diff --git a/sys/net/stf/if_stf.c b/sys/net/stf/if_stf.c index 7a8256ffab..b957ec3571 100644 --- a/sys/net/stf/if_stf.c +++ b/sys/net/stf/if_stf.c @@ -421,11 +421,12 @@ static int stf_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { + const struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); int error; - ifnet_serialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); error = stf_output_serialized(ifp, m, dst, rt); - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); return error; } diff --git a/sys/net/tun/if_tun.c b/sys/net/tun/if_tun.c index 94f686145a..0846c623a7 100644 --- a/sys/net/tun/if_tun.c +++ b/sys/net/tun/if_tun.c @@ -803,8 +803,8 @@ tunstart(struct ifnet *ifp, struct ifaltq_subque *ifsq) } if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) pgsigio(tp->tun_sigio, SIGIO, 0); - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); KNOTE(&tp->tun_rkq.ki_note, 0); - ifnet_serialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); } } diff --git a/sys/net/vlan/if_vlan.c b/sys/net/vlan/if_vlan.c index ba2e2ec710..0e291ef5f7 100644 --- a/sys/net/vlan/if_vlan.c +++ b/sys/net/vlan/if_vlan.c @@ -505,7 +505,7 @@ vlan_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) lwkt_port_t p_port; ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - ASSERT_IFNET_SERIALIZED_TX(ifp); + ASSERT_IFNET_SERIALIZED_TX(ifp, ifsq); if (ifp_p == NULL) { ifsq_purge(ifsq); diff --git a/sys/netgraph/fec/ng_fec.c b/sys/netgraph/fec/ng_fec.c index 2c6d1c1132..925ea9bb5e 100644 --- a/sys/netgraph/fec/ng_fec.c +++ b/sys/netgraph/fec/ng_fec.c @@ -842,11 +842,12 @@ static int ng_fec_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt0) { + const struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); int error; - ifnet_serialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); error = ng_fec_output_serialized(ifp, m, dst, rt0); - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); return error; } diff --git a/sys/netgraph/iface/ng_iface.c b/sys/netgraph/iface/ng_iface.c index 0040cfa0a7..988ad916d2 100644 --- a/sys/netgraph/iface/ng_iface.c +++ b/sys/netgraph/iface/ng_iface.c @@ -461,11 +461,12 @@ static int ng_iface_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt0) { + const struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); int error; - ifnet_serialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); error = ng_iface_output_serialized(ifp, m, dst, rt0); - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); return error; } diff --git a/sys/netgraph7/ng_fec.c b/sys/netgraph7/ng_fec.c index 90cee84c23..97c9c51bbb 100644 --- a/sys/netgraph7/ng_fec.c +++ b/sys/netgraph7/ng_fec.c @@ -1112,7 +1112,7 @@ ng_fec_choose_port(struct ng_fec_bundle *b, * transmission. */ static void -ng_fec_start(struct ifnet *ifp, struct ifaltq_subque *ifsq __unused) +ng_fec_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) { struct ng_fec_private *priv; struct ng_fec_bundle *b; @@ -1139,9 +1139,9 @@ ng_fec_start(struct ifnet *ifp, struct ifaltq_subque *ifsq __unused) } ifp->if_opackets++; - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); error = ifq_dispatch(oifp, m0, NULL); - ifnet_serialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); priv->if_error = error; } diff --git a/sys/netproto/atm/atm_if.c b/sys/netproto/atm/atm_if.c index 6804716352..2243c0e2b2 100644 --- a/sys/netproto/atm/atm_if.c +++ b/sys/netproto/atm/atm_if.c @@ -972,11 +972,12 @@ int atm_ifoutput(struct ifnet *ifp, KBuffer *m, struct sockaddr *dst, struct rtentry *rt) { + const struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); int error; - ifnet_serialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); error = atm_ifoutput_serialized(ifp, m, dst, rt); - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); return error; } diff --git a/sys/netproto/ipx/ipx_ip.c b/sys/netproto/ipx/ipx_ip.c index d73686cadb..613a41bad1 100644 --- a/sys/netproto/ipx/ipx_ip.c +++ b/sys/netproto/ipx/ipx_ip.c @@ -60,6 +60,7 @@ #include #include +#include #include #include @@ -292,11 +293,12 @@ static int ipxipoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { + const struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); int error; - ifnet_serialize_tx(ifp); + ifnet_serialize_tx(ifp, ifsq); error = ipxipoutput_serialized(ifp, m, dst, rt); - ifnet_deserialize_tx(ifp); + ifnet_deserialize_tx(ifp, ifsq); return error; }