enetc: Simply TX ring credits counting logic

According to the RM rings can hold at most ring_size - 1 descriptors at any time.
No additional logic is needed since iflib already respects this constrain.
Thanks to that the pidx == cidx situation is not ambiguous and indicates an
empty ring.
Use that to simplify the logic that calculates the amount of processed frames.

Obtained from: Semihalf
Sponsored by: Alstom Group
This commit is contained in:
Kornel Duleba 2022-01-27 10:24:26 +01:00 committed by Wojciech Macek
parent f485d733e8
commit a6bda3e1ef
2 changed files with 21 additions and 18 deletions

View File

@ -52,8 +52,7 @@ struct enetc_tx_queue {
union enetc_tx_bd *ring;
uint64_t ring_paddr;
qidx_t next_to_clean;
bool ring_full;
qidx_t cidx;
struct if_irq irq;
};

View File

@ -503,8 +503,7 @@ enetc_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs,
queue->sc = sc;
queue->ring = (union enetc_tx_bd*)(vaddrs[i]);
queue->ring_paddr = paddrs[i];
queue->next_to_clean = 0;
queue->ring_full = false;
queue->cidx = 0;
}
return (0);
@ -1125,8 +1124,6 @@ enetc_isc_txd_encap(void *data, if_pkt_info_t ipi)
desc->flags |= ENETC_TXBD_FLAGS_F;
ipi->ipi_new_pidx = pidx;
if (pidx == queue->next_to_clean)
queue->ring_full = true;
return (0);
}
@ -1144,28 +1141,35 @@ enetc_isc_txd_credits_update(void *data, uint16_t qid, bool clear)
{
struct enetc_softc *sc = data;
struct enetc_tx_queue *queue;
qidx_t next_to_clean, next_to_process;
int clean_count;
int cidx, hw_cidx, count;
queue = &sc->tx_queues[qid];
next_to_process =
ENETC_TXQ_RD4(sc, qid, ENETC_TBCIR) & ENETC_TBCIR_IDX_MASK;
next_to_clean = queue->next_to_clean;
hw_cidx = ENETC_TXQ_RD4(sc, qid, ENETC_TBCIR) & ENETC_TBCIR_IDX_MASK;
cidx = queue->cidx;
if (next_to_clean == next_to_process && !queue->ring_full)
/*
* RM states that the ring can hold at most ring_size - 1 descriptors.
* Thanks to that we can assume that the ring is empty if cidx == pidx.
* This requirement is guaranteed implicitly by iflib as it will only
* encap a new frame if we have at least nfrags + 2 descriptors available
* on the ring. This driver uses at most one additional descriptor for
* VLAN tag insertion.
* Also RM states that the TBCIR register is only updated once all
* descriptors in the chain have been processed.
*/
if (cidx == hw_cidx)
return (0);
if (!clear)
return (1);
clean_count = next_to_process - next_to_clean;
if (clean_count <= 0)
clean_count += sc->tx_queue_size;
count = hw_cidx - cidx;
if (count < 0)
count += sc->tx_queue_size;
queue->next_to_clean = next_to_process;
queue->ring_full = false;
queue->cidx = hw_cidx;
return (clean_count);
return (count);
}
static int