linux-rockchip.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/5] brcmfmac: sdio: Deal better w/ transmission errors related to idle
@ 2019-06-07 22:37 Douglas Anderson
  2019-06-07 22:37 ` [PATCH v3 1/5] Revert "brcmfmac: disable command decode in sdio_aos" Douglas Anderson
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Douglas Anderson @ 2019-06-07 22:37 UTC (permalink / raw)
  To: Ulf Hansson, Kalle Valo, Adrian Hunter, Arend van Spriel
  Cc: brcm80211-dev-list.pdl, linux-rockchip, Double Lo, briannorris,
	linux-wireless, Naveen Gupta, Madhan Mohan R, mka, Wright Feng,
	Chi-Hsien Lin, netdev, brcm80211-dev-list, Douglas Anderson,
	linux-mmc, Linus Walleij, Shawn Lin, YueHaibing,
	Rafał Miłecki, Hante Meuleman, Martin Blumenstingl

This series attempts to deal better with the expected transmission
errors related to the idle states (handled by the Always-On-Subsystem
or AOS) on the SDIO-based WiFi on rk3288-veyron-minnie,
rk3288-veyron-speedy, and rk3288-veyron-mickey.

Some details about those errors can be found in
<https://crbug.com/960222>, but to summarize it here: if we try to
send the wakeup command to the WiFi card at the same time it has
decided to wake up itself then it will behave badly on the SDIO bus.
This can cause timeouts or CRC errors.

When I tested on 4.19 and 4.20 these CRC errors can be seen to cause
re-tuning.  Since I am currently developing on 4.19 this was the
original problem I attempted to solve.

On mainline it turns out that you don't see the retuning errors but
you see tons of spam about timeouts trying to wakeup from sleep.  I
tracked down the commit that was causing that and have partially
reverted it here.  I have no real knowledge about Broadcom WiFi, but
the commit that was causing problems sounds (from the descriptioin) to
be a hack commit penalizing all Broadcom WiFi users because of a bug
in a Cypress SD controller.  I will let others comment if this is
truly the case and, if so, what the right solution should be.

For v3 of this series I have added 2 patches to the end of the series
to address errors that would show up on systems with these same SDIO
WiFi cards when used on controllers that do periodic retuning.  These
systems need an extra fix to prevent the retuning from happening when
the card is asleep.

Changes in v3:
- Took out the spinlock since I believe this is all in one context.
- Expect errors for all of brcmf_sdio_kso_control() (Adrian).
- ("mmc: core: Export mmc_retune_hold_now() mmc_retune_release()") new for v3.
- ("brcmfmac: sdio: Don't tune while the card is off") new for v3.

Changes in v2:
- A full revert, not just a partial one (Arend).  ...with explicit Cc.
- Updated commit message to clarify based on discussion of v1.

Douglas Anderson (5):
  Revert "brcmfmac: disable command decode in sdio_aos"
  mmc: core: API for temporarily disabling auto-retuning due to errors
  brcmfmac: sdio: Disable auto-tuning around commands expected to fail
  mmc: core: Export mmc_retune_hold_now() mmc_retune_release()
  brcmfmac: sdio: Don't tune while the card is off

 drivers/mmc/core/core.c                       | 19 +++++++++++++++++--
 drivers/mmc/core/host.c                       |  7 +++++++
 drivers/mmc/core/host.h                       |  7 -------
 .../broadcom/brcm80211/brcmfmac/sdio.c        | 18 +++++++++++++-----
 include/linux/mmc/core.h                      |  4 ++++
 include/linux/mmc/host.h                      |  1 +
 6 files changed, 42 insertions(+), 14 deletions(-)

-- 
2.22.0.rc2.383.gf4fbbf30c2-goog

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/5] Revert "brcmfmac: disable command decode in sdio_aos"
  2019-06-07 22:37 [PATCH v3 0/5] brcmfmac: sdio: Deal better w/ transmission errors related to idle Douglas Anderson
@ 2019-06-07 22:37 ` Douglas Anderson
       [not found] ` <20190607223716.119277-1-dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 15+ messages in thread
From: Douglas Anderson @ 2019-06-07 22:37 UTC (permalink / raw)
  To: Ulf Hansson, Kalle Valo, Adrian Hunter, Arend van Spriel
  Cc: brcm80211-dev-list.pdl, linux-rockchip, Double Lo, briannorris,
	linux-wireless, Naveen Gupta, Madhan Mohan R, mka, Wright Feng,
	Chi-Hsien Lin, netdev, brcm80211-dev-list, Douglas Anderson,
	David S. Miller, Franky Lin, linux-kernel,
	Rafał Miłecki, Hante Meuleman, YueHaibing,
	Michael Trimarchi

This reverts commit 29f6589140a10ece8c1d73f58043ea5b3473ab3e.

After that patch landed I find that my kernel log on
rk3288-veyron-minnie and rk3288-veyron-speedy is filled with:
brcmfmac: brcmf_sdio_bus_sleep: error while changing bus sleep state -110

This seems to happen every time the Broadcom WiFi transitions out of
sleep mode.  Reverting the commit fixes the problem for me, so that's
what this patch does.

Note that, in general, the justification in the original commit seemed
a little weak.  It looked like someone was testing on a SD card
controller that would sometimes die if there were CRC errors on the
bus.  This used to happen back in early days of dw_mmc (the controller
on my boards), but we fixed it.  Disabling a feature on all boards
just because one SD card controller is broken seems bad.

Fixes: 29f6589140a1 ("brcmfmac: disable command decode in sdio_aos")
Cc: Wright Feng <wright.feng@cypress.com>
Cc: Double Lo <double.lo@cypress.com>
Cc: Madhan Mohan R <madhanmohan.r@cypress.com>
Cc: Chi-Hsien Lin <chi-hsien.lin@cypress.com>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
As far as I know this patch can land anytime.

Changes in v3: None
Changes in v2:
- A full revert, not just a partial one (Arend).  ...with explicit Cc.

 drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 4e15ea57d4f5..4a750838d8cd 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -3364,11 +3364,7 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
 
 static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus)
 {
-	if (bus->ci->chip == CY_CC_43012_CHIP_ID ||
-	    bus->ci->chip == CY_CC_4373_CHIP_ID ||
-	    bus->ci->chip == BRCM_CC_4339_CHIP_ID ||
-	    bus->ci->chip == BRCM_CC_4345_CHIP_ID ||
-	    bus->ci->chip == BRCM_CC_4354_CHIP_ID)
+	if (bus->ci->chip == CY_CC_43012_CHIP_ID)
 		return true;
 	else
 		return false;
-- 
2.22.0.rc2.383.gf4fbbf30c2-goog

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 2/5] mmc: core: API for temporarily disabling auto-retuning due to errors
       [not found] ` <20190607223716.119277-1-dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2019-06-07 22:37   ` Douglas Anderson
  2019-06-12 13:25     ` Ulf Hansson
  2019-06-07 22:37   ` [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail Douglas Anderson
  1 sibling, 1 reply; 15+ messages in thread
From: Douglas Anderson @ 2019-06-07 22:37 UTC (permalink / raw)
  To: Ulf Hansson, Kalle Valo, Adrian Hunter, Arend van Spriel
  Cc: Madhan Mohan R, brcm80211-dev-list.pdl-dY08KVG/lbpWk0Htik3J/w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Wolfram Sang,
	netdev-u79uwXL29TY76Z2rM5mHXA, Chi-Hsien Lin,
	briannorris-F7+t8E8rja9g9hUCZPvPmw,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA, Double Lo,
	Douglas Anderson,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Avri Altman,
	mka-F7+t8E8rja9g9hUCZPvPmw, Ritesh Harjani, Wright Feng,
	Jiong Wu, linux-mmc-u79uwXL29TY76Z2rM5mHXA, Shawn Lin,
	brcm80211-dev-list-+wT8y+m8/X5BDgjK7y7TUQ, Naveen Gupta

Normally when the MMC core sees an "-EILSEQ" error returned by a host
controller then it will trigger a retuning of the card.  This is
generally a good idea.

However, if a command is expected to sometimes cause transfer errors
then these transfer errors shouldn't cause a re-tuning.  This
re-tuning will be a needless waste of time.  One example case where a
transfer is expected to cause errors is when transitioning between
idle (sometimes referred to as "sleep" in Broadcom code) and active
state on certain Broadcom WiFi cards.  Specifically if the card was
already transitioning between states when the command was sent it
could cause an error on the SDIO bus.

Let's add an API that the SDIO card drivers can call that will
temporarily disable the auto-tuning functionality.  Then we can add a
call to this in the Broadcom WiFi driver and any other driver that
might have similar needs.

NOTE: this makes the assumption that the card is already tuned well
enough that it's OK to disable the auto-retuning during one of these
error-prone situations.  Presumably the driver code performing the
error-prone transfer knows how to recover / retry from errors.  ...and
after we can get back to a state where transfers are no longer
error-prone then we can enable the auto-retuning again.  If we truly
find ourselves in a case where the card needs to be retuned sometimes
to handle one of these error-prone transfers then we can always try a
few transfers first without auto-retuning and then re-try with
auto-retuning if the first few fail.

Without this change on rk3288-veyron-minnie I periodically see this in
the logs of a machine just sitting there idle:
  dwmmc_rockchip ff0d0000.dwmmc: Successfully tuned phase to XYZ

Fixes: bd11e8bd03ca ("mmc: core: Flag re-tuning is needed on CRC errors")
Signed-off-by: Douglas Anderson <dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---
Note that are are a whole boatload of different ways that we could
provide an API for the Broadcom WiFi SDIO driver.  This patch
illustrates one way but if maintainers feel strongly that this is too
ugly and have a better idea then I can give it a shot too.  From a
purist point of view I kinda felt that the "expect errors" really
belonged as part of the mmc_request structure, but getting it into
there meant changing a whole pile of core SD/MMC APIs.  Simply adding
it to the host seemed to match the current style better and was a less
intrusive change.

Changes in v3:
- Took out the spinlock since I believe this is all in one context.

Changes in v2:
- Updated commit message to clarify based on discussion of v1.

 drivers/mmc/core/core.c  | 19 +++++++++++++++++--
 include/linux/mmc/core.h |  2 ++
 include/linux/mmc/host.h |  1 +
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 6db36dc870b5..bc109ec49406 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -144,8 +144,9 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
 	int err = cmd->error;
 
 	/* Flag re-tuning needed on CRC errors */
-	if ((cmd->opcode != MMC_SEND_TUNING_BLOCK &&
-	    cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) &&
+	if (cmd->opcode != MMC_SEND_TUNING_BLOCK &&
+	    cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200 &&
+	    !host->expect_errors &&
 	    (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) ||
 	    (mrq->data && mrq->data->error == -EILSEQ) ||
 	    (mrq->stop && mrq->stop->error == -EILSEQ)))
@@ -2163,6 +2164,20 @@ int mmc_sw_reset(struct mmc_host *host)
 }
 EXPORT_SYMBOL(mmc_sw_reset);
 
+void mmc_expect_errors_begin(struct mmc_host *host)
+{
+	WARN_ON(host->expect_errors);
+	host->expect_errors = true;
+}
+EXPORT_SYMBOL_GPL(mmc_expect_errors_begin);
+
+void mmc_expect_errors_end(struct mmc_host *host)
+{
+	WARN_ON(!host->expect_errors);
+	host->expect_errors = false;
+}
+EXPORT_SYMBOL_GPL(mmc_expect_errors_end);
+
 static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
 {
 	host->f_init = freq;
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 134a6483347a..02a13abf0cda 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -178,6 +178,8 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd,
 
 int mmc_hw_reset(struct mmc_host *host);
 int mmc_sw_reset(struct mmc_host *host);
+void mmc_expect_errors_begin(struct mmc_host *host);
+void mmc_expect_errors_end(struct mmc_host *host);
 void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card);
 
 #endif /* LINUX_MMC_CORE_H */
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 43d0f0c496f6..8d553fb8c834 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -398,6 +398,7 @@ struct mmc_host {
 	unsigned int		retune_now:1;	/* do re-tuning at next req */
 	unsigned int		retune_paused:1; /* re-tuning is temporarily disabled */
 	unsigned int		use_blk_mq:1;	/* use blk-mq */
+	unsigned int		expect_errors:1; /* don't trigger retune upon errors */
 
 	int			rescan_disable;	/* disable card detection */
 	int			rescan_entered;	/* used with nonremovable devices */
-- 
2.22.0.rc2.383.gf4fbbf30c2-goog

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail
       [not found] ` <20190607223716.119277-1-dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2019-06-07 22:37   ` [PATCH v3 2/5] mmc: core: API for temporarily disabling auto-retuning due to errors Douglas Anderson
@ 2019-06-07 22:37   ` Douglas Anderson
  2019-06-10  8:56     ` Hunter, Adrian
  1 sibling, 1 reply; 15+ messages in thread
From: Douglas Anderson @ 2019-06-07 22:37 UTC (permalink / raw)
  To: Ulf Hansson, Kalle Valo, Adrian Hunter, Arend van Spriel
  Cc: Madhan Mohan R, brcm80211-dev-list.pdl-dY08KVG/lbpWk0Htik3J/w,
	YueHaibing, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Hante Meuleman,
	David S. Miller, netdev-u79uwXL29TY76Z2rM5mHXA, Chi-Hsien Lin,
	briannorris-F7+t8E8rja9g9hUCZPvPmw,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA, Double Lo,
	Douglas Anderson,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	mka-F7+t8E8rja9g9hUCZPvPmw, Wright Feng,
	brcm80211-dev-list-+wT8y+m8/X5BDgjK7y7TUQ, Naveen Gupta,
	Franky Lin

There are certain cases, notably when transitioning between sleep and
active state, when Broadcom SDIO WiFi cards will produce errors on the
SDIO bus.  This is evident from the source code where you can see that
we try commands in a loop until we either get success or we've tried
too many times.  The comment in the code reinforces this by saying
"just one write attempt may fail"

Unfortunately these failures sometimes end up causing an "-EILSEQ"
back to the core which triggers a retuning of the SDIO card and that
blocks all traffic to the card until it's done.

Let's disable retuning around the commands we expect might fail.

Fixes: bd11e8bd03ca ("mmc: core: Flag re-tuning is needed on CRC errors")
Signed-off-by: Douglas Anderson <dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---

Changes in v3:
- Expect errors for all of brcmf_sdio_kso_control() (Adrian).

Changes in v2: None

 drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 4a750838d8cd..4040aae1f9ed 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -16,6 +16,7 @@
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/card.h>
+#include <linux/mmc/core.h>
 #include <linux/semaphore.h>
 #include <linux/firmware.h>
 #include <linux/module.h>
@@ -667,6 +668,8 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
 
 	brcmf_dbg(TRACE, "Enter: on=%d\n", on);
 
+	mmc_expect_errors_begin(bus->sdiodev->func1->card->host);
+
 	wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
 	/* 1st KSO write goes to AOS wake up core if device is asleep  */
 	brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
@@ -727,6 +730,8 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
 	if (try_cnt > MAX_KSO_ATTEMPTS)
 		brcmf_err("max tries: rd_val=0x%x err=%d\n", rd_val, err);
 
+	mmc_expect_errors_end(bus->sdiodev->func1->card->host);
+
 	return err;
 }
 
-- 
2.22.0.rc2.383.gf4fbbf30c2-goog

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 4/5] mmc: core: Export mmc_retune_hold_now() mmc_retune_release()
  2019-06-07 22:37 [PATCH v3 0/5] brcmfmac: sdio: Deal better w/ transmission errors related to idle Douglas Anderson
  2019-06-07 22:37 ` [PATCH v3 1/5] Revert "brcmfmac: disable command decode in sdio_aos" Douglas Anderson
       [not found] ` <20190607223716.119277-1-dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2019-06-07 22:37 ` Douglas Anderson
  2019-06-07 22:37 ` [PATCH v3 5/5] brcmfmac: sdio: Don't tune while the card is off Douglas Anderson
  3 siblings, 0 replies; 15+ messages in thread
From: Douglas Anderson @ 2019-06-07 22:37 UTC (permalink / raw)
  To: Ulf Hansson, Kalle Valo, Adrian Hunter, Arend van Spriel
  Cc: brcm80211-dev-list.pdl, linux-rockchip, Double Lo, briannorris,
	linux-wireless, Naveen Gupta, Madhan Mohan R, mka, Wright Feng,
	Chi-Hsien Lin, netdev, brcm80211-dev-list, Douglas Anderson,
	Martin Blumenstingl, Pan Bian, Linus Walleij, linux-mmc,
	linux-kernel, Tony Lindgren, Mathieu Malaterre, Pavel Machek

We want SDIO drivers to be able to temporarily stop retuning when the
driver knows that the SDIO card is not in a state where retuning will
work (maybe because the card is asleep).  We'll move the relevant
functions to a place where drivers can call them.

NOTE: We'll leave the calls with a mmc_ prefix following the lead of
the API call mmc_hw_reset(), which is also expected to be called
directly by SDIO cards.

Signed-off-by: Douglas Anderson <dianders@chromium.org>
---

Changes in v3:
- ("mmc: core: Export mmc_retune_hold_now() mmc_retune_release()") new for v3.

Changes in v2: None

 drivers/mmc/core/host.c  | 7 +++++++
 drivers/mmc/core/host.h  | 7 -------
 include/linux/mmc/core.h | 2 ++
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 6a51f7a06ce7..361f4d151d20 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -111,6 +111,13 @@ void mmc_retune_hold(struct mmc_host *host)
 	host->hold_retune += 1;
 }
 
+void mmc_retune_hold_now(struct mmc_host *host)
+{
+	host->retune_now = 0;
+	host->hold_retune += 1;
+}
+EXPORT_SYMBOL(mmc_retune_hold_now);
+
 void mmc_retune_release(struct mmc_host *host)
 {
 	if (host->hold_retune)
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
index 4805438c02ff..3212afc6c9fe 100644
--- a/drivers/mmc/core/host.h
+++ b/drivers/mmc/core/host.h
@@ -19,17 +19,10 @@ void mmc_unregister_host_class(void);
 void mmc_retune_enable(struct mmc_host *host);
 void mmc_retune_disable(struct mmc_host *host);
 void mmc_retune_hold(struct mmc_host *host);
-void mmc_retune_release(struct mmc_host *host);
 int mmc_retune(struct mmc_host *host);
 void mmc_retune_pause(struct mmc_host *host);
 void mmc_retune_unpause(struct mmc_host *host);
 
-static inline void mmc_retune_hold_now(struct mmc_host *host)
-{
-	host->retune_now = 0;
-	host->hold_retune += 1;
-}
-
 static inline void mmc_retune_recheck(struct mmc_host *host)
 {
 	if (host->hold_retune <= 1)
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 02a13abf0cda..53085245383c 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -181,5 +181,7 @@ int mmc_sw_reset(struct mmc_host *host);
 void mmc_expect_errors_begin(struct mmc_host *host);
 void mmc_expect_errors_end(struct mmc_host *host);
 void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card);
+void mmc_retune_release(struct mmc_host *host);
+void mmc_retune_hold_now(struct mmc_host *host);
 
 #endif /* LINUX_MMC_CORE_H */
-- 
2.22.0.rc2.383.gf4fbbf30c2-goog

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 5/5] brcmfmac: sdio: Don't tune while the card is off
  2019-06-07 22:37 [PATCH v3 0/5] brcmfmac: sdio: Deal better w/ transmission errors related to idle Douglas Anderson
                   ` (2 preceding siblings ...)
  2019-06-07 22:37 ` [PATCH v3 4/5] mmc: core: Export mmc_retune_hold_now() mmc_retune_release() Douglas Anderson
@ 2019-06-07 22:37 ` Douglas Anderson
  3 siblings, 0 replies; 15+ messages in thread
From: Douglas Anderson @ 2019-06-07 22:37 UTC (permalink / raw)
  To: Ulf Hansson, Kalle Valo, Adrian Hunter, Arend van Spriel
  Cc: brcm80211-dev-list.pdl, linux-rockchip, Double Lo, briannorris,
	linux-wireless, Naveen Gupta, Madhan Mohan R, mka, Wright Feng,
	Chi-Hsien Lin, netdev, brcm80211-dev-list, Douglas Anderson,
	Franky Lin, linux-kernel, Hante Meuleman, Ondrej Jirman,
	YueHaibing, David S. Miller

When Broadcom SDIO cards are idled they go to sleep and a whole
separate subsystem takes over their SDIO communication.  This is the
Always-On-Subsystem (AOS) and it can't handle tuning requests.

Specifically, as tested on rk3288-veyron-minnie (which reports having
BCM4354/1 in dmesg), if I force a retune in brcmf_sdio_kso_control()
when "on = 1" (aka we're transition from sleep to wake) by whacking:
  bus->sdiodev->func1->card->host->need_retune = 1
...then I can often see tuning fail.  In this case dw_mmc reports "All
phases bad!").  Note that I don't get 100% failure, presumably because
sometimes the card itself has already transitioned away from the AOS
itself by the time we try to wake it up.  If I force retuning when "on
= 0" (AKA force retuning right before sending the command to go to
sleep) then retuning is always OK.

NOTE: we need _both_ this patch and the patch to avoid triggering
tuning due to CRC errors in the sleep/wake transition, AKA ("brcmfmac:
sdio: Disable auto-tuning around commands expected to fail").  Though
both patches handle issues with Broadcom's AOS, the problems are
distinct:
1. We want to defer (but not ignore) asynchronous (like
   timer-requested) tuning requests till the card is awake.  However,
   we want to ignore CRC errors during the transition, we don't want
   to queue deferred tuning request.
2. You could imagine that the AOS could implement retuning but we
   could still get errors while transitioning in and out of the AOS.
   Similarly you could imagine a seamless transition into and out of
   the AOS (with no CRC errors) even if the AOS couldn't handle
   tuning.

ALSO NOTE: presumably there is never a desperate need to retune in
order to wake up the card, since doing so is impossible.  Luckily the
only way the card can get into sleep state is if we had a good enough
tuning to send it a sleep command, so presumably that "good enough"
tuning is enough to wake us up, at least with a few retries.

Signed-off-by: Douglas Anderson <dianders@chromium.org>
---

Changes in v3:
- ("brcmfmac: sdio: Don't tune while the card is off") new for v3.

Changes in v2: None

 drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 4040aae1f9ed..98ffb4e90e15 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -670,6 +670,10 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
 
 	mmc_expect_errors_begin(bus->sdiodev->func1->card->host);
 
+	/* Cannot re-tune if device is asleep; defer till we're awake */
+	if (on)
+		mmc_retune_hold_now(bus->sdiodev->func1->card->host);
+
 	wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
 	/* 1st KSO write goes to AOS wake up core if device is asleep  */
 	brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
@@ -730,6 +734,9 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
 	if (try_cnt > MAX_KSO_ATTEMPTS)
 		brcmf_err("max tries: rd_val=0x%x err=%d\n", rd_val, err);
 
+	if (on)
+		mmc_retune_release(bus->sdiodev->func1->card->host);
+
 	mmc_expect_errors_end(bus->sdiodev->func1->card->host);
 
 	return err;
-- 
2.22.0.rc2.383.gf4fbbf30c2-goog

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* RE: [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail
  2019-06-07 22:37   ` [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail Douglas Anderson
@ 2019-06-10  8:56     ` Hunter, Adrian
  2019-06-10 16:50       ` Doug Anderson
  0 siblings, 1 reply; 15+ messages in thread
From: Hunter, Adrian @ 2019-06-10  8:56 UTC (permalink / raw)
  To: Douglas Anderson, Ulf Hansson, Kalle Valo, Arend van Spriel
  Cc: brcm80211-dev-list.pdl, linux-rockchip, Double Lo, briannorris,
	linux-wireless, Naveen Gupta, Madhan Mohan R, mka, Wright Feng,
	Chi-Hsien Lin, netdev, brcm80211-dev-list, Franky Lin,
	linux-kernel, Madhan Mohan R

> -----Original Message-----
> From: Douglas Anderson [mailto:dianders@chromium.org]
> Sent: Saturday, June 8, 2019 1:37 AM
> To: Ulf Hansson <ulf.hansson@linaro.org>; Kalle Valo
> <kvalo@codeaurora.org>; Hunter, Adrian <adrian.hunter@intel.com>; Arend
> van Spriel <arend.vanspriel@broadcom.com>
> Cc: brcm80211-dev-list.pdl@broadcom.com; linux-
> rockchip@lists.infradead.org; Double Lo <double.lo@cypress.com>;
> briannorris@chromium.org; linux-wireless@vger.kernel.org; Naveen Gupta
> <naveen.gupta@cypress.com>; Madhan Mohan R
> <madhanmohan.r@cypress.com>; mka@chromium.org; Wright Feng
> <wright.feng@cypress.com>; Chi-Hsien Lin <chi-hsien.lin@cypress.com>;
> netdev@vger.kernel.org; brcm80211-dev-list@cypress.com; Douglas
> Anderson <dianders@chromium.org>; Franky Lin
> <franky.lin@broadcom.com>; linux-kernel@vger.kernel.org; Madhan Mohan
> R <MadhanMohan.R@cypress.com>; Hante Meuleman
> <hante.meuleman@broadcom.com>; YueHaibing
> <yuehaibing@huawei.com>; David S. Miller <davem@davemloft.net>
> Subject: [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around
> commands expected to fail
> 
> There are certain cases, notably when transitioning between sleep and active
> state, when Broadcom SDIO WiFi cards will produce errors on the SDIO bus.
> This is evident from the source code where you can see that we try
> commands in a loop until we either get success or we've tried too many
> times.  The comment in the code reinforces this by saying "just one write
> attempt may fail"
> 
> Unfortunately these failures sometimes end up causing an "-EILSEQ"
> back to the core which triggers a retuning of the SDIO card and that blocks all
> traffic to the card until it's done.
> 
> Let's disable retuning around the commands we expect might fail.
> 
> Fixes: bd11e8bd03ca ("mmc: core: Flag re-tuning is needed on CRC errors")
> Signed-off-by: Douglas Anderson <dianders@chromium.org>
> ---
> 
> Changes in v3:
> - Expect errors for all of brcmf_sdio_kso_control() (Adrian).
> 
> Changes in v2: None
> 
>  drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> index 4a750838d8cd..4040aae1f9ed 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> @@ -16,6 +16,7 @@
>  #include <linux/mmc/sdio_ids.h>
>  #include <linux/mmc/sdio_func.h>
>  #include <linux/mmc/card.h>
> +#include <linux/mmc/core.h>

SDIO function drivers should not really include linux/mmc/core.h
(Also don't know why linux/mmc/card.h is included)

>  #include <linux/semaphore.h>
>  #include <linux/firmware.h>
>  #include <linux/module.h>
> @@ -667,6 +668,8 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool
> on)
> 
>  	brcmf_dbg(TRACE, "Enter: on=%d\n", on);
> 
> +	mmc_expect_errors_begin(bus->sdiodev->func1->card->host);
> +
>  	wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
>  	/* 1st KSO write goes to AOS wake up core if device is asleep  */
>  	brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
> wr_val, &err); @@ -727,6 +730,8 @@ brcmf_sdio_kso_control(struct
> brcmf_sdio *bus, bool on)
>  	if (try_cnt > MAX_KSO_ATTEMPTS)
>  		brcmf_err("max tries: rd_val=0x%x err=%d\n", rd_val, err);
> 
> +	mmc_expect_errors_end(bus->sdiodev->func1->card->host);
> +
>  	return err;
>  }
> 
> --
> 2.22.0.rc2.383.gf4fbbf30c2-goog

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail
  2019-06-10  8:56     ` Hunter, Adrian
@ 2019-06-10 16:50       ` Doug Anderson
  2019-06-11  7:17         ` Adrian Hunter
  2019-06-12 10:10         ` Ulf Hansson
  0 siblings, 2 replies; 15+ messages in thread
From: Doug Anderson @ 2019-06-10 16:50 UTC (permalink / raw)
  To: Hunter, Adrian
  Cc: Ulf Hansson, Kalle Valo, Arend van Spriel,
	brcm80211-dev-list.pdl, linux-rockchip, Double Lo, briannorris,
	linux-wireless, Naveen Gupta, Madhan Mohan R, mka, Wright Feng,
	Chi-Hsien Lin, netdev, brcm80211-dev-list, Fra

Hi,

On Mon, Jun 10, 2019 at 1:56 AM Hunter, Adrian <adrian.hunter@intel.com> wrote:
>
> > --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> > @@ -16,6 +16,7 @@
> >  #include <linux/mmc/sdio_ids.h>
> >  #include <linux/mmc/sdio_func.h>
> >  #include <linux/mmc/card.h>
> > +#include <linux/mmc/core.h>
>
> SDIO function drivers should not really include linux/mmc/core.h
> (Also don't know why linux/mmc/card.h is included)

OK, so I guess you're requesting an extra level of "sdio_" wrappers
for all the functions I need to call.  I don't think the wrappers buy
us a ton other than to abstract things a little bit and make it look
prettier.  :-)  ...but certainly I can code that up if that's what
everyone wants.

Just to make sure, I looked in "drivers/net/wireless/" and I do see
quite a few instances of "mmc_" functions being used.  That doesn't
mean all these instances are correct but it does appear to be
commonplace.  Selected examples:

drivers/net/wireless/ath/ath10k/sdio.c:
  ret = mmc_hw_reset(ar_sdio->func->card->host);

drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c:
  mmc_set_data_timeout(md, func->card);
  mmc_wait_for_req(func->card->host, mr);

drivers/net/wireless/marvell/mwifiex/sdio.c:
  mmc_hw_reset(func->card->host);

drivers/net/wireless/rsi/rsi_91x_sdio.c:
  err = mmc_wait_for_cmd(host, &cmd, 3);


...anyway, I'll give it a few days and if nobody else chimes in then
I'll assume you indeed want "sdio_" wrappers for things and I'll post
a v4.  If patch #1 happens to land in the meantime then I won't
object.  ;-)


-Doug

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail
  2019-06-10 16:50       ` Doug Anderson
@ 2019-06-11  7:17         ` Adrian Hunter
  2019-06-12 10:10         ` Ulf Hansson
  1 sibling, 0 replies; 15+ messages in thread
From: Adrian Hunter @ 2019-06-11  7:17 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Ulf Hansson, Kalle Valo, Arend van Spriel,
	brcm80211-dev-list.pdl, linux-rockchip, Double Lo, briannorris,
	linux-wireless, Naveen Gupta, Madhan Mohan R, mka, Wright Feng,
	Chi-Hsien Lin, netdev, brcm80211-dev-list, Fra

On 10/06/19 7:50 PM, Doug Anderson wrote:
> Hi,
> 
> On Mon, Jun 10, 2019 at 1:56 AM Hunter, Adrian <adrian.hunter@intel.com> wrote:
>>
>>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
>>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
>>> @@ -16,6 +16,7 @@
>>>  #include <linux/mmc/sdio_ids.h>
>>>  #include <linux/mmc/sdio_func.h>
>>>  #include <linux/mmc/card.h>
>>> +#include <linux/mmc/core.h>
>>
>> SDIO function drivers should not really include linux/mmc/core.h
>> (Also don't know why linux/mmc/card.h is included)
> 
> OK, so I guess you're requesting an extra level of "sdio_" wrappers
> for all the functions I need to call.  I don't think the wrappers buy
> us a ton other than to abstract things a little bit and make it look
> prettier.  :-)  ...but certainly I can code that up if that's what
> everyone wants.

I guess it is really up to Ulf.

> 
> Just to make sure, I looked in "drivers/net/wireless/" and I do see
> quite a few instances of "mmc_" functions being used.  That doesn't
> mean all these instances are correct but it does appear to be
> commonplace.  Selected examples:
> 
> drivers/net/wireless/ath/ath10k/sdio.c:
>   ret = mmc_hw_reset(ar_sdio->func->card->host);
> 
> drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c:
>   mmc_set_data_timeout(md, func->card);
>   mmc_wait_for_req(func->card->host, mr);
> 
> drivers/net/wireless/marvell/mwifiex/sdio.c:
>   mmc_hw_reset(func->card->host);
> 
> drivers/net/wireless/rsi/rsi_91x_sdio.c:
>   err = mmc_wait_for_cmd(host, &cmd, 3);
> 
> 
> ...anyway, I'll give it a few days and if nobody else chimes in then
> I'll assume you indeed want "sdio_" wrappers for things and I'll post
> a v4.  If patch #1 happens to land in the meantime then I won't
> object.  ;-)
> 
> 
> -Doug
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail
  2019-06-10 16:50       ` Doug Anderson
  2019-06-11  7:17         ` Adrian Hunter
@ 2019-06-12 10:10         ` Ulf Hansson
  2019-06-12 11:11           ` Arend Van Spriel
  1 sibling, 1 reply; 15+ messages in thread
From: Ulf Hansson @ 2019-06-12 10:10 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Hunter, Adrian, Kalle Valo, Arend van Spriel,
	brcm80211-dev-list.pdl, linux-rockchip, Double Lo, briannorris,
	linux-wireless, Naveen Gupta, Madhan Mohan R, mka, Wright Feng,
	Chi-Hsien Lin, netdev, brcm80211-dev-list

On Mon, 10 Jun 2019 at 18:50, Doug Anderson <dianders@chromium.org> wrote:
>
> Hi,
>
> On Mon, Jun 10, 2019 at 1:56 AM Hunter, Adrian <adrian.hunter@intel.com> wrote:
> >
> > > --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> > > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
> > > @@ -16,6 +16,7 @@
> > >  #include <linux/mmc/sdio_ids.h>
> > >  #include <linux/mmc/sdio_func.h>
> > >  #include <linux/mmc/card.h>
> > > +#include <linux/mmc/core.h>
> >
> > SDIO function drivers should not really include linux/mmc/core.h
> > (Also don't know why linux/mmc/card.h is included)
>
> OK, so I guess you're requesting an extra level of "sdio_" wrappers
> for all the functions I need to call.  I don't think the wrappers buy
> us a ton other than to abstract things a little bit and make it look
> prettier.  :-)  ...but certainly I can code that up if that's what
> everyone wants.

Are the new code you refer to going to be used for anything else but
SDIO? If not, please put them in the sdio specific headers instead.

BTW, apologize for not looking at this series any earlier, but I will
come to it soon.

>
> Just to make sure, I looked in "drivers/net/wireless/" and I do see
> quite a few instances of "mmc_" functions being used.  That doesn't
> mean all these instances are correct but it does appear to be
> commonplace.  Selected examples:
>
> drivers/net/wireless/ath/ath10k/sdio.c:
>   ret = mmc_hw_reset(ar_sdio->func->card->host);

mmc_hw_reset() is already an exported function, used by the mmc block
layer. So I think this is okay.

>
> drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c:
>   mmc_set_data_timeout(md, func->card);
>   mmc_wait_for_req(func->card->host, mr);

These are not okay, none of these things calls should really be done
from an SDIO func driver.

It tells me that the func driver is a doing workaround for something
that should be managed in a common way.

>
> drivers/net/wireless/marvell/mwifiex/sdio.c:
>   mmc_hw_reset(func->card->host);

Okay.

>
> drivers/net/wireless/rsi/rsi_91x_sdio.c:
>   err = mmc_wait_for_cmd(host, &cmd, 3);

Not okay.

>
>
> ...anyway, I'll give it a few days and if nobody else chimes in then
> I'll assume you indeed want "sdio_" wrappers for things and I'll post
> a v4.  If patch #1 happens to land in the meantime then I won't
> object.  ;-)

Adrian has a very good point. We need to strive to avoid exporting
APIs to here and there and just trust that they will be used wisely.

If the above calls to mmc_wait_for_req|cmd() and
mmc_set_data_timeout() could have been avoided, we would probably have
a more proper solution by now.

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail
  2019-06-12 10:10         ` Ulf Hansson
@ 2019-06-12 11:11           ` Arend Van Spriel
  2019-06-12 11:48             ` Ulf Hansson
  0 siblings, 1 reply; 15+ messages in thread
From: Arend Van Spriel @ 2019-06-12 11:11 UTC (permalink / raw)
  To: Ulf Hansson, Doug Anderson
  Cc: Hunter, Adrian, Kalle Valo, brcm80211-dev-list.pdl,
	linux-rockchip, Double Lo, briannorris, linux-wireless,
	Naveen Gupta, Madhan Mohan R, mka, Wright Feng, Chi-Hsien Lin,
	netdev, brcm80211-dev-list, Franky Lin, linux-k

On 6/12/2019 12:10 PM, Ulf Hansson wrote:
>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c:
>>    mmc_set_data_timeout(md, func->card);
>>    mmc_wait_for_req(func->card->host, mr);
> These are not okay, none of these things calls should really be done
> from an SDIO func driver.
> 
> It tells me that the func driver is a doing workaround for something
> that should be managed in a common way.

We are using some low-level functions passing chain of skbuff to the 
device using CMD53 with scatterlist. If I recall correctly Marvell made 
an attempt to have a similar function for it in the mmc stack. Not sure 
if that ever made it in. If so I can rework our driver using that API. 
If not, I can make a new attempt.

Regards,
Arend

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail
  2019-06-12 11:11           ` Arend Van Spriel
@ 2019-06-12 11:48             ` Ulf Hansson
       [not found]               ` <CAPDyKFpM0+FfvoMo8Z_hxM9rzSjeQZHCsA2SPa8WP+SRDhhsPA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 15+ messages in thread
From: Ulf Hansson @ 2019-06-12 11:48 UTC (permalink / raw)
  To: Arend Van Spriel
  Cc: Doug Anderson, Hunter, Adrian, Kalle Valo,
	brcm80211-dev-list.pdl, linux-rockchip, Double Lo, briannorris,
	linux-wireless, Naveen Gupta, Madhan Mohan R, mka, Wright Feng,
	Chi-Hsien Lin, netdev, brcm80211-dev-list, Franky

On Wed, 12 Jun 2019 at 13:11, Arend Van Spriel
<arend.vanspriel@broadcom.com> wrote:
>
> On 6/12/2019 12:10 PM, Ulf Hansson wrote:
> >> drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c:
> >>    mmc_set_data_timeout(md, func->card);
> >>    mmc_wait_for_req(func->card->host, mr);
> > These are not okay, none of these things calls should really be done
> > from an SDIO func driver.
> >
> > It tells me that the func driver is a doing workaround for something
> > that should be managed in a common way.
>
> We are using some low-level functions passing chain of skbuff to the
> device using CMD53 with scatterlist. If I recall correctly Marvell made
> an attempt to have a similar function for it in the mmc stack. Not sure
> if that ever made it in. If so I can rework our driver using that API.
> If not, I can make a new attempt.

I recall there were some patches, but not sure why we didn't merge them.

Anyway, if you want to move this forward, that would be awesome!

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 2/5] mmc: core: API for temporarily disabling auto-retuning due to errors
  2019-06-07 22:37   ` [PATCH v3 2/5] mmc: core: API for temporarily disabling auto-retuning due to errors Douglas Anderson
@ 2019-06-12 13:25     ` Ulf Hansson
  0 siblings, 0 replies; 15+ messages in thread
From: Ulf Hansson @ 2019-06-12 13:25 UTC (permalink / raw)
  To: Douglas Anderson
  Cc: Kalle Valo, Adrian Hunter, Arend van Spriel,
	brcm80211-dev-list.pdl, open list:ARM/Rockchip SoC...,
	Double Lo, Brian Norris, linux-wireless, Naveen Gupta,
	Madhan Mohan R, Matthias Kaehlcke, Wright Feng, Chi-Hsien Lin,
	netdev, brcm80211-dev-list, Jiong Wu, Ritesh Harjani, linux-mmc,
	Linux

On Sat, 8 Jun 2019 at 00:37, Douglas Anderson <dianders@chromium.org> wrote:
>
> Normally when the MMC core sees an "-EILSEQ" error returned by a host
> controller then it will trigger a retuning of the card.  This is
> generally a good idea.
>
> However, if a command is expected to sometimes cause transfer errors
> then these transfer errors shouldn't cause a re-tuning.  This
> re-tuning will be a needless waste of time.  One example case where a
> transfer is expected to cause errors is when transitioning between
> idle (sometimes referred to as "sleep" in Broadcom code) and active
> state on certain Broadcom WiFi cards.  Specifically if the card was
> already transitioning between states when the command was sent it
> could cause an error on the SDIO bus.
>
> Let's add an API that the SDIO card drivers can call that will
> temporarily disable the auto-tuning functionality.  Then we can add a
> call to this in the Broadcom WiFi driver and any other driver that
> might have similar needs.
>
> NOTE: this makes the assumption that the card is already tuned well
> enough that it's OK to disable the auto-retuning during one of these
> error-prone situations.  Presumably the driver code performing the
> error-prone transfer knows how to recover / retry from errors.  ...and
> after we can get back to a state where transfers are no longer
> error-prone then we can enable the auto-retuning again.  If we truly
> find ourselves in a case where the card needs to be retuned sometimes
> to handle one of these error-prone transfers then we can always try a
> few transfers first without auto-retuning and then re-try with
> auto-retuning if the first few fail.
>
> Without this change on rk3288-veyron-minnie I periodically see this in
> the logs of a machine just sitting there idle:
>   dwmmc_rockchip ff0d0000.dwmmc: Successfully tuned phase to XYZ
>
> Fixes: bd11e8bd03ca ("mmc: core: Flag re-tuning is needed on CRC errors")
> Signed-off-by: Douglas Anderson <dianders@chromium.org>
> ---
> Note that are are a whole boatload of different ways that we could
> provide an API for the Broadcom WiFi SDIO driver.  This patch
> illustrates one way but if maintainers feel strongly that this is too
> ugly and have a better idea then I can give it a shot too.  From a
> purist point of view I kinda felt that the "expect errors" really
> belonged as part of the mmc_request structure, but getting it into
> there meant changing a whole pile of core SD/MMC APIs.  Simply adding
> it to the host seemed to match the current style better and was a less
> intrusive change.
>
> Changes in v3:
> - Took out the spinlock since I believe this is all in one context.

This needs to be clarified, preferable also in a function header.

If I understand correctly, the SDIO func driver needs the host to be
claimed when it calls mmc_expect_errors_begin(). More importantly, it
also needs to be keep it claimed until after it had called
mmc_expect_errors_end(). Correct?

>
> Changes in v2:
> - Updated commit message to clarify based on discussion of v1.
>
>  drivers/mmc/core/core.c  | 19 +++++++++++++++++--
>  include/linux/mmc/core.h |  2 ++
>  include/linux/mmc/host.h |  1 +
>  3 files changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 6db36dc870b5..bc109ec49406 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -144,8 +144,9 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
>         int err = cmd->error;
>
>         /* Flag re-tuning needed on CRC errors */
> -       if ((cmd->opcode != MMC_SEND_TUNING_BLOCK &&
> -           cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) &&
> +       if (cmd->opcode != MMC_SEND_TUNING_BLOCK &&
> +           cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200 &&
> +           !host->expect_errors &&
>             (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) ||
>             (mrq->data && mrq->data->error == -EILSEQ) ||
>             (mrq->stop && mrq->stop->error == -EILSEQ)))
> @@ -2163,6 +2164,20 @@ int mmc_sw_reset(struct mmc_host *host)
>  }
>  EXPORT_SYMBOL(mmc_sw_reset);
>
> +void mmc_expect_errors_begin(struct mmc_host *host)
> +{
> +       WARN_ON(host->expect_errors);

Please remove the WARN_ON. If you believe there is a need for
reference counting, then please add that instead (but likely not in
the phase?).

> +       host->expect_errors = true;
> +}
> +EXPORT_SYMBOL_GPL(mmc_expect_errors_begin);
> +
> +void mmc_expect_errors_end(struct mmc_host *host)
> +{
> +       WARN_ON(!host->expect_errors);

Ditto.

> +       host->expect_errors = false;
> +}
> +EXPORT_SYMBOL_GPL(mmc_expect_errors_end);

These new APIs seems to be useful solely for SDIO. Even if it turns
out later that they can be made generic, I suggest to start with a
SDIO func API instead.

However, using a new host variable (->expect_errors) is fine by me.

> +
>  static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
>  {
>         host->f_init = freq;
> diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
> index 134a6483347a..02a13abf0cda 100644
> --- a/include/linux/mmc/core.h
> +++ b/include/linux/mmc/core.h
> @@ -178,6 +178,8 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd,
>
>  int mmc_hw_reset(struct mmc_host *host);
>  int mmc_sw_reset(struct mmc_host *host);
> +void mmc_expect_errors_begin(struct mmc_host *host);
> +void mmc_expect_errors_end(struct mmc_host *host);

The API prevents a new re-tune to be "scheduled" in case requests are
failing with -EILSEQ.

To better reflect that, may I suggest to rename this to
sdio_retune_crc_disable() and sdio_retune_crc_enable(). Or something
along those lines.


>  void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card);
>
>  #endif /* LINUX_MMC_CORE_H */
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index 43d0f0c496f6..8d553fb8c834 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -398,6 +398,7 @@ struct mmc_host {
>         unsigned int            retune_now:1;   /* do re-tuning at next req */
>         unsigned int            retune_paused:1; /* re-tuning is temporarily disabled */
>         unsigned int            use_blk_mq:1;   /* use blk-mq */
> +       unsigned int            expect_errors:1; /* don't trigger retune upon errors */
>
>         int                     rescan_disable; /* disable card detection */
>         int                     rescan_entered; /* used with nonremovable devices */
> --
> 2.22.0.rc2.383.gf4fbbf30c2-goog
>

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail
       [not found]               ` <CAPDyKFpM0+FfvoMo8Z_hxM9rzSjeQZHCsA2SPa8WP+SRDhhsPA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2019-06-12 13:58                 ` Arend Van Spriel
       [not found]                   ` <16b4bfb39e0.2764.9b12b7fc0a3841636cfb5e919b41b954-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
  0 siblings, 1 reply; 15+ messages in thread
From: Arend Van Spriel @ 2019-06-12 13:58 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Doug Anderson, Hunter, Adrian, Kalle Valo,
	brcm80211-dev-list.pdl-dY08KVG/lbpWk0Htik3J/w,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Double Lo,
	briannorris-F7+t8E8rja9g9hUCZPvPmw,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA, Naveen Gupta,
	Madhan Mohan R, mka-F7+t8E8rja9g9hUCZPvPmw, Wright Feng,
	Chi-Hsien Lin, netdev-u79uwXL29TY76Z2rM5mHXA,
	brcm80211-dev-list-+wT8y+m8/X5BDgjK7y7TUQ, Franky Lin,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Hante Meuleman, YueHaibing,
	David S. Miller


On 6/12/2019 1:48 PM, Ulf Hansson wrote:
> On Wed, 12 Jun 2019 at 13:11, Arend Van Spriel
> <arend.vanspriel-dY08KVG/lbpWk0Htik3J/w@public.gmane.org> wrote:
>>
>> On 6/12/2019 12:10 PM, Ulf Hansson wrote:
>>>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c:
>>>>     mmc_set_data_timeout(md, func->card);
>>>>     mmc_wait_for_req(func->card->host, mr);
>>> These are not okay, none of these things calls should really be done
>>> from an SDIO func driver.
>>>
>>> It tells me that the func driver is a doing workaround for something
>>> that should be managed in a common way.
>>
>> We are using some low-level functions passing chain of skbuff to the
>> device using CMD53 with scatterlist. If I recall correctly Marvell made
>> an attempt to have a similar function for it in the mmc stack. Not sure
>> if that ever made it in. If so I can rework our driver using that API.
>> If not, I can make a new attempt.
> 
> I recall there were some patches, but not sure why we didn't merge them.
> 
> Anyway, if you want to move this forward, that would be awesome!

Let's scope it before moving forward. Our use-case is to transfer a
chain of skbuff's. I am pretty sure that is not something we want to
deal with in mmc stack api. So I suppose passing a scatterlist is more
sensible, right? Maybe on sdio layer of the stack we could consider
dealing with skbuff's for network func drivers?

Let me see if I can find those Marvell patches. Might be a good start.

Regards,
Arend

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail
       [not found]                   ` <16b4bfb39e0.2764.9b12b7fc0a3841636cfb5e919b41b954-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
@ 2019-06-13  9:48                     ` Ulf Hansson
  0 siblings, 0 replies; 15+ messages in thread
From: Ulf Hansson @ 2019-06-13  9:48 UTC (permalink / raw)
  To: Arend Van Spriel
  Cc: Madhan Mohan R, brcm80211-dev-list.pdl-dY08KVG/lbpWk0Htik3J/w,
	YueHaibing, Linux Kernel Mailing List, Hante Meuleman,
	David S. Miller, netdev-u79uwXL29TY76Z2rM5mHXA, Chi-Hsien Lin,
	Brian Norris, linux-wireless, Double Lo, Doug Anderson,
	open list:ARM/Rockchip SoC...,
	Matthias Kaehlcke, Naveen Gupta, Wright Feng, Hunter, Adrian,
	brcm80211-dev-list-+wT8y+m8/X5BDgjK7y7TUQ, Kalle Valo,
	Franky Lin

On Wed, 12 Jun 2019 at 15:58, Arend Van Spriel
<arend.vanspriel-dY08KVG/lbpWk0Htik3J/w@public.gmane.org> wrote:
>
>
> On 6/12/2019 1:48 PM, Ulf Hansson wrote:
> > On Wed, 12 Jun 2019 at 13:11, Arend Van Spriel
> > <arend.vanspriel-dY08KVG/lbpWk0Htik3J/w@public.gmane.org> wrote:
> >>
> >> On 6/12/2019 12:10 PM, Ulf Hansson wrote:
> >>>> drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c:
> >>>>     mmc_set_data_timeout(md, func->card);
> >>>>     mmc_wait_for_req(func->card->host, mr);
> >>> These are not okay, none of these things calls should really be done
> >>> from an SDIO func driver.
> >>>
> >>> It tells me that the func driver is a doing workaround for something
> >>> that should be managed in a common way.
> >>
> >> We are using some low-level functions passing chain of skbuff to the
> >> device using CMD53 with scatterlist. If I recall correctly Marvell made
> >> an attempt to have a similar function for it in the mmc stack. Not sure
> >> if that ever made it in. If so I can rework our driver using that API.
> >> If not, I can make a new attempt.
> >
> > I recall there were some patches, but not sure why we didn't merge them.
> >
> > Anyway, if you want to move this forward, that would be awesome!
>
> Let's scope it before moving forward. Our use-case is to transfer a
> chain of skbuff's. I am pretty sure that is not something we want to
> deal with in mmc stack api. So I suppose passing a scatterlist is more
> sensible, right? Maybe on sdio layer of the stack we could consider
> dealing with skbuff's for network func drivers?

Passing a scatter gather list seems reasonable. Ideally we should be
highly influenced with how buffers and dealt with for mmc block
requests.

Some information that may be needed by upper SDIO layers is the
segment/block constraints set by the MMC/SDIO host controller/driver.
The below is what we have today (see include/linux/mmc/host.h):

max_seg_size;   /* see blk_queue_max_segment_size */
max_segs;       /* see blk_queue_max_segments */
max_req_size;   /* maximum number of bytes in one req */
max_blk_size;   /* maximum size of one mmc block */
max_blk_count;  /* maximum number of blocks in one req */

Ideally we don't want SDIO func drivers to access these directly from
the ->host pointer, but rather via new SDIO func APIs.

>
> Let me see if I can find those Marvell patches. Might be a good start.

Great! Thanks!

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2019-06-13  9:48 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-07 22:37 [PATCH v3 0/5] brcmfmac: sdio: Deal better w/ transmission errors related to idle Douglas Anderson
2019-06-07 22:37 ` [PATCH v3 1/5] Revert "brcmfmac: disable command decode in sdio_aos" Douglas Anderson
     [not found] ` <20190607223716.119277-1-dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2019-06-07 22:37   ` [PATCH v3 2/5] mmc: core: API for temporarily disabling auto-retuning due to errors Douglas Anderson
2019-06-12 13:25     ` Ulf Hansson
2019-06-07 22:37   ` [PATCH v3 3/5] brcmfmac: sdio: Disable auto-tuning around commands expected to fail Douglas Anderson
2019-06-10  8:56     ` Hunter, Adrian
2019-06-10 16:50       ` Doug Anderson
2019-06-11  7:17         ` Adrian Hunter
2019-06-12 10:10         ` Ulf Hansson
2019-06-12 11:11           ` Arend Van Spriel
2019-06-12 11:48             ` Ulf Hansson
     [not found]               ` <CAPDyKFpM0+FfvoMo8Z_hxM9rzSjeQZHCsA2SPa8WP+SRDhhsPA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2019-06-12 13:58                 ` Arend Van Spriel
     [not found]                   ` <16b4bfb39e0.2764.9b12b7fc0a3841636cfb5e919b41b954-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
2019-06-13  9:48                     ` Ulf Hansson
2019-06-07 22:37 ` [PATCH v3 4/5] mmc: core: Export mmc_retune_hold_now() mmc_retune_release() Douglas Anderson
2019-06-07 22:37 ` [PATCH v3 5/5] brcmfmac: sdio: Don't tune while the card is off Douglas Anderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).