ionic: rework and simplify handling of the queue stats block

Use a block of stats structs attached to the lif instead of
little ones attached to each qcq.  This simplifies our memory
management and gets rid of a lot of unnecessary indirection.

Signed-off-by: Shannon Nelson <snelson@pensando.io>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Shannon Nelson 2020-08-27 16:00:23 -07:00 committed by David S. Miller
parent 30b87ab4c0
commit 34dec947b9
5 changed files with 91 additions and 148 deletions

View File

@ -454,7 +454,7 @@ static int ionic_set_coalesce(struct net_device *netdev,
if (test_bit(IONIC_LIF_F_UP, lif->state)) {
for (i = 0; i < lif->nxqs; i++) {
qcq = lif->rxqcqs[i].qcq;
qcq = lif->rxqcqs[i];
ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
qcq->intr.index,
lif->rx_coalesce_hw);
@ -471,7 +471,7 @@ static int ionic_set_coalesce(struct net_device *netdev,
if (test_bit(IONIC_LIF_F_UP, lif->state)) {
for (i = 0; i < lif->nxqs; i++) {
qcq = lif->txqcqs[i].qcq;
qcq = lif->txqcqs[i];
ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
qcq->intr.index,
lif->tx_coalesce_hw);

View File

@ -327,7 +327,6 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
static void ionic_qcqs_free(struct ionic_lif *lif)
{
struct device *dev = lif->ionic->dev;
unsigned int i;
if (lif->notifyqcq) {
ionic_qcq_free(lif, lif->notifyqcq);
@ -340,17 +339,15 @@ static void ionic_qcqs_free(struct ionic_lif *lif)
}
if (lif->rxqcqs) {
for (i = 0; i < lif->nxqs; i++)
if (lif->rxqcqs[i].stats)
devm_kfree(dev, lif->rxqcqs[i].stats);
devm_kfree(dev, lif->rxqstats);
lif->rxqstats = NULL;
devm_kfree(dev, lif->rxqcqs);
lif->rxqcqs = NULL;
}
if (lif->txqcqs) {
for (i = 0; i < lif->nxqs; i++)
if (lif->txqcqs[i].stats)
devm_kfree(dev, lif->txqcqs[i].stats);
devm_kfree(dev, lif->txqstats);
lif->txqstats = NULL;
devm_kfree(dev, lif->txqcqs);
lif->txqcqs = NULL;
}
@ -524,7 +521,6 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif)
struct device *dev = lif->ionic->dev;
unsigned int flags;
int err;
int i;
flags = IONIC_QCQ_F_INTR;
err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags,
@ -544,7 +540,7 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif)
sizeof(union ionic_notifyq_comp),
0, lif->kern_pid, &lif->notifyqcq);
if (err)
goto err_out_free_adminqcq;
goto err_out;
ionic_debugfs_add_qcq(lif, lif->notifyqcq);
/* Let the notifyq ride on the adminq interrupt */
@ -553,52 +549,27 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif)
err = -ENOMEM;
lif->txqcqs = devm_kcalloc(dev, lif->ionic->ntxqs_per_lif,
sizeof(*lif->txqcqs), GFP_KERNEL);
sizeof(struct ionic_qcq *), GFP_KERNEL);
if (!lif->txqcqs)
goto err_out_free_notifyqcq;
for (i = 0; i < lif->nxqs; i++) {
lif->txqcqs[i].stats = devm_kzalloc(dev,
sizeof(struct ionic_q_stats),
GFP_KERNEL);
if (!lif->txqcqs[i].stats)
goto err_out_free_tx_stats;
}
goto err_out;
lif->rxqcqs = devm_kcalloc(dev, lif->ionic->nrxqs_per_lif,
sizeof(*lif->rxqcqs), GFP_KERNEL);
sizeof(struct ionic_qcq *), GFP_KERNEL);
if (!lif->rxqcqs)
goto err_out_free_tx_stats;
for (i = 0; i < lif->nxqs; i++) {
lif->rxqcqs[i].stats = devm_kzalloc(dev,
sizeof(struct ionic_q_stats),
GFP_KERNEL);
if (!lif->rxqcqs[i].stats)
goto err_out_free_rx_stats;
}
goto err_out;
lif->txqstats = devm_kcalloc(dev, lif->ionic->ntxqs_per_lif,
sizeof(struct ionic_tx_stats), GFP_KERNEL);
if (!lif->txqstats)
goto err_out;
lif->rxqstats = devm_kcalloc(dev, lif->ionic->nrxqs_per_lif,
sizeof(struct ionic_rx_stats), GFP_KERNEL);
if (!lif->rxqstats)
goto err_out;
return 0;
err_out_free_rx_stats:
for (i = 0; i < lif->nxqs; i++)
if (lif->rxqcqs[i].stats)
devm_kfree(dev, lif->rxqcqs[i].stats);
devm_kfree(dev, lif->rxqcqs);
lif->rxqcqs = NULL;
err_out_free_tx_stats:
for (i = 0; i < lif->nxqs; i++)
if (lif->txqcqs[i].stats)
devm_kfree(dev, lif->txqcqs[i].stats);
devm_kfree(dev, lif->txqcqs);
lif->txqcqs = NULL;
err_out_free_notifyqcq:
if (lif->notifyqcq) {
ionic_qcq_free(lif, lif->notifyqcq);
lif->notifyqcq = NULL;
}
err_out_free_adminqcq:
ionic_qcq_free(lif, lif->adminqcq);
lif->adminqcq = NULL;
err_out:
ionic_qcqs_free(lif);
return err;
}
@ -630,7 +601,7 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
intr_index = qcq->intr.index;
else
intr_index = lif->rxqcqs[q->index].qcq->intr.index;
intr_index = lif->rxqcqs[q->index]->intr.index;
ctx.cmd.q_init.intr_index = cpu_to_le16(intr_index);
dev_dbg(dev, "txq_init.pid %d\n", ctx.cmd.q_init.pid);
@ -1483,7 +1454,7 @@ static void ionic_txrx_disable(struct ionic_lif *lif)
if (lif->txqcqs) {
for (i = 0; i < lif->nxqs; i++) {
err = ionic_qcq_disable(lif->txqcqs[i].qcq);
err = ionic_qcq_disable(lif->txqcqs[i]);
if (err == -ETIMEDOUT)
break;
}
@ -1491,7 +1462,7 @@ static void ionic_txrx_disable(struct ionic_lif *lif)
if (lif->rxqcqs) {
for (i = 0; i < lif->nxqs; i++) {
err = ionic_qcq_disable(lif->rxqcqs[i].qcq);
err = ionic_qcq_disable(lif->rxqcqs[i]);
if (err == -ETIMEDOUT)
break;
}
@ -1504,17 +1475,17 @@ static void ionic_txrx_deinit(struct ionic_lif *lif)
if (lif->txqcqs) {
for (i = 0; i < lif->nxqs; i++) {
ionic_lif_qcq_deinit(lif, lif->txqcqs[i].qcq);
ionic_tx_flush(&lif->txqcqs[i].qcq->cq);
ionic_tx_empty(&lif->txqcqs[i].qcq->q);
ionic_lif_qcq_deinit(lif, lif->txqcqs[i]);
ionic_tx_flush(&lif->txqcqs[i]->cq);
ionic_tx_empty(&lif->txqcqs[i]->q);
}
}
if (lif->rxqcqs) {
for (i = 0; i < lif->nxqs; i++) {
ionic_lif_qcq_deinit(lif, lif->rxqcqs[i].qcq);
ionic_rx_flush(&lif->rxqcqs[i].qcq->cq);
ionic_rx_empty(&lif->rxqcqs[i].qcq->q);
ionic_lif_qcq_deinit(lif, lif->rxqcqs[i]);
ionic_rx_flush(&lif->rxqcqs[i]->cq);
ionic_rx_empty(&lif->rxqcqs[i]->q);
}
}
lif->rx_mode = 0;
@ -1526,15 +1497,15 @@ static void ionic_txrx_free(struct ionic_lif *lif)
if (lif->txqcqs) {
for (i = 0; i < lif->nxqs; i++) {
ionic_qcq_free(lif, lif->txqcqs[i].qcq);
lif->txqcqs[i].qcq = NULL;
ionic_qcq_free(lif, lif->txqcqs[i]);
lif->txqcqs[i] = NULL;
}
}
if (lif->rxqcqs) {
for (i = 0; i < lif->nxqs; i++) {
ionic_qcq_free(lif, lif->rxqcqs[i].qcq);
lif->rxqcqs[i].qcq = NULL;
ionic_qcq_free(lif, lif->rxqcqs[i]);
lif->rxqcqs[i] = NULL;
}
}
}
@ -1562,17 +1533,16 @@ static int ionic_txrx_alloc(struct ionic_lif *lif)
sizeof(struct ionic_txq_desc),
sizeof(struct ionic_txq_comp),
sg_desc_sz,
lif->kern_pid, &lif->txqcqs[i].qcq);
lif->kern_pid, &lif->txqcqs[i]);
if (err)
goto err_out;
if (flags & IONIC_QCQ_F_INTR)
ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
lif->txqcqs[i].qcq->intr.index,
lif->txqcqs[i]->intr.index,
lif->tx_coalesce_hw);
lif->txqcqs[i].qcq->stats = lif->txqcqs[i].stats;
ionic_debugfs_add_qcq(lif, lif->txqcqs[i].qcq);
ionic_debugfs_add_qcq(lif, lif->txqcqs[i]);
}
flags = IONIC_QCQ_F_RX_STATS | IONIC_QCQ_F_SG | IONIC_QCQ_F_INTR;
@ -1582,20 +1552,19 @@ static int ionic_txrx_alloc(struct ionic_lif *lif)
sizeof(struct ionic_rxq_desc),
sizeof(struct ionic_rxq_comp),
sizeof(struct ionic_rxq_sg_desc),
lif->kern_pid, &lif->rxqcqs[i].qcq);
lif->kern_pid, &lif->rxqcqs[i]);
if (err)
goto err_out;
ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
lif->rxqcqs[i].qcq->intr.index,
lif->rxqcqs[i]->intr.index,
lif->rx_coalesce_hw);
if (!test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
ionic_link_qcq_interrupts(lif->rxqcqs[i].qcq,
lif->txqcqs[i].qcq);
ionic_link_qcq_interrupts(lif->rxqcqs[i],
lif->txqcqs[i]);
lif->rxqcqs[i].qcq->stats = lif->rxqcqs[i].stats;
ionic_debugfs_add_qcq(lif, lif->rxqcqs[i].qcq);
ionic_debugfs_add_qcq(lif, lif->rxqcqs[i]);
}
return 0;
@ -1612,13 +1581,13 @@ static int ionic_txrx_init(struct ionic_lif *lif)
int err;
for (i = 0; i < lif->nxqs; i++) {
err = ionic_lif_txq_init(lif, lif->txqcqs[i].qcq);
err = ionic_lif_txq_init(lif, lif->txqcqs[i]);
if (err)
goto err_out;
err = ionic_lif_rxq_init(lif, lif->rxqcqs[i].qcq);
err = ionic_lif_rxq_init(lif, lif->rxqcqs[i]);
if (err) {
ionic_lif_qcq_deinit(lif, lif->txqcqs[i].qcq);
ionic_lif_qcq_deinit(lif, lif->txqcqs[i]);
goto err_out;
}
}
@ -1632,8 +1601,8 @@ static int ionic_txrx_init(struct ionic_lif *lif)
err_out:
while (i--) {
ionic_lif_qcq_deinit(lif, lif->txqcqs[i].qcq);
ionic_lif_qcq_deinit(lif, lif->rxqcqs[i].qcq);
ionic_lif_qcq_deinit(lif, lif->txqcqs[i]);
ionic_lif_qcq_deinit(lif, lif->rxqcqs[i]);
}
return err;
@ -1644,15 +1613,15 @@ static int ionic_txrx_enable(struct ionic_lif *lif)
int i, err;
for (i = 0; i < lif->nxqs; i++) {
ionic_rx_fill(&lif->rxqcqs[i].qcq->q);
err = ionic_qcq_enable(lif->rxqcqs[i].qcq);
ionic_rx_fill(&lif->rxqcqs[i]->q);
err = ionic_qcq_enable(lif->rxqcqs[i]);
if (err)
goto err_out;
err = ionic_qcq_enable(lif->txqcqs[i].qcq);
err = ionic_qcq_enable(lif->txqcqs[i]);
if (err) {
if (err != -ETIMEDOUT)
ionic_qcq_disable(lif->rxqcqs[i].qcq);
ionic_qcq_disable(lif->rxqcqs[i]);
goto err_out;
}
}
@ -1661,10 +1630,10 @@ static int ionic_txrx_enable(struct ionic_lif *lif)
err_out:
while (i--) {
err = ionic_qcq_disable(lif->txqcqs[i].qcq);
err = ionic_qcq_disable(lif->txqcqs[i]);
if (err == -ETIMEDOUT)
break;
err = ionic_qcq_disable(lif->rxqcqs[i].qcq);
err = ionic_qcq_disable(lif->rxqcqs[i]);
if (err == -ETIMEDOUT)
break;
}

View File

@ -56,13 +56,6 @@ struct ionic_napi_stats {
u64 work_done_cntr[IONIC_MAX_NUM_NAPI_CNTR];
};
struct ionic_q_stats {
union {
struct ionic_tx_stats tx;
struct ionic_rx_stats rx;
};
};
struct ionic_qcq {
void *base;
dma_addr_t base_pa;
@ -72,19 +65,13 @@ struct ionic_qcq {
struct ionic_intr_info intr;
struct napi_struct napi;
struct ionic_napi_stats napi_stats;
struct ionic_q_stats *stats;
unsigned int flags;
struct dentry *dentry;
};
struct ionic_qcqst {
struct ionic_qcq *qcq;
struct ionic_q_stats *stats;
};
#define q_to_qcq(q) container_of(q, struct ionic_qcq, q)
#define q_to_tx_stats(q) (&q_to_qcq(q)->stats->tx)
#define q_to_rx_stats(q) (&q_to_qcq(q)->stats->rx)
#define q_to_tx_stats(q) (&(q)->lif->txqstats[(q)->index])
#define q_to_rx_stats(q) (&(q)->lif->rxqstats[(q)->index])
#define napi_to_qcq(napi) container_of(napi, struct ionic_qcq, napi)
#define napi_to_cq(napi) (&napi_to_qcq(napi)->cq)
@ -170,8 +157,10 @@ struct ionic_lif {
spinlock_t adminq_lock; /* lock for AdminQ operations */
struct ionic_qcq *adminqcq;
struct ionic_qcq *notifyqcq;
struct ionic_qcqst *txqcqs;
struct ionic_qcqst *rxqcqs;
struct ionic_qcq **txqcqs;
struct ionic_tx_stats *txqstats;
struct ionic_qcq **rxqcqs;
struct ionic_rx_stats *rxqstats;
u64 last_eid;
unsigned int neqs;
unsigned int nxqs;
@ -212,13 +201,6 @@ struct ionic_lif {
struct work_struct tx_timeout_work;
};
#define lif_to_txqcq(lif, i) ((lif)->txqcqs[i].qcq)
#define lif_to_rxqcq(lif, i) ((lif)->rxqcqs[i].qcq)
#define lif_to_txstats(lif, i) ((lif)->txqcqs[i].stats->tx)
#define lif_to_rxstats(lif, i) ((lif)->rxqcqs[i].stats->rx)
#define lif_to_txq(lif, i) (&lif_to_txqcq((lif), i)->q)
#define lif_to_rxq(lif, i) (&lif_to_txqcq((lif), i)->q)
static inline u32 ionic_coal_usec_to_hw(struct ionic *ionic, u32 usecs)
{
u32 mult = le32_to_cpu(ionic->ident.dev.intr_coal_mult);
@ -258,18 +240,18 @@ int ionic_open(struct net_device *netdev);
int ionic_stop(struct net_device *netdev);
int ionic_reset_queues(struct ionic_lif *lif, ionic_reset_cb cb, void *arg);
static inline void debug_stats_txq_post(struct ionic_qcq *qcq,
static inline void debug_stats_txq_post(struct ionic_queue *q,
struct ionic_txq_desc *desc, bool dbell)
{
u8 num_sg_elems = ((le64_to_cpu(desc->cmd) >> IONIC_TXQ_DESC_NSGE_SHIFT)
& IONIC_TXQ_DESC_NSGE_MASK);
qcq->q.dbell_count += dbell;
q->dbell_count += dbell;
if (num_sg_elems > (IONIC_MAX_NUM_SG_CNTR - 1))
num_sg_elems = IONIC_MAX_NUM_SG_CNTR - 1;
qcq->stats->tx.sg_cntr[num_sg_elems]++;
q->lif->txqstats[q->index].sg_cntr[num_sg_elems]++;
}
static inline void debug_stats_napi_poll(struct ionic_qcq *qcq,
@ -284,10 +266,10 @@ static inline void debug_stats_napi_poll(struct ionic_qcq *qcq,
}
#define DEBUG_STATS_CQE_CNT(cq) ((cq)->compl_count++)
#define DEBUG_STATS_RX_BUFF_CNT(qcq) ((qcq)->stats->rx.buffers_posted++)
#define DEBUG_STATS_RX_BUFF_CNT(q) ((q)->lif->rxqstats[q->index].buffers_posted++)
#define DEBUG_STATS_INTR_REARM(intr) ((intr)->rearm_count++)
#define DEBUG_STATS_TXQ_POST(qcq, txdesc, dbell) \
debug_stats_txq_post(qcq, txdesc, dbell)
#define DEBUG_STATS_TXQ_POST(q, txdesc, dbell) \
debug_stats_txq_post(q, txdesc, dbell)
#define DEBUG_STATS_NAPI_POLL(qcq, work_done) \
debug_stats_napi_poll(qcq, work_done)

View File

@ -179,36 +179,28 @@ static const struct ionic_stat_desc ionic_dbg_napi_stats_desc[] = {
static void ionic_get_lif_stats(struct ionic_lif *lif,
struct ionic_lif_sw_stats *stats)
{
struct ionic_tx_stats *tstats;
struct ionic_rx_stats *rstats;
struct ionic_tx_stats *txstats;
struct ionic_rx_stats *rxstats;
struct rtnl_link_stats64 ns;
struct ionic_qcq *txqcq;
struct ionic_qcq *rxqcq;
int q_num;
memset(stats, 0, sizeof(*stats));
for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
txqcq = lif_to_txqcq(lif, q_num);
if (txqcq && txqcq->stats) {
tstats = &txqcq->stats->tx;
stats->tx_packets += tstats->pkts;
stats->tx_bytes += tstats->bytes;
stats->tx_tso += tstats->tso;
stats->tx_tso_bytes += tstats->tso_bytes;
stats->tx_csum_none += tstats->csum_none;
stats->tx_csum += tstats->csum;
}
txstats = &lif->txqstats[q_num];
stats->tx_packets += txstats->pkts;
stats->tx_bytes += txstats->bytes;
stats->tx_tso += txstats->tso;
stats->tx_tso_bytes += txstats->tso_bytes;
stats->tx_csum_none += txstats->csum_none;
stats->tx_csum += txstats->csum;
rxqcq = lif_to_rxqcq(lif, q_num);
if (rxqcq && rxqcq->stats) {
rstats = &rxqcq->stats->rx;
stats->rx_packets += rstats->pkts;
stats->rx_bytes += rstats->bytes;
stats->rx_csum_none += rstats->csum_none;
stats->rx_csum_complete += rstats->csum_complete;
stats->rx_csum_error += rstats->csum_error;
}
rxstats = &lif->rxqstats[q_num];
stats->rx_packets += rxstats->pkts;
stats->rx_bytes += rxstats->bytes;
stats->rx_csum_none += rxstats->csum_none;
stats->rx_csum_complete += rxstats->csum_complete;
stats->rx_csum_error += rxstats->csum_error;
}
ionic_get_stats64(lif->netdev, &ns);
@ -371,7 +363,7 @@ static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf)
}
for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
txstats = &lif_to_txstats(lif, q_num);
txstats = &lif->txqstats[q_num];
for (i = 0; i < IONIC_NUM_TX_STATS; i++) {
**buf = IONIC_READ_STAT64(txstats,
@ -381,7 +373,7 @@ static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf)
if (test_bit(IONIC_LIF_F_UP, lif->state) &&
test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) {
txqcq = lif_to_txqcq(lif, q_num);
txqcq = lif->txqcqs[q_num];
for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) {
**buf = IONIC_READ_STAT64(&txqcq->q,
&ionic_txq_stats_desc[i]);
@ -405,7 +397,7 @@ static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf)
}
for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
rxstats = &lif_to_rxstats(lif, q_num);
rxstats = &lif->rxqstats[q_num];
for (i = 0; i < IONIC_NUM_RX_STATS; i++) {
**buf = IONIC_READ_STAT64(rxstats,
@ -415,7 +407,7 @@ static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf)
if (test_bit(IONIC_LIF_F_UP, lif->state) &&
test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) {
rxqcq = lif_to_rxqcq(lif, q_num);
rxqcq = lif->rxqcqs[q_num];
for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) {
**buf = IONIC_READ_STAT64(&rxqcq->cq,
&ionic_dbg_cq_stats_desc[i]);

View File

@ -22,7 +22,7 @@ static bool ionic_tx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info)
static inline void ionic_txq_post(struct ionic_queue *q, bool ring_dbell,
ionic_desc_cb cb_func, void *cb_arg)
{
DEBUG_STATS_TXQ_POST(q_to_qcq(q), q->head->desc, ring_dbell);
DEBUG_STATS_TXQ_POST(q, q->head->desc, ring_dbell);
ionic_q_post(q, ring_dbell, cb_func, cb_arg);
}
@ -32,7 +32,7 @@ static inline void ionic_rxq_post(struct ionic_queue *q, bool ring_dbell,
{
ionic_q_post(q, ring_dbell, cb_func, cb_arg);
DEBUG_STATS_RX_BUFF_CNT(q_to_qcq(q));
DEBUG_STATS_RX_BUFF_CNT(q);
}
static inline struct netdev_queue *q_to_ndq(struct ionic_queue *q)
@ -49,7 +49,7 @@ static struct sk_buff *ionic_rx_skb_alloc(struct ionic_queue *q,
struct sk_buff *skb;
netdev = lif->netdev;
stats = q_to_rx_stats(q);
stats = &q->lif->rxqstats[q->index];
if (frags)
skb = napi_get_frags(&q_to_qcq(q)->napi);
@ -502,7 +502,7 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget)
lif = rxcq->bound_q->lif;
idev = &lif->ionic->idev;
txcq = &lif->txqcqs[qi].qcq->cq;
txcq = &lif->txqcqs[qi]->cq;
tx_work_done = ionic_cq_service(txcq, lif->tx_budget,
ionic_tx_service, NULL, NULL);
@ -1111,9 +1111,9 @@ netdev_tx_t ionic_start_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}
if (unlikely(!lif_to_txqcq(lif, queue_index)))
if (unlikely(queue_index >= lif->nxqs))
queue_index = 0;
q = lif_to_txq(lif, queue_index);
q = &lif->txqcqs[queue_index]->q;
ndescs = ionic_tx_descs_needed(q, skb);
if (ndescs < 0)