diff mbox series

[3/6] brcmfmac: reserve 2 credits for host tx control path

Message ID 20200609105913.163239-4-chi-hsien.lin@cypress.com (mailing list archive)
State Changes Requested
Delegated to: Kalle Valo
Headers show
Series brcmfmac: flow control and p2p fix series | expand

Commit Message

Chi-Hsien Lin June 9, 2020, 10:59 a.m. UTC
From: Amar Shankar <amsr@cypress.com>

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 <saint.chuang@cypress.com>
Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
---
 .../wireless/broadcom/brcm80211/brcmfmac/sdio.c   | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

Comments

Kalle Valo June 9, 2020, 11:51 a.m. UTC | #1
Chi-Hsien Lin <chi-hsien.lin@cypress.com> writes:

> From: Amar Shankar <amsr@cypress.com>
>
> 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 <saint.chuang@cypress.com>
> Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
> ---
>  .../wireless/broadcom/brcm80211/brcmfmac/sdio.c   | 15 ++++++++++++++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> index ce6f15284277..163bb7f41e44 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> @@ -635,6 +635,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;
> @@ -647,6 +649,14 @@ 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)
> +{
> +	/* Reserve TXCTL_CREDITS credits for txctl */
> +	return (u8)(bus->tx_max - bus->tx_seq) > TXCTL_CREDITS &&
> +	       ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
> +}

Why casting to u8? Is it really necessary?
Chi-Hsien Lin June 10, 2020, 5:19 a.m. UTC | #2
On 06/09/2020 7:51, Kalle Valo wrote:
> Chi-Hsien Lin <chi-hsien.lin@cypress.com> writes:
> 
>> From: Amar Shankar <amsr@cypress.com>
>>
>> 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 <saint.chuang@cypress.com>
>> Signed-off-by: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
>> ---
>>   .../wireless/broadcom/brcm80211/brcmfmac/sdio.c   | 15 ++++++++++++++-
>>   1 file changed, 14 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
>> index ce6f15284277..163bb7f41e44 100644
>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
>> @@ -635,6 +635,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;
>> @@ -647,6 +649,14 @@ 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)
>> +{
>> +	/* Reserve TXCTL_CREDITS credits for txctl */
>> +	return (u8)(bus->tx_max - bus->tx_seq) > TXCTL_CREDITS &&
>> +	       ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
>> +}
> 
> Why casting to u8? Is it really necessary?

I don't think the casting is necessary since tx_max and tx_seq are both u8.

The code is taken from a similar function data_ok(). I'll remove the 
casting from both functions in V2.



>
diff mbox series

Patch

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index ce6f15284277..163bb7f41e44 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -635,6 +635,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;
@@ -647,6 +649,14 @@  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)
+{
+	/* Reserve TXCTL_CREDITS credits for txctl */
+	return (u8)(bus->tx_max - bus->tx_seq) > TXCTL_CREDITS &&
+	       ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
+}
+
+/* To check if there's window offered */
+static bool txctl_ok(struct brcmf_sdio *bus)
 {
 	return (u8)(bus->tx_max - bus->tx_seq) != 0 &&
 	       ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
@@ -2655,7 +2665,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,
@@ -2663,6 +2673,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);