@@ -83,7 +83,10 @@ struct ionic_admin_ctx {
union ionic_adminq_comp comp;
};
+int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx);
int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx);
+int ionic_adminq_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx);
+uint16_t ionic_adminq_space_avail(struct ionic_lif *lif);
int ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait);
int ionic_setup(struct ionic_adapter *adapter);
@@ -31,11 +31,15 @@ static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr);
static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr);
static int
-ionic_qcq_disable(struct ionic_qcq *qcq)
+ionic_qcq_disable_nowait(struct ionic_qcq *qcq,
+ struct ionic_admin_ctx *ctx)
{
+ int err;
+
struct ionic_queue *q = &qcq->q;
struct ionic_lif *lif = qcq->lif;
- struct ionic_admin_ctx ctx = {
+
+ *ctx = (struct ionic_admin_ctx) {
.pending_work = true,
.cmd.q_control = {
.opcode = IONIC_CMD_Q_CONTROL,
@@ -45,28 +49,39 @@ ionic_qcq_disable(struct ionic_qcq *qcq)
},
};
- return ionic_adminq_post_wait(lif, &ctx);
+ /* Does not wait for command completion */
+ err = ionic_adminq_post(lif, ctx);
+ if (err)
+ ctx->pending_work = false;
+ return err;
}
void
ionic_lif_stop(struct ionic_lif *lif)
{
- uint32_t i;
+ struct rte_eth_dev *dev = lif->eth_dev;
+ uint32_t i, j, chunk;
IONIC_PRINT_CALL();
lif->state &= ~IONIC_LIF_F_UP;
- for (i = 0; i < lif->nrxqcqs; i++) {
- struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
- if (rxq->flags & IONIC_QCQ_F_INITED)
- (void)ionic_dev_rx_queue_stop(lif->eth_dev, i);
+ chunk = ionic_adminq_space_avail(lif);
+
+ for (i = 0; i < lif->nrxqcqs; i += chunk) {
+ for (j = 0; j < chunk && i + j < lif->nrxqcqs; j++)
+ ionic_dev_rx_queue_stop_firsthalf(dev, i + j);
+
+ for (j = 0; j < chunk && i + j < lif->nrxqcqs; j++)
+ ionic_dev_rx_queue_stop_secondhalf(dev, i + j);
}
- for (i = 0; i < lif->ntxqcqs; i++) {
- struct ionic_tx_qcq *txq = lif->txqcqs[i];
- if (txq->flags & IONIC_QCQ_F_INITED)
- (void)ionic_dev_tx_queue_stop(lif->eth_dev, i);
+ for (i = 0; i < lif->ntxqcqs; i += chunk) {
+ for (j = 0; j < chunk && i + j < lif->ntxqcqs; j++)
+ ionic_dev_tx_queue_stop_firsthalf(dev, i + j);
+
+ for (j = 0; j < chunk && i + j < lif->ntxqcqs; j++)
+ ionic_dev_tx_queue_stop_secondhalf(dev, i + j);
}
}
@@ -1240,21 +1255,42 @@ ionic_lif_rss_teardown(struct ionic_lif *lif)
}
void
-ionic_lif_txq_deinit(struct ionic_tx_qcq *txq)
+ionic_lif_txq_deinit_nowait(struct ionic_tx_qcq *txq)
{
- ionic_qcq_disable(&txq->qcq);
+ ionic_qcq_disable_nowait(&txq->qcq, &txq->admin_ctx);
txq->flags &= ~IONIC_QCQ_F_INITED;
}
void
-ionic_lif_rxq_deinit(struct ionic_rx_qcq *rxq)
+ionic_lif_txq_stats(struct ionic_tx_qcq *txq)
+{
+ struct ionic_tx_stats *stats = &txq->stats;
+
+ IONIC_PRINT(DEBUG, "TX queue %u pkts %ju tso %ju",
+ txq->qcq.q.index, stats->packets, stats->tso);
+ IONIC_PRINT(DEBUG, "TX queue %u comps %ju (%ju per)",
+ txq->qcq.q.index, stats->comps,
+ stats->comps ? stats->packets / stats->comps : 0);
+}
+
+void
+ionic_lif_rxq_deinit_nowait(struct ionic_rx_qcq *rxq)
{
- ionic_qcq_disable(&rxq->qcq);
+ ionic_qcq_disable_nowait(&rxq->qcq, &rxq->admin_ctx);
rxq->flags &= ~IONIC_QCQ_F_INITED;
}
+void
+ionic_lif_rxq_stats(struct ionic_rx_qcq *rxq)
+{
+ struct ionic_rx_stats *stats = &rxq->stats;
+
+ IONIC_PRINT(DEBUG, "RX queue %u pkts %ju mtod %ju",
+ rxq->qcq.q.index, stats->packets, stats->mtods);
+}
+
static void
ionic_lif_adminq_deinit(struct ionic_lif *lif)
{
@@ -10,7 +10,7 @@
#include <rte_ethdev.h>
#include <rte_ether.h>
-#include "ionic_osdep.h"
+#include "ionic.h"
#include "ionic_dev.h"
#include "ionic_rx_filter.h"
@@ -99,6 +99,8 @@ struct ionic_rx_qcq {
/* cacheline4+ */
struct rte_mbuf *mbs[IONIC_MBUF_BULK_ALLOC] __rte_cache_aligned;
+
+ struct ionic_admin_ctx admin_ctx;
};
struct ionic_tx_qcq {
@@ -112,6 +114,8 @@ struct ionic_tx_qcq {
uint16_t flags;
struct ionic_tx_stats stats;
+
+ struct ionic_admin_ctx admin_ctx;
};
#define IONIC_Q_TO_QCQ(_q) container_of(_q, struct ionic_qcq, q)
@@ -225,10 +229,12 @@ int ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id,
void ionic_qcq_free(struct ionic_qcq *qcq);
int ionic_lif_rxq_init(struct ionic_rx_qcq *rxq);
-void ionic_lif_rxq_deinit(struct ionic_rx_qcq *rxq);
+void ionic_lif_rxq_deinit_nowait(struct ionic_rx_qcq *rxq);
+void ionic_lif_rxq_stats(struct ionic_rx_qcq *rxq);
int ionic_lif_txq_init(struct ionic_tx_qcq *txq);
-void ionic_lif_txq_deinit(struct ionic_tx_qcq *txq);
+void ionic_lif_txq_deinit_nowait(struct ionic_tx_qcq *txq);
+void ionic_lif_txq_stats(struct ionic_tx_qcq *txq);
int ionic_lif_rss_config(struct ionic_lif *lif, const uint16_t types,
const uint8_t *key, const uint32_t *indir);
@@ -180,6 +180,12 @@ ionic_adminq_service(struct ionic_cq *cq, uint16_t cq_desc_index,
return true;
}
+uint16_t
+ionic_adminq_space_avail(struct ionic_lif *lif)
+{
+ return ionic_q_space_avail(&lif->adminqcq->qcq.q);
+}
+
/** ionic_adminq_post - Post an admin command.
* @lif: Handle to lif.
* @cmd_ctx: Api admin command context.
@@ -191,7 +197,7 @@ ionic_adminq_service(struct ionic_cq *cq, uint16_t cq_desc_index,
*
* Return: zero or negative error status.
*/
-static int
+int
ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
{
struct ionic_queue *q = &lif->adminqcq->qcq.q;
@@ -279,7 +285,6 @@ ionic_adminq_wait_for_completion(struct ionic_lif *lif,
int
ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
{
- bool done;
int err;
IONIC_PRINT(DEBUG, "Sending %s (%d) via the admin queue",
@@ -292,6 +297,14 @@ ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
return err;
}
+ return ionic_adminq_wait(lif, ctx);
+}
+
+int
+ionic_adminq_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
+{
+ bool done;
+
done = ionic_adminq_wait_for_completion(lif, ctx,
IONIC_DEVCMD_TIMEOUT);
@@ -92,36 +92,40 @@ ionic_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
}
int __rte_cold
-ionic_dev_tx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id)
+ionic_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
{
- struct ionic_tx_stats *stats;
- struct ionic_tx_qcq *txq;
+ ionic_dev_tx_queue_stop_firsthalf(dev, tx_queue_id);
+ ionic_dev_tx_queue_stop_secondhalf(dev, tx_queue_id);
+
+ return 0;
+}
+
+void __rte_cold
+ionic_dev_tx_queue_stop_firsthalf(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id)
+{
+ struct ionic_tx_qcq *txq = dev->data->tx_queues[tx_queue_id];
IONIC_PRINT(DEBUG, "Stopping TX queue %u", tx_queue_id);
- txq = eth_dev->data->tx_queues[tx_queue_id];
+ dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
- eth_dev->data->tx_queue_state[tx_queue_id] =
- RTE_ETH_QUEUE_STATE_STOPPED;
+ ionic_lif_txq_deinit_nowait(txq);
+}
- /*
- * Note: we should better post NOP Tx desc and wait for its completion
- * before disabling Tx queue
- */
+void __rte_cold
+ionic_dev_tx_queue_stop_secondhalf(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id)
+{
+ struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(dev);
+ struct ionic_tx_qcq *txq = dev->data->tx_queues[tx_queue_id];
- ionic_lif_txq_deinit(txq);
+ ionic_adminq_wait(lif, &txq->admin_ctx);
/* Free all buffers from descriptor ring */
ionic_tx_empty(txq);
- stats = &txq->stats;
- IONIC_PRINT(DEBUG, "TX queue %u pkts %ju tso %ju",
- txq->qcq.q.index, stats->packets, stats->tso);
- IONIC_PRINT(DEBUG, "TX queue %u comps %ju (%ju per)",
- txq->qcq.q.index, stats->comps,
- stats->comps ? stats->packets / stats->comps : 0);
-
- return 0;
+ ionic_lif_txq_stats(txq);
}
int __rte_cold
@@ -726,28 +730,40 @@ ionic_dev_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
* Stop Receive Units for specified queue.
*/
int __rte_cold
-ionic_dev_rx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id)
+ionic_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
{
- uint8_t *rx_queue_state = eth_dev->data->rx_queue_state;
- struct ionic_rx_stats *stats;
- struct ionic_rx_qcq *rxq;
+ ionic_dev_rx_queue_stop_firsthalf(dev, rx_queue_id);
+ ionic_dev_rx_queue_stop_secondhalf(dev, rx_queue_id);
+
+ return 0;
+}
+
+void __rte_cold
+ionic_dev_rx_queue_stop_firsthalf(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id)
+{
+ struct ionic_rx_qcq *rxq = dev->data->rx_queues[rx_queue_id];
IONIC_PRINT(DEBUG, "Stopping RX queue %u", rx_queue_id);
- rxq = eth_dev->data->rx_queues[rx_queue_id];
+ dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+ ionic_lif_rxq_deinit_nowait(rxq);
+}
- rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
+void __rte_cold
+ionic_dev_rx_queue_stop_secondhalf(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id)
+{
+ struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(dev);
+ struct ionic_rx_qcq *rxq = dev->data->rx_queues[rx_queue_id];
- ionic_lif_rxq_deinit(rxq);
+ ionic_adminq_wait(lif, &rxq->admin_ctx);
/* Free all buffers from descriptor ring */
ionic_rx_empty(rxq);
- stats = &rxq->stats;
- IONIC_PRINT(DEBUG, "RX queue %u pkts %ju mtod %ju",
- rxq->qcq.q.index, stats->packets, stats->mtods);
-
- return 0;
+ ionic_lif_rxq_stats(rxq);
}
int
@@ -37,14 +37,24 @@ int ionic_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp);
void ionic_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid);
int ionic_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id);
-int ionic_dev_rx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id);
+int ionic_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id);
int ionic_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
uint16_t nb_desc, uint32_t socket_id,
const struct rte_eth_txconf *tx_conf);
void ionic_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid);
-int ionic_dev_tx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id);
int ionic_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id);
+int ionic_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id);
+
+/* Helpers for optimized dev_stop() */
+void ionic_dev_rx_queue_stop_firsthalf(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id);
+void ionic_dev_rx_queue_stop_secondhalf(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id);
+void ionic_dev_tx_queue_stop_firsthalf(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id);
+void ionic_dev_tx_queue_stop_secondhalf(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id);
void ionic_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
struct rte_eth_rxq_info *qinfo);