Re: [PATCH v3] net: mvneta: support suspend and resume
On 03/16/2017 03:48 PM, Jisheng Zhang wrote: On Thu, 16 Mar 2017 15:11:48 +0800 Jane Li wrote: Add basic support for handling suspend and resume. Signed-off-by: Jane Li <j...@marvell.com> --- Since v2: - use SIMPLE_DEV_PM_OPS instead of SET_LATE_SYSTEM_SLEEP_PM_OPS Since v1: - add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume() drivers/net/ethernet/marvell/mvneta.c | 60 --- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..b0fea26 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -431,6 +431,7 @@ struct mvneta_port { /* Flags for special SoC configurations */ bool neta_armada3700; u16 rx_offset_correction; + const struct mbus_dram_target_info *dram_target_info; }; /* The mvneta_tx_desc and mvneta_rx_desc structures describe the @@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) /* Device initialization routine */ static int mvneta_probe(struct platform_device *pdev) { - const struct mbus_dram_target_info *dram_target_info; struct resource *res; struct device_node *dn = pdev->dev.of_node; struct device_node *phy_node; @@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev) pp->tx_csum_limit = tx_csum_limit; - dram_target_info = mv_mbus_dram_info(); + pp->dram_target_info = mv_mbus_dram_info(); /* Armada3700 requires setting default configuration of Mbus * windows, however without using filled mbus_dram_target_info * structure. */ - if (dram_target_info || pp->neta_armada3700) - mvneta_conf_mbus_windows(pp, dram_target_info); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); pp->tx_ring_size = MVNETA_MAX_TXD; pp->rx_ring_size = MVNETA_MAX_RXD; @@ -4405,6 +4405,57 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + clk_prepare_enable(pp->clk_bus); hmm, since clk_bus is optional, it's better to add check here. Except the above, you could add Reviewed-by: Jisheng Zhang <jszh...@marvell.com> Done. Add this in patch v4. + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); + if (pp->bm_priv) { + err = mvneta_bm_port_init(pdev, pp); + if (err < 0) { + dev_info(>dev, "use SW buffer management\n"); + pp->bm_priv = NULL; + } + } + mvneta_defaults_set(pp); + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(mvneta_pm_ops, mvneta_suspend, mvneta_resume); + static const struct of_device_id mvneta_match[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -4419,6 +4470,7 @@ static int mvneta_remove(struct platform_device *pdev) .driver = { .name = MVNETA_DRIVER_NAME, .of_match_table = mvneta_match, + .pm = _pm_ops, }, };
Re: [PATCH v3] net: mvneta: support suspend and resume
On 03/16/2017 03:48 PM, Jisheng Zhang wrote: On Thu, 16 Mar 2017 15:11:48 +0800 Jane Li wrote: Add basic support for handling suspend and resume. Signed-off-by: Jane Li --- Since v2: - use SIMPLE_DEV_PM_OPS instead of SET_LATE_SYSTEM_SLEEP_PM_OPS Since v1: - add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume() drivers/net/ethernet/marvell/mvneta.c | 60 --- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..b0fea26 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -431,6 +431,7 @@ struct mvneta_port { /* Flags for special SoC configurations */ bool neta_armada3700; u16 rx_offset_correction; + const struct mbus_dram_target_info *dram_target_info; }; /* The mvneta_tx_desc and mvneta_rx_desc structures describe the @@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) /* Device initialization routine */ static int mvneta_probe(struct platform_device *pdev) { - const struct mbus_dram_target_info *dram_target_info; struct resource *res; struct device_node *dn = pdev->dev.of_node; struct device_node *phy_node; @@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev) pp->tx_csum_limit = tx_csum_limit; - dram_target_info = mv_mbus_dram_info(); + pp->dram_target_info = mv_mbus_dram_info(); /* Armada3700 requires setting default configuration of Mbus * windows, however without using filled mbus_dram_target_info * structure. */ - if (dram_target_info || pp->neta_armada3700) - mvneta_conf_mbus_windows(pp, dram_target_info); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); pp->tx_ring_size = MVNETA_MAX_TXD; pp->rx_ring_size = MVNETA_MAX_RXD; @@ -4405,6 +4405,57 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + clk_prepare_enable(pp->clk_bus); hmm, since clk_bus is optional, it's better to add check here. Except the above, you could add Reviewed-by: Jisheng Zhang Done. Add this in patch v4. + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); + if (pp->bm_priv) { + err = mvneta_bm_port_init(pdev, pp); + if (err < 0) { + dev_info(>dev, "use SW buffer management\n"); + pp->bm_priv = NULL; + } + } + mvneta_defaults_set(pp); + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(mvneta_pm_ops, mvneta_suspend, mvneta_resume); + static const struct of_device_id mvneta_match[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -4419,6 +4470,7 @@ static int mvneta_remove(struct platform_device *pdev) .driver = { .name = MVNETA_DRIVER_NAME, .of_match_table = mvneta_match, + .pm = _pm_ops, }, };
[PATCH v4] net: mvneta: support suspend and resume
Add basic support for handling suspend and resume. Signed-off-by: Jane Li <j...@marvell.com> Reviewed-by: Jisheng Zhang <jszh...@marvell.com> --- Since v3: - check clk_bus before enabling it during resume Since v2: - use SIMPLE_DEV_PM_OPS instead of SET_LATE_SYSTEM_SLEEP_PM_OPS Since v1: - add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume() drivers/net/ethernet/marvell/mvneta.c | 61 --- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..aebbc53 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -431,6 +431,7 @@ struct mvneta_port { /* Flags for special SoC configurations */ bool neta_armada3700; u16 rx_offset_correction; + const struct mbus_dram_target_info *dram_target_info; }; /* The mvneta_tx_desc and mvneta_rx_desc structures describe the @@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) /* Device initialization routine */ static int mvneta_probe(struct platform_device *pdev) { - const struct mbus_dram_target_info *dram_target_info; struct resource *res; struct device_node *dn = pdev->dev.of_node; struct device_node *phy_node; @@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev) pp->tx_csum_limit = tx_csum_limit; - dram_target_info = mv_mbus_dram_info(); + pp->dram_target_info = mv_mbus_dram_info(); /* Armada3700 requires setting default configuration of Mbus * windows, however without using filled mbus_dram_target_info * structure. */ - if (dram_target_info || pp->neta_armada3700) - mvneta_conf_mbus_windows(pp, dram_target_info); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); pp->tx_ring_size = MVNETA_MAX_TXD; pp->rx_ring_size = MVNETA_MAX_RXD; @@ -4405,6 +4405,58 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + if (!IS_ERR(pp->clk_bus)) + clk_prepare_enable(pp->clk_bus); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); + if (pp->bm_priv) { + err = mvneta_bm_port_init(pdev, pp); + if (err < 0) { + dev_info(>dev, "use SW buffer management\n"); + pp->bm_priv = NULL; + } + } + mvneta_defaults_set(pp); + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(mvneta_pm_ops, mvneta_suspend, mvneta_resume); + static const struct of_device_id mvneta_match[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -4419,6 +4471,7 @@ static int mvneta_remove(struct platform_device *pdev) .driver = { .name = MVNETA_DRIVER_NAME, .of_match_table = mvneta_match, + .pm = _pm_ops, }, }; -- 1.9.1
[PATCH v4] net: mvneta: support suspend and resume
Add basic support for handling suspend and resume. Signed-off-by: Jane Li Reviewed-by: Jisheng Zhang --- Since v3: - check clk_bus before enabling it during resume Since v2: - use SIMPLE_DEV_PM_OPS instead of SET_LATE_SYSTEM_SLEEP_PM_OPS Since v1: - add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume() drivers/net/ethernet/marvell/mvneta.c | 61 --- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..aebbc53 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -431,6 +431,7 @@ struct mvneta_port { /* Flags for special SoC configurations */ bool neta_armada3700; u16 rx_offset_correction; + const struct mbus_dram_target_info *dram_target_info; }; /* The mvneta_tx_desc and mvneta_rx_desc structures describe the @@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) /* Device initialization routine */ static int mvneta_probe(struct platform_device *pdev) { - const struct mbus_dram_target_info *dram_target_info; struct resource *res; struct device_node *dn = pdev->dev.of_node; struct device_node *phy_node; @@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev) pp->tx_csum_limit = tx_csum_limit; - dram_target_info = mv_mbus_dram_info(); + pp->dram_target_info = mv_mbus_dram_info(); /* Armada3700 requires setting default configuration of Mbus * windows, however without using filled mbus_dram_target_info * structure. */ - if (dram_target_info || pp->neta_armada3700) - mvneta_conf_mbus_windows(pp, dram_target_info); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); pp->tx_ring_size = MVNETA_MAX_TXD; pp->rx_ring_size = MVNETA_MAX_RXD; @@ -4405,6 +4405,58 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + if (!IS_ERR(pp->clk_bus)) + clk_prepare_enable(pp->clk_bus); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); + if (pp->bm_priv) { + err = mvneta_bm_port_init(pdev, pp); + if (err < 0) { + dev_info(>dev, "use SW buffer management\n"); + pp->bm_priv = NULL; + } + } + mvneta_defaults_set(pp); + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(mvneta_pm_ops, mvneta_suspend, mvneta_resume); + static const struct of_device_id mvneta_match[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -4419,6 +4471,7 @@ static int mvneta_remove(struct platform_device *pdev) .driver = { .name = MVNETA_DRIVER_NAME, .of_match_table = mvneta_match, + .pm = _pm_ops, }, }; -- 1.9.1
Re: [PATCH v2] net: mvneta: support suspend and resume
On 03/16/2017 11:37 AM, Jisheng Zhang wrote: On Thu, 16 Mar 2017 11:19:10 +0800 Jane Li wrote: Add basic support for handling suspend and resume. Signed-off-by: Jane Li <j...@marvell.com> --- Since v1: - add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume() drivers/net/ethernet/marvell/mvneta.c | 62 --- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..250017b 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -431,6 +431,7 @@ struct mvneta_port { /* Flags for special SoC configurations */ bool neta_armada3700; u16 rx_offset_correction; + const struct mbus_dram_target_info *dram_target_info; }; /* The mvneta_tx_desc and mvneta_rx_desc structures describe the @@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) /* Device initialization routine */ static int mvneta_probe(struct platform_device *pdev) { - const struct mbus_dram_target_info *dram_target_info; struct resource *res; struct device_node *dn = pdev->dev.of_node; struct device_node *phy_node; @@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev) pp->tx_csum_limit = tx_csum_limit; - dram_target_info = mv_mbus_dram_info(); + pp->dram_target_info = mv_mbus_dram_info(); /* Armada3700 requires setting default configuration of Mbus * windows, however without using filled mbus_dram_target_info * structure. */ - if (dram_target_info || pp->neta_armada3700) - mvneta_conf_mbus_windows(pp, dram_target_info); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); pp->tx_ring_size = MVNETA_MAX_TXD; pp->rx_ring_size = MVNETA_MAX_RXD; @@ -4405,6 +4405,59 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + clk_prepare_enable(pp->clk_bus); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); + if (pp->bm_priv) { + err = mvneta_bm_port_init(pdev, pp); + if (err < 0) { + dev_info(>dev, "use SW buffer management\n"); + pp->bm_priv = NULL; + } + } + mvneta_defaults_set(pp); + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static const struct dev_pm_ops mvneta_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(mvneta_suspend, mvneta_resume) +}; we could make use of SIMPLE_DEV_PM_OPS to simplify the code Thanks Done. Modify this in patch v3. Thanks, Jane
Re: [PATCH v2] net: mvneta: support suspend and resume
On 03/16/2017 11:37 AM, Jisheng Zhang wrote: On Thu, 16 Mar 2017 11:19:10 +0800 Jane Li wrote: Add basic support for handling suspend and resume. Signed-off-by: Jane Li --- Since v1: - add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume() drivers/net/ethernet/marvell/mvneta.c | 62 --- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..250017b 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -431,6 +431,7 @@ struct mvneta_port { /* Flags for special SoC configurations */ bool neta_armada3700; u16 rx_offset_correction; + const struct mbus_dram_target_info *dram_target_info; }; /* The mvneta_tx_desc and mvneta_rx_desc structures describe the @@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) /* Device initialization routine */ static int mvneta_probe(struct platform_device *pdev) { - const struct mbus_dram_target_info *dram_target_info; struct resource *res; struct device_node *dn = pdev->dev.of_node; struct device_node *phy_node; @@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev) pp->tx_csum_limit = tx_csum_limit; - dram_target_info = mv_mbus_dram_info(); + pp->dram_target_info = mv_mbus_dram_info(); /* Armada3700 requires setting default configuration of Mbus * windows, however without using filled mbus_dram_target_info * structure. */ - if (dram_target_info || pp->neta_armada3700) - mvneta_conf_mbus_windows(pp, dram_target_info); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); pp->tx_ring_size = MVNETA_MAX_TXD; pp->rx_ring_size = MVNETA_MAX_RXD; @@ -4405,6 +4405,59 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + clk_prepare_enable(pp->clk_bus); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); + if (pp->bm_priv) { + err = mvneta_bm_port_init(pdev, pp); + if (err < 0) { + dev_info(>dev, "use SW buffer management\n"); + pp->bm_priv = NULL; + } + } + mvneta_defaults_set(pp); + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static const struct dev_pm_ops mvneta_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(mvneta_suspend, mvneta_resume) +}; we could make use of SIMPLE_DEV_PM_OPS to simplify the code Thanks Done. Modify this in patch v3. Thanks, Jane
[PATCH v3] net: mvneta: support suspend and resume
Add basic support for handling suspend and resume. Signed-off-by: Jane Li <j...@marvell.com> --- Since v2: - use SIMPLE_DEV_PM_OPS instead of SET_LATE_SYSTEM_SLEEP_PM_OPS Since v1: - add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume() drivers/net/ethernet/marvell/mvneta.c | 60 --- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..b0fea26 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -431,6 +431,7 @@ struct mvneta_port { /* Flags for special SoC configurations */ bool neta_armada3700; u16 rx_offset_correction; + const struct mbus_dram_target_info *dram_target_info; }; /* The mvneta_tx_desc and mvneta_rx_desc structures describe the @@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) /* Device initialization routine */ static int mvneta_probe(struct platform_device *pdev) { - const struct mbus_dram_target_info *dram_target_info; struct resource *res; struct device_node *dn = pdev->dev.of_node; struct device_node *phy_node; @@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev) pp->tx_csum_limit = tx_csum_limit; - dram_target_info = mv_mbus_dram_info(); + pp->dram_target_info = mv_mbus_dram_info(); /* Armada3700 requires setting default configuration of Mbus * windows, however without using filled mbus_dram_target_info * structure. */ - if (dram_target_info || pp->neta_armada3700) - mvneta_conf_mbus_windows(pp, dram_target_info); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); pp->tx_ring_size = MVNETA_MAX_TXD; pp->rx_ring_size = MVNETA_MAX_RXD; @@ -4405,6 +4405,57 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + clk_prepare_enable(pp->clk_bus); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); + if (pp->bm_priv) { + err = mvneta_bm_port_init(pdev, pp); + if (err < 0) { + dev_info(>dev, "use SW buffer management\n"); + pp->bm_priv = NULL; + } + } + mvneta_defaults_set(pp); + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(mvneta_pm_ops, mvneta_suspend, mvneta_resume); + static const struct of_device_id mvneta_match[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -4419,6 +4470,7 @@ static int mvneta_remove(struct platform_device *pdev) .driver = { .name = MVNETA_DRIVER_NAME, .of_match_table = mvneta_match, + .pm = _pm_ops, }, }; -- 1.9.1
[PATCH v3] net: mvneta: support suspend and resume
Add basic support for handling suspend and resume. Signed-off-by: Jane Li --- Since v2: - use SIMPLE_DEV_PM_OPS instead of SET_LATE_SYSTEM_SLEEP_PM_OPS Since v1: - add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume() drivers/net/ethernet/marvell/mvneta.c | 60 --- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..b0fea26 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -431,6 +431,7 @@ struct mvneta_port { /* Flags for special SoC configurations */ bool neta_armada3700; u16 rx_offset_correction; + const struct mbus_dram_target_info *dram_target_info; }; /* The mvneta_tx_desc and mvneta_rx_desc structures describe the @@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) /* Device initialization routine */ static int mvneta_probe(struct platform_device *pdev) { - const struct mbus_dram_target_info *dram_target_info; struct resource *res; struct device_node *dn = pdev->dev.of_node; struct device_node *phy_node; @@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev) pp->tx_csum_limit = tx_csum_limit; - dram_target_info = mv_mbus_dram_info(); + pp->dram_target_info = mv_mbus_dram_info(); /* Armada3700 requires setting default configuration of Mbus * windows, however without using filled mbus_dram_target_info * structure. */ - if (dram_target_info || pp->neta_armada3700) - mvneta_conf_mbus_windows(pp, dram_target_info); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); pp->tx_ring_size = MVNETA_MAX_TXD; pp->rx_ring_size = MVNETA_MAX_RXD; @@ -4405,6 +4405,57 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + clk_prepare_enable(pp->clk_bus); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); + if (pp->bm_priv) { + err = mvneta_bm_port_init(pdev, pp); + if (err < 0) { + dev_info(>dev, "use SW buffer management\n"); + pp->bm_priv = NULL; + } + } + mvneta_defaults_set(pp); + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(mvneta_pm_ops, mvneta_suspend, mvneta_resume); + static const struct of_device_id mvneta_match[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -4419,6 +4470,7 @@ static int mvneta_remove(struct platform_device *pdev) .driver = { .name = MVNETA_DRIVER_NAME, .of_match_table = mvneta_match, + .pm = _pm_ops, }, }; -- 1.9.1
[PATCH v2] net: mvneta: support suspend and resume
Add basic support for handling suspend and resume. Signed-off-by: Jane Li <j...@marvell.com> --- Since v1: - add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume() drivers/net/ethernet/marvell/mvneta.c | 62 --- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..250017b 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -431,6 +431,7 @@ struct mvneta_port { /* Flags for special SoC configurations */ bool neta_armada3700; u16 rx_offset_correction; + const struct mbus_dram_target_info *dram_target_info; }; /* The mvneta_tx_desc and mvneta_rx_desc structures describe the @@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) /* Device initialization routine */ static int mvneta_probe(struct platform_device *pdev) { - const struct mbus_dram_target_info *dram_target_info; struct resource *res; struct device_node *dn = pdev->dev.of_node; struct device_node *phy_node; @@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev) pp->tx_csum_limit = tx_csum_limit; - dram_target_info = mv_mbus_dram_info(); + pp->dram_target_info = mv_mbus_dram_info(); /* Armada3700 requires setting default configuration of Mbus * windows, however without using filled mbus_dram_target_info * structure. */ - if (dram_target_info || pp->neta_armada3700) - mvneta_conf_mbus_windows(pp, dram_target_info); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); pp->tx_ring_size = MVNETA_MAX_TXD; pp->rx_ring_size = MVNETA_MAX_RXD; @@ -4405,6 +4405,59 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + clk_prepare_enable(pp->clk_bus); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); + if (pp->bm_priv) { + err = mvneta_bm_port_init(pdev, pp); + if (err < 0) { + dev_info(>dev, "use SW buffer management\n"); + pp->bm_priv = NULL; + } + } + mvneta_defaults_set(pp); + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static const struct dev_pm_ops mvneta_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(mvneta_suspend, mvneta_resume) +}; + static const struct of_device_id mvneta_match[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -4419,6 +4472,7 @@ static int mvneta_remove(struct platform_device *pdev) .driver = { .name = MVNETA_DRIVER_NAME, .of_match_table = mvneta_match, + .pm = _pm_ops, }, }; -- 1.9.1
[PATCH v2] net: mvneta: support suspend and resume
Add basic support for handling suspend and resume. Signed-off-by: Jane Li --- Since v1: - add mvneta_conf_mbus_windows() and mvneta_bm_port_init() in mvneta_resume() drivers/net/ethernet/marvell/mvneta.c | 62 --- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..250017b 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -431,6 +431,7 @@ struct mvneta_port { /* Flags for special SoC configurations */ bool neta_armada3700; u16 rx_offset_correction; + const struct mbus_dram_target_info *dram_target_info; }; /* The mvneta_tx_desc and mvneta_rx_desc structures describe the @@ -4118,7 +4119,6 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) /* Device initialization routine */ static int mvneta_probe(struct platform_device *pdev) { - const struct mbus_dram_target_info *dram_target_info; struct resource *res; struct device_node *dn = pdev->dev.of_node; struct device_node *phy_node; @@ -4267,13 +4267,13 @@ static int mvneta_probe(struct platform_device *pdev) pp->tx_csum_limit = tx_csum_limit; - dram_target_info = mv_mbus_dram_info(); + pp->dram_target_info = mv_mbus_dram_info(); /* Armada3700 requires setting default configuration of Mbus * windows, however without using filled mbus_dram_target_info * structure. */ - if (dram_target_info || pp->neta_armada3700) - mvneta_conf_mbus_windows(pp, dram_target_info); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); pp->tx_ring_size = MVNETA_MAX_TXD; pp->rx_ring_size = MVNETA_MAX_RXD; @@ -4405,6 +4405,59 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + clk_prepare_enable(pp->clk_bus); + if (pp->dram_target_info || pp->neta_armada3700) + mvneta_conf_mbus_windows(pp, pp->dram_target_info); + if (pp->bm_priv) { + err = mvneta_bm_port_init(pdev, pp); + if (err < 0) { + dev_info(>dev, "use SW buffer management\n"); + pp->bm_priv = NULL; + } + } + mvneta_defaults_set(pp); + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static const struct dev_pm_ops mvneta_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(mvneta_suspend, mvneta_resume) +}; + static const struct of_device_id mvneta_match[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -4419,6 +4472,7 @@ static int mvneta_remove(struct platform_device *pdev) .driver = { .name = MVNETA_DRIVER_NAME, .of_match_table = mvneta_match, + .pm = _pm_ops, }, }; -- 1.9.1
Re: [PATCH] net: mvneta: support suspend and resume
Hi Jisheng, On 2017年03月15日 15:18, Jisheng Zhang wrote: Hi Jane, On Wed, 15 Mar 2017 15:08:34 +0800 Jane Li wrote: Add basic support for handling suspend and resume. Signed-off-by: Jane Li <j...@marvell.com> --- drivers/net/ethernet/marvell/mvneta.c | 44 +++ 1 file changed, 44 insertions(+) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..4f16342 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -4405,6 +4405,49 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + clk_prepare_enable(pp->clk_bus); we may miss the necessary registers setting in mvneta_bm_port_init() and mvneta_conf_mbus_windows(). those registers also need to be restored. Done. Add them in patch v2. + mvneta_defaults_set(pp); before restore the default setting, is it safer to mvneta_port_disable()? Thanks, Jisheng During suspend, mvneta_port_disable() has been executed as bellow path. It seems it is not need to do mvneta_port_disable() during resume. mvneta_suspend() -> mvneta_stop() -> mvneta_stop_dev() -> mvneta_port_disable() Thanks, Jane + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static const struct dev_pm_ops mvneta_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(mvneta_suspend, mvneta_resume) +}; + static const struct of_device_id mvneta_match[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -4419,6 +4462,7 @@ static int mvneta_remove(struct platform_device *pdev) .driver = { .name = MVNETA_DRIVER_NAME, .of_match_table = mvneta_match, + .pm = _pm_ops, }, };
Re: [PATCH] net: mvneta: support suspend and resume
Hi Jisheng, On 2017年03月15日 15:18, Jisheng Zhang wrote: Hi Jane, On Wed, 15 Mar 2017 15:08:34 +0800 Jane Li wrote: Add basic support for handling suspend and resume. Signed-off-by: Jane Li --- drivers/net/ethernet/marvell/mvneta.c | 44 +++ 1 file changed, 44 insertions(+) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..4f16342 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -4405,6 +4405,49 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + clk_prepare_enable(pp->clk_bus); we may miss the necessary registers setting in mvneta_bm_port_init() and mvneta_conf_mbus_windows(). those registers also need to be restored. Done. Add them in patch v2. + mvneta_defaults_set(pp); before restore the default setting, is it safer to mvneta_port_disable()? Thanks, Jisheng During suspend, mvneta_port_disable() has been executed as bellow path. It seems it is not need to do mvneta_port_disable() during resume. mvneta_suspend() -> mvneta_stop() -> mvneta_stop_dev() -> mvneta_port_disable() Thanks, Jane + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static const struct dev_pm_ops mvneta_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(mvneta_suspend, mvneta_resume) +}; + static const struct of_device_id mvneta_match[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -4419,6 +4462,7 @@ static int mvneta_remove(struct platform_device *pdev) .driver = { .name = MVNETA_DRIVER_NAME, .of_match_table = mvneta_match, + .pm = _pm_ops, }, };
[PATCH] net: mvneta: support suspend and resume
Add basic support for handling suspend and resume. Signed-off-by: Jane Li <j...@marvell.com> --- drivers/net/ethernet/marvell/mvneta.c | 44 +++ 1 file changed, 44 insertions(+) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..4f16342 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -4405,6 +4405,49 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + clk_prepare_enable(pp->clk_bus); + mvneta_defaults_set(pp); + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static const struct dev_pm_ops mvneta_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(mvneta_suspend, mvneta_resume) +}; + static const struct of_device_id mvneta_match[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -4419,6 +4462,7 @@ static int mvneta_remove(struct platform_device *pdev) .driver = { .name = MVNETA_DRIVER_NAME, .of_match_table = mvneta_match, + .pm = _pm_ops, }, }; -- 1.9.1
[PATCH] net: mvneta: support suspend and resume
Add basic support for handling suspend and resume. Signed-off-by: Jane Li --- drivers/net/ethernet/marvell/mvneta.c | 44 +++ 1 file changed, 44 insertions(+) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 61dd446..4f16342 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -4405,6 +4405,49 @@ static int mvneta_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int mvneta_suspend(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + + if (netif_running(dev)) + mvneta_stop(dev); + netif_device_detach(dev); + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); + return 0; +} + +static int mvneta_resume(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct mvneta_port *pp = netdev_priv(dev); + int err; + + clk_prepare_enable(pp->clk); + clk_prepare_enable(pp->clk_bus); + mvneta_defaults_set(pp); + err = mvneta_port_power_up(pp, pp->phy_interface); + if (err < 0) { + dev_err(device, "can't power up port\n"); + return err; + } + + if (pp->use_inband_status) + mvneta_fixed_link_update(pp, dev->phydev); + + netif_device_attach(dev); + if (netif_running(dev)) + mvneta_open(dev); + return 0; +} +#endif + +static const struct dev_pm_ops mvneta_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(mvneta_suspend, mvneta_resume) +}; + static const struct of_device_id mvneta_match[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -4419,6 +4462,7 @@ static int mvneta_remove(struct platform_device *pdev) .driver = { .name = MVNETA_DRIVER_NAME, .of_match_table = mvneta_match, + .pm = _pm_ops, }, }; -- 1.9.1
Re: [PATCH] printk: fix one circular lockdep warning about console_lock
On 03/19/2014 06:00 PM, Jan Kara wrote: > On Wed 19-03-14 11:08:08, Jane Li wrote: >> On 02/12/2014 05:19 AM, Andrew Morton wrote: >>> On Tue, 11 Feb 2014 14:50:00 +0800 wrote: > Umm, I disagree with the patch. What I proposed in my answer to your patch > is something like the patch below. Does it fix your problem? > > Honza > > From 91497a88c403a7f22e78fee2f69d7413c6e8209f Mon Sep 17 00:00:00 2001 > From: Jan Kara > Date: Wed, 19 Mar 2014 10:56:12 +0100 > Subject: [PATCH] printk: Fixup lockdep annotation in console_suspend() > > Although console_suspend() releases console_sem, it doesn't tell lockdep > about it. That results in the lockdep warning about circular locking when > doing the following: > enter suspend -> resume -> plug-out CPUx (echo 0 > cpux/online) > > Fix the problem by telling lockdep we actually released the semaphore in > console_suspend() and acquired it again in console_resume(). > > Signed-off-by: Jan Kara > --- > kernel/printk/printk.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index > 4dae9cbe9259..e6ada322782b 100644 > --- a/kernel/printk/printk.c > +++ b/kernel/printk/printk.c > @@ -1880,6 +1880,7 @@ void suspend_console(void) > console_lock(); > console_suspended = 1; > up(_sem); > + mutex_release(_lock_dep_map, 1, _RET_IP_); > } > > void resume_console(void) > @@ -1887,6 +1888,7 @@ void resume_console(void) > if (!console_suspend_enabled) > return; > down(_sem); > + mutex_acquire(_lock_dep_map, 0, 0, _RET_IP_); > console_suspended = 0; > console_unlock(); > } > -- > 1.8.1.4 Oh, yes, this new solution works well. If run same test, no circular lockdep warning occurs now. I will update patch v2. Sorry for misunderstanding your answer before. Thanks! Best Regards, Jane -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] printk: fix one circular lockdep warning about console_lock
On 03/19/2014 06:00 PM, Jan Kara wrote: On Wed 19-03-14 11:08:08, Jane Li wrote: On 02/12/2014 05:19 AM, Andrew Morton wrote: On Tue, 11 Feb 2014 14:50:00 +0800j...@marvell.com wrote: Umm, I disagree with the patch. What I proposed in my answer to your patch is something like the patch below. Does it fix your problem? Honza From 91497a88c403a7f22e78fee2f69d7413c6e8209f Mon Sep 17 00:00:00 2001 From: Jan Kara j...@suse.cz Date: Wed, 19 Mar 2014 10:56:12 +0100 Subject: [PATCH] printk: Fixup lockdep annotation in console_suspend() Although console_suspend() releases console_sem, it doesn't tell lockdep about it. That results in the lockdep warning about circular locking when doing the following: enter suspend - resume - plug-out CPUx (echo 0 cpux/online) Fix the problem by telling lockdep we actually released the semaphore in console_suspend() and acquired it again in console_resume(). Signed-off-by: Jan Kara j...@suse.cz --- kernel/printk/printk.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 4dae9cbe9259..e6ada322782b 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1880,6 +1880,7 @@ void suspend_console(void) console_lock(); console_suspended = 1; up(console_sem); + mutex_release(console_lock_dep_map, 1, _RET_IP_); } void resume_console(void) @@ -1887,6 +1888,7 @@ void resume_console(void) if (!console_suspend_enabled) return; down(console_sem); + mutex_acquire(console_lock_dep_map, 0, 0, _RET_IP_); console_suspended = 0; console_unlock(); } -- 1.8.1.4 Oh, yes, this new solution works well. If run same test, no circular lockdep warning occurs now. I will update patch v2. Sorry for misunderstanding your answer before. Thanks! Best Regards, Jane -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] printk: fix one circular lockdep warning about console_lock
On 02/12/2014 05:19 AM, Andrew Morton wrote: On Tue, 11 Feb 2014 14:50:00 +0800 wrote: From: Jane Li This patch tries to fix a warning about possible circular locking dependency. If do in following sequence: enter suspend -> resume -> plug-out CPUx (echo 0 > cpux/online) lockdep will show warning as following: == [ INFO: possible circular locking dependency detected ] 3.10.0 #2 Tainted: G O --- sh/1271 is trying to acquire lock: (console_lock){+.+.+.}, at: [] console_cpu_notify+0x20/0x2c but task is already holding lock: (cpu_hotplug.lock){+.+.+.}, at: [] cpu_hotplug_begin+0x2c/0x58 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 (cpu_hotplug.lock){+.+.+.}: [] lock_acquire+0x98/0x12c [] mutex_lock_nested+0x50/0x3d8 [] cpu_hotplug_begin+0x2c/0x58 [] _cpu_up+0x24/0x154 [] cpu_up+0x64/0x84 [] smp_init+0x9c/0xd4 [] kernel_init_freeable+0x78/0x1c8 [] kernel_init+0x8/0xe4 [] ret_from_fork+0x14/0x2c -> #1 (cpu_add_remove_lock){+.+.+.}: [] lock_acquire+0x98/0x12c [] mutex_lock_nested+0x50/0x3d8 [] disable_nonboot_cpus+0x8/0xe8 [] suspend_devices_and_enter+0x214/0x448 [] pm_suspend+0x1e4/0x284 [] try_to_suspend+0xa4/0xbc [] process_one_work+0x1c4/0x4fc [] worker_thread+0x138/0x37c [] kthread+0xa4/0xb0 [] ret_from_fork+0x14/0x2c -> #0 (console_lock){+.+.+.}: [] __lock_acquire+0x1b38/0x1b80 [] lock_acquire+0x98/0x12c [] console_lock+0x54/0x68 [] console_cpu_notify+0x20/0x2c [] notifier_call_chain+0x44/0x84 [] __cpu_notify+0x2c/0x48 [] cpu_notify_nofail+0x8/0x14 [] _cpu_down+0xf4/0x258 [] cpu_down+0x24/0x40 [] store_online+0x30/0x74 [] dev_attr_store+0x18/0x24 [] sysfs_write_file+0x16c/0x19c [] vfs_write+0xb4/0x190 [] SyS_write+0x3c/0x70 [] ret_fast_syscall+0x0/0x48 Chain exists of: console_lock --> cpu_add_remove_lock --> cpu_hotplug.lock Possible unsafe locking scenario: CPU0CPU1 lock(cpu_hotplug.lock); lock(cpu_add_remove_lock); lock(cpu_hotplug.lock); lock(console_lock); *** DEADLOCK *** These traces hurt my brain. There are three locks involved in two sequence: a) pm suspend: console_lock (@suspend_console()) cpu_add_remove_lock (@disable_nonboot_cpus()) cpu_hotplug.lock (@_cpu_down()) But but but. suspend_console() releases console_sem again. So the sequence is actually down(_sem) (@suspend_console()) up(_sem) (@suspend_console()) cpu_add_remove_lock (@disable_nonboot_cpus()) cpu_hotplug.lock (@_cpu_down()) So console_sem *doesn't* nest outside cpu_add_remove_lock and cpu_hotplug.lock. Jan Kara and Jane have answered this question in other emails. b) Plug-out CPUx: cpu_add_remove_lock (@(cpu_down()) cpu_hotplug.lock (@_cpu_down()) console_lock (@console_cpu_notify()) => Lockdeps prints warning log. There should be not real deadlock, as flag of console_suspended can protect this. console_lock() does down(_sem) *before* testing console_suspended, so I don't understand this sentence - a more detailed description would help. Jane has answered this question in another email. Printk registers cpu hotplug notify function. When CPUx is plug-out/in, always execute console_lock() and console_unlock(). This patch modifies that with console_trylock() and console_unlock(). Then use that instead of the unconditional console_lock/unlock pair to avoid the warning. ... --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1893,6 +1893,20 @@ void resume_console(void) } /** + * console_flush - flush dmesg if console isn't suspended + * + * console_unlock always flushes the dmesg buffer, so just try to + * grab the console lock. If that fails we know that the current + * holder will eventually drop the console lock and so flush the dmesg + * buffers at the earliest possible time. + */ The comment should describe why we added this code, please: talk about cpu_hotplug.lock and console_lock. Daniel has answered this question in another email. +void console_flush(void) +{ + if (console_trylock()) + console_unlock(); +} + +/** * console_cpu_notify - print deferred console messages after CPU hotplug * @self: notifier struct * @action: CPU hotplug event @@ -1911,8 +1925,7 @@ static int console_cpu_notify(struct notifier_block *self, case CPU_DEAD: case CPU_DOWN_FAILED: case CPU_UP_CANCELED: - console_lock(); - console_unlock(); + console_flush(); } return NOTIFY_OK; Well, this is a bit hacky and makes the already-far-too-complex code even more complex. If it is indeed the case that the deadlock cannot really occur then let's try to find a way of suppressing
Re: [PATCH] printk: fix one circular lockdep warning about console_lock
On 02/12/2014 05:19 AM, Andrew Morton wrote: On Tue, 11 Feb 2014 14:50:00 +0800j...@marvell.com wrote: From: Jane Lij...@marvell.com This patch tries to fix a warning about possible circular locking dependency. If do in following sequence: enter suspend - resume - plug-out CPUx (echo 0 cpux/online) lockdep will show warning as following: == [ INFO: possible circular locking dependency detected ] 3.10.0 #2 Tainted: G O --- sh/1271 is trying to acquire lock: (console_lock){+.+.+.}, at: [c06ebf7c] console_cpu_notify+0x20/0x2c but task is already holding lock: (cpu_hotplug.lock){+.+.+.}, at: [c012b4e8] cpu_hotplug_begin+0x2c/0x58 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: - #2 (cpu_hotplug.lock){+.+.+.}: [c017bb7c] lock_acquire+0x98/0x12c [c06f5014] mutex_lock_nested+0x50/0x3d8 [c012b4e8] cpu_hotplug_begin+0x2c/0x58 [c06ebfac] _cpu_up+0x24/0x154 [c06ec140] cpu_up+0x64/0x84 [c0981834] smp_init+0x9c/0xd4 [c0973880] kernel_init_freeable+0x78/0x1c8 [c06e7f40] kernel_init+0x8/0xe4 [c010eec8] ret_from_fork+0x14/0x2c - #1 (cpu_add_remove_lock){+.+.+.}: [c017bb7c] lock_acquire+0x98/0x12c [c06f5014] mutex_lock_nested+0x50/0x3d8 [c012b758] disable_nonboot_cpus+0x8/0xe8 [c016b83c] suspend_devices_and_enter+0x214/0x448 [c016bc54] pm_suspend+0x1e4/0x284 [c016bdcc] try_to_suspend+0xa4/0xbc [c0143848] process_one_work+0x1c4/0x4fc [c0143f80] worker_thread+0x138/0x37c [c014aaf8] kthread+0xa4/0xb0 [c010eec8] ret_from_fork+0x14/0x2c - #0 (console_lock){+.+.+.}: [c017b5d0] __lock_acquire+0x1b38/0x1b80 [c017bb7c] lock_acquire+0x98/0x12c [c01288c4] console_lock+0x54/0x68 [c06ebf7c] console_cpu_notify+0x20/0x2c [c01501d4] notifier_call_chain+0x44/0x84 [c012b448] __cpu_notify+0x2c/0x48 [c012b5b0] cpu_notify_nofail+0x8/0x14 [c06e81bc] _cpu_down+0xf4/0x258 [c06e8344] cpu_down+0x24/0x40 [c06e921c] store_online+0x30/0x74 [c03b7298] dev_attr_store+0x18/0x24 [c025fc5c] sysfs_write_file+0x16c/0x19c [c0207a98] vfs_write+0xb4/0x190 [c0207e58] SyS_write+0x3c/0x70 [c010ee00] ret_fast_syscall+0x0/0x48 Chain exists of: console_lock -- cpu_add_remove_lock -- cpu_hotplug.lock Possible unsafe locking scenario: CPU0CPU1 lock(cpu_hotplug.lock); lock(cpu_add_remove_lock); lock(cpu_hotplug.lock); lock(console_lock); *** DEADLOCK *** These traces hurt my brain. There are three locks involved in two sequence: a) pm suspend: console_lock (@suspend_console()) cpu_add_remove_lock (@disable_nonboot_cpus()) cpu_hotplug.lock (@_cpu_down()) But but but. suspend_console() releases console_sem again. So the sequence is actually down(console_sem) (@suspend_console()) up(console_sem) (@suspend_console()) cpu_add_remove_lock (@disable_nonboot_cpus()) cpu_hotplug.lock (@_cpu_down()) So console_sem *doesn't* nest outside cpu_add_remove_lock and cpu_hotplug.lock. Jan Kara and Jane have answered this question in other emails. b) Plug-out CPUx: cpu_add_remove_lock (@(cpu_down()) cpu_hotplug.lock (@_cpu_down()) console_lock (@console_cpu_notify()) = Lockdeps prints warning log. There should be not real deadlock, as flag of console_suspended can protect this. console_lock() does down(console_sem) *before* testing console_suspended, so I don't understand this sentence - a more detailed description would help. Jane has answered this question in another email. Printk registers cpu hotplug notify function. When CPUx is plug-out/in, always execute console_lock() and console_unlock(). This patch modifies that with console_trylock() and console_unlock(). Then use that instead of the unconditional console_lock/unlock pair to avoid the warning. ... --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1893,6 +1893,20 @@ void resume_console(void) } /** + * console_flush - flush dmesg if console isn't suspended + * + * console_unlock always flushes the dmesg buffer, so just try to + * grabdrop the console lock. If that fails we know that the current + * holder will eventually drop the console lock and so flush the dmesg + * buffers at the earliest possible time. + */ The comment should describe why we added this code, please: talk about cpu_hotplug.lock and console_lock. Daniel has answered this question in another email. +void console_flush(void) +{ + if (console_trylock()) + console_unlock(); +} + +/** * console_cpu_notify - print deferred console messages after CPU hotplug * @self: notifier struct * @action: CPU hotplug event @@ -1911,8 +1925,7 @@ static int console_cpu_notify(struct notifier_block *self, case CPU_DEAD: case CPU_DOWN_FAILED: case CPU_UP_CANCELED: -
Re: [PATCH] printk: fix one circular lockdep warning about console_lock
On 02/12/2014 05:19 AM, Andrew Morton wrote: There are three locks involved in two sequence: a) pm suspend: console_lock (@suspend_console()) cpu_add_remove_lock (@disable_nonboot_cpus()) cpu_hotplug.lock (@_cpu_down()) But but but. suspend_console() releases console_sem again. Console_lock does not refer to console_sem but console_lock_dep_map. Its name is console_lock. Suspend_console() does not release console_lock_dep_map. So the sequence is actually down(_sem) (@suspend_console()) acquire(_lock_dep_map) (_console()) up(_sem) (@suspend_console()) cpu_add_remove_lock (@disable_nonboot_cpus()) cpu_hotplug.lock (@_cpu_down()) So console_sem *doesn't* nest outside cpu_add_remove_lock and cpu_hotplug.lock. Add console_lock in the sequence. b) Plug-out CPUx: cpu_add_remove_lock (@(cpu_down()) cpu_hotplug.lock (@_cpu_down()) console_lock (@console_cpu_notify()) => Lockdeps prints warning log. There should be not real deadlock, as flag of console_suspended can protect this. console_lock() does down(_sem) *before* testing console_suspended, so I don't understand this sentence - a more detailed description would help. After suspend_console(), console_sem is unlocked, but console_lock_dep_map has been acquired. Best Regards, Jane -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] printk: fix one circular lockdep warning about console_lock
On 02/12/2014 05:19 AM, Andrew Morton wrote: There are three locks involved in two sequence: a) pm suspend: console_lock (@suspend_console()) cpu_add_remove_lock (@disable_nonboot_cpus()) cpu_hotplug.lock (@_cpu_down()) But but but. suspend_console() releases console_sem again. Console_lock does not refer to console_sem but console_lock_dep_map. Its name is console_lock. Suspend_console() does not release console_lock_dep_map. So the sequence is actually down(console_sem) (@suspend_console()) acquire(console_lock_dep_map) (suspend_console()) up(console_sem) (@suspend_console()) cpu_add_remove_lock (@disable_nonboot_cpus()) cpu_hotplug.lock (@_cpu_down()) So console_sem *doesn't* nest outside cpu_add_remove_lock and cpu_hotplug.lock. Add console_lock in the sequence. b) Plug-out CPUx: cpu_add_remove_lock (@(cpu_down()) cpu_hotplug.lock (@_cpu_down()) console_lock (@console_cpu_notify()) = Lockdeps prints warning log. There should be not real deadlock, as flag of console_suspended can protect this. console_lock() does down(console_sem) *before* testing console_suspended, so I don't understand this sentence - a more detailed description would help. After suspend_console(), console_sem is unlocked, but console_lock_dep_map has been acquired. Best Regards, Jane -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: Question about console_lock lockdep after involving console_lock_dep_map
On 02/09/2014 11:45 PM, Daniel Vetter wrote: Adding many more people and lkml to the cc list. Please don't poke people in private, but always cc a relevant mailing list. On Sat, Feb 8, 2014 at 6:24 AM, Jane Li wrote: Hi Danial Vetter, I found you had added console_lock_dep_map in commit daee7797 (console: implement lockdep support for console_lock). I encounter another circular lock warning related to it. Sequence: enter suspend -> resume -> plug-out CPUx (echo 0 > cpux/online) Then, lockdep will show warning as following: == [ INFO: possible circular locking dependency detected ] 3.10.0 #2 Tainted: G O --- sh/1271 is trying to acquire lock: (console_lock){+.+.+.}, at: [] console_cpu_notify+0x20/0x2c but task is already holding lock: (cpu_hotplug.lock){+.+.+.}, at: [] cpu_hotplug_begin+0x2c/0x58 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 (cpu_hotplug.lock){+.+.+.}: [] lock_acquire+0x98/0x12c [] mutex_lock_nested+0x50/0x3d8 [] cpu_hotplug_begin+0x2c/0x58 [] _cpu_up+0x24/0x154 [] cpu_up+0x64/0x84 [] smp_init+0x9c/0xd4 [] kernel_init_freeable+0x78/0x1c8 [] kernel_init+0x8/0xe4 [] ret_from_fork+0x14/0x2c -> #1 (cpu_add_remove_lock){+.+.+.}: [] lock_acquire+0x98/0x12c [] mutex_lock_nested+0x50/0x3d8 [] disable_nonboot_cpus+0x8/0xe8 [] suspend_devices_and_enter+0x214/0x448 [] pm_suspend+0x1e4/0x284 [] try_to_suspend+0xa4/0xbc [] process_one_work+0x1c4/0x4fc [] worker_thread+0x138/0x37c [] kthread+0xa4/0xb0 [] ret_from_fork+0x14/0x2c -> #0 (console_lock){+.+.+.}: [] __lock_acquire+0x1b38/0x1b80 [] lock_acquire+0x98/0x12c [] console_lock+0x54/0x68 [] console_cpu_notify+0x20/0x2c [] notifier_call_chain+0x44/0x84 [] __cpu_notify+0x2c/0x48 [] cpu_notify_nofail+0x8/0x14 [] _cpu_down+0xf4/0x258 [] cpu_down+0x24/0x40 [] store_online+0x30/0x74 [] dev_attr_store+0x18/0x24 [] sysfs_write_file+0x16c/0x19c [] vfs_write+0xb4/0x190 [] SyS_write+0x3c/0x70 [] ret_fastChain exists of: console_lock --> cpu_add_remove_lock --> cpu_hotplug.lock Possible unsafe locking scenario: CPU0CPU1 lock(cpu_hotplug.lock); lock(cpu_add_remove_lock); lock(cpu_hotplug.lock); lock(console_lock); *** DEADLOCK *** Analyze this information, there are three locks involved in two sequence: pm suspend: console_lock (@suspend_console()) -> cpu_add_remove_lock (@disable_nonboot_cpus()) -> cpu_hotplug.lock (@_cpu_down()) Plug-out CPUx: cpu_add_remove_lock (@(cpu_down()) -> cpu_hotplug.lock (@_cpu_down()) -> console_lock (@console_cpu_notify()) => Lockdeps prints warning log. I check code and there should be not real deadlock, as flag of console_suspended can protect this. Do you know how to avoid this warning? I think the right approach here is to add a new function to do the console flushing: /** * console_flush - flush dmesg if console isn't suspended * * console_unlock always flushes the dmesg buffer, so just try to * grab the console lock. If that fails we know that the current * holder will eventually drop the console lock and so flush the dmesg * buffers at the earliest possible time. */ void console_flush(void) { if (console_trylock()) console_unlock(); } Then use that instead of the unconditional console_lock/unlock pair int the console_cpu_notitifier. Since that's practically the patch already feel free to smash a Signed-off-by: Daniel Vetter on top if it works. Cheers, Daniel Do same test as you suggested, there is no warning now. I have updated the patch named "printk: fix one circular lockdep warning about console_lock". Thanks! Best Regards, Jane -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: Question about console_lock lockdep after involving console_lock_dep_map
On 02/09/2014 11:45 PM, Daniel Vetter wrote: Adding many more people and lkml to the cc list. Please don't poke people in private, but always cc a relevant mailing list. On Sat, Feb 8, 2014 at 6:24 AM, Jane Li j...@marvell.com wrote: Hi Danial Vetter, I found you had added console_lock_dep_map in commit daee7797 (console: implement lockdep support for console_lock). I encounter another circular lock warning related to it. Sequence: enter suspend - resume - plug-out CPUx (echo 0 cpux/online) Then, lockdep will show warning as following: == [ INFO: possible circular locking dependency detected ] 3.10.0 #2 Tainted: G O --- sh/1271 is trying to acquire lock: (console_lock){+.+.+.}, at: [c06ebf7c] console_cpu_notify+0x20/0x2c but task is already holding lock: (cpu_hotplug.lock){+.+.+.}, at: [c012b4e8] cpu_hotplug_begin+0x2c/0x58 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: - #2 (cpu_hotplug.lock){+.+.+.}: [c017bb7c] lock_acquire+0x98/0x12c [c06f5014] mutex_lock_nested+0x50/0x3d8 [c012b4e8] cpu_hotplug_begin+0x2c/0x58 [c06ebfac] _cpu_up+0x24/0x154 [c06ec140] cpu_up+0x64/0x84 [c0981834] smp_init+0x9c/0xd4 [c0973880] kernel_init_freeable+0x78/0x1c8 [c06e7f40] kernel_init+0x8/0xe4 [c010eec8] ret_from_fork+0x14/0x2c - #1 (cpu_add_remove_lock){+.+.+.}: [c017bb7c] lock_acquire+0x98/0x12c [c06f5014] mutex_lock_nested+0x50/0x3d8 [c012b758] disable_nonboot_cpus+0x8/0xe8 [c016b83c] suspend_devices_and_enter+0x214/0x448 [c016bc54] pm_suspend+0x1e4/0x284 [c016bdcc] try_to_suspend+0xa4/0xbc [c0143848] process_one_work+0x1c4/0x4fc [c0143f80] worker_thread+0x138/0x37c [c014aaf8] kthread+0xa4/0xb0 [c010eec8] ret_from_fork+0x14/0x2c - #0 (console_lock){+.+.+.}: [c017b5d0] __lock_acquire+0x1b38/0x1b80 [c017bb7c] lock_acquire+0x98/0x12c [c01288c4] console_lock+0x54/0x68 [c06ebf7c] console_cpu_notify+0x20/0x2c [c01501d4] notifier_call_chain+0x44/0x84 [c012b448] __cpu_notify+0x2c/0x48 [c012b5b0] cpu_notify_nofail+0x8/0x14 [c06e81bc] _cpu_down+0xf4/0x258 [c06e8344] cpu_down+0x24/0x40 [c06e921c] store_online+0x30/0x74 [c03b7298] dev_attr_store+0x18/0x24 [c025fc5c] sysfs_write_file+0x16c/0x19c [c0207a98] vfs_write+0xb4/0x190 [c0207e58] SyS_write+0x3c/0x70 [c010ee00] ret_fastChain exists of: console_lock -- cpu_add_remove_lock -- cpu_hotplug.lock Possible unsafe locking scenario: CPU0CPU1 lock(cpu_hotplug.lock); lock(cpu_add_remove_lock); lock(cpu_hotplug.lock); lock(console_lock); *** DEADLOCK *** Analyze this information, there are three locks involved in two sequence: pm suspend: console_lock (@suspend_console()) - cpu_add_remove_lock (@disable_nonboot_cpus()) - cpu_hotplug.lock (@_cpu_down()) Plug-out CPUx: cpu_add_remove_lock (@(cpu_down()) - cpu_hotplug.lock (@_cpu_down()) - console_lock (@console_cpu_notify()) = Lockdeps prints warning log. I check code and there should be not real deadlock, as flag of console_suspended can protect this. Do you know how to avoid this warning? I think the right approach here is to add a new function to do the console flushing: /** * console_flush - flush dmesg if console isn't suspended * * console_unlock always flushes the dmesg buffer, so just try to * grabdrop the console lock. If that fails we know that the current * holder will eventually drop the console lock and so flush the dmesg * buffers at the earliest possible time. */ void console_flush(void) { if (console_trylock()) console_unlock(); } Then use that instead of the unconditional console_lock/unlock pair int the console_cpu_notitifier. Since that's practically the patch already feel free to smash a Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch on top if it works. Cheers, Daniel Do same test as you suggested, there is no warning now. I have updated the patch named printk: fix one circular lockdep warning about console_lock. Thanks! Best Regards, Jane -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3] cpufreq: Fix timer/workqueue corruption by protecting reading governor_enabled
On 01/03/2014 02:50 PM, Viresh Kumar wrote: On 3 January 2014 12:14, wrote: diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index dc196bb..15c62df 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -389,6 +389,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int relation); int cpufreq_register_governor(struct cpufreq_governor *governor); void cpufreq_unregister_governor(struct cpufreq_governor *governor); +extern struct mutex cpufreq_governor_lock; /* CPUFREQ DEFAULT GOVERNOR */ /* Move this to cpufreq_governor.h instead. I don't want this to be available for everybody to use it. OK. Have pushed PATCH v4. Please review again. Thanks! -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3] cpufreq: Fix timer/workqueue corruption by protecting reading governor_enabled
On 01/03/2014 02:50 PM, Viresh Kumar wrote: On 3 January 2014 12:14, j...@marvell.com wrote: diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index dc196bb..15c62df 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -389,6 +389,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int relation); int cpufreq_register_governor(struct cpufreq_governor *governor); void cpufreq_unregister_governor(struct cpufreq_governor *governor); +extern struct mutex cpufreq_governor_lock; /* CPUFREQ DEFAULT GOVERNOR */ /* Move this to cpufreq_governor.h instead. I don't want this to be available for everybody to use it. OK. Have pushed PATCH v4. Please review again. Thanks! -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2] cpufreq: Fix timer/workqueue corruption by protecting reading governor_enabled
On 01/03/2014 07:26 AM, Dmitry Torokhov wrote Unlocking in different branches is not the best practice IMO, I'd recommend doing: mutex_lock(_governor_lock); if (!policy->governor_enabled) goto out_unlock; ... out_unlock: mutex_unlock(_governor_lock); Thanks! OK. I have pushed PATCH v3. Please review again. Besides, I use checkpatch.pl to check this patch, and find there is warning. PATCH v3 also move cpufreq_governor_lock declaration to cpufreq.h. WARNING: externs should be avoided in .c files #106: FILE: drivers/cpufreq/cpufreq_governor.c:25: +extern struct mutex cpufreq_governor_lock; Thanks! -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2] cpufreq: Fix timer/workqueue corruption by protecting reading governor_enabled
On 01/03/2014 07:26 AM, Dmitry Torokhov wrote Unlocking in different branches is not the best practice IMO, I'd recommend doing: mutex_lock(cpufreq_governor_lock); if (!policy-governor_enabled) goto out_unlock; ... out_unlock: mutex_unlock(cpufreq_governor_lock); Thanks! OK. I have pushed PATCH v3. Please review again. Besides, I use checkpatch.pl to check this patch, and find there is warning. PATCH v3 also move cpufreq_governor_lock declaration to cpufreq.h. WARNING: externs should be avoided in .c files #106: FILE: drivers/cpufreq/cpufreq_governor.c:25: +extern struct mutex cpufreq_governor_lock; Thanks! -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] cpufreq: Fix timer/workqueue corruption by protecting reading governor_enabled
Yes, I test it. After adding cpufreq_governor_lock in gov_queue_work() and running same test, there is no debugobjects warning. But it really can't work at all.. There should be a separate copy of lock in every file that includes cpufreq.h.. And so this shouldn't have worked. Oh.. I understand what you mean now. My patch is not right and cannot fix this issue. By default, the debugobjects warning sometimes occurs after five minutes, and sometimes occurs after twenty hours. With this patch, I test more than fifty hours, and warning did not occurs. It shows that my test time is not long enough and miss the right one. I have updated PATCH v2, please review again. Thanks. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] cpufreq: Fix timer/workqueue corruption by protecting reading governor_enabled
Yes, I test it. After adding cpufreq_governor_lock in gov_queue_work() and running same test, there is no debugobjects warning. But it really can't work at all.. There should be a separate copy of lock in every file that includes cpufreq.h.. And so this shouldn't have worked. Oh.. I understand what you mean now. My patch is not right and cannot fix this issue. By default, the debugobjects warning sometimes occurs after five minutes, and sometimes occurs after twenty hours. With this patch, I test more than fifty hours, and warning did not occurs. It shows that my test time is not long enough and miss the right one. I have updated PATCH v2, please review again. Thanks. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] cpufreq: Fix timer/workqueue corruption by protecting reading governor_enabled
On 12/27/2013 05:40 PM, Viresh Kumar wrote: On 27 December 2013 15:00, wrote: diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c -static DEFINE_MUTEX(cpufreq_governor_lock); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index dc196bb..4faafe7 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -254,6 +254,7 @@ struct cpufreq_driver { int cpufreq_register_driver(struct cpufreq_driver *driver_data); int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); +static DEFINE_MUTEX(cpufreq_governor_lock); No way, this would never work. This would create separate locks in each file that includes cpufreq.h. And so the locks you are talking about wouldn't protect governor. I checked my code, and found I lost following part. My local code base is not exactly same as open source, and has included this. diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index e6be635..c4d0ee6 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "cpufreq_governor.h" Have you actually tested this code? If this fixes the breakage you saw? If this fixes it then you need to do better investigation of your problem. Yes, I test it. After adding cpufreq_governor_lock in gov_queue_work() and running same test, there is no debugobjects warning. you actually need to remove the static keyword from cpufreq.c file. Nothing else. Modify cpufreq_governor_lock definition. Do you think it is OK? diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 16d7b4a..185c9f5 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -39,7 +39,7 @@ static struct cpufreq_driver *cpufreq_driver; static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback); static DEFINE_RWLOCK(cpufreq_driver_lock); -static DEFINE_MUTEX(cpufreq_governor_lock); +DEFINE_MUTEX(cpufreq_governor_lock); static LIST_HEAD(cpufreq_policy_list); #ifdef CONFIG_HOTPLUG_CPU diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index e6be635..485ee0d 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -22,6 +22,8 @@ #include "cpufreq_governor.h" +extern struct mutex cpufreq_governor_lock; + static struct attribute_group *get_sysfs_attr(struct dbs_data *dbs_data) { if (have_governor_per_policy()) -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] cpufreq: Fix timer/workqueue corruption by protecting reading governor_enabled
On 12/27/2013 05:40 PM, Viresh Kumar wrote: On 27 December 2013 15:00, j...@marvell.com wrote: diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c -static DEFINE_MUTEX(cpufreq_governor_lock); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index dc196bb..4faafe7 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -254,6 +254,7 @@ struct cpufreq_driver { int cpufreq_register_driver(struct cpufreq_driver *driver_data); int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); +static DEFINE_MUTEX(cpufreq_governor_lock); No way, this would never work. This would create separate locks in each file that includes cpufreq.h. And so the locks you are talking about wouldn't protect governor. I checked my code, and found I lost following part. My local code base is not exactly same as open source, and has included this. diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index e6be635..c4d0ee6 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -19,6 +19,7 @@ #include linux/export.h #include linux/kernel_stat.h #include linux/slab.h +#include linux/cpufreq.h #include cpufreq_governor.h Have you actually tested this code? If this fixes the breakage you saw? If this fixes it then you need to do better investigation of your problem. Yes, I test it. After adding cpufreq_governor_lock in gov_queue_work() and running same test, there is no debugobjects warning. you actually need to remove the static keyword from cpufreq.c file. Nothing else. Modify cpufreq_governor_lock definition. Do you think it is OK? diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 16d7b4a..185c9f5 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -39,7 +39,7 @@ static struct cpufreq_driver *cpufreq_driver; static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback); static DEFINE_RWLOCK(cpufreq_driver_lock); -static DEFINE_MUTEX(cpufreq_governor_lock); +DEFINE_MUTEX(cpufreq_governor_lock); static LIST_HEAD(cpufreq_policy_list); #ifdef CONFIG_HOTPLUG_CPU diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index e6be635..485ee0d 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -22,6 +22,8 @@ #include cpufreq_governor.h +extern struct mutex cpufreq_governor_lock; + static struct attribute_group *get_sysfs_attr(struct dbs_data *dbs_data) { if (have_governor_per_policy()) -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/