diff options
-rw-r--r-- | include/linux/ethtool.h | 13 | ||||
-rw-r--r-- | include/linux/netdevice.h | 1 | ||||
-rw-r--r-- | net/core/ethtool.c | 49 |
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 | ||
253 | struct ethtool_perm_addr { | ||
254 | u32 cmd; /* ETHTOOL_GPERMADDR */ | ||
255 | u32 size; | ||
256 | u8 data[0]; | ||
257 | }; | ||
258 | |||
253 | struct net_device; | 259 | struct 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); | |||
261 | int ethtool_op_set_sg(struct net_device *dev, u32 data); | 267 | int ethtool_op_set_sg(struct net_device *dev, u32 data); |
262 | u32 ethtool_op_get_tso(struct net_device *dev); | 268 | u32 ethtool_op_get_tso(struct net_device *dev); |
263 | int ethtool_op_set_tso(struct net_device *dev, u32 data); | 269 | int ethtool_op_set_tso(struct net_device *dev, u32 data); |
270 | int ethtool_op_get_perm_addr(struct net_device *dev, | ||
271 | struct ethtool_perm_addr *addr, u8 *data); | ||
264 | 272 | ||
265 | /** | 273 | /** |
266 | * ðtool_ops - Alter and report network device settings | 274 | * ðtool_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 | ||
84 | int 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 | ||
86 | static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) | 98 | static 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 | ||
698 | static 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 | ||
688 | int dev_ethtool(struct ifreq *ifr) | 733 | int 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 | ||
827 | EXPORT_SYMBOL(dev_ethtool); | 875 | EXPORT_SYMBOL(dev_ethtool); |
828 | EXPORT_SYMBOL(ethtool_op_get_link); | 876 | EXPORT_SYMBOL(ethtool_op_get_link); |
877 | EXPORT_SYMBOL_GPL(ethtool_op_get_perm_addr); | ||
829 | EXPORT_SYMBOL(ethtool_op_get_sg); | 878 | EXPORT_SYMBOL(ethtool_op_get_sg); |
830 | EXPORT_SYMBOL(ethtool_op_get_tso); | 879 | EXPORT_SYMBOL(ethtool_op_get_tso); |
831 | EXPORT_SYMBOL(ethtool_op_get_tx_csum); | 880 | EXPORT_SYMBOL(ethtool_op_get_tx_csum); |