| 3724 | } |
| 3725 | |
| 3726 | static uint32_t |
| 3727 | iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx) |
| 3728 | { |
| 3729 | iflib_txq_t txq = r->cookie; |
| 3730 | if_ctx_t ctx = txq->ift_ctx; |
| 3731 | if_t ifp = ctx->ifc_ifp; |
| 3732 | struct mbuf *m, **mp; |
| 3733 | int avail, bytes_sent, skipped, count, err, i; |
| 3734 | int mcast_sent, pkt_sent, reclaimed; |
| 3735 | bool do_prefetch, rang, ring; |
| 3736 | |
| 3737 | if (__predict_false(!(if_getdrvflags(ifp) & IFF_DRV_RUNNING) || |
| 3738 | !LINK_ACTIVE(ctx))) { |
| 3739 | DBG_COUNTER_INC(txq_drain_notready); |
| 3740 | return (0); |
| 3741 | } |
| 3742 | reclaimed = iflib_completed_tx_reclaim(txq, RECLAIM_THRESH(ctx)); |
| 3743 | rang = iflib_txd_db_check(txq, reclaimed && txq->ift_db_pending); |
| 3744 | avail = IDXDIFF(pidx, cidx, r->size); |
| 3745 | |
| 3746 | if (__predict_false(ctx->ifc_flags & IFC_QFLUSH)) { |
| 3747 | /* |
| 3748 | * The driver is unloading so we need to free all pending packets. |
| 3749 | */ |
| 3750 | DBG_COUNTER_INC(txq_drain_flushing); |
| 3751 | for (i = 0; i < avail; i++) { |
| 3752 | if (__predict_true(r->items[(cidx + i) & (r->size-1)] != (void *)txq)) |
| 3753 | m_freem(r->items[(cidx + i) & (r->size-1)]); |
| 3754 | r->items[(cidx + i) & (r->size-1)] = NULL; |
| 3755 | } |
| 3756 | return (avail); |
| 3757 | } |
| 3758 | |
| 3759 | if (__predict_false(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_OACTIVE)) { |
| 3760 | txq->ift_qstatus = IFLIB_QUEUE_IDLE; |
| 3761 | CALLOUT_LOCK(txq); |
| 3762 | callout_stop(&txq->ift_timer); |
| 3763 | CALLOUT_UNLOCK(txq); |
| 3764 | DBG_COUNTER_INC(txq_drain_oactive); |
| 3765 | return (0); |
| 3766 | } |
| 3767 | |
| 3768 | /* |
| 3769 | * If we've reclaimed any packets this queue cannot be hung. |
| 3770 | */ |
| 3771 | if (reclaimed) |
| 3772 | txq->ift_qstatus = IFLIB_QUEUE_IDLE; |
| 3773 | skipped = mcast_sent = bytes_sent = pkt_sent = 0; |
| 3774 | count = MIN(avail, TX_BATCH_SIZE); |
| 3775 | #ifdef INVARIANTS |
| 3776 | if (iflib_verbose_debug) |
| 3777 | printf("%s avail=%d ifc_flags=%x txq_avail=%d ", __FUNCTION__, |
| 3778 | avail, ctx->ifc_flags, TXQ_AVAIL(txq)); |
| 3779 | #endif |
| 3780 | do_prefetch = (ctx->ifc_flags & IFC_PREFETCH); |
| 3781 | err = 0; |
| 3782 | for (i = 0; i < count && TXQ_AVAIL(txq) >= MAX_TX_DESC(ctx) + 2; i++) { |
| 3783 | int rem = do_prefetch ? count - i : 0; |
nothing calls this directly
no test coverage detected