diff options
Diffstat (limited to 'net/core/ethtool.c')
-rw-r--r-- | net/core/ethtool.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index b8c2b10f397a..b8c2bcfee6af 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -1823,6 +1823,87 @@ static noinline_for_stack int ethtool_flash_device(struct net_device *dev, | |||
1823 | return dev->ethtool_ops->flash_device(dev, &efl); | 1823 | return dev->ethtool_ops->flash_device(dev, &efl); |
1824 | } | 1824 | } |
1825 | 1825 | ||
1826 | static int ethtool_set_dump(struct net_device *dev, | ||
1827 | void __user *useraddr) | ||
1828 | { | ||
1829 | struct ethtool_dump dump; | ||
1830 | |||
1831 | if (!dev->ethtool_ops->set_dump) | ||
1832 | return -EOPNOTSUPP; | ||
1833 | |||
1834 | if (copy_from_user(&dump, useraddr, sizeof(dump))) | ||
1835 | return -EFAULT; | ||
1836 | |||
1837 | return dev->ethtool_ops->set_dump(dev, &dump); | ||
1838 | } | ||
1839 | |||
1840 | static int ethtool_get_dump_flag(struct net_device *dev, | ||
1841 | void __user *useraddr) | ||
1842 | { | ||
1843 | int ret; | ||
1844 | struct ethtool_dump dump; | ||
1845 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
1846 | |||
1847 | if (!dev->ethtool_ops->get_dump_flag) | ||
1848 | return -EOPNOTSUPP; | ||
1849 | |||
1850 | if (copy_from_user(&dump, useraddr, sizeof(dump))) | ||
1851 | return -EFAULT; | ||
1852 | |||
1853 | ret = ops->get_dump_flag(dev, &dump); | ||
1854 | if (ret) | ||
1855 | return ret; | ||
1856 | |||
1857 | if (copy_to_user(useraddr, &dump, sizeof(dump))) | ||
1858 | return -EFAULT; | ||
1859 | return 0; | ||
1860 | } | ||
1861 | |||
1862 | static int ethtool_get_dump_data(struct net_device *dev, | ||
1863 | void __user *useraddr) | ||
1864 | { | ||
1865 | int ret; | ||
1866 | __u32 len; | ||
1867 | struct ethtool_dump dump, tmp; | ||
1868 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
1869 | void *data = NULL; | ||
1870 | |||
1871 | if (!dev->ethtool_ops->get_dump_data || | ||
1872 | !dev->ethtool_ops->get_dump_flag) | ||
1873 | return -EOPNOTSUPP; | ||
1874 | |||
1875 | if (copy_from_user(&dump, useraddr, sizeof(dump))) | ||
1876 | return -EFAULT; | ||
1877 | |||
1878 | memset(&tmp, 0, sizeof(tmp)); | ||
1879 | tmp.cmd = ETHTOOL_GET_DUMP_FLAG; | ||
1880 | ret = ops->get_dump_flag(dev, &tmp); | ||
1881 | if (ret) | ||
1882 | return ret; | ||
1883 | |||
1884 | len = (tmp.len > dump.len) ? dump.len : tmp.len; | ||
1885 | if (!len) | ||
1886 | return -EFAULT; | ||
1887 | |||
1888 | data = vzalloc(tmp.len); | ||
1889 | if (!data) | ||
1890 | return -ENOMEM; | ||
1891 | ret = ops->get_dump_data(dev, &dump, data); | ||
1892 | if (ret) | ||
1893 | goto out; | ||
1894 | |||
1895 | if (copy_to_user(useraddr, &dump, sizeof(dump))) { | ||
1896 | ret = -EFAULT; | ||
1897 | goto out; | ||
1898 | } | ||
1899 | useraddr += offsetof(struct ethtool_dump, data); | ||
1900 | if (copy_to_user(useraddr, data, len)) | ||
1901 | ret = -EFAULT; | ||
1902 | out: | ||
1903 | vfree(data); | ||
1904 | return ret; | ||
1905 | } | ||
1906 | |||
1826 | /* The main entry point in this file. Called from net/core/dev.c */ | 1907 | /* The main entry point in this file. Called from net/core/dev.c */ |
1827 | 1908 | ||
1828 | int dev_ethtool(struct net *net, struct ifreq *ifr) | 1909 | int dev_ethtool(struct net *net, struct ifreq *ifr) |
@@ -2039,6 +2120,15 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
2039 | case ETHTOOL_SCHANNELS: | 2120 | case ETHTOOL_SCHANNELS: |
2040 | rc = ethtool_set_channels(dev, useraddr); | 2121 | rc = ethtool_set_channels(dev, useraddr); |
2041 | break; | 2122 | break; |
2123 | case ETHTOOL_SET_DUMP: | ||
2124 | rc = ethtool_set_dump(dev, useraddr); | ||
2125 | break; | ||
2126 | case ETHTOOL_GET_DUMP_FLAG: | ||
2127 | rc = ethtool_get_dump_flag(dev, useraddr); | ||
2128 | break; | ||
2129 | case ETHTOOL_GET_DUMP_DATA: | ||
2130 | rc = ethtool_get_dump_data(dev, useraddr); | ||
2131 | break; | ||
2042 | default: | 2132 | default: |
2043 | rc = -EOPNOTSUPP; | 2133 | rc = -EOPNOTSUPP; |
2044 | } | 2134 | } |