Skip to content

Commit 11ed8b8

Browse files
jim2101024bjorn-helgaas
authored andcommitted
PCI: brcmstb: Do not turn off WOL regulators on suspend
If any downstream device can be a wakeup device, do not turn off the regulators as the device will need them on. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jim Quinlan <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]>
1 parent 93e41f3 commit 11ed8b8

File tree

1 file changed

+44
-9
lines changed

1 file changed

+44
-9
lines changed

drivers/pci/controller/pcie-brcmstb.c

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ struct brcm_pcie {
310310
void (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val);
311311
bool refusal_mode;
312312
struct subdev_regulators *sr;
313+
bool ep_wakeup_capable;
313314
};
314315

315316
/*
@@ -1278,9 +1279,21 @@ static void brcm_pcie_turn_off(struct brcm_pcie *pcie)
12781279
pcie->bridge_sw_init_set(pcie, 1);
12791280
}
12801281

1282+
static int pci_dev_may_wakeup(struct pci_dev *dev, void *data)
1283+
{
1284+
bool *ret = data;
1285+
1286+
if (device_may_wakeup(&dev->dev)) {
1287+
*ret = true;
1288+
dev_info(&dev->dev, "disable cancelled for wake-up device\n");
1289+
}
1290+
return (int) *ret;
1291+
}
1292+
12811293
static int brcm_pcie_suspend(struct device *dev)
12821294
{
12831295
struct brcm_pcie *pcie = dev_get_drvdata(dev);
1296+
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
12841297
int ret;
12851298

12861299
brcm_pcie_turn_off(pcie);
@@ -1299,11 +1312,22 @@ static int brcm_pcie_suspend(struct device *dev)
12991312
}
13001313

13011314
if (pcie->sr) {
1302-
ret = regulator_bulk_disable(pcie->sr->num_supplies, pcie->sr->supplies);
1303-
if (ret) {
1304-
dev_err(dev, "Could not turn off regulators\n");
1305-
reset_control_reset(pcie->rescal);
1306-
return ret;
1315+
/*
1316+
* Now turn off the regulators, but if at least one
1317+
* downstream device is enabled as a wake-up source, do not
1318+
* turn off regulators.
1319+
*/
1320+
pcie->ep_wakeup_capable = false;
1321+
pci_walk_bus(bridge->bus, pci_dev_may_wakeup,
1322+
&pcie->ep_wakeup_capable);
1323+
if (!pcie->ep_wakeup_capable) {
1324+
ret = regulator_bulk_disable(pcie->sr->num_supplies,
1325+
pcie->sr->supplies);
1326+
if (ret) {
1327+
dev_err(dev, "Could not turn off regulators\n");
1328+
reset_control_reset(pcie->rescal);
1329+
return ret;
1330+
}
13071331
}
13081332
}
13091333
clk_disable_unprepare(pcie->clk);
@@ -1324,10 +1348,21 @@ static int brcm_pcie_resume(struct device *dev)
13241348
return ret;
13251349

13261350
if (pcie->sr) {
1327-
ret = regulator_bulk_enable(pcie->sr->num_supplies, pcie->sr->supplies);
1328-
if (ret) {
1329-
dev_err(dev, "Could not turn on regulators\n");
1330-
goto err_disable_clk;
1351+
if (pcie->ep_wakeup_capable) {
1352+
/*
1353+
* We are resuming from a suspend. In the suspend we
1354+
* did not disable the power supplies, so there is
1355+
* no need to enable them (and falsely increase their
1356+
* usage count).
1357+
*/
1358+
pcie->ep_wakeup_capable = false;
1359+
} else {
1360+
ret = regulator_bulk_enable(pcie->sr->num_supplies,
1361+
pcie->sr->supplies);
1362+
if (ret) {
1363+
dev_err(dev, "Could not turn on regulators\n");
1364+
goto err_disable_clk;
1365+
}
13311366
}
13321367
}
13331368

0 commit comments

Comments
 (0)