Commit 0a529da8 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-stmmac-improbe-suspend-resume-architecture'

Russell King says:

====================
net: stmmac: improbe suspend/resume architecture

This series improves the stmmac suspend/resume architecture by
providing a couple of method hooks in struct plat_stmmacenet_data which
are called by core code, and thus are available for any of the
platform glue drivers, whether using a platform or PCI device.

As these methods are called by core code, we can also provide a simple
PM ops structure also in the core code for converted glue drivers to
use.

The remainder of the patches convert the various drivers.
====================

Link: https://patch.msgid.link/aJo7kvoub5voHOUQ@shell.armlinux.org.uk


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents c88c6b2d d6e1f227
Loading
Loading
Loading
Loading
+35 −39
Original line number Diff line number Diff line
@@ -1231,6 +1231,37 @@ static int stmmac_config_multi_msi(struct pci_dev *pdev,
	return 0;
}

static int intel_eth_pci_suspend(struct device *dev, void *bsp_priv)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	int ret;

	ret = pci_save_state(pdev);
	if (ret)
		return ret;

	pci_wake_from_d3(pdev, true);
	pci_set_power_state(pdev, PCI_D3hot);
	return 0;
}

static int intel_eth_pci_resume(struct device *dev, void *bsp_priv)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	int ret;

	pci_restore_state(pdev);
	pci_set_power_state(pdev, PCI_D0);

	ret = pcim_enable_device(pdev);
	if (ret)
		return ret;

	pci_set_master(pdev);

	return 0;
}

/**
 * intel_eth_pci_probe
 *
@@ -1292,6 +1323,9 @@ static int intel_eth_pci_probe(struct pci_dev *pdev,
	pci_set_master(pdev);

	plat->bsp_priv = intel_priv;
	plat->suspend = intel_eth_pci_suspend;
	plat->resume = intel_eth_pci_resume;

	intel_priv->mdio_adhoc_addr = INTEL_MGBE_ADHOC_ADDR;
	intel_priv->crossts_adj = 1;

@@ -1355,44 +1389,6 @@ static void intel_eth_pci_remove(struct pci_dev *pdev)
	clk_unregister_fixed_rate(priv->plat->stmmac_clk);
}

static int __maybe_unused intel_eth_pci_suspend(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	int ret;

	ret = stmmac_suspend(dev);
	if (ret)
		return ret;

	ret = pci_save_state(pdev);
	if (ret)
		return ret;

	pci_wake_from_d3(pdev, true);
	pci_set_power_state(pdev, PCI_D3hot);
	return 0;
}

static int __maybe_unused intel_eth_pci_resume(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	int ret;

	pci_restore_state(pdev);
	pci_set_power_state(pdev, PCI_D0);

	ret = pcim_enable_device(pdev);
	if (ret)
		return ret;

	pci_set_master(pdev);

	return stmmac_resume(dev);
}

static SIMPLE_DEV_PM_OPS(intel_eth_pm_ops, intel_eth_pci_suspend,
			 intel_eth_pci_resume);

#define PCI_DEVICE_ID_INTEL_QUARK		0x0937
#define PCI_DEVICE_ID_INTEL_EHL_RGMII1G		0x4b30
#define PCI_DEVICE_ID_INTEL_EHL_SGMII1G		0x4b31
@@ -1442,7 +1438,7 @@ static struct pci_driver intel_eth_pci_driver = {
	.probe = intel_eth_pci_probe,
	.remove = intel_eth_pci_remove,
	.driver         = {
		.pm     = &intel_eth_pm_ops,
		.pm     = &stmmac_simple_pm_ops,
	},
};

+34 −39
Original line number Diff line number Diff line
@@ -521,6 +521,37 @@ static int loongson_dwmac_fix_reset(void *priv, void __iomem *ioaddr)
				  10000, 2000000);
}

static int loongson_dwmac_suspend(struct device *dev, void *bsp_priv)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	int ret;

	ret = pci_save_state(pdev);
	if (ret)
		return ret;

	pci_disable_device(pdev);
	pci_wake_from_d3(pdev, true);
	return 0;
}

static int loongson_dwmac_resume(struct device *dev, void *bsp_priv)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	int ret;

	pci_restore_state(pdev);
	pci_set_power_state(pdev, PCI_D0);

	ret = pci_enable_device(pdev);
	if (ret)
		return ret;

	pci_set_master(pdev);

	return 0;
}

static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
	struct plat_stmmacenet_data *plat;
@@ -565,6 +596,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
	plat->bsp_priv = ld;
	plat->setup = loongson_dwmac_setup;
	plat->fix_soc_reset = loongson_dwmac_fix_reset;
	plat->suspend = loongson_dwmac_suspend;
	plat->resume = loongson_dwmac_resume;
	ld->dev = &pdev->dev;
	ld->loongson_id = readl(res.addr + GMAC_VERSION) & 0xff;

@@ -621,44 +654,6 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)
	pci_disable_device(pdev);
}

static int __maybe_unused loongson_dwmac_suspend(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	int ret;

	ret = stmmac_suspend(dev);
	if (ret)
		return ret;

	ret = pci_save_state(pdev);
	if (ret)
		return ret;

	pci_disable_device(pdev);
	pci_wake_from_d3(pdev, true);
	return 0;
}

static int __maybe_unused loongson_dwmac_resume(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	int ret;

	pci_restore_state(pdev);
	pci_set_power_state(pdev, PCI_D0);

	ret = pci_enable_device(pdev);
	if (ret)
		return ret;

	pci_set_master(pdev);

	return stmmac_resume(dev);
}

static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
			 loongson_dwmac_resume);

static const struct pci_device_id loongson_dwmac_id_table[] = {
	{ PCI_DEVICE_DATA(LOONGSON, GMAC1, &loongson_gmac_pci_info) },
	{ PCI_DEVICE_DATA(LOONGSON, GMAC2, &loongson_gmac_pci_info) },
@@ -673,7 +668,7 @@ static struct pci_driver loongson_dwmac_driver = {
	.probe = loongson_dwmac_probe,
	.remove = loongson_dwmac_remove,
	.driver = {
		.pm = &loongson_dwmac_pm_ops,
		.pm = &stmmac_simple_pm_ops,
	},
};

+5 −5
Original line number Diff line number Diff line
@@ -523,7 +523,7 @@ static int mediatek_dwmac_clk_init(struct mediatek_dwmac_plat_data *plat)
	return ret;
}

static int mediatek_dwmac_init(struct platform_device *pdev, void *priv)
static int mediatek_dwmac_init(struct device *dev, void *priv)
{
	struct mediatek_dwmac_plat_data *plat = priv;
	const struct mediatek_dwmac_variant *variant = plat->variant;
@@ -532,7 +532,7 @@ static int mediatek_dwmac_init(struct platform_device *pdev, void *priv)
	if (variant->dwmac_set_phy_interface) {
		ret = variant->dwmac_set_phy_interface(plat);
		if (ret) {
			dev_err(plat->dev, "failed to set phy interface, err = %d\n", ret);
			dev_err(dev, "failed to set phy interface, err = %d\n", ret);
			return ret;
		}
	}
@@ -540,7 +540,7 @@ static int mediatek_dwmac_init(struct platform_device *pdev, void *priv)
	if (variant->dwmac_set_delay) {
		ret = variant->dwmac_set_delay(plat);
		if (ret) {
			dev_err(plat->dev, "failed to set delay value, err = %d\n", ret);
			dev_err(dev, "failed to set delay value, err = %d\n", ret);
			return ret;
		}
	}
@@ -589,7 +589,7 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev,
	plat->maxmtu = ETH_DATA_LEN;
	plat->host_dma_width = priv_plat->variant->dma_bit_mask;
	plat->bsp_priv = priv_plat;
	plat->init = mediatek_dwmac_init;
	plat->resume = mediatek_dwmac_init;
	plat->clks_config = mediatek_dwmac_clks_config;

	plat->safety_feat_cfg = devm_kzalloc(&pdev->dev,
@@ -654,7 +654,7 @@ static int mediatek_dwmac_probe(struct platform_device *pdev)
		return PTR_ERR(plat_dat);

	mediatek_dwmac_common_data(pdev, plat_dat, priv_plat);
	mediatek_dwmac_init(pdev, priv_plat);
	mediatek_dwmac_init(&pdev->dev, priv_plat);

	ret = mediatek_dwmac_clks_config(priv_plat, true);
	if (ret)
+25 −33
Original line number Diff line number Diff line
@@ -71,7 +71,6 @@ struct rk_priv_data {
	phy_interface_t phy_iface;
	int id;
	struct regulator *regulator;
	bool suspended;
	const struct rk_gmac_ops *ops;

	bool clk_enabled;
@@ -1706,6 +1705,28 @@ static int rk_set_clk_tx_rate(void *bsp_priv_, struct clk *clk_tx_i,
	return -EINVAL;
}

static int rk_gmac_suspend(struct device *dev, void *bsp_priv_)
{
	struct rk_priv_data *bsp_priv = bsp_priv_;

	/* Keep the PHY up if we use Wake-on-Lan. */
	if (!device_may_wakeup(dev))
		rk_gmac_powerdown(bsp_priv);

	return 0;
}

static int rk_gmac_resume(struct device *dev, void *bsp_priv_)
{
	struct rk_priv_data *bsp_priv = bsp_priv_;

	/* The PHY was up for Wake-on-Lan. */
	if (!device_may_wakeup(dev))
		rk_gmac_powerup(bsp_priv);

	return 0;
}

static int rk_gmac_probe(struct platform_device *pdev)
{
	struct plat_stmmacenet_data *plat_dat;
@@ -1738,6 +1759,8 @@ static int rk_gmac_probe(struct platform_device *pdev)

	plat_dat->get_interfaces = rk_get_interfaces;
	plat_dat->set_clk_tx_rate = rk_set_clk_tx_rate;
	plat_dat->suspend = rk_gmac_suspend;
	plat_dat->resume = rk_gmac_resume;

	plat_dat->bsp_priv = rk_gmac_setup(pdev, plat_dat, data);
	if (IS_ERR(plat_dat->bsp_priv))
@@ -1772,37 +1795,6 @@ static void rk_gmac_remove(struct platform_device *pdev)
	rk_gmac_powerdown(bsp_priv);
}

#ifdef CONFIG_PM_SLEEP
static int rk_gmac_suspend(struct device *dev)
{
	struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(dev);
	int ret = stmmac_suspend(dev);

	/* Keep the PHY up if we use Wake-on-Lan. */
	if (!device_may_wakeup(dev)) {
		rk_gmac_powerdown(bsp_priv);
		bsp_priv->suspended = true;
	}

	return ret;
}

static int rk_gmac_resume(struct device *dev)
{
	struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(dev);

	/* The PHY was up for Wake-on-Lan. */
	if (bsp_priv->suspended) {
		rk_gmac_powerup(bsp_priv);
		bsp_priv->suspended = false;
	}

	return stmmac_resume(dev);
}
#endif /* CONFIG_PM_SLEEP */

static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops, rk_gmac_suspend, rk_gmac_resume);

static const struct of_device_id rk_gmac_dwmac_match[] = {
	{ .compatible = "rockchip,px30-gmac",	.data = &px30_ops   },
	{ .compatible = "rockchip,rk3128-gmac", .data = &rk3128_ops },
@@ -1828,7 +1820,7 @@ static struct platform_driver rk_gmac_dwmac_driver = {
	.remove = rk_gmac_remove,
	.driver = {
		.name           = "rk_gmac-dwmac",
		.pm		= &rk_gmac_pm_ops,
		.pm		= &stmmac_simple_pm_ops,
		.of_match_table = rk_gmac_dwmac_match,
	},
};
+23 −45
Original line number Diff line number Diff line
@@ -498,6 +498,26 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
	return err;
}

static int stm32_dwmac_suspend(struct device *dev, void *bsp_priv)
{
	struct stm32_dwmac *dwmac = bsp_priv;

	stm32_dwmac_clk_disable(dwmac);

	return dwmac->ops->suspend ? dwmac->ops->suspend(dwmac) : 0;
}

static int stm32_dwmac_resume(struct device *dev, void *bsp_priv)
{
	struct stmmac_priv *priv = netdev_priv(dev_get_drvdata(dev));
	struct stm32_dwmac *dwmac = bsp_priv;

	if (dwmac->ops->resume)
		dwmac->ops->resume(dwmac);

	return stm32_dwmac_init(priv->plat);
}

static int stm32_dwmac_probe(struct platform_device *pdev)
{
	struct plat_stmmacenet_data *plat_dat;
@@ -535,6 +555,8 @@ static int stm32_dwmac_probe(struct platform_device *pdev)

	plat_dat->flags |= STMMAC_FLAG_EN_TX_LPI_CLK_PHY_CAP;
	plat_dat->bsp_priv = dwmac;
	plat_dat->suspend = stm32_dwmac_suspend;
	plat_dat->resume = stm32_dwmac_resume;

	ret = stm32_dwmac_init(plat_dat);
	if (ret)
@@ -600,50 +622,6 @@ static void stm32mp1_resume(struct stm32_dwmac *dwmac)
	clk_disable_unprepare(dwmac->clk_ethstp);
}

#ifdef CONFIG_PM_SLEEP
static int stm32_dwmac_suspend(struct device *dev)
{
	struct net_device *ndev = dev_get_drvdata(dev);
	struct stmmac_priv *priv = netdev_priv(ndev);
	struct stm32_dwmac *dwmac = priv->plat->bsp_priv;

	int ret;

	ret = stmmac_suspend(dev);
	if (ret)
		return ret;

	stm32_dwmac_clk_disable(dwmac);

	if (dwmac->ops->suspend)
		ret = dwmac->ops->suspend(dwmac);

	return ret;
}

static int stm32_dwmac_resume(struct device *dev)
{
	struct net_device *ndev = dev_get_drvdata(dev);
	struct stmmac_priv *priv = netdev_priv(ndev);
	struct stm32_dwmac *dwmac = priv->plat->bsp_priv;
	int ret;

	if (dwmac->ops->resume)
		dwmac->ops->resume(dwmac);

	ret = stm32_dwmac_init(priv->plat);
	if (ret)
		return ret;

	ret = stmmac_resume(dev);

	return ret;
}
#endif /* CONFIG_PM_SLEEP */

static SIMPLE_DEV_PM_OPS(stm32_dwmac_pm_ops,
	stm32_dwmac_suspend, stm32_dwmac_resume);

static struct stm32_ops stm32mcu_dwmac_data = {
	.set_mode = stm32mcu_set_mode
};
@@ -691,7 +669,7 @@ static struct platform_driver stm32_dwmac_driver = {
	.remove = stm32_dwmac_remove,
	.driver = {
		.name           = "stm32-dwmac",
		.pm		= &stm32_dwmac_pm_ops,
		.pm		= &stmmac_simple_pm_ops,
		.of_match_table = stm32_dwmac_match,
	},
};
Loading