aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/dsa/bcm_sf2.c58
-rw-r--r--drivers/net/dsa/bcm_sf2.h3
2 files changed, 61 insertions, 0 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 29ceee366e44..d9b7da545063 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -22,6 +22,7 @@
22#include <linux/of_irq.h> 22#include <linux/of_irq.h>
23#include <linux/of_address.h> 23#include <linux/of_address.h>
24#include <net/dsa.h> 24#include <net/dsa.h>
25#include <linux/ethtool.h>
25 26
26#include "bcm_sf2.h" 27#include "bcm_sf2.h"
27#include "bcm_sf2_regs.h" 28#include "bcm_sf2_regs.h"
@@ -242,6 +243,9 @@ static void bcm_sf2_port_disable(struct dsa_switch *ds, int port)
242 struct bcm_sf2_priv *priv = ds_to_priv(ds); 243 struct bcm_sf2_priv *priv = ds_to_priv(ds);
243 u32 off, reg; 244 u32 off, reg;
244 245
246 if (priv->wol_ports_mask & (1 << port))
247 return;
248
245 if (dsa_is_cpu_port(ds, port)) 249 if (dsa_is_cpu_port(ds, port))
246 off = CORE_IMP_CTL; 250 off = CORE_IMP_CTL;
247 else 251 else
@@ -689,6 +693,58 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds)
689 return 0; 693 return 0;
690} 694}
691 695
696static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
697 struct ethtool_wolinfo *wol)
698{
699 struct net_device *p = ds->dst[ds->index].master_netdev;
700 struct bcm_sf2_priv *priv = ds_to_priv(ds);
701 struct ethtool_wolinfo pwol;
702
703 /* Get the parent device WoL settings */
704 p->ethtool_ops->get_wol(p, &pwol);
705
706 /* Advertise the parent device supported settings */
707 wol->supported = pwol.supported;
708 memset(&wol->sopass, 0, sizeof(wol->sopass));
709
710 if (pwol.wolopts & WAKE_MAGICSECURE)
711 memcpy(&wol->sopass, pwol.sopass, sizeof(wol->sopass));
712
713 if (priv->wol_ports_mask & (1 << port))
714 wol->wolopts = pwol.wolopts;
715 else
716 wol->wolopts = 0;
717}
718
719static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
720 struct ethtool_wolinfo *wol)
721{
722 struct net_device *p = ds->dst[ds->index].master_netdev;
723 struct bcm_sf2_priv *priv = ds_to_priv(ds);
724 s8 cpu_port = ds->dst[ds->index].cpu_port;
725 struct ethtool_wolinfo pwol;
726
727 p->ethtool_ops->get_wol(p, &pwol);
728 if (wol->wolopts & ~pwol.supported)
729 return -EINVAL;
730
731 if (wol->wolopts)
732 priv->wol_ports_mask |= (1 << port);
733 else
734 priv->wol_ports_mask &= ~(1 << port);
735
736 /* If we have at least one port enabled, make sure the CPU port
737 * is also enabled. If the CPU port is the last one enabled, we disable
738 * it since this configuration does not make sense.
739 */
740 if (priv->wol_ports_mask && priv->wol_ports_mask != (1 << cpu_port))
741 priv->wol_ports_mask |= (1 << cpu_port);
742 else
743 priv->wol_ports_mask &= ~(1 << cpu_port);
744
745 return p->ethtool_ops->set_wol(p, wol);
746}
747
692static struct dsa_switch_driver bcm_sf2_switch_driver = { 748static struct dsa_switch_driver bcm_sf2_switch_driver = {
693 .tag_protocol = DSA_TAG_PROTO_BRCM, 749 .tag_protocol = DSA_TAG_PROTO_BRCM,
694 .priv_size = sizeof(struct bcm_sf2_priv), 750 .priv_size = sizeof(struct bcm_sf2_priv),
@@ -705,6 +761,8 @@ static struct dsa_switch_driver bcm_sf2_switch_driver = {
705 .fixed_link_update = bcm_sf2_sw_fixed_link_update, 761 .fixed_link_update = bcm_sf2_sw_fixed_link_update,
706 .suspend = bcm_sf2_sw_suspend, 762 .suspend = bcm_sf2_sw_suspend,
707 .resume = bcm_sf2_sw_resume, 763 .resume = bcm_sf2_sw_resume,
764 .get_wol = bcm_sf2_sw_get_wol,
765 .set_wol = bcm_sf2_sw_set_wol,
708}; 766};
709 767
710static int __init bcm_sf2_init(void) 768static int __init bcm_sf2_init(void)
diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h
index d3bd52dc40d2..8fd6c1451a84 100644
--- a/drivers/net/dsa/bcm_sf2.h
+++ b/drivers/net/dsa/bcm_sf2.h
@@ -70,6 +70,9 @@ struct bcm_sf2_priv {
70 struct bcm_sf2_hw_params hw_params; 70 struct bcm_sf2_hw_params hw_params;
71 71
72 struct bcm_sf2_port_status port_sts[DSA_MAX_PORTS]; 72 struct bcm_sf2_port_status port_sts[DSA_MAX_PORTS];
73
74 /* Mask of ports enabled for Wake-on-LAN */
75 u32 wol_ports_mask;
73}; 76};
74 77
75struct bcm_sf2_hw_stats { 78struct bcm_sf2_hw_stats {