summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale/dpa
diff options
context:
space:
mode:
authorCristian Sovaiala <cristian.sovaiala@freescale.com>2014-03-13 09:45:55 (GMT)
committerMadalin-Cristian Bucur <madalin.bucur@freescale.com>2014-03-27 10:19:41 (GMT)
commit8e4f6f6cb2233cd40ff80f8c9cd66f187b3656f0 (patch)
treeac83f042ccad385a0a4793e6161f0c2fd9e976ab /drivers/net/ethernet/freescale/dpa
parent0608f0e1eae8b107c33e4cf1f9e712fcb2e8453b (diff)
downloadlinux-fsl-qoriq-8e4f6f6cb2233cd40ff80f8c9cd66f187b3656f0.tar.xz
dpaa_eth: Add support for Wake on Lan
Currently the system wakes up from sleep mode on Magic Packets. The ports that are configured as Auto Response will not have the WoL feature enabled. Magic Packets are not yet supported on those ports. Signed-off-by: Cristian Sovaiala <cristian.sovaiala@freescale.com> Change-Id: I579494dab0a0e918a2644483129951d370cbccf9 Reviewed-on: http://git.am.freescale.net:8181/9904 Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com> Reviewed-by: Jose Rivera <German.Rivera@freescale.com> (cherry picked from commit 0d0575e647c95c988148a107839a1c1f31baa420) Reviewed-on: http://git.am.freescale.net:8181/10401 Reviewed-by: Madalin-Cristian Bucur <madalin.bucur@freescale.com> Tested-by: Madalin-Cristian Bucur <madalin.bucur@freescale.com>
Diffstat (limited to 'drivers/net/ethernet/freescale/dpa')
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth.c18
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth.h8
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c52
-rw-r--r--drivers/net/ethernet/freescale/dpa/mac-api.c3
-rw-r--r--drivers/net/ethernet/freescale/dpa/mac.h2
5 files changed, 83 insertions, 0 deletions
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth.c
index 21352e1..9a9f0c8 100644
--- a/drivers/net/ethernet/freescale/dpa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth.c
@@ -130,6 +130,13 @@ static int dpaa_suspend_noirq(struct device *dev)
err = fm_port_suspend(mac_dev->port_dev[TX]);
if (err)
err = fm_port_resume(mac_dev->port_dev[RX]);
+
+ if (priv->wol & DPAA_WOL_MAGIC) {
+ err = priv->mac_dev->set_wol(mac_dev->port_dev[RX],
+ priv->mac_dev->get_mac_handle(mac_dev), true);
+ if (unlikely(err < 0))
+ netdev_err(net_dev, "set_wol() = %d\n", err);
+ }
}
port_suspend_failed:
@@ -149,6 +156,13 @@ static int dpaa_resume_noirq(struct device *dev)
priv = netdev_priv(net_dev);
mac_dev = priv->mac_dev;
+ if (priv->wol & DPAA_WOL_MAGIC) {
+ err = priv->mac_dev->set_wol(mac_dev->port_dev[RX],
+ priv->mac_dev->get_mac_handle(mac_dev), false);
+ if (unlikely(err < 0))
+ netdev_err(net_dev, "set_wol() = %d\n", err);
+ }
+
err = fm_port_resume(mac_dev->port_dev[TX]);
if (err)
goto port_resume_failed;
@@ -1000,6 +1014,10 @@ dpaa_eth_priv_probe(struct platform_device *_of_dev)
dpaa_eth_sysfs_init(&net_dev->dev);
+#ifdef CONFIG_PM
+ device_set_wakeup_capable(dev, true);
+#endif
+
pr_info("fsl_dpa: Probed interface %s\n", net_dev->name);
return 0;
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpa/dpaa_eth.h
index 0b29a3b..a781954 100644
--- a/drivers/net/ethernet/freescale/dpa/dpaa_eth.h
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth.h
@@ -188,6 +188,11 @@ struct dpa_buffer_layout_s {
#define DPAA_ETH_TX_QUEUES NR_CPUS
#define DPAA_ETH_RX_QUEUES 128
+#ifdef CONFIG_PM
+/* Magic Packet wakeup */
+#define DPAA_WOL_MAGIC 0x00000001
+#endif
+
#if defined(CONFIG_FSL_FMAN_TEST)
struct pcd_range {
uint32_t base;
@@ -374,6 +379,9 @@ struct dpa_priv_s {
char if_type[30];
void *peer;
+#ifdef CONFIG_PM
+ u32 wol;
+#endif
};
struct fm_port_fqs {
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c
index deb7091..839c223 100644
--- a/drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c
@@ -279,6 +279,54 @@ static int __cold dpa_set_pauseparam(struct net_device *net_dev,
return 0;
}
+#ifdef CONFIG_PM
+static void dpa_get_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+
+ wol->supported = 0;
+ wol->wolopts = 0;
+
+ if (!priv->wol || !device_can_wakeup(net_dev->dev.parent))
+ return;
+
+ if (priv->wol & DPAA_WOL_MAGIC) {
+ wol->supported = WAKE_MAGIC;
+ wol->wolopts = WAKE_MAGIC;
+ }
+}
+
+static int dpa_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+
+ if (priv->mac_dev == NULL) {
+ netdev_info(net_dev, "This is a MAC-less interface\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(priv->mac_dev->phy_dev == NULL)) {
+ netdev_dbg(net_dev, "phy device not initialized\n");
+ return -ENODEV;
+ }
+
+ if (!device_can_wakeup(net_dev->dev.parent) ||
+ (wol->wolopts & ~WAKE_MAGIC))
+ return -EOPNOTSUPP;
+
+ priv->wol = 0;
+
+ if (wol->wolopts & WAKE_MAGIC) {
+ priv->wol = DPAA_WOL_MAGIC;
+ device_set_wakeup_enable(net_dev->dev.parent, 1);
+ } else {
+ device_set_wakeup_enable(net_dev->dev.parent, 0);
+ }
+
+ return 0;
+}
+#endif
+
const struct ethtool_ops dpa_ethtool_ops = {
.get_settings = dpa_get_settings,
.set_settings = dpa_set_settings,
@@ -292,4 +340,8 @@ const struct ethtool_ops dpa_ethtool_ops = {
.self_test = NULL, /* TODO invoke the cold-boot unit-test? */
.get_ethtool_stats = NULL, /* TODO other stats, currently in debugfs */
.get_link = ethtool_op_get_link,
+#ifdef CONFIG_PM
+ .get_wol = dpa_get_wol,
+ .set_wol = dpa_set_wol,
+#endif
};
diff --git a/drivers/net/ethernet/freescale/dpa/mac-api.c b/drivers/net/ethernet/freescale/dpa/mac-api.c
index 4105e1d..5833a5e 100644
--- a/drivers/net/ethernet/freescale/dpa/mac-api.c
+++ b/drivers/net/ethernet/freescale/dpa/mac-api.c
@@ -720,6 +720,7 @@ static void __cold setup_dtsec(struct mac_device *mac_dev)
mac_dev->fm_rtc_set_drift = fm_rtc_set_drift;
mac_dev->fm_rtc_set_alarm = fm_rtc_set_alarm;
mac_dev->fm_rtc_set_fiper = fm_rtc_set_fiper;
+ mac_dev->set_wol = fm_mac_set_wol;
mac_dev->dump_mac_regs = dtsec_dump_regs;
}
@@ -736,6 +737,7 @@ static void __cold setup_xgmac(struct mac_device *mac_dev)
mac_dev->get_mac_handle = get_mac_handle;
mac_dev->set_tx_pause = fm_mac_set_tx_pause_frames;
mac_dev->set_rx_pause = fm_mac_set_rx_pause_frames;
+ mac_dev->set_wol = fm_mac_set_wol;
mac_dev->dump_mac_regs = xgmac_dump_regs;
}
@@ -760,6 +762,7 @@ static void __cold setup_memac(struct mac_device *mac_dev)
mac_dev->fm_rtc_set_drift = fm_rtc_set_drift;
mac_dev->fm_rtc_set_alarm = fm_rtc_set_alarm;
mac_dev->fm_rtc_set_fiper = fm_rtc_set_fiper;
+ mac_dev->set_wol = fm_mac_set_wol;
mac_dev->dump_mac_regs = memac_dump_regs;
}
diff --git a/drivers/net/ethernet/freescale/dpa/mac.h b/drivers/net/ethernet/freescale/dpa/mac.h
index 3aa3c65..8814c28 100644
--- a/drivers/net/ethernet/freescale/dpa/mac.h
+++ b/drivers/net/ethernet/freescale/dpa/mac.h
@@ -94,6 +94,8 @@ struct mac_device {
int (*fm_rtc_set_alarm)(struct fm *fm_dev, uint32_t id, uint64_t time);
int (*fm_rtc_set_fiper)(struct fm *fm_dev, uint32_t id,
uint64_t fiper);
+ int (*set_wol)(struct fm_port *port, struct fm_mac_dev *fm_mac_dev,
+ bool en);
int (*dump_mac_regs)(struct mac_device *h_mac, char *buf, int nn);
};