@@ -56,6 +56,9 @@ Properties:
hardware.
- fsl,magic-packet : If present, indicates that the hardware supports
waking up via magic packet.
+ - fsl,wake-on-filer : If present, indicates that the hardware supports
+ waking up via arp request to local ip address or unicast packet to
+ local mac address.
- bd-stash : If present, indicates that the hardware supports stashing
buffer descriptors in the L2.
- rx-stash-len : Denotes the number of bytes of a received buffer to stash
@@ -85,6 +85,8 @@
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/in.h>
+#include <linux/inetdevice.h>
+#include <sysdev/fsl_soc.h>
#include <linux/net_tstamp.h>
#include <asm/io.h>
@@ -147,6 +149,17 @@ static void gfar_clear_exact_match(struct net_device *dev);
static void gfar_set_mac_for_addr(struct net_device *dev, int num,
const u8 *addr);
static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void gfar_schedule_cleanup(struct gfar_priv_grp *gfargrp);
+
+#ifdef CONFIG_PM
+static void gfar_halt_rx(struct net_device *dev);
+static void gfar_rx_start(struct net_device *dev);
+static void gfar_enable_filer(struct net_device *dev);
+static void gfar_disable_filer(struct net_device *dev);
+static void gfar_config_filer_arptable(struct net_device *dev);
+static void gfar_restore_filer_table(struct net_device *dev);
+static int gfar_get_ip(struct net_device *dev);
+#endif
MODULE_AUTHOR("Freescale Semiconductor, Inc");
MODULE_DESCRIPTION("Gianfar Ethernet Driver");
@@ -751,7 +764,6 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
FSL_GIANFAR_DEV_HAS_PADDING |
FSL_GIANFAR_DEV_HAS_CSUM |
FSL_GIANFAR_DEV_HAS_VLAN |
- FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
FSL_GIANFAR_DEV_HAS_EXTENDED_HASH |
FSL_GIANFAR_DEV_HAS_TIMER;
@@ -766,6 +778,9 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
if (of_get_property(np, "fsl,magic-packet", NULL))
priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;
+ if (of_get_property(np, "fsl,wake-on-filer", NULL))
+ priv->device_flags |= FSL_GIANFAR_DEV_HAS_ARP_PACKET;
+
priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
/* Find the TBI PHY. If it's not there, we don't support SGMII */
@@ -1168,8 +1183,11 @@ static int gfar_probe(struct platform_device *ofdev)
goto register_fail;
}
- device_init_wakeup(&dev->dev,
- priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+ if ((priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) ||
+ (priv->device_flags & FSL_GIANFAR_DEV_HAS_ARP_PACKET)) {
+ device_set_wakeup_capable(&ofdev->dev, true);
+ device_set_wakeup_enable(&ofdev->dev, false);
+ }
/* fill out IRQ number and name fields */
len_devname = strlen(dev->name);
@@ -1260,6 +1278,163 @@ static int gfar_remove(struct platform_device *ofdev)
}
#ifdef CONFIG_PM
+static void gfar_enable_filer(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 temp;
+
+ lock_rx_qs(priv);
+
+ temp = gfar_read(®s->rctrl);
+ temp &= ~(RCTRL_FSQEN | RCTRL_PRSDEP_MASK);
+ temp |= RCTRL_FILREN | RCTRL_PRSDEP_L2L3;
+ gfar_write(®s->rctrl, temp);
+
+ unlock_rx_qs(priv);
+}
+
+static void gfar_disable_filer(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 temp;
+
+ lock_rx_qs(priv);
+
+ temp = gfar_read(®s->rctrl);
+ temp &= ~RCTRL_FILREN;
+ gfar_write(®s->rctrl, temp);
+
+ unlock_rx_qs(priv);
+}
+
+static int gfar_get_ip(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct in_device *in_dev = (struct in_device *)dev->ip_ptr;
+ struct in_ifaddr *ifa;
+
+ if (in_dev != NULL) {
+ ifa = (struct in_ifaddr *)in_dev->ifa_list;
+ if (ifa != NULL) {
+ memcpy(priv->ip_addr, &ifa->ifa_address, 4);
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+static void gfar_restore_filer_table(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ u32 rqfcr, rqfpr;
+ int i;
+
+ lock_rx_qs(priv);
+
+ for (i = 0; i <= MAX_FILER_IDX; i++) {
+ rqfcr = priv->ftp_rqfcr[i];
+ rqfpr = priv->ftp_rqfpr[i];
+ gfar_write_filer(priv, i, rqfcr, rqfpr);
+ }
+
+ unlock_rx_qs(priv);
+}
+
+static void gfar_config_filer_arptable(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ u8 *ip_addr;
+ u32 wakeup_ip, dest_mac_addr_h, dest_mac_addr_l;
+ u32 rqfpr = 0x0;
+ u32 rqfcr = RQFCR_RJE | RQFCR_CMP_MATCH;
+ u8 rqfcr_queue = priv->num_rx_queues - 1;
+ int i;
+
+ if (gfar_get_ip(dev))
+ netif_err(priv, wol, dev, "WOL: get the ip address error\n");
+ ip_addr = priv->ip_addr;
+
+ wakeup_ip = (*ip_addr << 24) | (*(ip_addr + 1) << 16) | \
+ (*(ip_addr + 2) << 8) | (*(ip_addr + 3));
+
+ dest_mac_addr_h = (dev->dev_addr[0] << 16) | \
+ (dev->dev_addr[1] << 8) | dev->dev_addr[2];
+ dest_mac_addr_l = (dev->dev_addr[3] << 16) | \
+ (dev->dev_addr[4] << 8) | dev->dev_addr[5];
+
+ lock_rx_qs(priv);
+
+ for (i = 0; i <= MAX_FILER_IDX; i++)
+ gfar_write_filer(priv, i, rqfcr, rqfpr);
+
+ /* ARP request filer, filling the packet to queue #1 */
+ rqfcr = (rqfcr_queue << 10) | RQFCR_AND |
+ RQFCR_CMP_EXACT | RQFCR_PID_MASK;
+ rqfpr = RQFPR_ARQ;
+ gfar_write_filer(priv, 0, rqfcr, rqfpr);
+
+ rqfcr = (rqfcr_queue << 10) | RQFCR_AND |
+ RQFCR_CMP_EXACT | RQFCR_PID_PARSE;
+ rqfpr = RQFPR_ARQ;
+ gfar_write_filer(priv, 1, rqfcr, rqfpr);
+
+ /* DEST_IP address in ARP packet, filling it to queue #1 */
+ rqfcr = (rqfcr_queue << 10) | RQFCR_AND |
+ RQFCR_CMP_EXACT | RQFCR_PID_MASK;
+ rqfpr = FPR_FILER_MASK;
+ gfar_write_filer(priv, 2, rqfcr, rqfpr);
+
+ rqfcr = RQFCR_GPI | (rqfcr_queue << 10) |
+ RQFCR_CMP_EXACT | RQFCR_PID_DIA;
+ rqfpr = wakeup_ip;
+ gfar_write_filer(priv, 3, rqfcr, rqfpr);
+
+ /* Unicast packet, filling it to queue #1 */
+ rqfcr = (rqfcr_queue << 10) | RQFCR_AND |
+ RQFCR_CMP_EXACT | RQFCR_PID_DAH;
+ rqfpr = dest_mac_addr_h;
+ gfar_write_filer(priv, 4, rqfcr, rqfpr);
+
+ rqfcr = RQFCR_GPI | (rqfcr_queue << 10) |
+ RQFCR_CMP_EXACT | RQFCR_PID_DAL;
+ mb();
+ rqfpr = dest_mac_addr_l;
+ gfar_write_filer(priv, 5, rqfcr, rqfpr);
+
+ unlock_rx_qs(priv);
+}
+
+static int gfar_arp_suspend(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ netif_device_detach(dev);
+
+ if (netif_running(dev)) {
+ local_irq_save(flags);
+ lock_tx_qs(priv);
+ lock_rx_qs(priv);
+
+ gfar_halt(dev);
+
+ unlock_rx_qs(priv);
+ unlock_tx_qs(priv);
+ local_irq_restore(flags);
+
+ disable_napi(priv);
+
+ gfar_disable_filer(dev);
+ gfar_config_filer_arptable(dev);
+ gfar_enable_filer(dev);
+ gfar_rx_start(dev);
+ }
+
+ return 0;
+}
+
static int gfar_suspend(struct device *dev)
{
@@ -1268,9 +1443,17 @@ static int gfar_suspend(struct device *dev)
struct gfar __iomem *regs = priv->gfargrp[0].regs;
unsigned long flags;
u32 tempval;
-
int magic_packet = priv->wol_en &&
- (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+ (priv->wol_opts & GIANFAR_WOL_MAGIC);
+ int arp_packet = priv->wol_en &&
+ (priv->wol_opts & GIANFAR_WOL_ARP);
+
+ if (arp_packet) {
+ pmc_enable_wake(priv->ofdev, PM_SUSPEND_MEM, 1);
+ pmc_enable_lossless(1);
+ gfar_arp_suspend(ndev);
+ return 0;
+ }
netif_device_detach(ndev);
@@ -1299,6 +1482,7 @@ static int gfar_suspend(struct device *dev)
disable_napi(priv);
if (magic_packet) {
+ pmc_enable_wake(priv->ofdev, PM_SUSPEND_MEM, 1);
/* Enable interrupt on Magic Packet */
gfar_write(®s->imask, IMASK_MAG);
@@ -1314,6 +1498,30 @@ static int gfar_suspend(struct device *dev)
return 0;
}
+static int gfar_arp_resume(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ int i;
+
+ if (!netif_running(dev)) {
+ netif_device_attach(dev);
+ return 0;
+ }
+
+ gfar_halt_rx(dev);
+ gfar_disable_filer(dev);
+ gfar_restore_filer_table(dev);
+ gfar_start(dev);
+
+ netif_device_attach(dev);
+ enable_napi(priv);
+
+ for (i = 0; i < priv->num_grps; i++)
+ gfar_schedule_cleanup(&priv->gfargrp[i]);
+
+ return 0;
+}
+
static int gfar_resume(struct device *dev)
{
struct gfar_private *priv = dev_get_drvdata(dev);
@@ -1322,7 +1530,18 @@ static int gfar_resume(struct device *dev)
unsigned long flags;
u32 tempval;
int magic_packet = priv->wol_en &&
- (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+ (priv->wol_opts & GIANFAR_WOL_MAGIC);
+ int arp_packet = priv->wol_en &&
+ (priv->wol_opts & GIANFAR_WOL_ARP);
+
+ if (arp_packet) {
+ pmc_enable_wake(priv->ofdev, PM_SUSPEND_MEM, 0);
+ pmc_enable_lossless(0);
+ gfar_arp_resume(ndev);
+ return 0;
+ } else if (magic_packet) {
+ pmc_enable_wake(priv->ofdev, PM_SUSPEND_MEM, 0);
+ }
if (!netif_running(ndev)) {
netif_device_attach(ndev);
@@ -1602,6 +1821,48 @@ static int __gfar_is_rx_idle(struct gfar_private *priv)
return 0;
}
+#ifdef CONFIG_PM
+/* Halt the receive queues */
+static void gfar_halt_rx(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 tempval;
+ int i = 0;
+
+ for (i = 0; i < priv->num_grps; i++) {
+ regs = priv->gfargrp[i].regs;
+ /* Mask all interrupts */
+ gfar_write(®s->imask, IMASK_INIT_CLEAR);
+
+ /* Clear all interrupts */
+ gfar_write(®s->ievent, IEVENT_INIT_CLEAR);
+ }
+
+ regs = priv->gfargrp[0].regs;
+ /* Stop the DMA, and wait for it to stop */
+ tempval = gfar_read(®s->dmactrl);
+ if ((tempval & DMACTRL_GRS) != DMACTRL_GRS) {
+ int ret;
+
+ tempval |= DMACTRL_GRS;
+ gfar_write(®s->dmactrl, tempval);
+
+ do {
+ ret = spin_event_timeout(((gfar_read(®s->ievent) &
+ IEVENT_GRSC) == IEVENT_GRSC), 1000000, 0);
+ if (!ret && !(gfar_read(®s->ievent) & IEVENT_GRSC))
+ ret = __gfar_is_rx_idle(priv);
+ } while (!ret);
+ }
+
+ /* Disable Rx in MACCFG1 */
+ tempval = gfar_read(®s->maccfg1);
+ tempval &= ~MACCFG1_RX_EN;
+ gfar_write(®s->maccfg1, tempval);
+}
+#endif
+
/* Halt the receive and transmit queues */
static void gfar_halt_nodisable(struct net_device *dev)
{
@@ -1808,6 +2069,40 @@ void gfar_start(struct net_device *dev)
dev->trans_start = jiffies; /* prevent tx timeout */
}
+#ifdef CONFIG_PM
+void gfar_rx_start(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 tempval;
+ int i = 0;
+
+ /* Enable Rx in MACCFG1 */
+ tempval = gfar_read(®s->maccfg1);
+ tempval |= MACCFG1_RX_EN;
+ gfar_write(®s->maccfg1, tempval);
+
+ /* Initialize DMACTRL to have WWR and WOP */
+ tempval = gfar_read(®s->dmactrl);
+ tempval |= DMACTRL_INIT_SETTINGS;
+ gfar_write(®s->dmactrl, tempval);
+
+ /* Make sure we aren't stopped */
+ tempval = gfar_read(®s->dmactrl);
+ tempval &= ~DMACTRL_GRS;
+ gfar_write(®s->dmactrl, tempval);
+
+ for (i = 0; i < priv->num_grps; i++) {
+ regs = priv->gfargrp[i].regs;
+ /* Clear RHLT, so that the DMA starts polling now */
+ gfar_write(®s->rstat, priv->gfargrp[i].rstat);
+
+ /* Unmask the interrupts we look for */
+ gfar_write(®s->imask, IMASK_DEFAULT);
+ }
+}
+#endif
+
void gfar_configure_coalescing(struct gfar_private *priv,
unsigned long tx_mask, unsigned long rx_mask)
{
@@ -1970,7 +2265,7 @@ static int gfar_enet_open(struct net_device *dev)
netif_tx_start_all_queues(dev);
- device_set_wakeup_enable(&dev->dev, priv->wol_en);
+ device_set_wakeup_enable(&priv->ofdev->dev, priv->wol_en);
return err;
}
@@ -2657,6 +2952,17 @@ static inline void count_errors(unsigned short status, struct net_device *dev)
irqreturn_t gfar_receive(int irq, void *grp_id)
{
+ struct gfar_priv_grp *gfargrp = grp_id;
+ struct gfar __iomem *regs = gfargrp->regs;
+ u32 ievent;
+
+ ievent = gfar_read(®s->ievent);
+
+ if ((ievent & IEVENT_FGPI) == IEVENT_FGPI) {
+ gfar_write(®s->ievent, ievent & IEVENT_RX_MASK);
+ return IRQ_HANDLED;
+ }
+
gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id);
return IRQ_HANDLED;
}
@@ -232,6 +232,14 @@ extern const char gfar_driver_version[];
#define RQUEUE_EN7 0x00000001
#define RQUEUE_EN_ALL 0x000000FF
+/* Wake-On-Lan options */
+#define GIANFAR_WOL_PHY (1 << 0)
+#define GIANFAR_WOL_UCAST (1 << 1)
+#define GIANFAR_WOL_MCAST (1 << 2)
+#define GIANFAR_WOL_BCAST (1 << 3)
+#define GIANFAR_WOL_ARP (1 << 4)
+#define GIANFAR_WOL_MAGIC (1 << 5)
+
/* Init to do tx snooping for buffers and descriptors */
#define DMACTRL_INIT_SETTINGS 0x000000c3
#define DMACTRL_GRS 0x00000010
@@ -277,11 +285,15 @@ extern const char gfar_driver_version[];
#define RCTRL_PAL_MASK 0x001f0000
#define RCTRL_VLEX 0x00002000
#define RCTRL_FILREN 0x00001000
+#define RCTRL_FSQEN 0x00000800
#define RCTRL_GHTX 0x00000400
#define RCTRL_IPCSEN 0x00000200
#define RCTRL_TUCSEN 0x00000100
#define RCTRL_PRSDEP_MASK 0x000000c0
#define RCTRL_PRSDEP_INIT 0x000000c0
+#define RCTRL_PRSDEP_L2 0x00000040
+#define RCTRL_PRSDEP_L2L3 0x00000080
+#define RCTRL_PRSDEP_L2L3L4 0x000000c0
#define RCTRL_PRSFM 0x00000020
#define RCTRL_PROM 0x00000008
#define RCTRL_EMEN 0x00000002
@@ -327,18 +339,20 @@ extern const char gfar_driver_version[];
#define IEVENT_MAG 0x00000800
#define IEVENT_GRSC 0x00000100
#define IEVENT_RXF0 0x00000080
+#define IEVENT_FGPI 0x00000010
#define IEVENT_FIR 0x00000008
#define IEVENT_FIQ 0x00000004
#define IEVENT_DPE 0x00000002
#define IEVENT_PERR 0x00000001
-#define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0 | IEVENT_BSY)
+#define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0 | \
+ IEVENT_FGPI | IEVENT_BSY)
#define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF)
#define IEVENT_RTX_MASK (IEVENT_RX_MASK | IEVENT_TX_MASK)
#define IEVENT_ERR_MASK \
-(IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
- IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
- | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR \
- | IEVENT_MAG | IEVENT_BABR)
+ (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
+ IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC | \
+ IEVENT_CRL | IEVENT_XFUN | IEVENT_FIR | IEVENT_FIQ | \
+ IEVENT_DPE | IEVENT_PERR | IEVENT_MAG | IEVENT_BABR)
#define IMASK_INIT_CLEAR 0x00000000
#define IMASK_BABR 0x80000000
@@ -359,14 +373,15 @@ extern const char gfar_driver_version[];
#define IMASK_MAG 0x00000800
#define IMASK_GRSC 0x00000100
#define IMASK_RXFEN0 0x00000080
+#define IMASK_FGPI 0x00000010
#define IMASK_FIR 0x00000008
#define IMASK_FIQ 0x00000004
#define IMASK_DPE 0x00000002
#define IMASK_PERR 0x00000001
#define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \
IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \
- IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
- | IMASK_PERR)
+ IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_FGPI | \
+ IMASK_FIR | IMASK_FIQ | IMASK_DPE | IMASK_PERR)
#define IMASK_RTX_DISABLED ((~(IMASK_RXFEN0 | IMASK_TXFEN | IMASK_BSY)) \
& IMASK_DEFAULT)
@@ -883,6 +898,7 @@ struct gfar {
#define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200
#define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400
#define FSL_GIANFAR_DEV_HAS_TIMER 0x00000800
+#define FSL_GIANFAR_DEV_HAS_ARP_PACKET 0x00001000
#if (MAXGROUPS == 2)
#define DEFAULT_MAPPING 0xAA
@@ -1115,6 +1131,9 @@ struct gfar_private {
struct work_struct reset_task;
+ u8 ip_addr[4];
+ int wol_opts;
+
/* Network Statistics */
struct gfar_extra_stats extra_stats;
@@ -29,6 +29,7 @@
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -577,11 +578,18 @@ static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct gfar_private *priv = netdev_priv(dev);
+ wol->supported = 0;
+ wol->wolopts = 0;
+
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) {
- wol->supported = WAKE_MAGIC;
- wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0;
- } else {
- wol->supported = wol->wolopts = 0;
+ wol->supported |= WAKE_MAGIC;
+ wol->wolopts |= (priv->wol_opts & GIANFAR_WOL_MAGIC) ?
+ WAKE_MAGIC : 0;
+ }
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_ARP_PACKET) {
+ wol->supported |= WAKE_ARP;
+ wol->wolopts |= (priv->wol_opts & GIANFAR_WOL_ARP) ?
+ WAKE_ARP : 0;
}
}
@@ -591,16 +599,21 @@ static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
unsigned long flags;
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
- wol->wolopts != 0)
- return -EINVAL;
-
- if (wol->wolopts & ~WAKE_MAGIC)
+ !(priv->device_flags & FSL_GIANFAR_DEV_HAS_ARP_PACKET))
return -EINVAL;
- device_set_wakeup_enable(&dev->dev, wol->wolopts & WAKE_MAGIC);
-
spin_lock_irqsave(&priv->bflock, flags);
- priv->wol_en = !!device_may_wakeup(&dev->dev);
+ if (wol->wolopts & WAKE_MAGIC) {
+ priv->wol_en = 1;
+ priv->wol_opts = GIANFAR_WOL_MAGIC;
+ } else if (wol->wolopts & WAKE_ARP) {
+ priv->wol_en = 1;
+ priv->wol_opts = GIANFAR_WOL_ARP;
+ } else {
+ priv->wol_en = 0;
+ priv->wol_opts = 0;
+ }
+ device_set_wakeup_enable(&priv->ofdev->dev, (u32)priv->wol_en);
spin_unlock_irqrestore(&priv->bflock, flags);
return 0;