Commit 86ec882f authored by Ioana Ciornei's avatar Ioana Ciornei Committed by David S. Miller

soc: fsl: dpio: read the consumer index from the cache inhibited area

Once we added support in the dpaa2-eth for driver level software TSO we
observed the following situation: if the EQCR CI (consumer index) is
read from the cache-enabled area we sometimes end up with a computed
value of available enqueue entries bigger than the size of the ring.

This eventually will lead to the multiple enqueue of the same FD which
will determine the same FD to end up on the Tx confirmation path and the
same skb being freed twice.

Just read the consumer index from the cache inhibited area so that we
avoid this situation.
Signed-off-by: default avatarIoana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3dc709e0
...@@ -743,8 +743,8 @@ int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, ...@@ -743,8 +743,8 @@ int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
full_mask = s->eqcr.pi_ci_mask; full_mask = s->eqcr.pi_ci_mask;
if (!s->eqcr.available) { if (!s->eqcr.available) {
eqcr_ci = s->eqcr.ci; eqcr_ci = s->eqcr.ci;
p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI_MEMBACK; s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI);
s->eqcr.ci = *p & full_mask; s->eqcr.ci &= full_mask;
s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size, s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
eqcr_ci, s->eqcr.ci); eqcr_ci, s->eqcr.ci);
if (!s->eqcr.available) { if (!s->eqcr.available) {
...@@ -887,8 +887,8 @@ int qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s, ...@@ -887,8 +887,8 @@ int qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s,
full_mask = s->eqcr.pi_ci_mask; full_mask = s->eqcr.pi_ci_mask;
if (!s->eqcr.available) { if (!s->eqcr.available) {
eqcr_ci = s->eqcr.ci; eqcr_ci = s->eqcr.ci;
p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI_MEMBACK; s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI);
s->eqcr.ci = *p & full_mask; s->eqcr.ci &= full_mask;
s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size, s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
eqcr_ci, s->eqcr.ci); eqcr_ci, s->eqcr.ci);
if (!s->eqcr.available) if (!s->eqcr.available)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment