diff options
Diffstat (limited to 'net/core/ethtool.c')
-rw-r--r-- | net/core/ethtool.c | 49 |
1 files changed, 49 insertions, 0 deletions
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); |