Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163229436
D12855.id34518.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D12855.id34518.diff
View Options
Index: sys/dev/ena/ena.h
===================================================================
--- sys/dev/ena/ena.h
+++ sys/dev/ena/ena.h
@@ -242,12 +242,17 @@
counter_u64_t bad_desc_num;
/* Not counted */
counter_u64_t small_copy_len_pkt;
+ counter_u64_t bad_req_id;
+ counter_u64_t empty_rx_ring;
};
struct ena_ring {
- /* Holds the empty requests for TX out of order completions */
- uint16_t *free_tx_ids;
+ /* Holds the empty requests for TX/RX out of order completions */
+ union {
+ uint16_t *free_tx_ids;
+ uint16_t *free_rx_ids;
+ };
struct ena_com_dev *ena_dev;
struct ena_adapter *adapter;
struct ena_com_io_cq *ena_com_io_cq;
Index: sys/dev/ena/ena.c
===================================================================
--- sys/dev/ena/ena.c
+++ sys/dev/ena/ena.c
@@ -102,6 +102,7 @@
static void ena_free_tx_resources(struct ena_adapter *, int);
static int ena_setup_all_tx_resources(struct ena_adapter *);
static void ena_free_all_tx_resources(struct ena_adapter *);
+static inline int validate_rx_req_id(struct ena_ring *, uint16_t);
static int ena_setup_rx_resources(struct ena_adapter *, unsigned int);
static void ena_free_rx_resources(struct ena_adapter *, unsigned int);
static int ena_setup_all_rx_resources(struct ena_adapter *);
@@ -780,6 +781,23 @@
return;
}
+static inline int
+validate_rx_req_id(struct ena_ring *rx_ring, uint16_t req_id)
+{
+ if (likely(req_id < rx_ring->ring_size))
+ return (0);
+
+ device_printf(rx_ring->adapter->pdev, "Invalid rx req_id: %hu\n",
+ req_id);
+ counter_u64_add(rx_ring->rx_stats.bad_req_id, 1);
+
+ /* Trigger device reset */
+ rx_ring->adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID;
+ rx_ring->adapter->trigger_reset = true;
+
+ return (EFAULT);
+}
+
/**
* ena_setup_rx_resources - allocate Rx resources (Descriptors)
* @adapter: network interface device structure
@@ -809,6 +827,14 @@
if (rx_ring->rx_buffer_info == NULL)
return (ENOMEM);
+ size = sizeof(uint16_t) * rx_ring->ring_size;
+ rx_ring->free_rx_ids = malloc(size, M_DEVBUF, M_WAITOK);
+ if (unlikely(rx_ring->free_rx_ids == NULL))
+ goto err_buf_info_free;
+
+ for (i = 0; i < rx_ring->ring_size; i++)
+ rx_ring->free_rx_ids[i] = i;
+
/* Reset RX statistics. */
ena_reset_counters((counter_u64_t *)&rx_ring->rx_stats,
sizeof(rx_ring->rx_stats));
@@ -848,6 +874,9 @@
rx_ring->rx_buffer_info[i].map);
}
+ free(rx_ring->free_rx_ids, M_DEVBUF);
+ rx_ring->free_rx_ids = NULL;
+err_buf_info_free:
free(rx_ring->rx_buffer_info, M_DEVBUF);
rx_ring->rx_buffer_info = NULL;
ena_trace(ENA_ALERT, "RX resource allocation fail");
@@ -885,6 +914,9 @@
free(rx_ring->rx_buffer_info, M_DEVBUF);
rx_ring->rx_buffer_info = NULL;
+ free(rx_ring->free_rx_ids, M_DEVBUF);
+ rx_ring->free_rx_ids = NULL;
+
return;
}
@@ -1014,7 +1046,7 @@
ena_refill_rx_bufs(struct ena_ring *rx_ring, uint32_t num)
{
struct ena_adapter *adapter = rx_ring->adapter;
- uint16_t next_to_use;
+ uint16_t next_to_use, req_id;
uint32_t i;
int rc;
@@ -1024,11 +1056,17 @@
next_to_use = rx_ring->next_to_use;
for (i = 0; i < num; i++) {
+ struct ena_rx_buffer *rx_info;
+
ena_trace(ENA_DBG | ENA_RXPTH | ENA_RSC,
"RX buffer - next to use: %d", next_to_use);
- struct ena_rx_buffer *rx_info =
- &rx_ring->rx_buffer_info[next_to_use];
+ req_id = rx_ring->free_rx_ids[next_to_use];
+ rc = validate_rx_req_id(rx_ring, req_id);
+ if (unlikely(rc))
+ break;
+
+ rx_info = &rx_ring->rx_buffer_info[req_id];
rc = ena_alloc_rx_mbuf(adapter, rx_ring, rx_info);
if (rc != 0) {
@@ -1037,7 +1075,7 @@
break;
}
rc = ena_com_add_single_rx_desc(rx_ring->ena_com_io_sq,
- &rx_info->ena_buf, next_to_use);
+ &rx_info->ena_buf, req_id);
if (unlikely(rc)) {
device_printf(adapter->pdev,
"failed to add buffer for rx queue %d\n",
@@ -1421,7 +1459,7 @@
* @rx_ring: ring for which we want to clean packets
* @ena_bufs: buffer info
* @ena_rx_ctx: metadata for this packet(s)
- * @next_to_clean: ring pointer
+ * @next_to_clean: ring pointer, will be updated only upon success
*
**/
static struct mbuf*
@@ -1431,15 +1469,22 @@
struct mbuf *mbuf;
struct ena_rx_buffer *rx_info;
struct ena_adapter *adapter;
- unsigned int len, buf = 0;
unsigned int descs = ena_rx_ctx->descs;
+ uint16_t ntc, len, req_id, buf = 0;
+ ntc = *next_to_clean;
adapter = rx_ring->adapter;
- rx_info = &rx_ring->rx_buffer_info[*next_to_clean];
+ rx_info = &rx_ring->rx_buffer_info[ntc];
+
+ if (unlikely(rx_info->mbuf == NULL)) {
+ device_printf(adapter->pdev, "NULL mbuf in rx_info");
+ return (NULL);
+ }
- ENA_ASSERT(rx_info->mbuf, "Invalid alloc frag buffer\n");
+ len = ena_bufs[buf].len;
+ req_id = ena_bufs[buf].req_id;
+ rx_info = &rx_ring->rx_buffer_info[req_id];
- len = ena_bufs[0].len;
ena_trace(ENA_DBG | ENA_RXPTH, "rx_info %p, mbuf %p, paddr %jx",
rx_info, rx_info->mbuf, (uintmax_t)rx_info->ena_buf.paddr);
@@ -1459,18 +1504,35 @@
bus_dmamap_unload(rx_ring->adapter->rx_buf_tag, rx_info->map);
rx_info->mbuf = NULL;
- *next_to_clean = ENA_RX_RING_IDX_NEXT(*next_to_clean,
- rx_ring->ring_size);
+ rx_ring->free_rx_ids[ntc] = req_id;
+ ntc = ENA_RX_RING_IDX_NEXT(ntc, rx_ring->ring_size);
/*
* While we have more than 1 descriptors for one rcvd packet, append
* other mbufs to the main one
*/
while (--descs) {
- rx_info = &rx_ring->rx_buffer_info[*next_to_clean];
- len = ena_bufs[++buf].len;
+ ++buf;
+ len = ena_bufs[buf].len;
+ req_id = ena_bufs[buf].req_id;
+ rx_info = &rx_ring->rx_buffer_info[req_id];
+
+ if (unlikely(rx_info->mbuf == NULL)) {
+ device_printf(adapter->pdev, "NULL mbuf in rx_info");
+ /*
+ * If one of the required mbufs was not allocated yet,
+ * we can break there.
+ * All earlier used descriptors will be reallocated
+ * later and not used mbufs can be reused.
+ * The next_to_clean pointer will not be updated in case
+ * of an error, so caller should advance it manually
+ * in error handling routine to keep it up to date
+ * with hw ring.
+ */
+ goto err_mbuf_null;
+ }
- if (!m_append(mbuf, len, rx_info->mbuf->m_data)) {
+ if (m_append(mbuf, len, rx_info->mbuf->m_data) == 0) {
counter_u64_add(rx_ring->rx_stats.mbuf_alloc_fail, 1);
ena_trace(ENA_WARNING, "Failed to append Rx mbuf %p",
mbuf);
@@ -1480,11 +1542,18 @@
m_freem(rx_info->mbuf);
rx_info->mbuf = NULL;
- *next_to_clean = ENA_RX_RING_IDX_NEXT(*next_to_clean,
- rx_ring->ring_size);
+ rx_ring->free_rx_ids[ntc] = req_id;
+ ntc = ENA_RX_RING_IDX_NEXT(ntc, rx_ring->ring_size);
}
+ *next_to_clean = ntc;
+
return (mbuf);
+
+err_mbuf_null:
+ m_freem(mbuf);
+
+ return (NULL);
}
/**
@@ -1540,7 +1609,7 @@
uint32_t refill_threshold;
uint32_t do_if_input = 0;
unsigned int qid;
- int rc;
+ int rc, i;
int budget = RX_BUDGET;
adapter = rx_ring->que->adapter;
@@ -1569,8 +1638,14 @@
/* Exit if we failed to retrieve a buffer */
if (unlikely(!mbuf)) {
- next_to_clean = ENA_RX_RING_IDX_ADD(next_to_clean,
- ena_rx_ctx.descs, rx_ring->ring_size);
+ for (i = 0; i < ena_rx_ctx.descs; ++i) {
+ rx_ring->free_tx_ids[next_to_clean] =
+ rx_ring->ena_bufs[i].req_id;
+ next_to_clean =
+ ENA_RX_RING_IDX_NEXT(next_to_clean,
+ rx_ring->ring_size);
+
+ }
break;
}
ena_trace(ENA_DBG | ENA_RXPTH, "Rx: %d bytes",
Index: sys/dev/ena/ena_sysctl.c
===================================================================
--- sys/dev/ena/ena_sysctl.c
+++ sys/dev/ena/ena_sysctl.c
@@ -197,6 +197,9 @@
SYSCTL_ADD_COUNTER_U64(ctx, rx_list, OID_AUTO,
"small_copy_len_pkt", CTLFLAG_RD,
&rx_stats->small_copy_len_pkt, "Small copy packet count");
+ SYSCTL_ADD_COUNTER_U64(ctx, rx_list, OID_AUTO,
+ "bad_req_id", CTLFLAG_RD,
+ &rx_stats->bad_req_id, "Bad request id count");
}
/* Stats read from device */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jul 22, 6:25 AM (13 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35351302
Default Alt Text
D12855.id34518.diff (7 KB)
Attached To
Mode
D12855: Add RX OOO completion feature
Attached
Detach File
Event Timeline
Log In to Comment