|
@@ -81,6 +81,18 @@ int ethtool_op_set_tso(struct net_device *dev, u32 data)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+int ethtool_op_get_perm_addr(struct net_device *dev, struct ethtool_perm_addr *addr, u8 *data)
|
|
|
+{
|
|
|
+ unsigned char len = dev->addr_len;
|
|
|
+ if ( addr->size < len )
|
|
|
+ return -ETOOSMALL;
|
|
|
+
|
|
|
+ addr->size = len;
|
|
|
+ memcpy(data, dev->perm_addr, len);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/* Handlers for each ethtool command */
|
|
|
|
|
|
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)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int ethtool_get_perm_addr(struct net_device *dev, void *useraddr)
|
|
|
+{
|
|
|
+ struct ethtool_perm_addr epaddr;
|
|
|
+ u8 *data;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!dev->ethtool_ops->get_perm_addr)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ if (copy_from_user(&epaddr,useraddr,sizeof(epaddr)))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ data = kmalloc(epaddr.size, GFP_USER);
|
|
|
+ if (!data)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ ret = dev->ethtool_ops->get_perm_addr(dev,&epaddr,data);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ ret = -EFAULT;
|
|
|
+ if (copy_to_user(useraddr, &epaddr, sizeof(epaddr)))
|
|
|
+ goto out;
|
|
|
+ useraddr += sizeof(epaddr);
|
|
|
+ if (copy_to_user(useraddr, data, epaddr.size))
|
|
|
+ goto out;
|
|
|
+ ret = 0;
|
|
|
+
|
|
|
+ out:
|
|
|
+ kfree(data);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/* The main entry point in this file. Called from net/core/dev.c */
|
|
|
|
|
|
int dev_ethtool(struct ifreq *ifr)
|
|
@@ -806,6 +851,9 @@ int dev_ethtool(struct ifreq *ifr)
|
|
|
case ETHTOOL_GSTATS:
|
|
|
rc = ethtool_get_stats(dev, useraddr);
|
|
|
break;
|
|
|
+ case ETHTOOL_GPERMADDR:
|
|
|
+ rc = ethtool_get_perm_addr(dev, useraddr);
|
|
|
+ break;
|
|
|
default:
|
|
|
rc = -EOPNOTSUPP;
|
|
|
}
|
|
@@ -826,6 +874,7 @@ int dev_ethtool(struct ifreq *ifr)
|
|
|
|
|
|
EXPORT_SYMBOL(dev_ethtool);
|
|
|
EXPORT_SYMBOL(ethtool_op_get_link);
|
|
|
+EXPORT_SYMBOL_GPL(ethtool_op_get_perm_addr);
|
|
|
EXPORT_SYMBOL(ethtool_op_get_sg);
|
|
|
EXPORT_SYMBOL(ethtool_op_get_tso);
|
|
|
EXPORT_SYMBOL(ethtool_op_get_tx_csum);
|