brcmfmac: reserve 2 credits for host tx control path
It is observed that sometimes when sdiod is low in tx credits in low rssi scenarios, the data path consumes all sdiod rx all credits and there is no sdiod rx credit available for control path causing host and card to go out of sync resulting in link loss between host and card. So in order to prevent it some credits are reserved for control path. Note that TXCTL_CREDITS can't be larger than the firmware default credit update threshold 2; otherwise there will be a deadlock for both side waiting for each other. Signed-off-by: Amar Shankar <amsr@cypress.com> Signed-off-by: Jia-Shyr Chuang <joseph.chuang@cypress.com> Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@cypress.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/20200610152106.175257-4-chi-hsien.lin@cypress.com
This commit is contained in:
parent
fc4aa12597
commit
b41c232d33
|
@ -648,6 +648,8 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
|
|||
BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012)
|
||||
};
|
||||
|
||||
#define TXCTL_CREDITS 2
|
||||
|
||||
static void pkt_align(struct sk_buff *p, int len, int align)
|
||||
{
|
||||
uint datalign;
|
||||
|
@ -661,8 +663,16 @@ static void pkt_align(struct sk_buff *p, int len, int align)
|
|||
/* To check if there's window offered */
|
||||
static bool data_ok(struct brcmf_sdio *bus)
|
||||
{
|
||||
return (u8)(bus->tx_max - bus->tx_seq) != 0 &&
|
||||
((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
|
||||
/* Reserve TXCTL_CREDITS credits for txctl */
|
||||
return (bus->tx_max - bus->tx_seq) > TXCTL_CREDITS &&
|
||||
((bus->tx_max - bus->tx_seq) & 0x80) == 0;
|
||||
}
|
||||
|
||||
/* To check if there's window offered */
|
||||
static bool txctl_ok(struct brcmf_sdio *bus)
|
||||
{
|
||||
return (bus->tx_max - bus->tx_seq) != 0 &&
|
||||
((bus->tx_max - bus->tx_seq) & 0x80) == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2668,7 +2678,7 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
|
|||
brcmf_sdio_clrintr(bus);
|
||||
|
||||
if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) &&
|
||||
data_ok(bus)) {
|
||||
txctl_ok(bus)) {
|
||||
sdio_claim_host(bus->sdiodev->func1);
|
||||
if (bus->ctrl_frame_stat) {
|
||||
err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf,
|
||||
|
@ -2676,6 +2686,9 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
|
|||
bus->ctrl_frame_err = err;
|
||||
wmb();
|
||||
bus->ctrl_frame_stat = false;
|
||||
if (err)
|
||||
brcmf_err("sdio ctrlframe tx failed err=%d\n",
|
||||
err);
|
||||
}
|
||||
sdio_release_host(bus->sdiodev->func1);
|
||||
brcmf_sdio_wait_event_wakeup(bus);
|
||||
|
|
Loading…
Reference in New Issue