aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGovindarajulu Varadarajan <_govind@gmx.com>2014-09-02 17:47:20 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-05 15:12:20 -0400
commitf0db9b073415848709dd59a6394969882f517da9 (patch)
treef9d5de4b8528c4f5c55d04c5642ac4053489fe5e
parenta03bb56e67c357980dae886683733dab5583dc14 (diff)
ethtool: Add generic options for tunables
This patch adds new ethtool cmd, ETHTOOL_GTUNABLE & ETHTOOL_STUNABLE for getting tunable values from driver. Add get_tunable and set_tunable to ethtool_ops. Driver implements these functions for getting/setting tunable value. Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/ethtool.h4
-rw-r--r--include/uapi/linux/ethtool.h28
-rw-r--r--net/core/ethtool.c81
3 files changed, 113 insertions, 0 deletions
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index e658229fee39..c1a2d60dfb82 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -257,6 +257,10 @@ struct ethtool_ops {
257 struct ethtool_eeprom *, u8 *); 257 struct ethtool_eeprom *, u8 *);
258 int (*get_eee)(struct net_device *, struct ethtool_eee *); 258 int (*get_eee)(struct net_device *, struct ethtool_eee *);
259 int (*set_eee)(struct net_device *, struct ethtool_eee *); 259 int (*set_eee)(struct net_device *, struct ethtool_eee *);
260 int (*get_tunable)(struct net_device *,
261 const struct ethtool_tunable *, void *);
262 int (*set_tunable)(struct net_device *,
263 const struct ethtool_tunable *, const void *);
260 264
261 265
262}; 266};
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index e3c7a719c76b..7a364f2f3d3f 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -209,6 +209,32 @@ struct ethtool_value {
209 __u32 data; 209 __u32 data;
210}; 210};
211 211
212enum tunable_id {
213 ETHTOOL_ID_UNSPEC,
214 ETHTOOL_RX_COPYBREAK,
215};
216
217enum tunable_type_id {
218 ETHTOOL_TUNABLE_UNSPEC,
219 ETHTOOL_TUNABLE_U8,
220 ETHTOOL_TUNABLE_U16,
221 ETHTOOL_TUNABLE_U32,
222 ETHTOOL_TUNABLE_U64,
223 ETHTOOL_TUNABLE_STRING,
224 ETHTOOL_TUNABLE_S8,
225 ETHTOOL_TUNABLE_S16,
226 ETHTOOL_TUNABLE_S32,
227 ETHTOOL_TUNABLE_S64,
228};
229
230struct ethtool_tunable {
231 __u32 cmd;
232 __u32 id;
233 __u32 type_id;
234 __u32 len;
235 void *data[0];
236};
237
212/** 238/**
213 * struct ethtool_regs - hardware register dump 239 * struct ethtool_regs - hardware register dump
214 * @cmd: Command number = %ETHTOOL_GREGS 240 * @cmd: Command number = %ETHTOOL_GREGS
@@ -1152,6 +1178,8 @@ enum ethtool_sfeatures_retval_bits {
1152 1178
1153#define ETHTOOL_GRSSH 0x00000046 /* Get RX flow hash configuration */ 1179#define ETHTOOL_GRSSH 0x00000046 /* Get RX flow hash configuration */
1154#define ETHTOOL_SRSSH 0x00000047 /* Set RX flow hash configuration */ 1180#define ETHTOOL_SRSSH 0x00000047 /* Set RX flow hash configuration */
1181#define ETHTOOL_GTUNABLE 0x00000048 /* Get tunable configuration */
1182#define ETHTOOL_STUNABLE 0x00000049 /* Set tunable configuration */
1155 1183
1156/* compatibility with older code */ 1184/* compatibility with older code */
1157#define SPARC_ETH_GSET ETHTOOL_GSET 1185#define SPARC_ETH_GSET ETHTOOL_GSET
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 17cb912793fa..27e61b886520 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1621,6 +1621,80 @@ static int ethtool_get_module_eeprom(struct net_device *dev,
1621 modinfo.eeprom_len); 1621 modinfo.eeprom_len);
1622} 1622}
1623 1623
1624static int ethtool_tunable_valid(const struct ethtool_tunable *tuna)
1625{
1626 switch (tuna->id) {
1627 case ETHTOOL_RX_COPYBREAK:
1628 if (tuna->len != sizeof(u32) ||
1629 tuna->type_id != ETHTOOL_TUNABLE_U32)
1630 return -EINVAL;
1631 break;
1632 default:
1633 return -EINVAL;
1634 }
1635
1636 return 0;
1637}
1638
1639static int ethtool_get_tunable(struct net_device *dev, void __user *useraddr)
1640{
1641 int ret;
1642 struct ethtool_tunable tuna;
1643 const struct ethtool_ops *ops = dev->ethtool_ops;
1644 void *data;
1645
1646 if (!ops->get_tunable)
1647 return -EOPNOTSUPP;
1648 if (copy_from_user(&tuna, useraddr, sizeof(tuna)))
1649 return -EFAULT;
1650 ret = ethtool_tunable_valid(&tuna);
1651 if (ret)
1652 return ret;
1653 data = kmalloc(tuna.len, GFP_USER);
1654 if (!data)
1655 return -ENOMEM;
1656 ret = ops->get_tunable(dev, &tuna, data);
1657 if (ret)
1658 goto out;
1659 useraddr += sizeof(tuna);
1660 ret = -EFAULT;
1661 if (copy_to_user(useraddr, data, tuna.len))
1662 goto out;
1663 ret = 0;
1664
1665out:
1666 kfree(data);
1667 return ret;
1668}
1669
1670static int ethtool_set_tunable(struct net_device *dev, void __user *useraddr)
1671{
1672 int ret;
1673 struct ethtool_tunable tuna;
1674 const struct ethtool_ops *ops = dev->ethtool_ops;
1675 void *data;
1676
1677 if (!ops->set_tunable)
1678 return -EOPNOTSUPP;
1679 if (copy_from_user(&tuna, useraddr, sizeof(tuna)))
1680 return -EFAULT;
1681 ret = ethtool_tunable_valid(&tuna);
1682 if (ret)
1683 return ret;
1684 data = kmalloc(tuna.len, GFP_USER);
1685 if (!data)
1686 return -ENOMEM;
1687 useraddr += sizeof(tuna);
1688 ret = -EFAULT;
1689 if (copy_from_user(data, useraddr, tuna.len))
1690 goto out;
1691 ret = ops->set_tunable(dev, &tuna, data);
1692
1693out:
1694 kfree(data);
1695 return ret;
1696}
1697
1624/* The main entry point in this file. Called from net/core/dev_ioctl.c */ 1698/* The main entry point in this file. Called from net/core/dev_ioctl.c */
1625 1699
1626int dev_ethtool(struct net *net, struct ifreq *ifr) 1700int dev_ethtool(struct net *net, struct ifreq *ifr)
@@ -1670,6 +1744,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1670 case ETHTOOL_GCHANNELS: 1744 case ETHTOOL_GCHANNELS:
1671 case ETHTOOL_GET_TS_INFO: 1745 case ETHTOOL_GET_TS_INFO:
1672 case ETHTOOL_GEEE: 1746 case ETHTOOL_GEEE:
1747 case ETHTOOL_GTUNABLE:
1673 break; 1748 break;
1674 default: 1749 default:
1675 if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 1750 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
@@ -1857,6 +1932,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1857 case ETHTOOL_GMODULEEEPROM: 1932 case ETHTOOL_GMODULEEEPROM:
1858 rc = ethtool_get_module_eeprom(dev, useraddr); 1933 rc = ethtool_get_module_eeprom(dev, useraddr);
1859 break; 1934 break;
1935 case ETHTOOL_GTUNABLE:
1936 rc = ethtool_get_tunable(dev, useraddr);
1937 break;
1938 case ETHTOOL_STUNABLE:
1939 rc = ethtool_set_tunable(dev, useraddr);
1940 break;
1860 default: 1941 default:
1861 rc = -EOPNOTSUPP; 1942 rc = -EOPNOTSUPP;
1862 } 1943 }