aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa/dsa.c
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2014-09-18 20:31:22 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-22 14:41:23 -0400
commit2446254915a7d6f08bba9a755a34cc0402880472 (patch)
tree2b27382c1139a4a9e2b012fa7a9b9604e51bb031 /net/dsa/dsa.c
parent34f6b8745d421683ca0a268540869eb30721e970 (diff)
net: dsa: allow switch drivers to implement suspend/resume hooks
Add an abstraction layer to suspend/resume switch devices, doing the following split: - suspend/resume the slave network devices and their corresponding PHY devices - suspend/resume the switch hardware using switch driver callbacks Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa/dsa.c')
-rw-r--r--net/dsa/dsa.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 6e40928ec0e7..6905f2d84c44 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -238,6 +238,49 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
238{ 238{
239} 239}
240 240
241static int dsa_switch_suspend(struct dsa_switch *ds)
242{
243 int i, ret = 0;
244
245 /* Suspend slave network devices */
246 for (i = 0; i < DSA_MAX_PORTS; i++) {
247 if (!(ds->phys_port_mask & (1 << i)))
248 continue;
249
250 ret = dsa_slave_suspend(ds->ports[i]);
251 if (ret)
252 return ret;
253 }
254
255 if (ds->drv->suspend)
256 ret = ds->drv->suspend(ds);
257
258 return ret;
259}
260
261static int dsa_switch_resume(struct dsa_switch *ds)
262{
263 int i, ret = 0;
264
265 if (ds->drv->resume)
266 ret = ds->drv->resume(ds);
267
268 if (ret)
269 return ret;
270
271 /* Resume slave network devices */
272 for (i = 0; i < DSA_MAX_PORTS; i++) {
273 if (!(ds->phys_port_mask & (1 << i)))
274 continue;
275
276 ret = dsa_slave_resume(ds->ports[i]);
277 if (ret)
278 return ret;
279 }
280
281 return 0;
282}
283
241 284
242/* link polling *************************************************************/ 285/* link polling *************************************************************/
243static void dsa_link_poll_work(struct work_struct *ugly) 286static void dsa_link_poll_work(struct work_struct *ugly)
@@ -650,6 +693,42 @@ static struct packet_type dsa_pack_type __read_mostly = {
650 .func = dsa_switch_rcv, 693 .func = dsa_switch_rcv,
651}; 694};
652 695
696#ifdef CONFIG_PM_SLEEP
697static int dsa_suspend(struct device *d)
698{
699 struct platform_device *pdev = to_platform_device(d);
700 struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
701 int i, ret = 0;
702
703 for (i = 0; i < dst->pd->nr_chips; i++) {
704 struct dsa_switch *ds = dst->ds[i];
705
706 if (ds != NULL)
707 ret = dsa_switch_suspend(ds);
708 }
709
710 return ret;
711}
712
713static int dsa_resume(struct device *d)
714{
715 struct platform_device *pdev = to_platform_device(d);
716 struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
717 int i, ret = 0;
718
719 for (i = 0; i < dst->pd->nr_chips; i++) {
720 struct dsa_switch *ds = dst->ds[i];
721
722 if (ds != NULL)
723 ret = dsa_switch_resume(ds);
724 }
725
726 return ret;
727}
728#endif
729
730static SIMPLE_DEV_PM_OPS(dsa_pm_ops, dsa_suspend, dsa_resume);
731
653static const struct of_device_id dsa_of_match_table[] = { 732static const struct of_device_id dsa_of_match_table[] = {
654 { .compatible = "brcm,bcm7445-switch-v4.0" }, 733 { .compatible = "brcm,bcm7445-switch-v4.0" },
655 { .compatible = "marvell,dsa", }, 734 { .compatible = "marvell,dsa", },
@@ -665,6 +744,7 @@ static struct platform_driver dsa_driver = {
665 .name = "dsa", 744 .name = "dsa",
666 .owner = THIS_MODULE, 745 .owner = THIS_MODULE,
667 .of_match_table = dsa_of_match_table, 746 .of_match_table = dsa_of_match_table,
747 .pm = &dsa_pm_ops,
668 }, 748 },
669}; 749};
670 750