Skip to content

Commit ad974ba

Browse files
NetanelBelgazaldavem330
authored andcommitted
net: ena: add support for out of order rx buffers refill
ENA driver post Rx buffers through the Rx submission queue for the ENA device to fill them with receive packets. Each Rx buffer is marked with req_id in the Rx descriptor. Newer ENA devices could consume the posted Rx buffer in out of order, and as result the corresponding Rx completion queue will have Rx completion descriptors with non contiguous req_id(s) In this change the driver holds two rings. The first ring (called free_rx_ids) is a mapping ring. It holds all the unused request ids. The values in this ring are from 0 to ring_size -1. When the driver wants to allocate a new Rx buffer it uses the head of free_rx_ids and uses it's value as the index for rx_buffer_info ring. The req_id is also written to the Rx descriptor Upon Rx completion, The driver took the req_id from the completion descriptor and uses it as index in rx_buffer_info. The req_id is then return to the free_rx_ids ring. This patch also adds statistics to inform when the driver receive out of range or unused req_id. Note: free_rx_ids is only accessible from the napi handler, so no locking is required Signed-off-by: Netanel Belgazal <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e2eed0e commit ad974ba

File tree

4 files changed

+83
-17
lines changed

4 files changed

+83
-17
lines changed

drivers/net/ethernet/amazon/ena/ena_eth_com.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,11 @@ int ena_com_tx_comp_req_id_get(struct ena_com_io_cq *io_cq, u16 *req_id)
493493
if (cdesc_phase != expected_phase)
494494
return -EAGAIN;
495495

496+
if (unlikely(cdesc->req_id >= io_cq->q_depth)) {
497+
pr_err("Invalid req id %d\n", cdesc->req_id);
498+
return -EINVAL;
499+
}
500+
496501
ena_com_cq_inc_head(io_cq);
497502

498503
*req_id = READ_ONCE(cdesc->req_id);

drivers/net/ethernet/amazon/ena/ena_ethtool.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ static const struct ena_stats ena_stats_rx_strings[] = {
9393
ENA_STAT_RX_ENTRY(dma_mapping_err),
9494
ENA_STAT_RX_ENTRY(bad_desc_num),
9595
ENA_STAT_RX_ENTRY(rx_copybreak_pkt),
96+
ENA_STAT_RX_ENTRY(bad_req_id),
9697
ENA_STAT_RX_ENTRY(empty_rx_ring),
9798
};
9899

drivers/net/ethernet/amazon/ena/ena_netdev.c

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,24 @@ static void ena_free_all_io_tx_resources(struct ena_adapter *adapter)
304304
ena_free_tx_resources(adapter, i);
305305
}
306306

307+
static inline int validate_rx_req_id(struct ena_ring *rx_ring, u16 req_id)
308+
{
309+
if (likely(req_id < rx_ring->ring_size))
310+
return 0;
311+
312+
netif_err(rx_ring->adapter, rx_err, rx_ring->netdev,
313+
"Invalid rx req_id: %hu\n", req_id);
314+
315+
u64_stats_update_begin(&rx_ring->syncp);
316+
rx_ring->rx_stats.bad_req_id++;
317+
u64_stats_update_end(&rx_ring->syncp);
318+
319+
/* Trigger device reset */
320+
rx_ring->adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID;
321+
set_bit(ENA_FLAG_TRIGGER_RESET, &rx_ring->adapter->flags);
322+
return -EFAULT;
323+
}
324+
307325
/* ena_setup_rx_resources - allocate I/O Rx resources (Descriptors)
308326
* @adapter: network interface device structure
309327
* @qid: queue index
@@ -315,7 +333,7 @@ static int ena_setup_rx_resources(struct ena_adapter *adapter,
315333
{
316334
struct ena_ring *rx_ring = &adapter->rx_ring[qid];
317335
struct ena_irq *ena_irq = &adapter->irq_tbl[ENA_IO_IRQ_IDX(qid)];
318-
int size, node;
336+
int size, node, i;
319337

320338
if (rx_ring->rx_buffer_info) {
321339
netif_err(adapter, ifup, adapter->netdev,
@@ -336,6 +354,20 @@ static int ena_setup_rx_resources(struct ena_adapter *adapter,
336354
return -ENOMEM;
337355
}
338356

357+
size = sizeof(u16) * rx_ring->ring_size;
358+
rx_ring->free_rx_ids = vzalloc_node(size, node);
359+
if (!rx_ring->free_rx_ids) {
360+
rx_ring->free_rx_ids = vzalloc(size);
361+
if (!rx_ring->free_rx_ids) {
362+
vfree(rx_ring->rx_buffer_info);
363+
return -ENOMEM;
364+
}
365+
}
366+
367+
/* Req id ring for receiving RX pkts out of order */
368+
for (i = 0; i < rx_ring->ring_size; i++)
369+
rx_ring->free_rx_ids[i] = i;
370+
339371
/* Reset rx statistics */
340372
memset(&rx_ring->rx_stats, 0x0, sizeof(rx_ring->rx_stats));
341373

@@ -359,6 +391,9 @@ static void ena_free_rx_resources(struct ena_adapter *adapter,
359391

360392
vfree(rx_ring->rx_buffer_info);
361393
rx_ring->rx_buffer_info = NULL;
394+
395+
vfree(rx_ring->free_rx_ids);
396+
rx_ring->free_rx_ids = NULL;
362397
}
363398

364399
/* ena_setup_all_rx_resources - allocate I/O Rx queues resources for all queues
@@ -464,15 +499,22 @@ static void ena_free_rx_page(struct ena_ring *rx_ring,
464499

465500
static int ena_refill_rx_bufs(struct ena_ring *rx_ring, u32 num)
466501
{
467-
u16 next_to_use;
502+
u16 next_to_use, req_id;
468503
u32 i;
469504
int rc;
470505

471506
next_to_use = rx_ring->next_to_use;
472507

473508
for (i = 0; i < num; i++) {
474-
struct ena_rx_buffer *rx_info =
475-
&rx_ring->rx_buffer_info[next_to_use];
509+
struct ena_rx_buffer *rx_info;
510+
511+
req_id = rx_ring->free_rx_ids[next_to_use];
512+
rc = validate_rx_req_id(rx_ring, req_id);
513+
if (unlikely(rc < 0))
514+
break;
515+
516+
rx_info = &rx_ring->rx_buffer_info[req_id];
517+
476518

477519
rc = ena_alloc_rx_page(rx_ring, rx_info,
478520
__GFP_COLD | GFP_ATOMIC | __GFP_COMP);
@@ -484,7 +526,7 @@ static int ena_refill_rx_bufs(struct ena_ring *rx_ring, u32 num)
484526
}
485527
rc = ena_com_add_single_rx_desc(rx_ring->ena_com_io_sq,
486528
&rx_info->ena_buf,
487-
next_to_use);
529+
req_id);
488530
if (unlikely(rc)) {
489531
netif_warn(rx_ring->adapter, rx_status, rx_ring->netdev,
490532
"failed to add buffer for rx queue %d\n",
@@ -789,13 +831,14 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
789831
u16 *next_to_clean)
790832
{
791833
struct sk_buff *skb;
792-
struct ena_rx_buffer *rx_info =
793-
&rx_ring->rx_buffer_info[*next_to_clean];
794-
u32 len;
795-
u32 buf = 0;
834+
struct ena_rx_buffer *rx_info;
835+
u16 len, req_id, buf = 0;
796836
void *va;
797837

798-
len = ena_bufs[0].len;
838+
len = ena_bufs[buf].len;
839+
req_id = ena_bufs[buf].req_id;
840+
rx_info = &rx_ring->rx_buffer_info[req_id];
841+
799842
if (unlikely(!rx_info->page)) {
800843
netif_err(rx_ring->adapter, rx_err, rx_ring->netdev,
801844
"Page is NULL\n");
@@ -867,13 +910,18 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
867910
skb->len, skb->data_len);
868911

869912
rx_info->page = NULL;
913+
914+
rx_ring->free_rx_ids[*next_to_clean] = req_id;
870915
*next_to_clean =
871916
ENA_RX_RING_IDX_NEXT(*next_to_clean,
872917
rx_ring->ring_size);
873918
if (likely(--descs == 0))
874919
break;
875-
rx_info = &rx_ring->rx_buffer_info[*next_to_clean];
876-
len = ena_bufs[++buf].len;
920+
921+
buf++;
922+
len = ena_bufs[buf].len;
923+
req_id = ena_bufs[buf].req_id;
924+
rx_info = &rx_ring->rx_buffer_info[req_id];
877925
} while (1);
878926

879927
return skb;
@@ -974,6 +1022,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
9741022
int rc = 0;
9751023
int total_len = 0;
9761024
int rx_copybreak_pkt = 0;
1025+
int i;
9771026

9781027
netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
9791028
"%s qid %d\n", __func__, rx_ring->qid);
@@ -1003,9 +1052,13 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
10031052

10041053
/* exit if we failed to retrieve a buffer */
10051054
if (unlikely(!skb)) {
1006-
next_to_clean = ENA_RX_RING_IDX_ADD(next_to_clean,
1007-
ena_rx_ctx.descs,
1008-
rx_ring->ring_size);
1055+
for (i = 0; i < ena_rx_ctx.descs; i++) {
1056+
rx_ring->free_tx_ids[next_to_clean] =
1057+
rx_ring->ena_bufs[i].req_id;
1058+
next_to_clean =
1059+
ENA_RX_RING_IDX_NEXT(next_to_clean,
1060+
rx_ring->ring_size);
1061+
}
10091062
break;
10101063
}
10111064

drivers/net/ethernet/amazon/ena/ena_netdev.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,19 @@ struct ena_stats_rx {
194194
u64 dma_mapping_err;
195195
u64 bad_desc_num;
196196
u64 rx_copybreak_pkt;
197+
u64 bad_req_id;
197198
u64 empty_rx_ring;
198199
};
199200

200201
struct ena_ring {
201-
/* Holds the empty requests for TX out of order completions */
202-
u16 *free_tx_ids;
202+
union {
203+
/* Holds the empty requests for TX/RX
204+
* out of order completions
205+
*/
206+
u16 *free_tx_ids;
207+
u16 *free_rx_ids;
208+
};
209+
203210
union {
204211
struct ena_tx_buffer *tx_buffer_info;
205212
struct ena_rx_buffer *rx_buffer_info;

0 commit comments

Comments
 (0)