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: Wright Feng <wright.feng@cypress.com> Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@cypress.com> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Signed-off-by: Kalle Valo <kvalo@kernel.org> Link: https://lore.kernel.org/r/20220722115632.620681-3-alvin@pqrs.dk
This commit is contained in:
parent
0fa24196e4
commit
09be7546a6
|
@ -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,10 +457,8 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue