Commit 09be7546 authored by Wright Feng's avatar Wright Feng Committed by Kalle Valo

wifi: brcmfmac: fix scheduling while atomic issue when deleting flowring

We should not sleep while holding the spin lock. It makes
'scheduling while atomic' in brcmf_msgbuf_delete_flowring.
And to avoid race condition between deleting flowring and txflow,
we only hold spin lock when seting flowring status to RING_CLOSING.
Signed-off-by: default avatarWright Feng <wright.feng@cypress.com>
Signed-off-by: default avatarChi-Hsien Lin <chi-hsien.lin@cypress.com>
Signed-off-by: default avatarAhmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: default avatarAlvin Šipraga <alsi@bang-olufsen.dk>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220722115632.620681-3-alvin@pqrs.dk
parent 0fa24196
......@@ -419,7 +419,6 @@ void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
flowid = flow->hash[i].flowid;
if (flow->rings[flowid]->status != RING_OPEN)
continue;
flow->rings[flowid]->status = RING_CLOSING;
brcmf_msgbuf_delete_flowring(drvr, flowid);
}
}
......@@ -458,12 +457,10 @@ void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
if ((sta || (memcmp(hash[i].mac, peer, ETH_ALEN) == 0)) &&
(hash[i].ifidx == ifidx)) {
flowid = flow->hash[i].flowid;
if (flow->rings[flowid]->status == RING_OPEN) {
flow->rings[flowid]->status = RING_CLOSING;
if (flow->rings[flowid]->status == RING_OPEN)
brcmf_msgbuf_delete_flowring(drvr, flowid);
}
}
}
if (search) {
if (prev)
......
......@@ -1400,22 +1400,24 @@ void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid)
struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
struct msgbuf_tx_flowring_delete_req *delete;
struct brcmf_commonring *commonring;
struct brcmf_commonring *commonring_del;
struct brcmf_commonring *commonring_del = msgbuf->flowrings[flowid];
struct brcmf_flowring *flow = msgbuf->flow;
void *ret_ptr;
u8 ifidx;
int err;
int retry = BRCMF_MAX_TXSTATUS_WAIT_RETRIES;
/* wait for commonring txflow finished */
commonring_del = msgbuf->flowrings[flowid];
/* make sure it is not in txflow */
brcmf_commonring_lock(commonring_del);
flow->rings[flowid]->status = RING_CLOSING;
brcmf_commonring_unlock(commonring_del);
/* wait for commonring txflow finished */
while (retry && atomic_read(&commonring_del->outstanding_tx)) {
usleep_range(5000, 10000);
retry--;
}
brcmf_commonring_unlock(commonring_del);
if (!retry && atomic_read(&commonring_del->outstanding_tx)) {
if (!retry) {
brcmf_err("timed out waiting for txstatus\n");
atomic_set(&commonring_del->outstanding_tx, 0);
}
......
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