Commit 8c317062 authored by Matthias Proske's avatar Matthias Proske Committed by Johannes Berg
Browse files

wifi: brcmfmac: keep power during suspend if board requires it



After commit 92cadedd ("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.

This conflicts with some embedded boards that require to remain powered.
They will fail on resume with:

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

This commit checks for the Device Tree property 'cap-power-off-cards'.
If this property is not set, it means that we do not have the capability
to power off and should therefore remain powered.

Signed-off-by: default avatarMatthias Proske <email@matthias-proske.de>
Acked-by: default avatarArend van Spriel <arend.vanspriel@broadcom.com>
Link: https://patch.msgid.link/20250212185941.146958-2-email@matthias-proske.de


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 861d0445
Loading
Loading
Loading
Loading
+13 −7
Original line number Diff line number Diff line
@@ -1172,6 +1172,7 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
	struct brcmf_bus *bus_if;
	struct brcmf_sdio_dev *sdiodev;
	mmc_pm_flag_t sdio_flags;
	bool cap_power_off;
	int ret = 0;

	func = container_of(dev, struct sdio_func, dev);
@@ -1179,19 +1180,23 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
	if (func->num != 1)
		return 0;

	cap_power_off = !!(func->card->host->caps & MMC_CAP_POWER_OFF_CARD);

	bus_if = dev_get_drvdata(dev);
	sdiodev = bus_if->bus_priv.sdio;

	if (sdiodev->wowl_enabled) {
	if (sdiodev->wowl_enabled || !cap_power_off) {
		brcmf_sdiod_freezer_on(sdiodev);
		brcmf_sdio_wd_timer(sdiodev->bus, 0);

		sdio_flags = MMC_PM_KEEP_POWER;

		if (sdiodev->wowl_enabled) {
			if (sdiodev->settings->bus.sdio.oob_irq_supported)
				enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
			else
				sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
		}

		if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags))
			brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
@@ -1213,18 +1218,19 @@ static int brcmf_ops_sdio_resume(struct device *dev)
	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
	struct sdio_func *func = container_of(dev, struct sdio_func, dev);
	int ret = 0;
	bool cap_power_off = !!(func->card->host->caps & MMC_CAP_POWER_OFF_CARD);

	brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
	if (func->num != 2)
		return 0;

	if (!sdiodev->wowl_enabled) {
	if (!sdiodev->wowl_enabled && cap_power_off) {
		/* bus was powered off and device removed, probe again */
		ret = brcmf_sdiod_probe(sdiodev);
		if (ret)
			brcmf_err("Failed to probe device on resume\n");
	} else {
		if (sdiodev->settings->bus.sdio.oob_irq_supported)
		if (sdiodev->wowl_enabled && sdiodev->settings->bus.sdio.oob_irq_supported)
			disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);

		brcmf_sdiod_freezer_off(sdiodev);