[<prev] [next>] [day] [month] [year] [list]
Message-Id: <1201640528.11148.32.camel@strongmad.jf.intel.com>
Date: Tue, 29 Jan 2008 13:02:08 -0800
From: Mitch Williams <mitch.a.williams@...el.com>
To: netdev@...r.kernel.org
Cc: jgarzik@...ox.com, davem@...emloft.net
Subject: [PATCH 1/3] Kernel support for flexible wakeup filters
Add ethtool infrastructure support for Wake-on-Lan flexible filters.
Signed-off-by: Mitch Williams <mitch.a.williams@...el.com>
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 71d4ada..70b86da 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -56,6 +56,16 @@ struct ethtool_wolinfo {
__u8 sopass[SOPASS_MAX]; /* SecureOn(tm) password */
};
+#define WOL_FILTER_MAX_LEN 256
+#define WOL_FILTER_IGNORE_OCTET 0x100
+/* wake-on-lan flexible filters */
+struct ethtool_wol_filter {
+ __u32 cmd;
+ __u32 index;
+ __u32 len;
+ __u16 mask_val[0];
+};
+
/* for passing single values */
struct ethtool_value {
__u32 cmd;
@@ -326,6 +336,8 @@ int ethtool_op_set_flags(struct net_device *dev, u32 data);
* get_stats: Return statistics about the device
* get_flags: get 32-bit flags bitmap
* set_flags: set 32-bit flags bitmap
+ * get_wol_filter: get user-defined Wake-on-Lan filter
+ * set_wol_filter: set user-defined Wake-on-Lan filter
*
* Description:
*
@@ -391,6 +403,8 @@ struct ethtool_ops {
u32 (*get_priv_flags)(struct net_device *);
int (*set_priv_flags)(struct net_device *, u32);
int (*get_sset_count)(struct net_device *, int);
+ int (*get_wol_filter)(struct net_device *, struct ethtool_wol_filter *, u16 *);
+ int (*set_wol_filter)(struct net_device *, struct ethtool_wol_filter *, u16 *);
/* the following hooks are obsolete */
int (*self_test_count)(struct net_device *);/* use get_sset_count */
@@ -440,6 +454,9 @@ struct ethtool_ops {
#define ETHTOOL_SFLAGS 0x00000026 /* Set flags bitmap(ethtool_value) */
#define ETHTOOL_GPFLAGS 0x00000027 /* Get driver-private flags bitmap */
#define ETHTOOL_SPFLAGS 0x00000028 /* Set driver-private flags bitmap */
+#define ETHTOOL_GNUMWOLFILT 0x00000029 /* Get number of WOL filters. */
+#define ETHTOOL_GWOLFILTER 0x0000002a /* Get WOL filter */
+#define ETHTOOL_SWOLFILTER 0x0000002b /* Set WOL filter */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
@@ -526,5 +543,6 @@ struct ethtool_ops {
#define WAKE_ARP (1 << 4)
#define WAKE_MAGIC (1 << 5)
#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */
+#define WAKE_FILTER (1 << 7)
#endif /* _LINUX_ETHTOOL_H */
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 1163eb2..9ba9eb5 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -272,6 +272,64 @@ static int ethtool_set_wol(struct net_device *dev, char __user *useraddr)
return dev->ethtool_ops->set_wol(dev, &wol);
}
+static int ethtool_get_wol_filter(struct net_device *dev, char __user *useraddr)
+{
+ struct ethtool_wol_filter wolfilt = { ETHTOOL_GWOLFILTER };
+ u16 *data;
+
+ if (!dev->ethtool_ops->get_wol_filter)
+ return -EOPNOTSUPP;
+
+ data = kmalloc(WOL_FILTER_MAX_LEN * 2, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ if (copy_from_user(&wolfilt, useraddr, sizeof(wolfilt)))
+ return -EFAULT;
+
+ dev->ethtool_ops->get_wol_filter(dev, &wolfilt, data);
+
+ if (copy_to_user(useraddr, &wolfilt, sizeof(wolfilt)))
+ return -EFAULT;
+ if (copy_to_user(useraddr + sizeof(wolfilt), data, wolfilt.len * 2))
+ return -EFAULT;
+
+ kfree(data);
+ return 0;
+}
+
+static int ethtool_set_wol_filter(struct net_device *dev, char __user *useraddr)
+{
+ struct ethtool_wol_filter wolfilt;
+ u16 *data = NULL;
+ int ret;
+
+ if (!dev->ethtool_ops->get_wol_filter)
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&wolfilt, useraddr, sizeof(wolfilt)))
+ return -EFAULT;
+
+ if (wolfilt.len > WOL_FILTER_MAX_LEN)
+ return -EOPNOTSUPP;
+
+ if (wolfilt.len) {
+ data = kmalloc(wolfilt.len * 2, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ }
+
+ ret = -EFAULT;
+ if (copy_from_user(data, useraddr + sizeof(wolfilt), wolfilt.len * 2))
+ goto out;
+
+ ret = dev->ethtool_ops->set_wol_filter(dev, &wolfilt, data);
+out:
+ kfree(data);
+ return ret;
+
+}
+
static int ethtool_nway_reset(struct net_device *dev)
{
if (!dev->ethtool_ops->nway_reset)
@@ -964,6 +1022,13 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
rc = ethtool_set_value(dev, useraddr,
dev->ethtool_ops->set_priv_flags);
break;
+ case ETHTOOL_GNUMWOLFILT:
+ case ETHTOOL_GWOLFILTER:
+ rc = ethtool_get_wol_filter(dev, useraddr);
+ break;
+ case ETHTOOL_SWOLFILTER:
+ rc = ethtool_set_wol_filter(dev, useraddr);
+ break;
default:
rc = -EOPNOTSUPP;
}
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists