Download raw body.
interface multiqueue timout race
On Wed, Oct 02, 2024 at 05:01:39PM +1000, Jonathan Matthew wrote:
> I'd rather fix the driver so it doesn't need this.
> The problem here seems to be that bnxt has two rings to refill, and
> the timeout tries to refill them both, even if one of them is not empty.
> Can you try this diff instead?
Works for me. OK bluhm@
> diff --git a/sys/dev/pci/if_bnxt.c b/sys/dev/pci/if_bnxt.c
> index 52165d95f2c..5a40908cb1e 100644
> --- a/sys/dev/pci/if_bnxt.c
> +++ b/sys/dev/pci/if_bnxt.c
> @@ -315,7 +315,7 @@ void bnxt_write_rx_doorbell(struct bnxt_softc *, struct bnxt_ring *,
> void bnxt_write_tx_doorbell(struct bnxt_softc *, struct bnxt_ring *,
> int);
>
> -int bnxt_rx_fill(struct bnxt_queue *);
> +int bnxt_rx_fill(struct bnxt_queue *, int, int);
> u_int bnxt_rx_fill_slots(struct bnxt_softc *, struct bnxt_ring *, void *,
> struct bnxt_slot *, uint *, int, uint16_t, u_int);
> void bnxt_refill(void *);
> @@ -954,7 +954,7 @@ bnxt_queue_up(struct bnxt_softc *sc, struct bnxt_queue *bq)
> rx->rx_cons = 0;
> rx->rx_ag_prod = 0;
> rx->rx_ag_cons = 0;
> - bnxt_rx_fill(bq);
> + bnxt_rx_fill(bq, 1, 1);
>
> tx->tx_cons = 0;
> tx->tx_prod = 0;
> @@ -1658,7 +1658,7 @@ bnxt_intr(void *xq)
> if_rxr_livelocked(&rx->rxr[1]);
> }
>
> - bnxt_rx_fill(q);
> + bnxt_rx_fill(q, 1, 1);
> if ((rx->rx_cons == rx->rx_prod) ||
> (rx->rx_ag_cons == rx->rx_ag_prod))
> timeout_add(&rx->rx_refill, 0);
> @@ -2216,33 +2216,37 @@ bnxt_rx_fill_slots(struct bnxt_softc *sc, struct bnxt_ring *ring, void *ring_mem
> }
>
> int
> -bnxt_rx_fill(struct bnxt_queue *q)
> +bnxt_rx_fill(struct bnxt_queue *q, int rxring, int agring)
> {
> struct bnxt_rx_queue *rx = &q->q_rx;
> struct bnxt_softc *sc = q->q_sc;
> u_int slots;
> int rv = 0;
>
> - slots = if_rxr_get(&rx->rxr[0], rx->rx_ring.ring_size);
> - if (slots > 0) {
> - slots = bnxt_rx_fill_slots(sc, &rx->rx_ring,
> - BNXT_DMA_KVA(rx->rx_ring_mem), rx->rx_slots,
> - &rx->rx_prod, MCLBYTES,
> - RX_PROD_PKT_BD_TYPE_RX_PROD_PKT, slots);
> - if_rxr_put(&rx->rxr[0], slots);
> - } else
> - rv = 1;
> -
> - slots = if_rxr_get(&rx->rxr[1], rx->rx_ag_ring.ring_size);
> - if (slots > 0) {
> - slots = bnxt_rx_fill_slots(sc, &rx->rx_ag_ring,
> - BNXT_DMA_KVA(rx->rx_ring_mem) + PAGE_SIZE,
> - rx->rx_ag_slots, &rx->rx_ag_prod,
> - BNXT_AG_BUFFER_SIZE,
> - RX_PROD_AGG_BD_TYPE_RX_PROD_AGG, slots);
> - if_rxr_put(&rx->rxr[1], slots);
> - } else
> - rv = 1;
> + if (rxring != 0) {
> + slots = if_rxr_get(&rx->rxr[0], rx->rx_ring.ring_size);
> + if (slots > 0) {
> + slots = bnxt_rx_fill_slots(sc, &rx->rx_ring,
> + BNXT_DMA_KVA(rx->rx_ring_mem), rx->rx_slots,
> + &rx->rx_prod, MCLBYTES,
> + RX_PROD_PKT_BD_TYPE_RX_PROD_PKT, slots);
> + if_rxr_put(&rx->rxr[0], slots);
> + } else
> + rv = 1;
> + }
> +
> + if (agring != 0) {
> + slots = if_rxr_get(&rx->rxr[1], rx->rx_ag_ring.ring_size);
> + if (slots > 0) {
> + slots = bnxt_rx_fill_slots(sc, &rx->rx_ag_ring,
> + BNXT_DMA_KVA(rx->rx_ring_mem) + PAGE_SIZE,
> + rx->rx_ag_slots, &rx->rx_ag_prod,
> + BNXT_AG_BUFFER_SIZE,
> + RX_PROD_AGG_BD_TYPE_RX_PROD_AGG, slots);
> + if_rxr_put(&rx->rxr[1], slots);
> + } else
> + rv = 1;
> + }
>
> return (rv);
> }
> @@ -2253,9 +2257,10 @@ bnxt_refill(void *xq)
> struct bnxt_queue *q = xq;
> struct bnxt_rx_queue *rx = &q->q_rx;
>
> - bnxt_rx_fill(q);
> + bnxt_rx_fill(q, rx->rx_cons == rx->rx_prod, rx->rx_ag_cons == rx->rx_ag_prod);
>
> - if (rx->rx_cons == rx->rx_prod)
> + if ((rx->rx_cons == rx->rx_prod) ||
> + (rx->rx_ag_cons == rx->rx_ag_prod))
> timeout_add(&rx->rx_refill, 1);
> }
>
interface multiqueue timout race