aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ethtool.h13
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--net/core/ethtool.c49
3 files changed, 62 insertions, 1 deletions
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index d7021c391b2b..ed1440ea4c91 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -250,6 +250,12 @@ struct ethtool_stats {
250 u64 data[0]; 250 u64 data[0];
251}; 251};
252 252
253struct ethtool_perm_addr {
254 u32 cmd; /* ETHTOOL_GPERMADDR */
255 u32 size;
256 u8 data[0];
257};
258
253struct net_device; 259struct net_device;
254 260
255/* Some generic methods drivers may use in their ethtool_ops */ 261/* Some generic methods drivers may use in their ethtool_ops */
@@ -261,6 +267,8 @@ u32 ethtool_op_get_sg(struct net_device *dev);
261int ethtool_op_set_sg(struct net_device *dev, u32 data); 267int ethtool_op_set_sg(struct net_device *dev, u32 data);
262u32 ethtool_op_get_tso(struct net_device *dev); 268u32 ethtool_op_get_tso(struct net_device *dev);
263int ethtool_op_set_tso(struct net_device *dev, u32 data); 269int ethtool_op_set_tso(struct net_device *dev, u32 data);
270int ethtool_op_get_perm_addr(struct net_device *dev,
271 struct ethtool_perm_addr *addr, u8 *data);
264 272
265/** 273/**
266 * &ethtool_ops - Alter and report network device settings 274 * &ethtool_ops - Alter and report network device settings
@@ -294,7 +302,8 @@ int ethtool_op_set_tso(struct net_device *dev, u32 data);
294 * get_strings: Return a set of strings that describe the requested objects 302 * get_strings: Return a set of strings that describe the requested objects
295 * phys_id: Identify the device 303 * phys_id: Identify the device
296 * get_stats: Return statistics about the device 304 * get_stats: Return statistics about the device
297 * 305 * get_perm_addr: Gets the permanent hardware address
306 *
298 * Description: 307 * Description:
299 * 308 *
300 * get_settings: 309 * get_settings:
@@ -352,6 +361,7 @@ struct ethtool_ops {
352 int (*phys_id)(struct net_device *, u32); 361 int (*phys_id)(struct net_device *, u32);
353 int (*get_stats_count)(struct net_device *); 362 int (*get_stats_count)(struct net_device *);
354 void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *); 363 void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *);
364 int (*get_perm_addr)(struct net_device *, struct ethtool_perm_addr *, u8 *);
355 int (*begin)(struct net_device *); 365 int (*begin)(struct net_device *);
356 void (*complete)(struct net_device *); 366 void (*complete)(struct net_device *);
357}; 367};
@@ -389,6 +399,7 @@ struct ethtool_ops {
389#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ 399#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */
390#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ 400#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */
391#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ 401#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */
402#define ETHTOOL_GPERMADDR 0x00000020 /* Get permanent hardware address */
392 403
393/* compatibility with older code */ 404/* compatibility with older code */
394#define SPARC_ETH_GSET ETHTOOL_GSET 405#define SPARC_ETH_GSET ETHTOOL_GSET
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 1fcaa88b8625..7c717907896d 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -337,6 +337,7 @@ struct net_device
337 /* Interface address info. */ 337 /* Interface address info. */
338 unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ 338 unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
339 unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */ 339 unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */
340 unsigned char perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
340 unsigned char addr_len; /* hardware address length */ 341 unsigned char addr_len; /* hardware address length */
341 unsigned short dev_id; /* for shared network cards */ 342 unsigned short dev_id; /* for shared network cards */
342 343
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index a3eeb88e1c81..289c1b5a8e4a 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -81,6 +81,18 @@ int ethtool_op_set_tso(struct net_device *dev, u32 data)
81 return 0; 81 return 0;
82} 82}
83 83
84int ethtool_op_get_perm_addr(struct net_device *dev, struct ethtool_perm_addr *addr, u8 *data)
85{
86 unsigned char len = dev->addr_len;
87 if ( addr->size < len )
88 return -ETOOSMALL;
89
90 addr->size = len;
91 memcpy(data, dev->perm_addr, len);
92 return 0;
93}
94
95
84/* Handlers for each ethtool command */ 96/* Handlers for each ethtool command */
85 97
86static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) 98static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
@@ -683,6 +695,39 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
683 return ret; 695 return ret;
684} 696}
685 697
698static int ethtool_get_perm_addr(struct net_device *dev, void *useraddr)
699{
700 struct ethtool_perm_addr epaddr;
701 u8 *data;
702 int ret;
703
704 if (!dev->ethtool_ops->get_perm_addr)
705 return -EOPNOTSUPP;
706
707 if (copy_from_user(&epaddr,useraddr,sizeof(epaddr)))
708 return -EFAULT;
709
710 data = kmalloc(epaddr.size, GFP_USER);
711 if (!data)
712 return -ENOMEM;
713
714 ret = dev->ethtool_ops->get_perm_addr(dev,&epaddr,data);
715 if (ret)
716 return ret;
717
718 ret = -EFAULT;
719 if (copy_to_user(useraddr, &epaddr, sizeof(epaddr)))
720 goto out;
721 useraddr += sizeof(epaddr);
722 if (copy_to_user(useraddr, data, epaddr.size))
723 goto out;
724 ret = 0;
725
726 out:
727 kfree(data);
728 return ret;
729}
730
686/* The main entry point in this file. Called from net/core/dev.c */ 731/* The main entry point in this file. Called from net/core/dev.c */
687 732
688int dev_ethtool(struct ifreq *ifr) 733int dev_ethtool(struct ifreq *ifr)
@@ -806,6 +851,9 @@ int dev_ethtool(struct ifreq *ifr)
806 case ETHTOOL_GSTATS: 851 case ETHTOOL_GSTATS:
807 rc = ethtool_get_stats(dev, useraddr); 852 rc = ethtool_get_stats(dev, useraddr);
808 break; 853 break;
854 case ETHTOOL_GPERMADDR:
855 rc = ethtool_get_perm_addr(dev, useraddr);
856 break;
809 default: 857 default:
810 rc = -EOPNOTSUPP; 858 rc = -EOPNOTSUPP;
811 } 859 }
@@ -826,6 +874,7 @@ int dev_ethtool(struct ifreq *ifr)
826 874
827EXPORT_SYMBOL(dev_ethtool); 875EXPORT_SYMBOL(dev_ethtool);
828EXPORT_SYMBOL(ethtool_op_get_link); 876EXPORT_SYMBOL(ethtool_op_get_link);
877EXPORT_SYMBOL_GPL(ethtool_op_get_perm_addr);
829EXPORT_SYMBOL(ethtool_op_get_sg); 878EXPORT_SYMBOL(ethtool_op_get_sg);
830EXPORT_SYMBOL(ethtool_op_get_tso); 879EXPORT_SYMBOL(ethtool_op_get_tso);
831EXPORT_SYMBOL(ethtool_op_get_tx_csum); 880EXPORT_SYMBOL(ethtool_op_get_tx_csum);