forked from luck/tmp_suning_uos_patched
ethtool: Add direct access to ops->get_sset_count
This patch is an alternative approach for accessing string counts, vs. the drvinfo indirect approach. This way the drvinfo space doesn't run out, and we don't break ABI later. Signed-off-by: Jeff Garzik <jgarzik@redhat.com> Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4b79a1aedc
commit
723b2f57ad
@ -253,6 +253,17 @@ struct ethtool_gstrings {
|
||||
__u8 data[0];
|
||||
};
|
||||
|
||||
struct ethtool_sset_info {
|
||||
__u32 cmd; /* ETHTOOL_GSSET_INFO */
|
||||
__u32 reserved;
|
||||
__u64 sset_mask; /* input: each bit selects an sset to query */
|
||||
/* output: each bit a returned sset */
|
||||
__u32 data[0]; /* ETH_SS_xxx count, in order, based on bits
|
||||
in sset_mask. One bit implies one
|
||||
__u32, two bits implies two
|
||||
__u32's, etc. */
|
||||
};
|
||||
|
||||
enum ethtool_test_flags {
|
||||
ETH_TEST_FL_OFFLINE = (1 << 0), /* online / offline */
|
||||
ETH_TEST_FL_FAILED = (1 << 1), /* test passed / failed */
|
||||
@ -606,9 +617,9 @@ struct ethtool_ops {
|
||||
#define ETHTOOL_SRXCLSRLINS 0x00000032 /* Insert RX classification rule */
|
||||
#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */
|
||||
#define ETHTOOL_RESET 0x00000034 /* Reset hardware */
|
||||
|
||||
#define ETHTOOL_SRXNTUPLE 0x00000035 /* Add an n-tuple filter to device */
|
||||
#define ETHTOOL_GRXNTUPLE 0x00000036 /* Get n-tuple filters from device */
|
||||
#define ETHTOOL_SRXNTUPLE 0x00000035 /* Add an n-tuple filter to device */
|
||||
#define ETHTOOL_GRXNTUPLE 0x00000036 /* Get n-tuple filters from device */
|
||||
#define ETHTOOL_GSSET_INFO 0x00000037 /* Get string set info */
|
||||
|
||||
/* compatibility with older code */
|
||||
#define SPARC_ETH_GSET ETHTOOL_GSET
|
||||
|
@ -214,6 +214,10 @@ static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *use
|
||||
info.cmd = ETHTOOL_GDRVINFO;
|
||||
ops->get_drvinfo(dev, &info);
|
||||
|
||||
/*
|
||||
* this method of obtaining string set info is deprecated;
|
||||
* consider using ETHTOOL_GSSET_INFO instead
|
||||
*/
|
||||
if (ops->get_sset_count) {
|
||||
int rc;
|
||||
|
||||
@ -237,6 +241,71 @@ static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *use
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* noinline attribute so that gcc doesnt use too much stack in dev_ethtool()
|
||||
*/
|
||||
static noinline int ethtool_get_sset_info(struct net_device *dev,
|
||||
void __user *useraddr)
|
||||
{
|
||||
struct ethtool_sset_info info;
|
||||
const struct ethtool_ops *ops = dev->ethtool_ops;
|
||||
u64 sset_mask;
|
||||
int i, idx = 0, n_bits = 0, ret, rc;
|
||||
u32 *info_buf = NULL;
|
||||
|
||||
if (!ops->get_sset_count)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (copy_from_user(&info, useraddr, sizeof(info)))
|
||||
return -EFAULT;
|
||||
|
||||
/* store copy of mask, because we zero struct later on */
|
||||
sset_mask = info.sset_mask;
|
||||
if (!sset_mask)
|
||||
return 0;
|
||||
|
||||
/* calculate size of return buffer */
|
||||
for (i = 0; i < 64; i++)
|
||||
if (sset_mask & (1ULL << i))
|
||||
n_bits++;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.cmd = ETHTOOL_GSSET_INFO;
|
||||
|
||||
info_buf = kzalloc(n_bits * sizeof(u32), GFP_USER);
|
||||
if (!info_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* fill return buffer based on input bitmask and successful
|
||||
* get_sset_count return
|
||||
*/
|
||||
for (i = 0; i < 64; i++) {
|
||||
if (!(sset_mask & (1ULL << i)))
|
||||
continue;
|
||||
|
||||
rc = ops->get_sset_count(dev, i);
|
||||
if (rc >= 0) {
|
||||
info.sset_mask |= (1ULL << i);
|
||||
info_buf[idx++] = rc;
|
||||
}
|
||||
}
|
||||
|
||||
ret = -EFAULT;
|
||||
if (copy_to_user(useraddr, &info, sizeof(info)))
|
||||
goto out;
|
||||
|
||||
useraddr += offsetof(struct ethtool_sset_info, data);
|
||||
if (copy_to_user(useraddr, info_buf, idx * sizeof(u32)))
|
||||
goto out;
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
kfree(info_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* noinline attribute so that gcc doesnt use too much stack in dev_ethtool()
|
||||
*/
|
||||
@ -1471,6 +1540,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
|
||||
case ETHTOOL_GRXNTUPLE:
|
||||
rc = ethtool_get_rx_ntuple(dev, useraddr);
|
||||
break;
|
||||
case ETHTOOL_GSSET_INFO:
|
||||
rc = ethtool_get_sset_info(dev, useraddr);
|
||||
break;
|
||||
default:
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user