[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1481063590-7727-2-git-send-email-saeedm@mellanox.com>
Date: Wed, 7 Dec 2016 00:33:09 +0200
From: Saeed Mahameed <saeedm@...lanox.com>
To: "David S. Miller" <davem@...emloft.net>
Cc: netdev@...r.kernel.org,
"John W . Linville" <linville@...driver.com>,
Gal Pressman <galp@...lanox.com>,
Dmitry Teif <dimat@...lanox.com>,
Saeed Mahameed <saeedm@...lanox.com>
Subject: [PATCH net-next 1/2] ethtool: Add set regs -D option support
From: Gal Pressman <galp@...lanox.com>
Currently ethtool only allows us to get device registers, in this patch
we extend this functionality to also set device registers.
ethtool -D DEVNAME [ file FILENAME ] is used to set registers in
the device using vendor specific binary registers data provided via
stdin/file. Changes made by this option can be queried using get
regs -d flag.
Example:
$ ethtool -D eth1 file /tmp/mlx5_regs
Signed-off-by: Gal Pressman <galp@...lanox.com>
Signed-off-by: Dmitry Teif <dimat@...lanox.com>
CC: John W. Linville <linville@...driver.com>
Signed-off-by: Saeed Mahameed <saeedm@...lanox.com>
---
include/linux/ethtool.h | 1 +
include/uapi/linux/ethtool.h | 1 +
net/core/ethtool.c | 31 +++++++++++++++++++++++++++++++
3 files changed, 33 insertions(+)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 9ded8c6..c9f5d37 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -305,6 +305,7 @@ struct ethtool_ops {
void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);
int (*get_regs_len)(struct net_device *);
void (*get_regs)(struct net_device *, struct ethtool_regs *, void *);
+ int (*set_regs)(struct net_device *, struct ethtool_regs *, u8 *);
void (*get_wol)(struct net_device *, struct ethtool_wolinfo *);
int (*set_wol)(struct net_device *, struct ethtool_wolinfo *);
u32 (*get_msglevel)(struct net_device *);
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index f0db778..f81c6fd 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -1330,6 +1330,7 @@ struct ethtool_per_queue_op {
#define ETHTOOL_SLINKSETTINGS 0x0000004d /* Set ethtool_link_settings */
#define ETHTOOL_PHY_GTUNABLE 0x0000004e /* Get PHY tunable configuration */
#define ETHTOOL_PHY_STUNABLE 0x0000004f /* Set PHY tunable configuration */
+#define ETHTOOL_SREGS 0x00000050 /* Set NIC registers */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index e23766c..5548565 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1424,6 +1424,34 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
return ret;
}
+static int ethtool_set_regs(struct net_device *dev, char __user *useraddr)
+{
+ void __user *userbuf = useraddr + offsetof(struct ethtool_regs, data);
+ const struct ethtool_ops *ops = dev->ethtool_ops;
+ struct ethtool_regs regs;
+ int ret = 0;
+ u8 *data;
+
+ if (!ops->set_regs || !ops->get_regs_len)
+ return -EOPNOTSUPP;
+ if (copy_from_user(®s, useraddr, sizeof(regs)))
+ return -EFAULT;
+
+ data = kmalloc(PAGE_SIZE, GFP_USER);
+ if (!data)
+ return -ENOMEM;
+
+ ret = -EFAULT;
+ if (copy_from_user(data, userbuf, regs.len))
+ goto out;
+
+ ret = ops->set_regs(dev, ®s, data);
+
+out:
+ kfree(data);
+ return ret;
+}
+
static int ethtool_reset(struct net_device *dev, char __user *useraddr)
{
struct ethtool_value reset;
@@ -2597,6 +2625,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
case ETHTOOL_GREGS:
rc = ethtool_get_regs(dev, useraddr);
break;
+ case ETHTOOL_SREGS:
+ rc = ethtool_set_regs(dev, useraddr);
+ break;
case ETHTOOL_GWOL:
rc = ethtool_get_wol(dev, useraddr);
break;
--
2.7.4
Powered by blists - more mailing lists