aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/mana/mana_en.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/mana/mana_en.c')
-rw-r--r--sys/dev/mana/mana_en.c276
1 files changed, 180 insertions, 96 deletions
diff --git a/sys/dev/mana/mana_en.c b/sys/dev/mana/mana_en.c
index 0e5f86b5e105..949b498ceadc 100644
--- a/sys/dev/mana/mana_en.c
+++ b/sys/dev/mana/mana_en.c
@@ -67,6 +67,10 @@
static int mana_up(struct mana_port_context *apc);
static int mana_down(struct mana_port_context *apc);
+extern unsigned int mana_tx_req_size;
+extern unsigned int mana_rx_req_size;
+extern unsigned int mana_rx_refill_threshold;
+
static void
mana_rss_key_fill(void *k, size_t size)
{
@@ -492,6 +496,7 @@ mana_xmit(struct mana_txq *txq)
if_t ndev = txq->ndev;
struct mbuf *mbuf;
struct mana_port_context *apc = if_getsoftc(ndev);
+ unsigned int tx_queue_size = apc->tx_queue_size;
struct mana_port_stats *port_stats = &apc->port_stats;
struct gdma_dev *gd = apc->ac->gdma_dev;
uint64_t packets, bytes;
@@ -634,8 +639,7 @@ mana_xmit(struct mana_txq *txq)
continue;
}
- next_to_use =
- (next_to_use + 1) % MAX_SEND_BUFFERS_PER_QUEUE;
+ next_to_use = MANA_IDX_NEXT(next_to_use, tx_queue_size);
(void)atomic_inc_return(&txq->pending_sends);
@@ -921,13 +925,6 @@ mana_init_port_context(struct mana_port_context *apc)
apc->rxqs = mallocarray(apc->num_queues, sizeof(struct mana_rxq *),
M_DEVBUF, M_WAITOK | M_ZERO);
- if (!apc->rxqs) {
- bus_dma_tag_destroy(apc->tx_buf_tag);
- bus_dma_tag_destroy(apc->rx_buf_tag);
- apc->rx_buf_tag = NULL;
- return ENOMEM;
- }
-
return 0;
}
@@ -1156,8 +1153,6 @@ mana_cfg_vport_steering(struct mana_port_context *apc,
req_buf_size = sizeof(*req) + sizeof(mana_handle_t) * num_entries;
req = malloc(req_buf_size, M_DEVBUF, M_WAITOK | M_ZERO);
- if (!req)
- return ENOMEM;
mana_gd_init_req_hdr(&req->hdr, MANA_CONFIG_VPORT_RX, req_buf_size,
sizeof(resp));
@@ -1325,8 +1320,6 @@ mana_create_eq(struct mana_context *ac)
ac->eqs = mallocarray(gc->max_num_queues, sizeof(struct mana_eq),
M_DEVBUF, M_WAITOK | M_ZERO);
- if (!ac->eqs)
- return ENOMEM;
spec.type = GDMA_EQ;
spec.monitor_avl_buf = false;
@@ -1434,10 +1427,11 @@ mana_poll_tx_cq(struct mana_cq *cq)
unsigned int wqe_unit_cnt = 0;
struct mana_txq *txq = cq->txq;
struct mana_port_context *apc;
+ unsigned int tx_queue_size;
uint16_t next_to_complete;
if_t ndev;
int comp_read;
- int txq_idx = txq->idx;;
+ int txq_idx = txq->idx;
int i;
int sa_drop = 0;
@@ -1447,6 +1441,7 @@ mana_poll_tx_cq(struct mana_cq *cq)
ndev = txq->ndev;
apc = if_getsoftc(ndev);
+ tx_queue_size = apc->tx_queue_size;
comp_read = mana_gd_poll_cq(cq->gdma_cq, completions,
CQE_POLLING_BUFFER);
@@ -1532,7 +1527,7 @@ mana_poll_tx_cq(struct mana_cq *cq)
mb();
next_to_complete =
- (next_to_complete + 1) % MAX_SEND_BUFFERS_PER_QUEUE;
+ MANA_IDX_NEXT(next_to_complete, tx_queue_size);
pkt_transmitted++;
}
@@ -1597,18 +1592,11 @@ mana_poll_tx_cq(struct mana_cq *cq)
}
static void
-mana_post_pkt_rxq(struct mana_rxq *rxq)
+mana_post_pkt_rxq(struct mana_rxq *rxq,
+ struct mana_recv_buf_oob *recv_buf_oob)
{
- struct mana_recv_buf_oob *recv_buf_oob;
- uint32_t curr_index;
int err;
- curr_index = rxq->buf_index++;
- if (rxq->buf_index == rxq->num_rx_buf)
- rxq->buf_index = 0;
-
- recv_buf_oob = &rxq->rx_oobs[curr_index];
-
err = mana_gd_post_work_request(rxq->gdma_rq, &recv_buf_oob->wqe_req,
&recv_buf_oob->wqe_inf);
if (err) {
@@ -1727,6 +1715,68 @@ mana_rx_mbuf(struct mbuf *mbuf, struct mana_rxcomp_oob *cqe,
counter_exit();
}
+static int
+mana_refill_rx_mbufs(struct mana_port_context *apc,
+ struct mana_rxq *rxq, uint32_t num)
+{
+ struct mana_recv_buf_oob *rxbuf_oob;
+ uint32_t next_to_refill;
+ uint32_t i;
+ int err;
+
+ next_to_refill = rxq->next_to_refill;
+
+ for (i = 0; i < num; i++) {
+ if (next_to_refill == rxq->buf_index) {
+ mana_warn(NULL, "refilling index reached current, "
+ "aborted! rxq %u, oob idx %u\n",
+ rxq->rxq_idx, next_to_refill);
+ break;
+ }
+
+ rxbuf_oob = &rxq->rx_oobs[next_to_refill];
+
+ if (likely(rxbuf_oob->mbuf == NULL)) {
+ err = mana_load_rx_mbuf(apc, rxq, rxbuf_oob, true);
+ } else {
+ mana_warn(NULL, "mbuf not null when refilling, "
+ "rxq %u, oob idx %u, reusing\n",
+ rxq->rxq_idx, next_to_refill);
+ err = mana_load_rx_mbuf(apc, rxq, rxbuf_oob, false);
+ }
+
+ if (unlikely(err != 0)) {
+ mana_dbg(NULL,
+ "failed to load rx mbuf, err = %d, rxq = %u\n",
+ err, rxq->rxq_idx);
+ counter_u64_add(rxq->stats.mbuf_alloc_fail, 1);
+ break;
+ }
+
+ mana_post_pkt_rxq(rxq, rxbuf_oob);
+
+ next_to_refill = MANA_IDX_NEXT(next_to_refill,
+ rxq->num_rx_buf);
+ }
+
+ if (likely(i != 0)) {
+ struct gdma_context *gc =
+ rxq->gdma_rq->gdma_dev->gdma_context;
+
+ mana_gd_wq_ring_doorbell(gc, rxq->gdma_rq);
+ }
+
+ if (unlikely(i < num)) {
+ counter_u64_add(rxq->stats.partial_refill, 1);
+ mana_dbg(NULL,
+ "refilled rxq %u with only %u mbufs (%u requested)\n",
+ rxq->rxq_idx, i, num);
+ }
+
+ rxq->next_to_refill = next_to_refill;
+ return (i);
+}
+
static void
mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
struct gdma_comp *cqe)
@@ -1736,8 +1786,8 @@ mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
if_t ndev = rxq->ndev;
struct mana_port_context *apc;
struct mbuf *old_mbuf;
+ uint32_t refill_required;
uint32_t curr, pktlen;
- int err;
switch (oob->cqe_hdr.cqe_type) {
case CQE_RX_OKAY:
@@ -1790,29 +1840,24 @@ mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
/* Unload DMA map for the old mbuf */
mana_unload_rx_mbuf(apc, rxq, rxbuf_oob, false);
-
- /* Load a new mbuf to replace the old one */
- err = mana_load_rx_mbuf(apc, rxq, rxbuf_oob, true);
- if (err) {
- mana_dbg(NULL,
- "failed to load rx mbuf, err = %d, packet dropped.\n",
- err);
- counter_u64_add(rxq->stats.mbuf_alloc_fail, 1);
- /*
- * Failed to load new mbuf, rxbuf_oob->mbuf is still
- * pointing to the old one. Drop the packet.
- */
- old_mbuf = NULL;
- /* Reload the existing mbuf */
- mana_load_rx_mbuf(apc, rxq, rxbuf_oob, false);
- }
+ /* Clear the mbuf pointer to avoid reuse */
+ rxbuf_oob->mbuf = NULL;
mana_rx_mbuf(old_mbuf, oob, rxq);
drop:
mana_move_wq_tail(rxq->gdma_rq, rxbuf_oob->wqe_inf.wqe_size_in_bu);
- mana_post_pkt_rxq(rxq);
+ rxq->buf_index = MANA_IDX_NEXT(rxq->buf_index, rxq->num_rx_buf);
+
+ /* Check if refill is needed */
+ refill_required = MANA_GET_SPACE(rxq->next_to_refill,
+ rxq->buf_index, rxq->num_rx_buf);
+
+ if (refill_required >= rxq->refill_thresh) {
+ /* Refill empty rx_oobs with new mbufs */
+ mana_refill_rx_mbufs(apc, rxq, refill_required);
+ }
}
static void
@@ -1845,13 +1890,6 @@ mana_poll_rx_cq(struct mana_cq *cq)
mana_process_rx_cqe(cq->rxq, cq, &comp[i]);
}
- if (comp_read > 0) {
- struct gdma_context *gc =
- cq->rxq->gdma_rq->gdma_dev->gdma_context;
-
- mana_gd_wq_ring_doorbell(gc, cq->rxq->gdma_rq);
- }
-
tcp_lro_flush_all(&cq->rxq->lro);
}
@@ -1878,9 +1916,9 @@ mana_cq_handler(void *context, struct gdma_queue *gdma_queue)
mana_gd_ring_cq(gdma_queue, arm_bit);
}
-#define MANA_POLL_BUDGET 8
-#define MANA_RX_BUDGET 256
-#define MANA_TX_BUDGET MAX_SEND_BUFFERS_PER_QUEUE
+#define MANA_POLL_BUDGET 256
+#define MANA_RX_BUDGET 8
+#define MANA_TX_BUDGET 8
static void
mana_poll(void *arg, int pending)
@@ -1987,7 +2025,7 @@ mana_deinit_txq(struct mana_port_context *apc, struct mana_txq *txq)
if (txq->tx_buf_info) {
/* Free all mbufs which are still in-flight */
- for (i = 0; i < MAX_SEND_BUFFERS_PER_QUEUE; i++) {
+ for (i = 0; i < apc->tx_queue_size; i++) {
txbuf_info = &txq->tx_buf_info[i];
if (txbuf_info->mbuf) {
mana_tx_unmap_mbuf(apc, txbuf_info);
@@ -2043,19 +2081,21 @@ mana_create_txq(struct mana_port_context *apc, if_t net)
apc->tx_qp = mallocarray(apc->num_queues, sizeof(struct mana_tx_qp),
M_DEVBUF, M_WAITOK | M_ZERO);
- if (!apc->tx_qp)
- return ENOMEM;
/* The minimum size of the WQE is 32 bytes, hence
- * MAX_SEND_BUFFERS_PER_QUEUE represents the maximum number of WQEs
+ * apc->tx_queue_size represents the maximum number of WQEs
* the SQ can store. This value is then used to size other queues
* to prevent overflow.
+ * Also note that the txq_size is always going to be page aligned,
+ * as min val of apc->tx_queue_size is 128 and that would make
+ * txq_size 128 * 32 = 4096 and the other higher values of
+ * apc->tx_queue_size are always power of two.
*/
- txq_size = MAX_SEND_BUFFERS_PER_QUEUE * 32;
+ txq_size = apc->tx_queue_size * 32;
KASSERT(IS_ALIGNED(txq_size, PAGE_SIZE),
("txq size not page aligned"));
- cq_size = MAX_SEND_BUFFERS_PER_QUEUE * COMP_ENTRY_SIZE;
+ cq_size = apc->tx_queue_size * COMP_ENTRY_SIZE;
cq_size = ALIGN(cq_size, PAGE_SIZE);
gc = gd->gdma_context;
@@ -2127,7 +2167,7 @@ mana_create_txq(struct mana_port_context *apc, if_t net)
mana_dbg(NULL,
"txq %d, txq gdma id %d, txq cq gdma id %d\n",
- i, txq->gdma_txq_id, cq->gdma_id);;
+ i, txq->gdma_txq_id, cq->gdma_id);
if (cq->gdma_id >= gc->max_num_cqs) {
if_printf(net, "CQ id %u too large.\n", cq->gdma_id);
@@ -2138,31 +2178,16 @@ mana_create_txq(struct mana_port_context *apc, if_t net)
gc->cq_table[cq->gdma_id] = cq->gdma_cq;
/* Initialize tx specific data */
- txq->tx_buf_info = malloc(MAX_SEND_BUFFERS_PER_QUEUE *
+ txq->tx_buf_info = malloc(apc->tx_queue_size *
sizeof(struct mana_send_buf_info),
M_DEVBUF, M_WAITOK | M_ZERO);
- if (unlikely(txq->tx_buf_info == NULL)) {
- if_printf(net,
- "Failed to allocate tx buf info for SQ %u\n",
- txq->gdma_sq->id);
- err = ENOMEM;
- goto out;
- }
-
snprintf(txq->txq_mtx_name, nitems(txq->txq_mtx_name),
"mana:tx(%d)", i);
mtx_init(&txq->txq_mtx, txq->txq_mtx_name, NULL, MTX_DEF);
- txq->txq_br = buf_ring_alloc(4 * MAX_SEND_BUFFERS_PER_QUEUE,
+ txq->txq_br = buf_ring_alloc(4 * apc->tx_queue_size,
M_DEVBUF, M_WAITOK, &txq->txq_mtx);
- if (unlikely(txq->txq_br == NULL)) {
- if_printf(net,
- "Failed to allocate buf ring for SQ %u\n",
- txq->gdma_sq->id);
- err = ENOMEM;
- goto out;
- }
/* Allocate taskqueue for deferred send */
TASK_INIT(&txq->enqueue_task, 0, mana_xmit_taskfunc, txq);
@@ -2351,13 +2376,10 @@ mana_create_rxq(struct mana_port_context *apc, uint32_t rxq_idx,
gc = gd->gdma_context;
rxq = malloc(sizeof(*rxq) +
- RX_BUFFERS_PER_QUEUE * sizeof(struct mana_recv_buf_oob),
+ apc->rx_queue_size * sizeof(struct mana_recv_buf_oob),
M_DEVBUF, M_WAITOK | M_ZERO);
- if (!rxq)
- return NULL;
-
rxq->ndev = ndev;
- rxq->num_rx_buf = RX_BUFFERS_PER_QUEUE;
+ rxq->num_rx_buf = apc->rx_queue_size;
rxq->rxq_idx = rxq_idx;
/*
* Minimum size is MCLBYTES(2048) bytes for a mbuf cluster.
@@ -2370,6 +2392,23 @@ mana_create_rxq(struct mana_port_context *apc, uint32_t rxq_idx,
mana_dbg(NULL, "Setting rxq %d datasize %d\n",
rxq_idx, rxq->datasize);
+ /*
+ * Two steps to set the mbuf refill_thresh.
+ * 1) If mana_rx_refill_threshold is set, honor it.
+ * Set to default value otherwise.
+ * 2) Select the smaller of 1) above and 1/4 of the
+ * rx buffer size.
+ */
+ if (mana_rx_refill_threshold != 0)
+ rxq->refill_thresh = mana_rx_refill_threshold;
+ else
+ rxq->refill_thresh = MANA_RX_REFILL_THRESH;
+ rxq->refill_thresh = min_t(uint32_t,
+ rxq->num_rx_buf / 4, rxq->refill_thresh);
+
+ mana_dbg(NULL, "Setting rxq %d refill thresh %u\n",
+ rxq_idx, rxq->refill_thresh);
+
rxq->rxobj = INVALID_MANA_HANDLE;
err = mana_alloc_rx_wqe(apc, rxq, &rq_size, &cq_size);
@@ -2794,6 +2833,62 @@ mana_detach(if_t ndev)
return err;
}
+static unsigned int
+mana_get_tx_queue_size(int port_idx, unsigned int request_size)
+{
+ unsigned int new_size;
+
+ if (request_size == 0)
+ /* Uninitialized */
+ new_size = DEF_SEND_BUFFERS_PER_QUEUE;
+ else
+ new_size = roundup_pow_of_two(request_size);
+
+ if (new_size < MIN_SEND_BUFFERS_PER_QUEUE ||
+ new_size > MAX_SEND_BUFFERS_PER_QUEUE) {
+ mana_info(NULL, "mana port %d: requested tx buffer "
+ "size %u out of allowable range (%u - %u), "
+ "setting to default\n",
+ port_idx, request_size,
+ MIN_SEND_BUFFERS_PER_QUEUE,
+ MAX_SEND_BUFFERS_PER_QUEUE);
+ new_size = DEF_SEND_BUFFERS_PER_QUEUE;
+ }
+ mana_info(NULL, "mana port %d: tx buffer size %u "
+ "(%u requested)\n",
+ port_idx, new_size, request_size);
+
+ return (new_size);
+}
+
+static unsigned int
+mana_get_rx_queue_size(int port_idx, unsigned int request_size)
+{
+ unsigned int new_size;
+
+ if (request_size == 0)
+ /* Uninitialized */
+ new_size = DEF_RX_BUFFERS_PER_QUEUE;
+ else
+ new_size = roundup_pow_of_two(request_size);
+
+ if (new_size < MIN_RX_BUFFERS_PER_QUEUE ||
+ new_size > MAX_RX_BUFFERS_PER_QUEUE) {
+ mana_info(NULL, "mana port %d: requested rx buffer "
+ "size %u out of allowable range (%u - %u), "
+ "setting to default\n",
+ port_idx, request_size,
+ MIN_RX_BUFFERS_PER_QUEUE,
+ MAX_RX_BUFFERS_PER_QUEUE);
+ new_size = DEF_RX_BUFFERS_PER_QUEUE;
+ }
+ mana_info(NULL, "mana port %d: rx buffer size %u "
+ "(%u requested)\n",
+ port_idx, new_size, request_size);
+
+ return (new_size);
+}
+
static int
mana_probe_port(struct mana_context *ac, int port_idx,
if_t *ndev_storage)
@@ -2805,25 +2900,18 @@ mana_probe_port(struct mana_context *ac, int port_idx,
int err;
ndev = if_alloc_dev(IFT_ETHER, gc->dev);
- if (!ndev) {
- mana_err(NULL, "Failed to allocate ifnet struct\n");
- return ENOMEM;
- }
-
*ndev_storage = ndev;
apc = malloc(sizeof(*apc), M_DEVBUF, M_WAITOK | M_ZERO);
- if (!apc) {
- mana_err(NULL, "Failed to allocate port context\n");
- err = ENOMEM;
- goto free_net;
- }
-
apc->ac = ac;
apc->ndev = ndev;
apc->max_queues = gc->max_num_queues;
apc->num_queues = min_t(unsigned int,
gc->max_num_queues, MANA_MAX_NUM_QUEUES);
+ apc->tx_queue_size = mana_get_tx_queue_size(port_idx,
+ mana_tx_req_size);
+ apc->rx_queue_size = mana_get_rx_queue_size(port_idx,
+ mana_rx_req_size);
apc->port_handle = INVALID_MANA_HANDLE;
apc->port_idx = port_idx;
apc->frame_size = DEFAULT_FRAME_SIZE;
@@ -2897,7 +2985,6 @@ mana_probe_port(struct mana_context *ac, int port_idx,
reset_apc:
free(apc, M_DEVBUF);
-free_net:
*ndev_storage = NULL;
if_printf(ndev, "Failed to probe vPort %d: %d\n", port_idx, err);
if_free(ndev);
@@ -2920,9 +3007,6 @@ int mana_probe(struct gdma_dev *gd)
return err;
ac = malloc(sizeof(*ac), M_DEVBUF, M_WAITOK | M_ZERO);
- if (!ac)
- return ENOMEM;
-
ac->gdma_dev = gd;
ac->num_ports = 1;
gd->driver_data = ac;