/* ** Multiqueue Transmit driver ** */ int ixl_mq_start(struct ifnet *ifp, struct mbuf *m) { struct ixl_vsi *vsi = ifp->if_softc; struct ixl_queue *que; struct tx_ring *txr; int err, i; /* Which queue to use */ if ((m->m_flags & M_FLOWID) != 0) i = m->m_pkthdr.flowid % vsi->num_queues; else i = curcpu % vsi->num_queues; /* Check for a hung queue and pick alternative */ if (((1 << i) & vsi->active_queues) == 0) i = ffsl(vsi->active_queues); que = &vsi->queues[i]; txr = &que->txr; err = drbr_enqueue(ifp, txr->br, m); if (err) return(err); if (IXL_TX_TRYLOCK(txr)) { ixl_mq_start_locked(ifp, txr); IXL_TX_UNLOCK(txr); } else taskqueue_enqueue(que->tq, &que->tx_task); return (0); }
static int nicvf_if_transmit(struct ifnet *ifp, struct mbuf *mbuf) { struct nicvf *nic = if_getsoftc(ifp); struct queue_set *qs = nic->qs; struct snd_queue *sq; struct mbuf *mtmp; int qidx; int err = 0; if (__predict_false(qs == NULL)) { panic("%s: missing queue set for %s", __func__, device_get_nameunit(nic->dev)); } /* Select queue */ if (M_HASHTYPE_GET(mbuf) != M_HASHTYPE_NONE) qidx = mbuf->m_pkthdr.flowid % qs->sq_cnt; else qidx = curcpu % qs->sq_cnt; sq = &qs->sq[qidx]; if (mbuf->m_next != NULL && (mbuf->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_SCTP)) != 0) { if (M_WRITABLE(mbuf) == 0) { mtmp = m_dup(mbuf, M_NOWAIT); m_freem(mbuf); if (mtmp == NULL) return (ENOBUFS); mbuf = mtmp; } } err = drbr_enqueue(ifp, sq->br, mbuf); if (((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) || !nic->link_up || (err != 0)) { /* * Try to enqueue packet to the ring buffer. * If the driver is not active, link down or enqueue operation * failed, return with the appropriate error code. */ return (err); } if (NICVF_TX_TRYLOCK(sq) != 0) { err = nicvf_xmit_locked(sq); NICVF_TX_UNLOCK(sq); return (err); } else taskqueue_enqueue(sq->snd_taskq, &sq->snd_task); return (0); }