wifi: brcmfmac: fix continuous 802.1x tx pending timeout error
The race condition in brcmf_msgbuf_txflow and brcmf_msgbuf_delete_flowring makes tx_msghdr writing after brcmf_msgbuf_remove_flowring. Host driver should delete flowring after txflow complete and all txstatus back, or pend_8021x_cnt will never be zero and cause every connection 950 milliseconds(MAX_WAIT_FOR_8021X_TX) delay. 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-2-alvin@pqrs.dk
This commit is contained in:
parent
bafe9528b7
commit
0fa24196e4
|
@ -1480,8 +1480,10 @@ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp)
|
|||
!brcmf_get_pend_8021x_cnt(ifp),
|
||||
MAX_WAIT_FOR_8021X_TX);
|
||||
|
||||
if (!err)
|
||||
if (!err) {
|
||||
bphy_err(drvr, "Timed out waiting for no pending 802.1x packets\n");
|
||||
atomic_set(&ifp->pend_8021x_cnt, 0);
|
||||
}
|
||||
|
||||
return !err;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
#define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32
|
||||
#define BRCMF_MSGBUF_UPDATE_RX_PTR_THRS 48
|
||||
|
||||
#define BRCMF_MAX_TXSTATUS_WAIT_RETRIES 10
|
||||
|
||||
struct msgbuf_common_hdr {
|
||||
u8 msgtype;
|
||||
|
@ -806,8 +807,12 @@ static int brcmf_msgbuf_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
|
|||
flowid = brcmf_flowring_lookup(flow, eh->h_dest, skb->priority, ifidx);
|
||||
if (flowid == BRCMF_FLOWRING_INVALID_ID) {
|
||||
flowid = brcmf_msgbuf_flowring_create(msgbuf, ifidx, skb);
|
||||
if (flowid == BRCMF_FLOWRING_INVALID_ID)
|
||||
if (flowid == BRCMF_FLOWRING_INVALID_ID) {
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
brcmf_flowring_enqueue(flow, flowid, skb);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
queue_count = brcmf_flowring_enqueue(flow, flowid, skb);
|
||||
force = ((queue_count % BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) == 0);
|
||||
|
@ -1395,9 +1400,25 @@ 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;
|
||||
|
||||
void *ret_ptr;
|
||||
u8 ifidx;
|
||||
int err;
|
||||
int retry = BRCMF_MAX_TXSTATUS_WAIT_RETRIES;
|
||||
|
||||
/* wait for commonring txflow finished */
|
||||
commonring_del = msgbuf->flowrings[flowid];
|
||||
brcmf_commonring_lock(commonring_del);
|
||||
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)) {
|
||||
brcmf_err("timed out waiting for txstatus\n");
|
||||
atomic_set(&commonring_del->outstanding_tx, 0);
|
||||
}
|
||||
|
||||
/* no need to submit if firmware can not be reached */
|
||||
if (drvr->bus_if->state != BRCMF_BUS_UP) {
|
||||
|
|
Loading…
Reference in New Issue