Skip to content

Commit e4efa51

Browse files
jwrdegoedeKalle Valo
authored andcommitted
wifi: brcmfmac: Fix SDIO suspend/resume regression
After commit 92caded ("brcmfmac: Avoid keeping power to SDIO card unless WOWL is used"), the wifi adapter by default is turned off on suspend and then re-probed on resume. In at least 2 model x86/acpi tablets with brcmfmac43430a1 wifi adapters, the newly added re-probe on resume fails like this: brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout ieee80211 phy1: brcmf_bus_started: failed: -110 ieee80211 phy1: brcmf_attach: dongle is not responding: err=-110 brcmfmac: brcmf_sdio_firmware_callback: brcmf_attach failed It seems this specific brcmfmac model does not like being reprobed without it actually being turned off first. And the adapter is not being turned off during suspend because of commit f0992ac ("brcmfmac: prohibit ACPI power management for brcmfmac driver"). Now that the driver is being reprobed on resume, the disabling of ACPI pm is no longer necessary, except when WOWL is used (in which case there is no-reprobe). Move the dis-/en-abling of ACPI pm to brcmf_sdio_wowl_config(), this fixes the brcmfmac43430a1 suspend/resume regression and should help save some power when suspended. This change means that the code now also may re-enable ACPI pm when WOWL gets disabled. ACPI pm should only be re-enabled if it was enabled by the ACPI core originally. Add a brcmf_sdiod_acpi_save_power_manageable() to save the original state for this. This has been tested on the following devices: Asus T100TA brcmfmac43241b4-sdio Acer Iconia One 7 B1-750 brcmfmac43340-sdio Chuwi Hi8 brcmfmac43430a0-sdio Chuwi Hi8 brcmfmac43430a1-sdio (the Asus T100TA is the device for which the prohibiting of ACPI pm was originally added) Fixes: 92caded ("brcmfmac: Avoid keeping power to SDIO card unless WOWL is used") Cc: Ulf Hansson <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Reviewed-by: Ulf Hansson <[email protected]> Signed-off-by: Kalle Valo <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 12b220a commit e4efa51

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -994,15 +994,34 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
994994
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
995995

996996

997-
static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev,
998-
int val)
997+
static void brcmf_sdiod_acpi_save_power_manageable(struct brcmf_sdio_dev *sdiodev)
999998
{
1000999
#if IS_ENABLED(CONFIG_ACPI)
10011000
struct acpi_device *adev;
10021001

1003-
adev = ACPI_COMPANION(dev);
1002+
adev = ACPI_COMPANION(&sdiodev->func1->dev);
10041003
if (adev)
1005-
adev->flags.power_manageable = 0;
1004+
sdiodev->func1_power_manageable = adev->flags.power_manageable;
1005+
1006+
adev = ACPI_COMPANION(&sdiodev->func2->dev);
1007+
if (adev)
1008+
sdiodev->func2_power_manageable = adev->flags.power_manageable;
1009+
#endif
1010+
}
1011+
1012+
static void brcmf_sdiod_acpi_set_power_manageable(struct brcmf_sdio_dev *sdiodev,
1013+
int enable)
1014+
{
1015+
#if IS_ENABLED(CONFIG_ACPI)
1016+
struct acpi_device *adev;
1017+
1018+
adev = ACPI_COMPANION(&sdiodev->func1->dev);
1019+
if (adev)
1020+
adev->flags.power_manageable = enable ? sdiodev->func1_power_manageable : 0;
1021+
1022+
adev = ACPI_COMPANION(&sdiodev->func2->dev);
1023+
if (adev)
1024+
adev->flags.power_manageable = enable ? sdiodev->func2_power_manageable : 0;
10061025
#endif
10071026
}
10081027

@@ -1012,22 +1031,16 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
10121031
int err;
10131032
struct brcmf_sdio_dev *sdiodev;
10141033
struct brcmf_bus *bus_if;
1015-
struct device *dev;
10161034

10171035
brcmf_dbg(SDIO, "Enter\n");
10181036
brcmf_dbg(SDIO, "Class=%x\n", func->class);
10191037
brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
10201038
brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
10211039
brcmf_dbg(SDIO, "Function#: %d\n", func->num);
10221040

1023-
dev = &func->dev;
1024-
10251041
/* Set MMC_QUIRK_LENIENT_FN0 for this card */
10261042
func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
10271043

1028-
/* prohibit ACPI power management for this device */
1029-
brcmf_sdiod_acpi_set_power_manageable(dev, 0);
1030-
10311044
/* Consume func num 1 but dont do anything with it. */
10321045
if (func->num == 1)
10331046
return 0;
@@ -1059,6 +1072,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
10591072
dev_set_drvdata(&sdiodev->func1->dev, bus_if);
10601073
sdiodev->dev = &sdiodev->func1->dev;
10611074

1075+
brcmf_sdiod_acpi_save_power_manageable(sdiodev);
10621076
brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN);
10631077

10641078
brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n");
@@ -1124,6 +1138,8 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled)
11241138

11251139
if (sdiodev->settings->bus.sdio.oob_irq_supported ||
11261140
pm_caps & MMC_PM_WAKE_SDIO_IRQ) {
1141+
/* Stop ACPI from turning off the device when wowl is enabled */
1142+
brcmf_sdiod_acpi_set_power_manageable(sdiodev, !enabled);
11271143
sdiodev->wowl_enabled = enabled;
11281144
brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled);
11291145
return;

drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ struct brcmf_sdio_dev {
188188
char nvram_name[BRCMF_FW_NAME_LEN];
189189
char clm_name[BRCMF_FW_NAME_LEN];
190190
bool wowl_enabled;
191+
bool func1_power_manageable;
192+
bool func2_power_manageable;
191193
enum brcmf_sdiod_state state;
192194
struct brcmf_sdiod_freezer *freezer;
193195
const struct firmware *clm_fw;

0 commit comments

Comments
 (0)