aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2022-08-26 14:13:52 +0100
committerMichael Brown <mcb30@ipxe.org>2022-08-26 19:37:54 +0100
commit856ffe000e79a1af24ea11301447dd70b8d54ac2 (patch)
tree7d8f0ed41689425803f0c19eed5207de1d32e6b0
parentc5af41a6f5b5f4a420b3e539f9e3a8dc9f8dd03e (diff)
downloadipxe-856ffe000e79a1af24ea11301447dd70b8d54ac2.zip
ipxe-856ffe000e79a1af24ea11301447dd70b8d54ac2.tar.gz
ipxe-856ffe000e79a1af24ea11301447dd70b8d54ac2.tar.bz2
[ena] Limit submission queue fill level to completion queue size
The CREATE_CQ command is permitted to return a size smaller than requested, which could leave us in a situation where the completion queue could overflow. Avoid overflow by limiting the submission queue fill level to the actual size of the completion queue. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/drivers/net/ena.c13
-rw-r--r--src/drivers/net/ena.h2
2 files changed, 11 insertions, 4 deletions
diff --git a/src/drivers/net/ena.c b/src/drivers/net/ena.c
index 85da1c0..9f52a65 100644
--- a/src/drivers/net/ena.c
+++ b/src/drivers/net/ena.c
@@ -391,11 +391,16 @@ static int ena_create_sq ( struct ena_nic *ena, struct ena_sq *sq,
sq->prod = 0;
sq->phase = ENA_SQE_PHASE;
- DBGC ( ena, "ENA %p %s SQ%d at [%08lx,%08lx) db +%04x CQ%d\n",
+ /* Calculate fill level */
+ sq->fill = sq->count;
+ if ( sq->fill > cq->actual )
+ sq->fill = cq->actual;
+
+ DBGC ( ena, "ENA %p %s SQ%d at [%08lx,%08lx) fill %d db +%04x CQ%d\n",
ena, ena_direction ( sq->direction ), sq->id,
virt_to_phys ( sq->sqe.raw ),
( virt_to_phys ( sq->sqe.raw ) + sq->len ),
- sq->doorbell, cq->id );
+ sq->fill, sq->doorbell, cq->id );
return 0;
err_admin:
@@ -658,7 +663,7 @@ static void ena_refill_rx ( struct net_device *netdev ) {
unsigned int refilled = 0;
/* Refill queue */
- while ( ( ena->rx.sq.prod - ena->rx.cq.cons ) < ENA_RX_COUNT ) {
+ while ( ( ena->rx.sq.prod - ena->rx.cq.cons ) < ena->rx.sq.fill ) {
/* Allocate I/O buffer */
iobuf = alloc_iob ( len );
@@ -783,7 +788,7 @@ static int ena_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
size_t len;
/* Get next submission queue entry */
- if ( ( ena->tx.sq.prod - ena->tx.cq.cons ) >= ENA_TX_COUNT ) {
+ if ( ( ena->tx.sq.prod - ena->tx.cq.cons ) >= ena->tx.sq.fill ) {
DBGC ( ena, "ENA %p out of transmit descriptors\n", ena );
return -ENOBUFS;
}
diff --git a/src/drivers/net/ena.h b/src/drivers/net/ena.h
index 676c5b8..2832b67 100644
--- a/src/drivers/net/ena.h
+++ b/src/drivers/net/ena.h
@@ -496,6 +496,8 @@ struct ena_sq {
uint8_t direction;
/** Number of entries */
uint8_t count;
+ /** Fill level (limited to completion queue size) */
+ uint8_t fill;
};
/**