diff options
author | Michael Brown <mcb30@ipxe.org> | 2022-08-26 14:13:52 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2022-08-26 19:37:54 +0100 |
commit | 856ffe000e79a1af24ea11301447dd70b8d54ac2 (patch) | |
tree | 7d8f0ed41689425803f0c19eed5207de1d32e6b0 | |
parent | c5af41a6f5b5f4a420b3e539f9e3a8dc9f8dd03e (diff) | |
download | ipxe-856ffe000e79a1af24ea11301447dd70b8d54ac2.tar.gz |
[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.c | 13 | ||||
-rw-r--r-- | src/drivers/net/ena.h | 2 |
2 files changed, 11 insertions, 4 deletions
diff --git a/src/drivers/net/ena.c b/src/drivers/net/ena.c index 85da1c090..9f52a658e 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 676c5b878..2832b67e5 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; }; /** |