* [RFC PATCH ethtool v2 00/23] ethtool netlink interface (userspace side) (WiP)
From: Michal Kubecek @ 2018-07-30 12:55 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, John W. Linville
(The series is based on v4.17)
This patch series is and ethtool counterpart to kernel series "ethtool
netlink interface (WiP)"; it's marked as "v2" to match kernel series
version even if I never really sent "v1" to the list. It's only an RFC
as the netlink API it implements is still only a proposal.
The series modifies ethtool to use the netlink based kernel API when
available. If not, it falls back to the ioctl API. The aim is to
preserve command line syntax (with few extensions) and preserve the
output as much as possible.
This brings a natural question: why? It would be certainly tempting to
start with a new tool without the limitations of the old command line
syntax and without having to immitatte strange artefacts of the past.
It may still come to that but experience with iproute2 shows even if you
provide a new tool with cleaner syntax, more features and better
organized output, 19 years later you may still meet (a lot of) people
still using the old tool and claiming they are not going to learn some
new tools with "strange syntax and incomprehensible output" (the sadest
part being that many of them haven't learn using ifconfig before it had
been already obsolete for ten years). That's why I tried to give this
approach at least a try.
As both parser and dump functions in current ethtool code are closely
tied to data structures used by ioctl API, only very little of existing
code could be reused. The parts used also by netlink code were moved to
common.h and common.c. New netlink related code resides in netlink/
subdirectory. Copies of kernel uapi headers were moved to uapi/
directory to make their status more apparent. Netlink code uses libmnl
for message composition and parsing.
Currently reimplemented functions are
-i / --driver
(no option)
-s
-k / --show-features / --show-offload
-K / --features / --offload
-c / --show-coalesce
-C / --coalesce
-g / --show-ring
-G / --set-ring
-a / --show-pause
-A / --pause
-l / --show-channels
-L / --set-channels
--show-eee
--set-eee
--show-fec
--set-fec
For all "get" type options, "*" can be used as device name to request
information about all interfaces supporting that request type.
The most interesting new feature is notification monitoring. When
started as
ethtool --monitor --all
ethtool will listen to netlink notifications and display information
about changes. Replacing "--all" with one of the options above will show
only notifications about changes related to that option. A device name
can be also used to display only notifications related to that device.
ToDo / open questions:
- the most important question still is if we want to reimplement ethtool
or come with a completely new utility instead
- if we go on with teaching ethtool netlink, another interesting
question is how closely we need to stick to current output and its
formatting; even if people are told not to, there are certainly tons
of scripts parsing ethtool output which may break on any change
- an example of this are legacy "flags" for netdev features; we will
have to make sure "ethtool -K dev tso off" will do what users expect
it to but can we get rid of them at least in "ethtool -k" output?
- having to say "--monitor -all" for monitoring all events while just
"--monitor" only watches for sset ("-s") type changes is probably
counterintuitive; would it be better to make "--all" default and leave
only "--monitor -s" for watching only "sset" events
Michal Kubecek (23):
move UAPI header copies to a separate directory
update UAPI header copies
netlink: add netlink interface
netlink: add support for string sets
netlink: add notification monitor
netlink: add netlink handler for gdrv (-i)
netlink: add netlink handler for gset (no option)
netlink: add helpers for command line parsing
netlink: add netlink handler for sset (-s)
netlink: add netlink handler for gfeatures (-k)
netlink: add netlink handler for sfeatures (-K)
netlink: add netlink handler for gcoalesce (-c)
netlink: add netlink handler for gring (-g)
netlink: add netlink handler for gpause (-a)
netlink: add netlink handler for gchannels (-l)
netlink: add netlink handler for geee (--show-eee)
netlink: add netlink handler for gfec (--show-fec)
netlink: add netlink handler for scoalesce (-C)
netlink: add netlink handler for sring (-G)
netlink: add netlink handler for spause (-A)
netlink: add netlink handler for schannels (-L)
netlink: add netlink handler for seee (--set-eee)
netlink: add netlink handler for sfec (--set-fec)
Makefile.am | 20 +-
common.c | 325 ++++++
common.h | 83 ++
configure.ac | 14 +-
ethtool.c | 437 +++-----
internal.h | 12 +-
netlink/drvinfo.c | 43 +
netlink/extapi.h | 37 +
netlink/monitor.c | 283 +++++
netlink/netlink.c | 681 ++++++++++++
netlink/netlink.h | 189 ++++
netlink/params.c | 659 +++++++++++
netlink/parser.c | 559 ++++++++++
netlink/parser.h | 49 +
netlink/settings.c | 1035 ++++++++++++++++++
netlink/strset.c | 265 +++++
netlink/strset.h | 16 +
ethtool-copy.h => uapi/linux/ethtool.h | 13 +-
uapi/linux/ethtool_netlink.h | 325 ++++++
uapi/linux/genetlink.h | 89 ++
net_tstamp-copy.h => uapi/linux/net_tstamp.h | 19 +
uapi/linux/netlink.h | 247 +++++
22 files changed, 5134 insertions(+), 266 deletions(-)
create mode 100644 common.c
create mode 100644 common.h
create mode 100644 netlink/drvinfo.c
create mode 100644 netlink/extapi.h
create mode 100644 netlink/monitor.c
create mode 100644 netlink/netlink.c
create mode 100644 netlink/netlink.h
create mode 100644 netlink/params.c
create mode 100644 netlink/parser.c
create mode 100644 netlink/parser.h
create mode 100644 netlink/settings.c
create mode 100644 netlink/strset.c
create mode 100644 netlink/strset.h
rename ethtool-copy.h => uapi/linux/ethtool.h (99%)
create mode 100644 uapi/linux/ethtool_netlink.h
create mode 100644 uapi/linux/genetlink.h
rename net_tstamp-copy.h => uapi/linux/net_tstamp.h (89%)
create mode 100644 uapi/linux/netlink.h
--
2.18.0
^ permalink raw reply
* [RFC PATCH net-next v2 17/17] ethtool: implement SET_PARAMS message
From: Michal Kubecek @ 2018-07-30 12:54 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>
Sets the information provided by ETHTOOL_SCOALESCE, ETHTOOL_SRINGPARAM,
ETHTOOL_SPAUSEPARAM, ETHTOOL_SCHANNELS, ETHTOOL_SEEE and ETHTOOL_SFECPARAM.
Each of these has corresponding nesting attribute containing attributes for
its settings. This way, userspace can request changes equivalent to one or
more of the legacy requests (and provide only part of the data to update).
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
Documentation/networking/ethtool-netlink.txt | 71 ++-
net/ethtool/netlink.c | 6 +
net/ethtool/params.c | 429 +++++++++++++++++++
3 files changed, 499 insertions(+), 7 deletions(-)
diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
index 630eebd7e741..2b70736110fe 100644
--- a/Documentation/networking/ethtool-netlink.txt
+++ b/Documentation/networking/ethtool-netlink.txt
@@ -126,7 +126,7 @@ List of message types
ETHNL_CMD_GET_SETTINGS
ETHNL_CMD_SET_SETTINGS
ETHNL_CMD_GET_PARAMS
- ETHNL_CMD_SET_PARAMS response only (for now)
+ ETHNL_CMD_SET_PARAMS
All constants use ETHNL_CMD_ prefix, usually followed by "GET", "SET" or "ACT"
to indicate the type.
@@ -408,6 +408,63 @@ to them are broadcasted as notifications on change of these settings using
netlink or ioctl ethtool interface.
+SET_PARAMS
+----------
+
+SET_PARAMS request modifies the settings retrieved by GET_PARAMS, i.e. it
+replaces ETHTOOL_SCOALESCE, ETHTOOL_SRINGPARAM, ETHTOOL_SPAUSEPARAM,
+ETHTOOL_SCHANNELS, ETHTOOL_SEEE and ETHTOOL_SFECPARAM legacy commands. For
+each of these, relevant data attributes are contained in a corresponding nest
+attribute. Some of the attributes provided by GET_SETPARAMS are read only and
+cannot be set by SET_PARAMS request.
+
+ ETHA_PARAMS_COALESCE (nest) coalescing
+ ETHA_COALESCE_RX_USECS (u32)
+ ETHA_COALESCE_RX_MAXFRM (u32)
+ ETHA_COALESCE_RX_USECS_IRQ (u32)
+ ETHA_COALESCE_RX_MAXFRM_IRQ (u32)
+ ETHA_COALESCE_RX_USECS_LOW (u32)
+ ETHA_COALESCE_RX_MAXFRM_LOW (u32)
+ ETHA_COALESCE_RX_USECS_HIGH (u32)
+ ETHA_COALESCE_RX_MAXFRM_HIGH (u32)
+ ETHA_COALESCE_TX_USECS (u32)
+ ETHA_COALESCE_TX_MAXFRM (u32)
+ ETHA_COALESCE_TX_USECS_IRQ (u32)
+ ETHA_COALESCE_TX_MAXFRM_IRQ (u32)
+ ETHA_COALESCE_TX_USECS_LOW (u32)
+ ETHA_COALESCE_TX_MAXFRM_LOW (u32)
+ ETHA_COALESCE_TX_USECS_HIGH (u32)
+ ETHA_COALESCE_TX_MAXFRM_HIGH (u32)
+ ETHA_COALESCE_PKT_RATE_LOW (u32)
+ ETHA_COALESCE_PKT_RATE_HIGH (u32)
+ ETHA_COALESCE_RX_USE_ADAPTIVE (bool)
+ ETHA_COALESCE_TX_USE_ADAPTIVE (bool)
+ ETHA_COALESCE_RATE_SAMPLE_INTERVAL (u32)
+ ETHA_COALESCE_STATS_BLOCK_USECS (u32)
+ ETHA_PARAMS_RING (nest) ring parameters
+ ETHA_RING_RX_PENDING (u32)
+ ETHA_RING_RX_MINI_PENDING (u32)
+ ETHA_RING_RX_JUMBO_PENDING (u32)
+ ETHA_RING_TX_PENDING (u32)
+ ETHA_PARAMS_PAUSE (nest) pause parameters
+ ETHA_PAUSE_AUTONEG (bool)
+ ETHA_PAUSE_RX (bool)
+ ETHA_PAUSE_TX (bool)
+ ETHA_PARAMS_CHANNELS (nest) channel settings
+ ETHA_CHANNELS_RX_COUNT (u32)
+ ETHA_CHANNELS_TX_COUNT (u32)
+ ETHA_CHANNELS_OTHER_COUNT (u32)
+ ETHA_CHANNELS_COMBINED_COUNT (u32)
+ ETHA_PARAMS_EEE (nest) EEE settings
+ ETHA_EEE_LINK_MODES (bitset)
+ - change modes for which EEE is advertised
+ ETHA_EEE_ENABLED (bool)
+ ETHA_EEE_TX_LPI_ENABLED (bool)
+ ETHA_EEE_TX_LPI_TIMER (u32)
+ ETHA_PARAMS_FEC (nest) FEC parameters
+ ETHA_FEC_MODES (bitfield32)
+ - change configured FEC encodings
+
Request translation
-------------------
@@ -431,11 +488,11 @@ ETHTOOL_GLINK ETHNL_CMD_GET_SETTINGS
ETHTOOL_GEEPROM n/a
ETHTOOL_SEEPROM n/a
ETHTOOL_GCOALESCE ETHNL_CMD_GET_PARAMS
-ETHTOOL_SCOALESCE n/a
+ETHTOOL_SCOALESCE ETHNL_CMD_SET_PARAMS
ETHTOOL_GRINGPARAM ETHNL_CMD_GET_PARAMS
-ETHTOOL_SRINGPARAM n/a
+ETHTOOL_SRINGPARAM ETHNL_CMD_SET_PARAMS
ETHTOOL_GPAUSEPARAM ETHNL_CMD_GET_PARAMS
-ETHTOOL_SPAUSEPARAM n/a
+ETHTOOL_SPAUSEPARAM ETHNL_CMD_SET_PARAMS
ETHTOOL_GRXCSUM ETHNL_CMD_GET_SETTINGS
ETHTOOL_SRXCSUM ETHNL_CMD_SET_SETTINGS
ETHTOOL_GTXCSUM ETHNL_CMD_GET_SETTINGS
@@ -477,7 +534,7 @@ ETHTOOL_SRXFHINDIR n/a
ETHTOOL_GFEATURES ETHNL_CMD_GET_SETTINGS
ETHTOOL_SFEATURES n/a
ETHTOOL_GCHANNELS ETHNL_CMD_GET_PARAMS
-ETHTOOL_SCHANNELS n/a
+ETHTOOL_SCHANNELS ETHNL_CMD_SET_PARAMS
ETHTOOL_SET_DUMP n/a
ETHTOOL_GET_DUMP_FLAG n/a
ETHTOOL_GET_DUMP_DATA n/a
@@ -485,7 +542,7 @@ ETHTOOL_GET_TS_INFO n/a
ETHTOOL_GMODULEINFO n/a
ETHTOOL_GMODULEEEPROM n/a
ETHTOOL_GEEE ETHNL_CMD_GET_PARAMS
-ETHTOOL_SEEE n/a
+ETHTOOL_SEEE ETHNL_CMD_SET_PARAMS
ETHTOOL_GRSSH n/a
ETHTOOL_SRSSH n/a
ETHTOOL_GTUNABLE n/a
@@ -497,5 +554,5 @@ ETHTOOL_SLINKSETTINGS ETHNL_CMD_SET_SETTINGS
ETHTOOL_PHY_GTUNABLE n/a
ETHTOOL_PHY_STUNABLE n/a
ETHTOOL_GFECPARAM ETHNL_CMD_GET_PARAMS
-ETHTOOL_SFECPARAM n/a
+ETHTOOL_SFECPARAM ETHNL_CMD_SET_PARAMS
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index b24a0e045ec0..17fee1ce077b 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -735,6 +735,7 @@ int ethnl_get_drvinfo(struct sk_buff *skb, struct genl_info *info);
int ethnl_get_settings(struct sk_buff *skb, struct genl_info *info);
int ethnl_set_settings(struct sk_buff *skb, struct genl_info *info);
int ethnl_get_params(struct sk_buff *skb, struct genl_info *info);
+int ethnl_set_params(struct sk_buff *skb, struct genl_info *info);
int ethnl_strset_start(struct netlink_callback *cb);
int ethnl_drvinfo_start(struct netlink_callback *cb);
@@ -778,6 +779,11 @@ static const struct genl_ops ethtool_genl_ops[] = {
.dumpit = ethnl_dumpit,
.done = ethnl_params_done,
},
+ {
+ .cmd = ETHNL_CMD_SET_PARAMS,
+ .flags = GENL_UNS_ADMIN_PERM,
+ .doit = ethnl_set_params,
+ },
};
static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
diff --git a/net/ethtool/params.c b/net/ethtool/params.c
index 773e13fc1ae6..8cbf33ad81b8 100644
--- a/net/ethtool/params.c
+++ b/net/ethtool/params.c
@@ -577,3 +577,432 @@ void ethnl_params_notify(struct netdev_notifier_ethtool_info *info)
err_skb:
nlmsg_free(skb);
}
+
+static const struct nla_policy coalesce_policy[ETHA_COALESCE_MAX + 1] = {
+ [ETHA_COALESCE_UNSPEC] = { .type = NLA_UNSPEC },
+ [ETHA_COALESCE_RX_USECS] = { .type = NLA_U32 },
+ [ETHA_COALESCE_RX_MAXFRM] = { .type = NLA_U32 },
+ [ETHA_COALESCE_RX_USECS_IRQ] = { .type = NLA_U32 },
+ [ETHA_COALESCE_RX_MAXFRM_IRQ] = { .type = NLA_U32 },
+ [ETHA_COALESCE_RX_USECS_LOW] = { .type = NLA_U32 },
+ [ETHA_COALESCE_RX_MAXFRM_LOW] = { .type = NLA_U32 },
+ [ETHA_COALESCE_RX_USECS_HIGH] = { .type = NLA_U32 },
+ [ETHA_COALESCE_RX_MAXFRM_HIGH] = { .type = NLA_U32 },
+ [ETHA_COALESCE_TX_USECS] = { .type = NLA_U32 },
+ [ETHA_COALESCE_TX_MAXFRM] = { .type = NLA_U32 },
+ [ETHA_COALESCE_TX_USECS_IRQ] = { .type = NLA_U32 },
+ [ETHA_COALESCE_TX_MAXFRM_IRQ] = { .type = NLA_U32 },
+ [ETHA_COALESCE_TX_USECS_LOW] = { .type = NLA_U32 },
+ [ETHA_COALESCE_TX_MAXFRM_LOW] = { .type = NLA_U32 },
+ [ETHA_COALESCE_TX_USECS_HIGH] = { .type = NLA_U32 },
+ [ETHA_COALESCE_TX_MAXFRM_HIGH] = { .type = NLA_U32 },
+ [ETHA_COALESCE_PKT_RATE_LOW] = { .type = NLA_U32 },
+ [ETHA_COALESCE_PKT_RATE_HIGH] = { .type = NLA_U32 },
+ [ETHA_COALESCE_RX_USE_ADAPTIVE] = { .type = NLA_U8 },
+ [ETHA_COALESCE_TX_USE_ADAPTIVE] = { .type = NLA_U8 },
+ [ETHA_COALESCE_RATE_SAMPLE_INTERVAL] = { .type = NLA_U32 },
+ [ETHA_COALESCE_STATS_BLOCK_USECS] = { .type = NLA_U32 },
+};
+
+static int update_coalesce(struct genl_info *info, struct net_device *dev,
+ struct nlattr *nest)
+{
+ struct nlattr *tb[ETHA_COALESCE_MAX + 1];
+ struct ethtool_coalesce data = {};
+ bool mod = false;
+ int ret;
+
+ if (!nest)
+ return 0;
+ if (!dev->ethtool_ops->get_coalesce || !dev->ethtool_ops->set_coalesce)
+ return -EOPNOTSUPP;
+ ret = dev->ethtool_ops->get_coalesce(dev, &data);
+ if (ret < 0)
+ return ret;
+
+ ret = nla_parse_nested(tb, ETHA_COALESCE_MAX, nest, coalesce_policy,
+ info->extack);
+ if (ret < 0)
+ return ret;
+
+ if (ethnl_update_u32(&data.rx_coalesce_usecs,
+ tb[ETHA_COALESCE_RX_USECS]))
+ mod = true;
+ if (ethnl_update_u32(&data.rx_max_coalesced_frames,
+ tb[ETHA_COALESCE_RX_MAXFRM]))
+ mod = true;
+ if (ethnl_update_u32(&data.rx_coalesce_usecs_irq,
+ tb[ETHA_COALESCE_RX_USECS_IRQ]))
+ mod = true;
+ if (ethnl_update_u32(&data.rx_max_coalesced_frames_irq,
+ tb[ETHA_COALESCE_RX_MAXFRM_IRQ]))
+ mod = true;
+ if (ethnl_update_u32(&data.rx_coalesce_usecs_low,
+ tb[ETHA_COALESCE_RX_USECS_LOW]))
+ mod = true;
+ if (ethnl_update_u32(&data.rx_max_coalesced_frames_low,
+ tb[ETHA_COALESCE_RX_MAXFRM_LOW]))
+ mod = true;
+ if (ethnl_update_u32(&data.rx_coalesce_usecs_high,
+ tb[ETHA_COALESCE_RX_USECS_HIGH]))
+ mod = true;
+ if (ethnl_update_u32(&data.rx_max_coalesced_frames_high,
+ tb[ETHA_COALESCE_RX_MAXFRM_HIGH]))
+ mod = true;
+ if (ethnl_update_u32(&data.tx_coalesce_usecs,
+ tb[ETHA_COALESCE_TX_USECS]))
+ mod = true;
+ if (ethnl_update_u32(&data.tx_max_coalesced_frames,
+ tb[ETHA_COALESCE_TX_MAXFRM]))
+ mod = true;
+ if (ethnl_update_u32(&data.tx_coalesce_usecs_irq,
+ tb[ETHA_COALESCE_TX_USECS_IRQ]))
+ mod = true;
+ if (ethnl_update_u32(&data.tx_max_coalesced_frames_irq,
+ tb[ETHA_COALESCE_TX_MAXFRM_IRQ]))
+ mod = true;
+ if (ethnl_update_u32(&data.tx_coalesce_usecs_low,
+ tb[ETHA_COALESCE_TX_USECS_LOW]))
+ mod = true;
+ if (ethnl_update_u32(&data.tx_max_coalesced_frames_low,
+ tb[ETHA_COALESCE_TX_MAXFRM_LOW]))
+ mod = true;
+ if (ethnl_update_u32(&data.tx_coalesce_usecs_high,
+ tb[ETHA_COALESCE_TX_USECS_HIGH]))
+ mod = true;
+ if (ethnl_update_u32(&data.tx_max_coalesced_frames_high,
+ tb[ETHA_COALESCE_TX_MAXFRM_HIGH]))
+ mod = true;
+ if (ethnl_update_u32(&data.pkt_rate_low,
+ tb[ETHA_COALESCE_PKT_RATE_LOW]))
+ mod = true;
+ if (ethnl_update_u32(&data.pkt_rate_high,
+ tb[ETHA_COALESCE_PKT_RATE_HIGH]))
+ mod = true;
+ if (ethnl_update_bool32(&data.use_adaptive_rx_coalesce,
+ tb[ETHA_COALESCE_RX_USE_ADAPTIVE]))
+ mod = true;
+ if (ethnl_update_bool32(&data.use_adaptive_tx_coalesce,
+ tb[ETHA_COALESCE_TX_USE_ADAPTIVE]))
+ mod = true;
+ if (ethnl_update_u32(&data.rate_sample_interval,
+ tb[ETHA_COALESCE_RATE_SAMPLE_INTERVAL]))
+ mod = true;
+ if (ethnl_update_u32(&data.stats_block_coalesce_usecs,
+ tb[ETHA_COALESCE_STATS_BLOCK_USECS]))
+ mod = true;
+
+ if (!mod)
+ return 0;
+ ret = dev->ethtool_ops->set_coalesce(dev, &data);
+ return (ret < 0) ? ret : 1;
+}
+
+static const struct nla_policy ring_policy[ETHA_RING_MAX + 1] = {
+ [ETHA_RING_UNSPEC] = { .type = NLA_UNSPEC },
+ [ETHA_RING_RX_MAX_PENDING] = { .type = NLA_U32 },
+ [ETHA_RING_RX_MINI_MAX_PENDING] = { .type = NLA_U32 },
+ [ETHA_RING_RX_JUMBO_MAX_PENDING] = { .type = NLA_U32 },
+ [ETHA_RING_TX_MAX_PENDING] = { .type = NLA_U32 },
+ [ETHA_RING_RX_PENDING] = { .type = NLA_U32 },
+ [ETHA_RING_RX_MINI_PENDING] = { .type = NLA_U32 },
+ [ETHA_RING_RX_JUMBO_PENDING] = { .type = NLA_U32 },
+ [ETHA_RING_TX_PENDING] = { .type = NLA_U32 },
+};
+
+static int update_ring(struct genl_info *info, struct net_device *dev,
+ struct nlattr *nest)
+{
+ struct nlattr *tb[ETHA_RING_MAX + 1];
+ struct ethtool_ringparam data = {};
+ bool mod = false;
+ int ret;
+
+ if (!nest)
+ return 0;
+ if (!dev->ethtool_ops->get_ringparam ||
+ !dev->ethtool_ops->set_ringparam)
+ return -EOPNOTSUPP;
+ dev->ethtool_ops->get_ringparam(dev, &data);
+
+ ret = nla_parse_nested(tb, ETHA_RING_MAX, nest, ring_policy,
+ info->extack);
+ if (ret < 0)
+ return ret;
+ /* read only attributes */
+ if (tb[ETHA_RING_RX_MAX_PENDING] || tb[ETHA_RING_RX_MINI_MAX_PENDING] ||
+ tb[ETHA_RING_RX_JUMBO_MAX_PENDING] ||
+ tb[ETHA_RING_TX_MAX_PENDING]) {
+ ETHNL_SET_ERRMSG(info, "attempt to set a read only attribute");
+ return -EINVAL;
+ }
+
+ if (ethnl_update_u32(&data.rx_pending, tb[ETHA_RING_RX_PENDING]))
+ mod = true;
+ if (ethnl_update_u32(&data.rx_mini_pending,
+ tb[ETHA_RING_RX_MINI_PENDING]))
+ mod = true;
+ if (ethnl_update_u32(&data.rx_jumbo_pending,
+ tb[ETHA_RING_RX_JUMBO_PENDING]))
+ mod = true;
+ if (ethnl_update_u32(&data.tx_pending, tb[ETHA_RING_TX_PENDING]))
+ mod = true;
+ if (!mod)
+ return 0;
+
+ /* ensure new ring parameters are within the maximums */
+ if (data.rx_pending > data.rx_max_pending ||
+ data.rx_mini_pending > data.rx_mini_max_pending ||
+ data.rx_jumbo_pending > data.rx_jumbo_max_pending ||
+ data.tx_pending > data.tx_max_pending) {
+ ETHNL_SET_ERRMSG(info,
+ "requested ring param value exceeeds maximum");
+ return -EINVAL;
+ }
+
+ ret = dev->ethtool_ops->set_ringparam(dev, &data);
+ return (ret < 0) ? ret : 1;
+}
+
+static const struct nla_policy pause_policy[ETHA_PAUSE_MAX + 1] = {
+ [ETHA_PAUSE_UNSPEC] = { .type = NLA_UNSPEC },
+ [ETHA_PAUSE_AUTONEG] = { .type = NLA_U8 },
+ [ETHA_PAUSE_RX] = { .type = NLA_U8 },
+ [ETHA_PAUSE_TX] = { .type = NLA_U8 },
+};
+
+static int update_pause(struct genl_info *info, struct net_device *dev,
+ struct nlattr *nest)
+{
+ struct nlattr *tb[ETHA_RING_MAX + 1];
+ struct ethtool_pauseparam data = {};
+ bool mod = false;
+ int ret;
+
+ if (!nest)
+ return 0;
+ if (!dev->ethtool_ops->get_pauseparam ||
+ !dev->ethtool_ops->set_pauseparam)
+ return -EOPNOTSUPP;
+ dev->ethtool_ops->get_pauseparam(dev, &data);
+
+ ret = nla_parse_nested(tb, ETHA_PAUSE_MAX, nest, pause_policy,
+ info->extack);
+ if (ret < 0)
+ return ret;
+
+ if (ethnl_update_u32(&data.autoneg, tb[ETHA_PAUSE_AUTONEG]))
+ mod = true;
+ if (ethnl_update_u32(&data.rx_pause, tb[ETHA_PAUSE_RX]))
+ mod = true;
+ if (ethnl_update_u32(&data.tx_pause, tb[ETHA_PAUSE_TX]))
+ mod = true;
+
+ if (!mod)
+ return 0;
+ ret = dev->ethtool_ops->set_pauseparam(dev, &data);
+ return (ret < 0) ? ret : 1;
+}
+
+static const struct nla_policy channels_policy[ETHA_CHANNELS_MAX + 1] = {
+ [ETHA_CHANNELS_UNSPEC] = { .type = NLA_UNSPEC },
+ [ETHA_CHANNELS_MAX_RX] = { .type = NLA_U32 },
+ [ETHA_CHANNELS_MAX_TX] = { .type = NLA_U32 },
+ [ETHA_CHANNELS_MAX_OTHER] = { .type = NLA_U32 },
+ [ETHA_CHANNELS_MAX_COMBINED] = { .type = NLA_U32 },
+ [ETHA_CHANNELS_RX_COUNT] = { .type = NLA_U32 },
+ [ETHA_CHANNELS_TX_COUNT] = { .type = NLA_U32 },
+ [ETHA_CHANNELS_OTHER_COUNT] = { .type = NLA_U32 },
+ [ETHA_CHANNELS_COMBINED_COUNT] = { .type = NLA_U32 },
+};
+
+static int update_channels(struct genl_info *info, struct net_device *dev,
+ struct nlattr *nest)
+{
+ struct nlattr *tb[ETHA_CHANNELS_MAX + 1];
+ struct ethtool_channels data = {};
+ bool mod = false;
+ int ret;
+
+ if (!nest)
+ return 0;
+ if (!dev->ethtool_ops->get_channels ||
+ !dev->ethtool_ops->set_channels)
+ return -EOPNOTSUPP;
+ dev->ethtool_ops->get_channels(dev, &data);
+
+ ret = nla_parse_nested(tb, ETHA_CHANNELS_MAX, nest, channels_policy,
+ info->extack);
+ if (ret < 0)
+ return ret;
+ /* read only attributes */
+ if (tb[ETHA_CHANNELS_MAX_RX] || tb[ETHA_CHANNELS_MAX_TX] ||
+ tb[ETHA_CHANNELS_MAX_OTHER] || tb[ETHA_CHANNELS_MAX_COMBINED]) {
+ ETHNL_SET_ERRMSG(info, "attempt to set a read only attribute");
+ return -EINVAL;
+ }
+
+ if (ethnl_update_u32(&data.rx_count, tb[ETHA_CHANNELS_RX_COUNT]))
+ mod = true;
+ if (ethnl_update_u32(&data.tx_count, tb[ETHA_CHANNELS_TX_COUNT]))
+ mod = true;
+ if (ethnl_update_u32(&data.other_count, tb[ETHA_CHANNELS_OTHER_COUNT]))
+ mod = true;
+ if (ethnl_update_u32(&data.combined_count,
+ tb[ETHA_CHANNELS_COMBINED_COUNT]))
+ mod = true;
+
+ if (!mod)
+ return 0;
+ ret = dev->ethtool_ops->set_channels(dev, &data);
+ return (ret < 0) ? ret : 1;
+}
+
+static const struct nla_policy eee_policy[ETHA_EEE_MAX + 1] = {
+ [ETHA_EEE_UNSPEC] = { .type = NLA_UNSPEC },
+ [ETHA_EEE_LINK_MODES] = { .type = NLA_NESTED },
+ [ETHA_EEE_PEER_MODES] = { .type = NLA_NESTED },
+ [ETHA_EEE_ACTIVE] = { .type = NLA_U8 },
+ [ETHA_EEE_ENABLED] = { .type = NLA_U8 },
+ [ETHA_EEE_TX_LPI_ENABLED] = { .type = NLA_U8 },
+ [ETHA_EEE_TX_LPI_TIMER] = { .type = NLA_U32 },
+};
+
+static int update_eee(struct genl_info *info, struct net_device *dev,
+ struct nlattr *nest)
+{
+ struct nlattr *tb[ETHA_EEE_MAX + 1];
+ struct ethtool_eee data = {};
+ bool mod = false;
+ int ret;
+
+ if (!nest)
+ return 0;
+ if (!dev->ethtool_ops->get_eee ||
+ !dev->ethtool_ops->set_eee)
+ return -EOPNOTSUPP;
+ ret = dev->ethtool_ops->get_eee(dev, &data);
+ if (ret < 0)
+ return ret;
+
+ ret = nla_parse_nested(tb, ETHA_EEE_MAX, nest, eee_policy,
+ info->extack);
+ if (ret < 0)
+ return ret;
+ /* read only attributes */
+ if (tb[ETHA_EEE_PEER_MODES] || tb[ETHA_EEE_ACTIVE]) {
+ ETHNL_SET_ERRMSG(info, "attempt to set a read only attribute");
+ return -EINVAL;
+ }
+
+ if (ethnl_update_bitset32(&data.advertised, NULL, 32,
+ tb[ETHA_EEE_LINK_MODES], &ret,
+ link_mode_names, info))
+ mod = true;
+ if (ret < 0)
+ return ret;
+ if (ethnl_update_bool32(&data.eee_enabled, tb[ETHA_EEE_ENABLED]))
+ mod = true;
+ if (ethnl_update_bool32(&data.tx_lpi_enabled,
+ tb[ETHA_EEE_TX_LPI_ENABLED]))
+ mod = true;
+ if (ethnl_update_u32(&data.tx_lpi_timer, tb[ETHA_EEE_TX_LPI_TIMER]))
+ mod = true;
+
+ if (!mod)
+ return 0;
+ ret = dev->ethtool_ops->set_eee(dev, &data);
+ return (ret < 0) ? ret : 1;
+}
+
+static const struct nla_policy fec_policy[ETHA_FEC_MAX + 1] = {
+ [ETHA_FEC_UNSPEC] = { .type = NLA_UNSPEC },
+ [ETHA_FEC_MODES] = { .type = NLA_U32 },
+};
+
+static int update_fec(struct genl_info *info, struct net_device *dev,
+ struct nlattr *nest)
+{
+ struct nlattr *tb[ETHA_FEC_MAX + 1];
+ struct ethtool_fecparam data = {};
+ bool mod = false;
+ int ret;
+
+ if (!nest)
+ return 0;
+ if (!dev->ethtool_ops->get_fecparam ||
+ !dev->ethtool_ops->set_fecparam)
+ return -EOPNOTSUPP;
+ ret = dev->ethtool_ops->get_fecparam(dev, &data);
+ if (ret < 0)
+ return ret;
+
+ ret = nla_parse_nested(tb, ETHA_FEC_MAX, nest, fec_policy,
+ info->extack);
+ if (ret < 0)
+ return ret;
+
+ if (ethnl_update_bitfield32(&data.fec, tb[ETHA_FEC_MODES]))
+ mod = true;
+
+ if (!mod)
+ return 0;
+ ret = dev->ethtool_ops->set_fecparam(dev, &data);
+ return (ret < 0) ? ret : 1;
+}
+
+int ethnl_set_params(struct sk_buff *skb, struct genl_info *info)
+{
+ struct nlattr *tb[ETHA_PARAMS_MAX + 1];
+ struct net_device *dev;
+ u32 req_mask = 0;
+ int ret;
+
+ ret = genlmsg_parse(info->nlhdr, ðtool_genl_family, tb,
+ ETHA_PARAMS_MAX, params_policy, info->extack);
+ if (ret < 0)
+ return ret;
+ dev = ethnl_dev_get(info, tb[ETHA_PARAMS_DEV]);
+ if (IS_ERR(dev))
+ return PTR_ERR(dev);
+ rtnl_lock();
+
+ ret = update_coalesce(info, dev, tb[ETHA_PARAMS_COALESCE]);
+ if (ret < 0)
+ goto out_unlock;
+ if (ret)
+ req_mask |= ETH_PARAMS_IM_COALESCE;
+ ret = update_ring(info, dev, tb[ETHA_PARAMS_RING]);
+ if (ret < 0)
+ goto out_unlock;
+ if (ret)
+ req_mask |= ETH_PARAMS_IM_RING;
+ ret = update_pause(info, dev, tb[ETHA_PARAMS_PAUSE]);
+ if (ret < 0)
+ goto out_unlock;
+ if (ret)
+ req_mask |= ETH_PARAMS_IM_PAUSE;
+ ret = update_channels(info, dev, tb[ETHA_PARAMS_CHANNELS]);
+ if (ret < 0)
+ goto out_unlock;
+ if (ret)
+ req_mask |= ETH_PARAMS_IM_CHANNELS;
+ ret = update_eee(info, dev, tb[ETHA_PARAMS_EEE]);
+ if (ret < 0)
+ goto out_unlock;
+ if (ret)
+ req_mask |= ETH_PARAMS_IM_EEE;
+ ret = update_fec(info, dev, tb[ETHA_PARAMS_FEC]);
+ if (ret < 0)
+ goto out_unlock;
+ if (ret)
+ req_mask |= ETH_PARAMS_IM_FEC;
+
+ ret = 0;
+out_unlock:
+ if (req_mask)
+ ethnl_notify(dev, NULL, ETHNL_CMD_SET_PARAMS, req_mask);
+ rtnl_unlock();
+ dev_put(dev);
+ return ret;
+}
--
2.18.0
^ permalink raw reply related
* [RFC PATCH net-next v2 15/17] ethtool: implement GET_PARAMS message
From: Michal Kubecek @ 2018-07-30 12:53 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>
Requests the information provide by ETHTOOL_GCOALESCE, ETHTOOL_GRINGPARAM,
ETHTOOL_GPAUSEPARAM, ETHTOOL_GCHANNELS, ETHTOOL_GEEE and ETHTOOL_GFECPARAM.
Flags in info_mask allow selecting only some (or on) of these categories.
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
Documentation/networking/ethtool-netlink.txt | 107 +++-
include/uapi/linux/ethtool_netlink.h | 119 ++++
net/ethtool/Makefile | 2 +-
net/ethtool/netlink.c | 10 +
net/ethtool/params.c | 539 +++++++++++++++++++
5 files changed, 770 insertions(+), 7 deletions(-)
create mode 100644 net/ethtool/params.c
diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
index 307d8c6c6c85..630eebd7e741 100644
--- a/Documentation/networking/ethtool-netlink.txt
+++ b/Documentation/networking/ethtool-netlink.txt
@@ -125,6 +125,8 @@ List of message types
ETHNL_CMD_SET_DRVINFO response only
ETHNL_CMD_GET_SETTINGS
ETHNL_CMD_SET_SETTINGS
+ ETHNL_CMD_GET_PARAMS
+ ETHNL_CMD_SET_PARAMS response only (for now)
All constants use ETHNL_CMD_ prefix, usually followed by "GET", "SET" or "ACT"
to indicate the type.
@@ -314,6 +316,99 @@ the operation); mask shows bits which have been changed and value their new
values.
+GET_PARAMS
+----------
+
+GET_PARAMS request retrieves information provided by legacy comands
+ETHTOOL_GCOALESCE (coalescing setting), ETHTOOL_GRINGPARAM (ring parameters),
+ETHTOOL_GPAUSEPARAM (pause parameters), ETHTOOL_GCHANNELS (channel settings),
+ETHTOOL_GEEE (EEE settings) and ETHTOOL_GFECPARAM (FEC parameters). For each
+of these, there is a bit in header info_mask so that only one type of
+information can be requested.
+
+Request contents:
+
+ ETHA_PARAMS_DEV (nested) device identification
+ ETHA_PARAMS_INFOMASK (u32) info mask
+ ETHA_PARAMS_COMPACT (flag) request compact bitsets
+
+Info mask bits:
+
+ ETH_PARAMS_IM_COALESCE coalescing settings
+ ETH_PARAMS_IM_RING ring parameters
+ ETH_PARAMS_IM_PAUSE pause parameters
+ ETH_PARAMS_IM_CHANNELS channel settings
+ ETH_PARAMS_IM_EEE EEE settings
+ ETH_PARAMS_IM_FEC FEC parameters
+
+Response contents: On top level, there is one attribute for each of the
+information categories, the information is nested in it.
+
+ ETHA_PARAMS_DEV (nested) device identification
+ ETHA_PARAMS_COALESCE (nested) coalescing
+ ETHA_COALESCE_RX_USECS (u32)
+ ETHA_COALESCE_RX_MAXFRM (u32)
+ ETHA_COALESCE_RX_USECS_IRQ (u32)
+ ETHA_COALESCE_RX_MAXFRM_IRQ (u32)
+ ETHA_COALESCE_RX_USECS_LOW (u32)
+ ETHA_COALESCE_RX_MAXFRM_LOW (u32)
+ ETHA_COALESCE_RX_USECS_HIGH (u32)
+ ETHA_COALESCE_RX_MAXFRM_HIGH (u32)
+ ETHA_COALESCE_TX_USECS (u32)
+ ETHA_COALESCE_TX_MAXFRM (u32)
+ ETHA_COALESCE_TX_USECS_IRQ (u32)
+ ETHA_COALESCE_TX_MAXFRM_IRQ (u32)
+ ETHA_COALESCE_TX_USECS_LOW (u32)
+ ETHA_COALESCE_TX_MAXFRM_LOW (u32)
+ ETHA_COALESCE_TX_USECS_HIGH (u32)
+ ETHA_COALESCE_TX_MAXFRM_HIGH (u32)
+ ETHA_COALESCE_PKT_RATE_LOW (u32)
+ ETHA_COALESCE_PKT_RATE_HIGH (u32)
+ ETHA_COALESCE_RX_USE_ADAPTIVE (bool)
+ ETHA_COALESCE_TX_USE_ADAPTIVE (bool)
+ ETHA_COALESCE_RATE_SAMPLE_INTERVAL (u32)
+ ETHA_COALESCE_STATS_BLOCK_USECS (u32)
+ ETHA_PARAMS_RING (nested) ring parameters
+ ETHA_RING_RX_MAX_PENDING (u32)
+ ETHA_RING_RX_MINI_MAX_PENDING (u32)
+ ETHA_RING_RX_JUMBO_MAX_PENDING (u32)
+ ETHA_RING_TX_MAX_PENDING (u32)
+ ETHA_RING_RX_PENDING (u32)
+ ETHA_RING_RX_MINI_PENDING (u32)
+ ETHA_RING_RX_JUMBO_PENDING (u32)
+ ETHA_RING_TX_PENDING (u32)
+ ETHA_PARAMS_PAUSE (nested) pause parameters
+ ETHA_PAUSE_AUTONEG (bool)
+ ETHA_PAUSE_RX (bool)
+ ETHA_PAUSE_TX (bool)
+ ETHA_PARAMS_CHANNELS (nested) channel settings
+ ETHA_CHANNELS_MAX_RX (u32)
+ ETHA_CHANNELS_MAX_TX (u32)
+ ETHA_CHANNELS_MAX_OTHER (u32)
+ ETHA_CHANNELS_MAX_COMBINED (u32)
+ ETHA_CHANNELS_RX_COUNT (u32)
+ ETHA_CHANNELS_TX_COUNT (u32)
+ ETHA_CHANNELS_OTHER_COUNT (u32)
+ ETHA_CHANNELS_COMBINED_COUNT (u32)
+ ETHA_PARAMS_EEE (nested) EEE settings
+ ETHA_EEE_LINK_MODES (bitset)
+ - modes for which EEE is advertised (value) or supported (mask)
+ ETHA_EEE_PEER_MODES (bitset)
+ - modes for which link partner advertises EEE
+ ETHA_EEE_ACTIVE (bool)
+ ETHA_EEE_ENABLED (bool)
+ ETHA_EEE_TX_LPI_ENABLED (bool)
+ ETHA_EEE_TX_LPI_TIMER (u32)
+ ETHA_PARAMS_FEC (nested) FEC parameters
+ ETHA_FEC_MODES (bitfield32)
+ - active (value) and configured (selector) FEC encodings
+
+GET_PARAMS requests allow dumps and messages in the same format as response
+to them are broadcasted as notifications on change of these settings using
+netlink or ioctl ethtool interface.
+
+
+
Request translation
-------------------
@@ -335,11 +430,11 @@ ETHTOOL_NWAY_RST n/a
ETHTOOL_GLINK ETHNL_CMD_GET_SETTINGS
ETHTOOL_GEEPROM n/a
ETHTOOL_SEEPROM n/a
-ETHTOOL_GCOALESCE n/a
+ETHTOOL_GCOALESCE ETHNL_CMD_GET_PARAMS
ETHTOOL_SCOALESCE n/a
-ETHTOOL_GRINGPARAM n/a
+ETHTOOL_GRINGPARAM ETHNL_CMD_GET_PARAMS
ETHTOOL_SRINGPARAM n/a
-ETHTOOL_GPAUSEPARAM n/a
+ETHTOOL_GPAUSEPARAM ETHNL_CMD_GET_PARAMS
ETHTOOL_SPAUSEPARAM n/a
ETHTOOL_GRXCSUM ETHNL_CMD_GET_SETTINGS
ETHTOOL_SRXCSUM ETHNL_CMD_SET_SETTINGS
@@ -381,7 +476,7 @@ ETHTOOL_GRXFHINDIR n/a
ETHTOOL_SRXFHINDIR n/a
ETHTOOL_GFEATURES ETHNL_CMD_GET_SETTINGS
ETHTOOL_SFEATURES n/a
-ETHTOOL_GCHANNELS n/a
+ETHTOOL_GCHANNELS ETHNL_CMD_GET_PARAMS
ETHTOOL_SCHANNELS n/a
ETHTOOL_SET_DUMP n/a
ETHTOOL_GET_DUMP_FLAG n/a
@@ -389,7 +484,7 @@ ETHTOOL_GET_DUMP_DATA n/a
ETHTOOL_GET_TS_INFO n/a
ETHTOOL_GMODULEINFO n/a
ETHTOOL_GMODULEEEPROM n/a
-ETHTOOL_GEEE n/a
+ETHTOOL_GEEE ETHNL_CMD_GET_PARAMS
ETHTOOL_SEEE n/a
ETHTOOL_GRSSH n/a
ETHTOOL_SRSSH n/a
@@ -401,6 +496,6 @@ ETHTOOL_GLINKSETTINGS ETHNL_CMD_GET_SETTINGS
ETHTOOL_SLINKSETTINGS ETHNL_CMD_SET_SETTINGS
ETHTOOL_PHY_GTUNABLE n/a
ETHTOOL_PHY_STUNABLE n/a
-ETHTOOL_GFECPARAM n/a
+ETHTOOL_GFECPARAM ETHNL_CMD_GET_PARAMS
ETHTOOL_SFECPARAM n/a
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index 8dfcb9ef4009..fec0f2000dc5 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -14,6 +14,8 @@ enum {
ETHNL_CMD_SET_DRVINFO, /* only for reply */
ETHNL_CMD_GET_SETTINGS,
ETHNL_CMD_SET_SETTINGS,
+ ETHNL_CMD_GET_PARAMS,
+ ETHNL_CMD_SET_PARAMS,
__ETHNL_CMD_MAX,
ETHNL_CMD_MAX = (__ETHNL_CMD_MAX - 1)
@@ -197,6 +199,123 @@ enum {
ETHA_FEATURES_MAX = (__ETHA_FEATURES_MAX - 1)
};
+/* GET_PARAMS / SET_PARAMS */
+
+enum {
+ ETHA_PARAMS_UNSPEC,
+ ETHA_PARAMS_DEV, /* nest - ETHA_DEV_* */
+ ETHA_PARAMS_INFOMASK, /* u32 */
+ ETHA_PARAMS_COMPACT, /* flag */
+ ETHA_PARAMS_COALESCE, /* nest - ETHA_COALESCE_* */
+ ETHA_PARAMS_RING, /* nest - ETHA_RING_* */
+ ETHA_PARAMS_PAUSE, /* nest - ETHA_PAUSE_* */
+ ETHA_PARAMS_CHANNELS, /* nest - ETHA_CHANNELS_* */
+ ETHA_PARAMS_EEE, /* nest - ETHA_EEE_* */
+ ETHA_PARAMS_FEC, /* nest - ETHA_FEC_* */
+
+ __ETHA_PARAMS_MAX,
+ ETHA_PARAMS_MAX = (__ETHA_PARAMS_MAX - 1)
+};
+
+#define ETH_PARAMS_IM_COALESCE 0x01
+#define ETH_PARAMS_IM_RING 0x02
+#define ETH_PARAMS_IM_PAUSE 0x04
+#define ETH_PARAMS_IM_CHANNELS 0x08
+#define ETH_PARAMS_IM_EEE 0x10
+#define ETH_PARAMS_IM_FEC 0x20
+
+#define ETH_PARAMS_IM_DEFAULT 0x3f
+
+enum {
+ ETHA_COALESCE_UNSPEC,
+ ETHA_COALESCE_RX_USECS, /* u32 */
+ ETHA_COALESCE_RX_MAXFRM, /* u32 */
+ ETHA_COALESCE_RX_USECS_IRQ, /* u32 */
+ ETHA_COALESCE_RX_MAXFRM_IRQ, /* u32 */
+ ETHA_COALESCE_RX_USECS_LOW, /* u32 */
+ ETHA_COALESCE_RX_MAXFRM_LOW, /* u32 */
+ ETHA_COALESCE_RX_USECS_HIGH, /* u32 */
+ ETHA_COALESCE_RX_MAXFRM_HIGH, /* u32 */
+ ETHA_COALESCE_TX_USECS, /* u32 */
+ ETHA_COALESCE_TX_MAXFRM, /* u32 */
+ ETHA_COALESCE_TX_USECS_IRQ, /* u32 */
+ ETHA_COALESCE_TX_MAXFRM_IRQ, /* u32 */
+ ETHA_COALESCE_TX_USECS_LOW, /* u32 */
+ ETHA_COALESCE_TX_MAXFRM_LOW, /* u32 */
+ ETHA_COALESCE_TX_USECS_HIGH, /* u32 */
+ ETHA_COALESCE_TX_MAXFRM_HIGH, /* u32 */
+ ETHA_COALESCE_PKT_RATE_LOW, /* u32 */
+ ETHA_COALESCE_PKT_RATE_HIGH, /* u32 */
+ ETHA_COALESCE_RX_USE_ADAPTIVE, /* u8 */
+ ETHA_COALESCE_TX_USE_ADAPTIVE, /* u8 */
+ ETHA_COALESCE_RATE_SAMPLE_INTERVAL, /* u32 */
+ ETHA_COALESCE_STATS_BLOCK_USECS, /* u32 */
+
+ __ETHA_COALESCE_MAX,
+ ETHA_COALESCE_MAX = (__ETHA_COALESCE_MAX - 1)
+};
+
+enum {
+ ETHA_RING_UNSPEC,
+ ETHA_RING_RX_MAX_PENDING, /* u32 */
+ ETHA_RING_RX_MINI_MAX_PENDING, /* u32 */
+ ETHA_RING_RX_JUMBO_MAX_PENDING, /* u32 */
+ ETHA_RING_TX_MAX_PENDING, /* u32 */
+ ETHA_RING_RX_PENDING, /* u32 */
+ ETHA_RING_RX_MINI_PENDING, /* u32 */
+ ETHA_RING_RX_JUMBO_PENDING, /* u32 */
+ ETHA_RING_TX_PENDING, /* u32 */
+
+ __ETHA_RING_MAX,
+ ETHA_RING_MAX = (__ETHA_RING_MAX - 1)
+};
+
+enum {
+ ETHA_PAUSE_UNSPEC,
+ ETHA_PAUSE_AUTONEG, /* u8 */
+ ETHA_PAUSE_RX, /* u8 */
+ ETHA_PAUSE_TX, /* u8 */
+
+ __ETHA_PAUSE_MAX,
+ ETHA_PAUSE_MAX = (__ETHA_PAUSE_MAX - 1)
+};
+
+enum {
+ ETHA_CHANNELS_UNSPEC,
+ ETHA_CHANNELS_MAX_RX, /* u32 */
+ ETHA_CHANNELS_MAX_TX, /* u32 */
+ ETHA_CHANNELS_MAX_OTHER, /* u32 */
+ ETHA_CHANNELS_MAX_COMBINED, /* u32 */
+ ETHA_CHANNELS_RX_COUNT, /* u32 */
+ ETHA_CHANNELS_TX_COUNT, /* u32 */
+ ETHA_CHANNELS_OTHER_COUNT, /* u32 */
+ ETHA_CHANNELS_COMBINED_COUNT, /* u32 */
+
+ __ETHA_CHANNELS_MAX,
+ ETHA_CHANNELS_MAX = (__ETHA_CHANNELS_MAX - 1)
+};
+
+enum {
+ ETHA_EEE_UNSPEC,
+ ETHA_EEE_LINK_MODES, /* bitset */
+ ETHA_EEE_PEER_MODES, /* bitset */
+ ETHA_EEE_ACTIVE, /* u8 */
+ ETHA_EEE_ENABLED, /* u8 */
+ ETHA_EEE_TX_LPI_ENABLED, /* u8 */
+ ETHA_EEE_TX_LPI_TIMER, /* u32 */
+
+ __ETHA_EEE_MAX,
+ ETHA_EEE_MAX = (__ETHA_EEE_MAX - 1)
+};
+
+enum {
+ ETHA_FEC_UNSPEC,
+ ETHA_FEC_MODES, /* bitfield32 */
+
+ __ETHA_FEC_MAX,
+ ETHA_FEC_MAX = (__ETHA_FEC_MAX - 1)
+};
+
/* generic netlink info */
#define ETHTOOL_GENL_NAME "ethtool"
#define ETHTOOL_GENL_VERSION 1
diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile
index 8dd98310ed6f..10aeedcee336 100644
--- a/net/ethtool/Makefile
+++ b/net/ethtool/Makefile
@@ -4,4 +4,4 @@ obj-y += ioctl.o common.o
obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o
-ethtool_nl-y := netlink.o strset.o drvinfo.o settings.o
+ethtool_nl-y := netlink.o strset.o drvinfo.o settings.o params.o
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 6e183caca01f..721101ed2ab6 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -731,13 +731,16 @@ int ethnl_get_strset(struct sk_buff *skb, struct genl_info *info);
int ethnl_get_drvinfo(struct sk_buff *skb, struct genl_info *info);
int ethnl_get_settings(struct sk_buff *skb, struct genl_info *info);
int ethnl_set_settings(struct sk_buff *skb, struct genl_info *info);
+int ethnl_get_params(struct sk_buff *skb, struct genl_info *info);
int ethnl_strset_start(struct netlink_callback *cb);
int ethnl_drvinfo_start(struct netlink_callback *cb);
int ethnl_settings_start(struct netlink_callback *cb);
+int ethnl_params_start(struct netlink_callback *cb);
int ethnl_strset_done(struct netlink_callback *cb);
int ethnl_settings_done(struct netlink_callback *cb);
+int ethnl_params_done(struct netlink_callback *cb);
static const struct genl_ops ethtool_genl_ops[] = {
{
@@ -765,6 +768,13 @@ static const struct genl_ops ethtool_genl_ops[] = {
.flags = GENL_UNS_ADMIN_PERM,
.doit = ethnl_set_settings,
},
+ {
+ .cmd = ETHNL_CMD_GET_PARAMS,
+ .doit = ethnl_get_params,
+ .start = ethnl_params_start,
+ .dumpit = ethnl_dumpit,
+ .done = ethnl_params_done,
+ },
};
static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
diff --git a/net/ethtool/params.c b/net/ethtool/params.c
new file mode 100644
index 000000000000..07d4c527abf2
--- /dev/null
+++ b/net/ethtool/params.c
@@ -0,0 +1,539 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#include "netlink.h"
+#include "common.h"
+
+static const struct nla_policy params_policy[ETHA_PARAMS_MAX + 1] = {
+ [ETHA_PARAMS_UNSPEC] = { .type = NLA_UNSPEC },
+ [ETHA_PARAMS_DEV] = { .type = NLA_NESTED },
+ [ETHA_PARAMS_INFOMASK] = { .type = NLA_U32 },
+ [ETHA_PARAMS_COMPACT] = { .type = NLA_FLAG },
+ [ETHA_PARAMS_COALESCE] = { .type = NLA_NESTED },
+ [ETHA_PARAMS_RING] = { .type = NLA_NESTED },
+ [ETHA_PARAMS_PAUSE] = { .type = NLA_NESTED },
+ [ETHA_PARAMS_CHANNELS] = { .type = NLA_NESTED },
+ [ETHA_PARAMS_EEE] = { .type = NLA_NESTED },
+ [ETHA_PARAMS_FEC] = { .type = NLA_NESTED },
+};
+
+struct params_data {
+ struct ethtool_coalesce coalesce;
+ struct ethtool_channels channels;
+ struct ethtool_pauseparam pause;
+ struct ethtool_ringparam ring;
+ struct ethtool_eee eee;
+ struct ethtool_fecparam fec;
+ u32 req_mask;
+};
+
+struct params_reqinfo {
+ struct net_device *dev;
+ u32 req_mask;
+ bool compact;
+ bool have_rtnl;
+};
+
+static int ethnl_get_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *data)
+{
+ if (!dev->ethtool_ops->get_coalesce)
+ return -EOPNOTSUPP;
+ return dev->ethtool_ops->get_coalesce(dev, data);
+}
+
+static int ethnl_get_ring(struct net_device *dev,
+ struct ethtool_ringparam *data)
+{
+ if (!dev->ethtool_ops->get_ringparam)
+ return -EOPNOTSUPP;
+ dev->ethtool_ops->get_ringparam(dev, data);
+ return 0;
+}
+
+static int ethnl_get_pause(struct net_device *dev,
+ struct ethtool_pauseparam *data)
+{
+ if (!dev->ethtool_ops->get_pauseparam)
+ return -EOPNOTSUPP;
+ dev->ethtool_ops->get_pauseparam(dev, data);
+ return 0;
+}
+
+static int ethnl_get_channels(struct net_device *dev,
+ struct ethtool_channels *data)
+{
+ if (!dev->ethtool_ops->get_channels)
+ return -EOPNOTSUPP;
+ dev->ethtool_ops->get_channels(dev, data);
+ return 0;
+}
+
+static int ethnl_get_eee(struct net_device *dev, struct ethtool_eee *data)
+{
+ if (!dev->ethtool_ops->get_eee)
+ return -EOPNOTSUPP;
+ return dev->ethtool_ops->get_eee(dev, data);
+}
+
+static int ethnl_get_fec(struct net_device *dev, struct ethtool_fecparam *data)
+{
+ if (!dev->ethtool_ops->get_fecparam)
+ return -EOPNOTSUPP;
+ return dev->ethtool_ops->get_fecparam(dev, data);
+}
+
+static int params_size(struct params_data *data,
+ struct params_reqinfo *req_info)
+{
+ struct ethtool_eee *eee = &data->eee;
+ u32 req_mask = req_info->req_mask;
+ bool compact = req_info->compact;
+ int len = 0;
+
+ if (req_mask & ETH_PARAMS_IM_COALESCE)
+ len += nla_total_size(20 * nla_total_size(sizeof(u32)) +
+ 2 * nla_total_size(sizeof(u8)));
+ if (req_mask & ETH_PARAMS_IM_RING)
+ len += nla_total_size(8 * nla_total_size(sizeof(u32)));
+ if (req_mask & ETH_PARAMS_IM_PAUSE)
+ len += nla_total_size(3 * nla_total_size(sizeof(u8)));
+ if (req_mask & ETH_PARAMS_IM_CHANNELS)
+ len += nla_total_size(8 * nla_total_size(sizeof(u32)));
+ if (req_mask & ETH_PARAMS_IM_EEE) {
+ int nlen = 0;
+ int ret;
+
+ /* link_modes */
+ ret = ethnl_bitset32_size(compact, sizeof(u32) * 8,
+ &eee->advertised, &eee->supported,
+ link_mode_names);
+ if (ret < 0)
+ return ret;
+ nlen += ret;
+ /* peer_modes */
+ ret = ethnl_bitset32_size(compact, sizeof(u32) * 8,
+ &eee->lp_advertised,
+ &eee->lp_advertised, link_mode_names);
+ if (ret < 0)
+ return ret;
+ nlen += ret;
+ /* active, enabled, tx_lpi_enabled */
+ nlen += 3 * nla_total_size(sizeof(u8));
+ /* tx_lpi_timer */
+ nlen += nla_total_size(sizeof(u32));
+ /* nest */
+ len += nla_total_size(nlen);
+ }
+ if (req_mask & ETH_PARAMS_IM_FEC) {
+ int nlen = nla_total_size(sizeof(struct nla_bitfield32));
+
+ len += nla_total_size(nlen);
+ }
+
+ return len;
+}
+
+static int fill_coalesce(struct sk_buff *skb, struct ethtool_coalesce *data)
+{
+ struct nlattr *nest = ethnl_nest_start(skb, ETHA_PARAMS_COALESCE);
+
+ if (!nest)
+ return -EMSGSIZE;
+ if (nla_put_u32(skb, ETHA_COALESCE_RX_USECS,
+ data->rx_coalesce_usecs) ||
+ nla_put_u32(skb, ETHA_COALESCE_RX_MAXFRM,
+ data->rx_max_coalesced_frames) ||
+ nla_put_u32(skb, ETHA_COALESCE_RX_USECS_IRQ,
+ data->rx_coalesce_usecs_irq) ||
+ nla_put_u32(skb, ETHA_COALESCE_RX_MAXFRM_IRQ,
+ data->rx_max_coalesced_frames_irq) ||
+ nla_put_u32(skb, ETHA_COALESCE_RX_USECS_LOW,
+ data->rx_coalesce_usecs_low) ||
+ nla_put_u32(skb, ETHA_COALESCE_RX_MAXFRM_LOW,
+ data->rx_max_coalesced_frames_low) ||
+ nla_put_u32(skb, ETHA_COALESCE_RX_USECS_HIGH,
+ data->rx_coalesce_usecs_high) ||
+ nla_put_u32(skb, ETHA_COALESCE_RX_MAXFRM_HIGH,
+ data->rx_max_coalesced_frames_high) ||
+ nla_put_u32(skb, ETHA_COALESCE_TX_USECS,
+ data->tx_coalesce_usecs) ||
+ nla_put_u32(skb, ETHA_COALESCE_TX_MAXFRM,
+ data->tx_max_coalesced_frames) ||
+ nla_put_u32(skb, ETHA_COALESCE_TX_USECS_IRQ,
+ data->tx_coalesce_usecs_irq) ||
+ nla_put_u32(skb, ETHA_COALESCE_TX_MAXFRM_IRQ,
+ data->tx_max_coalesced_frames_irq) ||
+ nla_put_u32(skb, ETHA_COALESCE_TX_USECS_LOW,
+ data->tx_coalesce_usecs_low) ||
+ nla_put_u32(skb, ETHA_COALESCE_TX_MAXFRM_LOW,
+ data->tx_max_coalesced_frames_low) ||
+ nla_put_u32(skb, ETHA_COALESCE_TX_USECS_HIGH,
+ data->tx_coalesce_usecs_high) ||
+ nla_put_u32(skb, ETHA_COALESCE_TX_MAXFRM_HIGH,
+ data->tx_max_coalesced_frames_high) ||
+ nla_put_u32(skb, ETHA_COALESCE_PKT_RATE_LOW,
+ data->pkt_rate_low) ||
+ nla_put_u32(skb, ETHA_COALESCE_PKT_RATE_HIGH,
+ data->pkt_rate_high) ||
+ nla_put_u8(skb, ETHA_COALESCE_RX_USE_ADAPTIVE,
+ !!data->use_adaptive_rx_coalesce) ||
+ nla_put_u8(skb, ETHA_COALESCE_TX_USE_ADAPTIVE,
+ !!data->use_adaptive_tx_coalesce) ||
+ nla_put_u32(skb, ETHA_COALESCE_RATE_SAMPLE_INTERVAL,
+ data->rate_sample_interval) ||
+ nla_put_u32(skb, ETHA_COALESCE_STATS_BLOCK_USECS,
+ data->stats_block_coalesce_usecs)) {
+ nla_nest_cancel(skb, nest);
+ return -EMSGSIZE;
+ }
+
+ nla_nest_end(skb, nest);
+ return 0;
+}
+
+static int fill_ring(struct sk_buff *skb, struct ethtool_ringparam *data)
+{
+ struct nlattr *nest = ethnl_nest_start(skb, ETHA_PARAMS_RING);
+
+ if (!nest)
+ return -EMSGSIZE;
+ if (nla_put_u32(skb, ETHA_RING_RX_MAX_PENDING,
+ data->rx_max_pending) ||
+ nla_put_u32(skb, ETHA_RING_RX_MINI_MAX_PENDING,
+ data->rx_mini_max_pending) ||
+ nla_put_u32(skb, ETHA_RING_RX_JUMBO_MAX_PENDING,
+ data->rx_jumbo_max_pending) ||
+ nla_put_u32(skb, ETHA_RING_TX_MAX_PENDING,
+ data->tx_max_pending) ||
+ nla_put_u32(skb, ETHA_RING_RX_PENDING,
+ data->rx_pending) ||
+ nla_put_u32(skb, ETHA_RING_RX_MINI_PENDING,
+ data->rx_mini_pending) ||
+ nla_put_u32(skb, ETHA_RING_RX_JUMBO_PENDING,
+ data->rx_jumbo_pending) ||
+ nla_put_u32(skb, ETHA_RING_TX_PENDING,
+ data->tx_pending)) {
+ nla_nest_cancel(skb, nest);
+ return -EMSGSIZE;
+ }
+
+ nla_nest_end(skb, nest);
+ return 0;
+}
+
+static int fill_pause(struct sk_buff *skb, struct ethtool_pauseparam *data)
+{
+ struct nlattr *nest = ethnl_nest_start(skb, ETHA_PARAMS_PAUSE);
+
+ if (!nest)
+ return -EMSGSIZE;
+ if (nla_put_u8(skb, ETHA_PAUSE_AUTONEG, !!data->autoneg) ||
+ nla_put_u8(skb, ETHA_PAUSE_RX, !!data->rx_pause) ||
+ nla_put_u8(skb, ETHA_PAUSE_TX, !!data->tx_pause)) {
+ nla_nest_cancel(skb, nest);
+ return -EMSGSIZE;
+ }
+
+ nla_nest_end(skb, nest);
+ return 0;
+}
+
+static int fill_channels(struct sk_buff *skb, struct ethtool_channels *data)
+{
+ struct nlattr *nest = ethnl_nest_start(skb, ETHA_PARAMS_CHANNELS);
+
+ if (!nest)
+ return -EMSGSIZE;
+ if (nla_put_u32(skb, ETHA_CHANNELS_MAX_RX, data->max_rx) ||
+ nla_put_u32(skb, ETHA_CHANNELS_MAX_TX, data->max_tx) ||
+ nla_put_u32(skb, ETHA_CHANNELS_MAX_OTHER, data->max_other) ||
+ nla_put_u32(skb, ETHA_CHANNELS_MAX_COMBINED, data->max_combined) ||
+ nla_put_u32(skb, ETHA_CHANNELS_RX_COUNT, data->rx_count) ||
+ nla_put_u32(skb, ETHA_CHANNELS_TX_COUNT, data->tx_count) ||
+ nla_put_u32(skb, ETHA_CHANNELS_OTHER_COUNT, data->other_count) ||
+ nla_put_u32(skb, ETHA_CHANNELS_COMBINED_COUNT,
+ data->combined_count)) {
+ return -EMSGSIZE;
+ }
+
+ nla_nest_end(skb, nest);
+ return 0;
+}
+
+static int fill_eee(struct sk_buff *skb, struct ethtool_eee *data, bool compact)
+{
+ struct nlattr *nest = ethnl_nest_start(skb, ETHA_PARAMS_EEE);
+ int ret;
+
+ if (!nest)
+ return -EMSGSIZE;
+ ret = ethnl_put_bitset32(skb, ETHA_EEE_LINK_MODES, compact,
+ sizeof(data->advertised) * 8,
+ &data->advertised, &data->supported,
+ link_mode_names);
+ if (ret < 0)
+ goto err;
+ ret = ethnl_put_bitset32(skb, ETHA_EEE_PEER_MODES, compact,
+ sizeof(data->advertised) * 8,
+ &data->lp_advertised, &data->lp_advertised,
+ link_mode_names);
+ if (ret < 0)
+ goto err;
+
+ if (nla_put_u8(skb, ETHA_EEE_ACTIVE, !!data->eee_active) ||
+ nla_put_u8(skb, ETHA_EEE_ENABLED, !!data->eee_enabled) ||
+ nla_put_u8(skb, ETHA_EEE_TX_LPI_ENABLED, !!data->tx_lpi_enabled) ||
+ nla_put_u32(skb, ETHA_EEE_TX_LPI_TIMER, data->tx_lpi_timer)) {
+ ret = -EMSGSIZE;
+ goto err;
+ }
+
+ nla_nest_end(skb, nest);
+ return 0;
+err:
+ nla_nest_cancel(skb, nest);
+ return ret;
+}
+
+static int fill_fec(struct sk_buff *skb, struct ethtool_fecparam *data)
+{
+ struct nlattr *nest = ethnl_nest_start(skb, ETHA_PARAMS_FEC);
+
+ if (!nest)
+ return -EMSGSIZE;
+ if (nla_put_bitfield32(skb, ETHA_FEC_MODES, data->active_fec,
+ data->fec)) {
+ nla_nest_cancel(skb, nest);
+ return -EMSGSIZE;
+ }
+
+ nla_nest_end(skb, nest);
+ return 0;
+}
+
+static int parse_params_req(struct params_reqinfo *req_info,
+ struct genl_info *info, struct sk_buff *skb,
+ const struct nlmsghdr *nlhdr)
+{
+ struct nlattr *tb[ETHA_PARAMS_MAX + 1];
+ int ret;
+
+ memset(req_info, '\0', sizeof(*req_info));
+
+ ret = genlmsg_parse(nlhdr, ðtool_genl_family, tb,
+ ETHA_PARAMS_MAX, params_policy,
+ info ? info->extack : NULL);
+ if (ret < 0)
+ return ret;
+
+ if (tb[ETHA_PARAMS_DEV]) {
+ req_info->dev = ethnl_dev_get(info, tb[ETHA_PARAMS_DEV]);
+ if (IS_ERR(req_info->dev)) {
+ ret = PTR_ERR(req_info->dev);
+ req_info->dev = NULL;
+ return ret;
+ }
+ }
+ if (tb[ETHA_PARAMS_INFOMASK])
+ req_info->req_mask = nla_get_u32(tb[ETHA_PARAMS_INFOMASK]);
+ if (tb[ETHA_PARAMS_COMPACT])
+ req_info->compact = true;
+ if (req_info->req_mask == 0)
+ req_info->req_mask = ETH_PARAMS_IM_DEFAULT;
+
+ return 0;
+}
+
+static int prepare_params(struct params_data *data,
+ struct params_reqinfo *req_info,
+ struct genl_info *info, struct net_device *dev)
+{
+ u32 req_mask = req_info->req_mask;
+ int ret;
+
+ memset(data, '\0', sizeof(*data));
+ if (!req_info->have_rtnl)
+ rtnl_lock();
+ if (req_mask & ETH_PARAMS_IM_COALESCE) {
+ ret = ethnl_get_coalesce(dev, &data->coalesce);
+ if (ret < 0) {
+ warn_partial_info(info);
+ req_mask &= ~ETH_PARAMS_IM_COALESCE;
+ }
+ }
+ if (req_mask & ETH_PARAMS_IM_RING) {
+ ret = ethnl_get_ring(dev, &data->ring);
+ if (ret < 0) {
+ warn_partial_info(info);
+ req_mask &= ~ETH_PARAMS_IM_RING;
+ }
+ }
+ if (req_mask & ETH_PARAMS_IM_PAUSE) {
+ ret = ethnl_get_pause(dev, &data->pause);
+ if (ret < 0) {
+ warn_partial_info(info);
+ req_mask &= ~ETH_PARAMS_IM_PAUSE;
+ }
+ }
+ if (req_mask & ETH_PARAMS_IM_CHANNELS) {
+ ret = ethnl_get_channels(dev, &data->channels);
+ if (ret < 0) {
+ warn_partial_info(info);
+ req_mask &= ~ETH_PARAMS_IM_CHANNELS;
+ }
+ }
+ if (req_mask & ETH_PARAMS_IM_EEE) {
+ ret = ethnl_get_eee(dev, &data->eee);
+ if (ret < 0) {
+ warn_partial_info(info);
+ req_mask &= ~ETH_PARAMS_IM_EEE;
+ }
+ }
+ if (req_mask & ETH_PARAMS_IM_FEC) {
+ ret = ethnl_get_fec(dev, &data->fec);
+ if (ret < 0) {
+ warn_partial_info(info);
+ req_mask &= ~ETH_PARAMS_IM_FEC;
+ }
+ }
+ if (!req_info->have_rtnl)
+ rtnl_unlock();
+
+ data->req_mask = req_mask;
+ return 0;
+}
+
+static int fill_params(struct sk_buff *rskb, struct params_data *data,
+ struct params_reqinfo *req_info)
+{
+ u32 req_mask = data->req_mask;
+ int ret;
+
+ if (req_mask & ETH_PARAMS_IM_COALESCE) {
+ ret = fill_coalesce(rskb, &data->coalesce);
+ if (ret < 0)
+ return ret;
+ }
+ if (req_mask & ETH_PARAMS_IM_RING) {
+ ret = fill_ring(rskb, &data->ring);
+ if (ret < 0)
+ return ret;
+ }
+ if (req_mask & ETH_PARAMS_IM_PAUSE) {
+ ret = fill_pause(rskb, &data->pause);
+ if (ret < 0)
+ return ret;
+ }
+ if (req_mask & ETH_PARAMS_IM_CHANNELS) {
+ ret = fill_channels(rskb, &data->channels);
+ if (ret < 0)
+ return ret;
+ }
+ if (req_mask & ETH_PARAMS_IM_EEE) {
+ ret = fill_eee(rskb, &data->eee, req_info->compact);
+ if (ret < 0)
+ return ret;
+ }
+ if (req_mask & ETH_PARAMS_IM_FEC) {
+ ret = fill_fec(rskb, &data->fec);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+int ethnl_get_params(struct sk_buff *skb, struct genl_info *info)
+{
+ struct params_data data;
+ struct params_reqinfo req_info;
+ struct sk_buff *rskb;
+ int reply_len;
+ void *ehdr;
+ int ret;
+
+ ret = parse_params_req(&req_info, info, skb, info->nlhdr);
+ if (ret < 0)
+ goto err_dev;
+ ret = prepare_params(&data, &req_info, info, req_info.dev);
+ if (ret < 0)
+ goto err_dev;
+ reply_len = params_size(&data, &req_info);
+ if (ret < 0)
+ goto err_dev;
+ ret = -ENOMEM;
+ rskb = ethnl_reply_init(reply_len, req_info.dev, ETHNL_CMD_SET_PARAMS,
+ ETHA_PARAMS_DEV, info, &ehdr);
+ if (!rskb)
+ goto err_dev;
+ ret = fill_params(rskb, &data, &req_info);
+ if (ret < 0)
+ goto err;
+
+ genlmsg_end(rskb, ehdr);
+ dev_put(req_info.dev);
+ return genlmsg_reply(rskb, info);
+
+err:
+ WARN_ONCE(ret == -EMSGSIZE,
+ "calculated message payload length (%d) not sufficient\n",
+ reply_len);
+ nlmsg_free(rskb);
+err_dev:
+ if (req_info.dev)
+ dev_put(req_info.dev);
+ return ret;
+}
+
+static int params_dump(struct sk_buff *skb, struct netlink_callback *cb,
+ struct net_device *dev)
+{
+ struct params_data data;
+ struct params_reqinfo *req_info;
+ int ret;
+
+ req_info = (struct params_reqinfo *)cb->args[4];
+ ret = prepare_params(&data, req_info, NULL, dev);
+ if (ret < 0)
+ return ret;
+ ret = ethnl_fill_dev(skb, dev, ETHA_PARAMS_DEV);
+ if (ret < 0)
+ return ret;
+ ret = fill_params(skb, &data, req_info);
+ return ret;
+}
+
+int ethnl_params_start(struct netlink_callback *cb)
+{
+ struct params_reqinfo *req_info;
+ int ret;
+
+ req_info = kmalloc(sizeof(*req_info), GFP_KERNEL);
+ if (!req_info)
+ return -ENOMEM;
+ ret = parse_params_req(req_info, NULL, cb->skb, cb->nlh);
+ if (ret < 0) {
+ if (req_info->dev)
+ dev_put(req_info->dev);
+ req_info->dev = NULL;
+ return ret;
+ }
+
+ cb->args[0] = (long)params_dump;
+ cb->args[1] = ETHNL_CMD_SET_PARAMS;
+ cb->args[4] = (long)req_info;
+
+ return 0;
+}
+
+int ethnl_params_done(struct netlink_callback *cb)
+{
+ struct params_reqinfo *req_info;
+
+ req_info = (struct params_reqinfo *)cb->args[4];
+ if (req_info->dev)
+ dev_put(req_info->dev);
+ kfree(req_info);
+
+ return 0;
+}
--
2.18.0
^ permalink raw reply related
* [RFC PATCH net-next v2 13/17] ethtool: implement SET_SETTINGS message
From: Michal Kubecek @ 2018-07-30 12:53 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>
Sets the information provided by ETHTOOL_SLINKSETTINGS, ETHTOOL_SWOL and
ETHTOOL_SMSGLVL. Unlike with ioctl(), userspace can send only some
attributes so that we only need to call ethtool_ops callbacks which we
really need (and the "set" callback is only called when we actually changed
some setting).
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
Documentation/networking/ethtool-netlink.txt | 43 +-
net/ethtool/netlink.c | 6 +
net/ethtool/settings.c | 495 +++++++++++++++++++
3 files changed, 539 insertions(+), 5 deletions(-)
diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
index 3993652f81a9..c7fe4f518972 100644
--- a/Documentation/networking/ethtool-netlink.txt
+++ b/Documentation/networking/ethtool-netlink.txt
@@ -124,7 +124,7 @@ List of message types
ETHNL_CMD_GET_DRVINFO
ETHNL_CMD_SET_DRVINFO response only
ETHNL_CMD_GET_SETTINGS
- ETHNL_CMD_SET_SETTINGS response only (for now)
+ ETHNL_CMD_SET_SETTINGS
All constants use ETHNL_CMD_ prefix, usually followed by "GET", "SET" or "ACT"
to indicate the type.
@@ -267,6 +267,39 @@ netlink or ioctl ethtool interface; feature notifications are also sent
whenever netdev_update_features() or netdev_change_features() is called.
+SET_SETTINGS
+------------
+
+SET_SETTINGS request allows setting some of the data reported by GET_SETTINGS.
+Request flags, info_mask and index are ignored. These attributes are allowed
+to be passed with SET_SETTINGS request:
+
+ ETHA_SETTINGS_DEV (nested) device identification
+ ETHA_SETTINGS_SPEED (u32) link speed (Mb/s)
+ ETHA_SETTINGS_DUPLEX (u8) duplex mode
+ ETHA_SETTINGS_PORT (u8) physical port
+ ETHA_SETTINGS_PHYADDR (u8) MDIO address of phy
+ ETHA_SETTINGS_AUTONEG (u8) autoneotiation status
+ ETHA_SETTINGS_TP_MDIX_CTRL (u8) MDI(-X) control
+ ETHA_SETTINGS_WOL_MODES (bitfield32) wake-on-lan modes
+ ETHA_SETTINGS_SOPASS (binary) SecureOn(tm) password
+ ETHA_SETTINGS_MSGLVL (bitfield32) debug level
+ ETHA_SETTINGS_LINK_MODES (bitset) device link modes
+
+For both bitfield32 types, value and selector work the usual way, i.e. bits
+set in selector are set to corresponding bits from value and the rest is
+preserved. In a similar fashion, ETHA_SETTINGS_LINK_MODES allows setting
+advertised link modes.
+
+If autonegotiation is on (either set now or kept from before), advertised
+modes are not changed (no ETHA_SETTINGS_LINK_MODES attribute) and at least one
+of speed and duplex is specified, kernel adjusts advertised modes to all
+supported modes matching speed, duplex or both (whatever is specified). This
+autoselection is done on ethtool side with ioctl interface, netlink interface
+is supposed to allow requesting changes without knowing what exactly kernel
+supports.
+
+
Request translation
-------------------
@@ -277,13 +310,13 @@ have their netlink replacement yet.
ioctl command netlink command
---------------------------------------------------------------------
ETHTOOL_GSET ETHNL_CMD_GET_SETTINGS
-ETHTOOL_SSET n/a
+ETHTOOL_SSET ETHNL_CMD_SET_SETTINGS
ETHTOOL_GDRVINFO ETHNL_CMD_GET_DRVINFO
ETHTOOL_GREGS n/a
ETHTOOL_GWOL ETHNL_CMD_GET_SETTINGS
-ETHTOOL_SWOL n/a
+ETHTOOL_SWOL ETHNL_CMD_SET_SETTINGS
ETHTOOL_GMSGLVL ETHNL_CMD_GET_SETTINGS
-ETHTOOL_SMSGLVL n/a
+ETHTOOL_SMSGLVL ETHNL_CMD_SET_SETTINGS
ETHTOOL_NWAY_RST n/a
ETHTOOL_GLINK ETHNL_CMD_GET_SETTINGS
ETHTOOL_GEEPROM n/a
@@ -351,7 +384,7 @@ ETHTOOL_STUNABLE n/a
ETHTOOL_GPHYSTATS n/a
ETHTOOL_PERQUEUE n/a
ETHTOOL_GLINKSETTINGS ETHNL_CMD_GET_SETTINGS
-ETHTOOL_SLINKSETTINGS n/a
+ETHTOOL_SLINKSETTINGS ETHNL_CMD_SET_SETTINGS
ETHTOOL_PHY_GTUNABLE n/a
ETHTOOL_PHY_STUNABLE n/a
ETHTOOL_GFECPARAM n/a
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 0e2158092a44..6e183caca01f 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -730,6 +730,7 @@ static struct notifier_block ethnl_netdev_notifier = {
int ethnl_get_strset(struct sk_buff *skb, struct genl_info *info);
int ethnl_get_drvinfo(struct sk_buff *skb, struct genl_info *info);
int ethnl_get_settings(struct sk_buff *skb, struct genl_info *info);
+int ethnl_set_settings(struct sk_buff *skb, struct genl_info *info);
int ethnl_strset_start(struct netlink_callback *cb);
int ethnl_drvinfo_start(struct netlink_callback *cb);
@@ -759,6 +760,11 @@ static const struct genl_ops ethtool_genl_ops[] = {
.dumpit = ethnl_dumpit,
.done = ethnl_settings_done,
},
+ {
+ .cmd = ETHNL_CMD_SET_SETTINGS,
+ .flags = GENL_UNS_ADMIN_PERM,
+ .doit = ethnl_set_settings,
+ },
};
static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
diff --git a/net/ethtool/settings.c b/net/ethtool/settings.c
index 739bd006c924..678199e621a2 100644
--- a/net/ethtool/settings.c
+++ b/net/ethtool/settings.c
@@ -88,6 +88,222 @@ struct settings_reqinfo {
bool have_rtnl;
};
+struct link_mode_info {
+ int speed;
+ u8 duplex;
+};
+
+static const struct link_mode_info link_mode_params[] = {
+ [ETHTOOL_LINK_MODE_10baseT_Half_BIT] = {
+ .speed = 10,
+ .duplex = DUPLEX_HALF,
+ },
+ [ETHTOOL_LINK_MODE_10baseT_Full_BIT] = {
+ .speed = 10,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_100baseT_Half_BIT] = {
+ .speed = 100,
+ .duplex = DUPLEX_HALF,
+ },
+ [ETHTOOL_LINK_MODE_100baseT_Full_BIT] = {
+ .speed = 100,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_1000baseT_Half_BIT] = {
+ .speed = 1000,
+ .duplex = DUPLEX_HALF,
+ },
+ [ETHTOOL_LINK_MODE_1000baseT_Full_BIT] = {
+ .speed = 1000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_Autoneg_BIT] = {
+ .speed = SPEED_UNKNOWN,
+ .duplex = DUPLEX_UNKNOWN,
+ },
+ [ETHTOOL_LINK_MODE_TP_BIT] = {
+ .speed = SPEED_UNKNOWN,
+ .duplex = DUPLEX_UNKNOWN,
+ },
+ [ETHTOOL_LINK_MODE_AUI_BIT] = {
+ .speed = SPEED_UNKNOWN,
+ .duplex = DUPLEX_UNKNOWN,
+ },
+ [ETHTOOL_LINK_MODE_MII_BIT] = {
+ .speed = SPEED_UNKNOWN,
+ .duplex = DUPLEX_UNKNOWN,
+ },
+ [ETHTOOL_LINK_MODE_FIBRE_BIT] = {
+ .speed = SPEED_UNKNOWN,
+ .duplex = DUPLEX_UNKNOWN,
+ },
+ [ETHTOOL_LINK_MODE_BNC_BIT] = {
+ .speed = SPEED_UNKNOWN,
+ .duplex = DUPLEX_UNKNOWN,
+ },
+ [ETHTOOL_LINK_MODE_10000baseT_Full_BIT] = {
+ .speed = 10000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_Pause_BIT] = {
+ .speed = SPEED_UNKNOWN,
+ .duplex = DUPLEX_UNKNOWN,
+ },
+ [ETHTOOL_LINK_MODE_Asym_Pause_BIT] = {
+ .speed = SPEED_UNKNOWN,
+ .duplex = DUPLEX_UNKNOWN,
+ },
+ [ETHTOOL_LINK_MODE_2500baseX_Full_BIT] = {
+ .speed = 2500,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_Backplane_BIT] = {
+ .speed = SPEED_UNKNOWN,
+ .duplex = DUPLEX_UNKNOWN,
+ },
+ [ETHTOOL_LINK_MODE_1000baseKX_Full_BIT] = {
+ .speed = 1000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT] = {
+ .speed = 10000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_10000baseKR_Full_BIT] = {
+ .speed = 10000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_10000baseR_FEC_BIT] = {
+ .speed = 10000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT] = {
+ .speed = 20000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT] = {
+ .speed = 20000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT] = {
+ .speed = 40000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT] = {
+ .speed = 40000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT] = {
+ .speed = 40000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT] = {
+ .speed = 40000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT] = {
+ .speed = 56000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT] = {
+ .speed = 56000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT] = {
+ .speed = 56000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT] = {
+ .speed = 56000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_25000baseCR_Full_BIT] = {
+ .speed = 25000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_25000baseKR_Full_BIT] = {
+ .speed = 25000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_25000baseSR_Full_BIT] = {
+ .speed = 25000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT] = {
+ .speed = 50000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT] = {
+ .speed = 50000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT] = {
+ .speed = 100000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT] = {
+ .speed = 100000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT] = {
+ .speed = 100000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT] = {
+ .speed = 100000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT] = {
+ .speed = 50000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_1000baseX_Full_BIT] = {
+ .speed = 1000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_10000baseCR_Full_BIT] = {
+ .speed = 10000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_10000baseSR_Full_BIT] = {
+ .speed = 10000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_10000baseLR_Full_BIT] = {
+ .speed = 10000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT] = {
+ .speed = 10000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_10000baseER_Full_BIT] = {
+ .speed = 10000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_2500baseT_Full_BIT] = {
+ .speed = 2500,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_5000baseT_Full_BIT] = {
+ .speed = 5000,
+ .duplex = DUPLEX_FULL,
+ },
+ [ETHTOOL_LINK_MODE_FEC_NONE_BIT] = {
+ .speed = SPEED_UNKNOWN,
+ .duplex = DUPLEX_UNKNOWN,
+ },
+ [ETHTOOL_LINK_MODE_FEC_RS_BIT] = {
+ .speed = SPEED_UNKNOWN,
+ .duplex = DUPLEX_UNKNOWN,
+ },
+ [ETHTOOL_LINK_MODE_FEC_BASER_BIT] = {
+ .speed = SPEED_UNKNOWN,
+ .duplex = DUPLEX_UNKNOWN,
+ },
+};
+
/* We want to allow ~0 as selector for backward compatibility (to just set
* given set of modes, whatever kernel supports) so that we allow all bits
* on validation and do our own sanity check later.
@@ -606,3 +822,282 @@ void ethnl_settings_notify(struct netdev_notifier_ethtool_info *info)
err_skb:
nlmsg_free(skb);
}
+
+/* SET_SETTINGS */
+
+static int ethnl_set_link_ksettings(struct genl_info *info,
+ struct net_device *dev,
+ struct ethtool_link_ksettings *ksettings)
+{
+ int ret = dev->ethtool_ops->set_link_ksettings(dev, ksettings);
+
+ if (ret < 0)
+ ETHNL_SET_ERRMSG(info, "link settings update failed");
+ return ret;
+}
+
+static int ethnl_set_legacy_settings(struct genl_info *info,
+ struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ int ret;
+
+ if (!dev->ethtool_ops->set_settings) {
+ /* we already tried ->set_link_ksettings */
+ ETHNL_SET_ERRMSG(info, "link settings update unsupported");
+ return -EOPNOTSUPP;
+ }
+ ret = dev->ethtool_ops->set_settings(dev, cmd);
+ if (ret < 0)
+ ETHNL_SET_ERRMSG(info, "link settings update failed");
+
+ return ret;
+}
+
+static int ethnl_set_wol(struct genl_info *info, struct net_device *dev,
+ struct ethtool_wolinfo *wolinfo)
+{
+ int ret = dev->ethtool_ops->set_wol(dev, wolinfo);
+
+ if (ret < 0)
+ ETHNL_SET_ERRMSG(info, "wol info update failed");
+ return ret;
+}
+
+/* Set advertised link modes to all supported modes matching requested speed
+ * and duplex values. Called when autonegotiation is on, speed or duplex is
+ * requested but no link mode change. This is done in userspace with ioctl()
+ * interface, move it into kernel for netlink.
+ * Returns true if advertised modes bitmap was modified.
+ */
+static bool auto_link_modes(unsigned long *supported,
+ unsigned long *advertising, unsigned int nbits,
+ struct nlattr *speed_attr,
+ struct nlattr *duplex_attr)
+{
+ u8 duplex = duplex_attr ? nla_get_u8(duplex_attr) : DUPLEX_UNKNOWN;
+ u32 speed = speed_attr ? nla_get_u32(speed_attr) : SPEED_UNKNOWN;
+ DECLARE_BITMAP(old_adv, nbits);
+ unsigned int i;
+
+ bitmap_copy(old_adv, advertising, nbits);
+
+ for (i = 0; i < nbits; i++) {
+ const struct link_mode_info *info = &link_mode_params[i];
+
+ if (info->speed == SPEED_UNKNOWN)
+ continue;
+ if (test_bit(i, supported) &&
+ (!speed_attr || info->speed == speed) &&
+ (!duplex_attr || info->duplex == duplex))
+ set_bit(i, advertising);
+ else
+ clear_bit(i, advertising);
+ }
+
+ return !bitmap_equal(old_adv, advertising, nbits);
+}
+
+/* Update device settings using ->set_link_ksettings() callback */
+static int ethnl_update_ksettings(struct genl_info *info, struct nlattr **tb,
+ struct net_device *dev)
+{
+ struct ethtool_link_ksettings ksettings = {};
+ struct ethtool_link_settings *lsettings;
+ bool mod = false;
+ int ret;
+
+ ret = ethnl_get_link_ksettings(info, dev, &ksettings);
+ if (ret < 0)
+ return ret;
+ lsettings = &ksettings.base;
+
+ mod = false;
+ if (ethnl_update_u32(&lsettings->speed, tb[ETHA_SETTINGS_SPEED]))
+ mod = true;
+ if (ethnl_update_u8(&lsettings->duplex, tb[ETHA_SETTINGS_DUPLEX]))
+ mod = true;
+ if (ethnl_update_u8(&lsettings->port, tb[ETHA_SETTINGS_PORT]))
+ mod = true;
+ if (ethnl_update_u8(&lsettings->phy_address, tb[ETHA_SETTINGS_PHYADDR]))
+ mod = true;
+ if (ethnl_update_u8(&lsettings->autoneg, tb[ETHA_SETTINGS_AUTONEG]))
+ mod = true;
+ if (ethnl_update_u8(&lsettings->eth_tp_mdix_ctrl,
+ tb[ETHA_SETTINGS_TP_MDIX_CTRL]))
+ mod = true;
+ if (ethnl_update_bitset(ksettings.link_modes.advertising, NULL,
+ __ETHTOOL_LINK_MODE_MASK_NBITS,
+ tb[ETHA_SETTINGS_LINK_MODES],
+ &ret, link_mode_names, info))
+ mod = true;
+ if (ret < 0)
+ return ret;
+
+ if (!tb[ETHA_SETTINGS_LINK_MODES] && lsettings->autoneg &&
+ (tb[ETHA_SETTINGS_SPEED] || tb[ETHA_SETTINGS_DUPLEX])) {
+ if (auto_link_modes(ksettings.link_modes.supported,
+ ksettings.link_modes.advertising,
+ __ETHTOOL_LINK_MODE_MASK_NBITS,
+ tb[ETHA_SETTINGS_SPEED],
+ tb[ETHA_SETTINGS_DUPLEX]))
+ mod = true;
+ }
+
+ if (mod) {
+ ret = ethnl_set_link_ksettings(info, dev, &ksettings);
+ if (ret < 0)
+ return ret;
+ }
+
+ return mod ? 1 : 0;
+}
+
+/* Update legacy settings using ->set_settings() callback. */
+static int ethnl_update_lsettings(struct genl_info *info, struct nlattr **tb,
+ struct net_device *dev)
+{
+ struct ethtool_cmd cmd = {};
+ const unsigned int nbits = sizeof(cmd.advertising) * BITS_PER_BYTE;
+ DECLARE_BITMAP(advertising, nbits);
+ DECLARE_BITMAP(supported, nbits);
+ bool mod = false;
+ u32 speed;
+ int ret;
+
+ ret = ethnl_get_legacy_settings(info, dev, &cmd);
+ if (ret < 0)
+ return ret;
+ bitmap_from_arr32(supported, &cmd.supported, nbits);
+ bitmap_from_arr32(advertising, &cmd.advertising, nbits);
+
+ mod = false;
+ speed = ethtool_cmd_speed(&cmd);
+ if (ethnl_update_u32(&speed, tb[ETHA_SETTINGS_SPEED])) {
+ ethtool_cmd_speed_set(&cmd, speed);
+ mod = true;
+ }
+ if (ethnl_update_u8(&cmd.duplex, tb[ETHA_SETTINGS_DUPLEX]))
+ mod = true;
+ if (ethnl_update_u8(&cmd.port, tb[ETHA_SETTINGS_PORT]))
+ mod = true;
+ if (ethnl_update_u8(&cmd.phy_address, tb[ETHA_SETTINGS_PHYADDR]))
+ mod = true;
+ if (ethnl_update_u8(&cmd.autoneg, tb[ETHA_SETTINGS_AUTONEG]))
+ mod = true;
+ if (ethnl_update_u8(&cmd.eth_tp_mdix_ctrl,
+ tb[ETHA_SETTINGS_TP_MDIX_CTRL]))
+ mod = true;
+ if (ethnl_update_bitset(advertising, NULL, nbits,
+ tb[ETHA_SETTINGS_LINK_MODES],
+ &ret, link_mode_names, info)) {
+ bitmap_to_arr32(&cmd.advertising, advertising, nbits);
+ mod = true;
+ }
+ if (ret < 0)
+ return ret;
+
+ if (!tb[ETHA_SETTINGS_LINK_MODES] && cmd.autoneg &&
+ (tb[ETHA_SETTINGS_SPEED] || tb[ETHA_SETTINGS_DUPLEX])) {
+ if (auto_link_modes(supported, advertising, nbits,
+ tb[ETHA_SETTINGS_SPEED],
+ tb[ETHA_SETTINGS_DUPLEX])) {
+ bitmap_to_arr32(&cmd.advertising, advertising, nbits);
+ mod = true;
+ }
+ }
+
+ if (mod) {
+ ret = ethnl_set_legacy_settings(info, dev, &cmd);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+int ethnl_set_settings(struct sk_buff *skb, struct genl_info *info)
+{
+ struct nlattr *tb[ETHA_SETTINGS_MAX + 1];
+ struct ethtool_wolinfo wolinfo = {};
+ struct net_device *dev;
+ u32 req_mask = 0;
+ bool mod;
+ int ret;
+
+ ret = genlmsg_parse(info->nlhdr, ðtool_genl_family, tb,
+ ETHA_SETTINGS_MAX, settings_policy, info->extack);
+ if (ret < 0)
+ return ret;
+ dev = ethnl_dev_get(info, tb[ETHA_SETTINGS_DEV]);
+ if (IS_ERR(dev))
+ return PTR_ERR(dev);
+ rtnl_lock();
+
+ /* read only attributes */
+ ret = -EINVAL;
+ if (tb[ETHA_SETTINGS_MDIO_SUPPORT] || tb[ETHA_SETTINGS_TP_MDIX] ||
+ tb[ETHA_SETTINGS_TRANSCEIVER] || tb[ETHA_SETTINGS_PEER_MODES] ||
+ tb[ETHA_SETTINGS_LINK]) {
+ ETHNL_SET_ERRMSG(info, "attempt to set a read only attribute");
+ goto out_unlock;
+ }
+
+ if (tb[ETHA_SETTINGS_SPEED] || tb[ETHA_SETTINGS_DUPLEX] ||
+ tb[ETHA_SETTINGS_PORT] || tb[ETHA_SETTINGS_PHYADDR] ||
+ tb[ETHA_SETTINGS_AUTONEG] || tb[ETHA_SETTINGS_TP_MDIX_CTRL] ||
+ tb[ETHA_SETTINGS_LINK_MODES]) {
+ if (dev->ethtool_ops->get_link_ksettings)
+ ret = ethnl_update_ksettings(info, tb, dev);
+ else
+ ret = ethnl_update_lsettings(info, tb, dev);
+ if (ret < 0)
+ goto out_unlock;
+ req_mask |= ETH_SETTINGS_IM_LINKINFO |
+ ETH_SETTINGS_IM_LINKMODES;
+ }
+ if (tb[ETHA_SETTINGS_WOL_MODES] || tb[ETHA_SETTINGS_SOPASS]) {
+ ret = ethnl_get_wol(info, dev, &wolinfo);
+ if (ret < 0)
+ goto out_unlock;
+
+ mod = false;
+ if (ethnl_update_bitfield32(&wolinfo.wolopts,
+ tb[ETHA_SETTINGS_WOL_MODES]))
+ mod = true;
+ if (ethnl_update_binary(wolinfo.sopass, SOPASS_MAX,
+ tb[ETHA_SETTINGS_SOPASS]))
+ mod = true;
+ if (mod) {
+ ret = ethnl_set_wol(info, dev, &wolinfo);
+ if (ret < 0)
+ goto out_unlock;
+ req_mask |= ETH_SETTINGS_IM_WOLINFO;
+ }
+ }
+ if (tb[ETHA_SETTINGS_MSGLVL]) {
+ u32 msglvl;
+
+ ret = -EOPNOTSUPP;
+ if (!dev->ethtool_ops->get_msglevel ||
+ !dev->ethtool_ops->set_msglevel) {
+ ETHNL_SET_ERRMSG(info,
+ "device does not provide msglvl access");
+ goto out_unlock;
+ }
+ msglvl = dev->ethtool_ops->get_msglevel(dev);
+ if (ethnl_update_bitfield32(&msglvl,
+ tb[ETHA_SETTINGS_MSGLVL])) {
+ dev->ethtool_ops->set_msglevel(dev, msglvl);
+ req_mask |= ETH_SETTINGS_IM_MSGLEVEL;
+ }
+ }
+ ret = 0;
+
+out_unlock:
+ if (req_mask)
+ ethnl_notify(dev, NULL, ETHNL_CMD_SET_SETTINGS, req_mask);
+ rtnl_unlock();
+ dev_put(dev);
+ return ret;
+}
--
2.18.0
^ permalink raw reply related
* [RFC PATCH net-next v2 12/17] ethtool: implement SET_SETTINGS notification
From: Michal Kubecek @ 2018-07-30 12:53 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>
SET_SETTINGS notification message has the same format as response to
GET_SETTINGS request and is broadcasted on change of relevant fields. Info
mask can be used to limit the information passed to userspace.
Also trigger the notification on analogous changes performed via the legacy
ioctl interface.
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
Documentation/networking/ethtool-netlink.txt | 3 +-
net/core/dev.c | 3 ++
net/ethtool/ioctl.c | 36 +++++++++++++++--
net/ethtool/netlink.c | 2 +
net/ethtool/settings.c | 41 ++++++++++++++++++++
5 files changed, 80 insertions(+), 5 deletions(-)
diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
index 82b839c03707..3993652f81a9 100644
--- a/Documentation/networking/ethtool-netlink.txt
+++ b/Documentation/networking/ethtool-netlink.txt
@@ -263,7 +263,8 @@ requests.
GET_SETTINGS requests allow dumps and messages in the same format as response
to them are broadcasted as notifications on change of these settings using
-netlink or ioctl ethtool interface.
+netlink or ioctl ethtool interface; feature notifications are also sent
+whenever netdev_update_features() or netdev_change_features() is called.
Request translation
diff --git a/net/core/dev.c b/net/core/dev.c
index 8a0773a52dd7..66932a9f133e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -93,6 +93,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/ethtool_netlink.h>
#include <linux/notifier.h>
#include <linux/skbuff.h>
#include <linux/bpf.h>
@@ -1318,6 +1319,8 @@ int dev_get_alias(const struct net_device *dev, char *name, size_t len)
void netdev_features_change(struct net_device *dev)
{
call_netdevice_notifiers(NETDEV_FEAT_CHANGE, dev);
+ netdev_ethtool_info_change(dev, NULL, ETHNL_CMD_SET_SETTINGS,
+ ETH_SETTINGS_IM_FEATURES);
}
EXPORT_SYMBOL(netdev_features_change);
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 39e9aea60516..2754d3f6fd75 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -27,6 +27,7 @@
#include <linux/rtnetlink.h>
#include <linux/sched/signal.h>
#include <linux/net.h>
+#include <linux/ethtool_netlink.h>
#include "common.h"
/*
@@ -125,6 +126,8 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
dev->wanted_features &= ~valid;
dev->wanted_features |= wanted & valid;
__netdev_update_features(dev);
+ netdev_ethtool_info_change(dev, NULL, ETHNL_CMD_SET_SETTINGS,
+ ETH_SETTINGS_IM_FEATURES);
if ((dev->wanted_features ^ dev->features) & valid)
ret |= ETHTOOL_F_WISH;
@@ -243,6 +246,8 @@ static int ethtool_set_one_feature(struct net_device *dev,
dev->wanted_features &= ~mask;
__netdev_update_features(dev);
+ netdev_ethtool_info_change(dev, NULL, ETHNL_CMD_SET_SETTINGS,
+ ETH_SETTINGS_IM_FEATURES);
return 0;
}
@@ -298,6 +303,8 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data)
(dev->wanted_features & ~changed) | (features & changed);
__netdev_update_features(dev);
+ netdev_ethtool_info_change(dev, NULL, ETHNL_CMD_SET_SETTINGS,
+ ETH_SETTINGS_IM_FEATURES);
return 0;
}
@@ -638,6 +645,7 @@ static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
{
struct ethtool_cmd cmd;
+ int ret;
ASSERT_RTNL();
@@ -655,8 +663,14 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
link_ksettings.base.cmd = ETHTOOL_SLINKSETTINGS;
link_ksettings.base.link_mode_masks_nwords
= __ETHTOOL_LINK_MODE_MASK_NU32;
- return dev->ethtool_ops->set_link_ksettings(dev,
- &link_ksettings);
+ ret = dev->ethtool_ops->set_link_ksettings(dev,
+ &link_ksettings);
+ if (ret >= 0)
+ netdev_ethtool_info_change(dev, NULL,
+ ETHNL_CMD_SET_SETTINGS,
+ ETH_SETTINGS_IM_LINKINFO |
+ ETH_SETTINGS_IM_LINKMODES);
+ return ret;
}
/* legacy %ethtool_cmd API */
@@ -668,7 +682,12 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
if (!dev->ethtool_ops->set_settings)
return -EOPNOTSUPP;
- return dev->ethtool_ops->set_settings(dev, &cmd);
+ ret = dev->ethtool_ops->set_settings(dev, &cmd);
+ if (ret >= 0)
+ netdev_ethtool_info_change(dev, NULL, ETHNL_CMD_SET_SETTINGS,
+ ETH_SETTINGS_IM_LINKINFO |
+ ETH_SETTINGS_IM_LINKMODES);
+ return ret;
}
static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev,
@@ -1279,6 +1298,7 @@ static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
static int ethtool_set_wol(struct net_device *dev, char __user *useraddr)
{
struct ethtool_wolinfo wol;
+ int ret;
if (!dev->ethtool_ops->set_wol)
return -EOPNOTSUPP;
@@ -1286,7 +1306,11 @@ static int ethtool_set_wol(struct net_device *dev, char __user *useraddr)
if (copy_from_user(&wol, useraddr, sizeof(wol)))
return -EFAULT;
- return dev->ethtool_ops->set_wol(dev, &wol);
+ ret = dev->ethtool_ops->set_wol(dev, &wol);
+ if (ret >= 0)
+ netdev_ethtool_info_change(dev, NULL, ETHNL_CMD_SET_SETTINGS,
+ ETH_SETTINGS_IM_WOLINFO);
+ return ret;
}
static int ethtool_get_eee(struct net_device *dev, char __user *useraddr)
@@ -2478,6 +2502,10 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
case ETHTOOL_SMSGLVL:
rc = ethtool_set_value_void(dev, useraddr,
dev->ethtool_ops->set_msglevel);
+ if (rc >= 0)
+ netdev_ethtool_info_change(dev, NULL,
+ ETHNL_CMD_SET_SETTINGS,
+ ETH_SETTINGS_IM_MSGLEVEL);
break;
case ETHTOOL_GEEE:
rc = ethtool_get_eee(dev, useraddr);
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 6c14185a6466..0e2158092a44 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -629,7 +629,9 @@ int ethnl_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
typedef void (*ethnl_notify_handler_t)(struct netdev_notifier_ethtool_info *);
+void ethnl_settings_notify(struct netdev_notifier_ethtool_info *);
ethnl_notify_handler_t ethnl_notify_handlers[] = {
+ [ETHNL_CMD_SET_SETTINGS] = ethnl_settings_notify,
};
static void __ethnl_notify(struct netdev_notifier_ethtool_info *info)
diff --git a/net/ethtool/settings.c b/net/ethtool/settings.c
index fdca418a6d8e..739bd006c924 100644
--- a/net/ethtool/settings.c
+++ b/net/ethtool/settings.c
@@ -565,3 +565,44 @@ int ethnl_settings_done(struct netlink_callback *cb)
return 0;
}
+
+void ethnl_settings_notify(struct netdev_notifier_ethtool_info *info)
+{
+ struct settings_reqinfo req_info = {
+ .dev = info->info.dev,
+ .req_mask = info->ethtool_info.req_mask,
+ .compact = true,
+ .is_privileged = false,
+ .have_rtnl = true,
+ };
+ struct settings_data data;
+ struct sk_buff *skb;
+ int reply_len;
+ void *ehdr;
+ int ret;
+
+ ret = prepare_settings(&data, &req_info, NULL, req_info.dev);
+ if (ret < 0)
+ return;
+ reply_len = settings_size(&data, &req_info);
+ if (ret < 0)
+ return;
+ skb = genlmsg_new(reply_len, GFP_KERNEL);
+ if (!skb)
+ return;
+ ehdr = genlmsg_put(skb, 0, ++ethnl_bcast_seq, ðtool_genl_family, 0,
+ ETHNL_CMD_SET_SETTINGS);
+ ret = ethnl_fill_dev(skb, req_info.dev, ETHA_SETTINGS_DEV);
+ if (ret < 0)
+ goto err_skb;
+ ret = fill_settings(skb, &data, &req_info);
+ if (ret < 0)
+ goto err_skb;
+ genlmsg_end(skb, ehdr);
+
+ genlmsg_multicast(ðtool_genl_family, skb, 0, ETHNL_MCGRP_MONITOR,
+ GFP_KERNEL);
+ return;
+err_skb:
+ nlmsg_free(skb);
+}
--
2.18.0
^ permalink raw reply related
* [RFC PATCH net-next v2 11/17] ethtool: implement GET_SETTINGS request for features
From: Michal Kubecek @ 2018-07-30 12:53 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>
With ETH_SETTINGS_IM_FEATURES info mask, ETHNL_CMD_GET_SETTINGS request
gets network device feature values. This is the same information as
provided via ETHTOOL_GFEATURES ioctl request.
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
Documentation/networking/ethtool-netlink.txt | 33 ++--
include/uapi/linux/ethtool_netlink.h | 15 +-
net/ethtool/common.h | 2 +
net/ethtool/ioctl.c | 2 -
net/ethtool/settings.c | 151 +++++++++++++++++++
5 files changed, 191 insertions(+), 12 deletions(-)
diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
index 60d426cf6dad..82b839c03707 100644
--- a/Documentation/networking/ethtool-netlink.txt
+++ b/Documentation/networking/ethtool-netlink.txt
@@ -214,6 +214,7 @@ Info mask bits meaning:
ETH_SETTINGS_IM_MSGLEVEL msglevel
ETH_SETTINGS_IM_WOLINFO struct ethtool_wolinfo
ETH_SETTINGS_IM_LINK link state
+ ETH_SETTINGS_IM_FEATURES features
Response contents:
@@ -233,6 +234,11 @@ Response contents:
ETHA_SETTINGS_LINK_MODES (bitset) device link modes
ETHA_SETTINGS_PEER_MODES (bitset) link partner link modes
ETHA_SETTINGS_LINK (u32) link state
+ ETHA_SETTINGS_FEATURES (nested) device features
+ ETHA_FEATURES_HW (bitset) dev->hw_features
+ ETHA_FEATURES_WANTED (bitset) dev->wanted_features
+ ETHA_FEATURES_ACTIVE (bitset) dev->features
+ ETHA_FEATURES_NOCHANGE (bitset) NETIF_F_NEVER_CHANGE
Most of the attributes have the same meaning (including values) as
corresponding members of ioctl structures. For ETHA_SETTINGS_MDIO_SUPPORT and
@@ -242,6 +248,15 @@ ETHA_SETTINGS_LINK_MODES, value represent advertised modes and mask represents
supported modes. For ETHA_SETTINGS_PEER_MODES, both value and mask represent
partner advertised link modes.
+Bitmaps contained in ETHA_SETTINGS_FEATURES have the same meaning as bitmaps
+used in ioctl interference but attribute names are different (they are based
+on corresponding members of struct net_device). Legacy "flags" are not
+provided, if userspace needs them (most likely only ethtool for backward
+compatibility), it can calculate their values from related feature bits
+itself. ETHA_FEATURES_HW uses mask consisting of all features recognized by
+kernel (to provide all names when using verbose bitmap format), remaining
+three use mask equal to value (to save space).
+
GET_SETTINGS request is allowed for unprivileged user but ETHA_SETTINGS_SOPASS
is only provided by kernel in response to privileged (netns CAP_NET_ADMIN)
requests.
@@ -278,30 +293,30 @@ ETHTOOL_GRINGPARAM n/a
ETHTOOL_SRINGPARAM n/a
ETHTOOL_GPAUSEPARAM n/a
ETHTOOL_SPAUSEPARAM n/a
-ETHTOOL_GRXCSUM n/a
+ETHTOOL_GRXCSUM ETHNL_CMD_GET_SETTINGS
ETHTOOL_SRXCSUM n/a
-ETHTOOL_GTXCSUM n/a
+ETHTOOL_GTXCSUM ETHNL_CMD_GET_SETTINGS
ETHTOOL_STXCSUM n/a
-ETHTOOL_GSG n/a
+ETHTOOL_GSG ETHNL_CMD_GET_SETTINGS
ETHTOOL_SSG n/a
ETHTOOL_TEST n/a
ETHTOOL_GSTRINGS ETHNL_CMD_GET_STRSET
ETHTOOL_PHYS_ID n/a
ETHTOOL_GSTATS n/a
-ETHTOOL_GTSO n/a
+ETHTOOL_GTSO ETHNL_CMD_GET_SETTINGS
ETHTOOL_STSO n/a
ETHTOOL_GPERMADDR n/a
-ETHTOOL_GUFO n/a
+ETHTOOL_GUFO ETHNL_CMD_GET_SETTINGS
ETHTOOL_SUFO n/a
-ETHTOOL_GGSO n/a
+ETHTOOL_GGSO ETHNL_CMD_GET_SETTINGS
ETHTOOL_SGSO n/a
-ETHTOOL_GFLAGS n/a
+ETHTOOL_GFLAGS ETHNL_CMD_GET_SETTINGS
ETHTOOL_SFLAGS n/a
ETHTOOL_GPFLAGS n/a
ETHTOOL_SPFLAGS n/a
ETHTOOL_GRXFH n/a
ETHTOOL_SRXFH n/a
-ETHTOOL_GGRO n/a
+ETHTOOL_GGRO ETHNL_CMD_GET_SETTINGS
ETHTOOL_SGRO n/a
ETHTOOL_GRXRINGS n/a
ETHTOOL_GRXCLSRLCNT n/a
@@ -316,7 +331,7 @@ ETHTOOL_GRXNTUPLE n/a
ETHTOOL_GSSET_INFO ETHNL_CMD_GET_STRSET
ETHTOOL_GRXFHINDIR n/a
ETHTOOL_SRXFHINDIR n/a
-ETHTOOL_GFEATURES n/a
+ETHTOOL_GFEATURES ETHNL_CMD_GET_SETTINGS
ETHTOOL_SFEATURES n/a
ETHTOOL_GCHANNELS n/a
ETHTOOL_SCHANNELS n/a
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index 66df44aa7226..06c78b281275 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -170,6 +170,7 @@ enum {
ETHA_SETTINGS_LINK_MODES, /* bitset */
ETHA_SETTINGS_PEER_MODES, /* bitset */
ETHA_SETTINGS_LINK, /* u32 */
+ ETHA_SETTINGS_FEATURES, /* nest - ETHA_FEATURES_* */
__ETHA_SETTINGS_MAX,
ETHA_SETTINGS_MAX = (__ETHA_SETTINGS_MAX - 1)
@@ -180,8 +181,20 @@ enum {
#define ETH_SETTINGS_IM_MSGLEVEL 0x04
#define ETH_SETTINGS_IM_WOLINFO 0x08
#define ETH_SETTINGS_IM_LINK 0x10
+#define ETH_SETTINGS_IM_FEATURES 0x20
-#define ETH_SETTINGS_IM_DEFAULT 0x1f
+#define ETH_SETTINGS_IM_DEFAULT 0x3f
+
+enum {
+ ETHA_FEATURES_UNSPEC,
+ ETHA_FEATURES_HW, /* bitset */
+ ETHA_FEATURES_WANTED, /* bitset */
+ ETHA_FEATURES_ACTIVE, /* bitset */
+ ETHA_FEATURES_NOCHANGE, /* bitset */
+
+ __ETHA_FEATURES_MAX,
+ ETHA_FEATURES_MAX = (__ETHA_FEATURES_MAX - 1)
+};
/* generic netlink info */
#define ETHTOOL_GENL_NAME "ethtool"
diff --git a/net/ethtool/common.h b/net/ethtool/common.h
index ec90d4ccddf7..3b00ed6bfe10 100644
--- a/net/ethtool/common.h
+++ b/net/ethtool/common.h
@@ -6,6 +6,8 @@
#include <linux/netdevice.h>
#include <linux/ethtool.h>
+#define ETHTOOL_DEV_FEATURE_WORDS ((NETDEV_FEATURE_COUNT + 31) / 32)
+
extern const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN];
extern const char rss_hash_func_strings[ETH_RSS_HASH_FUNCS_COUNT][ETH_GSTRING_LEN];
extern const char tunable_strings[__ETHTOOL_TUNABLE_COUNT][ETH_GSTRING_LEN];
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 8613434b6fc0..39e9aea60516 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -54,8 +54,6 @@ EXPORT_SYMBOL(ethtool_op_get_ts_info);
/* Handlers for each ethtool command */
-#define ETHTOOL_DEV_FEATURE_WORDS ((NETDEV_FEATURE_COUNT + 31) / 32)
-
static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
{
struct ethtool_gfeatures cmd = {
diff --git a/net/ethtool/settings.c b/net/ethtool/settings.c
index dd76599f311f..fdca418a6d8e 100644
--- a/net/ethtool/settings.c
+++ b/net/ethtool/settings.c
@@ -4,6 +4,66 @@
#include "common.h"
#include <linux/rtnetlink.h>
+#define FEATURE_NAME_PTR(id) [id] = netdev_features_strings[id]
+static const char *feature_names[] = {
+ FEATURE_NAME_PTR(NETIF_F_SG_BIT),
+ FEATURE_NAME_PTR(NETIF_F_IP_CSUM_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_CSUM_BIT),
+ FEATURE_NAME_PTR(NETIF_F_IPV6_CSUM_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HIGHDMA_BIT),
+ FEATURE_NAME_PTR(NETIF_F_FRAGLIST_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_VLAN_CTAG_TX_BIT),
+
+ FEATURE_NAME_PTR(NETIF_F_HW_VLAN_CTAG_RX_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_VLAN_CTAG_FILTER_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_VLAN_STAG_TX_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_VLAN_STAG_RX_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_VLAN_STAG_FILTER_BIT),
+ FEATURE_NAME_PTR(NETIF_F_VLAN_CHALLENGED_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GSO_BIT),
+ FEATURE_NAME_PTR(NETIF_F_LLTX_BIT),
+ FEATURE_NAME_PTR(NETIF_F_NETNS_LOCAL_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GRO_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GRO_HW_BIT),
+ FEATURE_NAME_PTR(NETIF_F_LRO_BIT),
+
+ FEATURE_NAME_PTR(NETIF_F_TSO_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GSO_ROBUST_BIT),
+ FEATURE_NAME_PTR(NETIF_F_TSO_ECN_BIT),
+ FEATURE_NAME_PTR(NETIF_F_TSO_MANGLEID_BIT),
+ FEATURE_NAME_PTR(NETIF_F_TSO6_BIT),
+ FEATURE_NAME_PTR(NETIF_F_FSO_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GSO_GRE_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GSO_GRE_CSUM_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GSO_IPXIP4_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GSO_IPXIP6_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GSO_UDP_TUNNEL_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GSO_PARTIAL_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GSO_SCTP_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GSO_ESP_BIT),
+ FEATURE_NAME_PTR(NETIF_F_GSO_UDP_L4_BIT),
+
+ FEATURE_NAME_PTR(NETIF_F_FCOE_CRC_BIT),
+ FEATURE_NAME_PTR(NETIF_F_SCTP_CRC_BIT),
+ FEATURE_NAME_PTR(NETIF_F_FCOE_MTU_BIT),
+ FEATURE_NAME_PTR(NETIF_F_NTUPLE_BIT),
+ FEATURE_NAME_PTR(NETIF_F_RXHASH_BIT),
+ FEATURE_NAME_PTR(NETIF_F_RXCSUM_BIT),
+ FEATURE_NAME_PTR(NETIF_F_NOCACHE_COPY_BIT),
+ FEATURE_NAME_PTR(NETIF_F_LOOPBACK_BIT),
+ FEATURE_NAME_PTR(NETIF_F_RXFCS_BIT),
+ FEATURE_NAME_PTR(NETIF_F_RXALL_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_L2FW_DOFFLOAD_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_TC_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_ESP_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_ESP_TX_CSUM_BIT),
+ FEATURE_NAME_PTR(NETIF_F_RX_UDP_TUNNEL_PORT_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_TLS_RECORD_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_TLS_TX_BIT),
+ FEATURE_NAME_PTR(NETIF_F_HW_TLS_RX_BIT),
+};
+
struct settings_data {
struct ethtool_link_ksettings ksettings;
struct ethtool_link_settings *lsettings;
@@ -12,6 +72,12 @@ struct settings_data {
u32 msglevel;
bool lpm_empty;
u32 req_mask;
+ struct {
+ u32 hw[ETHTOOL_DEV_FEATURE_WORDS];
+ u32 wanted[ETHTOOL_DEV_FEATURE_WORDS];
+ u32 active[ETHTOOL_DEV_FEATURE_WORDS];
+ u32 nochange[ETHTOOL_DEV_FEATURE_WORDS];
+ } features;
};
struct settings_reqinfo {
@@ -51,6 +117,7 @@ static const struct nla_policy settings_policy[ETHA_SETTINGS_MAX + 1] = {
[ETHA_SETTINGS_LINK_MODES] = { .type = NLA_NESTED },
[ETHA_SETTINGS_PEER_MODES] = { .type = NLA_NESTED },
[ETHA_SETTINGS_LINK] = { .type = NLA_FLAG },
+ [ETHA_SETTINGS_FEATURES] = { .type = NLA_NESTED },
};
/* To keep things simple, reserve space for some attributes which may not
@@ -105,6 +172,35 @@ static int settings_size(struct settings_data *data,
}
if (req_mask & ETH_SETTINGS_IM_LINK)
len += nla_total_size(sizeof(u32));
+ if (req_mask & ETH_SETTINGS_IM_FEATURES) {
+ ret = ethnl_bitset32_size(compact, NETDEV_FEATURE_COUNT,
+ data->features.hw, NULL,
+ feature_names);
+ if (ret < 0)
+ return ret;
+ len += ret;
+ ret = ethnl_bitset32_size(compact, NETDEV_FEATURE_COUNT,
+ data->features.wanted,
+ data->features.wanted,
+ feature_names);
+ if (ret < 0)
+ return ret;
+ len += ret;
+ ret = ethnl_bitset32_size(compact, NETDEV_FEATURE_COUNT,
+ data->features.active,
+ data->features.active,
+ feature_names);
+ if (ret < 0)
+ return ret;
+ len += ret;
+ ret = ethnl_bitset32_size(compact, NETDEV_FEATURE_COUNT,
+ data->features.nochange,
+ data->features.nochange,
+ feature_names);
+ if (ret < 0)
+ return ret;
+ len += ret;
+ }
return len;
}
@@ -150,6 +246,24 @@ static int ethnl_get_wol(struct genl_info *info, struct net_device *dev,
return ret;
}
+static void features_to_bitmap(u32 *dest, netdev_features_t src)
+{
+ unsigned int i;
+
+ for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; i++)
+ dest[i] = (u32)(src >> (32 * i));
+}
+
+static int ethnl_get_features(struct net_device *dev,
+ struct settings_data *data)
+{
+ features_to_bitmap(data->features.hw, dev->hw_features);
+ features_to_bitmap(data->features.wanted, dev->wanted_features);
+ features_to_bitmap(data->features.active, dev->features);
+ features_to_bitmap(data->features.nochange, NETIF_F_NEVER_CHANGE);
+ return 0;
+}
+
static int parse_settings_req(struct settings_reqinfo *req_info,
struct genl_info *info, struct sk_buff *skb,
const struct nlmsghdr *nlhdr)
@@ -233,6 +347,8 @@ static int prepare_settings(struct settings_data *data,
}
if (req_mask & ETH_SETTINGS_IM_LINK)
data->link = __ethtool_get_link(dev);
+ if (req_mask & ETH_SETTINGS_IM_FEATURES)
+ ethnl_get_features(dev, data);
if (!req_info->have_rtnl)
rtnl_unlock();
@@ -316,6 +432,41 @@ static int fill_settings(struct sk_buff *rskb, struct settings_data *data,
if (nla_put_u32(rskb, ETHA_SETTINGS_LINK, data->link))
return ret;
}
+ if (req_mask & ETH_SETTINGS_IM_FEATURES) {
+ struct nlattr *feat_attr;
+
+ feat_attr = ethnl_nest_start(rskb, ETHA_SETTINGS_FEATURES);
+ if (!feat_attr)
+ return -ENOMEM;
+ ret = ethnl_put_bitset32(rskb, ETHA_FEATURES_HW,
+ compact, NETDEV_FEATURE_COUNT,
+ data->features.hw, NULL,
+ feature_names);
+ if (ret < 0)
+ return ret;
+ ret = ethnl_put_bitset32(rskb, ETHA_FEATURES_WANTED,
+ compact, NETDEV_FEATURE_COUNT,
+ data->features.wanted,
+ data->features.wanted,
+ feature_names);
+ if (ret < 0)
+ return ret;
+ ret = ethnl_put_bitset32(rskb, ETHA_FEATURES_ACTIVE,
+ compact, NETDEV_FEATURE_COUNT,
+ data->features.active,
+ data->features.active,
+ feature_names);
+ if (ret < 0)
+ return ret;
+ ret = ethnl_put_bitset32(rskb, ETHA_FEATURES_NOCHANGE,
+ compact, NETDEV_FEATURE_COUNT,
+ data->features.nochange,
+ data->features.nochange,
+ feature_names);
+ if (ret < 0)
+ return ret;
+ nla_nest_end(rskb, feat_attr);
+ }
return 0;
}
--
2.18.0
^ permalink raw reply related
* [RFC PATCH net-next v2 10/17] ethtool: implement GET_SETTINGS message
From: Michal Kubecek @ 2018-07-30 12:53 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>
Requests the information provided by ETHTOOL_GLINKSETTINGS, ETHTOOL_GWOL
and ETHTOOL_GMSGLVL. The info_mask header field can be used to request only
part of the information. Flag ETH_SETTINGS_RF_COMPACT_BITSETS switches
between flag-by-flag list and compact bitmaps for link modes in the reply.
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
Documentation/networking/ethtool-netlink.txt | 69 ++-
include/linux/ethtool_netlink.h | 3 +
include/linux/netdevice.h | 2 +
include/uapi/linux/ethtool.h | 3 +
include/uapi/linux/ethtool_netlink.h | 37 ++
net/ethtool/Makefile | 2 +-
net/ethtool/common.c | 112 +++++
net/ethtool/common.h | 8 +
net/ethtool/ioctl.c | 108 +----
net/ethtool/netlink.c | 69 +++
net/ethtool/netlink.h | 2 +
net/ethtool/settings.c | 416 +++++++++++++++++++
12 files changed, 725 insertions(+), 106 deletions(-)
create mode 100644 net/ethtool/settings.c
diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
index 1e3d5ffc97ab..60d426cf6dad 100644
--- a/Documentation/networking/ethtool-netlink.txt
+++ b/Documentation/networking/ethtool-netlink.txt
@@ -123,6 +123,8 @@ List of message types
ETHNL_CMD_SET_STRSET response only
ETHNL_CMD_GET_DRVINFO
ETHNL_CMD_SET_DRVINFO response only
+ ETHNL_CMD_GET_SETTINGS
+ ETHNL_CMD_SET_SETTINGS response only (for now)
All constants use ETHNL_CMD_ prefix, usually followed by "GET", "SET" or "ACT"
to indicate the type.
@@ -192,6 +194,63 @@ GET_DRVINFO requests).
GET_DRVINFO requests allow dumps.
+GET_SETTINGS
+------------
+
+GET_SETTINGS request retrieves information provided by ETHTOOL_GLINKSETTINGS,
+ETHTOOL_GWOL, ETHTOOL_GMSGLVL and ETHTOOL_GLINK ioctl requests. The request
+doesn't use any attributes.
+
+Request attributes:
+
+ ETHA_SETTINGS_DEV (nested) device identification
+ ETHA_SETTINGS_INFOMASK (u32) info mask
+ ETHA_SETTINGS_COMPACT (flag) request compact bitsets
+
+Info mask bits meaning:
+
+ ETH_SETTINGS_IM_LINKINFO link_ksettings except link modes
+ ETH_SETTINGS_IM_LINKMODES link modes from link_ksettings
+ ETH_SETTINGS_IM_MSGLEVEL msglevel
+ ETH_SETTINGS_IM_WOLINFO struct ethtool_wolinfo
+ ETH_SETTINGS_IM_LINK link state
+
+Response contents:
+
+ ETHA_SETTINGS_DEV (nested) device identification
+ ETHA_SETTINGS_SPEED (u32) link speed (Mb/s)
+ ETHA_SETTINGS_DUPLEX (u8) duplex mode
+ ETHA_SETTINGS_PORT (u8) physical port
+ ETHA_SETTINGS_PHYADDR (u8) MDIO address of phy
+ ETHA_SETTINGS_AUTONEG (u8) autoneotiation status
+ ETHA_SETTINGS_MDIO_SUPPORT (bitfield32) MDIO support flags
+ ETHA_SETTINGS_TP_MDIX (u8) MDI(-X) status
+ ETHA_SETTINGS_TP_MDIX_CTRL (u8) MDI(-X) control
+ ETHA_SETTINGS_TRANSCEIVER (u8) transceiver
+ ETHA_SETTINGS_WOL_MODES (bitfield32) wake-on-lan modes
+ ETHA_SETTINGS_SOPASS (binary) SecureOn(tm) password
+ ETHA_SETTINGS_MSGLVL (bitfield32) debug level
+ ETHA_SETTINGS_LINK_MODES (bitset) device link modes
+ ETHA_SETTINGS_PEER_MODES (bitset) link partner link modes
+ ETHA_SETTINGS_LINK (u32) link state
+
+Most of the attributes have the same meaning (including values) as
+corresponding members of ioctl structures. For ETHA_SETTINGS_MDIO_SUPPORT and
+ETHA_SETTINGS_MSGLVL, selector reports flags supported by kernel. For
+ETHA_SETTINGS_WOL_MODES it reports flags supported by the device. For
+ETHA_SETTINGS_LINK_MODES, value represent advertised modes and mask represents
+supported modes. For ETHA_SETTINGS_PEER_MODES, both value and mask represent
+partner advertised link modes.
+
+GET_SETTINGS request is allowed for unprivileged user but ETHA_SETTINGS_SOPASS
+is only provided by kernel in response to privileged (netns CAP_NET_ADMIN)
+requests.
+
+GET_SETTINGS requests allow dumps and messages in the same format as response
+to them are broadcasted as notifications on change of these settings using
+netlink or ioctl ethtool interface.
+
+
Request translation
-------------------
@@ -201,16 +260,16 @@ have their netlink replacement yet.
ioctl command netlink command
---------------------------------------------------------------------
-ETHTOOL_GSET n/a
+ETHTOOL_GSET ETHNL_CMD_GET_SETTINGS
ETHTOOL_SSET n/a
ETHTOOL_GDRVINFO ETHNL_CMD_GET_DRVINFO
ETHTOOL_GREGS n/a
-ETHTOOL_GWOL n/a
+ETHTOOL_GWOL ETHNL_CMD_GET_SETTINGS
ETHTOOL_SWOL n/a
-ETHTOOL_GMSGLVL n/a
+ETHTOOL_GMSGLVL ETHNL_CMD_GET_SETTINGS
ETHTOOL_SMSGLVL n/a
ETHTOOL_NWAY_RST n/a
-ETHTOOL_GLINK n/a
+ETHTOOL_GLINK ETHNL_CMD_GET_SETTINGS
ETHTOOL_GEEPROM n/a
ETHTOOL_SEEPROM n/a
ETHTOOL_GCOALESCE n/a
@@ -275,7 +334,7 @@ ETHTOOL_GTUNABLE n/a
ETHTOOL_STUNABLE n/a
ETHTOOL_GPHYSTATS n/a
ETHTOOL_PERQUEUE n/a
-ETHTOOL_GLINKSETTINGS n/a
+ETHTOOL_GLINKSETTINGS ETHNL_CMD_GET_SETTINGS
ETHTOOL_SLINKSETTINGS n/a
ETHTOOL_PHY_GTUNABLE n/a
ETHTOOL_PHY_STUNABLE n/a
diff --git a/include/linux/ethtool_netlink.h b/include/linux/ethtool_netlink.h
index 2a15e64a16f3..fba8ff961887 100644
--- a/include/linux/ethtool_netlink.h
+++ b/include/linux/ethtool_netlink.h
@@ -7,6 +7,9 @@
#include <linux/ethtool.h>
#include <linux/netdevice.h>
+#define __ETHTOOL_LINK_MODE_MASK_NWORDS \
+ ((__ETHTOOL_LINK_MODE_MASK_NBITS + 31) / 32)
+
enum ethtool_multicast_groups {
ETHNL_MCGRP_MONITOR,
};
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c4b0c575d57e..93071380558c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3738,6 +3738,8 @@ enum {
NETIF_MSG_PKTDATA = 0x1000,
NETIF_MSG_HW = 0x2000,
NETIF_MSG_WOL = 0x4000,
+
+ NETIF_MSG_ALL = 0x7fff,
};
#define netif_msg_drv(p) ((p)->msg_enable & NETIF_MSG_DRV)
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index 2ae393963704..98f645a38168 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -143,6 +143,9 @@ static inline __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep)
*/
#define ETH_MDIO_SUPPORTS_C45 2
+/* All defined ETH_MDIO_SUPPORTS_* flags */
+#define ETH_MDIO_SUPPORTS_ALL (ETH_MDIO_SUPPORTS_C22 | ETH_MDIO_SUPPORTS_C45)
+
#define ETHTOOL_FWVERS_LEN 32
#define ETHTOOL_BUSINFO_LEN 32
#define ETHTOOL_EROMVERS_LEN 32
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index df4de61fac48..66df44aa7226 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -12,6 +12,8 @@ enum {
ETHNL_CMD_SET_STRSET, /* only for reply */
ETHNL_CMD_GET_DRVINFO,
ETHNL_CMD_SET_DRVINFO, /* only for reply */
+ ETHNL_CMD_GET_SETTINGS,
+ ETHNL_CMD_SET_SETTINGS,
__ETHNL_CMD_MAX,
ETHNL_CMD_MAX = (__ETHNL_CMD_MAX - 1)
@@ -146,6 +148,41 @@ enum {
ETHA_DRVINFO_MAX = (__ETHA_DRVINFO_MAX - 1)
};
+/* GET_SETTINGS / SET_SETTINGS */
+
+enum {
+ ETHA_SETTINGS_UNSPEC,
+ ETHA_SETTINGS_DEV, /* nest - ETHA_DEV_* */
+ ETHA_SETTINGS_INFOMASK, /* u32 */
+ ETHA_SETTINGS_COMPACT, /* flag */
+ ETHA_SETTINGS_SPEED, /* u32 */
+ ETHA_SETTINGS_DUPLEX, /* u8 */
+ ETHA_SETTINGS_PORT, /* u8 */
+ ETHA_SETTINGS_PHYADDR, /* u8 */
+ ETHA_SETTINGS_AUTONEG, /* u8 */
+ ETHA_SETTINGS_MDIO_SUPPORT, /* bitfield32 */
+ ETHA_SETTINGS_TP_MDIX, /* u8 */
+ ETHA_SETTINGS_TP_MDIX_CTRL, /* u8 */
+ ETHA_SETTINGS_TRANSCEIVER, /* u8 */
+ ETHA_SETTINGS_WOL_MODES, /* bitfield32 */
+ ETHA_SETTINGS_SOPASS, /* binary */
+ ETHA_SETTINGS_MSGLVL, /* bitfield32 */
+ ETHA_SETTINGS_LINK_MODES, /* bitset */
+ ETHA_SETTINGS_PEER_MODES, /* bitset */
+ ETHA_SETTINGS_LINK, /* u32 */
+
+ __ETHA_SETTINGS_MAX,
+ ETHA_SETTINGS_MAX = (__ETHA_SETTINGS_MAX - 1)
+};
+
+#define ETH_SETTINGS_IM_LINKINFO 0x01
+#define ETH_SETTINGS_IM_LINKMODES 0x02
+#define ETH_SETTINGS_IM_MSGLEVEL 0x04
+#define ETH_SETTINGS_IM_WOLINFO 0x08
+#define ETH_SETTINGS_IM_LINK 0x10
+
+#define ETH_SETTINGS_IM_DEFAULT 0x1f
+
/* generic netlink info */
#define ETHTOOL_GENL_NAME "ethtool"
#define ETHTOOL_GENL_VERSION 1
diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile
index 2e840ae0ba1e..8dd98310ed6f 100644
--- a/net/ethtool/Makefile
+++ b/net/ethtool/Makefile
@@ -4,4 +4,4 @@ obj-y += ioctl.o common.o
obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o
-ethtool_nl-y := netlink.o strset.o drvinfo.o
+ethtool_nl-y := netlink.o strset.o drvinfo.o settings.o
diff --git a/net/ethtool/common.c b/net/ethtool/common.c
index 1dc4a6515996..986e82664447 100644
--- a/net/ethtool/common.c
+++ b/net/ethtool/common.c
@@ -128,3 +128,115 @@ int __ethtool_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
return 0;
}
EXPORT_SYMBOL(__ethtool_get_drvinfo);
+
+/* return false if legacy contained non-0 deprecated fields
+ * maxtxpkt/maxrxpkt. rest of ksettings always updated
+ */
+bool
+convert_legacy_settings_to_link_ksettings(
+ struct ethtool_link_ksettings *link_ksettings,
+ const struct ethtool_cmd *legacy_settings)
+{
+ bool retval = true;
+
+ memset(link_ksettings, 0, sizeof(*link_ksettings));
+
+ /* This is used to tell users that driver is still using these
+ * deprecated legacy fields, and they should not use
+ * %ETHTOOL_GLINKSETTINGS/%ETHTOOL_SLINKSETTINGS
+ */
+ if (legacy_settings->maxtxpkt ||
+ legacy_settings->maxrxpkt)
+ retval = false;
+
+ ethtool_convert_legacy_u32_to_link_mode(
+ link_ksettings->link_modes.supported,
+ legacy_settings->supported);
+ ethtool_convert_legacy_u32_to_link_mode(
+ link_ksettings->link_modes.advertising,
+ legacy_settings->advertising);
+ ethtool_convert_legacy_u32_to_link_mode(
+ link_ksettings->link_modes.lp_advertising,
+ legacy_settings->lp_advertising);
+ link_ksettings->base.speed
+ = ethtool_cmd_speed(legacy_settings);
+ link_ksettings->base.duplex
+ = legacy_settings->duplex;
+ link_ksettings->base.port
+ = legacy_settings->port;
+ link_ksettings->base.phy_address
+ = legacy_settings->phy_address;
+ link_ksettings->base.autoneg
+ = legacy_settings->autoneg;
+ link_ksettings->base.mdio_support
+ = legacy_settings->mdio_support;
+ link_ksettings->base.eth_tp_mdix
+ = legacy_settings->eth_tp_mdix;
+ link_ksettings->base.eth_tp_mdix_ctrl
+ = legacy_settings->eth_tp_mdix_ctrl;
+ return retval;
+}
+
+/* Internal kernel helper to query a device ethtool_link_settings.
+ *
+ * Backward compatibility note: for compatibility with legacy drivers
+ * that implement only the ethtool_cmd API, this has to work with both
+ * drivers implementing get_link_ksettings API and drivers
+ * implementing get_settings API. When drivers implement get_settings
+ * and report ethtool_cmd deprecated fields
+ * (transceiver/maxrxpkt/maxtxpkt), these fields are silently ignored
+ * because the resulting struct ethtool_link_settings does not report them.
+ */
+int __ethtool_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *link_ksettings)
+{
+ int err;
+ struct ethtool_cmd cmd;
+
+ ASSERT_RTNL();
+
+ if (dev->ethtool_ops->get_link_ksettings) {
+ memset(link_ksettings, 0, sizeof(*link_ksettings));
+ return dev->ethtool_ops->get_link_ksettings(dev,
+ link_ksettings);
+ }
+
+ /* driver doesn't support %ethtool_link_ksettings API. revert to
+ * legacy %ethtool_cmd API, unless it's not supported either.
+ * TODO: remove when ethtool_ops::get_settings disappears internally
+ */
+ if (!dev->ethtool_ops->get_settings)
+ return -EOPNOTSUPP;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = ETHTOOL_GSET;
+ err = dev->ethtool_ops->get_settings(dev, &cmd);
+ if (err < 0)
+ return err;
+
+ /* we ignore deprecated fields transceiver/maxrxpkt/maxtxpkt
+ */
+ convert_legacy_settings_to_link_ksettings(link_ksettings, &cmd);
+ return err;
+}
+EXPORT_SYMBOL(__ethtool_get_link_ksettings);
+
+int __ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ if (!dev->ethtool_ops->get_wol)
+ return -EOPNOTSUPP;
+
+ dev->ethtool_ops->get_wol(dev, wol);
+
+ return 0;
+}
+EXPORT_SYMBOL(__ethtool_get_wol);
+
+int __ethtool_get_link(struct net_device *dev)
+{
+ if (!dev->ethtool_ops->get_link)
+ return -EOPNOTSUPP;
+
+ return netif_running(dev) && dev->ethtool_ops->get_link(dev);
+}
+EXPORT_SYMBOL(__ethtool_get_link);
diff --git a/net/ethtool/common.h b/net/ethtool/common.h
index 0f768c1be527..ec90d4ccddf7 100644
--- a/net/ethtool/common.h
+++ b/net/ethtool/common.h
@@ -12,5 +12,13 @@ extern const char tunable_strings[__ETHTOOL_TUNABLE_COUNT][ETH_GSTRING_LEN];
extern const char phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN];
int __ethtool_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);
+int __ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
+int __ethtool_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *link_ksettings);
+int __ethtool_get_link(struct net_device *dev);
+
+bool convert_legacy_settings_to_link_ksettings(
+ struct ethtool_link_ksettings *link_ksettings,
+ const struct ethtool_cmd *legacy_settings);
#endif /* _ETHTOOL_COMMON_H */
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 7b5831d35bca..8613434b6fc0 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -352,54 +352,6 @@ bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32,
}
EXPORT_SYMBOL(ethtool_convert_link_mode_to_legacy_u32);
-/* return false if legacy contained non-0 deprecated fields
- * maxtxpkt/maxrxpkt. rest of ksettings always updated
- */
-static bool
-convert_legacy_settings_to_link_ksettings(
- struct ethtool_link_ksettings *link_ksettings,
- const struct ethtool_cmd *legacy_settings)
-{
- bool retval = true;
-
- memset(link_ksettings, 0, sizeof(*link_ksettings));
-
- /* This is used to tell users that driver is still using these
- * deprecated legacy fields, and they should not use
- * %ETHTOOL_GLINKSETTINGS/%ETHTOOL_SLINKSETTINGS
- */
- if (legacy_settings->maxtxpkt ||
- legacy_settings->maxrxpkt)
- retval = false;
-
- ethtool_convert_legacy_u32_to_link_mode(
- link_ksettings->link_modes.supported,
- legacy_settings->supported);
- ethtool_convert_legacy_u32_to_link_mode(
- link_ksettings->link_modes.advertising,
- legacy_settings->advertising);
- ethtool_convert_legacy_u32_to_link_mode(
- link_ksettings->link_modes.lp_advertising,
- legacy_settings->lp_advertising);
- link_ksettings->base.speed
- = ethtool_cmd_speed(legacy_settings);
- link_ksettings->base.duplex
- = legacy_settings->duplex;
- link_ksettings->base.port
- = legacy_settings->port;
- link_ksettings->base.phy_address
- = legacy_settings->phy_address;
- link_ksettings->base.autoneg
- = legacy_settings->autoneg;
- link_ksettings->base.mdio_support
- = legacy_settings->mdio_support;
- link_ksettings->base.eth_tp_mdix
- = legacy_settings->eth_tp_mdix;
- link_ksettings->base.eth_tp_mdix_ctrl
- = legacy_settings->eth_tp_mdix_ctrl;
- return retval;
-}
-
/* return false if ksettings link modes had higher bits
* set. legacy_settings always updated (best effort)
*/
@@ -460,50 +412,6 @@ struct ethtool_link_usettings {
} link_modes;
};
-/* Internal kernel helper to query a device ethtool_link_settings.
- *
- * Backward compatibility note: for compatibility with legacy drivers
- * that implement only the ethtool_cmd API, this has to work with both
- * drivers implementing get_link_ksettings API and drivers
- * implementing get_settings API. When drivers implement get_settings
- * and report ethtool_cmd deprecated fields
- * (transceiver/maxrxpkt/maxtxpkt), these fields are silently ignored
- * because the resulting struct ethtool_link_settings does not report them.
- */
-int __ethtool_get_link_ksettings(struct net_device *dev,
- struct ethtool_link_ksettings *link_ksettings)
-{
- int err;
- struct ethtool_cmd cmd;
-
- ASSERT_RTNL();
-
- if (dev->ethtool_ops->get_link_ksettings) {
- memset(link_ksettings, 0, sizeof(*link_ksettings));
- return dev->ethtool_ops->get_link_ksettings(dev,
- link_ksettings);
- }
-
- /* driver doesn't support %ethtool_link_ksettings API. revert to
- * legacy %ethtool_cmd API, unless it's not supported either.
- * TODO: remove when ethtool_ops::get_settings disappears internally
- */
- if (!dev->ethtool_ops->get_settings)
- return -EOPNOTSUPP;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmd = ETHTOOL_GSET;
- err = dev->ethtool_ops->get_settings(dev, &cmd);
- if (err < 0)
- return err;
-
- /* we ignore deprecated fields transceiver/maxrxpkt/maxtxpkt
- */
- convert_legacy_settings_to_link_ksettings(link_ksettings, &cmd);
- return err;
-}
-EXPORT_SYMBOL(__ethtool_get_link_ksettings);
-
/* convert ethtool_link_usettings in user space to a kernel internal
* ethtool_link_ksettings. return 0 on success, errno on error.
*/
@@ -1359,11 +1267,11 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
{
struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
+ int rc;
- if (!dev->ethtool_ops->get_wol)
- return -EOPNOTSUPP;
-
- dev->ethtool_ops->get_wol(dev, &wol);
+ rc = __ethtool_get_wol(dev, &wol);
+ if (rc < 0)
+ return rc;
if (copy_to_user(useraddr, &wol, sizeof(wol)))
return -EFAULT;
@@ -1428,12 +1336,12 @@ static int ethtool_nway_reset(struct net_device *dev)
static int ethtool_get_link(struct net_device *dev, char __user *useraddr)
{
struct ethtool_value edata = { .cmd = ETHTOOL_GLINK };
+ int link = __ethtool_get_link(dev);
- if (!dev->ethtool_ops->get_link)
- return -EOPNOTSUPP;
-
- edata.data = netif_running(dev) && dev->ethtool_ops->get_link(dev);
+ if (link < 0)
+ return link;
+ edata.data = link;
if (copy_to_user(useraddr, &edata, sizeof(edata)))
return -EFAULT;
return 0;
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 305baa02ff70..6c14185a6466 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -2,12 +2,68 @@
#include <linux/module.h>
#include <linux/bitmap.h>
+#include <linux/rtnetlink.h>
#include <net/sock.h>
#include <linux/ethtool_netlink.h>
#include "netlink.h"
u32 ethnl_bcast_seq;
+const char *const link_mode_names[] = {
+ [ETHTOOL_LINK_MODE_10baseT_Half_BIT] = "10baseT/Half",
+ [ETHTOOL_LINK_MODE_10baseT_Full_BIT] = "10baseT/Full",
+ [ETHTOOL_LINK_MODE_100baseT_Half_BIT] = "100baseT/Half",
+ [ETHTOOL_LINK_MODE_100baseT_Full_BIT] = "100baseT/Full",
+ [ETHTOOL_LINK_MODE_1000baseT_Half_BIT] = "1000baseT/Half",
+ [ETHTOOL_LINK_MODE_1000baseT_Full_BIT] = "1000baseT/Full",
+ [ETHTOOL_LINK_MODE_Autoneg_BIT] = "Autoneg",
+ [ETHTOOL_LINK_MODE_TP_BIT] = "TP",
+ [ETHTOOL_LINK_MODE_AUI_BIT] = "AUI",
+ [ETHTOOL_LINK_MODE_MII_BIT] = "MII",
+ [ETHTOOL_LINK_MODE_FIBRE_BIT] = "FIBRE",
+ [ETHTOOL_LINK_MODE_BNC_BIT] = "BNC",
+ [ETHTOOL_LINK_MODE_10000baseT_Full_BIT] = "10000baseT/Full",
+ [ETHTOOL_LINK_MODE_Pause_BIT] = "Pause",
+ [ETHTOOL_LINK_MODE_Asym_Pause_BIT] = "Asym_Pause",
+ [ETHTOOL_LINK_MODE_2500baseX_Full_BIT] = "2500baseX/Full",
+ [ETHTOOL_LINK_MODE_Backplane_BIT] = "Backplane",
+ [ETHTOOL_LINK_MODE_1000baseKX_Full_BIT] = "1000baseKX/Full",
+ [ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT] = "10000baseKX4/Full",
+ [ETHTOOL_LINK_MODE_10000baseKR_Full_BIT] = "10000baseKR/Full",
+ [ETHTOOL_LINK_MODE_10000baseR_FEC_BIT] = "10000baseR/FEC",
+ [ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT] = "20000baseMLD2/Full",
+ [ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT] = "20000baseKR2/Full",
+ [ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT] = "40000baseKR4/Full",
+ [ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT] = "40000baseCR4/Full",
+ [ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT] = "40000baseSR4/Full",
+ [ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT] = "40000baseLR4/Full",
+ [ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT] = "56000baseKR4/Full",
+ [ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT] = "56000baseCR4/Full",
+ [ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT] = "56000baseSR4/Full",
+ [ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT] = "56000baseLR4/Full",
+ [ETHTOOL_LINK_MODE_25000baseCR_Full_BIT] = "25000baseCR/Full",
+ [ETHTOOL_LINK_MODE_25000baseKR_Full_BIT] = "25000baseKR/Full",
+ [ETHTOOL_LINK_MODE_25000baseSR_Full_BIT] = "25000baseSR/Full",
+ [ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT] = "50000baseCR2/Full",
+ [ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT] = "50000baseKR2/Full",
+ [ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT] = "100000baseKR4/Full",
+ [ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT] = "100000baseSR4/Full",
+ [ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT] = "100000baseCR4/Full",
+ [ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT] = "100000baseLR4/ER4_Full",
+ [ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT] = "50000baseSR2/Full",
+ [ETHTOOL_LINK_MODE_1000baseX_Full_BIT] = "1000baseX/Full",
+ [ETHTOOL_LINK_MODE_10000baseCR_Full_BIT] = "10000baseCR/Full",
+ [ETHTOOL_LINK_MODE_10000baseSR_Full_BIT] = "10000baseSR/Full",
+ [ETHTOOL_LINK_MODE_10000baseLR_Full_BIT] = "10000baseLR/Full",
+ [ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT] = "10000baseLRM/Full",
+ [ETHTOOL_LINK_MODE_10000baseER_Full_BIT] = "10000baseER/Full",
+ [ETHTOOL_LINK_MODE_2500baseT_Full_BIT] = "2500baseT/Full",
+ [ETHTOOL_LINK_MODE_5000baseT_Full_BIT] = "5000baseT/Full",
+ [ETHTOOL_LINK_MODE_FEC_NONE_BIT] = "None",
+ [ETHTOOL_LINK_MODE_FEC_RS_BIT] = "RS",
+ [ETHTOOL_LINK_MODE_FEC_BASER_BIT] = "BASER",
+};
+
static const struct nla_policy dev_policy[ETHA_DEV_MAX + 1] = {
[ETHA_DEV_UNSPEC] = { .type = NLA_UNSPEC },
[ETHA_DEV_INDEX] = { .type = NLA_U32 },
@@ -671,11 +727,14 @@ static struct notifier_block ethnl_netdev_notifier = {
int ethnl_get_strset(struct sk_buff *skb, struct genl_info *info);
int ethnl_get_drvinfo(struct sk_buff *skb, struct genl_info *info);
+int ethnl_get_settings(struct sk_buff *skb, struct genl_info *info);
int ethnl_strset_start(struct netlink_callback *cb);
int ethnl_drvinfo_start(struct netlink_callback *cb);
+int ethnl_settings_start(struct netlink_callback *cb);
int ethnl_strset_done(struct netlink_callback *cb);
+int ethnl_settings_done(struct netlink_callback *cb);
static const struct genl_ops ethtool_genl_ops[] = {
{
@@ -691,6 +750,13 @@ static const struct genl_ops ethtool_genl_ops[] = {
.start = ethnl_drvinfo_start,
.dumpit = ethnl_dumpit,
},
+ {
+ .cmd = ETHNL_CMD_GET_SETTINGS,
+ .doit = ethnl_get_settings,
+ .start = ethnl_settings_start,
+ .dumpit = ethnl_dumpit,
+ .done = ethnl_settings_done,
+ },
};
static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
@@ -715,6 +781,9 @@ static int __init ethtool_nl_init(void)
{
int ret;
+ BUILD_BUG_ON(ARRAY_SIZE(link_mode_names) <
+ __ETHTOOL_LINK_MODE_MASK_NBITS);
+
ret = genl_register_family(ðtool_genl_family);
if (ret < 0)
return ret;
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 94c14ec2c3fc..789aceae9f5e 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -15,6 +15,8 @@ extern u32 ethnl_bcast_seq;
extern struct genl_family ethtool_genl_family;
+extern const char *const link_mode_names[];
+
struct net_device *ethnl_dev_get(struct genl_info *info, struct nlattr *nest);
int ethnl_fill_dev(struct sk_buff *msg, struct net_device *dev, u16 attrtype);
diff --git a/net/ethtool/settings.c b/net/ethtool/settings.c
new file mode 100644
index 000000000000..dd76599f311f
--- /dev/null
+++ b/net/ethtool/settings.c
@@ -0,0 +1,416 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#include "netlink.h"
+#include "common.h"
+#include <linux/rtnetlink.h>
+
+struct settings_data {
+ struct ethtool_link_ksettings ksettings;
+ struct ethtool_link_settings *lsettings;
+ struct ethtool_wolinfo wolinfo;
+ int link;
+ u32 msglevel;
+ bool lpm_empty;
+ u32 req_mask;
+};
+
+struct settings_reqinfo {
+ struct net_device *dev;
+ u32 req_mask;
+ bool compact;
+ bool is_privileged;
+ bool have_rtnl;
+};
+
+/* We want to allow ~0 as selector for backward compatibility (to just set
+ * given set of modes, whatever kernel supports) so that we allow all bits
+ * on validation and do our own sanity check later.
+ */
+static u32 all_bits = ~(u32)0;
+
+static const struct nla_policy settings_policy[ETHA_SETTINGS_MAX + 1] = {
+ [ETHA_SETTINGS_UNSPEC] = { .type = NLA_UNSPEC },
+ [ETHA_SETTINGS_DEV] = { .type = NLA_NESTED },
+ [ETHA_SETTINGS_INFOMASK] = { .type = NLA_U32 },
+ [ETHA_SETTINGS_COMPACT] = { .type = NLA_FLAG },
+ [ETHA_SETTINGS_SPEED] = { .type = NLA_U32 },
+ [ETHA_SETTINGS_DUPLEX] = { .type = NLA_U8 },
+ [ETHA_SETTINGS_PORT] = { .type = NLA_U8 },
+ [ETHA_SETTINGS_PHYADDR] = { .type = NLA_U8 },
+ [ETHA_SETTINGS_AUTONEG] = { .type = NLA_U8 },
+ [ETHA_SETTINGS_MDIO_SUPPORT] = { .type = NLA_BITFIELD32 },
+ [ETHA_SETTINGS_TP_MDIX] = { .type = NLA_U8 },
+ [ETHA_SETTINGS_TP_MDIX_CTRL] = { .type = NLA_U8 },
+ [ETHA_SETTINGS_TRANSCEIVER] = { .type = NLA_U8 },
+ [ETHA_SETTINGS_WOL_MODES] = { .type = NLA_BITFIELD32,
+ .validation_data = &all_bits },
+ [ETHA_SETTINGS_SOPASS] = { .type = NLA_BINARY,
+ .len = SOPASS_MAX },
+ [ETHA_SETTINGS_MSGLVL] = { .type = NLA_BITFIELD32,
+ .validation_data = &all_bits },
+ [ETHA_SETTINGS_LINK_MODES] = { .type = NLA_NESTED },
+ [ETHA_SETTINGS_PEER_MODES] = { .type = NLA_NESTED },
+ [ETHA_SETTINGS_LINK] = { .type = NLA_FLAG },
+};
+
+/* To keep things simple, reserve space for some attributes which may not
+ * be added to the message (e.g. ETHA_SETTINGS_SOPASS); therefore the length
+ * returned may be bigger than the actual length of the message sent
+ */
+static int settings_size(struct settings_data *data,
+ struct settings_reqinfo *req_info)
+{
+ struct ethtool_link_ksettings *ksettings = &data->ksettings;
+ u32 req_mask = req_info->req_mask;
+ bool compact = req_info->compact;
+ size_t len = 0;
+ int ret = 0;
+
+ if (req_mask & ETH_SETTINGS_IM_LINKINFO) {
+ /* speed */
+ len += nla_total_size(sizeof(u32));
+ /* duplex, autoneg, port, phyaddr, mdix, mdixctrl, transcvr */
+ len += 7 * nla_total_size(sizeof(u8));
+ /* mdio_support */
+ len += nla_total_size(sizeof(struct nla_bitfield32));
+ }
+ if (req_mask & ETH_SETTINGS_IM_LINKMODES) {
+ u32 *supported = (u32 *)ksettings->link_modes.supported;
+ u32 *advertising = (u32 *)ksettings->link_modes.advertising;
+ u32 *lp_advertising =
+ (u32 *)ksettings->link_modes.lp_advertising;
+
+ ret = ethnl_bitset32_size(compact,
+ __ETHTOOL_LINK_MODE_MASK_NBITS,
+ advertising, supported,
+ link_mode_names);
+ if (ret < 0)
+ return ret;
+ len += ret;
+ ret = ethnl_bitset32_size(compact,
+ __ETHTOOL_LINK_MODE_MASK_NBITS,
+ lp_advertising, lp_advertising,
+ link_mode_names);
+ if (ret < 0)
+ return ret;
+ len += ret;
+ }
+ if (req_mask & ETH_SETTINGS_IM_MSGLEVEL)
+ len += nla_total_size(sizeof(struct nla_bitfield32));
+ if (req_mask & ETH_SETTINGS_IM_WOLINFO) {
+ /* wolopts / wol_supported */
+ len += nla_total_size(sizeof(struct nla_bitfield32));
+ /* sopass */
+ len += nla_total_size(SOPASS_MAX);
+ }
+ if (req_mask & ETH_SETTINGS_IM_LINK)
+ len += nla_total_size(sizeof(u32));
+
+ return len;
+}
+
+static int ethnl_get_link_ksettings(struct genl_info *info,
+ struct net_device *dev,
+ struct ethtool_link_ksettings *ksettings)
+{
+ int ret;
+
+ ret = __ethtool_get_link_ksettings(dev, ksettings);
+
+ if (ret < 0)
+ ETHNL_SET_ERRMSG(info, "failed to retrieve link settings");
+ return ret;
+}
+
+static int ethnl_get_legacy_settings(struct genl_info *info,
+ struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ int ret;
+
+ if (!dev->ethtool_ops->get_settings) {
+ /* we already tried ->get_link_ksettings */
+ ETHNL_SET_ERRMSG(info, "link settings retrieval unsupported");
+ return -EOPNOTSUPP;
+ }
+ ret = dev->ethtool_ops->get_settings(dev, cmd);
+ if (ret < 0)
+ ETHNL_SET_ERRMSG(info, "failed to retrieve link settings");
+
+ return ret;
+}
+
+static int ethnl_get_wol(struct genl_info *info, struct net_device *dev,
+ struct ethtool_wolinfo *wolinfo)
+{
+ int ret = __ethtool_get_wol(dev, wolinfo);
+
+ if (ret < 0)
+ ETHNL_SET_ERRMSG(info, "failed to retrieve wol info");
+ return ret;
+}
+
+static int parse_settings_req(struct settings_reqinfo *req_info,
+ struct genl_info *info, struct sk_buff *skb,
+ const struct nlmsghdr *nlhdr)
+{
+ struct nlattr *tb[ETHA_SETTINGS_MAX + 1];
+ int ret;
+
+ memset(req_info, '\0', sizeof(*req_info));
+ req_info->is_privileged = ethnl_is_privileged(skb);
+
+ ret = genlmsg_parse(nlhdr, ðtool_genl_family, tb,
+ ETHA_SETTINGS_MAX, settings_policy,
+ info ? info->extack : NULL);
+ if (ret < 0)
+ return ret;
+
+ if (tb[ETHA_SETTINGS_DEV]) {
+ req_info->dev = ethnl_dev_get(info, tb[ETHA_SETTINGS_DEV]);
+ if (IS_ERR(req_info->dev)) {
+ ret = PTR_ERR(req_info->dev);
+ req_info->dev = NULL;
+ return ret;
+ }
+ }
+ if (tb[ETHA_SETTINGS_INFOMASK])
+ req_info->req_mask = nla_get_u32(tb[ETHA_SETTINGS_INFOMASK]);
+ if (tb[ETHA_SETTINGS_COMPACT])
+ req_info->compact = true;
+ if (req_info->req_mask == 0)
+ req_info->req_mask = ETH_SETTINGS_IM_DEFAULT;
+
+ return 0;
+}
+
+static int prepare_settings(struct settings_data *data,
+ struct settings_reqinfo *req_info,
+ struct genl_info *info, struct net_device *dev)
+{
+ u32 req_mask = req_info->req_mask;
+ int ret;
+
+ memset(data, '\0', sizeof(*data));
+ data->lsettings = &data->ksettings.base;
+ data->lpm_empty = true;
+ data->link = -EOPNOTSUPP;
+
+ if (!req_info->have_rtnl)
+ rtnl_lock();
+ if (req_mask & (ETH_SETTINGS_IM_LINKINFO | ETH_SETTINGS_IM_LINKMODES)) {
+ ret = ethnl_get_link_ksettings(info, dev, &data->ksettings);
+ if (ret < 0) {
+ warn_partial_info(info);
+ req_mask &= ~(ETH_SETTINGS_IM_LINKINFO |
+ ETH_SETTINGS_IM_LINKMODES);
+ }
+ }
+ if (req_mask & ETH_SETTINGS_IM_LINKMODES) {
+ data->lpm_empty = bitmap_empty(data->ksettings.link_modes.lp_advertising,
+ __ETHTOOL_LINK_MODE_MASK_NBITS);
+ ethnl_bitmap_to_u32(data->ksettings.link_modes.supported,
+ __ETHTOOL_LINK_MODE_MASK_NWORDS);
+ ethnl_bitmap_to_u32(data->ksettings.link_modes.advertising,
+ __ETHTOOL_LINK_MODE_MASK_NWORDS);
+ ethnl_bitmap_to_u32(data->ksettings.link_modes.lp_advertising,
+ __ETHTOOL_LINK_MODE_MASK_NWORDS);
+ }
+ if (req_mask & ETH_SETTINGS_IM_MSGLEVEL) {
+ if (dev->ethtool_ops->get_msglevel) {
+ data->msglevel = dev->ethtool_ops->get_msglevel(dev);
+ } else {
+ warn_partial_info(info);
+ req_mask &= ~ETH_SETTINGS_IM_MSGLEVEL;
+ }
+ }
+ if (req_mask & ETH_SETTINGS_IM_WOLINFO) {
+ ret = ethnl_get_wol(info, dev, &data->wolinfo);
+ if (ret < 0) {
+ warn_partial_info(info);
+ req_mask &= ~ETH_SETTINGS_IM_WOLINFO;
+ }
+ }
+ if (req_mask & ETH_SETTINGS_IM_LINK)
+ data->link = __ethtool_get_link(dev);
+ if (!req_info->have_rtnl)
+ rtnl_unlock();
+
+ data->req_mask = req_mask;
+ return 0;
+}
+
+static int fill_settings(struct sk_buff *rskb, struct settings_data *data,
+ struct settings_reqinfo *req_info)
+{
+ struct ethtool_link_settings *lsettings = data->lsettings;
+ u32 req_mask = data->req_mask;
+ bool compact = req_info->compact;
+ int ret;
+
+ ret = -EMSGSIZE;
+ if (req_mask & ETH_SETTINGS_IM_LINKINFO) {
+ if (nla_put_u32(rskb, ETHA_SETTINGS_SPEED, lsettings->speed) ||
+ nla_put_u8(rskb, ETHA_SETTINGS_DUPLEX, lsettings->duplex) ||
+ nla_put_u8(rskb, ETHA_SETTINGS_PORT, lsettings->port) ||
+ nla_put_u8(rskb, ETHA_SETTINGS_PHYADDR,
+ lsettings->phy_address) ||
+ nla_put_u8(rskb, ETHA_SETTINGS_AUTONEG,
+ lsettings->autoneg) ||
+ nla_put_bitfield32(rskb, ETHA_SETTINGS_MDIO_SUPPORT,
+ lsettings->mdio_support,
+ ETH_MDIO_SUPPORTS_ALL) ||
+ nla_put_u8(rskb, ETHA_SETTINGS_TP_MDIX,
+ lsettings->eth_tp_mdix) ||
+ nla_put_u8(rskb, ETHA_SETTINGS_TP_MDIX_CTRL,
+ lsettings->eth_tp_mdix_ctrl) ||
+ nla_put_u8(rskb, ETHA_SETTINGS_TRANSCEIVER,
+ lsettings->transceiver))
+ return ret;
+ }
+ if (req_mask & ETH_SETTINGS_IM_LINKMODES) {
+ u32 *supported = (u32 *)data->ksettings.link_modes.supported;
+ u32 *advertising =
+ (u32 *)data->ksettings.link_modes.advertising;
+ u32 *lp_advertising =
+ (u32 *)data->ksettings.link_modes.lp_advertising;
+
+ ret = ethnl_put_bitset32(rskb, ETHA_SETTINGS_LINK_MODES,
+ compact,
+ __ETHTOOL_LINK_MODE_MASK_NBITS,
+ advertising, supported,
+ link_mode_names);
+ if (ret < 0)
+ return ret;
+ if (!data->lpm_empty) {
+ ret = ethnl_put_bitset32(rskb, ETHA_SETTINGS_PEER_MODES,
+ compact,
+ __ETHTOOL_LINK_MODE_MASK_NBITS,
+ lp_advertising, lp_advertising,
+ link_mode_names);
+ if (ret < 0)
+ return ret;
+ }
+ ret = -EMSGSIZE;
+ }
+ if (req_mask & ETH_SETTINGS_IM_MSGLEVEL) {
+ if (nla_put_bitfield32(rskb, ETHA_SETTINGS_MSGLVL,
+ data->msglevel, NETIF_MSG_ALL))
+ return ret;
+ }
+ if (req_mask & ETH_SETTINGS_IM_WOLINFO) {
+ /* ioctl() restricts read access to wolinfo but the actual
+ * reason is to hide sopass from unprivileged users; netlink
+ * can show wol modes without sopass
+ */
+ if (nla_put_bitfield32(rskb, ETHA_SETTINGS_WOL_MODES,
+ data->wolinfo.wolopts,
+ data->wolinfo.supported))
+ return ret;
+ if (req_info->is_privileged &&
+ nla_put(rskb, ETHA_SETTINGS_SOPASS,
+ sizeof(data->wolinfo.sopass), data->wolinfo.sopass))
+ return ret;
+ }
+ if (req_mask & ETH_SETTINGS_IM_LINK && data->link >= 0) {
+ if (nla_put_u32(rskb, ETHA_SETTINGS_LINK, data->link))
+ return ret;
+ }
+
+ return 0;
+}
+
+int ethnl_get_settings(struct sk_buff *skb, struct genl_info *info)
+{
+ struct settings_data data;
+ struct settings_reqinfo req_info;
+ struct sk_buff *rskb;
+ int reply_len;
+ void *ehdr;
+ int ret;
+
+ ret = parse_settings_req(&req_info, info, skb, info->nlhdr);
+ if (ret < 0)
+ goto err_dev;
+ ret = prepare_settings(&data, &req_info, info, req_info.dev);
+ if (ret < 0)
+ goto err_dev;
+ reply_len = settings_size(&data, &req_info);
+ if (ret < 0)
+ goto err_dev;
+ ret = -ENOMEM;
+ rskb = ethnl_reply_init(reply_len, req_info.dev, ETHNL_CMD_SET_SETTINGS,
+ ETHA_SETTINGS_DEV, info, &ehdr);
+ if (!rskb)
+ goto err_dev;
+ ret = fill_settings(rskb, &data, &req_info);
+ if (ret < 0)
+ goto err;
+
+ genlmsg_end(rskb, ehdr);
+ dev_put(req_info.dev);
+ return genlmsg_reply(rskb, info);
+
+err:
+ WARN_ONCE(ret == -EMSGSIZE,
+ "calculated message payload length (%d) not sufficient\n",
+ reply_len);
+ nlmsg_free(rskb);
+err_dev:
+ if (req_info.dev)
+ dev_put(req_info.dev);
+ return ret;
+}
+
+static int settings_dump(struct sk_buff *skb, struct netlink_callback *cb,
+ struct net_device *dev)
+{
+ struct settings_data data;
+ struct settings_reqinfo *req_info;
+ int ret;
+
+ req_info = (struct settings_reqinfo *)cb->args[4];
+ ret = prepare_settings(&data, req_info, NULL, dev);
+ if (ret < 0)
+ return ret;
+ ret = ethnl_fill_dev(skb, dev, ETHA_SETTINGS_DEV);
+ if (ret < 0)
+ return ret;
+ ret = fill_settings(skb, &data, req_info);
+ return ret;
+}
+
+int ethnl_settings_start(struct netlink_callback *cb)
+{
+ struct settings_reqinfo *req_info;
+ int ret;
+
+ req_info = kmalloc(sizeof(*req_info), GFP_KERNEL);
+ if (!req_info)
+ return -ENOMEM;
+ ret = parse_settings_req(req_info, NULL, cb->skb, cb->nlh);
+ if (ret < 0) {
+ if (req_info->dev)
+ dev_put(req_info->dev);
+ req_info->dev = NULL;
+ return ret;
+ }
+
+ cb->args[0] = (long)settings_dump;
+ cb->args[1] = ETHNL_CMD_SET_SETTINGS;
+ cb->args[4] = (long)req_info;
+
+ return 0;
+}
+
+int ethnl_settings_done(struct netlink_callback *cb)
+{
+ struct settings_reqinfo *req_info;
+
+ req_info = (struct settings_reqinfo *)cb->args[4];
+ if (req_info->dev)
+ dev_put(req_info->dev);
+ kfree(req_info);
+
+ return 0;
+}
--
2.18.0
^ permalink raw reply related
* [RFC PATCH net-next v2 08/17] ethtool: implement GET_STRSET message
From: Michal Kubecek @ 2018-07-30 12:53 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>
Requests a contents of a string set, i.e. indexed array of strings; this
information is provided by ETHTOOL_GSSET_INFO and ETHTOOL_GSTRINGS commands
of ioctl interface. There are three types of requests
- no NLM_F_DUMP, no device: get all "global" stringsets
- no NLM_F_DUMP, with device: get all string sets related to the device
- NLM_F_DUMP, no device: get all device related string sets for all
devices
It's also possible to request only specific string sets.
In addition to string sets recognized by ioctl interface, GET_STRSET
request can also retrieve list of link modes.
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
Documentation/networking/ethtool-netlink.txt | 6 +-
include/uapi/linux/ethtool.h | 4 +
include/uapi/linux/ethtool_netlink.h | 42 ++
net/ethtool/Makefile | 2 +-
net/ethtool/common.c | 87 +++
net/ethtool/common.h | 13 +
net/ethtool/ioctl.c | 80 ---
net/ethtool/netlink.c | 13 +
net/ethtool/strset.c | 552 +++++++++++++++++++
9 files changed, 716 insertions(+), 83 deletions(-)
create mode 100644 net/ethtool/common.c
create mode 100644 net/ethtool/common.h
create mode 100644 net/ethtool/strset.c
diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
index 0e83397f2975..8b43f41a8140 100644
--- a/Documentation/networking/ethtool-netlink.txt
+++ b/Documentation/networking/ethtool-netlink.txt
@@ -119,6 +119,8 @@ List of message types
---------------------
ETHNL_CMD_EVENT notification only
+ ETHNL_CMD_GET_STRSET
+ ETHNL_CMD_SET_STRSET response only
All constants use ETHNL_CMD_ prefix, usually followed by "GET", "SET" or "ACT"
to indicate the type.
@@ -188,7 +190,7 @@ ETHTOOL_STXCSUM n/a
ETHTOOL_GSG n/a
ETHTOOL_SSG n/a
ETHTOOL_TEST n/a
-ETHTOOL_GSTRINGS n/a
+ETHTOOL_GSTRINGS ETHNL_CMD_GET_STRSET
ETHTOOL_PHYS_ID n/a
ETHTOOL_GSTATS n/a
ETHTOOL_GTSO n/a
@@ -216,7 +218,7 @@ ETHTOOL_FLASHDEV n/a
ETHTOOL_RESET n/a
ETHTOOL_SRXNTUPLE n/a
ETHTOOL_GRXNTUPLE n/a
-ETHTOOL_GSSET_INFO n/a
+ETHTOOL_GSSET_INFO ETHNL_CMD_GET_STRSET
ETHTOOL_GRXFHINDIR n/a
ETHTOOL_SRXFHINDIR n/a
ETHTOOL_GFEATURES n/a
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index 7363f18e65a5..2ae393963704 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -578,6 +578,10 @@ enum ethtool_stringset {
ETH_SS_TUNABLES,
ETH_SS_PHY_STATS,
ETH_SS_PHY_TUNABLES,
+ ETH_SS_LINK_MODES,
+
+ __ETH_SS_MAX,
+ ETH_SS_MAX = (__ETH_SS_MAX - 1)
};
/**
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index f162cd6f80d4..5177c1940c2b 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -8,6 +8,8 @@
enum {
ETHNL_CMD_NOOP,
ETHNL_CMD_EVENT, /* only for notifications */
+ ETHNL_CMD_GET_STRSET,
+ ETHNL_CMD_SET_STRSET, /* only for reply */
__ETHNL_CMD_MAX,
ETHNL_CMD_MAX = (__ETHNL_CMD_MAX - 1)
@@ -82,6 +84,46 @@ enum {
ETHA_EVENT_MAX = (__ETHA_EVENT_MAX - 1)
};
+/* string sets */
+
+enum {
+ ETHA_STRING_UNSPEC,
+ ETHA_STRING_INDEX, /* u32 */
+ ETHA_STRING_VALUE, /* string */
+
+ __ETHA_STRING_MAX,
+ ETHA_STRING_MAX = (__ETHA_STRING_MAX - 1)
+};
+
+enum {
+ ETHA_STRINGS_UNSPEC,
+ ETHA_STRINGS_STRING, /* nest - ETHA_STRINGS_* */
+
+ __ETHA_STRINGS_MAX,
+ ETHA_STRINGS_MAX = (__ETHA_STRINGS_MAX - 1)
+};
+
+enum {
+ ETHA_STRINGSET_UNSPEC,
+ ETHA_STRINGSET_ID, /* u32 */
+ ETHA_STRINGSET_COUNT, /* u32 */
+ ETHA_STRINGSET_STRINGS, /* nest - ETHA_STRINGS_* */
+
+ __ETHA_STRINGSET_MAX,
+ ETHA_STRINGSET_MAX = (__ETHA_STRINGSET_MAX - 1)
+};
+
+/* GET_STRINGSET / SET_STRINGSET */
+
+enum {
+ ETHA_STRSET_UNSPEC,
+ ETHA_STRSET_DEV, /* nest - ETHA_DEV_* */
+ ETHA_STRSET_STRINGSET, /* nest - ETHA_STRSET_* */
+
+ __ETHA_STRSET_MAX,
+ ETHA_STRSET_MAX = (__ETHA_STRSET_MAX - 1)
+};
+
/* generic netlink info */
#define ETHTOOL_GENL_NAME "ethtool"
#define ETHTOOL_GENL_VERSION 1
diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile
index f30e0da88be5..ba260d5b53b2 100644
--- a/net/ethtool/Makefile
+++ b/net/ethtool/Makefile
@@ -4,4 +4,4 @@ obj-y += ioctl.o
obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o
-ethtool_nl-y := netlink.o
+ethtool_nl-y := netlink.o strset.o
diff --git a/net/ethtool/common.c b/net/ethtool/common.c
new file mode 100644
index 000000000000..208259c51b73
--- /dev/null
+++ b/net/ethtool/common.c
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#include "common.h"
+
+const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = {
+ [NETIF_F_SG_BIT] = "tx-scatter-gather",
+ [NETIF_F_IP_CSUM_BIT] = "tx-checksum-ipv4",
+ [NETIF_F_HW_CSUM_BIT] = "tx-checksum-ip-generic",
+ [NETIF_F_IPV6_CSUM_BIT] = "tx-checksum-ipv6",
+ [NETIF_F_HIGHDMA_BIT] = "highdma",
+ [NETIF_F_FRAGLIST_BIT] = "tx-scatter-gather-fraglist",
+ [NETIF_F_HW_VLAN_CTAG_TX_BIT] = "tx-vlan-hw-insert",
+
+ [NETIF_F_HW_VLAN_CTAG_RX_BIT] = "rx-vlan-hw-parse",
+ [NETIF_F_HW_VLAN_CTAG_FILTER_BIT] = "rx-vlan-filter",
+ [NETIF_F_HW_VLAN_STAG_TX_BIT] = "tx-vlan-stag-hw-insert",
+ [NETIF_F_HW_VLAN_STAG_RX_BIT] = "rx-vlan-stag-hw-parse",
+ [NETIF_F_HW_VLAN_STAG_FILTER_BIT] = "rx-vlan-stag-filter",
+ [NETIF_F_VLAN_CHALLENGED_BIT] = "vlan-challenged",
+ [NETIF_F_GSO_BIT] = "tx-generic-segmentation",
+ [NETIF_F_LLTX_BIT] = "tx-lockless",
+ [NETIF_F_NETNS_LOCAL_BIT] = "netns-local",
+ [NETIF_F_GRO_BIT] = "rx-gro",
+ [NETIF_F_GRO_HW_BIT] = "rx-gro-hw",
+ [NETIF_F_LRO_BIT] = "rx-lro",
+
+ [NETIF_F_TSO_BIT] = "tx-tcp-segmentation",
+ [NETIF_F_GSO_ROBUST_BIT] = "tx-gso-robust",
+ [NETIF_F_TSO_ECN_BIT] = "tx-tcp-ecn-segmentation",
+ [NETIF_F_TSO_MANGLEID_BIT] = "tx-tcp-mangleid-segmentation",
+ [NETIF_F_TSO6_BIT] = "tx-tcp6-segmentation",
+ [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation",
+ [NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation",
+ [NETIF_F_GSO_GRE_CSUM_BIT] = "tx-gre-csum-segmentation",
+ [NETIF_F_GSO_IPXIP4_BIT] = "tx-ipxip4-segmentation",
+ [NETIF_F_GSO_IPXIP6_BIT] = "tx-ipxip6-segmentation",
+ [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation",
+ [NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation",
+ [NETIF_F_GSO_PARTIAL_BIT] = "tx-gso-partial",
+ [NETIF_F_GSO_SCTP_BIT] = "tx-sctp-segmentation",
+ [NETIF_F_GSO_ESP_BIT] = "tx-esp-segmentation",
+ [NETIF_F_GSO_UDP_L4_BIT] = "tx-udp-segmentation",
+
+ [NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc",
+ [NETIF_F_SCTP_CRC_BIT] = "tx-checksum-sctp",
+ [NETIF_F_FCOE_MTU_BIT] = "fcoe-mtu",
+ [NETIF_F_NTUPLE_BIT] = "rx-ntuple-filter",
+ [NETIF_F_RXHASH_BIT] = "rx-hashing",
+ [NETIF_F_RXCSUM_BIT] = "rx-checksum",
+ [NETIF_F_NOCACHE_COPY_BIT] = "tx-nocache-copy",
+ [NETIF_F_LOOPBACK_BIT] = "loopback",
+ [NETIF_F_RXFCS_BIT] = "rx-fcs",
+ [NETIF_F_RXALL_BIT] = "rx-all",
+ [NETIF_F_HW_L2FW_DOFFLOAD_BIT] = "l2-fwd-offload",
+ [NETIF_F_HW_TC_BIT] = "hw-tc-offload",
+ [NETIF_F_HW_ESP_BIT] = "esp-hw-offload",
+ [NETIF_F_HW_ESP_TX_CSUM_BIT] = "esp-tx-csum-hw-offload",
+ [NETIF_F_RX_UDP_TUNNEL_PORT_BIT] = "rx-udp_tunnel-port-offload",
+ [NETIF_F_HW_TLS_RECORD_BIT] = "tls-hw-record",
+ [NETIF_F_HW_TLS_TX_BIT] = "tls-hw-tx-offload",
+ [NETIF_F_HW_TLS_RX_BIT] = "tls-hw-rx-offload",
+};
+EXPORT_SYMBOL(netdev_features_strings);
+
+const char
+rss_hash_func_strings[ETH_RSS_HASH_FUNCS_COUNT][ETH_GSTRING_LEN] = {
+ [ETH_RSS_HASH_TOP_BIT] = "toeplitz",
+ [ETH_RSS_HASH_XOR_BIT] = "xor",
+ [ETH_RSS_HASH_CRC32_BIT] = "crc32",
+};
+EXPORT_SYMBOL(rss_hash_func_strings);
+
+const char
+tunable_strings[__ETHTOOL_TUNABLE_COUNT][ETH_GSTRING_LEN] = {
+ [ETHTOOL_ID_UNSPEC] = "Unspec",
+ [ETHTOOL_RX_COPYBREAK] = "rx-copybreak",
+ [ETHTOOL_TX_COPYBREAK] = "tx-copybreak",
+ [ETHTOOL_PFC_PREVENTION_TOUT] = "pfc-prevention-tout",
+};
+EXPORT_SYMBOL(tunable_strings);
+
+const char
+phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN] = {
+ [ETHTOOL_ID_UNSPEC] = "Unspec",
+ [ETHTOOL_PHY_DOWNSHIFT] = "phy-downshift",
+};
+EXPORT_SYMBOL(phy_tunable_strings);
diff --git a/net/ethtool/common.h b/net/ethtool/common.h
new file mode 100644
index 000000000000..45c6492e4aee
--- /dev/null
+++ b/net/ethtool/common.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#ifndef _ETHTOOL_COMMON_H
+#define _ETHTOOL_COMMON_H
+
+#include <linux/ethtool.h>
+
+extern const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN];
+extern const char rss_hash_func_strings[ETH_RSS_HASH_FUNCS_COUNT][ETH_GSTRING_LEN];
+extern const char tunable_strings[__ETHTOOL_TUNABLE_COUNT][ETH_GSTRING_LEN];
+extern const char phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN];
+
+#endif /* _ETHTOOL_COMMON_H */
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index c9993c6c2fd4..a91b597073f8 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -55,86 +55,6 @@ EXPORT_SYMBOL(ethtool_op_get_ts_info);
#define ETHTOOL_DEV_FEATURE_WORDS ((NETDEV_FEATURE_COUNT + 31) / 32)
-static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = {
- [NETIF_F_SG_BIT] = "tx-scatter-gather",
- [NETIF_F_IP_CSUM_BIT] = "tx-checksum-ipv4",
- [NETIF_F_HW_CSUM_BIT] = "tx-checksum-ip-generic",
- [NETIF_F_IPV6_CSUM_BIT] = "tx-checksum-ipv6",
- [NETIF_F_HIGHDMA_BIT] = "highdma",
- [NETIF_F_FRAGLIST_BIT] = "tx-scatter-gather-fraglist",
- [NETIF_F_HW_VLAN_CTAG_TX_BIT] = "tx-vlan-hw-insert",
-
- [NETIF_F_HW_VLAN_CTAG_RX_BIT] = "rx-vlan-hw-parse",
- [NETIF_F_HW_VLAN_CTAG_FILTER_BIT] = "rx-vlan-filter",
- [NETIF_F_HW_VLAN_STAG_TX_BIT] = "tx-vlan-stag-hw-insert",
- [NETIF_F_HW_VLAN_STAG_RX_BIT] = "rx-vlan-stag-hw-parse",
- [NETIF_F_HW_VLAN_STAG_FILTER_BIT] = "rx-vlan-stag-filter",
- [NETIF_F_VLAN_CHALLENGED_BIT] = "vlan-challenged",
- [NETIF_F_GSO_BIT] = "tx-generic-segmentation",
- [NETIF_F_LLTX_BIT] = "tx-lockless",
- [NETIF_F_NETNS_LOCAL_BIT] = "netns-local",
- [NETIF_F_GRO_BIT] = "rx-gro",
- [NETIF_F_GRO_HW_BIT] = "rx-gro-hw",
- [NETIF_F_LRO_BIT] = "rx-lro",
-
- [NETIF_F_TSO_BIT] = "tx-tcp-segmentation",
- [NETIF_F_GSO_ROBUST_BIT] = "tx-gso-robust",
- [NETIF_F_TSO_ECN_BIT] = "tx-tcp-ecn-segmentation",
- [NETIF_F_TSO_MANGLEID_BIT] = "tx-tcp-mangleid-segmentation",
- [NETIF_F_TSO6_BIT] = "tx-tcp6-segmentation",
- [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation",
- [NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation",
- [NETIF_F_GSO_GRE_CSUM_BIT] = "tx-gre-csum-segmentation",
- [NETIF_F_GSO_IPXIP4_BIT] = "tx-ipxip4-segmentation",
- [NETIF_F_GSO_IPXIP6_BIT] = "tx-ipxip6-segmentation",
- [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation",
- [NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation",
- [NETIF_F_GSO_PARTIAL_BIT] = "tx-gso-partial",
- [NETIF_F_GSO_SCTP_BIT] = "tx-sctp-segmentation",
- [NETIF_F_GSO_ESP_BIT] = "tx-esp-segmentation",
- [NETIF_F_GSO_UDP_L4_BIT] = "tx-udp-segmentation",
-
- [NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc",
- [NETIF_F_SCTP_CRC_BIT] = "tx-checksum-sctp",
- [NETIF_F_FCOE_MTU_BIT] = "fcoe-mtu",
- [NETIF_F_NTUPLE_BIT] = "rx-ntuple-filter",
- [NETIF_F_RXHASH_BIT] = "rx-hashing",
- [NETIF_F_RXCSUM_BIT] = "rx-checksum",
- [NETIF_F_NOCACHE_COPY_BIT] = "tx-nocache-copy",
- [NETIF_F_LOOPBACK_BIT] = "loopback",
- [NETIF_F_RXFCS_BIT] = "rx-fcs",
- [NETIF_F_RXALL_BIT] = "rx-all",
- [NETIF_F_HW_L2FW_DOFFLOAD_BIT] = "l2-fwd-offload",
- [NETIF_F_HW_TC_BIT] = "hw-tc-offload",
- [NETIF_F_HW_ESP_BIT] = "esp-hw-offload",
- [NETIF_F_HW_ESP_TX_CSUM_BIT] = "esp-tx-csum-hw-offload",
- [NETIF_F_RX_UDP_TUNNEL_PORT_BIT] = "rx-udp_tunnel-port-offload",
- [NETIF_F_HW_TLS_RECORD_BIT] = "tls-hw-record",
- [NETIF_F_HW_TLS_TX_BIT] = "tls-hw-tx-offload",
- [NETIF_F_HW_TLS_RX_BIT] = "tls-hw-rx-offload",
-};
-
-static const char
-rss_hash_func_strings[ETH_RSS_HASH_FUNCS_COUNT][ETH_GSTRING_LEN] = {
- [ETH_RSS_HASH_TOP_BIT] = "toeplitz",
- [ETH_RSS_HASH_XOR_BIT] = "xor",
- [ETH_RSS_HASH_CRC32_BIT] = "crc32",
-};
-
-static const char
-tunable_strings[__ETHTOOL_TUNABLE_COUNT][ETH_GSTRING_LEN] = {
- [ETHTOOL_ID_UNSPEC] = "Unspec",
- [ETHTOOL_RX_COPYBREAK] = "rx-copybreak",
- [ETHTOOL_TX_COPYBREAK] = "tx-copybreak",
- [ETHTOOL_PFC_PREVENTION_TOUT] = "pfc-prevention-tout",
-};
-
-static const char
-phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN] = {
- [ETHTOOL_ID_UNSPEC] = "Unspec",
- [ETHTOOL_PHY_DOWNSHIFT] = "phy-downshift",
-};
-
static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
{
struct ethtool_gfeatures cmd = {
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 543560778c80..237a2cb40be4 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -669,7 +669,20 @@ static struct notifier_block ethnl_netdev_notifier = {
/* genetlink setup */
+int ethnl_get_strset(struct sk_buff *skb, struct genl_info *info);
+
+int ethnl_strset_start(struct netlink_callback *cb);
+
+int ethnl_strset_done(struct netlink_callback *cb);
+
static const struct genl_ops ethtool_genl_ops[] = {
+ {
+ .cmd = ETHNL_CMD_GET_STRSET,
+ .doit = ethnl_get_strset,
+ .start = ethnl_strset_start,
+ .dumpit = ethnl_dumpit,
+ .done = ethnl_strset_done,
+ },
};
static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c
new file mode 100644
index 000000000000..32543c68fae8
--- /dev/null
+++ b/net/ethtool/strset.c
@@ -0,0 +1,552 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include "netlink.h"
+#include "common.h"
+
+enum strset_type {
+ ETH_SS_TYPE_NONE,
+ ETH_SS_TYPE_LEGACY,
+ ETH_SS_TYPE_SIMPLE,
+};
+
+struct strset_info {
+ enum strset_type type;
+ bool per_dev;
+ bool free_data;
+ unsigned int count;
+ union {
+ const char (*legacy)[ETH_GSTRING_LEN];
+ const char * const *simple;
+ void *ptr;
+ } data;
+};
+
+static const struct strset_info info_template[] = {
+ [ETH_SS_TEST] = {
+ .type = ETH_SS_TYPE_LEGACY,
+ .per_dev = true,
+ },
+ [ETH_SS_STATS] = {
+ .type = ETH_SS_TYPE_LEGACY,
+ .per_dev = true,
+ },
+ [ETH_SS_PRIV_FLAGS] = {
+ .type = ETH_SS_TYPE_LEGACY,
+ .per_dev = true,
+ },
+ [ETH_SS_NTUPLE_FILTERS] = {
+ .type = ETH_SS_TYPE_NONE,
+ },
+ [ETH_SS_FEATURES] = {
+ .type = ETH_SS_TYPE_LEGACY,
+ .per_dev = false,
+ .count = ARRAY_SIZE(netdev_features_strings),
+ .data = { .legacy = netdev_features_strings },
+ },
+ [ETH_SS_RSS_HASH_FUNCS] = {
+ .type = ETH_SS_TYPE_LEGACY,
+ .per_dev = false,
+ .count = ARRAY_SIZE(rss_hash_func_strings),
+ .data = { .legacy = rss_hash_func_strings },
+ },
+ [ETH_SS_TUNABLES] = {
+ .type = ETH_SS_TYPE_LEGACY,
+ .per_dev = false,
+ .count = ARRAY_SIZE(tunable_strings),
+ .data = { .legacy = tunable_strings },
+ },
+ [ETH_SS_PHY_STATS] = {
+ .type = ETH_SS_TYPE_LEGACY,
+ .per_dev = true,
+ },
+ [ETH_SS_PHY_TUNABLES] = {
+ .type = ETH_SS_TYPE_LEGACY,
+ .per_dev = false,
+ .count = ARRAY_SIZE(phy_tunable_strings),
+ .data = { .legacy = phy_tunable_strings },
+ },
+ [ETH_SS_LINK_MODES] = {
+ .type = ETH_SS_TYPE_SIMPLE,
+ .per_dev = false,
+ .count = __ETHTOOL_LINK_MODE_MASK_NBITS,
+ .data = { .simple = link_mode_names },
+ },
+};
+
+struct strset_data {
+ struct net_device *dev;
+ struct strset_info info[ETH_SS_MAX + 1];
+};
+
+struct strset_reqinfo {
+ struct net_device *dev;
+ u32 req_ids;
+ bool have_rtnl;
+};
+
+static const struct nla_policy get_strset_policy[ETHA_STRSET_MAX + 1] = {
+ [ETHA_STRSET_DEV] = { .type = NLA_NESTED },
+ [ETHA_STRSET_STRINGSET] = { .type = NLA_NESTED },
+};
+
+static const struct nla_policy stringset_policy[ETHA_STRINGSET_MAX + 1] = {
+ [ETHA_STRINGSET_ID] = { .type = NLA_U32 },
+ [ETHA_STRINGSET_COUNT] = { .type = NLA_U32 },
+ [ETHA_STRINGSET_STRINGS] = { .type = NLA_NESTED },
+};
+
+static int legacy_set_size(const char (*set)[ETH_GSTRING_LEN], unsigned count)
+{
+ unsigned len = 0;
+ unsigned int i;
+
+ for (i = 0; i < count; i++)
+ len += nla_total_size(nla_total_size(sizeof(u32)) +
+ ethnl_str_size(set[i]));
+ len = 2 * nla_total_size(sizeof(u32)) + nla_total_size(len);
+
+ return nla_total_size(len);
+}
+
+static int simple_set_size(const char * const *set, unsigned count)
+{
+ unsigned len = 0;
+ unsigned int i;
+
+ for (i = 0; i < count; i++)
+ len += nla_total_size(nla_total_size(sizeof(u32)) +
+ ethnl_str_size(set[i]));
+ len = 2 * nla_total_size(sizeof(u32)) + nla_total_size(len);
+
+ return nla_total_size(len);
+}
+
+static int set_size(const struct strset_info *info)
+{
+ if (info->count == 0)
+ return 0;
+
+ switch(info->type) {
+ case ETH_SS_TYPE_LEGACY:
+ return legacy_set_size(info->data.legacy, info->count);
+ case ETH_SS_TYPE_SIMPLE:
+ return simple_set_size(info->data.simple, info->count);
+ default:
+ return -EINVAL;
+ };
+}
+
+static bool id_requested(const struct strset_reqinfo *req_info, u32 id)
+{
+ return req_info->req_ids & (1U << id);
+}
+
+static bool include_set(struct strset_data *data,
+ struct strset_reqinfo *req_info, u32 id)
+{
+ /* once ETH_SS_MAX reaches 32, we will need to change
+ * strset_info::req_ids to u64; one day we might even need to use
+ * generic bitmap but let's not complicate the code prematurely
+ */
+ BUILD_BUG_ON(ETH_SS_MAX >= BITS_PER_BYTE * sizeof(req_info->req_ids));
+
+ if (req_info->req_ids)
+ return id_requested(req_info, id);
+ else {
+ bool per_dev = data->info[id].per_dev;
+
+ if (data->info[id].type == ETH_SS_TYPE_NONE)
+ return false;
+ return data->dev ? per_dev : !per_dev;
+ }
+}
+
+static int strset_size(struct strset_data *data,
+ struct strset_reqinfo *req_info)
+{
+ unsigned int i;
+ int len = 0;
+ int ret;
+ for (i = 0; i <= ETH_SS_MAX; i++) {
+ const struct strset_info *info = &data->info[i];
+
+ if (!include_set(data, req_info, i) ||
+ (info->type == ETH_SS_TYPE_NONE))
+ continue;
+
+ ret = set_size(info);
+ if (ret < 0)
+ return ret;
+ else
+ len += ret;
+ }
+
+ return len;
+}
+
+const char *str_value(struct strset_info *info, unsigned int i)
+{
+ switch(info->type) {
+ case ETH_SS_TYPE_LEGACY:
+ return info->data.legacy[i];
+ case ETH_SS_TYPE_SIMPLE:
+ return info->data.simple[i];
+ default:
+ WARN_ONCE(1, "unexpected string set type");
+ return "";
+ }
+}
+
+static int get_strset_id(const struct nlattr *nest, u32 *val,
+ struct genl_info *info)
+{
+ struct nlattr *tb[ETHA_STRINGSET_MAX + 1];
+ int ret;
+
+ ret = nla_parse_nested(tb, ETHA_STRINGSET_MAX, nest, stringset_policy,
+ info ? info->extack : NULL);
+ if (ret < 0)
+ return ret;
+ if (!tb[ETHA_STRINGSET_ID])
+ return -EINVAL;
+
+ *val = nla_get_u32(tb[ETHA_STRINGSET_ID]);
+ return 0;
+}
+
+static int parse_strset_req(struct strset_reqinfo *req_info,
+ struct genl_info *info, struct sk_buff *skb,
+ const struct nlmsghdr *nlhdr)
+{
+ struct nlattr *tb[ETHA_STRSET_MAX + 1];
+ int ret;
+
+ memset(req_info, '\0', sizeof(*req_info));
+
+ ret = genlmsg_parse(nlhdr, ðtool_genl_family, tb,
+ ETHA_STRSET_MAX, get_strset_policy,
+ info ? info->extack : NULL);
+ if (ret < 0)
+ return ret;
+
+ if (tb[ETHA_STRSET_DEV]) {
+ req_info->dev = ethnl_dev_get(info, tb[ETHA_STRSET_DEV]);
+ if (IS_ERR(req_info->dev)) {
+ ret = PTR_ERR(req_info->dev);
+ req_info->dev = NULL;
+ return ret;
+ }
+ }
+ if (tb[ETHA_STRSET_STRINGSET]) {
+ struct nlattr *set;
+ int rem;
+
+ nlmsg_for_each_attr(set, nlhdr, GENL_HDRLEN, rem) {
+ u32 id;
+
+ ret = get_strset_id(set, &id, info);
+ if (ret < 0)
+ return ret;
+ if (ret > ETH_SS_MAX)
+ return -EOPNOTSUPP;
+ req_info->req_ids |= (1U << id);
+ }
+ }
+
+ return 0;
+}
+
+static void free_strset(struct strset_data *data)
+{
+ unsigned int i;
+
+ for (i = 0; i <= ETH_SS_MAX; i++)
+ if (data->info[i].free_data) {
+ kfree(data->info[i].data.ptr);
+ data->info[i].data.ptr = NULL;
+ data->info[i].free_data = false;
+ }
+}
+
+static int prepare_one_stringset(struct strset_info *info,
+ struct net_device *dev, unsigned int id)
+{
+ const struct ethtool_ops *ops = dev->ethtool_ops;
+ void *strings;
+ int count, ret;
+
+
+ if (id == ETH_SS_PHY_STATS && dev->phydev &&
+ !ops->get_ethtool_phy_stats)
+ ret = phy_ethtool_get_sset_count(dev->phydev);
+ else if (ops->get_sset_count && ops->get_strings)
+ ret = ops->get_sset_count(dev, id);
+ else
+ ret = -EOPNOTSUPP;
+ if (ret <= 0) {
+ info->count = 0;
+ return 0;
+ }
+
+ count = ret;
+ strings = kcalloc(count, ETH_GSTRING_LEN, GFP_KERNEL);
+ if (!strings)
+ return -ENOMEM;
+ if (id == ETH_SS_PHY_STATS && dev->phydev &&
+ !ops->get_ethtool_phy_stats)
+ phy_ethtool_get_strings(dev->phydev, strings);
+ else
+ ops->get_strings(dev, id, strings);
+ info->count = count;
+ info->data.legacy = strings;
+ info->free_data = true;
+
+ return 0;
+}
+
+static int prepare_strset(struct strset_data *data,
+ struct strset_reqinfo *req_info,
+ struct genl_info *info, struct net_device *dev)
+{
+ unsigned int i;
+ int ret;
+
+ memset(data, '\0', sizeof(*data));
+ memcpy(&data->info, &info_template, sizeof(data->info));
+ data->dev = dev;
+
+ if (!dev)
+ for (i = 0; i <= ETH_SS_MAX; i++)
+ if (id_requested(req_info, i) &&
+ data->info[i].per_dev) {
+ ETHNL_SET_ERRMSG(info,
+ "requested per device strings without dev");
+ return -EINVAL;
+ }
+
+ if (!req_info->have_rtnl)
+ rtnl_lock();
+ for (i = 0; i <= ETH_SS_MAX; i++) {
+ if (!include_set(data, req_info, i) || !data->info[i].per_dev)
+ continue;
+ if (WARN_ONCE(data->info[i].type != ETH_SS_TYPE_LEGACY,
+ "unexpected string set type %u",
+ data->info[i].type))
+ goto err_free;
+
+ ret = prepare_one_stringset(&data->info[i], dev, i);
+ if (ret < 0)
+ goto err_free;
+ }
+ if (!req_info->have_rtnl)
+ rtnl_unlock();
+
+ return 0;
+err_free:
+ if (!req_info->have_rtnl)
+ rtnl_unlock();
+ free_strset(data);
+ return ret;
+}
+
+static int fill_set(struct sk_buff *skb, struct strset_data *data, u32 id)
+{
+ struct strset_info *info = &data->info[id];
+ struct nlattr *strings;
+ struct nlattr *nest;
+ unsigned int i = (unsigned int)(-1);
+
+ if (info->type == ETH_SS_TYPE_NONE)
+ return -EOPNOTSUPP;
+ if (info->count == 0)
+ return 0;
+ nest = ethnl_nest_start(skb, ETHA_STRSET_STRINGSET);
+ if (!nest)
+ return -EMSGSIZE;
+
+ if (nla_put_u32(skb, ETHA_STRINGSET_ID, id) ||
+ nla_put_u32(skb, ETHA_STRINGSET_COUNT, info->count))
+ goto err;
+
+ strings = ethnl_nest_start(skb, ETHA_STRINGSET_STRINGS);
+ if (!strings)
+ goto err;
+ for (i = 0; i < info->count; i++) {
+ struct nlattr *string = ethnl_nest_start(skb,
+ ETHA_STRINGS_STRING);
+
+ if (!string)
+ goto err;
+ if (nla_put_u32(skb, ETHA_STRING_INDEX, i) ||
+ nla_put_string(skb, ETHA_STRING_VALUE, str_value(info, i)))
+ goto err;
+ nla_nest_end(skb, string);
+ }
+ nla_nest_end(skb, strings);
+
+ nla_nest_end(skb, nest);
+ return 0;
+
+err:
+ nla_nest_cancel(skb, nest);
+ return -EMSGSIZE;
+}
+
+static int fill_strset(struct sk_buff *skb, struct strset_data *data,
+ struct strset_reqinfo *req_info)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i <= ETH_SS_MAX; i++)
+ if (include_set(data, req_info, i)) {
+ ret = fill_set(skb, data, i);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+int ethnl_get_strset(struct sk_buff *skb, struct genl_info *info)
+{
+ struct strset_data data;
+ struct strset_reqinfo req_info;
+ struct sk_buff *rskb;
+ int reply_len;
+ void *ehdr;
+ int ret;
+
+ ret = parse_strset_req(&req_info, info, skb, info->nlhdr);
+ if (ret < 0)
+ goto err_dev;
+ ret = prepare_strset(&data, &req_info, info, req_info.dev);
+ if (ret < 0)
+ goto err_dev;
+ ret = strset_size(&data, &req_info);
+ if (ret < 0)
+ goto err_data;
+ reply_len = ret;
+ ret = -ENOMEM;
+ rskb = ethnl_reply_init(reply_len, req_info.dev, ETHNL_CMD_SET_STRSET,
+ ETHA_STRSET_DEV, info, &ehdr);
+ if (!rskb)
+ goto err_data;
+ ret = fill_strset(rskb, &data, &req_info);
+ if (ret < 0)
+ goto err;
+
+ genlmsg_end(rskb, ehdr);
+ free_strset(&data);
+ if (req_info.dev)
+ dev_put(req_info.dev);
+ return genlmsg_reply(rskb, info);
+
+err:
+ WARN_ONCE(ret == -EMSGSIZE,
+ "calculated message payload length (%d) not sufficient\n",
+ reply_len);
+ nlmsg_free(rskb);
+err_data:
+ free_strset(&data);
+err_dev:
+ if (req_info.dev)
+ dev_put(req_info.dev);
+ return ret;
+}
+
+static int strset_dump(struct sk_buff *skb, struct netlink_callback *cb,
+ struct net_device *dev)
+{
+ struct strset_data data;
+ struct strset_reqinfo *req_info;
+ int ret;
+
+ req_info = (struct strset_reqinfo *)cb->args[4];
+ ret = prepare_strset(&data, req_info, NULL, dev);
+ if (ret < 0)
+ return ret;
+ ret = ethnl_fill_dev(skb, dev, ETHA_STRSET_DEV);
+ if (ret < 0)
+ goto out;
+ ret = fill_strset(skb, &data, req_info);
+out:
+ free_strset(&data);
+ return ret;
+}
+
+int ethnl_strset_start(struct netlink_callback *cb)
+{
+ struct strset_reqinfo *req_info;
+ int ret;
+
+ req_info = kmalloc(sizeof(*req_info), GFP_KERNEL);
+ if (!req_info)
+ return -ENOMEM;
+ ret = parse_strset_req(req_info, NULL, cb->skb, cb->nlh);
+ if (ret < 0) {
+ if (req_info->dev)
+ dev_put(req_info->dev);
+ req_info->dev = NULL;
+ return ret;
+ }
+
+ cb->args[0] = (long)strset_dump;
+ cb->args[1] = ETHNL_CMD_SET_STRSET;
+ cb->args[4] = (long)req_info;
+ cb->min_dump_alloc = 65535;
+
+ return 0;
+}
+
+int ethnl_strset_done(struct netlink_callback *cb)
+{
+ struct strset_reqinfo *req_info;
+
+ req_info = (struct strset_reqinfo *)cb->args[4];
+ if (req_info->dev)
+ dev_put(req_info->dev);
+ kfree(req_info);
+
+ return 0;
+}
+
+void ethnl_strset_notify(struct netdev_notifier_ethtool_info *info)
+{
+ struct strset_reqinfo req_info = {
+ .dev = info->info.dev,
+ .have_rtnl = true,
+ };
+ struct strset_data data;
+ struct sk_buff *skb;
+ int reply_len;
+ void *ehdr;
+ int ret;
+
+ ret = prepare_strset(&data, &req_info, NULL, req_info.dev);
+ if (ret < 0)
+ return;
+ reply_len = strset_size(&data, &req_info);
+ if (reply_len < 0)
+ return;
+ skb = genlmsg_new(reply_len, GFP_KERNEL);
+ if (!skb)
+ return;
+ ehdr = genlmsg_put(skb, 0, ++ethnl_bcast_seq, ðtool_genl_family, 0,
+ ETHNL_CMD_SET_STRSET);
+ ret = ethnl_fill_dev(skb, req_info.dev, ETHA_STRSET_DEV);
+ if (ret < 0)
+ goto err_skb;
+ ret = fill_strset(skb, &data, &req_info);
+ if (ret < 0)
+ goto err_skb;
+ genlmsg_end(skb, ehdr);
+
+ genlmsg_multicast(ðtool_genl_family, skb, 0, ETHNL_MCGRP_MONITOR,
+ GFP_KERNEL);
+ return;
+err_skb:
+ nlmsg_free(skb);
+}
--
2.18.0
^ permalink raw reply related
* [PATCH net-next] net: phy: mscc: the extended page access register is 16 bits
From: Quentin Schulz @ 2018-07-30 12:53 UTC (permalink / raw)
To: andrew, f.fainelli, davem
Cc: netdev, alexandre.belloni, linux-kernel, thomas.petazzoni,
Quentin Schulz
The Extended Page Access is a 16-bit register, so change the page
parameter of vsc85xx_phy_page_set to a u16.
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
drivers/net/phy/mscc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index 650c2667d523..84ca9ff40ae0 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -123,7 +123,7 @@ static const struct vsc8531_edge_rate_table edge_table[] = {
};
#endif /* CONFIG_OF_MDIO */
-static int vsc85xx_phy_page_set(struct phy_device *phydev, u8 page)
+static int vsc85xx_phy_page_set(struct phy_device *phydev, u16 page)
{
int rc;
--
2.17.1
^ permalink raw reply related
* [RFC PATCH net-next v2 05/17] ethtool: netlink bitset handling
From: Michal Kubecek @ 2018-07-30 12:53 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>
Declare attribute type constants and add helper functions to handle
arbitrary length bit sets.
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
Documentation/networking/ethtool-netlink.txt | 56 +++
include/uapi/linux/ethtool_netlink.h | 31 ++
net/ethtool/netlink.c | 395 +++++++++++++++++++
net/ethtool/netlink.h | 26 ++
4 files changed, 508 insertions(+)
diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
index 120376e0f91b..a49dfe3ef4bb 100644
--- a/Documentation/networking/ethtool-netlink.txt
+++ b/Documentation/networking/ethtool-netlink.txt
@@ -59,6 +59,62 @@ provided by kernel. In dump requests, device is not specified and kernel
replies with one message per network device (only those for which the request
is supported).
+Bit sets
+--------
+
+For short bitmaps of (reasonably) fixed length, standard NLA_BITFIELD32 type
+is used. For arbitrary length bitmaps, ethtool netlink uses a nested attribute
+with contents of one of two forms: compact (two binary bitmaps representing
+bit values and mask of affected bits) and bit-by-bit (list of bits identified
+by either index or name).
+
+Compact form: nested (bitset) atrribute contents:
+
+ ETHA_BITSET_SIZE (u32) number of significant bits
+ ETHA_BITSET_VALUE (binary) bitmap of bit values
+ ETHA_BITSET_MASK (binary) bitmap of valid bits
+
+Value and mask must have length at least ETHA_BITSET_SIZE bits rounded up to
+a multiple of 32 bits. They consist of 32-bit words in host byt order, words
+ordered from least significant to most significant (i.e. the same way as
+bitmaps are passed with ioctl interface).
+
+For compact form, ETHA_BITSET_SIZE and ETHA_BITSET_VALUE are mandatory.
+Similar to BITFIELD32, a compact form bit set requests to set bits in the mask
+to 1 (if set in value) or 0 (if not) and preserve the rest. If the mask is
+omitted, it is supposed to be "all ones", i.e. set all bits according to
+value.
+
+Kernel bit set length may differ from userspace length if older application is
+used on newer kernel or vice versa. If userspace bitmaps are longer, error is
+only issued if request actually tries to set bits not implemented in kernel.
+
+Bit-by-bit form: nested (bitset) attribute contents:
+
+ ETHA_BITSET_SIZE (u32) number of significant bits (optional)
+ ETHA_BITSET_BITS (nested) array of bits
+ ETHA_BITSET_BIT
+ ETHA_BIT_INDEX (u32) bit index (0 for LSB)
+ ETHA_BIT_NAME (string) bit name
+ ETHA_BIT_VALUE (flag) present if bit is set
+ ETHA_BITSET_BIT
+ ...
+
+Bit size is optional for bit-by-bit form. ETHA_BITSET_BITS nest can only
+contain ETHA_BITS_BIT attributes but there can be an arbitrary number of them.
+A bit may be identified by its index or by its name. When used in requests,
+listed bits are set to 0 or 1 according to ETHA_BIT_VALUE, the rest is
+preserved. A request fails if index exceeds kernel bit length or if name is
+not recognized.
+
+In requests, application can use either form. Form used by kernel in reply is
+determined by a flag in flags field of request header. Semantics of value and
+mask depends on the attribute. General idea is that flags control request
+processing, info_mask control which parts of the information are returned in
+"get" request and index identifies a particular subcommand or an object to
+which the request applies.
+
+
List of message types
---------------------
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index 1df263d9feb7..98d6fae315f3 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -23,6 +23,37 @@ enum {
ETHA_DEV_MAX = (__ETHA_DEV_MAX - 1)
};
+/* bit sets */
+
+enum {
+ ETHA_BIT_UNSPEC,
+ ETHA_BIT_INDEX, /* u32 */
+ ETHA_BIT_NAME, /* string */
+ ETHA_BIT_VALUE, /* flag */
+
+ __ETHA_BIT_MAX,
+ ETHA_BIT_MAX = (__ETHA_BIT_MAX - 1)
+};
+
+enum {
+ ETHA_BITS_UNSPEC,
+ ETHA_BITS_BIT,
+
+ __ETHA_BITS_MAX,
+ ETHA_BITS_MAX = (__ETHA_BITS_MAX - 1)
+};
+
+enum {
+ ETHA_BITSET_UNSPEC,
+ ETHA_BITSET_SIZE, /* u32 */
+ ETHA_BITSET_BITS, /* nest - ETHA_BITS_* */
+ ETHA_BITSET_VALUE, /* binary */
+ ETHA_BITSET_MASK, /* binary */
+
+ __ETHA_BITSET_MAX,
+ ETHA_BITSET_MAX = (__ETHA_BITSET_MAX - 1)
+};
+
/* generic netlink info */
#define ETHTOOL_GENL_NAME "ethtool"
#define ETHTOOL_GENL_VERSION 1
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index bf234e5bc660..df065fd3dc80 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#include <linux/module.h>
+#include <linux/bitmap.h>
#include <net/sock.h>
#include <linux/ethtool_netlink.h>
#include "netlink.h"
@@ -67,6 +68,400 @@ int ethnl_fill_dev(struct sk_buff *msg, struct net_device *dev, u16 attrtype)
return ret;
}
+/* bitset helper functions */
+
+static bool ethnl_test_bit(u32 *val, unsigned int index)
+{
+ if (val)
+ return val[index / 32] & (1 << (index % 32));
+ else
+ return true;
+}
+
+static void ethnl_copy_bitmap(u32 *dst, u32 *src, unsigned int size)
+{
+ unsigned int full_words = size / 32;
+
+ memcpy(dst, src, full_words * sizeof(u32));
+ if (size % 32 != 0)
+ dst[full_words] = src[full_words] & ((1U << (size % 32)) - 1);
+}
+
+static void ethnl_fill_bitmap(u32 *dst, unsigned int size)
+{
+ unsigned int full_words = size / 32;
+
+ memset(dst, 0xff, full_words * sizeof(u32));
+ if (size % 32 != 0)
+ dst[full_words] = (1U << (size % 32)) - 1;
+}
+
+/* convert standard kernel bitmap (long sized words) to ethtool one (u32 words)
+ * bitmap_to_arr32() is not guaranteed to do "in place" conversion correctly;
+ * moreover, we can use the fact that the conversion is no-op except for 64-bit
+ * big endian architectures
+ */
+#if BITS_PER_LONG == 64 && defined(__BIG_ENDIAN)
+void ethnl_bitmap_to_u32(unsigned long *bitmap, unsigned int nwords)
+{
+ u32 *dst = (u32 *)bitmap;
+ unsigned int i;
+
+ for (i = 0; i < nwords; i++) {
+ unsigned long tmp = READ_ONCE(bitmap[i]);
+
+ dst[2 * i] = tmp & 0xffffffff;
+ dst[2 * i + 1] = tmp >> 32;
+ }
+}
+#endif
+
+/* calculate size for a bitset attribute
+ * see ethnl_put_bitset() for arguments
+ */
+int ethnl_bitset32_size(bool compact, unsigned int size, u32 *val, u32 *mask,
+ const char *const *names)
+{
+ unsigned int nwords = (size + 31) / 32;
+ unsigned int len;
+
+ if (WARN_ON(!compact && !names))
+ return -EINVAL;
+ /* size */
+ len = nla_total_size(sizeof(u32));
+
+ if (compact) {
+ /* values, mask */
+ len += 2 * nla_total_size(nwords * sizeof(u32));
+ } else {
+ unsigned int bits_len = 0;
+ unsigned int bit_len, i;
+
+ for (i = 0; i < size; i++) {
+ if (!ethnl_test_bit(mask, i))
+ continue;
+ /* index */
+ bit_len = nla_total_size(sizeof(u32));
+ /* name */
+ bit_len += ethnl_str_size(names[i] ?: "");
+ /* value */
+ if (ethnl_test_bit(val, i))
+ bit_len += nla_total_size(0);
+
+ /* bit nest */
+ bits_len += nla_total_size(bit_len);
+ }
+ len += nla_total_size(bits_len);
+ }
+
+ /* outermost nest */
+ return nla_total_size(len);
+}
+
+int ethnl_bitset_size(bool compact, unsigned int size, unsigned long *val,
+ unsigned long *mask, const char *const *names)
+{
+ const unsigned int words = (size + 31) / 32;
+ u32 mask32[words];
+ u32 val32[words];
+ int ret;
+
+ bitmap_to_arr32(val32, val, size);
+ if (mask)
+ bitmap_to_arr32(mask32, mask, size);
+ ret = ethnl_bitset32_size(compact, size, val32, mask ? mask32 : NULL,
+ names);
+ bitmap_from_arr32(val, val32, size);
+ if (mask)
+ bitmap_from_arr32(mask, mask32, size);
+
+ return ret;
+}
+
+/* put bitset into a message
+ * skb: skb with the message
+ * attrtype: attribute type for the bitset
+ * compact: compact (bitmaps) or verbose (bit-by-bit with names) format
+ * size: size of the set in bits
+ * val: bitset values
+ * mask: mask of valid bits
+ * names: bit names (only used for verbose format)
+ */
+int ethnl_put_bitset32(struct sk_buff *skb, int attrtype, bool compact,
+ unsigned int size, u32 *val, u32 *mask,
+ const char *const *names)
+{
+ struct nlattr *nest;
+ struct nlattr *attr;
+ int ret;
+
+ if (WARN_ON(!compact && !names))
+ return -EINVAL;
+ nest = ethnl_nest_start(skb, attrtype);
+ if (!nest)
+ return -EMSGSIZE;
+
+ ret = -EMSGSIZE;
+ if (nla_put_u32(skb, ETHA_BITSET_SIZE, size))
+ goto err;
+ if (compact) {
+ unsigned int bytesize = ((size + 31) / 32) * sizeof(u32);
+
+ ret = -EMSGSIZE;
+ attr = nla_reserve(skb, ETHA_BITSET_VALUE, bytesize);
+ if (!attr)
+ goto err;
+ ethnl_copy_bitmap(nla_data(attr), val, size);
+ attr = nla_reserve(skb, ETHA_BITSET_MASK, bytesize);
+ if (!attr)
+ goto err;
+ if (mask)
+ ethnl_copy_bitmap(nla_data(attr), mask, size);
+ else
+ ethnl_fill_bitmap(nla_data(attr), size);
+ } else {
+ struct nlattr *bits;
+ unsigned int i;
+
+ bits = ethnl_nest_start(skb, ETHA_BITSET_BITS);
+ if (!bits)
+ goto err;
+ for (i = 0; i < size; i++) {
+ if (!ethnl_test_bit(mask, i))
+ continue;
+ attr = ethnl_nest_start(skb, ETHA_BITS_BIT);
+ if (!attr ||
+ nla_put_u32(skb, ETHA_BIT_INDEX, i) ||
+ nla_put_string(skb, ETHA_BIT_NAME, names[i] ?: ""))
+ goto err;
+ if (ethnl_test_bit(val, i))
+ if (nla_put_flag(skb, ETHA_BIT_VALUE))
+ goto err;
+ nla_nest_end(skb, attr);
+ }
+ nla_nest_end(skb, bits);
+ }
+
+ nla_nest_end(skb, nest);
+ return 0;
+err:
+ nla_nest_cancel(skb, nest);
+ return ret;
+}
+
+int ethnl_put_bitset(struct sk_buff *skb, int attrtype, bool compact,
+ unsigned int size, unsigned long *val, unsigned long *mask,
+ const char *const *names)
+{
+ const unsigned int words = (size + 31) / 32;
+ u32 mask32[words];
+ u32 val32[words];
+ int ret;
+
+ bitmap_to_arr32(val32, val, size);
+ if (mask)
+ bitmap_to_arr32(mask32, mask, size);
+ ret = ethnl_put_bitset32(skb, attrtype, compact, size, val32,
+ mask ? mask32 : NULL, names);
+ bitmap_from_arr32(val, val32, size);
+ if (mask)
+ bitmap_from_arr32(mask, mask32, size);
+
+ return ret;
+}
+
+static const struct nla_policy bitset_policy[ETHA_BITSET_MAX + 1] = {
+ [ETHA_BITSET_UNSPEC] = { .type = NLA_UNSPEC },
+ [ETHA_BITSET_SIZE] = { .type = NLA_U32 },
+ [ETHA_BITSET_BITS] = { .type = NLA_NESTED },
+ [ETHA_BITSET_VALUE] = { .type = NLA_BINARY },
+ [ETHA_BITSET_MASK] = { .type = NLA_BINARY },
+};
+
+static const struct nla_policy bit_policy[ETHA_BIT_MAX + 1] = {
+ [ETHA_BIT_UNSPEC] = { .type = NLA_UNSPEC },
+ [ETHA_BIT_INDEX] = { .type = NLA_U32 },
+ [ETHA_BIT_NAME] = { .type = NLA_STRING },
+ [ETHA_BIT_VALUE] = { .type = NLA_FLAG },
+};
+
+static int ethnl_name_to_idx(const char *const *names, unsigned int n_names,
+ const char *name, unsigned int name_len)
+{
+ unsigned int i;
+
+ for (i = 0; i < n_names; i++)
+ if (names[i] && !strncmp(names[i], name, name_len))
+ return i;
+
+ return n_names;
+}
+
+static int ethnl_update_bit(unsigned long *bitmap, unsigned long *bitmask,
+ unsigned int nbits, struct nlattr *bit_attr,
+ const char *const *names, struct genl_info *info)
+{
+ struct nlattr *tb[ETHA_BIT_MAX + 1];
+ int ret, idx;
+
+ if (nla_type(bit_attr) != ETHA_BITS_BIT) {
+ ETHNL_SET_ERRMSG(info,
+ "ETHA_BITSET_BITS can contain only ETHA_BITS_BIT");
+ return genl_err_attr(info, -EINVAL, bit_attr);
+ }
+ ret = nla_parse_nested(tb, ETHA_BIT_MAX, bit_attr, bit_policy,
+ info->extack);
+ if (ret < 0)
+ return ret;
+
+ if (tb[ETHA_BIT_INDEX]) {
+ idx = nla_get_u32(tb[ETHA_BIT_INDEX]);
+ if (idx >= nbits) {
+ ETHNL_SET_ERRMSG(info, "bit index too high");
+ return genl_err_attr(info, -EOPNOTSUPP,
+ tb[ETHA_BIT_INDEX]);
+ }
+ if (tb[ETHA_BIT_NAME] && names[idx] &&
+ strncmp(nla_data(tb[ETHA_BIT_NAME]), names[idx],
+ nla_len(tb[ETHA_BIT_NAME]))) {
+ ETHNL_SET_ERRMSG(info, "bit index and name mismatch");
+ return genl_err_attr(info, -EINVAL, bit_attr);
+ }
+ } else if (tb[ETHA_BIT_NAME]) {
+ idx = ethnl_name_to_idx(names, nbits,
+ nla_data(tb[ETHA_BIT_NAME]),
+ nla_len(tb[ETHA_BIT_NAME]));
+ if (idx >= nbits) {
+ ETHNL_SET_ERRMSG(info, "bit name not found");
+ return genl_err_attr(info, -EOPNOTSUPP,
+ tb[ETHA_BIT_NAME]);
+ }
+ } else {
+ ETHNL_SET_ERRMSG(info, "neither bit index nor name specified");
+ return genl_err_attr(info, -EINVAL, bit_attr);
+ }
+
+ if (tb[ETHA_BIT_VALUE])
+ set_bit(idx, bitmap);
+ else
+ clear_bit(idx, bitmap);
+ if (bitmask)
+ set_bit(idx, bitmask);
+ return 0;
+}
+
+bool ethnl_update_bitset(unsigned long *bitmap, unsigned long *bitmask,
+ unsigned int nbits, struct nlattr *attr, int *err,
+ const char *const *names, struct genl_info *info)
+{
+ struct nlattr *tb[ETHA_BITSET_MAX + 1];
+ unsigned int change_bits = 0;
+ bool mod = false;
+
+ if (!attr)
+ return false;
+ *err = nla_parse_nested(tb, ETHA_BITSET_MAX, attr, bitset_policy,
+ info->extack);
+ if (*err < 0)
+ return mod;
+
+ /* To let new userspace to work with old kernel, we allow bitmaps
+ * from userspace to be longer than kernel ones and only issue an
+ * error if userspace actually tries to change a bit not existing
+ * in kernel.
+ */
+ if (tb[ETHA_BITSET_SIZE])
+ change_bits = nla_get_u32(tb[ETHA_BITSET_SIZE]);
+
+ if (tb[ETHA_BITSET_BITS]) {
+ DECLARE_BITMAP(val, nbits);
+ DECLARE_BITMAP(mask, nbits);
+ struct nlattr *bit_attr;
+ int rem;
+
+ *err = -EINVAL;
+ if (tb[ETHA_BITSET_VALUE] || tb[ETHA_BITSET_MASK])
+ return mod;
+ bitmap_copy(val, bitmap, nbits);
+ bitmap_zero(mask, nbits);
+ nla_for_each_nested(bit_attr, tb[ETHA_BITSET_BITS], rem) {
+ *err = ethnl_update_bit(val, mask, nbits, bit_attr,
+ names, info);
+ if (*err < 0)
+ return mod;
+ }
+ mod = !bitmap_equal(val, bitmap, nbits);
+ if (mod)
+ bitmap_copy(bitmap, val, nbits);
+ if (bitmask)
+ bitmap_copy(bitmask, mask, nbits);
+ } else {
+ const unsigned int max_bits =
+ max_t(unsigned int, nbits, change_bits);
+ unsigned int nwords = (change_bits + 31) / 32;
+ DECLARE_BITMAP(mask, max_bits);
+ DECLARE_BITMAP(val, max_bits);
+
+ *err = -EINVAL;
+ if (!change_bits || !tb[ETHA_BITSET_VALUE])
+ return mod;
+ if (nla_len(tb[ETHA_BITSET_VALUE]) < nwords * sizeof(u32))
+ return mod;
+ if (tb[ETHA_BITSET_MASK] &&
+ nla_len(tb[ETHA_BITSET_VALUE]) < nwords * sizeof(u32))
+ return mod;
+
+ bitmap_zero(val, max_bits);
+ bitmap_from_arr32(val, nla_data(tb[ETHA_BITSET_VALUE]),
+ change_bits);
+ bitmap_zero(mask, max_bits);
+ if (tb[ETHA_BITSET_MASK])
+ bitmap_from_arr32(mask, nla_data(tb[ETHA_BITSET_MASK]),
+ change_bits);
+ else
+ bitmap_fill(mask, change_bits);
+
+ if (nbits < change_bits) {
+ unsigned int idx = find_next_bit(mask, max_bits, nbits);
+
+ *err = -EINVAL;
+ if (idx >= nbits)
+ return mod;
+ }
+
+ if (bitmask)
+ bitmap_copy(bitmask, mask, nbits);
+ bitmap_and(val, val, mask, nbits);
+ bitmap_complement(mask, mask, nbits);
+ bitmap_and(mask, mask, bitmap, nbits);
+ bitmap_or(val, val, mask, nbits);
+ mod = !bitmap_equal(val, bitmap, nbits);
+ if (mod)
+ bitmap_copy(bitmap, val, nbits);
+ }
+
+ *err = 0;
+ return mod;
+}
+
+bool ethnl_update_bitset32(u32 *bitmap, u32 *bitmask, unsigned int nbits,
+ struct nlattr *attr, int *err,
+ const char *const *names, struct genl_info *info)
+{
+ DECLARE_BITMAP(tmp, nbits);
+ DECLARE_BITMAP(tmp_mask, nbits);
+ bool mod;
+
+ bitmap_from_arr32(tmp, bitmap, nbits);
+ bitmap_zero(tmp_mask, nbits);
+ mod = ethnl_update_bitset(tmp, tmp_mask, nbits, attr, err, names, info);
+ if (!*err && mod)
+ bitmap_to_arr32(bitmap, tmp, nbits);
+ if (bitmask)
+ bitmap_to_arr32(bitmask, tmp_mask, nbits);
+ return (!*err && mod);
+}
+
/* create skb for a reply
* payload: payload length (without netlink, genetlink and ethnl headers)
* dev: device the reply is about
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index acfed5ba6b54..6e9e854eec5d 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -20,6 +20,32 @@ struct sk_buff *ethnl_reply_init(size_t payload, struct net_device *dev, u8 cmd,
u16 dev_attrtype, struct genl_info *info,
void **ehdrp);
+#if BITS_PER_LONG == 64 && defined(__BIG_ENDIAN)
+void ethnl_bitmap_to_u32(unsigned long *bitmap, unsigned int nwords);
+#else
+static inline void ethnl_bitmap_to_u32(unsigned long *bitmap,
+ unsigned int nwords)
+{
+}
+#endif
+
+int ethnl_bitset_size(bool compact, unsigned int size, unsigned long *val,
+ unsigned long *mask, const char *const *names);
+int ethnl_bitset32_size(bool compact, unsigned int size, u32 *val, u32 *mask,
+ const char *const *names);
+int ethnl_put_bitset(struct sk_buff *skb, int attrtype, bool compact,
+ unsigned int size, unsigned long *val, unsigned long *mask,
+ const char *const *names);
+int ethnl_put_bitset32(struct sk_buff *skb, int attrtype, bool compact,
+ unsigned int size, u32 *val, u32 *mask,
+ const char *const *names);
+bool ethnl_update_bitset(unsigned long *bitmap, unsigned long *bitmask,
+ unsigned int nbits, struct nlattr *attr, int *err,
+ const char *const *names, struct genl_info *info);
+bool ethnl_update_bitset32(u32 *bitmap, u32 *bitmask, unsigned int nbits,
+ struct nlattr *attr, int *err,
+ const char *const *names, struct genl_info *info);
+
static inline int ethnl_str_size(const char *s)
{
return nla_total_size(strlen(s) + 1);
--
2.18.0
^ permalink raw reply related
* [RFC PATCH net-next v2 04/17] ethtool: helper functions for netlink interface
From: Michal Kubecek @ 2018-07-30 12:53 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>
Misc helpers used by ethtool netlink code.
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
include/uapi/linux/ethtool_netlink.h | 11 ++
net/ethtool/netlink.c | 163 +++++++++++++++++++++++++++
net/ethtool/netlink.h | 124 ++++++++++++++++++++
3 files changed, 298 insertions(+)
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index 3c0c5c70692b..1df263d9feb7 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -12,6 +12,17 @@ enum {
ETHNL_CMD_MAX = (__ETHNL_CMD_MAX - 1)
};
+/* device specification */
+
+enum {
+ ETHA_DEV_UNSPEC,
+ ETHA_DEV_INDEX, /* u32 */
+ ETHA_DEV_NAME, /* string */
+
+ __ETHA_DEV_MAX,
+ ETHA_DEV_MAX = (__ETHA_DEV_MAX - 1)
+};
+
/* generic netlink info */
#define ETHTOOL_GENL_NAME "ethtool"
#define ETHTOOL_GENL_VERSION 1
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 1c6efb9b2eae..bf234e5bc660 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -1,9 +1,172 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#include <linux/module.h>
+#include <net/sock.h>
#include <linux/ethtool_netlink.h>
#include "netlink.h"
+static const struct nla_policy dev_policy[ETHA_DEV_MAX + 1] = {
+ [ETHA_DEV_UNSPEC] = { .type = NLA_UNSPEC },
+ [ETHA_DEV_INDEX] = { .type = NLA_U32 },
+ [ETHA_DEV_NAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
+};
+
+struct net_device *ethnl_dev_get(struct genl_info *info, struct nlattr *nest)
+{
+ struct net *net = genl_info_net(info);
+ struct nlattr *tb[ETHA_DEV_MAX + 1];
+ struct net_device *dev;
+ int ret;
+
+ ret = nla_parse_nested(tb, ETHA_DEV_MAX, nest, dev_policy,
+ info->extack);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ if (tb[ETHA_DEV_INDEX]) {
+ dev = dev_get_by_index(net, nla_get_u32(tb[ETHA_BIT_INDEX]));
+ if (!dev)
+ return ERR_PTR(-ENODEV);
+ /* if both ifindex and ifname are passed, they must match */
+ if (tb[ETHA_DEV_NAME]) {
+ const char *nl_name = nla_data(tb[ETHA_DEV_NAME]);
+
+ if (strncmp(dev->name, nl_name, IFNAMSIZ)) {
+ ETHNL_SET_ERRMSG(info,
+ "ifindex and ifname do not match");
+ return ERR_PTR(-ENODEV);
+ }
+ }
+ return dev;
+ } else if (tb[ETHA_DEV_NAME]) {
+ dev = dev_get_by_name(net, nla_data(tb[ETHA_DEV_NAME]));
+ return dev ?: ERR_PTR(-ENODEV);
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+int ethnl_fill_dev(struct sk_buff *msg, struct net_device *dev, u16 attrtype)
+{
+ struct nlattr *nest;
+ int ret = -EMSGSIZE;
+
+ nest = ethnl_nest_start(msg, attrtype);
+ if (!nest)
+ return -EMSGSIZE;
+
+ if (nla_put_u32(msg, ETHA_DEV_INDEX, (u32)dev->ifindex))
+ goto err;
+ if (nla_put_string(msg, ETHA_DEV_NAME, dev->name))
+ goto err;
+
+ nla_nest_end(msg, nest);
+ return 0;
+err:
+ nla_nest_cancel(msg, nest);
+ return ret;
+}
+
+/* create skb for a reply
+ * payload: payload length (without netlink, genetlink and ethnl headers)
+ * dev: device the reply is about
+ * cmd: ETHNL_CMD_* command for reply
+ * info: info for the received packet we respond to
+ * ehdrp: place to store payload pointer returned by genlmsg_new()
+ * returns: skb or null on error
+ */
+struct sk_buff *ethnl_reply_init(size_t payload, struct net_device *dev, u8 cmd,
+ u16 dev_attrtype, struct genl_info *info,
+ void **ehdrp)
+{
+ void *ehdr;
+ struct sk_buff *rskb;
+
+ if (dev)
+ payload += nla_total_size(nla_total_size(sizeof(u32)) +
+ nla_total_size(IFNAMSIZ));
+ rskb = genlmsg_new(payload, GFP_KERNEL);
+ if (!rskb) {
+ ETHNL_SET_ERRMSG(info,
+ "failed to allocate reply message");
+ return NULL;
+ }
+
+ ehdr = genlmsg_put_reply(rskb, info, ðtool_genl_family, 0, cmd);
+ if (!ehdr)
+ goto err;
+ if (ehdrp)
+ *ehdrp = ehdr;
+ if (dev) {
+ int ret = ethnl_fill_dev(rskb, dev, dev_attrtype);
+
+ if (ret < 0)
+ goto err;
+ }
+
+ return rskb;
+err:
+ nlmsg_free(rskb);
+ return NULL;
+}
+
+/* device iteration copied from rtnl_dump_ifinfo()
+ * cb->args[0]: command specific dump function
+ * cb->args[1]: ethnl command to use in reply
+ * cb->args[2]: position - hashbucket
+ * cb->args[3]: position - ifindex
+ */
+int ethnl_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int (*dumpfn)(struct sk_buff *skb, struct netlink_callback *cb,
+ struct net_device *dev);
+ struct net *net = sock_net(skb->sk);
+ struct hlist_head *head;
+ struct net_device *dev;
+ int h, s_h, idx = 0, s_idx;
+ int ret = 0;
+ void *ehdr;
+ u8 rcmd;
+
+ dumpfn = (void *)cb->args[0];
+ rcmd = cb->args[1];
+ s_h = cb->args[2];
+ s_idx = cb->args[3];
+
+ for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
+ idx = 0;
+ head = &net->dev_index_head[h];
+ hlist_for_each_entry(dev, head, index_hlist) {
+ if (idx < s_idx)
+ goto cont;
+ ehdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq,
+ ðtool_genl_family, 0, rcmd);
+ ret = dumpfn(skb, cb, dev);
+ if (ret < 0) {
+ genlmsg_cancel(skb, ehdr);
+ if (ret == -EOPNOTSUPP)
+ goto cont;
+ if (likely(skb->len))
+ goto out;
+ goto out_err;
+ }
+ genlmsg_end(skb, ehdr);
+cont:
+ idx++;
+ }
+ }
+out:
+ ret = skb->len;
+out_err:
+ cb->args[2] = h;
+ cb->args[3] = idx;
+ cb->seq = net->dev_base_seq;
+ nl_dump_check_consistent(cb, nlmsg_hdr(skb));
+
+ return ret;
+}
+
/* genetlink setup */
static const struct genl_ops ethtool_genl_ops[] = {
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 63063b582ca2..acfed5ba6b54 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -6,7 +6,131 @@
#include <linux/ethtool_netlink.h>
#include <linux/netdevice.h>
#include <net/genetlink.h>
+#include <net/sock.h>
+
+#define ETHNL_SET_ERRMSG(info, msg) \
+ do { if (info) GENL_SET_ERR_MSG(info, msg); } while (0)
extern struct genl_family ethtool_genl_family;
+struct net_device *ethnl_dev_get(struct genl_info *info, struct nlattr *nest);
+int ethnl_fill_dev(struct sk_buff *msg, struct net_device *dev, u16 attrtype);
+
+struct sk_buff *ethnl_reply_init(size_t payload, struct net_device *dev, u8 cmd,
+ u16 dev_attrtype, struct genl_info *info,
+ void **ehdrp);
+
+static inline int ethnl_str_size(const char *s)
+{
+ return nla_total_size(strlen(s) + 1);
+}
+
+static inline int ethnl_str_ifne_size(const char *s)
+{
+ return s[0] ? ethnl_str_size(s) : 0;
+}
+
+static inline int ethnl_put_str_ifne(struct sk_buff *skb, int attrtype,
+ const char *s)
+{
+ if (!s[0])
+ return 0;
+ return nla_put_string(skb, attrtype, s);
+}
+
+static inline struct nlattr *ethnl_nest_start(struct sk_buff *skb,
+ int attrtype)
+{
+ return nla_nest_start(skb, attrtype | NLA_F_NESTED);
+}
+
+/* ethnl_update_* return true if the value is changed */
+static inline bool ethnl_update_u32(u32 *dst, struct nlattr *attr)
+{
+ u32 val;
+
+ if (!attr)
+ return false;
+ val = nla_get_u32(attr);
+ if (*dst == val)
+ return false;
+
+ *dst = val;
+ return true;
+}
+
+static inline bool ethnl_update_u8(u8 *dst, struct nlattr *attr)
+{
+ u8 val;
+
+ if (!attr)
+ return false;
+ val = nla_get_u8(attr);
+ if (*dst == val)
+ return false;
+
+ *dst = val;
+ return true;
+}
+
+/* update u32 value used as bool from NLA_U8 */
+static inline bool ethnl_update_bool32(u32 *dst, struct nlattr *attr)
+{
+ u8 val;
+
+ if (!attr)
+ return false;
+ val = !!nla_get_u8(attr);
+ if (!!*dst == val)
+ return false;
+
+ *dst = val;
+ return true;
+}
+
+static inline bool ethnl_update_binary(u8 *dst, unsigned int len, struct nlattr *attr)
+{
+ if (!attr)
+ return false;
+ if (nla_len(attr) < len)
+ len = nla_len(attr);
+ if (!memcmp(dst, nla_data(attr), len))
+ return false;
+
+ memcpy(dst, nla_data(attr), len);
+ return true;
+}
+
+static inline bool ethnl_update_bitfield32(u32 *dst, struct nlattr *attr)
+{
+ struct nla_bitfield32 change;
+ u32 newval;
+
+ if (!attr)
+ return false;
+ change = nla_get_bitfield32(attr);
+ newval = (*dst & ~change.selector) | (change.value & change.selector);
+ if (*dst == newval)
+ return false;
+
+ *dst = newval;
+ return true;
+}
+
+static inline void warn_partial_info(struct genl_info *info)
+{
+ ETHNL_SET_ERRMSG(info, "not all requested data could be retrieved");
+}
+
+/* Check user privileges explicitly to allow finer access control based on
+ * context of the request or hiding part of the information from unprivileged
+ * users
+ */
+static inline bool ethnl_is_privileged(struct sk_buff *skb)
+{
+ struct net *net = sock_net(skb->sk);
+
+ return netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN);
+}
+
#endif /* _NET_ETHTOOL_NETLINK_H */
--
2.18.0
^ permalink raw reply related
* [RFC PATCH net-next v2 03/17] ethtool: introduce ethtool netlink interface
From: Michal Kubecek @ 2018-07-30 12:52 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>
No function implemented yet, only genetlink and module infrastructure.
Register/unregister genetlink family "ethtool" and allow the module to be
autoloaded by genetlink code (if built as a module, distributions would
probably prefer "y").
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
Documentation/networking/ethtool-netlink.txt | 168 +++++++++++++++++++
include/linux/ethtool_netlink.h | 9 +
include/uapi/linux/ethtool_netlink.h | 19 +++
net/Kconfig | 7 +
net/ethtool/Makefile | 6 +-
net/ethtool/netlink.c | 41 +++++
net/ethtool/netlink.h | 12 ++
7 files changed, 261 insertions(+), 1 deletion(-)
create mode 100644 Documentation/networking/ethtool-netlink.txt
create mode 100644 include/linux/ethtool_netlink.h
create mode 100644 include/uapi/linux/ethtool_netlink.h
create mode 100644 net/ethtool/netlink.c
create mode 100644 net/ethtool/netlink.h
diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
new file mode 100644
index 000000000000..120376e0f91b
--- /dev/null
+++ b/Documentation/networking/ethtool-netlink.txt
@@ -0,0 +1,168 @@
+ Netlink interface for ethtool
+ =============================
+
+
+Basic information
+-----------------
+
+Netlink interface for ethtool uses generic netlink family "ethtool" (userspace
+application should use macros ETHTOOL_GENL_NAME and ETHTOOL_GENL_VERSION
+defined in <linux/ethtool_netlink.h> uapi header). This family does not use
+a specific header, all information in requests and replies is passed using
+netlink attributes.
+
+In requests, device can be identified by ifindex or by name; if both are used,
+they must match. In replies, kernel fills both. The meaning of flags,
+info_mask and index fields depends on request type.
+
+The ethtool netlink interface uses extended ACK for error and warning
+reporting, userspace application developers are encouraged to make these
+messages available to user in a suitable way.
+
+Requests can be divided into three categories: "get" (retrieving information),
+"set" (setting parameters) and "action" (invoking an action).
+
+All "set" and "action" type requests require admin privileges (CAP_NET_ADMIN
+in the namespace). Most "get" type request are allowed for anyone but there
+are exceptions (where the response contains sensitive information). In some
+cases, the request as such is allowed for anyone but unprivileged users have
+attributes with sensitive information (e.g. wake-on-lan password) omitted.
+
+
+Conventions
+-----------
+
+Attributes which represent a boolean value usually use u8 type so that we can
+distinguish three states: "on", "off" and "not present" (meaning the
+information is not available in "get" requests or value is not to be changed
+in "set" requests). For these attributes, the "true" value should be passed as
+number 1 but any non-zero value should be understood as "true" by recipient.
+
+Some request types allow passing an attribute named ETHA_*_INFOMASK with
+a bitmask telling kernel that we are only interested in some parts of the
+information. If info mask is omitted, all available information is returned.
+Meaning of info mask bits depends on request type and is listed below.
+
+
+Device identification
+---------------------
+
+When appropriate, network device is identified by a nested attribute named
+ETHA_*_DEV. This attribute can contain
+
+ ETHA_DEV_INDEX (u32) device ifindex
+ ETHA_DEV_NAME (string) device name
+
+In device related requests, one of these is sufficient; if both are used, they
+must match (i.e. identify the same device). In device related replies both are
+provided by kernel. In dump requests, device is not specified and kernel
+replies with one message per network device (only those for which the request
+is supported).
+
+List of message types
+---------------------
+
+All constants use ETHNL_CMD_ prefix, usually followed by "GET", "SET" or "ACT"
+to indicate the type.
+
+Messages of type "get" are used by userspace to request information and
+usually do not contain any attributes (that may be added later for dump
+filtering). Kernel response is in the form of corresponding "set" message;
+the same message can be also used to set (some of) the parameters, except for
+messages marked as "response only" in the table above. "Get" messages with
+NLM_F_DUMP flags and no device identification dump the information for all
+devices supporting the request.
+
+Later sections describe the format and semantics of these request messages.
+
+
+Request translation
+-------------------
+
+The following table maps iosctl commands to netlink commands providing their
+functionality. Entries with "n/a" in right column are commands which do not
+have their netlink replacement yet.
+
+ioctl command netlink command
+---------------------------------------------------------------------
+ETHTOOL_GSET n/a
+ETHTOOL_SSET n/a
+ETHTOOL_GDRVINFO n/a
+ETHTOOL_GREGS n/a
+ETHTOOL_GWOL n/a
+ETHTOOL_SWOL n/a
+ETHTOOL_GMSGLVL n/a
+ETHTOOL_SMSGLVL n/a
+ETHTOOL_NWAY_RST n/a
+ETHTOOL_GLINK n/a
+ETHTOOL_GEEPROM n/a
+ETHTOOL_SEEPROM n/a
+ETHTOOL_GCOALESCE n/a
+ETHTOOL_SCOALESCE n/a
+ETHTOOL_GRINGPARAM n/a
+ETHTOOL_SRINGPARAM n/a
+ETHTOOL_GPAUSEPARAM n/a
+ETHTOOL_SPAUSEPARAM n/a
+ETHTOOL_GRXCSUM n/a
+ETHTOOL_SRXCSUM n/a
+ETHTOOL_GTXCSUM n/a
+ETHTOOL_STXCSUM n/a
+ETHTOOL_GSG n/a
+ETHTOOL_SSG n/a
+ETHTOOL_TEST n/a
+ETHTOOL_GSTRINGS n/a
+ETHTOOL_PHYS_ID n/a
+ETHTOOL_GSTATS n/a
+ETHTOOL_GTSO n/a
+ETHTOOL_STSO n/a
+ETHTOOL_GPERMADDR n/a
+ETHTOOL_GUFO n/a
+ETHTOOL_SUFO n/a
+ETHTOOL_GGSO n/a
+ETHTOOL_SGSO n/a
+ETHTOOL_GFLAGS n/a
+ETHTOOL_SFLAGS n/a
+ETHTOOL_GPFLAGS n/a
+ETHTOOL_SPFLAGS n/a
+ETHTOOL_GRXFH n/a
+ETHTOOL_SRXFH n/a
+ETHTOOL_GGRO n/a
+ETHTOOL_SGRO n/a
+ETHTOOL_GRXRINGS n/a
+ETHTOOL_GRXCLSRLCNT n/a
+ETHTOOL_GRXCLSRULE n/a
+ETHTOOL_GRXCLSRLALL n/a
+ETHTOOL_SRXCLSRLDEL n/a
+ETHTOOL_SRXCLSRLINS n/a
+ETHTOOL_FLASHDEV n/a
+ETHTOOL_RESET n/a
+ETHTOOL_SRXNTUPLE n/a
+ETHTOOL_GRXNTUPLE n/a
+ETHTOOL_GSSET_INFO n/a
+ETHTOOL_GRXFHINDIR n/a
+ETHTOOL_SRXFHINDIR n/a
+ETHTOOL_GFEATURES n/a
+ETHTOOL_SFEATURES n/a
+ETHTOOL_GCHANNELS n/a
+ETHTOOL_SCHANNELS n/a
+ETHTOOL_SET_DUMP n/a
+ETHTOOL_GET_DUMP_FLAG n/a
+ETHTOOL_GET_DUMP_DATA n/a
+ETHTOOL_GET_TS_INFO n/a
+ETHTOOL_GMODULEINFO n/a
+ETHTOOL_GMODULEEEPROM n/a
+ETHTOOL_GEEE n/a
+ETHTOOL_SEEE n/a
+ETHTOOL_GRSSH n/a
+ETHTOOL_SRSSH n/a
+ETHTOOL_GTUNABLE n/a
+ETHTOOL_STUNABLE n/a
+ETHTOOL_GPHYSTATS n/a
+ETHTOOL_PERQUEUE n/a
+ETHTOOL_GLINKSETTINGS n/a
+ETHTOOL_SLINKSETTINGS n/a
+ETHTOOL_PHY_GTUNABLE n/a
+ETHTOOL_PHY_STUNABLE n/a
+ETHTOOL_GFECPARAM n/a
+ETHTOOL_SFECPARAM n/a
+
diff --git a/include/linux/ethtool_netlink.h b/include/linux/ethtool_netlink.h
new file mode 100644
index 000000000000..0412adb4f42f
--- /dev/null
+++ b/include/linux/ethtool_netlink.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#ifndef _LINUX_ETHTOOL_NETLINK_H_
+#define _LINUX_ETHTOOL_NETLINK_H_
+
+#include <uapi/linux/ethtool_netlink.h>
+#include <linux/ethtool.h>
+
+#endif /* _LINUX_ETHTOOL_NETLINK_H_ */
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
new file mode 100644
index 000000000000..3c0c5c70692b
--- /dev/null
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#ifndef _UAPI_LINUX_ETHTOOL_NETLINK_H_
+#define _UAPI_LINUX_ETHTOOL_NETLINK_H_
+
+#include <linux/ethtool.h>
+
+enum {
+ ETHNL_CMD_NOOP,
+
+ __ETHNL_CMD_MAX,
+ ETHNL_CMD_MAX = (__ETHNL_CMD_MAX - 1)
+};
+
+/* generic netlink info */
+#define ETHTOOL_GENL_NAME "ethtool"
+#define ETHTOOL_GENL_VERSION 1
+
+#endif /* _UAPI_LINUX_ETHTOOL_NETLINK_H_ */
diff --git a/net/Kconfig b/net/Kconfig
index 228dfa382eec..12e763449525 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -445,6 +445,13 @@ config FAILOVER
migration of VMs with direct attached VFs by failing over to the
paravirtual datapath when the VF is unplugged.
+config ETHTOOL_NETLINK
+ tristate "Netlink interface for ethtool"
+ default m
+ help
+ New netlink based interface for ethtool which is going to obsolete
+ the old ioctl based one once it provides all features.
+
endif # if NET
# Used by archs to tell that they support BPF JIT compiler plus which flavour.
diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile
index 3ebfab2bca66..f30e0da88be5 100644
--- a/net/ethtool/Makefile
+++ b/net/ethtool/Makefile
@@ -1,3 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
-obj-y += ioctl.o
+obj-y += ioctl.o
+
+obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o
+
+ethtool_nl-y := netlink.o
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
new file mode 100644
index 000000000000..1c6efb9b2eae
--- /dev/null
+++ b/net/ethtool/netlink.c
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#include <linux/module.h>
+#include <linux/ethtool_netlink.h>
+#include "netlink.h"
+
+/* genetlink setup */
+
+static const struct genl_ops ethtool_genl_ops[] = {
+};
+
+struct genl_family ethtool_genl_family = {
+ .hdrsize = 0,
+ .name = ETHTOOL_GENL_NAME,
+ .version = ETHTOOL_GENL_VERSION,
+ .netnsok = true,
+ .parallel_ops = true,
+ .ops = ethtool_genl_ops,
+ .n_ops = ARRAY_SIZE(ethtool_genl_ops),
+};
+
+/* module setup */
+
+static int __init ethtool_nl_init(void)
+{
+ return genl_register_family(ðtool_genl_family);
+}
+
+static void __exit ethtool_nl_exit(void)
+{
+ genl_unregister_family(ðtool_genl_family);
+}
+
+module_init(ethtool_nl_init);
+module_exit(ethtool_nl_exit);
+
+/* alias for module autoload */
+MODULE_ALIAS_GENL_FAMILY(ETHTOOL_GENL_NAME);
+MODULE_AUTHOR("Michal Kubecek <mkubecek@suse.cz>");
+MODULE_DESCRIPTION("Netlink interface for ethtool");
+MODULE_LICENSE("GPL");
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
new file mode 100644
index 000000000000..63063b582ca2
--- /dev/null
+++ b/net/ethtool/netlink.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#ifndef _NET_ETHTOOL_NETLINK_H
+#define _NET_ETHTOOL_NETLINK_H
+
+#include <linux/ethtool_netlink.h>
+#include <linux/netdevice.h>
+#include <net/genetlink.h>
+
+extern struct genl_family ethtool_genl_family;
+
+#endif /* _NET_ETHTOOL_NETLINK_H */
--
2.18.0
^ permalink raw reply related
* [RFC PATCH net-next v2 02/17] ethtool: move to its own directory
From: Michal Kubecek @ 2018-07-30 12:52 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>
With ethtool netlink interface, there is going to be a lot of new files
so that it seem more convenient to put them into a separate directory
net/ethtool. Start with moving current file with ioctl implementation
there and renaming it to ioctl.c.
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
net/Makefile | 2 +-
net/core/Makefile | 2 +-
net/ethtool/Makefile | 3 +++
net/{core/ethtool.c => ethtool/ioctl.c} | 0
4 files changed, 5 insertions(+), 2 deletions(-)
create mode 100644 net/ethtool/Makefile
rename net/{core/ethtool.c => ethtool/ioctl.c} (100%)
diff --git a/net/Makefile b/net/Makefile
index bdaf53925acd..6c68520e5eb9 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_NET) += $(tmp-y)
# LLC has to be linked before the files in net/802/
obj-$(CONFIG_LLC) += llc/
-obj-$(CONFIG_NET) += ethernet/ 802/ sched/ netlink/ bpf/
+obj-$(CONFIG_NET) += ethernet/ 802/ sched/ netlink/ bpf/ ethtool/
obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_INET) += ipv4/
obj-$(CONFIG_TLS) += tls/
diff --git a/net/core/Makefile b/net/core/Makefile
index 80175e6a2eb8..55734d0a1603 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -8,7 +8,7 @@ obj-y := sock.o request_sock.o skbuff.o datagram.o stream.o scm.o \
obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
-obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \
+obj-y += dev.o dev_addr_lists.o dst.o netevent.o \
neighbour.o rtnetlink.o utils.o link_watch.o filter.o \
sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \
fib_notifier.o xdp.o
diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile
new file mode 100644
index 000000000000..3ebfab2bca66
--- /dev/null
+++ b/net/ethtool/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += ioctl.o
diff --git a/net/core/ethtool.c b/net/ethtool/ioctl.c
similarity index 100%
rename from net/core/ethtool.c
rename to net/ethtool/ioctl.c
--
2.18.0
^ permalink raw reply related
* [RFC PATCH net-next v2 01/17] netlink: introduce nla_put_bitfield32()
From: Michal Kubecek @ 2018-07-30 12:52 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
In-Reply-To: <cover.1532953989.git.mkubecek@suse.cz>
Similar to other data types, this helper puts NLA_BITFIELD32 attribute into
a netlink message. It takes separate value and selector arguments, if you
already have struct nla_bitfield32, you can use nla_put().
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
include/net/netlink.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 0c154f98e987..6d4eb6bd9235 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -1064,6 +1064,21 @@ static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype,
return nla_put(skb, attrtype, sizeof(*addr), addr);
}
+/**
+ * nla_put_bitfield32 - Add a bitfield32 value/selector attribute to
+ * a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @value: 32-bit value bitmap
+ * @selector: 32-bit selector bitmap
+ */
+static inline int nla_put_bitfield32(struct sk_buff *skb, int attrtype,
+ u32 value, u32 selector)
+{
+ struct nla_bitfield32 tmp = { .value = value, .selector = selector };
+
+ return nla_put(skb, attrtype, sizeof(tmp), &tmp);
+}
+
/**
* nla_get_u32 - return payload of u32 attribute
* @nla: u32 netlink attribute
--
2.18.0
^ permalink raw reply related
* [RFC PATCH net-next v2 00/17] ethtool netlink interface (WiP)
From: Michal Kubecek @ 2018-07-30 12:52 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, Jiri Pirko, David Miller, Florian Fainelli,
Roopa Prabhu, Jakub Kicinski, John W. Linville
A netlink based interface for ethtool is a recurring discussion theme;
such discussion happens from time to time but never seems to reach any
clear conclusion except that netlink interface is desperately needed.
I'm sending this hoping that having a proposal (even if partial) on the
table could help move the discussion further.
The interface used for communication between ethtool and kernel is based on
ioctl() and suffers from many problems. The most pressing seems the be the
lack of extensibility. While some of the newer commands use structures
designed to allow future extensions (e.g. GFEATURES or TEST), most either
allow no extension at all (GPAUSEPARAM, GCOALESCE) or only limited set of
reserved fields (GDRVINFO, GEEE). Even most of those which support future
extensions limit the data types that can be used.
This series aims to provide an alternative interface based on netlink which
is what other network configuration utilities use. In particular, it uses
generic netlink (family "ethtool"). The goal is to provide an interface
which would be extensible, flexible and practical both for ethtool and for
other network configuration tools (e.g. wicked, systemd-networkd or
NetworkManager).
The interface is documented in Documentation/networking/ethtool-netlink.txt
A series for ethtool utility will follow shortly.
Basic concepts:
- the interface is based on generic netlink (family name "ethtool")
- the goal is to provide all features of ioctl interface but allow
easier future extensions
- inextensibility of ioctl interface resulted in way too many commands,
many of them obsoleted by newer ones; reduce the number by ignoring the
obsolete commands and grouping some together
- for "set" type commands, netlink allows providing only the attributes to
be changed; therefore we don't need a get-modify-set cycle (which is
inherently racy), userspace can simply say what it wants to change
- provide notifications to multicast group "monitor" like rtnetlink
does, i.e. in the form of messages close to replies to "get" requests
- allow dump requests to get some information about all network defices
providing it
- be less dependent on ethtool and kernel being in sync; allow e.g. saying
"ethtool -s eth0 advertise foo off" without ethtool knowing what "foo"
means; it's kernel's job to know what mode "xyz" is and if it exists
and is supported
Main changes again RFC v1:
- support dumps for all "get" requests
- provide notifications for changes related to supported request types
- support getting string sets (both global and per device)
- support getting/setting device features
- get rid of family specific header, everything passed as attributes
- split netlink code into multiple files in net/ethtool/ directory
ToDo / open questions:
- as some comments in discussion on v1 pointed out, some features of
ethtool would rather belong to devlink; phy_tunables and phy_stats
seem to be candidates, maybe part of drvinfo; are there more?
- another question is where to do the split; should ethtool use devlink
API for these or can we provide them in ethtool API as well but with
devlink backend (for communication with NIC)
- currently, all communication with drivers via ethtool_ops is done
under RTNL as this is what ioctl interface does and I suspect many
ethtool_ops rely on that; can we do without RTNL?
- notifications are sent whenever a change is done via netlink API or
ioctl API and for netdev features also whenever they are updated using
netdev_change_features(); it would be desirable to notify also about
link state and negotiation result (speed/duplex and partner link
modes) but it would be more tricky
- find reasonable format for data transfers (e.g. eeprom dump or flash);
I don't have clear idea how big these can get and if 64 KB limit on
attribute size (including nested ones) is a problem; if so, dumps can
be an answer for dumps, some kind of multi-message requests would be
needed for flashes
- while the netlink interface allows easy future extensions, ethtool_ops
interface does not; some settings could be implemented using tunables and
accessed via relevant netlink messages (as well as tunables) from
userspace but in the long term, something better will be needed
- it would be nice if driver could provide useful error/warning messages to
be passed to userspace via extended ACK; example: while testing, I found
a driver which only allows values 0, 1, 3 and 10000 for certain parameter
but the only way poor user can find out is either by trying all values or
by checking driver source
- some of the functions for GET_SETTINGS and GET_PARAMS are quite
similar (e.g. ethtool_get_*); it might be beneficial to introduce some
"ops", leave only "parse", "prepare", "size" and "fill" handlers and
make the rest generic (like ethnl_dumpit()).
- the counts and sizes in GET_DRVINFO reply seem to be a relic of the
past and if userspace needs them, there are (or will be) other ways to
get them; they should most likely go
Michal Kubecek (17):
netlink: introduce nla_put_bitfield32()
ethtool: move to its own directory
ethtool: introduce ethtool netlink interface
ethtool: helper functions for netlink interface
ethtool: netlink bitset handling
ethtool: support for netlink notifications
ethtool: implement EVENT notifications
ethtool: implement GET_STRSET message
ethtool: implement GET_DRVINFO message
ethtool: implement GET_SETTINGS message
ethtool: implement GET_SETTINGS request for features
ethtool: implement SET_SETTINGS notification
ethtool: implement SET_SETTINGS message
ethtool: implement SET_SETTINGS request for features
ethtool: implement GET_PARAMS message
ethtool: implement SET_PARAMS notification
ethtool: implement SET_PARAMS message
Documentation/networking/ethtool-netlink.txt | 558 ++++++++
include/linux/ethtool_netlink.h | 17 +
include/linux/netdevice.h | 25 +
include/net/netlink.h | 15 +
include/uapi/linux/ethtool.h | 7 +
include/uapi/linux/ethtool_netlink.h | 325 +++++
net/Kconfig | 7 +
net/Makefile | 2 +-
net/core/Makefile | 2 +-
net/core/dev.c | 27 +-
net/ethtool/Makefile | 7 +
net/ethtool/common.c | 242 ++++
net/ethtool/common.h | 26 +
net/ethtool/drvinfo.c | 131 ++
net/{core/ethtool.c => ethtool/ioctl.c} | 310 ++---
net/ethtool/netlink.c | 840 ++++++++++++
net/ethtool/netlink.h | 169 +++
net/ethtool/params.c | 1008 ++++++++++++++
net/ethtool/settings.c | 1230 ++++++++++++++++++
net/ethtool/strset.c | 552 ++++++++
20 files changed, 5269 insertions(+), 231 deletions(-)
create mode 100644 Documentation/networking/ethtool-netlink.txt
create mode 100644 include/linux/ethtool_netlink.h
create mode 100644 include/uapi/linux/ethtool_netlink.h
create mode 100644 net/ethtool/Makefile
create mode 100644 net/ethtool/common.c
create mode 100644 net/ethtool/common.h
create mode 100644 net/ethtool/drvinfo.c
rename net/{core/ethtool.c => ethtool/ioctl.c} (88%)
create mode 100644 net/ethtool/netlink.c
create mode 100644 net/ethtool/netlink.h
create mode 100644 net/ethtool/params.c
create mode 100644 net/ethtool/settings.c
create mode 100644 net/ethtool/strset.c
--
2.18.0
^ permalink raw reply
* [PATCH net-next 10/10] net: mscc: ocelot: make use of SerDes PHYs for handling their configuration
From: Quentin Schulz @ 2018-07-30 12:43 UTC (permalink / raw)
To: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, davem
Cc: kishon, andrew, f.fainelli, linux-mips, devicetree, linux-kernel,
netdev, allan.nielsen, thomas.petazzoni, Quentin Schulz
In-Reply-To: <cover.aa759035f6eefdd0bb2a5ae335dab5bd5399bd46.1532954208.git-series.quentin.schulz@bootlin.com>
Previously, the SerDes muxing was hardcoded to a given mode in the MAC
controller driver. Now, the SerDes muxing is configured within the
Device Tree and is enforced in the MAC controller driver so we can have
a lot of different SerDes configurations.
Make use of the SerDes PHYs in the MAC controller to set up the SerDes
according to the SerDes<->switch port mapping and the communication mode
with the Ethernet PHY.
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
drivers/net/ethernet/mscc/Kconfig | 2 +-
drivers/net/ethernet/mscc/ocelot.c | 16 ++++++++-
drivers/net/ethernet/mscc/ocelot.h | 5 +++-
drivers/net/ethernet/mscc/ocelot_board.c | 43 +++++++++++++++++++------
4 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/mscc/Kconfig b/drivers/net/ethernet/mscc/Kconfig
index 36c8462..bcec058 100644
--- a/drivers/net/ethernet/mscc/Kconfig
+++ b/drivers/net/ethernet/mscc/Kconfig
@@ -23,6 +23,8 @@ config MSCC_OCELOT_SWITCH
config MSCC_OCELOT_SWITCH_OCELOT
tristate "Ocelot switch driver on Ocelot"
depends on MSCC_OCELOT_SWITCH
+ depends on GENERIC_PHY
+ depends on OF_NET
help
This driver supports the Ocelot network switch device as present on
the Ocelot SoCs.
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 1a4f2bb..8f11fdb 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -472,6 +472,7 @@ static int ocelot_port_open(struct net_device *dev)
{
struct ocelot_port *port = netdev_priv(dev);
struct ocelot *ocelot = port->ocelot;
+ enum phy_mode phy_mode;
int err;
/* Enable receiving frames on the port, and activate auto-learning of
@@ -482,8 +483,21 @@ static int ocelot_port_open(struct net_device *dev)
ANA_PORT_PORT_CFG_PORTID_VAL(port->chip_port),
ANA_PORT_PORT_CFG, port->chip_port);
+ if (port->serdes) {
+ if (port->phy_mode == PHY_INTERFACE_MODE_SGMII)
+ phy_mode = PHY_MODE_SGMII;
+ else
+ phy_mode = PHY_MODE_QSGMII;
+
+ err = phy_set_mode(port->serdes, phy_mode);
+ if (err) {
+ netdev_err(dev, "Could not set mode of SerDes\n");
+ return err;
+ }
+ }
+
err = phy_connect_direct(dev, port->phy, &ocelot_port_adjust_link,
- PHY_INTERFACE_MODE_NA);
+ port->phy_mode);
if (err) {
netdev_err(dev, "Could not attach to PHY\n");
return err;
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 3720e51..62c7c8e 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -11,6 +11,8 @@
#include <linux/bitops.h>
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -453,6 +455,9 @@ struct ocelot_port {
u8 vlan_aware;
u64 *stats;
+
+ phy_interface_t phy_mode;
+ struct phy *serdes;
};
u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset);
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index b7d755b..3bb71b7 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -6,6 +6,7 @@
*/
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/of_net.h>
#include <linux/netdevice.h>
#include <linux/of_mdio.h>
#include <linux/of_platform.h>
@@ -247,18 +248,12 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&ocelot->multicast);
ocelot_init(ocelot);
- ocelot_rmw(ocelot, HSIO_HW_CFG_DEV1G_4_MODE |
- HSIO_HW_CFG_DEV1G_6_MODE |
- HSIO_HW_CFG_DEV1G_9_MODE,
- HSIO_HW_CFG_DEV1G_4_MODE |
- HSIO_HW_CFG_DEV1G_6_MODE |
- HSIO_HW_CFG_DEV1G_9_MODE,
- HSIO_HW_CFG);
-
for_each_available_child_of_node(ports, portnp) {
struct device_node *phy_node;
struct phy_device *phy;
struct resource *res;
+ struct phy *serdes;
+ enum phy_mode phy_mode;
void __iomem *regs;
char res_name[8];
u32 port;
@@ -283,10 +278,38 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
continue;
err = ocelot_probe_port(ocelot, port, regs, phy);
- if (err) {
- dev_err(&pdev->dev, "failed to probe ports\n");
+ if (err)
+ return err;
+
+ err = of_get_phy_mode(portnp);
+ if (err < 0)
+ ocelot->ports[port]->phy_mode = PHY_INTERFACE_MODE_NA;
+ else
+ ocelot->ports[port]->phy_mode = err;
+
+ if (ocelot->ports[port]->phy_mode == PHY_INTERFACE_MODE_NA)
+ continue;
+
+ if (ocelot->ports[port]->phy_mode == PHY_INTERFACE_MODE_SGMII)
+ phy_mode = PHY_MODE_SGMII;
+ else
+ phy_mode = PHY_MODE_QSGMII;
+
+ serdes = devm_of_phy_get(ocelot->dev, portnp, NULL);
+ if (IS_ERR(serdes)) {
+ if (PTR_ERR(serdes) == -EPROBE_DEFER) {
+ dev_err(ocelot->dev, "deferring probe\n");
+ err = -EPROBE_DEFER;
+ goto err_probe_ports;
+ }
+
+ dev_err(ocelot->dev, "missing SerDes phys for port%d\n",
+ port);
+ err = -ENODEV;
goto err_probe_ports;
}
+
+ ocelot->ports[port]->serdes = serdes;
}
register_netdevice_notifier(&ocelot_netdevice_nb);
--
git-series 0.9.1
^ permalink raw reply related
* [PATCH 09/10] phy: add driver for Microsemi Ocelot SerDes muxing
From: Quentin Schulz @ 2018-07-30 12:43 UTC (permalink / raw)
To: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, davem
Cc: kishon, andrew, f.fainelli, linux-mips, devicetree, linux-kernel,
netdev, allan.nielsen, thomas.petazzoni, Quentin Schulz
In-Reply-To: <cover.aa759035f6eefdd0bb2a5ae335dab5bd5399bd46.1532954208.git-series.quentin.schulz@bootlin.com>
The Microsemi Ocelot can mux SerDes lanes (aka macros) to different
switch ports or even make it act as a PCIe interface.
This adds support for the muxing of the SerDes.
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
drivers/phy/Kconfig | 1 +-
drivers/phy/Makefile | 1 +-
drivers/phy/mscc/Kconfig | 11 +-
drivers/phy/mscc/Makefile | 5 +-
drivers/phy/mscc/phy-ocelot-serdes.c | 314 ++++++++++++++++++++++++++++-
5 files changed, 332 insertions(+)
create mode 100644 drivers/phy/mscc/Kconfig
create mode 100644 drivers/phy/mscc/Makefile
create mode 100644 drivers/phy/mscc/phy-ocelot-serdes.c
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 5c8d452..c89d3ef 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -48,6 +48,7 @@ source "drivers/phy/lantiq/Kconfig"
source "drivers/phy/marvell/Kconfig"
source "drivers/phy/mediatek/Kconfig"
source "drivers/phy/motorola/Kconfig"
+source "drivers/phy/mscc/Kconfig"
source "drivers/phy/qualcomm/Kconfig"
source "drivers/phy/ralink/Kconfig"
source "drivers/phy/renesas/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 84e3bd9..ce8339f 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -18,6 +18,7 @@ obj-y += broadcom/ \
hisilicon/ \
marvell/ \
motorola/ \
+ mscc/ \
qualcomm/ \
ralink/ \
samsung/ \
diff --git a/drivers/phy/mscc/Kconfig b/drivers/phy/mscc/Kconfig
new file mode 100644
index 0000000..2e2a466
--- /dev/null
+++ b/drivers/phy/mscc/Kconfig
@@ -0,0 +1,11 @@
+#
+# Phy drivers for Microsemi devices
+#
+
+config PHY_OCELOT_SERDES
+ tristate "SerDes PHY driver for Microsemi Ocelot"
+ select GENERIC_PHY
+ depends on OF
+ depends on MFD_SYSCON
+ help
+ Enable this for supporting SerDes muxing with Microsemi Ocelot.
diff --git a/drivers/phy/mscc/Makefile b/drivers/phy/mscc/Makefile
new file mode 100644
index 0000000..e147491
--- /dev/null
+++ b/drivers/phy/mscc/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Microsemi phy drivers.
+#
+
+obj-$(CONFIG_PHY_OCELOT_SERDES) := phy-ocelot-serdes.o
diff --git a/drivers/phy/mscc/phy-ocelot-serdes.c b/drivers/phy/mscc/phy-ocelot-serdes.c
new file mode 100644
index 0000000..e87c400
--- /dev/null
+++ b/drivers/phy/mscc/phy-ocelot-serdes.c
@@ -0,0 +1,314 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * SerDes PHY driver for Microsemi Ocelot
+ *
+ * Copyright (c) 2018 Microsemi
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <soc/mscc/ocelot_hsio.h>
+
+#define SERDES1G_MAX 6
+#define SERDES6G_MAX 3
+#define SERDES_MAX (SERDES1G_MAX + SERDES6G_MAX)
+
+enum serdes_type {
+ SERDES1G = 1,
+ SERDES6G = 6,
+};
+
+struct serdes_ctrl {
+ struct regmap *regs;
+ struct device *dev;
+ struct phy *phys[SERDES_MAX];
+};
+
+struct serdes_macro {
+ enum serdes_type type;
+ u8 idx;
+ /* Not used when in QSGMII or PCIe mode */
+ int port;
+ struct serdes_ctrl *ctrl;
+};
+
+#define MCB_S1G_CFG_TIMEOUT 50
+
+static int __serdes_write_mcb_s1g(struct regmap *regmap, u8 macro, u32 op)
+{
+ unsigned int regval;
+
+ regmap_write(regmap, HSIO_MCB_S1G_ADDR_CFG, op |
+ HSIO_MCB_S1G_ADDR_CFG_SERDES1G_ADDR(BIT(macro)));
+
+ return regmap_read_poll_timeout(regmap, HSIO_MCB_S1G_ADDR_CFG, regval,
+ (regval & op) != op, 100,
+ MCB_S1G_CFG_TIMEOUT * 1000);
+}
+
+static int serdes_commit_mcb_s1g(struct regmap *regmap, u8 macro)
+{
+ return __serdes_write_mcb_s1g(regmap, macro,
+ HSIO_MCB_S1G_ADDR_CFG_SERDES1G_WR_ONE_SHOT);
+}
+
+static int serdes_update_mcb_s1g(struct regmap *regmap, u8 macro)
+{
+ return __serdes_write_mcb_s1g(regmap, macro,
+ HSIO_MCB_S1G_ADDR_CFG_SERDES1G_RD_ONE_SHOT);
+}
+
+static int serdes_init_s1g(struct regmap *regmap, u8 serdes)
+{
+ int ret;
+
+ ret = serdes_update_mcb_s1g(regmap, serdes);
+ if (ret)
+ return ret;
+
+ regmap_update_bits(regmap, HSIO_S1G_COMMON_CFG,
+ HSIO_S1G_COMMON_CFG_SYS_RST |
+ HSIO_S1G_COMMON_CFG_ENA_LANE |
+ HSIO_S1G_COMMON_CFG_ENA_ELOOP |
+ HSIO_S1G_COMMON_CFG_ENA_FLOOP,
+ HSIO_S1G_COMMON_CFG_ENA_LANE);
+
+ regmap_update_bits(regmap, HSIO_S1G_PLL_CFG,
+ HSIO_S1G_PLL_CFG_PLL_FSM_ENA |
+ HSIO_S1G_PLL_CFG_PLL_FSM_CTRL_DATA_M,
+ HSIO_S1G_PLL_CFG_PLL_FSM_CTRL_DATA(200) |
+ HSIO_S1G_PLL_CFG_PLL_FSM_ENA);
+
+ regmap_update_bits(regmap, HSIO_S1G_MISC_CFG,
+ HSIO_S1G_MISC_CFG_DES_100FX_CPMD_ENA |
+ HSIO_S1G_MISC_CFG_LANE_RST,
+ HSIO_S1G_MISC_CFG_LANE_RST);
+
+ ret = serdes_commit_mcb_s1g(regmap, serdes);
+ if (ret)
+ return ret;
+
+ regmap_update_bits(regmap, HSIO_S1G_COMMON_CFG,
+ HSIO_S1G_COMMON_CFG_SYS_RST,
+ HSIO_S1G_COMMON_CFG_SYS_RST);
+
+ regmap_update_bits(regmap, HSIO_S1G_MISC_CFG,
+ HSIO_S1G_MISC_CFG_LANE_RST, 0);
+
+ ret = serdes_commit_mcb_s1g(regmap, serdes);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+struct serdes_mux {
+ enum serdes_type type;
+ u8 idx;
+ u8 port;
+ enum phy_mode mode;
+ u32 mask;
+ u32 mux;
+};
+
+#define SERDES_MUX(_type, _idx, _port, _mode, _mask, _mux) { \
+ .type = _type, \
+ .idx = _idx, \
+ .port = _port, \
+ .mode = _mode, \
+ .mask = _mask, \
+ .mux = _mux, \
+}
+
+static const struct serdes_mux ocelot_serdes_muxes[] = {
+ SERDES_MUX(SERDES1G, 0, 0, PHY_MODE_SGMII, 0, 0),
+ SERDES_MUX(SERDES1G, 1, 1, PHY_MODE_SGMII, HSIO_HW_CFG_DEV1G_5_MODE, 0),
+ SERDES_MUX(SERDES1G, 1, 5, PHY_MODE_SGMII, HSIO_HW_CFG_QSGMII_ENA |
+ HSIO_HW_CFG_DEV1G_5_MODE, HSIO_HW_CFG_DEV1G_5_MODE),
+ SERDES_MUX(SERDES1G, 2, 2, PHY_MODE_SGMII, HSIO_HW_CFG_DEV1G_4_MODE, 0),
+ SERDES_MUX(SERDES1G, 2, 4, PHY_MODE_SGMII, HSIO_HW_CFG_QSGMII_ENA |
+ HSIO_HW_CFG_DEV1G_4_MODE, HSIO_HW_CFG_DEV1G_4_MODE),
+ SERDES_MUX(SERDES1G, 3, 3, PHY_MODE_SGMII, HSIO_HW_CFG_DEV1G_6_MODE, 0),
+ SERDES_MUX(SERDES1G, 3, 6, PHY_MODE_SGMII, HSIO_HW_CFG_QSGMII_ENA |
+ HSIO_HW_CFG_DEV1G_6_MODE, HSIO_HW_CFG_DEV1G_6_MODE),
+ SERDES_MUX(SERDES1G, 4, 4, PHY_MODE_SGMII, HSIO_HW_CFG_QSGMII_ENA |
+ HSIO_HW_CFG_DEV1G_4_MODE | HSIO_HW_CFG_DEV1G_9_MODE, 0),
+ SERDES_MUX(SERDES1G, 4, 9, PHY_MODE_SGMII, HSIO_HW_CFG_DEV1G_4_MODE |
+ HSIO_HW_CFG_DEV1G_9_MODE, HSIO_HW_CFG_DEV1G_4_MODE |
+ HSIO_HW_CFG_DEV1G_9_MODE),
+ SERDES_MUX(SERDES1G, 5, 5, PHY_MODE_SGMII, HSIO_HW_CFG_QSGMII_ENA |
+ HSIO_HW_CFG_DEV1G_5_MODE | HSIO_HW_CFG_DEV2G5_10_MODE, 0),
+ SERDES_MUX(SERDES1G, 5, 10, PHY_MODE_SGMII, HSIO_HW_CFG_PCIE_ENA |
+ HSIO_HW_CFG_DEV1G_5_MODE | HSIO_HW_CFG_DEV2G5_10_MODE,
+ HSIO_HW_CFG_DEV1G_5_MODE | HSIO_HW_CFG_DEV2G5_10_MODE),
+ SERDES_MUX(SERDES6G, 0, 4, PHY_MODE_QSGMII, HSIO_HW_CFG_QSGMII_ENA,
+ HSIO_HW_CFG_QSGMII_ENA),
+ SERDES_MUX(SERDES6G, 0, 5, PHY_MODE_QSGMII, HSIO_HW_CFG_QSGMII_ENA,
+ HSIO_HW_CFG_QSGMII_ENA),
+ SERDES_MUX(SERDES6G, 0, 6, PHY_MODE_QSGMII, HSIO_HW_CFG_QSGMII_ENA,
+ HSIO_HW_CFG_QSGMII_ENA),
+ SERDES_MUX(SERDES6G, 0, 7, PHY_MODE_SGMII, HSIO_HW_CFG_QSGMII_ENA, 0),
+ SERDES_MUX(SERDES6G, 0, 7, PHY_MODE_QSGMII, HSIO_HW_CFG_QSGMII_ENA,
+ HSIO_HW_CFG_QSGMII_ENA),
+ SERDES_MUX(SERDES6G, 1, 8, PHY_MODE_SGMII, 0, 0),
+ SERDES_MUX(SERDES6G, 2, 10, PHY_MODE_SGMII, HSIO_HW_CFG_PCIE_ENA |
+ HSIO_HW_CFG_DEV2G5_10_MODE, 0),
+ SERDES_MUX(SERDES6G, 2, 10, PHY_MODE_PCIE, HSIO_HW_CFG_PCIE_ENA,
+ HSIO_HW_CFG_PCIE_ENA),
+};
+
+static int serdes_set_mode(struct phy *phy, enum phy_mode mode)
+{
+ struct serdes_macro *macro = phy_get_drvdata(phy);
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(ocelot_serdes_muxes); i++) {
+ if (macro->type != ocelot_serdes_muxes[i].type ||
+ macro->idx != ocelot_serdes_muxes[i].idx ||
+ mode != ocelot_serdes_muxes[i].mode)
+ continue;
+
+ if (mode != PHY_MODE_QSGMII &&
+ macro->port != ocelot_serdes_muxes[i].port)
+ continue;
+
+ ret = regmap_update_bits(macro->ctrl->regs, HSIO_HW_CFG,
+ ocelot_serdes_muxes[i].mask,
+ ocelot_serdes_muxes[i].mux);
+ if (ret)
+ return ret;
+
+ if (macro->type == SERDES1G)
+ return serdes_init_s1g(macro->ctrl->regs, macro->idx);
+
+ /* SERDES6G and PCIe not supported yet */
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static const struct phy_ops serdes_ops = {
+ .set_mode = serdes_set_mode,
+ .owner = THIS_MODULE,
+};
+
+static struct phy *serdes_simple_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ enum serdes_type type;
+ int port, i;
+ u8 idx;
+ struct serdes_ctrl *ctrl = dev_get_drvdata(dev);
+
+ if (args->args_count != 3)
+ return ERR_PTR(-EINVAL);
+
+ type = args->args[0];
+ idx = args->args[1];
+ port = args->args[2];
+
+ for (i = 0; i < SERDES_MAX; i++) {
+ struct serdes_macro *macro = phy_get_drvdata(ctrl->phys[i]);
+
+ if (type != macro->type)
+ continue;
+ if (idx != macro->idx)
+ continue;
+
+ /* SERDES6G_0 is the only SerDes capable of QSGMII */
+ if ((type == SERDES1G || macro->idx != 0) && macro->port >= 0)
+ return ERR_PTR(-EBUSY);
+
+ macro->port = port;
+ return ctrl->phys[i];
+ }
+
+ return ERR_PTR(-ENODEV);
+}
+
+static int serdes_phy_create(struct serdes_ctrl *ctrl, u8 idx,
+ enum serdes_type type, struct phy **phy)
+{
+ struct serdes_macro *macro;
+
+ *phy = devm_phy_create(ctrl->dev, NULL, &serdes_ops);
+ if (IS_ERR(*phy))
+ return PTR_ERR(*phy);
+
+ macro = devm_kzalloc(ctrl->dev, sizeof(*macro), GFP_KERNEL);
+ if (!macro)
+ return -ENOMEM;
+
+ macro->idx = idx;
+ macro->type = type;
+ macro->ctrl = ctrl;
+ macro->port = -1;
+
+ phy_set_drvdata(*phy, macro);
+
+ return 0;
+}
+
+static int serdes_probe(struct platform_device *pdev)
+{
+ struct phy_provider *provider;
+ struct serdes_ctrl *ctrl;
+ int i, ret;
+
+ ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+
+ ctrl->dev = &pdev->dev;
+ ctrl->regs = syscon_node_to_regmap(pdev->dev.parent->of_node);
+ if (!ctrl->regs)
+ return -ENODEV;
+
+ for (i = 0; i < SERDES1G_MAX; i++) {
+ ret = serdes_phy_create(ctrl, i, SERDES1G, &ctrl->phys[i]);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < SERDES6G_MAX; i++) {
+ ret = serdes_phy_create(ctrl, i, SERDES6G,
+ &ctrl->phys[SERDES1G_MAX + i]);
+ if (ret)
+ return ret;
+ }
+
+ dev_set_drvdata(&pdev->dev, ctrl);
+
+ provider = devm_of_phy_provider_register(ctrl->dev,
+ serdes_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(provider);
+}
+
+static const struct of_device_id serdes_ids[] = {
+ { .compatible = "mscc,vsc7514-serdes", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, serdes_ids);
+
+static struct platform_driver mscc_ocelot_serdes = {
+ .probe = serdes_probe,
+ .driver = {
+ .name = "mscc,ocelot-serdes",
+ .of_match_table = of_match_ptr(serdes_ids),
+ },
+};
+
+module_platform_driver(mscc_ocelot_serdes);
+
+MODULE_AUTHOR("Quentin Schulz <quentin.schulz@bootlin.com>");
+MODULE_DESCRIPTION("SerDes driver for Microsemi Ocelot");
+MODULE_LICENSE("Dual MIT/GPL");
--
git-series 0.9.1
^ permalink raw reply related
* [PATCH 08/10] MIPS: mscc: ocelot: add SerDes mux DT node
From: Quentin Schulz @ 2018-07-30 12:43 UTC (permalink / raw)
To: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, davem
Cc: kishon, andrew, f.fainelli, linux-mips, devicetree, linux-kernel,
netdev, allan.nielsen, thomas.petazzoni, Quentin Schulz
In-Reply-To: <cover.aa759035f6eefdd0bb2a5ae335dab5bd5399bd46.1532954208.git-series.quentin.schulz@bootlin.com>
The Microsemi Ocelot has a set of register for SerDes/switch port muxing
as well as PCIe muxing for a specific SerDes, so let's add the device
and all SerDes in the Device Tree.
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
arch/mips/boot/dts/mscc/ocelot.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/mips/boot/dts/mscc/ocelot.dtsi b/arch/mips/boot/dts/mscc/ocelot.dtsi
index c51663a..e03edf3 100644
--- a/arch/mips/boot/dts/mscc/ocelot.dtsi
+++ b/arch/mips/boot/dts/mscc/ocelot.dtsi
@@ -223,6 +223,11 @@
hsio: syscon@10d0000 {
compatible = "mscc,ocelot-hsio", "syscon", "simple-mfd";
reg = <0x10d0000 0x10000>;
+
+ serdes: serdes {
+ compatible = "mscc,vsc7514-serdes";
+ #phy-cells = <3>;
+ };
};
};
};
--
git-series 0.9.1
^ permalink raw reply related
* [PATCH 07/10] dt-bindings: phy: add DT binding for Microsemi Ocelot SerDes muxing
From: Quentin Schulz @ 2018-07-30 12:43 UTC (permalink / raw)
To: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, davem
Cc: kishon, andrew, f.fainelli, linux-mips, devicetree, linux-kernel,
netdev, allan.nielsen, thomas.petazzoni, Quentin Schulz
In-Reply-To: <cover.aa759035f6eefdd0bb2a5ae335dab5bd5399bd46.1532954208.git-series.quentin.schulz@bootlin.com>
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
Documentation/devicetree/bindings/phy/phy-ocelot-serdes.txt | 42 +++++++-
1 file changed, 42 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/phy-ocelot-serdes.txt
diff --git a/Documentation/devicetree/bindings/phy/phy-ocelot-serdes.txt b/Documentation/devicetree/bindings/phy/phy-ocelot-serdes.txt
new file mode 100644
index 0000000..25b102d
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-ocelot-serdes.txt
@@ -0,0 +1,42 @@
+Microsemi Ocelot SerDes muxing driver
+-------------------------------------
+
+On Microsemi Ocelot, there is a handful of registers in HSIO address
+space for setting up the SerDes to switch port muxing.
+
+A SerDes X can be "muxed" to work with switch port Y or Z for example.
+One specific SerDes can also be used as a PCIe interface.
+
+Hence, a SerDes represents an interface, be it an Ethernet or a PCIe one.
+
+There are two kinds of SerDes: SERDES1G supports 10/100Mbps in
+half/full-duplex and 1000Mbps in full-duplex mode while SERDES6G supports
+10/100Mbps in half/full-duplex and 1000/2500Mbps in full-duplex mode.
+
+Also, SERDES6G number (aka "macro") 0 is the only interface supporting
+QSGMII.
+
+Required properties:
+
+- compatible: should be "mscc,vsc7514-serdes"
+- #phy-cells : from the generic phy bindings, must be 3. The first number
+ defines the kind of Serdes (1 for SERDES1G_X, 6 for
+ SERDES6G_X), the second defines the macros in the specified
+ kind of Serdes (X for SERDES1G_X or SERDES6G_X) and the
+ last one defines the input port to use for a given SerDes
+ macro,
+
+Example:
+
+ serdes: serdes {
+ compatible = "mscc,vsc7514-serdes";
+ #phy-cells = <3>;
+ };
+
+ ethernet {
+ port1 {
+ phy-handle = <&phy_foo>;
+ /* Link SERDES1G_5 to port1 */
+ phys = <&serdes 1 5 1>;
+ };
+ };
--
git-series 0.9.1
^ permalink raw reply related
* [PATCH 06/10] phy: add QSGMII and PCIE modes
From: Quentin Schulz @ 2018-07-30 12:43 UTC (permalink / raw)
To: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, davem
Cc: kishon, andrew, f.fainelli, linux-mips, devicetree, linux-kernel,
netdev, allan.nielsen, thomas.petazzoni, Quentin Schulz
In-Reply-To: <cover.aa759035f6eefdd0bb2a5ae335dab5bd5399bd46.1532954208.git-series.quentin.schulz@bootlin.com>
Prepare for upcoming phys that'll handle QSGMII or PCIe.
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
include/linux/phy/phy.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 9713aeb..03b319f 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -37,9 +37,11 @@ enum phy_mode {
PHY_MODE_USB_OTG,
PHY_MODE_SGMII,
PHY_MODE_2500SGMII,
+ PHY_MODE_QSGMII,
PHY_MODE_10GKR,
PHY_MODE_UFS_HS_A,
PHY_MODE_UFS_HS_B,
+ PHY_MODE_PCIE,
};
/**
--
git-series 0.9.1
^ permalink raw reply related
* [PATCH net-next 05/10] net: mscc: ocelot: simplify register access for PLL5 configuration
From: Quentin Schulz @ 2018-07-30 12:43 UTC (permalink / raw)
To: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, davem
Cc: kishon, andrew, f.fainelli, linux-mips, devicetree, linux-kernel,
netdev, allan.nielsen, thomas.petazzoni, Quentin Schulz
In-Reply-To: <cover.aa759035f6eefdd0bb2a5ae335dab5bd5399bd46.1532954208.git-series.quentin.schulz@bootlin.com>
Since HSIO address space can be accessed by different drivers, let's
simplify the register address definitions so that it can be easily used
by all drivers and put the register address definition in the
include/soc/mscc/ocelot_hsio.h header file.
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
drivers/net/ethernet/mscc/ocelot.h | 73 +---------------------
drivers/net/ethernet/mscc/ocelot_regs.c | 92 ++------------------------
include/soc/mscc/ocelot_hsio.h | 74 +++++++++++++++++++++-
3 files changed, 83 insertions(+), 156 deletions(-)
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 2da20a3..3720e51 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -332,79 +332,6 @@ enum ocelot_reg {
SYS_CM_DATA_RD,
SYS_CM_OP,
SYS_CM_DATA,
- HSIO_PLL5G_CFG0 = HSIO << TARGET_OFFSET,
- HSIO_PLL5G_CFG1,
- HSIO_PLL5G_CFG2,
- HSIO_PLL5G_CFG3,
- HSIO_PLL5G_CFG4,
- HSIO_PLL5G_CFG5,
- HSIO_PLL5G_CFG6,
- HSIO_PLL5G_STATUS0,
- HSIO_PLL5G_STATUS1,
- HSIO_PLL5G_BIST_CFG0,
- HSIO_PLL5G_BIST_CFG1,
- HSIO_PLL5G_BIST_CFG2,
- HSIO_PLL5G_BIST_STAT0,
- HSIO_PLL5G_BIST_STAT1,
- HSIO_RCOMP_CFG0,
- HSIO_RCOMP_STATUS,
- HSIO_SYNC_ETH_CFG,
- HSIO_SYNC_ETH_PLL_CFG,
- HSIO_S1G_DES_CFG,
- HSIO_S1G_IB_CFG,
- HSIO_S1G_OB_CFG,
- HSIO_S1G_SER_CFG,
- HSIO_S1G_COMMON_CFG,
- HSIO_S1G_PLL_CFG,
- HSIO_S1G_PLL_STATUS,
- HSIO_S1G_DFT_CFG0,
- HSIO_S1G_DFT_CFG1,
- HSIO_S1G_DFT_CFG2,
- HSIO_S1G_TP_CFG,
- HSIO_S1G_RC_PLL_BIST_CFG,
- HSIO_S1G_MISC_CFG,
- HSIO_S1G_DFT_STATUS,
- HSIO_S1G_MISC_STATUS,
- HSIO_MCB_S1G_ADDR_CFG,
- HSIO_S6G_DIG_CFG,
- HSIO_S6G_DFT_CFG0,
- HSIO_S6G_DFT_CFG1,
- HSIO_S6G_DFT_CFG2,
- HSIO_S6G_TP_CFG0,
- HSIO_S6G_TP_CFG1,
- HSIO_S6G_RC_PLL_BIST_CFG,
- HSIO_S6G_MISC_CFG,
- HSIO_S6G_OB_ANEG_CFG,
- HSIO_S6G_DFT_STATUS,
- HSIO_S6G_ERR_CNT,
- HSIO_S6G_MISC_STATUS,
- HSIO_S6G_DES_CFG,
- HSIO_S6G_IB_CFG,
- HSIO_S6G_IB_CFG1,
- HSIO_S6G_IB_CFG2,
- HSIO_S6G_IB_CFG3,
- HSIO_S6G_IB_CFG4,
- HSIO_S6G_IB_CFG5,
- HSIO_S6G_OB_CFG,
- HSIO_S6G_OB_CFG1,
- HSIO_S6G_SER_CFG,
- HSIO_S6G_COMMON_CFG,
- HSIO_S6G_PLL_CFG,
- HSIO_S6G_ACJTAG_CFG,
- HSIO_S6G_GP_CFG,
- HSIO_S6G_IB_STATUS0,
- HSIO_S6G_IB_STATUS1,
- HSIO_S6G_ACJTAG_STATUS,
- HSIO_S6G_PLL_STATUS,
- HSIO_S6G_REVID,
- HSIO_MCB_S6G_ADDR_CFG,
- HSIO_HW_CFG,
- HSIO_HW_QSGMII_CFG,
- HSIO_HW_QSGMII_STAT,
- HSIO_CLK_CFG,
- HSIO_TEMP_SENSOR_CTRL,
- HSIO_TEMP_SENSOR_CFG,
- HSIO_TEMP_SENSOR_STAT,
};
enum ocelot_regfield {
diff --git a/drivers/net/ethernet/mscc/ocelot_regs.c b/drivers/net/ethernet/mscc/ocelot_regs.c
index bf0c609..9271af1 100644
--- a/drivers/net/ethernet/mscc/ocelot_regs.c
+++ b/drivers/net/ethernet/mscc/ocelot_regs.c
@@ -103,82 +103,6 @@ static const u32 ocelot_qs_regmap[] = {
REG(QS_INH_DBG, 0x000048),
};
-static const u32 ocelot_hsio_regmap[] = {
- REG(HSIO_PLL5G_CFG0, 0x000000),
- REG(HSIO_PLL5G_CFG1, 0x000004),
- REG(HSIO_PLL5G_CFG2, 0x000008),
- REG(HSIO_PLL5G_CFG3, 0x00000c),
- REG(HSIO_PLL5G_CFG4, 0x000010),
- REG(HSIO_PLL5G_CFG5, 0x000014),
- REG(HSIO_PLL5G_CFG6, 0x000018),
- REG(HSIO_PLL5G_STATUS0, 0x00001c),
- REG(HSIO_PLL5G_STATUS1, 0x000020),
- REG(HSIO_PLL5G_BIST_CFG0, 0x000024),
- REG(HSIO_PLL5G_BIST_CFG1, 0x000028),
- REG(HSIO_PLL5G_BIST_CFG2, 0x00002c),
- REG(HSIO_PLL5G_BIST_STAT0, 0x000030),
- REG(HSIO_PLL5G_BIST_STAT1, 0x000034),
- REG(HSIO_RCOMP_CFG0, 0x000038),
- REG(HSIO_RCOMP_STATUS, 0x00003c),
- REG(HSIO_SYNC_ETH_CFG, 0x000040),
- REG(HSIO_SYNC_ETH_PLL_CFG, 0x000048),
- REG(HSIO_S1G_DES_CFG, 0x00004c),
- REG(HSIO_S1G_IB_CFG, 0x000050),
- REG(HSIO_S1G_OB_CFG, 0x000054),
- REG(HSIO_S1G_SER_CFG, 0x000058),
- REG(HSIO_S1G_COMMON_CFG, 0x00005c),
- REG(HSIO_S1G_PLL_CFG, 0x000060),
- REG(HSIO_S1G_PLL_STATUS, 0x000064),
- REG(HSIO_S1G_DFT_CFG0, 0x000068),
- REG(HSIO_S1G_DFT_CFG1, 0x00006c),
- REG(HSIO_S1G_DFT_CFG2, 0x000070),
- REG(HSIO_S1G_TP_CFG, 0x000074),
- REG(HSIO_S1G_RC_PLL_BIST_CFG, 0x000078),
- REG(HSIO_S1G_MISC_CFG, 0x00007c),
- REG(HSIO_S1G_DFT_STATUS, 0x000080),
- REG(HSIO_S1G_MISC_STATUS, 0x000084),
- REG(HSIO_MCB_S1G_ADDR_CFG, 0x000088),
- REG(HSIO_S6G_DIG_CFG, 0x00008c),
- REG(HSIO_S6G_DFT_CFG0, 0x000090),
- REG(HSIO_S6G_DFT_CFG1, 0x000094),
- REG(HSIO_S6G_DFT_CFG2, 0x000098),
- REG(HSIO_S6G_TP_CFG0, 0x00009c),
- REG(HSIO_S6G_TP_CFG1, 0x0000a0),
- REG(HSIO_S6G_RC_PLL_BIST_CFG, 0x0000a4),
- REG(HSIO_S6G_MISC_CFG, 0x0000a8),
- REG(HSIO_S6G_OB_ANEG_CFG, 0x0000ac),
- REG(HSIO_S6G_DFT_STATUS, 0x0000b0),
- REG(HSIO_S6G_ERR_CNT, 0x0000b4),
- REG(HSIO_S6G_MISC_STATUS, 0x0000b8),
- REG(HSIO_S6G_DES_CFG, 0x0000bc),
- REG(HSIO_S6G_IB_CFG, 0x0000c0),
- REG(HSIO_S6G_IB_CFG1, 0x0000c4),
- REG(HSIO_S6G_IB_CFG2, 0x0000c8),
- REG(HSIO_S6G_IB_CFG3, 0x0000cc),
- REG(HSIO_S6G_IB_CFG4, 0x0000d0),
- REG(HSIO_S6G_IB_CFG5, 0x0000d4),
- REG(HSIO_S6G_OB_CFG, 0x0000d8),
- REG(HSIO_S6G_OB_CFG1, 0x0000dc),
- REG(HSIO_S6G_SER_CFG, 0x0000e0),
- REG(HSIO_S6G_COMMON_CFG, 0x0000e4),
- REG(HSIO_S6G_PLL_CFG, 0x0000e8),
- REG(HSIO_S6G_ACJTAG_CFG, 0x0000ec),
- REG(HSIO_S6G_GP_CFG, 0x0000f0),
- REG(HSIO_S6G_IB_STATUS0, 0x0000f4),
- REG(HSIO_S6G_IB_STATUS1, 0x0000f8),
- REG(HSIO_S6G_ACJTAG_STATUS, 0x0000fc),
- REG(HSIO_S6G_PLL_STATUS, 0x000100),
- REG(HSIO_S6G_REVID, 0x000104),
- REG(HSIO_MCB_S6G_ADDR_CFG, 0x000108),
- REG(HSIO_HW_CFG, 0x00010c),
- REG(HSIO_HW_QSGMII_CFG, 0x000110),
- REG(HSIO_HW_QSGMII_STAT, 0x000114),
- REG(HSIO_CLK_CFG, 0x000118),
- REG(HSIO_TEMP_SENSOR_CTRL, 0x00011c),
- REG(HSIO_TEMP_SENSOR_CFG, 0x000120),
- REG(HSIO_TEMP_SENSOR_STAT, 0x000124),
-};
-
static const u32 ocelot_qsys_regmap[] = {
REG(QSYS_PORT_MODE, 0x011200),
REG(QSYS_SWITCH_PORT_MODE, 0x011234),
@@ -303,7 +227,6 @@ static const u32 ocelot_sys_regmap[] = {
static const u32 *ocelot_regmap[] = {
[ANA] = ocelot_ana_regmap,
[QS] = ocelot_qs_regmap,
- [HSIO] = ocelot_hsio_regmap,
[QSYS] = ocelot_qsys_regmap,
[REW] = ocelot_rew_regmap,
[SYS] = ocelot_sys_regmap,
@@ -454,9 +377,11 @@ static void ocelot_pll5_init(struct ocelot *ocelot)
/* Configure PLL5. This will need a proper CCF driver
* The values are coming from the VTSS API for Ocelot
*/
- ocelot_write(ocelot, HSIO_PLL5G_CFG4_IB_CTRL(0x7600) |
- HSIO_PLL5G_CFG4_IB_BIAS_CTRL(0x8), HSIO_PLL5G_CFG4);
- ocelot_write(ocelot, HSIO_PLL5G_CFG0_CORE_CLK_DIV(0x11) |
+ regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG4,
+ HSIO_PLL5G_CFG4_IB_CTRL(0x7600) |
+ HSIO_PLL5G_CFG4_IB_BIAS_CTRL(0x8));
+ regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG0,
+ HSIO_PLL5G_CFG0_CORE_CLK_DIV(0x11) |
HSIO_PLL5G_CFG0_CPU_CLK_DIV(2) |
HSIO_PLL5G_CFG0_ENA_BIAS |
HSIO_PLL5G_CFG0_ENA_VCO_BUF |
@@ -466,13 +391,14 @@ static void ocelot_pll5_init(struct ocelot *ocelot)
HSIO_PLL5G_CFG0_SELBGV820(4) |
HSIO_PLL5G_CFG0_DIV4 |
HSIO_PLL5G_CFG0_ENA_CLKTREE |
- HSIO_PLL5G_CFG0_ENA_LANE, HSIO_PLL5G_CFG0);
- ocelot_write(ocelot, HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET |
+ HSIO_PLL5G_CFG0_ENA_LANE);
+ regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG2,
+ HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET |
HSIO_PLL5G_CFG2_EN_RESET_OVERRUN |
HSIO_PLL5G_CFG2_GAIN_TEST(0x8) |
HSIO_PLL5G_CFG2_ENA_AMPCTRL |
HSIO_PLL5G_CFG2_PWD_AMPCTRL_N |
- HSIO_PLL5G_CFG2_AMPC_SEL(0x10), HSIO_PLL5G_CFG2);
+ HSIO_PLL5G_CFG2_AMPC_SEL(0x10));
}
int ocelot_chip_init(struct ocelot *ocelot)
diff --git a/include/soc/mscc/ocelot_hsio.h b/include/soc/mscc/ocelot_hsio.h
index d93ddec..43112dd 100644
--- a/include/soc/mscc/ocelot_hsio.h
+++ b/include/soc/mscc/ocelot_hsio.h
@@ -8,6 +8,80 @@
#ifndef _MSCC_OCELOT_HSIO_H_
#define _MSCC_OCELOT_HSIO_H_
+#define HSIO_PLL5G_CFG0 0x0000
+#define HSIO_PLL5G_CFG1 0x0004
+#define HSIO_PLL5G_CFG2 0x0008
+#define HSIO_PLL5G_CFG3 0x000c
+#define HSIO_PLL5G_CFG4 0x0010
+#define HSIO_PLL5G_CFG5 0x0014
+#define HSIO_PLL5G_CFG6 0x0018
+#define HSIO_PLL5G_STATUS0 0x001c
+#define HSIO_PLL5G_STATUS1 0x0020
+#define HSIO_PLL5G_BIST_CFG0 0x0024
+#define HSIO_PLL5G_BIST_CFG1 0x0028
+#define HSIO_PLL5G_BIST_CFG2 0x002c
+#define HSIO_PLL5G_BIST_STAT0 0x0030
+#define HSIO_PLL5G_BIST_STAT1 0x0034
+#define HSIO_RCOMP_CFG0 0x0038
+#define HSIO_RCOMP_STATUS 0x003c
+#define HSIO_SYNC_ETH_CFG 0x0040
+#define HSIO_SYNC_ETH_PLL_CFG 0x0048
+#define HSIO_S1G_DES_CFG 0x004c
+#define HSIO_S1G_IB_CFG 0x0050
+#define HSIO_S1G_OB_CFG 0x0054
+#define HSIO_S1G_SER_CFG 0x0058
+#define HSIO_S1G_COMMON_CFG 0x005c
+#define HSIO_S1G_PLL_CFG 0x0060
+#define HSIO_S1G_PLL_STATUS 0x0064
+#define HSIO_S1G_DFT_CFG0 0x0068
+#define HSIO_S1G_DFT_CFG1 0x006c
+#define HSIO_S1G_DFT_CFG2 0x0070
+#define HSIO_S1G_TP_CFG 0x0074
+#define HSIO_S1G_RC_PLL_BIST_CFG 0x0078
+#define HSIO_S1G_MISC_CFG 0x007c
+#define HSIO_S1G_DFT_STATUS 0x0080
+#define HSIO_S1G_MISC_STATUS 0x0084
+#define HSIO_MCB_S1G_ADDR_CFG 0x0088
+#define HSIO_S6G_DIG_CFG 0x008c
+#define HSIO_S6G_DFT_CFG0 0x0090
+#define HSIO_S6G_DFT_CFG1 0x0094
+#define HSIO_S6G_DFT_CFG2 0x0098
+#define HSIO_S6G_TP_CFG0 0x009c
+#define HSIO_S6G_TP_CFG1 0x00a0
+#define HSIO_S6G_RC_PLL_BIST_CFG 0x00a4
+#define HSIO_S6G_MISC_CFG 0x00a8
+#define HSIO_S6G_OB_ANEG_CFG 0x00ac
+#define HSIO_S6G_DFT_STATUS 0x00b0
+#define HSIO_S6G_ERR_CNT 0x00b4
+#define HSIO_S6G_MISC_STATUS 0x00b8
+#define HSIO_S6G_DES_CFG 0x00bc
+#define HSIO_S6G_IB_CFG 0x00c0
+#define HSIO_S6G_IB_CFG1 0x00c4
+#define HSIO_S6G_IB_CFG2 0x00c8
+#define HSIO_S6G_IB_CFG3 0x00cc
+#define HSIO_S6G_IB_CFG4 0x00d0
+#define HSIO_S6G_IB_CFG5 0x00d4
+#define HSIO_S6G_OB_CFG 0x00d8
+#define HSIO_S6G_OB_CFG1 0x00dc
+#define HSIO_S6G_SER_CFG 0x00e0
+#define HSIO_S6G_COMMON_CFG 0x00e4
+#define HSIO_S6G_PLL_CFG 0x00e8
+#define HSIO_S6G_ACJTAG_CFG 0x00ec
+#define HSIO_S6G_GP_CFG 0x00f0
+#define HSIO_S6G_IB_STATUS0 0x00f4
+#define HSIO_S6G_IB_STATUS1 0x00f8
+#define HSIO_S6G_ACJTAG_STATUS 0x00fc
+#define HSIO_S6G_PLL_STATUS 0x0100
+#define HSIO_S6G_REVID 0x0104
+#define HSIO_MCB_S6G_ADDR_CFG 0x0108
+#define HSIO_HW_CFG 0x010c
+#define HSIO_HW_QSGMII_CFG 0x0110
+#define HSIO_HW_QSGMII_STAT 0x0114
+#define HSIO_CLK_CFG 0x0118
+#define HSIO_TEMP_SENSOR_CTRL 0x011c
+#define HSIO_TEMP_SENSOR_CFG 0x0120
+#define HSIO_TEMP_SENSOR_STAT 0x0124
+
#define HSIO_PLL5G_CFG0_ENA_ROT BIT(31)
#define HSIO_PLL5G_CFG0_ENA_LANE BIT(30)
#define HSIO_PLL5G_CFG0_ENA_CLKTREE BIT(29)
--
git-series 0.9.1
^ permalink raw reply related
* [PATCH net-next 04/10] net: mscc: ocelot: move the HSIO header to include/soc
From: Quentin Schulz @ 2018-07-30 12:43 UTC (permalink / raw)
To: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, davem
Cc: kishon, andrew, f.fainelli, linux-mips, devicetree, linux-kernel,
netdev, allan.nielsen, thomas.petazzoni, Quentin Schulz
In-Reply-To: <cover.aa759035f6eefdd0bb2a5ae335dab5bd5399bd46.1532954208.git-series.quentin.schulz@bootlin.com>
Since HSIO address space can be used by different drivers (PLL, SerDes
muxing, temperature sensor), let's move it somewhere it can be included
by all drivers.
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
drivers/net/ethernet/mscc/ocelot.h | 1 +-
drivers/net/ethernet/mscc/ocelot_hsio.h | 785 +-------------------------
drivers/net/ethernet/mscc/ocelot_regs.c | 1 +-
include/soc/mscc/ocelot_hsio.h | 785 +++++++++++++++++++++++++-
4 files changed, 786 insertions(+), 786 deletions(-)
delete mode 100644 drivers/net/ethernet/mscc/ocelot_hsio.h
create mode 100644 include/soc/mscc/ocelot_hsio.h
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 616bec3..2da20a3 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -16,7 +16,6 @@
#include "ocelot_ana.h"
#include "ocelot_dev.h"
-#include "ocelot_hsio.h"
#include "ocelot_qsys.h"
#include "ocelot_rew.h"
#include "ocelot_sys.h"
diff --git a/drivers/net/ethernet/mscc/ocelot_hsio.h b/drivers/net/ethernet/mscc/ocelot_hsio.h
deleted file mode 100644
index d93ddec..0000000
--- a/drivers/net/ethernet/mscc/ocelot_hsio.h
+++ /dev/null
@@ -1,785 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
-/*
- * Microsemi Ocelot Switch driver
- *
- * Copyright (c) 2017 Microsemi Corporation
- */
-
-#ifndef _MSCC_OCELOT_HSIO_H_
-#define _MSCC_OCELOT_HSIO_H_
-
-#define HSIO_PLL5G_CFG0_ENA_ROT BIT(31)
-#define HSIO_PLL5G_CFG0_ENA_LANE BIT(30)
-#define HSIO_PLL5G_CFG0_ENA_CLKTREE BIT(29)
-#define HSIO_PLL5G_CFG0_DIV4 BIT(28)
-#define HSIO_PLL5G_CFG0_ENA_LOCK_FINE BIT(27)
-#define HSIO_PLL5G_CFG0_SELBGV820(x) (((x) << 23) & GENMASK(26, 23))
-#define HSIO_PLL5G_CFG0_SELBGV820_M GENMASK(26, 23)
-#define HSIO_PLL5G_CFG0_SELBGV820_X(x) (((x) & GENMASK(26, 23)) >> 23)
-#define HSIO_PLL5G_CFG0_LOOP_BW_RES(x) (((x) << 18) & GENMASK(22, 18))
-#define HSIO_PLL5G_CFG0_LOOP_BW_RES_M GENMASK(22, 18)
-#define HSIO_PLL5G_CFG0_LOOP_BW_RES_X(x) (((x) & GENMASK(22, 18)) >> 18)
-#define HSIO_PLL5G_CFG0_SELCPI(x) (((x) << 16) & GENMASK(17, 16))
-#define HSIO_PLL5G_CFG0_SELCPI_M GENMASK(17, 16)
-#define HSIO_PLL5G_CFG0_SELCPI_X(x) (((x) & GENMASK(17, 16)) >> 16)
-#define HSIO_PLL5G_CFG0_ENA_VCO_CONTRH BIT(15)
-#define HSIO_PLL5G_CFG0_ENA_CP1 BIT(14)
-#define HSIO_PLL5G_CFG0_ENA_VCO_BUF BIT(13)
-#define HSIO_PLL5G_CFG0_ENA_BIAS BIT(12)
-#define HSIO_PLL5G_CFG0_CPU_CLK_DIV(x) (((x) << 6) & GENMASK(11, 6))
-#define HSIO_PLL5G_CFG0_CPU_CLK_DIV_M GENMASK(11, 6)
-#define HSIO_PLL5G_CFG0_CPU_CLK_DIV_X(x) (((x) & GENMASK(11, 6)) >> 6)
-#define HSIO_PLL5G_CFG0_CORE_CLK_DIV(x) ((x) & GENMASK(5, 0))
-#define HSIO_PLL5G_CFG0_CORE_CLK_DIV_M GENMASK(5, 0)
-
-#define HSIO_PLL5G_CFG1_ENA_DIRECT BIT(18)
-#define HSIO_PLL5G_CFG1_ROT_SPEED BIT(17)
-#define HSIO_PLL5G_CFG1_ROT_DIR BIT(16)
-#define HSIO_PLL5G_CFG1_READBACK_DATA_SEL BIT(15)
-#define HSIO_PLL5G_CFG1_RC_ENABLE BIT(14)
-#define HSIO_PLL5G_CFG1_RC_CTRL_DATA(x) (((x) << 6) & GENMASK(13, 6))
-#define HSIO_PLL5G_CFG1_RC_CTRL_DATA_M GENMASK(13, 6)
-#define HSIO_PLL5G_CFG1_RC_CTRL_DATA_X(x) (((x) & GENMASK(13, 6)) >> 6)
-#define HSIO_PLL5G_CFG1_QUARTER_RATE BIT(5)
-#define HSIO_PLL5G_CFG1_PWD_TX BIT(4)
-#define HSIO_PLL5G_CFG1_PWD_RX BIT(3)
-#define HSIO_PLL5G_CFG1_OUT_OF_RANGE_RECAL_ENA BIT(2)
-#define HSIO_PLL5G_CFG1_HALF_RATE BIT(1)
-#define HSIO_PLL5G_CFG1_FORCE_SET_ENA BIT(0)
-
-#define HSIO_PLL5G_CFG2_ENA_TEST_MODE BIT(30)
-#define HSIO_PLL5G_CFG2_ENA_PFD_IN_FLIP BIT(29)
-#define HSIO_PLL5G_CFG2_ENA_VCO_NREF_TESTOUT BIT(28)
-#define HSIO_PLL5G_CFG2_ENA_FBTESTOUT BIT(27)
-#define HSIO_PLL5G_CFG2_ENA_RCPLL BIT(26)
-#define HSIO_PLL5G_CFG2_ENA_CP2 BIT(25)
-#define HSIO_PLL5G_CFG2_ENA_CLK_BYPASS1 BIT(24)
-#define HSIO_PLL5G_CFG2_AMPC_SEL(x) (((x) << 16) & GENMASK(23, 16))
-#define HSIO_PLL5G_CFG2_AMPC_SEL_M GENMASK(23, 16)
-#define HSIO_PLL5G_CFG2_AMPC_SEL_X(x) (((x) & GENMASK(23, 16)) >> 16)
-#define HSIO_PLL5G_CFG2_ENA_CLK_BYPASS BIT(15)
-#define HSIO_PLL5G_CFG2_PWD_AMPCTRL_N BIT(14)
-#define HSIO_PLL5G_CFG2_ENA_AMPCTRL BIT(13)
-#define HSIO_PLL5G_CFG2_ENA_AMP_CTRL_FORCE BIT(12)
-#define HSIO_PLL5G_CFG2_FRC_FSM_POR BIT(11)
-#define HSIO_PLL5G_CFG2_DISABLE_FSM_POR BIT(10)
-#define HSIO_PLL5G_CFG2_GAIN_TEST(x) (((x) << 5) & GENMASK(9, 5))
-#define HSIO_PLL5G_CFG2_GAIN_TEST_M GENMASK(9, 5)
-#define HSIO_PLL5G_CFG2_GAIN_TEST_X(x) (((x) & GENMASK(9, 5)) >> 5)
-#define HSIO_PLL5G_CFG2_EN_RESET_OVERRUN BIT(4)
-#define HSIO_PLL5G_CFG2_EN_RESET_LIM_DET BIT(3)
-#define HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET BIT(2)
-#define HSIO_PLL5G_CFG2_DISABLE_FSM BIT(1)
-#define HSIO_PLL5G_CFG2_ENA_GAIN_TEST BIT(0)
-
-#define HSIO_PLL5G_CFG3_TEST_ANA_OUT_SEL(x) (((x) << 22) & GENMASK(23, 22))
-#define HSIO_PLL5G_CFG3_TEST_ANA_OUT_SEL_M GENMASK(23, 22)
-#define HSIO_PLL5G_CFG3_TEST_ANA_OUT_SEL_X(x) (((x) & GENMASK(23, 22)) >> 22)
-#define HSIO_PLL5G_CFG3_TESTOUT_SEL(x) (((x) << 19) & GENMASK(21, 19))
-#define HSIO_PLL5G_CFG3_TESTOUT_SEL_M GENMASK(21, 19)
-#define HSIO_PLL5G_CFG3_TESTOUT_SEL_X(x) (((x) & GENMASK(21, 19)) >> 19)
-#define HSIO_PLL5G_CFG3_ENA_ANA_TEST_OUT BIT(18)
-#define HSIO_PLL5G_CFG3_ENA_TEST_OUT BIT(17)
-#define HSIO_PLL5G_CFG3_SEL_FBDCLK BIT(16)
-#define HSIO_PLL5G_CFG3_SEL_CML_CMOS_PFD BIT(15)
-#define HSIO_PLL5G_CFG3_RST_FB_N BIT(14)
-#define HSIO_PLL5G_CFG3_FORCE_VCO_CONTRH BIT(13)
-#define HSIO_PLL5G_CFG3_FORCE_LO BIT(12)
-#define HSIO_PLL5G_CFG3_FORCE_HI BIT(11)
-#define HSIO_PLL5G_CFG3_FORCE_ENA BIT(10)
-#define HSIO_PLL5G_CFG3_FORCE_CP BIT(9)
-#define HSIO_PLL5G_CFG3_FBDIVSEL_TST_ENA BIT(8)
-#define HSIO_PLL5G_CFG3_FBDIVSEL(x) ((x) & GENMASK(7, 0))
-#define HSIO_PLL5G_CFG3_FBDIVSEL_M GENMASK(7, 0)
-
-#define HSIO_PLL5G_CFG4_IB_BIAS_CTRL(x) (((x) << 16) & GENMASK(23, 16))
-#define HSIO_PLL5G_CFG4_IB_BIAS_CTRL_M GENMASK(23, 16)
-#define HSIO_PLL5G_CFG4_IB_BIAS_CTRL_X(x) (((x) & GENMASK(23, 16)) >> 16)
-#define HSIO_PLL5G_CFG4_IB_CTRL(x) ((x) & GENMASK(15, 0))
-#define HSIO_PLL5G_CFG4_IB_CTRL_M GENMASK(15, 0)
-
-#define HSIO_PLL5G_CFG5_OB_BIAS_CTRL(x) (((x) << 16) & GENMASK(23, 16))
-#define HSIO_PLL5G_CFG5_OB_BIAS_CTRL_M GENMASK(23, 16)
-#define HSIO_PLL5G_CFG5_OB_BIAS_CTRL_X(x) (((x) & GENMASK(23, 16)) >> 16)
-#define HSIO_PLL5G_CFG5_OB_CTRL(x) ((x) & GENMASK(15, 0))
-#define HSIO_PLL5G_CFG5_OB_CTRL_M GENMASK(15, 0)
-
-#define HSIO_PLL5G_CFG6_REFCLK_SEL_SRC BIT(23)
-#define HSIO_PLL5G_CFG6_REFCLK_SEL(x) (((x) << 20) & GENMASK(22, 20))
-#define HSIO_PLL5G_CFG6_REFCLK_SEL_M GENMASK(22, 20)
-#define HSIO_PLL5G_CFG6_REFCLK_SEL_X(x) (((x) & GENMASK(22, 20)) >> 20)
-#define HSIO_PLL5G_CFG6_REFCLK_SRC BIT(19)
-#define HSIO_PLL5G_CFG6_POR_DEL_SEL(x) (((x) << 16) & GENMASK(17, 16))
-#define HSIO_PLL5G_CFG6_POR_DEL_SEL_M GENMASK(17, 16)
-#define HSIO_PLL5G_CFG6_POR_DEL_SEL_X(x) (((x) & GENMASK(17, 16)) >> 16)
-#define HSIO_PLL5G_CFG6_DIV125REF_SEL(x) (((x) << 8) & GENMASK(15, 8))
-#define HSIO_PLL5G_CFG6_DIV125REF_SEL_M GENMASK(15, 8)
-#define HSIO_PLL5G_CFG6_DIV125REF_SEL_X(x) (((x) & GENMASK(15, 8)) >> 8)
-#define HSIO_PLL5G_CFG6_ENA_REFCLKC2 BIT(7)
-#define HSIO_PLL5G_CFG6_ENA_FBCLKC2 BIT(6)
-#define HSIO_PLL5G_CFG6_DDR_CLK_DIV(x) ((x) & GENMASK(5, 0))
-#define HSIO_PLL5G_CFG6_DDR_CLK_DIV_M GENMASK(5, 0)
-
-#define HSIO_PLL5G_STATUS0_RANGE_LIM BIT(12)
-#define HSIO_PLL5G_STATUS0_OUT_OF_RANGE_ERR BIT(11)
-#define HSIO_PLL5G_STATUS0_CALIBRATION_ERR BIT(10)
-#define HSIO_PLL5G_STATUS0_CALIBRATION_DONE BIT(9)
-#define HSIO_PLL5G_STATUS0_READBACK_DATA(x) (((x) << 1) & GENMASK(8, 1))
-#define HSIO_PLL5G_STATUS0_READBACK_DATA_M GENMASK(8, 1)
-#define HSIO_PLL5G_STATUS0_READBACK_DATA_X(x) (((x) & GENMASK(8, 1)) >> 1)
-#define HSIO_PLL5G_STATUS0_LOCK_STATUS BIT(0)
-
-#define HSIO_PLL5G_STATUS1_SIG_DEL(x) (((x) << 21) & GENMASK(28, 21))
-#define HSIO_PLL5G_STATUS1_SIG_DEL_M GENMASK(28, 21)
-#define HSIO_PLL5G_STATUS1_SIG_DEL_X(x) (((x) & GENMASK(28, 21)) >> 21)
-#define HSIO_PLL5G_STATUS1_GAIN_STAT(x) (((x) << 16) & GENMASK(20, 16))
-#define HSIO_PLL5G_STATUS1_GAIN_STAT_M GENMASK(20, 16)
-#define HSIO_PLL5G_STATUS1_GAIN_STAT_X(x) (((x) & GENMASK(20, 16)) >> 16)
-#define HSIO_PLL5G_STATUS1_FBCNT_DIF(x) (((x) << 4) & GENMASK(13, 4))
-#define HSIO_PLL5G_STATUS1_FBCNT_DIF_M GENMASK(13, 4)
-#define HSIO_PLL5G_STATUS1_FBCNT_DIF_X(x) (((x) & GENMASK(13, 4)) >> 4)
-#define HSIO_PLL5G_STATUS1_FSM_STAT(x) (((x) << 1) & GENMASK(3, 1))
-#define HSIO_PLL5G_STATUS1_FSM_STAT_M GENMASK(3, 1)
-#define HSIO_PLL5G_STATUS1_FSM_STAT_X(x) (((x) & GENMASK(3, 1)) >> 1)
-#define HSIO_PLL5G_STATUS1_FSM_LOCK BIT(0)
-
-#define HSIO_PLL5G_BIST_CFG0_PLLB_START_BIST BIT(31)
-#define HSIO_PLL5G_BIST_CFG0_PLLB_MEAS_MODE BIT(30)
-#define HSIO_PLL5G_BIST_CFG0_PLLB_LOCK_REPEAT(x) (((x) << 20) & GENMASK(23, 20))
-#define HSIO_PLL5G_BIST_CFG0_PLLB_LOCK_REPEAT_M GENMASK(23, 20)
-#define HSIO_PLL5G_BIST_CFG0_PLLB_LOCK_REPEAT_X(x) (((x) & GENMASK(23, 20)) >> 20)
-#define HSIO_PLL5G_BIST_CFG0_PLLB_LOCK_UNCERT(x) (((x) << 16) & GENMASK(19, 16))
-#define HSIO_PLL5G_BIST_CFG0_PLLB_LOCK_UNCERT_M GENMASK(19, 16)
-#define HSIO_PLL5G_BIST_CFG0_PLLB_LOCK_UNCERT_X(x) (((x) & GENMASK(19, 16)) >> 16)
-#define HSIO_PLL5G_BIST_CFG0_PLLB_DIV_FACTOR_PRE(x) ((x) & GENMASK(15, 0))
-#define HSIO_PLL5G_BIST_CFG0_PLLB_DIV_FACTOR_PRE_M GENMASK(15, 0)
-
-#define HSIO_PLL5G_BIST_STAT0_PLLB_FSM_STAT(x) (((x) << 4) & GENMASK(7, 4))
-#define HSIO_PLL5G_BIST_STAT0_PLLB_FSM_STAT_M GENMASK(7, 4)
-#define HSIO_PLL5G_BIST_STAT0_PLLB_FSM_STAT_X(x) (((x) & GENMASK(7, 4)) >> 4)
-#define HSIO_PLL5G_BIST_STAT0_PLLB_BUSY BIT(2)
-#define HSIO_PLL5G_BIST_STAT0_PLLB_DONE_N BIT(1)
-#define HSIO_PLL5G_BIST_STAT0_PLLB_FAIL BIT(0)
-
-#define HSIO_PLL5G_BIST_STAT1_PLLB_CNT_OUT(x) (((x) << 16) & GENMASK(31, 16))
-#define HSIO_PLL5G_BIST_STAT1_PLLB_CNT_OUT_M GENMASK(31, 16)
-#define HSIO_PLL5G_BIST_STAT1_PLLB_CNT_OUT_X(x) (((x) & GENMASK(31, 16)) >> 16)
-#define HSIO_PLL5G_BIST_STAT1_PLLB_CNT_REF_DIFF(x) ((x) & GENMASK(15, 0))
-#define HSIO_PLL5G_BIST_STAT1_PLLB_CNT_REF_DIFF_M GENMASK(15, 0)
-
-#define HSIO_RCOMP_CFG0_PWD_ENA BIT(13)
-#define HSIO_RCOMP_CFG0_RUN_CAL BIT(12)
-#define HSIO_RCOMP_CFG0_SPEED_SEL(x) (((x) << 10) & GENMASK(11, 10))
-#define HSIO_RCOMP_CFG0_SPEED_SEL_M GENMASK(11, 10)
-#define HSIO_RCOMP_CFG0_SPEED_SEL_X(x) (((x) & GENMASK(11, 10)) >> 10)
-#define HSIO_RCOMP_CFG0_MODE_SEL(x) (((x) << 8) & GENMASK(9, 8))
-#define HSIO_RCOMP_CFG0_MODE_SEL_M GENMASK(9, 8)
-#define HSIO_RCOMP_CFG0_MODE_SEL_X(x) (((x) & GENMASK(9, 8)) >> 8)
-#define HSIO_RCOMP_CFG0_FORCE_ENA BIT(4)
-#define HSIO_RCOMP_CFG0_RCOMP_VAL(x) ((x) & GENMASK(3, 0))
-#define HSIO_RCOMP_CFG0_RCOMP_VAL_M GENMASK(3, 0)
-
-#define HSIO_RCOMP_STATUS_BUSY BIT(12)
-#define HSIO_RCOMP_STATUS_DELTA_ALERT BIT(7)
-#define HSIO_RCOMP_STATUS_RCOMP(x) ((x) & GENMASK(3, 0))
-#define HSIO_RCOMP_STATUS_RCOMP_M GENMASK(3, 0)
-
-#define HSIO_SYNC_ETH_CFG_RSZ 0x4
-
-#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_SRC(x) (((x) << 4) & GENMASK(7, 4))
-#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_SRC_M GENMASK(7, 4)
-#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_SRC_X(x) (((x) & GENMASK(7, 4)) >> 4)
-#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_DIV(x) (((x) << 1) & GENMASK(3, 1))
-#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_DIV_M GENMASK(3, 1)
-#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_DIV_X(x) (((x) & GENMASK(3, 1)) >> 1)
-#define HSIO_SYNC_ETH_CFG_RECO_CLK_ENA BIT(0)
-
-#define HSIO_SYNC_ETH_PLL_CFG_PLL_AUTO_SQUELCH_ENA BIT(0)
-
-#define HSIO_S1G_DES_CFG_DES_PHS_CTRL(x) (((x) << 13) & GENMASK(16, 13))
-#define HSIO_S1G_DES_CFG_DES_PHS_CTRL_M GENMASK(16, 13)
-#define HSIO_S1G_DES_CFG_DES_PHS_CTRL_X(x) (((x) & GENMASK(16, 13)) >> 13)
-#define HSIO_S1G_DES_CFG_DES_CPMD_SEL(x) (((x) << 11) & GENMASK(12, 11))
-#define HSIO_S1G_DES_CFG_DES_CPMD_SEL_M GENMASK(12, 11)
-#define HSIO_S1G_DES_CFG_DES_CPMD_SEL_X(x) (((x) & GENMASK(12, 11)) >> 11)
-#define HSIO_S1G_DES_CFG_DES_MBTR_CTRL(x) (((x) << 8) & GENMASK(10, 8))
-#define HSIO_S1G_DES_CFG_DES_MBTR_CTRL_M GENMASK(10, 8)
-#define HSIO_S1G_DES_CFG_DES_MBTR_CTRL_X(x) (((x) & GENMASK(10, 8)) >> 8)
-#define HSIO_S1G_DES_CFG_DES_BW_ANA(x) (((x) << 5) & GENMASK(7, 5))
-#define HSIO_S1G_DES_CFG_DES_BW_ANA_M GENMASK(7, 5)
-#define HSIO_S1G_DES_CFG_DES_BW_ANA_X(x) (((x) & GENMASK(7, 5)) >> 5)
-#define HSIO_S1G_DES_CFG_DES_SWAP_ANA BIT(4)
-#define HSIO_S1G_DES_CFG_DES_BW_HYST(x) (((x) << 1) & GENMASK(3, 1))
-#define HSIO_S1G_DES_CFG_DES_BW_HYST_M GENMASK(3, 1)
-#define HSIO_S1G_DES_CFG_DES_BW_HYST_X(x) (((x) & GENMASK(3, 1)) >> 1)
-#define HSIO_S1G_DES_CFG_DES_SWAP_HYST BIT(0)
-
-#define HSIO_S1G_IB_CFG_IB_FX100_ENA BIT(27)
-#define HSIO_S1G_IB_CFG_ACJTAG_HYST(x) (((x) << 24) & GENMASK(26, 24))
-#define HSIO_S1G_IB_CFG_ACJTAG_HYST_M GENMASK(26, 24)
-#define HSIO_S1G_IB_CFG_ACJTAG_HYST_X(x) (((x) & GENMASK(26, 24)) >> 24)
-#define HSIO_S1G_IB_CFG_IB_DET_LEV(x) (((x) << 19) & GENMASK(21, 19))
-#define HSIO_S1G_IB_CFG_IB_DET_LEV_M GENMASK(21, 19)
-#define HSIO_S1G_IB_CFG_IB_DET_LEV_X(x) (((x) & GENMASK(21, 19)) >> 19)
-#define HSIO_S1G_IB_CFG_IB_HYST_LEV BIT(14)
-#define HSIO_S1G_IB_CFG_IB_ENA_CMV_TERM BIT(13)
-#define HSIO_S1G_IB_CFG_IB_ENA_DC_COUPLING BIT(12)
-#define HSIO_S1G_IB_CFG_IB_ENA_DETLEV BIT(11)
-#define HSIO_S1G_IB_CFG_IB_ENA_HYST BIT(10)
-#define HSIO_S1G_IB_CFG_IB_ENA_OFFSET_COMP BIT(9)
-#define HSIO_S1G_IB_CFG_IB_EQ_GAIN(x) (((x) << 6) & GENMASK(8, 6))
-#define HSIO_S1G_IB_CFG_IB_EQ_GAIN_M GENMASK(8, 6)
-#define HSIO_S1G_IB_CFG_IB_EQ_GAIN_X(x) (((x) & GENMASK(8, 6)) >> 6)
-#define HSIO_S1G_IB_CFG_IB_SEL_CORNER_FREQ(x) (((x) << 4) & GENMASK(5, 4))
-#define HSIO_S1G_IB_CFG_IB_SEL_CORNER_FREQ_M GENMASK(5, 4)
-#define HSIO_S1G_IB_CFG_IB_SEL_CORNER_FREQ_X(x) (((x) & GENMASK(5, 4)) >> 4)
-#define HSIO_S1G_IB_CFG_IB_RESISTOR_CTRL(x) ((x) & GENMASK(3, 0))
-#define HSIO_S1G_IB_CFG_IB_RESISTOR_CTRL_M GENMASK(3, 0)
-
-#define HSIO_S1G_OB_CFG_OB_SLP(x) (((x) << 17) & GENMASK(18, 17))
-#define HSIO_S1G_OB_CFG_OB_SLP_M GENMASK(18, 17)
-#define HSIO_S1G_OB_CFG_OB_SLP_X(x) (((x) & GENMASK(18, 17)) >> 17)
-#define HSIO_S1G_OB_CFG_OB_AMP_CTRL(x) (((x) << 13) & GENMASK(16, 13))
-#define HSIO_S1G_OB_CFG_OB_AMP_CTRL_M GENMASK(16, 13)
-#define HSIO_S1G_OB_CFG_OB_AMP_CTRL_X(x) (((x) & GENMASK(16, 13)) >> 13)
-#define HSIO_S1G_OB_CFG_OB_CMM_BIAS_CTRL(x) (((x) << 10) & GENMASK(12, 10))
-#define HSIO_S1G_OB_CFG_OB_CMM_BIAS_CTRL_M GENMASK(12, 10)
-#define HSIO_S1G_OB_CFG_OB_CMM_BIAS_CTRL_X(x) (((x) & GENMASK(12, 10)) >> 10)
-#define HSIO_S1G_OB_CFG_OB_DIS_VCM_CTRL BIT(9)
-#define HSIO_S1G_OB_CFG_OB_EN_MEAS_VREG BIT(8)
-#define HSIO_S1G_OB_CFG_OB_VCM_CTRL(x) (((x) << 4) & GENMASK(7, 4))
-#define HSIO_S1G_OB_CFG_OB_VCM_CTRL_M GENMASK(7, 4)
-#define HSIO_S1G_OB_CFG_OB_VCM_CTRL_X(x) (((x) & GENMASK(7, 4)) >> 4)
-#define HSIO_S1G_OB_CFG_OB_RESISTOR_CTRL(x) ((x) & GENMASK(3, 0))
-#define HSIO_S1G_OB_CFG_OB_RESISTOR_CTRL_M GENMASK(3, 0)
-
-#define HSIO_S1G_SER_CFG_SER_IDLE BIT(9)
-#define HSIO_S1G_SER_CFG_SER_DEEMPH BIT(8)
-#define HSIO_S1G_SER_CFG_SER_CPMD_SEL BIT(7)
-#define HSIO_S1G_SER_CFG_SER_SWAP_CPMD BIT(6)
-#define HSIO_S1G_SER_CFG_SER_ALISEL(x) (((x) << 4) & GENMASK(5, 4))
-#define HSIO_S1G_SER_CFG_SER_ALISEL_M GENMASK(5, 4)
-#define HSIO_S1G_SER_CFG_SER_ALISEL_X(x) (((x) & GENMASK(5, 4)) >> 4)
-#define HSIO_S1G_SER_CFG_SER_ENHYS BIT(3)
-#define HSIO_S1G_SER_CFG_SER_BIG_WIN BIT(2)
-#define HSIO_S1G_SER_CFG_SER_EN_WIN BIT(1)
-#define HSIO_S1G_SER_CFG_SER_ENALI BIT(0)
-
-#define HSIO_S1G_COMMON_CFG_SYS_RST BIT(31)
-#define HSIO_S1G_COMMON_CFG_SE_AUTO_SQUELCH_ENA BIT(21)
-#define HSIO_S1G_COMMON_CFG_ENA_LANE BIT(18)
-#define HSIO_S1G_COMMON_CFG_PWD_RX BIT(17)
-#define HSIO_S1G_COMMON_CFG_PWD_TX BIT(16)
-#define HSIO_S1G_COMMON_CFG_LANE_CTRL(x) (((x) << 13) & GENMASK(15, 13))
-#define HSIO_S1G_COMMON_CFG_LANE_CTRL_M GENMASK(15, 13)
-#define HSIO_S1G_COMMON_CFG_LANE_CTRL_X(x) (((x) & GENMASK(15, 13)) >> 13)
-#define HSIO_S1G_COMMON_CFG_ENA_DIRECT BIT(12)
-#define HSIO_S1G_COMMON_CFG_ENA_ELOOP BIT(11)
-#define HSIO_S1G_COMMON_CFG_ENA_FLOOP BIT(10)
-#define HSIO_S1G_COMMON_CFG_ENA_ILOOP BIT(9)
-#define HSIO_S1G_COMMON_CFG_ENA_PLOOP BIT(8)
-#define HSIO_S1G_COMMON_CFG_HRATE BIT(7)
-#define HSIO_S1G_COMMON_CFG_IF_MODE BIT(0)
-
-#define HSIO_S1G_PLL_CFG_PLL_ENA_FB_DIV2 BIT(22)
-#define HSIO_S1G_PLL_CFG_PLL_ENA_RC_DIV2 BIT(21)
-#define HSIO_S1G_PLL_CFG_PLL_FSM_CTRL_DATA(x) (((x) << 8) & GENMASK(15, 8))
-#define HSIO_S1G_PLL_CFG_PLL_FSM_CTRL_DATA_M GENMASK(15, 8)
-#define HSIO_S1G_PLL_CFG_PLL_FSM_CTRL_DATA_X(x) (((x) & GENMASK(15, 8)) >> 8)
-#define HSIO_S1G_PLL_CFG_PLL_FSM_ENA BIT(7)
-#define HSIO_S1G_PLL_CFG_PLL_FSM_FORCE_SET_ENA BIT(6)
-#define HSIO_S1G_PLL_CFG_PLL_FSM_OOR_RECAL_ENA BIT(5)
-#define HSIO_S1G_PLL_CFG_PLL_RB_DATA_SEL BIT(3)
-
-#define HSIO_S1G_PLL_STATUS_PLL_CAL_NOT_DONE BIT(12)
-#define HSIO_S1G_PLL_STATUS_PLL_CAL_ERR BIT(11)
-#define HSIO_S1G_PLL_STATUS_PLL_OUT_OF_RANGE_ERR BIT(10)
-#define HSIO_S1G_PLL_STATUS_PLL_RB_DATA(x) ((x) & GENMASK(7, 0))
-#define HSIO_S1G_PLL_STATUS_PLL_RB_DATA_M GENMASK(7, 0)
-
-#define HSIO_S1G_DFT_CFG0_LAZYBIT BIT(31)
-#define HSIO_S1G_DFT_CFG0_INV_DIS BIT(23)
-#define HSIO_S1G_DFT_CFG0_PRBS_SEL(x) (((x) << 20) & GENMASK(21, 20))
-#define HSIO_S1G_DFT_CFG0_PRBS_SEL_M GENMASK(21, 20)
-#define HSIO_S1G_DFT_CFG0_PRBS_SEL_X(x) (((x) & GENMASK(21, 20)) >> 20)
-#define HSIO_S1G_DFT_CFG0_TEST_MODE(x) (((x) << 16) & GENMASK(18, 16))
-#define HSIO_S1G_DFT_CFG0_TEST_MODE_M GENMASK(18, 16)
-#define HSIO_S1G_DFT_CFG0_TEST_MODE_X(x) (((x) & GENMASK(18, 16)) >> 16)
-#define HSIO_S1G_DFT_CFG0_RX_PHS_CORR_DIS BIT(4)
-#define HSIO_S1G_DFT_CFG0_RX_PDSENS_ENA BIT(3)
-#define HSIO_S1G_DFT_CFG0_RX_DFT_ENA BIT(2)
-#define HSIO_S1G_DFT_CFG0_TX_DFT_ENA BIT(0)
-
-#define HSIO_S1G_DFT_CFG1_TX_JITTER_AMPL(x) (((x) << 8) & GENMASK(17, 8))
-#define HSIO_S1G_DFT_CFG1_TX_JITTER_AMPL_M GENMASK(17, 8)
-#define HSIO_S1G_DFT_CFG1_TX_JITTER_AMPL_X(x) (((x) & GENMASK(17, 8)) >> 8)
-#define HSIO_S1G_DFT_CFG1_TX_STEP_FREQ(x) (((x) << 4) & GENMASK(7, 4))
-#define HSIO_S1G_DFT_CFG1_TX_STEP_FREQ_M GENMASK(7, 4)
-#define HSIO_S1G_DFT_CFG1_TX_STEP_FREQ_X(x) (((x) & GENMASK(7, 4)) >> 4)
-#define HSIO_S1G_DFT_CFG1_TX_JI_ENA BIT(3)
-#define HSIO_S1G_DFT_CFG1_TX_WAVEFORM_SEL BIT(2)
-#define HSIO_S1G_DFT_CFG1_TX_FREQOFF_DIR BIT(1)
-#define HSIO_S1G_DFT_CFG1_TX_FREQOFF_ENA BIT(0)
-
-#define HSIO_S1G_DFT_CFG2_RX_JITTER_AMPL(x) (((x) << 8) & GENMASK(17, 8))
-#define HSIO_S1G_DFT_CFG2_RX_JITTER_AMPL_M GENMASK(17, 8)
-#define HSIO_S1G_DFT_CFG2_RX_JITTER_AMPL_X(x) (((x) & GENMASK(17, 8)) >> 8)
-#define HSIO_S1G_DFT_CFG2_RX_STEP_FREQ(x) (((x) << 4) & GENMASK(7, 4))
-#define HSIO_S1G_DFT_CFG2_RX_STEP_FREQ_M GENMASK(7, 4)
-#define HSIO_S1G_DFT_CFG2_RX_STEP_FREQ_X(x) (((x) & GENMASK(7, 4)) >> 4)
-#define HSIO_S1G_DFT_CFG2_RX_JI_ENA BIT(3)
-#define HSIO_S1G_DFT_CFG2_RX_WAVEFORM_SEL BIT(2)
-#define HSIO_S1G_DFT_CFG2_RX_FREQOFF_DIR BIT(1)
-#define HSIO_S1G_DFT_CFG2_RX_FREQOFF_ENA BIT(0)
-
-#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_ENA BIT(20)
-#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_FBS_HIGH(x) (((x) << 16) & GENMASK(17, 16))
-#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_FBS_HIGH_M GENMASK(17, 16)
-#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_FBS_HIGH_X(x) (((x) & GENMASK(17, 16)) >> 16)
-#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_HIGH(x) (((x) << 8) & GENMASK(15, 8))
-#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_HIGH_M GENMASK(15, 8)
-#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_HIGH_X(x) (((x) & GENMASK(15, 8)) >> 8)
-#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_LOW(x) ((x) & GENMASK(7, 0))
-#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_LOW_M GENMASK(7, 0)
-
-#define HSIO_S1G_MISC_CFG_DES_100FX_KICK_MODE(x) (((x) << 11) & GENMASK(12, 11))
-#define HSIO_S1G_MISC_CFG_DES_100FX_KICK_MODE_M GENMASK(12, 11)
-#define HSIO_S1G_MISC_CFG_DES_100FX_KICK_MODE_X(x) (((x) & GENMASK(12, 11)) >> 11)
-#define HSIO_S1G_MISC_CFG_DES_100FX_CPMD_SWAP BIT(10)
-#define HSIO_S1G_MISC_CFG_DES_100FX_CPMD_MODE BIT(9)
-#define HSIO_S1G_MISC_CFG_DES_100FX_CPMD_ENA BIT(8)
-#define HSIO_S1G_MISC_CFG_RX_LPI_MODE_ENA BIT(5)
-#define HSIO_S1G_MISC_CFG_TX_LPI_MODE_ENA BIT(4)
-#define HSIO_S1G_MISC_CFG_RX_DATA_INV_ENA BIT(3)
-#define HSIO_S1G_MISC_CFG_TX_DATA_INV_ENA BIT(2)
-#define HSIO_S1G_MISC_CFG_LANE_RST BIT(0)
-
-#define HSIO_S1G_DFT_STATUS_PLL_BIST_NOT_DONE BIT(7)
-#define HSIO_S1G_DFT_STATUS_PLL_BIST_FAILED BIT(6)
-#define HSIO_S1G_DFT_STATUS_PLL_BIST_TIMEOUT_ERR BIT(5)
-#define HSIO_S1G_DFT_STATUS_BIST_ACTIVE BIT(3)
-#define HSIO_S1G_DFT_STATUS_BIST_NOSYNC BIT(2)
-#define HSIO_S1G_DFT_STATUS_BIST_COMPLETE_N BIT(1)
-#define HSIO_S1G_DFT_STATUS_BIST_ERROR BIT(0)
-
-#define HSIO_S1G_MISC_STATUS_DES_100FX_PHASE_SEL BIT(0)
-
-#define HSIO_MCB_S1G_ADDR_CFG_SERDES1G_WR_ONE_SHOT BIT(31)
-#define HSIO_MCB_S1G_ADDR_CFG_SERDES1G_RD_ONE_SHOT BIT(30)
-#define HSIO_MCB_S1G_ADDR_CFG_SERDES1G_ADDR(x) ((x) & GENMASK(8, 0))
-#define HSIO_MCB_S1G_ADDR_CFG_SERDES1G_ADDR_M GENMASK(8, 0)
-
-#define HSIO_S6G_DIG_CFG_GP(x) (((x) << 16) & GENMASK(18, 16))
-#define HSIO_S6G_DIG_CFG_GP_M GENMASK(18, 16)
-#define HSIO_S6G_DIG_CFG_GP_X(x) (((x) & GENMASK(18, 16)) >> 16)
-#define HSIO_S6G_DIG_CFG_TX_BIT_DOUBLING_MODE_ENA BIT(7)
-#define HSIO_S6G_DIG_CFG_SIGDET_TESTMODE BIT(6)
-#define HSIO_S6G_DIG_CFG_SIGDET_AST(x) (((x) << 3) & GENMASK(5, 3))
-#define HSIO_S6G_DIG_CFG_SIGDET_AST_M GENMASK(5, 3)
-#define HSIO_S6G_DIG_CFG_SIGDET_AST_X(x) (((x) & GENMASK(5, 3)) >> 3)
-#define HSIO_S6G_DIG_CFG_SIGDET_DST(x) ((x) & GENMASK(2, 0))
-#define HSIO_S6G_DIG_CFG_SIGDET_DST_M GENMASK(2, 0)
-
-#define HSIO_S6G_DFT_CFG0_LAZYBIT BIT(31)
-#define HSIO_S6G_DFT_CFG0_INV_DIS BIT(23)
-#define HSIO_S6G_DFT_CFG0_PRBS_SEL(x) (((x) << 20) & GENMASK(21, 20))
-#define HSIO_S6G_DFT_CFG0_PRBS_SEL_M GENMASK(21, 20)
-#define HSIO_S6G_DFT_CFG0_PRBS_SEL_X(x) (((x) & GENMASK(21, 20)) >> 20)
-#define HSIO_S6G_DFT_CFG0_TEST_MODE(x) (((x) << 16) & GENMASK(18, 16))
-#define HSIO_S6G_DFT_CFG0_TEST_MODE_M GENMASK(18, 16)
-#define HSIO_S6G_DFT_CFG0_TEST_MODE_X(x) (((x) & GENMASK(18, 16)) >> 16)
-#define HSIO_S6G_DFT_CFG0_RX_PHS_CORR_DIS BIT(4)
-#define HSIO_S6G_DFT_CFG0_RX_PDSENS_ENA BIT(3)
-#define HSIO_S6G_DFT_CFG0_RX_DFT_ENA BIT(2)
-#define HSIO_S6G_DFT_CFG0_TX_DFT_ENA BIT(0)
-
-#define HSIO_S6G_DFT_CFG1_TX_JITTER_AMPL(x) (((x) << 8) & GENMASK(17, 8))
-#define HSIO_S6G_DFT_CFG1_TX_JITTER_AMPL_M GENMASK(17, 8)
-#define HSIO_S6G_DFT_CFG1_TX_JITTER_AMPL_X(x) (((x) & GENMASK(17, 8)) >> 8)
-#define HSIO_S6G_DFT_CFG1_TX_STEP_FREQ(x) (((x) << 4) & GENMASK(7, 4))
-#define HSIO_S6G_DFT_CFG1_TX_STEP_FREQ_M GENMASK(7, 4)
-#define HSIO_S6G_DFT_CFG1_TX_STEP_FREQ_X(x) (((x) & GENMASK(7, 4)) >> 4)
-#define HSIO_S6G_DFT_CFG1_TX_JI_ENA BIT(3)
-#define HSIO_S6G_DFT_CFG1_TX_WAVEFORM_SEL BIT(2)
-#define HSIO_S6G_DFT_CFG1_TX_FREQOFF_DIR BIT(1)
-#define HSIO_S6G_DFT_CFG1_TX_FREQOFF_ENA BIT(0)
-
-#define HSIO_S6G_DFT_CFG2_RX_JITTER_AMPL(x) (((x) << 8) & GENMASK(17, 8))
-#define HSIO_S6G_DFT_CFG2_RX_JITTER_AMPL_M GENMASK(17, 8)
-#define HSIO_S6G_DFT_CFG2_RX_JITTER_AMPL_X(x) (((x) & GENMASK(17, 8)) >> 8)
-#define HSIO_S6G_DFT_CFG2_RX_STEP_FREQ(x) (((x) << 4) & GENMASK(7, 4))
-#define HSIO_S6G_DFT_CFG2_RX_STEP_FREQ_M GENMASK(7, 4)
-#define HSIO_S6G_DFT_CFG2_RX_STEP_FREQ_X(x) (((x) & GENMASK(7, 4)) >> 4)
-#define HSIO_S6G_DFT_CFG2_RX_JI_ENA BIT(3)
-#define HSIO_S6G_DFT_CFG2_RX_WAVEFORM_SEL BIT(2)
-#define HSIO_S6G_DFT_CFG2_RX_FREQOFF_DIR BIT(1)
-#define HSIO_S6G_DFT_CFG2_RX_FREQOFF_ENA BIT(0)
-
-#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_ENA BIT(20)
-#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_FBS_HIGH(x) (((x) << 16) & GENMASK(19, 16))
-#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_FBS_HIGH_M GENMASK(19, 16)
-#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_FBS_HIGH_X(x) (((x) & GENMASK(19, 16)) >> 16)
-#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_HIGH(x) (((x) << 8) & GENMASK(15, 8))
-#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_HIGH_M GENMASK(15, 8)
-#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_HIGH_X(x) (((x) & GENMASK(15, 8)) >> 8)
-#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_LOW(x) ((x) & GENMASK(7, 0))
-#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_LOW_M GENMASK(7, 0)
-
-#define HSIO_S6G_MISC_CFG_SEL_RECO_CLK(x) (((x) << 13) & GENMASK(14, 13))
-#define HSIO_S6G_MISC_CFG_SEL_RECO_CLK_M GENMASK(14, 13)
-#define HSIO_S6G_MISC_CFG_SEL_RECO_CLK_X(x) (((x) & GENMASK(14, 13)) >> 13)
-#define HSIO_S6G_MISC_CFG_DES_100FX_KICK_MODE(x) (((x) << 11) & GENMASK(12, 11))
-#define HSIO_S6G_MISC_CFG_DES_100FX_KICK_MODE_M GENMASK(12, 11)
-#define HSIO_S6G_MISC_CFG_DES_100FX_KICK_MODE_X(x) (((x) & GENMASK(12, 11)) >> 11)
-#define HSIO_S6G_MISC_CFG_DES_100FX_CPMD_SWAP BIT(10)
-#define HSIO_S6G_MISC_CFG_DES_100FX_CPMD_MODE BIT(9)
-#define HSIO_S6G_MISC_CFG_DES_100FX_CPMD_ENA BIT(8)
-#define HSIO_S6G_MISC_CFG_RX_BUS_FLIP_ENA BIT(7)
-#define HSIO_S6G_MISC_CFG_TX_BUS_FLIP_ENA BIT(6)
-#define HSIO_S6G_MISC_CFG_RX_LPI_MODE_ENA BIT(5)
-#define HSIO_S6G_MISC_CFG_TX_LPI_MODE_ENA BIT(4)
-#define HSIO_S6G_MISC_CFG_RX_DATA_INV_ENA BIT(3)
-#define HSIO_S6G_MISC_CFG_TX_DATA_INV_ENA BIT(2)
-#define HSIO_S6G_MISC_CFG_LANE_RST BIT(0)
-
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_POST0(x) (((x) << 23) & GENMASK(28, 23))
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_POST0_M GENMASK(28, 23)
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_POST0_X(x) (((x) & GENMASK(28, 23)) >> 23)
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_POST1(x) (((x) << 18) & GENMASK(22, 18))
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_POST1_M GENMASK(22, 18)
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_POST1_X(x) (((x) & GENMASK(22, 18)) >> 18)
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_PREC(x) (((x) << 13) & GENMASK(17, 13))
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_PREC_M GENMASK(17, 13)
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_PREC_X(x) (((x) & GENMASK(17, 13)) >> 13)
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_ENA_CAS(x) (((x) << 6) & GENMASK(8, 6))
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_ENA_CAS_M GENMASK(8, 6)
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_ENA_CAS_X(x) (((x) & GENMASK(8, 6)) >> 6)
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_LEV(x) ((x) & GENMASK(5, 0))
-#define HSIO_S6G_OB_ANEG_CFG_AN_OB_LEV_M GENMASK(5, 0)
-
-#define HSIO_S6G_DFT_STATUS_PRBS_SYNC_STAT BIT(8)
-#define HSIO_S6G_DFT_STATUS_PLL_BIST_NOT_DONE BIT(7)
-#define HSIO_S6G_DFT_STATUS_PLL_BIST_FAILED BIT(6)
-#define HSIO_S6G_DFT_STATUS_PLL_BIST_TIMEOUT_ERR BIT(5)
-#define HSIO_S6G_DFT_STATUS_BIST_ACTIVE BIT(3)
-#define HSIO_S6G_DFT_STATUS_BIST_NOSYNC BIT(2)
-#define HSIO_S6G_DFT_STATUS_BIST_COMPLETE_N BIT(1)
-#define HSIO_S6G_DFT_STATUS_BIST_ERROR BIT(0)
-
-#define HSIO_S6G_MISC_STATUS_DES_100FX_PHASE_SEL BIT(0)
-
-#define HSIO_S6G_DES_CFG_DES_PHS_CTRL(x) (((x) << 13) & GENMASK(16, 13))
-#define HSIO_S6G_DES_CFG_DES_PHS_CTRL_M GENMASK(16, 13)
-#define HSIO_S6G_DES_CFG_DES_PHS_CTRL_X(x) (((x) & GENMASK(16, 13)) >> 13)
-#define HSIO_S6G_DES_CFG_DES_MBTR_CTRL(x) (((x) << 10) & GENMASK(12, 10))
-#define HSIO_S6G_DES_CFG_DES_MBTR_CTRL_M GENMASK(12, 10)
-#define HSIO_S6G_DES_CFG_DES_MBTR_CTRL_X(x) (((x) & GENMASK(12, 10)) >> 10)
-#define HSIO_S6G_DES_CFG_DES_CPMD_SEL(x) (((x) << 8) & GENMASK(9, 8))
-#define HSIO_S6G_DES_CFG_DES_CPMD_SEL_M GENMASK(9, 8)
-#define HSIO_S6G_DES_CFG_DES_CPMD_SEL_X(x) (((x) & GENMASK(9, 8)) >> 8)
-#define HSIO_S6G_DES_CFG_DES_BW_HYST(x) (((x) << 5) & GENMASK(7, 5))
-#define HSIO_S6G_DES_CFG_DES_BW_HYST_M GENMASK(7, 5)
-#define HSIO_S6G_DES_CFG_DES_BW_HYST_X(x) (((x) & GENMASK(7, 5)) >> 5)
-#define HSIO_S6G_DES_CFG_DES_SWAP_HYST BIT(4)
-#define HSIO_S6G_DES_CFG_DES_BW_ANA(x) (((x) << 1) & GENMASK(3, 1))
-#define HSIO_S6G_DES_CFG_DES_BW_ANA_M GENMASK(3, 1)
-#define HSIO_S6G_DES_CFG_DES_BW_ANA_X(x) (((x) & GENMASK(3, 1)) >> 1)
-#define HSIO_S6G_DES_CFG_DES_SWAP_ANA BIT(0)
-
-#define HSIO_S6G_IB_CFG_IB_SOFSI(x) (((x) << 29) & GENMASK(30, 29))
-#define HSIO_S6G_IB_CFG_IB_SOFSI_M GENMASK(30, 29)
-#define HSIO_S6G_IB_CFG_IB_SOFSI_X(x) (((x) & GENMASK(30, 29)) >> 29)
-#define HSIO_S6G_IB_CFG_IB_VBULK_SEL BIT(28)
-#define HSIO_S6G_IB_CFG_IB_RTRM_ADJ(x) (((x) << 24) & GENMASK(27, 24))
-#define HSIO_S6G_IB_CFG_IB_RTRM_ADJ_M GENMASK(27, 24)
-#define HSIO_S6G_IB_CFG_IB_RTRM_ADJ_X(x) (((x) & GENMASK(27, 24)) >> 24)
-#define HSIO_S6G_IB_CFG_IB_ICML_ADJ(x) (((x) << 20) & GENMASK(23, 20))
-#define HSIO_S6G_IB_CFG_IB_ICML_ADJ_M GENMASK(23, 20)
-#define HSIO_S6G_IB_CFG_IB_ICML_ADJ_X(x) (((x) & GENMASK(23, 20)) >> 20)
-#define HSIO_S6G_IB_CFG_IB_TERM_MODE_SEL(x) (((x) << 18) & GENMASK(19, 18))
-#define HSIO_S6G_IB_CFG_IB_TERM_MODE_SEL_M GENMASK(19, 18)
-#define HSIO_S6G_IB_CFG_IB_TERM_MODE_SEL_X(x) (((x) & GENMASK(19, 18)) >> 18)
-#define HSIO_S6G_IB_CFG_IB_SIG_DET_CLK_SEL(x) (((x) << 15) & GENMASK(17, 15))
-#define HSIO_S6G_IB_CFG_IB_SIG_DET_CLK_SEL_M GENMASK(17, 15)
-#define HSIO_S6G_IB_CFG_IB_SIG_DET_CLK_SEL_X(x) (((x) & GENMASK(17, 15)) >> 15)
-#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_HP(x) (((x) << 13) & GENMASK(14, 13))
-#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_HP_M GENMASK(14, 13)
-#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_HP_X(x) (((x) & GENMASK(14, 13)) >> 13)
-#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_MID(x) (((x) << 11) & GENMASK(12, 11))
-#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_MID_M GENMASK(12, 11)
-#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_MID_X(x) (((x) & GENMASK(12, 11)) >> 11)
-#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_LP(x) (((x) << 9) & GENMASK(10, 9))
-#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_LP_M GENMASK(10, 9)
-#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_LP_X(x) (((x) & GENMASK(10, 9)) >> 9)
-#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_OFFSET(x) (((x) << 7) & GENMASK(8, 7))
-#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_OFFSET_M GENMASK(8, 7)
-#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_OFFSET_X(x) (((x) & GENMASK(8, 7)) >> 7)
-#define HSIO_S6G_IB_CFG_IB_ANA_TEST_ENA BIT(6)
-#define HSIO_S6G_IB_CFG_IB_SIG_DET_ENA BIT(5)
-#define HSIO_S6G_IB_CFG_IB_CONCUR BIT(4)
-#define HSIO_S6G_IB_CFG_IB_CAL_ENA BIT(3)
-#define HSIO_S6G_IB_CFG_IB_SAM_ENA BIT(2)
-#define HSIO_S6G_IB_CFG_IB_EQZ_ENA BIT(1)
-#define HSIO_S6G_IB_CFG_IB_REG_ENA BIT(0)
-
-#define HSIO_S6G_IB_CFG1_IB_TJTAG(x) (((x) << 17) & GENMASK(21, 17))
-#define HSIO_S6G_IB_CFG1_IB_TJTAG_M GENMASK(21, 17)
-#define HSIO_S6G_IB_CFG1_IB_TJTAG_X(x) (((x) & GENMASK(21, 17)) >> 17)
-#define HSIO_S6G_IB_CFG1_IB_TSDET(x) (((x) << 12) & GENMASK(16, 12))
-#define HSIO_S6G_IB_CFG1_IB_TSDET_M GENMASK(16, 12)
-#define HSIO_S6G_IB_CFG1_IB_TSDET_X(x) (((x) & GENMASK(16, 12)) >> 12)
-#define HSIO_S6G_IB_CFG1_IB_SCALY(x) (((x) << 8) & GENMASK(11, 8))
-#define HSIO_S6G_IB_CFG1_IB_SCALY_M GENMASK(11, 8)
-#define HSIO_S6G_IB_CFG1_IB_SCALY_X(x) (((x) & GENMASK(11, 8)) >> 8)
-#define HSIO_S6G_IB_CFG1_IB_FILT_HP BIT(7)
-#define HSIO_S6G_IB_CFG1_IB_FILT_MID BIT(6)
-#define HSIO_S6G_IB_CFG1_IB_FILT_LP BIT(5)
-#define HSIO_S6G_IB_CFG1_IB_FILT_OFFSET BIT(4)
-#define HSIO_S6G_IB_CFG1_IB_FRC_HP BIT(3)
-#define HSIO_S6G_IB_CFG1_IB_FRC_MID BIT(2)
-#define HSIO_S6G_IB_CFG1_IB_FRC_LP BIT(1)
-#define HSIO_S6G_IB_CFG1_IB_FRC_OFFSET BIT(0)
-
-#define HSIO_S6G_IB_CFG2_IB_TINFV(x) (((x) << 27) & GENMASK(29, 27))
-#define HSIO_S6G_IB_CFG2_IB_TINFV_M GENMASK(29, 27)
-#define HSIO_S6G_IB_CFG2_IB_TINFV_X(x) (((x) & GENMASK(29, 27)) >> 27)
-#define HSIO_S6G_IB_CFG2_IB_OINFI(x) (((x) << 22) & GENMASK(26, 22))
-#define HSIO_S6G_IB_CFG2_IB_OINFI_M GENMASK(26, 22)
-#define HSIO_S6G_IB_CFG2_IB_OINFI_X(x) (((x) & GENMASK(26, 22)) >> 22)
-#define HSIO_S6G_IB_CFG2_IB_TAUX(x) (((x) << 19) & GENMASK(21, 19))
-#define HSIO_S6G_IB_CFG2_IB_TAUX_M GENMASK(21, 19)
-#define HSIO_S6G_IB_CFG2_IB_TAUX_X(x) (((x) & GENMASK(21, 19)) >> 19)
-#define HSIO_S6G_IB_CFG2_IB_OINFS(x) (((x) << 16) & GENMASK(18, 16))
-#define HSIO_S6G_IB_CFG2_IB_OINFS_M GENMASK(18, 16)
-#define HSIO_S6G_IB_CFG2_IB_OINFS_X(x) (((x) & GENMASK(18, 16)) >> 16)
-#define HSIO_S6G_IB_CFG2_IB_OCALS(x) (((x) << 10) & GENMASK(15, 10))
-#define HSIO_S6G_IB_CFG2_IB_OCALS_M GENMASK(15, 10)
-#define HSIO_S6G_IB_CFG2_IB_OCALS_X(x) (((x) & GENMASK(15, 10)) >> 10)
-#define HSIO_S6G_IB_CFG2_IB_TCALV(x) (((x) << 5) & GENMASK(9, 5))
-#define HSIO_S6G_IB_CFG2_IB_TCALV_M GENMASK(9, 5)
-#define HSIO_S6G_IB_CFG2_IB_TCALV_X(x) (((x) & GENMASK(9, 5)) >> 5)
-#define HSIO_S6G_IB_CFG2_IB_UMAX(x) (((x) << 3) & GENMASK(4, 3))
-#define HSIO_S6G_IB_CFG2_IB_UMAX_M GENMASK(4, 3)
-#define HSIO_S6G_IB_CFG2_IB_UMAX_X(x) (((x) & GENMASK(4, 3)) >> 3)
-#define HSIO_S6G_IB_CFG2_IB_UREG(x) ((x) & GENMASK(2, 0))
-#define HSIO_S6G_IB_CFG2_IB_UREG_M GENMASK(2, 0)
-
-#define HSIO_S6G_IB_CFG3_IB_INI_HP(x) (((x) << 18) & GENMASK(23, 18))
-#define HSIO_S6G_IB_CFG3_IB_INI_HP_M GENMASK(23, 18)
-#define HSIO_S6G_IB_CFG3_IB_INI_HP_X(x) (((x) & GENMASK(23, 18)) >> 18)
-#define HSIO_S6G_IB_CFG3_IB_INI_MID(x) (((x) << 12) & GENMASK(17, 12))
-#define HSIO_S6G_IB_CFG3_IB_INI_MID_M GENMASK(17, 12)
-#define HSIO_S6G_IB_CFG3_IB_INI_MID_X(x) (((x) & GENMASK(17, 12)) >> 12)
-#define HSIO_S6G_IB_CFG3_IB_INI_LP(x) (((x) << 6) & GENMASK(11, 6))
-#define HSIO_S6G_IB_CFG3_IB_INI_LP_M GENMASK(11, 6)
-#define HSIO_S6G_IB_CFG3_IB_INI_LP_X(x) (((x) & GENMASK(11, 6)) >> 6)
-#define HSIO_S6G_IB_CFG3_IB_INI_OFFSET(x) ((x) & GENMASK(5, 0))
-#define HSIO_S6G_IB_CFG3_IB_INI_OFFSET_M GENMASK(5, 0)
-
-#define HSIO_S6G_IB_CFG4_IB_MAX_HP(x) (((x) << 18) & GENMASK(23, 18))
-#define HSIO_S6G_IB_CFG4_IB_MAX_HP_M GENMASK(23, 18)
-#define HSIO_S6G_IB_CFG4_IB_MAX_HP_X(x) (((x) & GENMASK(23, 18)) >> 18)
-#define HSIO_S6G_IB_CFG4_IB_MAX_MID(x) (((x) << 12) & GENMASK(17, 12))
-#define HSIO_S6G_IB_CFG4_IB_MAX_MID_M GENMASK(17, 12)
-#define HSIO_S6G_IB_CFG4_IB_MAX_MID_X(x) (((x) & GENMASK(17, 12)) >> 12)
-#define HSIO_S6G_IB_CFG4_IB_MAX_LP(x) (((x) << 6) & GENMASK(11, 6))
-#define HSIO_S6G_IB_CFG4_IB_MAX_LP_M GENMASK(11, 6)
-#define HSIO_S6G_IB_CFG4_IB_MAX_LP_X(x) (((x) & GENMASK(11, 6)) >> 6)
-#define HSIO_S6G_IB_CFG4_IB_MAX_OFFSET(x) ((x) & GENMASK(5, 0))
-#define HSIO_S6G_IB_CFG4_IB_MAX_OFFSET_M GENMASK(5, 0)
-
-#define HSIO_S6G_IB_CFG5_IB_MIN_HP(x) (((x) << 18) & GENMASK(23, 18))
-#define HSIO_S6G_IB_CFG5_IB_MIN_HP_M GENMASK(23, 18)
-#define HSIO_S6G_IB_CFG5_IB_MIN_HP_X(x) (((x) & GENMASK(23, 18)) >> 18)
-#define HSIO_S6G_IB_CFG5_IB_MIN_MID(x) (((x) << 12) & GENMASK(17, 12))
-#define HSIO_S6G_IB_CFG5_IB_MIN_MID_M GENMASK(17, 12)
-#define HSIO_S6G_IB_CFG5_IB_MIN_MID_X(x) (((x) & GENMASK(17, 12)) >> 12)
-#define HSIO_S6G_IB_CFG5_IB_MIN_LP(x) (((x) << 6) & GENMASK(11, 6))
-#define HSIO_S6G_IB_CFG5_IB_MIN_LP_M GENMASK(11, 6)
-#define HSIO_S6G_IB_CFG5_IB_MIN_LP_X(x) (((x) & GENMASK(11, 6)) >> 6)
-#define HSIO_S6G_IB_CFG5_IB_MIN_OFFSET(x) ((x) & GENMASK(5, 0))
-#define HSIO_S6G_IB_CFG5_IB_MIN_OFFSET_M GENMASK(5, 0)
-
-#define HSIO_S6G_OB_CFG_OB_IDLE BIT(31)
-#define HSIO_S6G_OB_CFG_OB_ENA1V_MODE BIT(30)
-#define HSIO_S6G_OB_CFG_OB_POL BIT(29)
-#define HSIO_S6G_OB_CFG_OB_POST0(x) (((x) << 23) & GENMASK(28, 23))
-#define HSIO_S6G_OB_CFG_OB_POST0_M GENMASK(28, 23)
-#define HSIO_S6G_OB_CFG_OB_POST0_X(x) (((x) & GENMASK(28, 23)) >> 23)
-#define HSIO_S6G_OB_CFG_OB_PREC(x) (((x) << 18) & GENMASK(22, 18))
-#define HSIO_S6G_OB_CFG_OB_PREC_M GENMASK(22, 18)
-#define HSIO_S6G_OB_CFG_OB_PREC_X(x) (((x) & GENMASK(22, 18)) >> 18)
-#define HSIO_S6G_OB_CFG_OB_R_ADJ_MUX BIT(17)
-#define HSIO_S6G_OB_CFG_OB_R_ADJ_PDR BIT(16)
-#define HSIO_S6G_OB_CFG_OB_POST1(x) (((x) << 11) & GENMASK(15, 11))
-#define HSIO_S6G_OB_CFG_OB_POST1_M GENMASK(15, 11)
-#define HSIO_S6G_OB_CFG_OB_POST1_X(x) (((x) & GENMASK(15, 11)) >> 11)
-#define HSIO_S6G_OB_CFG_OB_R_COR BIT(10)
-#define HSIO_S6G_OB_CFG_OB_SEL_RCTRL BIT(9)
-#define HSIO_S6G_OB_CFG_OB_SR_H BIT(8)
-#define HSIO_S6G_OB_CFG_OB_SR(x) (((x) << 4) & GENMASK(7, 4))
-#define HSIO_S6G_OB_CFG_OB_SR_M GENMASK(7, 4)
-#define HSIO_S6G_OB_CFG_OB_SR_X(x) (((x) & GENMASK(7, 4)) >> 4)
-#define HSIO_S6G_OB_CFG_OB_RESISTOR_CTRL(x) ((x) & GENMASK(3, 0))
-#define HSIO_S6G_OB_CFG_OB_RESISTOR_CTRL_M GENMASK(3, 0)
-
-#define HSIO_S6G_OB_CFG1_OB_ENA_CAS(x) (((x) << 6) & GENMASK(8, 6))
-#define HSIO_S6G_OB_CFG1_OB_ENA_CAS_M GENMASK(8, 6)
-#define HSIO_S6G_OB_CFG1_OB_ENA_CAS_X(x) (((x) & GENMASK(8, 6)) >> 6)
-#define HSIO_S6G_OB_CFG1_OB_LEV(x) ((x) & GENMASK(5, 0))
-#define HSIO_S6G_OB_CFG1_OB_LEV_M GENMASK(5, 0)
-
-#define HSIO_S6G_SER_CFG_SER_4TAP_ENA BIT(8)
-#define HSIO_S6G_SER_CFG_SER_CPMD_SEL BIT(7)
-#define HSIO_S6G_SER_CFG_SER_SWAP_CPMD BIT(6)
-#define HSIO_S6G_SER_CFG_SER_ALISEL(x) (((x) << 4) & GENMASK(5, 4))
-#define HSIO_S6G_SER_CFG_SER_ALISEL_M GENMASK(5, 4)
-#define HSIO_S6G_SER_CFG_SER_ALISEL_X(x) (((x) & GENMASK(5, 4)) >> 4)
-#define HSIO_S6G_SER_CFG_SER_ENHYS BIT(3)
-#define HSIO_S6G_SER_CFG_SER_BIG_WIN BIT(2)
-#define HSIO_S6G_SER_CFG_SER_EN_WIN BIT(1)
-#define HSIO_S6G_SER_CFG_SER_ENALI BIT(0)
-
-#define HSIO_S6G_COMMON_CFG_SYS_RST BIT(17)
-#define HSIO_S6G_COMMON_CFG_SE_DIV2_ENA BIT(16)
-#define HSIO_S6G_COMMON_CFG_SE_AUTO_SQUELCH_ENA BIT(15)
-#define HSIO_S6G_COMMON_CFG_ENA_LANE BIT(14)
-#define HSIO_S6G_COMMON_CFG_PWD_RX BIT(13)
-#define HSIO_S6G_COMMON_CFG_PWD_TX BIT(12)
-#define HSIO_S6G_COMMON_CFG_LANE_CTRL(x) (((x) << 9) & GENMASK(11, 9))
-#define HSIO_S6G_COMMON_CFG_LANE_CTRL_M GENMASK(11, 9)
-#define HSIO_S6G_COMMON_CFG_LANE_CTRL_X(x) (((x) & GENMASK(11, 9)) >> 9)
-#define HSIO_S6G_COMMON_CFG_ENA_DIRECT BIT(8)
-#define HSIO_S6G_COMMON_CFG_ENA_ELOOP BIT(7)
-#define HSIO_S6G_COMMON_CFG_ENA_FLOOP BIT(6)
-#define HSIO_S6G_COMMON_CFG_ENA_ILOOP BIT(5)
-#define HSIO_S6G_COMMON_CFG_ENA_PLOOP BIT(4)
-#define HSIO_S6G_COMMON_CFG_HRATE BIT(3)
-#define HSIO_S6G_COMMON_CFG_QRATE BIT(2)
-#define HSIO_S6G_COMMON_CFG_IF_MODE(x) ((x) & GENMASK(1, 0))
-#define HSIO_S6G_COMMON_CFG_IF_MODE_M GENMASK(1, 0)
-
-#define HSIO_S6G_PLL_CFG_PLL_ENA_OFFS(x) (((x) << 16) & GENMASK(17, 16))
-#define HSIO_S6G_PLL_CFG_PLL_ENA_OFFS_M GENMASK(17, 16)
-#define HSIO_S6G_PLL_CFG_PLL_ENA_OFFS_X(x) (((x) & GENMASK(17, 16)) >> 16)
-#define HSIO_S6G_PLL_CFG_PLL_DIV4 BIT(15)
-#define HSIO_S6G_PLL_CFG_PLL_ENA_ROT BIT(14)
-#define HSIO_S6G_PLL_CFG_PLL_FSM_CTRL_DATA(x) (((x) << 6) & GENMASK(13, 6))
-#define HSIO_S6G_PLL_CFG_PLL_FSM_CTRL_DATA_M GENMASK(13, 6)
-#define HSIO_S6G_PLL_CFG_PLL_FSM_CTRL_DATA_X(x) (((x) & GENMASK(13, 6)) >> 6)
-#define HSIO_S6G_PLL_CFG_PLL_FSM_ENA BIT(5)
-#define HSIO_S6G_PLL_CFG_PLL_FSM_FORCE_SET_ENA BIT(4)
-#define HSIO_S6G_PLL_CFG_PLL_FSM_OOR_RECAL_ENA BIT(3)
-#define HSIO_S6G_PLL_CFG_PLL_RB_DATA_SEL BIT(2)
-#define HSIO_S6G_PLL_CFG_PLL_ROT_DIR BIT(1)
-#define HSIO_S6G_PLL_CFG_PLL_ROT_FRQ BIT(0)
-
-#define HSIO_S6G_ACJTAG_CFG_ACJTAG_INIT_DATA_N BIT(5)
-#define HSIO_S6G_ACJTAG_CFG_ACJTAG_INIT_DATA_P BIT(4)
-#define HSIO_S6G_ACJTAG_CFG_ACJTAG_INIT_CLK BIT(3)
-#define HSIO_S6G_ACJTAG_CFG_OB_DIRECT BIT(2)
-#define HSIO_S6G_ACJTAG_CFG_ACJTAG_ENA BIT(1)
-#define HSIO_S6G_ACJTAG_CFG_JTAG_CTRL_ENA BIT(0)
-
-#define HSIO_S6G_GP_CFG_GP_MSB(x) (((x) << 16) & GENMASK(31, 16))
-#define HSIO_S6G_GP_CFG_GP_MSB_M GENMASK(31, 16)
-#define HSIO_S6G_GP_CFG_GP_MSB_X(x) (((x) & GENMASK(31, 16)) >> 16)
-#define HSIO_S6G_GP_CFG_GP_LSB(x) ((x) & GENMASK(15, 0))
-#define HSIO_S6G_GP_CFG_GP_LSB_M GENMASK(15, 0)
-
-#define HSIO_S6G_IB_STATUS0_IB_CAL_DONE BIT(8)
-#define HSIO_S6G_IB_STATUS0_IB_HP_GAIN_ACT BIT(7)
-#define HSIO_S6G_IB_STATUS0_IB_MID_GAIN_ACT BIT(6)
-#define HSIO_S6G_IB_STATUS0_IB_LP_GAIN_ACT BIT(5)
-#define HSIO_S6G_IB_STATUS0_IB_OFFSET_ACT BIT(4)
-#define HSIO_S6G_IB_STATUS0_IB_OFFSET_VLD BIT(3)
-#define HSIO_S6G_IB_STATUS0_IB_OFFSET_ERR BIT(2)
-#define HSIO_S6G_IB_STATUS0_IB_OFFSDIR BIT(1)
-#define HSIO_S6G_IB_STATUS0_IB_SIG_DET BIT(0)
-
-#define HSIO_S6G_IB_STATUS1_IB_HP_GAIN_STAT(x) (((x) << 18) & GENMASK(23, 18))
-#define HSIO_S6G_IB_STATUS1_IB_HP_GAIN_STAT_M GENMASK(23, 18)
-#define HSIO_S6G_IB_STATUS1_IB_HP_GAIN_STAT_X(x) (((x) & GENMASK(23, 18)) >> 18)
-#define HSIO_S6G_IB_STATUS1_IB_MID_GAIN_STAT(x) (((x) << 12) & GENMASK(17, 12))
-#define HSIO_S6G_IB_STATUS1_IB_MID_GAIN_STAT_M GENMASK(17, 12)
-#define HSIO_S6G_IB_STATUS1_IB_MID_GAIN_STAT_X(x) (((x) & GENMASK(17, 12)) >> 12)
-#define HSIO_S6G_IB_STATUS1_IB_LP_GAIN_STAT(x) (((x) << 6) & GENMASK(11, 6))
-#define HSIO_S6G_IB_STATUS1_IB_LP_GAIN_STAT_M GENMASK(11, 6)
-#define HSIO_S6G_IB_STATUS1_IB_LP_GAIN_STAT_X(x) (((x) & GENMASK(11, 6)) >> 6)
-#define HSIO_S6G_IB_STATUS1_IB_OFFSET_STAT(x) ((x) & GENMASK(5, 0))
-#define HSIO_S6G_IB_STATUS1_IB_OFFSET_STAT_M GENMASK(5, 0)
-
-#define HSIO_S6G_ACJTAG_STATUS_ACJTAG_CAPT_DATA_N BIT(2)
-#define HSIO_S6G_ACJTAG_STATUS_ACJTAG_CAPT_DATA_P BIT(1)
-#define HSIO_S6G_ACJTAG_STATUS_IB_DIRECT BIT(0)
-
-#define HSIO_S6G_PLL_STATUS_PLL_CAL_NOT_DONE BIT(10)
-#define HSIO_S6G_PLL_STATUS_PLL_CAL_ERR BIT(9)
-#define HSIO_S6G_PLL_STATUS_PLL_OUT_OF_RANGE_ERR BIT(8)
-#define HSIO_S6G_PLL_STATUS_PLL_RB_DATA(x) ((x) & GENMASK(7, 0))
-#define HSIO_S6G_PLL_STATUS_PLL_RB_DATA_M GENMASK(7, 0)
-
-#define HSIO_S6G_REVID_SERDES_REV(x) (((x) << 26) & GENMASK(31, 26))
-#define HSIO_S6G_REVID_SERDES_REV_M GENMASK(31, 26)
-#define HSIO_S6G_REVID_SERDES_REV_X(x) (((x) & GENMASK(31, 26)) >> 26)
-#define HSIO_S6G_REVID_RCPLL_REV(x) (((x) << 21) & GENMASK(25, 21))
-#define HSIO_S6G_REVID_RCPLL_REV_M GENMASK(25, 21)
-#define HSIO_S6G_REVID_RCPLL_REV_X(x) (((x) & GENMASK(25, 21)) >> 21)
-#define HSIO_S6G_REVID_SER_REV(x) (((x) << 16) & GENMASK(20, 16))
-#define HSIO_S6G_REVID_SER_REV_M GENMASK(20, 16)
-#define HSIO_S6G_REVID_SER_REV_X(x) (((x) & GENMASK(20, 16)) >> 16)
-#define HSIO_S6G_REVID_DES_REV(x) (((x) << 10) & GENMASK(15, 10))
-#define HSIO_S6G_REVID_DES_REV_M GENMASK(15, 10)
-#define HSIO_S6G_REVID_DES_REV_X(x) (((x) & GENMASK(15, 10)) >> 10)
-#define HSIO_S6G_REVID_OB_REV(x) (((x) << 5) & GENMASK(9, 5))
-#define HSIO_S6G_REVID_OB_REV_M GENMASK(9, 5)
-#define HSIO_S6G_REVID_OB_REV_X(x) (((x) & GENMASK(9, 5)) >> 5)
-#define HSIO_S6G_REVID_IB_REV(x) ((x) & GENMASK(4, 0))
-#define HSIO_S6G_REVID_IB_REV_M GENMASK(4, 0)
-
-#define HSIO_MCB_S6G_ADDR_CFG_SERDES6G_WR_ONE_SHOT BIT(31)
-#define HSIO_MCB_S6G_ADDR_CFG_SERDES6G_RD_ONE_SHOT BIT(30)
-#define HSIO_MCB_S6G_ADDR_CFG_SERDES6G_ADDR(x) ((x) & GENMASK(24, 0))
-#define HSIO_MCB_S6G_ADDR_CFG_SERDES6G_ADDR_M GENMASK(24, 0)
-
-#define HSIO_HW_CFG_DEV2G5_10_MODE BIT(6)
-#define HSIO_HW_CFG_DEV1G_9_MODE BIT(5)
-#define HSIO_HW_CFG_DEV1G_6_MODE BIT(4)
-#define HSIO_HW_CFG_DEV1G_5_MODE BIT(3)
-#define HSIO_HW_CFG_DEV1G_4_MODE BIT(2)
-#define HSIO_HW_CFG_PCIE_ENA BIT(1)
-#define HSIO_HW_CFG_QSGMII_ENA BIT(0)
-
-#define HSIO_HW_QSGMII_CFG_SHYST_DIS BIT(3)
-#define HSIO_HW_QSGMII_CFG_E_DET_ENA BIT(2)
-#define HSIO_HW_QSGMII_CFG_USE_I1_ENA BIT(1)
-#define HSIO_HW_QSGMII_CFG_FLIP_LANES BIT(0)
-
-#define HSIO_HW_QSGMII_STAT_DELAY_VAR_X200PS(x) (((x) << 1) & GENMASK(6, 1))
-#define HSIO_HW_QSGMII_STAT_DELAY_VAR_X200PS_M GENMASK(6, 1)
-#define HSIO_HW_QSGMII_STAT_DELAY_VAR_X200PS_X(x) (((x) & GENMASK(6, 1)) >> 1)
-#define HSIO_HW_QSGMII_STAT_SYNC BIT(0)
-
-#define HSIO_CLK_CFG_CLKDIV_PHY(x) (((x) << 1) & GENMASK(8, 1))
-#define HSIO_CLK_CFG_CLKDIV_PHY_M GENMASK(8, 1)
-#define HSIO_CLK_CFG_CLKDIV_PHY_X(x) (((x) & GENMASK(8, 1)) >> 1)
-#define HSIO_CLK_CFG_CLKDIV_PHY_DIS BIT(0)
-
-#define HSIO_TEMP_SENSOR_CTRL_FORCE_TEMP_RD BIT(5)
-#define HSIO_TEMP_SENSOR_CTRL_FORCE_RUN BIT(4)
-#define HSIO_TEMP_SENSOR_CTRL_FORCE_NO_RST BIT(3)
-#define HSIO_TEMP_SENSOR_CTRL_FORCE_POWER_UP BIT(2)
-#define HSIO_TEMP_SENSOR_CTRL_FORCE_CLK BIT(1)
-#define HSIO_TEMP_SENSOR_CTRL_SAMPLE_ENA BIT(0)
-
-#define HSIO_TEMP_SENSOR_CFG_RUN_WID(x) (((x) << 8) & GENMASK(15, 8))
-#define HSIO_TEMP_SENSOR_CFG_RUN_WID_M GENMASK(15, 8)
-#define HSIO_TEMP_SENSOR_CFG_RUN_WID_X(x) (((x) & GENMASK(15, 8)) >> 8)
-#define HSIO_TEMP_SENSOR_CFG_SAMPLE_PER(x) ((x) & GENMASK(7, 0))
-#define HSIO_TEMP_SENSOR_CFG_SAMPLE_PER_M GENMASK(7, 0)
-
-#define HSIO_TEMP_SENSOR_STAT_TEMP_VALID BIT(8)
-#define HSIO_TEMP_SENSOR_STAT_TEMP(x) ((x) & GENMASK(7, 0))
-#define HSIO_TEMP_SENSOR_STAT_TEMP_M GENMASK(7, 0)
-
-#endif
diff --git a/drivers/net/ethernet/mscc/ocelot_regs.c b/drivers/net/ethernet/mscc/ocelot_regs.c
index e334b40..bf0c609 100644
--- a/drivers/net/ethernet/mscc/ocelot_regs.c
+++ b/drivers/net/ethernet/mscc/ocelot_regs.c
@@ -5,6 +5,7 @@
* Copyright (c) 2017 Microsemi Corporation
*/
#include "ocelot.h"
+#include <soc/mscc/ocelot_hsio.h>
static const u32 ocelot_ana_regmap[] = {
REG(ANA_ADVLEARN, 0x009000),
diff --git a/include/soc/mscc/ocelot_hsio.h b/include/soc/mscc/ocelot_hsio.h
new file mode 100644
index 0000000..d93ddec
--- /dev/null
+++ b/include/soc/mscc/ocelot_hsio.h
@@ -0,0 +1,785 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * Copyright (c) 2017 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_HSIO_H_
+#define _MSCC_OCELOT_HSIO_H_
+
+#define HSIO_PLL5G_CFG0_ENA_ROT BIT(31)
+#define HSIO_PLL5G_CFG0_ENA_LANE BIT(30)
+#define HSIO_PLL5G_CFG0_ENA_CLKTREE BIT(29)
+#define HSIO_PLL5G_CFG0_DIV4 BIT(28)
+#define HSIO_PLL5G_CFG0_ENA_LOCK_FINE BIT(27)
+#define HSIO_PLL5G_CFG0_SELBGV820(x) (((x) << 23) & GENMASK(26, 23))
+#define HSIO_PLL5G_CFG0_SELBGV820_M GENMASK(26, 23)
+#define HSIO_PLL5G_CFG0_SELBGV820_X(x) (((x) & GENMASK(26, 23)) >> 23)
+#define HSIO_PLL5G_CFG0_LOOP_BW_RES(x) (((x) << 18) & GENMASK(22, 18))
+#define HSIO_PLL5G_CFG0_LOOP_BW_RES_M GENMASK(22, 18)
+#define HSIO_PLL5G_CFG0_LOOP_BW_RES_X(x) (((x) & GENMASK(22, 18)) >> 18)
+#define HSIO_PLL5G_CFG0_SELCPI(x) (((x) << 16) & GENMASK(17, 16))
+#define HSIO_PLL5G_CFG0_SELCPI_M GENMASK(17, 16)
+#define HSIO_PLL5G_CFG0_SELCPI_X(x) (((x) & GENMASK(17, 16)) >> 16)
+#define HSIO_PLL5G_CFG0_ENA_VCO_CONTRH BIT(15)
+#define HSIO_PLL5G_CFG0_ENA_CP1 BIT(14)
+#define HSIO_PLL5G_CFG0_ENA_VCO_BUF BIT(13)
+#define HSIO_PLL5G_CFG0_ENA_BIAS BIT(12)
+#define HSIO_PLL5G_CFG0_CPU_CLK_DIV(x) (((x) << 6) & GENMASK(11, 6))
+#define HSIO_PLL5G_CFG0_CPU_CLK_DIV_M GENMASK(11, 6)
+#define HSIO_PLL5G_CFG0_CPU_CLK_DIV_X(x) (((x) & GENMASK(11, 6)) >> 6)
+#define HSIO_PLL5G_CFG0_CORE_CLK_DIV(x) ((x) & GENMASK(5, 0))
+#define HSIO_PLL5G_CFG0_CORE_CLK_DIV_M GENMASK(5, 0)
+
+#define HSIO_PLL5G_CFG1_ENA_DIRECT BIT(18)
+#define HSIO_PLL5G_CFG1_ROT_SPEED BIT(17)
+#define HSIO_PLL5G_CFG1_ROT_DIR BIT(16)
+#define HSIO_PLL5G_CFG1_READBACK_DATA_SEL BIT(15)
+#define HSIO_PLL5G_CFG1_RC_ENABLE BIT(14)
+#define HSIO_PLL5G_CFG1_RC_CTRL_DATA(x) (((x) << 6) & GENMASK(13, 6))
+#define HSIO_PLL5G_CFG1_RC_CTRL_DATA_M GENMASK(13, 6)
+#define HSIO_PLL5G_CFG1_RC_CTRL_DATA_X(x) (((x) & GENMASK(13, 6)) >> 6)
+#define HSIO_PLL5G_CFG1_QUARTER_RATE BIT(5)
+#define HSIO_PLL5G_CFG1_PWD_TX BIT(4)
+#define HSIO_PLL5G_CFG1_PWD_RX BIT(3)
+#define HSIO_PLL5G_CFG1_OUT_OF_RANGE_RECAL_ENA BIT(2)
+#define HSIO_PLL5G_CFG1_HALF_RATE BIT(1)
+#define HSIO_PLL5G_CFG1_FORCE_SET_ENA BIT(0)
+
+#define HSIO_PLL5G_CFG2_ENA_TEST_MODE BIT(30)
+#define HSIO_PLL5G_CFG2_ENA_PFD_IN_FLIP BIT(29)
+#define HSIO_PLL5G_CFG2_ENA_VCO_NREF_TESTOUT BIT(28)
+#define HSIO_PLL5G_CFG2_ENA_FBTESTOUT BIT(27)
+#define HSIO_PLL5G_CFG2_ENA_RCPLL BIT(26)
+#define HSIO_PLL5G_CFG2_ENA_CP2 BIT(25)
+#define HSIO_PLL5G_CFG2_ENA_CLK_BYPASS1 BIT(24)
+#define HSIO_PLL5G_CFG2_AMPC_SEL(x) (((x) << 16) & GENMASK(23, 16))
+#define HSIO_PLL5G_CFG2_AMPC_SEL_M GENMASK(23, 16)
+#define HSIO_PLL5G_CFG2_AMPC_SEL_X(x) (((x) & GENMASK(23, 16)) >> 16)
+#define HSIO_PLL5G_CFG2_ENA_CLK_BYPASS BIT(15)
+#define HSIO_PLL5G_CFG2_PWD_AMPCTRL_N BIT(14)
+#define HSIO_PLL5G_CFG2_ENA_AMPCTRL BIT(13)
+#define HSIO_PLL5G_CFG2_ENA_AMP_CTRL_FORCE BIT(12)
+#define HSIO_PLL5G_CFG2_FRC_FSM_POR BIT(11)
+#define HSIO_PLL5G_CFG2_DISABLE_FSM_POR BIT(10)
+#define HSIO_PLL5G_CFG2_GAIN_TEST(x) (((x) << 5) & GENMASK(9, 5))
+#define HSIO_PLL5G_CFG2_GAIN_TEST_M GENMASK(9, 5)
+#define HSIO_PLL5G_CFG2_GAIN_TEST_X(x) (((x) & GENMASK(9, 5)) >> 5)
+#define HSIO_PLL5G_CFG2_EN_RESET_OVERRUN BIT(4)
+#define HSIO_PLL5G_CFG2_EN_RESET_LIM_DET BIT(3)
+#define HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET BIT(2)
+#define HSIO_PLL5G_CFG2_DISABLE_FSM BIT(1)
+#define HSIO_PLL5G_CFG2_ENA_GAIN_TEST BIT(0)
+
+#define HSIO_PLL5G_CFG3_TEST_ANA_OUT_SEL(x) (((x) << 22) & GENMASK(23, 22))
+#define HSIO_PLL5G_CFG3_TEST_ANA_OUT_SEL_M GENMASK(23, 22)
+#define HSIO_PLL5G_CFG3_TEST_ANA_OUT_SEL_X(x) (((x) & GENMASK(23, 22)) >> 22)
+#define HSIO_PLL5G_CFG3_TESTOUT_SEL(x) (((x) << 19) & GENMASK(21, 19))
+#define HSIO_PLL5G_CFG3_TESTOUT_SEL_M GENMASK(21, 19)
+#define HSIO_PLL5G_CFG3_TESTOUT_SEL_X(x) (((x) & GENMASK(21, 19)) >> 19)
+#define HSIO_PLL5G_CFG3_ENA_ANA_TEST_OUT BIT(18)
+#define HSIO_PLL5G_CFG3_ENA_TEST_OUT BIT(17)
+#define HSIO_PLL5G_CFG3_SEL_FBDCLK BIT(16)
+#define HSIO_PLL5G_CFG3_SEL_CML_CMOS_PFD BIT(15)
+#define HSIO_PLL5G_CFG3_RST_FB_N BIT(14)
+#define HSIO_PLL5G_CFG3_FORCE_VCO_CONTRH BIT(13)
+#define HSIO_PLL5G_CFG3_FORCE_LO BIT(12)
+#define HSIO_PLL5G_CFG3_FORCE_HI BIT(11)
+#define HSIO_PLL5G_CFG3_FORCE_ENA BIT(10)
+#define HSIO_PLL5G_CFG3_FORCE_CP BIT(9)
+#define HSIO_PLL5G_CFG3_FBDIVSEL_TST_ENA BIT(8)
+#define HSIO_PLL5G_CFG3_FBDIVSEL(x) ((x) & GENMASK(7, 0))
+#define HSIO_PLL5G_CFG3_FBDIVSEL_M GENMASK(7, 0)
+
+#define HSIO_PLL5G_CFG4_IB_BIAS_CTRL(x) (((x) << 16) & GENMASK(23, 16))
+#define HSIO_PLL5G_CFG4_IB_BIAS_CTRL_M GENMASK(23, 16)
+#define HSIO_PLL5G_CFG4_IB_BIAS_CTRL_X(x) (((x) & GENMASK(23, 16)) >> 16)
+#define HSIO_PLL5G_CFG4_IB_CTRL(x) ((x) & GENMASK(15, 0))
+#define HSIO_PLL5G_CFG4_IB_CTRL_M GENMASK(15, 0)
+
+#define HSIO_PLL5G_CFG5_OB_BIAS_CTRL(x) (((x) << 16) & GENMASK(23, 16))
+#define HSIO_PLL5G_CFG5_OB_BIAS_CTRL_M GENMASK(23, 16)
+#define HSIO_PLL5G_CFG5_OB_BIAS_CTRL_X(x) (((x) & GENMASK(23, 16)) >> 16)
+#define HSIO_PLL5G_CFG5_OB_CTRL(x) ((x) & GENMASK(15, 0))
+#define HSIO_PLL5G_CFG5_OB_CTRL_M GENMASK(15, 0)
+
+#define HSIO_PLL5G_CFG6_REFCLK_SEL_SRC BIT(23)
+#define HSIO_PLL5G_CFG6_REFCLK_SEL(x) (((x) << 20) & GENMASK(22, 20))
+#define HSIO_PLL5G_CFG6_REFCLK_SEL_M GENMASK(22, 20)
+#define HSIO_PLL5G_CFG6_REFCLK_SEL_X(x) (((x) & GENMASK(22, 20)) >> 20)
+#define HSIO_PLL5G_CFG6_REFCLK_SRC BIT(19)
+#define HSIO_PLL5G_CFG6_POR_DEL_SEL(x) (((x) << 16) & GENMASK(17, 16))
+#define HSIO_PLL5G_CFG6_POR_DEL_SEL_M GENMASK(17, 16)
+#define HSIO_PLL5G_CFG6_POR_DEL_SEL_X(x) (((x) & GENMASK(17, 16)) >> 16)
+#define HSIO_PLL5G_CFG6_DIV125REF_SEL(x) (((x) << 8) & GENMASK(15, 8))
+#define HSIO_PLL5G_CFG6_DIV125REF_SEL_M GENMASK(15, 8)
+#define HSIO_PLL5G_CFG6_DIV125REF_SEL_X(x) (((x) & GENMASK(15, 8)) >> 8)
+#define HSIO_PLL5G_CFG6_ENA_REFCLKC2 BIT(7)
+#define HSIO_PLL5G_CFG6_ENA_FBCLKC2 BIT(6)
+#define HSIO_PLL5G_CFG6_DDR_CLK_DIV(x) ((x) & GENMASK(5, 0))
+#define HSIO_PLL5G_CFG6_DDR_CLK_DIV_M GENMASK(5, 0)
+
+#define HSIO_PLL5G_STATUS0_RANGE_LIM BIT(12)
+#define HSIO_PLL5G_STATUS0_OUT_OF_RANGE_ERR BIT(11)
+#define HSIO_PLL5G_STATUS0_CALIBRATION_ERR BIT(10)
+#define HSIO_PLL5G_STATUS0_CALIBRATION_DONE BIT(9)
+#define HSIO_PLL5G_STATUS0_READBACK_DATA(x) (((x) << 1) & GENMASK(8, 1))
+#define HSIO_PLL5G_STATUS0_READBACK_DATA_M GENMASK(8, 1)
+#define HSIO_PLL5G_STATUS0_READBACK_DATA_X(x) (((x) & GENMASK(8, 1)) >> 1)
+#define HSIO_PLL5G_STATUS0_LOCK_STATUS BIT(0)
+
+#define HSIO_PLL5G_STATUS1_SIG_DEL(x) (((x) << 21) & GENMASK(28, 21))
+#define HSIO_PLL5G_STATUS1_SIG_DEL_M GENMASK(28, 21)
+#define HSIO_PLL5G_STATUS1_SIG_DEL_X(x) (((x) & GENMASK(28, 21)) >> 21)
+#define HSIO_PLL5G_STATUS1_GAIN_STAT(x) (((x) << 16) & GENMASK(20, 16))
+#define HSIO_PLL5G_STATUS1_GAIN_STAT_M GENMASK(20, 16)
+#define HSIO_PLL5G_STATUS1_GAIN_STAT_X(x) (((x) & GENMASK(20, 16)) >> 16)
+#define HSIO_PLL5G_STATUS1_FBCNT_DIF(x) (((x) << 4) & GENMASK(13, 4))
+#define HSIO_PLL5G_STATUS1_FBCNT_DIF_M GENMASK(13, 4)
+#define HSIO_PLL5G_STATUS1_FBCNT_DIF_X(x) (((x) & GENMASK(13, 4)) >> 4)
+#define HSIO_PLL5G_STATUS1_FSM_STAT(x) (((x) << 1) & GENMASK(3, 1))
+#define HSIO_PLL5G_STATUS1_FSM_STAT_M GENMASK(3, 1)
+#define HSIO_PLL5G_STATUS1_FSM_STAT_X(x) (((x) & GENMASK(3, 1)) >> 1)
+#define HSIO_PLL5G_STATUS1_FSM_LOCK BIT(0)
+
+#define HSIO_PLL5G_BIST_CFG0_PLLB_START_BIST BIT(31)
+#define HSIO_PLL5G_BIST_CFG0_PLLB_MEAS_MODE BIT(30)
+#define HSIO_PLL5G_BIST_CFG0_PLLB_LOCK_REPEAT(x) (((x) << 20) & GENMASK(23, 20))
+#define HSIO_PLL5G_BIST_CFG0_PLLB_LOCK_REPEAT_M GENMASK(23, 20)
+#define HSIO_PLL5G_BIST_CFG0_PLLB_LOCK_REPEAT_X(x) (((x) & GENMASK(23, 20)) >> 20)
+#define HSIO_PLL5G_BIST_CFG0_PLLB_LOCK_UNCERT(x) (((x) << 16) & GENMASK(19, 16))
+#define HSIO_PLL5G_BIST_CFG0_PLLB_LOCK_UNCERT_M GENMASK(19, 16)
+#define HSIO_PLL5G_BIST_CFG0_PLLB_LOCK_UNCERT_X(x) (((x) & GENMASK(19, 16)) >> 16)
+#define HSIO_PLL5G_BIST_CFG0_PLLB_DIV_FACTOR_PRE(x) ((x) & GENMASK(15, 0))
+#define HSIO_PLL5G_BIST_CFG0_PLLB_DIV_FACTOR_PRE_M GENMASK(15, 0)
+
+#define HSIO_PLL5G_BIST_STAT0_PLLB_FSM_STAT(x) (((x) << 4) & GENMASK(7, 4))
+#define HSIO_PLL5G_BIST_STAT0_PLLB_FSM_STAT_M GENMASK(7, 4)
+#define HSIO_PLL5G_BIST_STAT0_PLLB_FSM_STAT_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define HSIO_PLL5G_BIST_STAT0_PLLB_BUSY BIT(2)
+#define HSIO_PLL5G_BIST_STAT0_PLLB_DONE_N BIT(1)
+#define HSIO_PLL5G_BIST_STAT0_PLLB_FAIL BIT(0)
+
+#define HSIO_PLL5G_BIST_STAT1_PLLB_CNT_OUT(x) (((x) << 16) & GENMASK(31, 16))
+#define HSIO_PLL5G_BIST_STAT1_PLLB_CNT_OUT_M GENMASK(31, 16)
+#define HSIO_PLL5G_BIST_STAT1_PLLB_CNT_OUT_X(x) (((x) & GENMASK(31, 16)) >> 16)
+#define HSIO_PLL5G_BIST_STAT1_PLLB_CNT_REF_DIFF(x) ((x) & GENMASK(15, 0))
+#define HSIO_PLL5G_BIST_STAT1_PLLB_CNT_REF_DIFF_M GENMASK(15, 0)
+
+#define HSIO_RCOMP_CFG0_PWD_ENA BIT(13)
+#define HSIO_RCOMP_CFG0_RUN_CAL BIT(12)
+#define HSIO_RCOMP_CFG0_SPEED_SEL(x) (((x) << 10) & GENMASK(11, 10))
+#define HSIO_RCOMP_CFG0_SPEED_SEL_M GENMASK(11, 10)
+#define HSIO_RCOMP_CFG0_SPEED_SEL_X(x) (((x) & GENMASK(11, 10)) >> 10)
+#define HSIO_RCOMP_CFG0_MODE_SEL(x) (((x) << 8) & GENMASK(9, 8))
+#define HSIO_RCOMP_CFG0_MODE_SEL_M GENMASK(9, 8)
+#define HSIO_RCOMP_CFG0_MODE_SEL_X(x) (((x) & GENMASK(9, 8)) >> 8)
+#define HSIO_RCOMP_CFG0_FORCE_ENA BIT(4)
+#define HSIO_RCOMP_CFG0_RCOMP_VAL(x) ((x) & GENMASK(3, 0))
+#define HSIO_RCOMP_CFG0_RCOMP_VAL_M GENMASK(3, 0)
+
+#define HSIO_RCOMP_STATUS_BUSY BIT(12)
+#define HSIO_RCOMP_STATUS_DELTA_ALERT BIT(7)
+#define HSIO_RCOMP_STATUS_RCOMP(x) ((x) & GENMASK(3, 0))
+#define HSIO_RCOMP_STATUS_RCOMP_M GENMASK(3, 0)
+
+#define HSIO_SYNC_ETH_CFG_RSZ 0x4
+
+#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_SRC(x) (((x) << 4) & GENMASK(7, 4))
+#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_SRC_M GENMASK(7, 4)
+#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_SRC_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_DIV(x) (((x) << 1) & GENMASK(3, 1))
+#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_DIV_M GENMASK(3, 1)
+#define HSIO_SYNC_ETH_CFG_SEL_RECO_CLK_DIV_X(x) (((x) & GENMASK(3, 1)) >> 1)
+#define HSIO_SYNC_ETH_CFG_RECO_CLK_ENA BIT(0)
+
+#define HSIO_SYNC_ETH_PLL_CFG_PLL_AUTO_SQUELCH_ENA BIT(0)
+
+#define HSIO_S1G_DES_CFG_DES_PHS_CTRL(x) (((x) << 13) & GENMASK(16, 13))
+#define HSIO_S1G_DES_CFG_DES_PHS_CTRL_M GENMASK(16, 13)
+#define HSIO_S1G_DES_CFG_DES_PHS_CTRL_X(x) (((x) & GENMASK(16, 13)) >> 13)
+#define HSIO_S1G_DES_CFG_DES_CPMD_SEL(x) (((x) << 11) & GENMASK(12, 11))
+#define HSIO_S1G_DES_CFG_DES_CPMD_SEL_M GENMASK(12, 11)
+#define HSIO_S1G_DES_CFG_DES_CPMD_SEL_X(x) (((x) & GENMASK(12, 11)) >> 11)
+#define HSIO_S1G_DES_CFG_DES_MBTR_CTRL(x) (((x) << 8) & GENMASK(10, 8))
+#define HSIO_S1G_DES_CFG_DES_MBTR_CTRL_M GENMASK(10, 8)
+#define HSIO_S1G_DES_CFG_DES_MBTR_CTRL_X(x) (((x) & GENMASK(10, 8)) >> 8)
+#define HSIO_S1G_DES_CFG_DES_BW_ANA(x) (((x) << 5) & GENMASK(7, 5))
+#define HSIO_S1G_DES_CFG_DES_BW_ANA_M GENMASK(7, 5)
+#define HSIO_S1G_DES_CFG_DES_BW_ANA_X(x) (((x) & GENMASK(7, 5)) >> 5)
+#define HSIO_S1G_DES_CFG_DES_SWAP_ANA BIT(4)
+#define HSIO_S1G_DES_CFG_DES_BW_HYST(x) (((x) << 1) & GENMASK(3, 1))
+#define HSIO_S1G_DES_CFG_DES_BW_HYST_M GENMASK(3, 1)
+#define HSIO_S1G_DES_CFG_DES_BW_HYST_X(x) (((x) & GENMASK(3, 1)) >> 1)
+#define HSIO_S1G_DES_CFG_DES_SWAP_HYST BIT(0)
+
+#define HSIO_S1G_IB_CFG_IB_FX100_ENA BIT(27)
+#define HSIO_S1G_IB_CFG_ACJTAG_HYST(x) (((x) << 24) & GENMASK(26, 24))
+#define HSIO_S1G_IB_CFG_ACJTAG_HYST_M GENMASK(26, 24)
+#define HSIO_S1G_IB_CFG_ACJTAG_HYST_X(x) (((x) & GENMASK(26, 24)) >> 24)
+#define HSIO_S1G_IB_CFG_IB_DET_LEV(x) (((x) << 19) & GENMASK(21, 19))
+#define HSIO_S1G_IB_CFG_IB_DET_LEV_M GENMASK(21, 19)
+#define HSIO_S1G_IB_CFG_IB_DET_LEV_X(x) (((x) & GENMASK(21, 19)) >> 19)
+#define HSIO_S1G_IB_CFG_IB_HYST_LEV BIT(14)
+#define HSIO_S1G_IB_CFG_IB_ENA_CMV_TERM BIT(13)
+#define HSIO_S1G_IB_CFG_IB_ENA_DC_COUPLING BIT(12)
+#define HSIO_S1G_IB_CFG_IB_ENA_DETLEV BIT(11)
+#define HSIO_S1G_IB_CFG_IB_ENA_HYST BIT(10)
+#define HSIO_S1G_IB_CFG_IB_ENA_OFFSET_COMP BIT(9)
+#define HSIO_S1G_IB_CFG_IB_EQ_GAIN(x) (((x) << 6) & GENMASK(8, 6))
+#define HSIO_S1G_IB_CFG_IB_EQ_GAIN_M GENMASK(8, 6)
+#define HSIO_S1G_IB_CFG_IB_EQ_GAIN_X(x) (((x) & GENMASK(8, 6)) >> 6)
+#define HSIO_S1G_IB_CFG_IB_SEL_CORNER_FREQ(x) (((x) << 4) & GENMASK(5, 4))
+#define HSIO_S1G_IB_CFG_IB_SEL_CORNER_FREQ_M GENMASK(5, 4)
+#define HSIO_S1G_IB_CFG_IB_SEL_CORNER_FREQ_X(x) (((x) & GENMASK(5, 4)) >> 4)
+#define HSIO_S1G_IB_CFG_IB_RESISTOR_CTRL(x) ((x) & GENMASK(3, 0))
+#define HSIO_S1G_IB_CFG_IB_RESISTOR_CTRL_M GENMASK(3, 0)
+
+#define HSIO_S1G_OB_CFG_OB_SLP(x) (((x) << 17) & GENMASK(18, 17))
+#define HSIO_S1G_OB_CFG_OB_SLP_M GENMASK(18, 17)
+#define HSIO_S1G_OB_CFG_OB_SLP_X(x) (((x) & GENMASK(18, 17)) >> 17)
+#define HSIO_S1G_OB_CFG_OB_AMP_CTRL(x) (((x) << 13) & GENMASK(16, 13))
+#define HSIO_S1G_OB_CFG_OB_AMP_CTRL_M GENMASK(16, 13)
+#define HSIO_S1G_OB_CFG_OB_AMP_CTRL_X(x) (((x) & GENMASK(16, 13)) >> 13)
+#define HSIO_S1G_OB_CFG_OB_CMM_BIAS_CTRL(x) (((x) << 10) & GENMASK(12, 10))
+#define HSIO_S1G_OB_CFG_OB_CMM_BIAS_CTRL_M GENMASK(12, 10)
+#define HSIO_S1G_OB_CFG_OB_CMM_BIAS_CTRL_X(x) (((x) & GENMASK(12, 10)) >> 10)
+#define HSIO_S1G_OB_CFG_OB_DIS_VCM_CTRL BIT(9)
+#define HSIO_S1G_OB_CFG_OB_EN_MEAS_VREG BIT(8)
+#define HSIO_S1G_OB_CFG_OB_VCM_CTRL(x) (((x) << 4) & GENMASK(7, 4))
+#define HSIO_S1G_OB_CFG_OB_VCM_CTRL_M GENMASK(7, 4)
+#define HSIO_S1G_OB_CFG_OB_VCM_CTRL_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define HSIO_S1G_OB_CFG_OB_RESISTOR_CTRL(x) ((x) & GENMASK(3, 0))
+#define HSIO_S1G_OB_CFG_OB_RESISTOR_CTRL_M GENMASK(3, 0)
+
+#define HSIO_S1G_SER_CFG_SER_IDLE BIT(9)
+#define HSIO_S1G_SER_CFG_SER_DEEMPH BIT(8)
+#define HSIO_S1G_SER_CFG_SER_CPMD_SEL BIT(7)
+#define HSIO_S1G_SER_CFG_SER_SWAP_CPMD BIT(6)
+#define HSIO_S1G_SER_CFG_SER_ALISEL(x) (((x) << 4) & GENMASK(5, 4))
+#define HSIO_S1G_SER_CFG_SER_ALISEL_M GENMASK(5, 4)
+#define HSIO_S1G_SER_CFG_SER_ALISEL_X(x) (((x) & GENMASK(5, 4)) >> 4)
+#define HSIO_S1G_SER_CFG_SER_ENHYS BIT(3)
+#define HSIO_S1G_SER_CFG_SER_BIG_WIN BIT(2)
+#define HSIO_S1G_SER_CFG_SER_EN_WIN BIT(1)
+#define HSIO_S1G_SER_CFG_SER_ENALI BIT(0)
+
+#define HSIO_S1G_COMMON_CFG_SYS_RST BIT(31)
+#define HSIO_S1G_COMMON_CFG_SE_AUTO_SQUELCH_ENA BIT(21)
+#define HSIO_S1G_COMMON_CFG_ENA_LANE BIT(18)
+#define HSIO_S1G_COMMON_CFG_PWD_RX BIT(17)
+#define HSIO_S1G_COMMON_CFG_PWD_TX BIT(16)
+#define HSIO_S1G_COMMON_CFG_LANE_CTRL(x) (((x) << 13) & GENMASK(15, 13))
+#define HSIO_S1G_COMMON_CFG_LANE_CTRL_M GENMASK(15, 13)
+#define HSIO_S1G_COMMON_CFG_LANE_CTRL_X(x) (((x) & GENMASK(15, 13)) >> 13)
+#define HSIO_S1G_COMMON_CFG_ENA_DIRECT BIT(12)
+#define HSIO_S1G_COMMON_CFG_ENA_ELOOP BIT(11)
+#define HSIO_S1G_COMMON_CFG_ENA_FLOOP BIT(10)
+#define HSIO_S1G_COMMON_CFG_ENA_ILOOP BIT(9)
+#define HSIO_S1G_COMMON_CFG_ENA_PLOOP BIT(8)
+#define HSIO_S1G_COMMON_CFG_HRATE BIT(7)
+#define HSIO_S1G_COMMON_CFG_IF_MODE BIT(0)
+
+#define HSIO_S1G_PLL_CFG_PLL_ENA_FB_DIV2 BIT(22)
+#define HSIO_S1G_PLL_CFG_PLL_ENA_RC_DIV2 BIT(21)
+#define HSIO_S1G_PLL_CFG_PLL_FSM_CTRL_DATA(x) (((x) << 8) & GENMASK(15, 8))
+#define HSIO_S1G_PLL_CFG_PLL_FSM_CTRL_DATA_M GENMASK(15, 8)
+#define HSIO_S1G_PLL_CFG_PLL_FSM_CTRL_DATA_X(x) (((x) & GENMASK(15, 8)) >> 8)
+#define HSIO_S1G_PLL_CFG_PLL_FSM_ENA BIT(7)
+#define HSIO_S1G_PLL_CFG_PLL_FSM_FORCE_SET_ENA BIT(6)
+#define HSIO_S1G_PLL_CFG_PLL_FSM_OOR_RECAL_ENA BIT(5)
+#define HSIO_S1G_PLL_CFG_PLL_RB_DATA_SEL BIT(3)
+
+#define HSIO_S1G_PLL_STATUS_PLL_CAL_NOT_DONE BIT(12)
+#define HSIO_S1G_PLL_STATUS_PLL_CAL_ERR BIT(11)
+#define HSIO_S1G_PLL_STATUS_PLL_OUT_OF_RANGE_ERR BIT(10)
+#define HSIO_S1G_PLL_STATUS_PLL_RB_DATA(x) ((x) & GENMASK(7, 0))
+#define HSIO_S1G_PLL_STATUS_PLL_RB_DATA_M GENMASK(7, 0)
+
+#define HSIO_S1G_DFT_CFG0_LAZYBIT BIT(31)
+#define HSIO_S1G_DFT_CFG0_INV_DIS BIT(23)
+#define HSIO_S1G_DFT_CFG0_PRBS_SEL(x) (((x) << 20) & GENMASK(21, 20))
+#define HSIO_S1G_DFT_CFG0_PRBS_SEL_M GENMASK(21, 20)
+#define HSIO_S1G_DFT_CFG0_PRBS_SEL_X(x) (((x) & GENMASK(21, 20)) >> 20)
+#define HSIO_S1G_DFT_CFG0_TEST_MODE(x) (((x) << 16) & GENMASK(18, 16))
+#define HSIO_S1G_DFT_CFG0_TEST_MODE_M GENMASK(18, 16)
+#define HSIO_S1G_DFT_CFG0_TEST_MODE_X(x) (((x) & GENMASK(18, 16)) >> 16)
+#define HSIO_S1G_DFT_CFG0_RX_PHS_CORR_DIS BIT(4)
+#define HSIO_S1G_DFT_CFG0_RX_PDSENS_ENA BIT(3)
+#define HSIO_S1G_DFT_CFG0_RX_DFT_ENA BIT(2)
+#define HSIO_S1G_DFT_CFG0_TX_DFT_ENA BIT(0)
+
+#define HSIO_S1G_DFT_CFG1_TX_JITTER_AMPL(x) (((x) << 8) & GENMASK(17, 8))
+#define HSIO_S1G_DFT_CFG1_TX_JITTER_AMPL_M GENMASK(17, 8)
+#define HSIO_S1G_DFT_CFG1_TX_JITTER_AMPL_X(x) (((x) & GENMASK(17, 8)) >> 8)
+#define HSIO_S1G_DFT_CFG1_TX_STEP_FREQ(x) (((x) << 4) & GENMASK(7, 4))
+#define HSIO_S1G_DFT_CFG1_TX_STEP_FREQ_M GENMASK(7, 4)
+#define HSIO_S1G_DFT_CFG1_TX_STEP_FREQ_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define HSIO_S1G_DFT_CFG1_TX_JI_ENA BIT(3)
+#define HSIO_S1G_DFT_CFG1_TX_WAVEFORM_SEL BIT(2)
+#define HSIO_S1G_DFT_CFG1_TX_FREQOFF_DIR BIT(1)
+#define HSIO_S1G_DFT_CFG1_TX_FREQOFF_ENA BIT(0)
+
+#define HSIO_S1G_DFT_CFG2_RX_JITTER_AMPL(x) (((x) << 8) & GENMASK(17, 8))
+#define HSIO_S1G_DFT_CFG2_RX_JITTER_AMPL_M GENMASK(17, 8)
+#define HSIO_S1G_DFT_CFG2_RX_JITTER_AMPL_X(x) (((x) & GENMASK(17, 8)) >> 8)
+#define HSIO_S1G_DFT_CFG2_RX_STEP_FREQ(x) (((x) << 4) & GENMASK(7, 4))
+#define HSIO_S1G_DFT_CFG2_RX_STEP_FREQ_M GENMASK(7, 4)
+#define HSIO_S1G_DFT_CFG2_RX_STEP_FREQ_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define HSIO_S1G_DFT_CFG2_RX_JI_ENA BIT(3)
+#define HSIO_S1G_DFT_CFG2_RX_WAVEFORM_SEL BIT(2)
+#define HSIO_S1G_DFT_CFG2_RX_FREQOFF_DIR BIT(1)
+#define HSIO_S1G_DFT_CFG2_RX_FREQOFF_ENA BIT(0)
+
+#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_ENA BIT(20)
+#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_FBS_HIGH(x) (((x) << 16) & GENMASK(17, 16))
+#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_FBS_HIGH_M GENMASK(17, 16)
+#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_FBS_HIGH_X(x) (((x) & GENMASK(17, 16)) >> 16)
+#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_HIGH(x) (((x) << 8) & GENMASK(15, 8))
+#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_HIGH_M GENMASK(15, 8)
+#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_HIGH_X(x) (((x) & GENMASK(15, 8)) >> 8)
+#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_LOW(x) ((x) & GENMASK(7, 0))
+#define HSIO_S1G_RC_PLL_BIST_CFG_PLL_BIST_LOW_M GENMASK(7, 0)
+
+#define HSIO_S1G_MISC_CFG_DES_100FX_KICK_MODE(x) (((x) << 11) & GENMASK(12, 11))
+#define HSIO_S1G_MISC_CFG_DES_100FX_KICK_MODE_M GENMASK(12, 11)
+#define HSIO_S1G_MISC_CFG_DES_100FX_KICK_MODE_X(x) (((x) & GENMASK(12, 11)) >> 11)
+#define HSIO_S1G_MISC_CFG_DES_100FX_CPMD_SWAP BIT(10)
+#define HSIO_S1G_MISC_CFG_DES_100FX_CPMD_MODE BIT(9)
+#define HSIO_S1G_MISC_CFG_DES_100FX_CPMD_ENA BIT(8)
+#define HSIO_S1G_MISC_CFG_RX_LPI_MODE_ENA BIT(5)
+#define HSIO_S1G_MISC_CFG_TX_LPI_MODE_ENA BIT(4)
+#define HSIO_S1G_MISC_CFG_RX_DATA_INV_ENA BIT(3)
+#define HSIO_S1G_MISC_CFG_TX_DATA_INV_ENA BIT(2)
+#define HSIO_S1G_MISC_CFG_LANE_RST BIT(0)
+
+#define HSIO_S1G_DFT_STATUS_PLL_BIST_NOT_DONE BIT(7)
+#define HSIO_S1G_DFT_STATUS_PLL_BIST_FAILED BIT(6)
+#define HSIO_S1G_DFT_STATUS_PLL_BIST_TIMEOUT_ERR BIT(5)
+#define HSIO_S1G_DFT_STATUS_BIST_ACTIVE BIT(3)
+#define HSIO_S1G_DFT_STATUS_BIST_NOSYNC BIT(2)
+#define HSIO_S1G_DFT_STATUS_BIST_COMPLETE_N BIT(1)
+#define HSIO_S1G_DFT_STATUS_BIST_ERROR BIT(0)
+
+#define HSIO_S1G_MISC_STATUS_DES_100FX_PHASE_SEL BIT(0)
+
+#define HSIO_MCB_S1G_ADDR_CFG_SERDES1G_WR_ONE_SHOT BIT(31)
+#define HSIO_MCB_S1G_ADDR_CFG_SERDES1G_RD_ONE_SHOT BIT(30)
+#define HSIO_MCB_S1G_ADDR_CFG_SERDES1G_ADDR(x) ((x) & GENMASK(8, 0))
+#define HSIO_MCB_S1G_ADDR_CFG_SERDES1G_ADDR_M GENMASK(8, 0)
+
+#define HSIO_S6G_DIG_CFG_GP(x) (((x) << 16) & GENMASK(18, 16))
+#define HSIO_S6G_DIG_CFG_GP_M GENMASK(18, 16)
+#define HSIO_S6G_DIG_CFG_GP_X(x) (((x) & GENMASK(18, 16)) >> 16)
+#define HSIO_S6G_DIG_CFG_TX_BIT_DOUBLING_MODE_ENA BIT(7)
+#define HSIO_S6G_DIG_CFG_SIGDET_TESTMODE BIT(6)
+#define HSIO_S6G_DIG_CFG_SIGDET_AST(x) (((x) << 3) & GENMASK(5, 3))
+#define HSIO_S6G_DIG_CFG_SIGDET_AST_M GENMASK(5, 3)
+#define HSIO_S6G_DIG_CFG_SIGDET_AST_X(x) (((x) & GENMASK(5, 3)) >> 3)
+#define HSIO_S6G_DIG_CFG_SIGDET_DST(x) ((x) & GENMASK(2, 0))
+#define HSIO_S6G_DIG_CFG_SIGDET_DST_M GENMASK(2, 0)
+
+#define HSIO_S6G_DFT_CFG0_LAZYBIT BIT(31)
+#define HSIO_S6G_DFT_CFG0_INV_DIS BIT(23)
+#define HSIO_S6G_DFT_CFG0_PRBS_SEL(x) (((x) << 20) & GENMASK(21, 20))
+#define HSIO_S6G_DFT_CFG0_PRBS_SEL_M GENMASK(21, 20)
+#define HSIO_S6G_DFT_CFG0_PRBS_SEL_X(x) (((x) & GENMASK(21, 20)) >> 20)
+#define HSIO_S6G_DFT_CFG0_TEST_MODE(x) (((x) << 16) & GENMASK(18, 16))
+#define HSIO_S6G_DFT_CFG0_TEST_MODE_M GENMASK(18, 16)
+#define HSIO_S6G_DFT_CFG0_TEST_MODE_X(x) (((x) & GENMASK(18, 16)) >> 16)
+#define HSIO_S6G_DFT_CFG0_RX_PHS_CORR_DIS BIT(4)
+#define HSIO_S6G_DFT_CFG0_RX_PDSENS_ENA BIT(3)
+#define HSIO_S6G_DFT_CFG0_RX_DFT_ENA BIT(2)
+#define HSIO_S6G_DFT_CFG0_TX_DFT_ENA BIT(0)
+
+#define HSIO_S6G_DFT_CFG1_TX_JITTER_AMPL(x) (((x) << 8) & GENMASK(17, 8))
+#define HSIO_S6G_DFT_CFG1_TX_JITTER_AMPL_M GENMASK(17, 8)
+#define HSIO_S6G_DFT_CFG1_TX_JITTER_AMPL_X(x) (((x) & GENMASK(17, 8)) >> 8)
+#define HSIO_S6G_DFT_CFG1_TX_STEP_FREQ(x) (((x) << 4) & GENMASK(7, 4))
+#define HSIO_S6G_DFT_CFG1_TX_STEP_FREQ_M GENMASK(7, 4)
+#define HSIO_S6G_DFT_CFG1_TX_STEP_FREQ_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define HSIO_S6G_DFT_CFG1_TX_JI_ENA BIT(3)
+#define HSIO_S6G_DFT_CFG1_TX_WAVEFORM_SEL BIT(2)
+#define HSIO_S6G_DFT_CFG1_TX_FREQOFF_DIR BIT(1)
+#define HSIO_S6G_DFT_CFG1_TX_FREQOFF_ENA BIT(0)
+
+#define HSIO_S6G_DFT_CFG2_RX_JITTER_AMPL(x) (((x) << 8) & GENMASK(17, 8))
+#define HSIO_S6G_DFT_CFG2_RX_JITTER_AMPL_M GENMASK(17, 8)
+#define HSIO_S6G_DFT_CFG2_RX_JITTER_AMPL_X(x) (((x) & GENMASK(17, 8)) >> 8)
+#define HSIO_S6G_DFT_CFG2_RX_STEP_FREQ(x) (((x) << 4) & GENMASK(7, 4))
+#define HSIO_S6G_DFT_CFG2_RX_STEP_FREQ_M GENMASK(7, 4)
+#define HSIO_S6G_DFT_CFG2_RX_STEP_FREQ_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define HSIO_S6G_DFT_CFG2_RX_JI_ENA BIT(3)
+#define HSIO_S6G_DFT_CFG2_RX_WAVEFORM_SEL BIT(2)
+#define HSIO_S6G_DFT_CFG2_RX_FREQOFF_DIR BIT(1)
+#define HSIO_S6G_DFT_CFG2_RX_FREQOFF_ENA BIT(0)
+
+#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_ENA BIT(20)
+#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_FBS_HIGH(x) (((x) << 16) & GENMASK(19, 16))
+#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_FBS_HIGH_M GENMASK(19, 16)
+#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_FBS_HIGH_X(x) (((x) & GENMASK(19, 16)) >> 16)
+#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_HIGH(x) (((x) << 8) & GENMASK(15, 8))
+#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_HIGH_M GENMASK(15, 8)
+#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_HIGH_X(x) (((x) & GENMASK(15, 8)) >> 8)
+#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_LOW(x) ((x) & GENMASK(7, 0))
+#define HSIO_S6G_RC_PLL_BIST_CFG_PLL_BIST_LOW_M GENMASK(7, 0)
+
+#define HSIO_S6G_MISC_CFG_SEL_RECO_CLK(x) (((x) << 13) & GENMASK(14, 13))
+#define HSIO_S6G_MISC_CFG_SEL_RECO_CLK_M GENMASK(14, 13)
+#define HSIO_S6G_MISC_CFG_SEL_RECO_CLK_X(x) (((x) & GENMASK(14, 13)) >> 13)
+#define HSIO_S6G_MISC_CFG_DES_100FX_KICK_MODE(x) (((x) << 11) & GENMASK(12, 11))
+#define HSIO_S6G_MISC_CFG_DES_100FX_KICK_MODE_M GENMASK(12, 11)
+#define HSIO_S6G_MISC_CFG_DES_100FX_KICK_MODE_X(x) (((x) & GENMASK(12, 11)) >> 11)
+#define HSIO_S6G_MISC_CFG_DES_100FX_CPMD_SWAP BIT(10)
+#define HSIO_S6G_MISC_CFG_DES_100FX_CPMD_MODE BIT(9)
+#define HSIO_S6G_MISC_CFG_DES_100FX_CPMD_ENA BIT(8)
+#define HSIO_S6G_MISC_CFG_RX_BUS_FLIP_ENA BIT(7)
+#define HSIO_S6G_MISC_CFG_TX_BUS_FLIP_ENA BIT(6)
+#define HSIO_S6G_MISC_CFG_RX_LPI_MODE_ENA BIT(5)
+#define HSIO_S6G_MISC_CFG_TX_LPI_MODE_ENA BIT(4)
+#define HSIO_S6G_MISC_CFG_RX_DATA_INV_ENA BIT(3)
+#define HSIO_S6G_MISC_CFG_TX_DATA_INV_ENA BIT(2)
+#define HSIO_S6G_MISC_CFG_LANE_RST BIT(0)
+
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_POST0(x) (((x) << 23) & GENMASK(28, 23))
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_POST0_M GENMASK(28, 23)
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_POST0_X(x) (((x) & GENMASK(28, 23)) >> 23)
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_POST1(x) (((x) << 18) & GENMASK(22, 18))
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_POST1_M GENMASK(22, 18)
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_POST1_X(x) (((x) & GENMASK(22, 18)) >> 18)
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_PREC(x) (((x) << 13) & GENMASK(17, 13))
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_PREC_M GENMASK(17, 13)
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_PREC_X(x) (((x) & GENMASK(17, 13)) >> 13)
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_ENA_CAS(x) (((x) << 6) & GENMASK(8, 6))
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_ENA_CAS_M GENMASK(8, 6)
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_ENA_CAS_X(x) (((x) & GENMASK(8, 6)) >> 6)
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_LEV(x) ((x) & GENMASK(5, 0))
+#define HSIO_S6G_OB_ANEG_CFG_AN_OB_LEV_M GENMASK(5, 0)
+
+#define HSIO_S6G_DFT_STATUS_PRBS_SYNC_STAT BIT(8)
+#define HSIO_S6G_DFT_STATUS_PLL_BIST_NOT_DONE BIT(7)
+#define HSIO_S6G_DFT_STATUS_PLL_BIST_FAILED BIT(6)
+#define HSIO_S6G_DFT_STATUS_PLL_BIST_TIMEOUT_ERR BIT(5)
+#define HSIO_S6G_DFT_STATUS_BIST_ACTIVE BIT(3)
+#define HSIO_S6G_DFT_STATUS_BIST_NOSYNC BIT(2)
+#define HSIO_S6G_DFT_STATUS_BIST_COMPLETE_N BIT(1)
+#define HSIO_S6G_DFT_STATUS_BIST_ERROR BIT(0)
+
+#define HSIO_S6G_MISC_STATUS_DES_100FX_PHASE_SEL BIT(0)
+
+#define HSIO_S6G_DES_CFG_DES_PHS_CTRL(x) (((x) << 13) & GENMASK(16, 13))
+#define HSIO_S6G_DES_CFG_DES_PHS_CTRL_M GENMASK(16, 13)
+#define HSIO_S6G_DES_CFG_DES_PHS_CTRL_X(x) (((x) & GENMASK(16, 13)) >> 13)
+#define HSIO_S6G_DES_CFG_DES_MBTR_CTRL(x) (((x) << 10) & GENMASK(12, 10))
+#define HSIO_S6G_DES_CFG_DES_MBTR_CTRL_M GENMASK(12, 10)
+#define HSIO_S6G_DES_CFG_DES_MBTR_CTRL_X(x) (((x) & GENMASK(12, 10)) >> 10)
+#define HSIO_S6G_DES_CFG_DES_CPMD_SEL(x) (((x) << 8) & GENMASK(9, 8))
+#define HSIO_S6G_DES_CFG_DES_CPMD_SEL_M GENMASK(9, 8)
+#define HSIO_S6G_DES_CFG_DES_CPMD_SEL_X(x) (((x) & GENMASK(9, 8)) >> 8)
+#define HSIO_S6G_DES_CFG_DES_BW_HYST(x) (((x) << 5) & GENMASK(7, 5))
+#define HSIO_S6G_DES_CFG_DES_BW_HYST_M GENMASK(7, 5)
+#define HSIO_S6G_DES_CFG_DES_BW_HYST_X(x) (((x) & GENMASK(7, 5)) >> 5)
+#define HSIO_S6G_DES_CFG_DES_SWAP_HYST BIT(4)
+#define HSIO_S6G_DES_CFG_DES_BW_ANA(x) (((x) << 1) & GENMASK(3, 1))
+#define HSIO_S6G_DES_CFG_DES_BW_ANA_M GENMASK(3, 1)
+#define HSIO_S6G_DES_CFG_DES_BW_ANA_X(x) (((x) & GENMASK(3, 1)) >> 1)
+#define HSIO_S6G_DES_CFG_DES_SWAP_ANA BIT(0)
+
+#define HSIO_S6G_IB_CFG_IB_SOFSI(x) (((x) << 29) & GENMASK(30, 29))
+#define HSIO_S6G_IB_CFG_IB_SOFSI_M GENMASK(30, 29)
+#define HSIO_S6G_IB_CFG_IB_SOFSI_X(x) (((x) & GENMASK(30, 29)) >> 29)
+#define HSIO_S6G_IB_CFG_IB_VBULK_SEL BIT(28)
+#define HSIO_S6G_IB_CFG_IB_RTRM_ADJ(x) (((x) << 24) & GENMASK(27, 24))
+#define HSIO_S6G_IB_CFG_IB_RTRM_ADJ_M GENMASK(27, 24)
+#define HSIO_S6G_IB_CFG_IB_RTRM_ADJ_X(x) (((x) & GENMASK(27, 24)) >> 24)
+#define HSIO_S6G_IB_CFG_IB_ICML_ADJ(x) (((x) << 20) & GENMASK(23, 20))
+#define HSIO_S6G_IB_CFG_IB_ICML_ADJ_M GENMASK(23, 20)
+#define HSIO_S6G_IB_CFG_IB_ICML_ADJ_X(x) (((x) & GENMASK(23, 20)) >> 20)
+#define HSIO_S6G_IB_CFG_IB_TERM_MODE_SEL(x) (((x) << 18) & GENMASK(19, 18))
+#define HSIO_S6G_IB_CFG_IB_TERM_MODE_SEL_M GENMASK(19, 18)
+#define HSIO_S6G_IB_CFG_IB_TERM_MODE_SEL_X(x) (((x) & GENMASK(19, 18)) >> 18)
+#define HSIO_S6G_IB_CFG_IB_SIG_DET_CLK_SEL(x) (((x) << 15) & GENMASK(17, 15))
+#define HSIO_S6G_IB_CFG_IB_SIG_DET_CLK_SEL_M GENMASK(17, 15)
+#define HSIO_S6G_IB_CFG_IB_SIG_DET_CLK_SEL_X(x) (((x) & GENMASK(17, 15)) >> 15)
+#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_HP(x) (((x) << 13) & GENMASK(14, 13))
+#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_HP_M GENMASK(14, 13)
+#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_HP_X(x) (((x) & GENMASK(14, 13)) >> 13)
+#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_MID(x) (((x) << 11) & GENMASK(12, 11))
+#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_MID_M GENMASK(12, 11)
+#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_MID_X(x) (((x) & GENMASK(12, 11)) >> 11)
+#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_LP(x) (((x) << 9) & GENMASK(10, 9))
+#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_LP_M GENMASK(10, 9)
+#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_LP_X(x) (((x) & GENMASK(10, 9)) >> 9)
+#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_OFFSET(x) (((x) << 7) & GENMASK(8, 7))
+#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_OFFSET_M GENMASK(8, 7)
+#define HSIO_S6G_IB_CFG_IB_REG_PAT_SEL_OFFSET_X(x) (((x) & GENMASK(8, 7)) >> 7)
+#define HSIO_S6G_IB_CFG_IB_ANA_TEST_ENA BIT(6)
+#define HSIO_S6G_IB_CFG_IB_SIG_DET_ENA BIT(5)
+#define HSIO_S6G_IB_CFG_IB_CONCUR BIT(4)
+#define HSIO_S6G_IB_CFG_IB_CAL_ENA BIT(3)
+#define HSIO_S6G_IB_CFG_IB_SAM_ENA BIT(2)
+#define HSIO_S6G_IB_CFG_IB_EQZ_ENA BIT(1)
+#define HSIO_S6G_IB_CFG_IB_REG_ENA BIT(0)
+
+#define HSIO_S6G_IB_CFG1_IB_TJTAG(x) (((x) << 17) & GENMASK(21, 17))
+#define HSIO_S6G_IB_CFG1_IB_TJTAG_M GENMASK(21, 17)
+#define HSIO_S6G_IB_CFG1_IB_TJTAG_X(x) (((x) & GENMASK(21, 17)) >> 17)
+#define HSIO_S6G_IB_CFG1_IB_TSDET(x) (((x) << 12) & GENMASK(16, 12))
+#define HSIO_S6G_IB_CFG1_IB_TSDET_M GENMASK(16, 12)
+#define HSIO_S6G_IB_CFG1_IB_TSDET_X(x) (((x) & GENMASK(16, 12)) >> 12)
+#define HSIO_S6G_IB_CFG1_IB_SCALY(x) (((x) << 8) & GENMASK(11, 8))
+#define HSIO_S6G_IB_CFG1_IB_SCALY_M GENMASK(11, 8)
+#define HSIO_S6G_IB_CFG1_IB_SCALY_X(x) (((x) & GENMASK(11, 8)) >> 8)
+#define HSIO_S6G_IB_CFG1_IB_FILT_HP BIT(7)
+#define HSIO_S6G_IB_CFG1_IB_FILT_MID BIT(6)
+#define HSIO_S6G_IB_CFG1_IB_FILT_LP BIT(5)
+#define HSIO_S6G_IB_CFG1_IB_FILT_OFFSET BIT(4)
+#define HSIO_S6G_IB_CFG1_IB_FRC_HP BIT(3)
+#define HSIO_S6G_IB_CFG1_IB_FRC_MID BIT(2)
+#define HSIO_S6G_IB_CFG1_IB_FRC_LP BIT(1)
+#define HSIO_S6G_IB_CFG1_IB_FRC_OFFSET BIT(0)
+
+#define HSIO_S6G_IB_CFG2_IB_TINFV(x) (((x) << 27) & GENMASK(29, 27))
+#define HSIO_S6G_IB_CFG2_IB_TINFV_M GENMASK(29, 27)
+#define HSIO_S6G_IB_CFG2_IB_TINFV_X(x) (((x) & GENMASK(29, 27)) >> 27)
+#define HSIO_S6G_IB_CFG2_IB_OINFI(x) (((x) << 22) & GENMASK(26, 22))
+#define HSIO_S6G_IB_CFG2_IB_OINFI_M GENMASK(26, 22)
+#define HSIO_S6G_IB_CFG2_IB_OINFI_X(x) (((x) & GENMASK(26, 22)) >> 22)
+#define HSIO_S6G_IB_CFG2_IB_TAUX(x) (((x) << 19) & GENMASK(21, 19))
+#define HSIO_S6G_IB_CFG2_IB_TAUX_M GENMASK(21, 19)
+#define HSIO_S6G_IB_CFG2_IB_TAUX_X(x) (((x) & GENMASK(21, 19)) >> 19)
+#define HSIO_S6G_IB_CFG2_IB_OINFS(x) (((x) << 16) & GENMASK(18, 16))
+#define HSIO_S6G_IB_CFG2_IB_OINFS_M GENMASK(18, 16)
+#define HSIO_S6G_IB_CFG2_IB_OINFS_X(x) (((x) & GENMASK(18, 16)) >> 16)
+#define HSIO_S6G_IB_CFG2_IB_OCALS(x) (((x) << 10) & GENMASK(15, 10))
+#define HSIO_S6G_IB_CFG2_IB_OCALS_M GENMASK(15, 10)
+#define HSIO_S6G_IB_CFG2_IB_OCALS_X(x) (((x) & GENMASK(15, 10)) >> 10)
+#define HSIO_S6G_IB_CFG2_IB_TCALV(x) (((x) << 5) & GENMASK(9, 5))
+#define HSIO_S6G_IB_CFG2_IB_TCALV_M GENMASK(9, 5)
+#define HSIO_S6G_IB_CFG2_IB_TCALV_X(x) (((x) & GENMASK(9, 5)) >> 5)
+#define HSIO_S6G_IB_CFG2_IB_UMAX(x) (((x) << 3) & GENMASK(4, 3))
+#define HSIO_S6G_IB_CFG2_IB_UMAX_M GENMASK(4, 3)
+#define HSIO_S6G_IB_CFG2_IB_UMAX_X(x) (((x) & GENMASK(4, 3)) >> 3)
+#define HSIO_S6G_IB_CFG2_IB_UREG(x) ((x) & GENMASK(2, 0))
+#define HSIO_S6G_IB_CFG2_IB_UREG_M GENMASK(2, 0)
+
+#define HSIO_S6G_IB_CFG3_IB_INI_HP(x) (((x) << 18) & GENMASK(23, 18))
+#define HSIO_S6G_IB_CFG3_IB_INI_HP_M GENMASK(23, 18)
+#define HSIO_S6G_IB_CFG3_IB_INI_HP_X(x) (((x) & GENMASK(23, 18)) >> 18)
+#define HSIO_S6G_IB_CFG3_IB_INI_MID(x) (((x) << 12) & GENMASK(17, 12))
+#define HSIO_S6G_IB_CFG3_IB_INI_MID_M GENMASK(17, 12)
+#define HSIO_S6G_IB_CFG3_IB_INI_MID_X(x) (((x) & GENMASK(17, 12)) >> 12)
+#define HSIO_S6G_IB_CFG3_IB_INI_LP(x) (((x) << 6) & GENMASK(11, 6))
+#define HSIO_S6G_IB_CFG3_IB_INI_LP_M GENMASK(11, 6)
+#define HSIO_S6G_IB_CFG3_IB_INI_LP_X(x) (((x) & GENMASK(11, 6)) >> 6)
+#define HSIO_S6G_IB_CFG3_IB_INI_OFFSET(x) ((x) & GENMASK(5, 0))
+#define HSIO_S6G_IB_CFG3_IB_INI_OFFSET_M GENMASK(5, 0)
+
+#define HSIO_S6G_IB_CFG4_IB_MAX_HP(x) (((x) << 18) & GENMASK(23, 18))
+#define HSIO_S6G_IB_CFG4_IB_MAX_HP_M GENMASK(23, 18)
+#define HSIO_S6G_IB_CFG4_IB_MAX_HP_X(x) (((x) & GENMASK(23, 18)) >> 18)
+#define HSIO_S6G_IB_CFG4_IB_MAX_MID(x) (((x) << 12) & GENMASK(17, 12))
+#define HSIO_S6G_IB_CFG4_IB_MAX_MID_M GENMASK(17, 12)
+#define HSIO_S6G_IB_CFG4_IB_MAX_MID_X(x) (((x) & GENMASK(17, 12)) >> 12)
+#define HSIO_S6G_IB_CFG4_IB_MAX_LP(x) (((x) << 6) & GENMASK(11, 6))
+#define HSIO_S6G_IB_CFG4_IB_MAX_LP_M GENMASK(11, 6)
+#define HSIO_S6G_IB_CFG4_IB_MAX_LP_X(x) (((x) & GENMASK(11, 6)) >> 6)
+#define HSIO_S6G_IB_CFG4_IB_MAX_OFFSET(x) ((x) & GENMASK(5, 0))
+#define HSIO_S6G_IB_CFG4_IB_MAX_OFFSET_M GENMASK(5, 0)
+
+#define HSIO_S6G_IB_CFG5_IB_MIN_HP(x) (((x) << 18) & GENMASK(23, 18))
+#define HSIO_S6G_IB_CFG5_IB_MIN_HP_M GENMASK(23, 18)
+#define HSIO_S6G_IB_CFG5_IB_MIN_HP_X(x) (((x) & GENMASK(23, 18)) >> 18)
+#define HSIO_S6G_IB_CFG5_IB_MIN_MID(x) (((x) << 12) & GENMASK(17, 12))
+#define HSIO_S6G_IB_CFG5_IB_MIN_MID_M GENMASK(17, 12)
+#define HSIO_S6G_IB_CFG5_IB_MIN_MID_X(x) (((x) & GENMASK(17, 12)) >> 12)
+#define HSIO_S6G_IB_CFG5_IB_MIN_LP(x) (((x) << 6) & GENMASK(11, 6))
+#define HSIO_S6G_IB_CFG5_IB_MIN_LP_M GENMASK(11, 6)
+#define HSIO_S6G_IB_CFG5_IB_MIN_LP_X(x) (((x) & GENMASK(11, 6)) >> 6)
+#define HSIO_S6G_IB_CFG5_IB_MIN_OFFSET(x) ((x) & GENMASK(5, 0))
+#define HSIO_S6G_IB_CFG5_IB_MIN_OFFSET_M GENMASK(5, 0)
+
+#define HSIO_S6G_OB_CFG_OB_IDLE BIT(31)
+#define HSIO_S6G_OB_CFG_OB_ENA1V_MODE BIT(30)
+#define HSIO_S6G_OB_CFG_OB_POL BIT(29)
+#define HSIO_S6G_OB_CFG_OB_POST0(x) (((x) << 23) & GENMASK(28, 23))
+#define HSIO_S6G_OB_CFG_OB_POST0_M GENMASK(28, 23)
+#define HSIO_S6G_OB_CFG_OB_POST0_X(x) (((x) & GENMASK(28, 23)) >> 23)
+#define HSIO_S6G_OB_CFG_OB_PREC(x) (((x) << 18) & GENMASK(22, 18))
+#define HSIO_S6G_OB_CFG_OB_PREC_M GENMASK(22, 18)
+#define HSIO_S6G_OB_CFG_OB_PREC_X(x) (((x) & GENMASK(22, 18)) >> 18)
+#define HSIO_S6G_OB_CFG_OB_R_ADJ_MUX BIT(17)
+#define HSIO_S6G_OB_CFG_OB_R_ADJ_PDR BIT(16)
+#define HSIO_S6G_OB_CFG_OB_POST1(x) (((x) << 11) & GENMASK(15, 11))
+#define HSIO_S6G_OB_CFG_OB_POST1_M GENMASK(15, 11)
+#define HSIO_S6G_OB_CFG_OB_POST1_X(x) (((x) & GENMASK(15, 11)) >> 11)
+#define HSIO_S6G_OB_CFG_OB_R_COR BIT(10)
+#define HSIO_S6G_OB_CFG_OB_SEL_RCTRL BIT(9)
+#define HSIO_S6G_OB_CFG_OB_SR_H BIT(8)
+#define HSIO_S6G_OB_CFG_OB_SR(x) (((x) << 4) & GENMASK(7, 4))
+#define HSIO_S6G_OB_CFG_OB_SR_M GENMASK(7, 4)
+#define HSIO_S6G_OB_CFG_OB_SR_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define HSIO_S6G_OB_CFG_OB_RESISTOR_CTRL(x) ((x) & GENMASK(3, 0))
+#define HSIO_S6G_OB_CFG_OB_RESISTOR_CTRL_M GENMASK(3, 0)
+
+#define HSIO_S6G_OB_CFG1_OB_ENA_CAS(x) (((x) << 6) & GENMASK(8, 6))
+#define HSIO_S6G_OB_CFG1_OB_ENA_CAS_M GENMASK(8, 6)
+#define HSIO_S6G_OB_CFG1_OB_ENA_CAS_X(x) (((x) & GENMASK(8, 6)) >> 6)
+#define HSIO_S6G_OB_CFG1_OB_LEV(x) ((x) & GENMASK(5, 0))
+#define HSIO_S6G_OB_CFG1_OB_LEV_M GENMASK(5, 0)
+
+#define HSIO_S6G_SER_CFG_SER_4TAP_ENA BIT(8)
+#define HSIO_S6G_SER_CFG_SER_CPMD_SEL BIT(7)
+#define HSIO_S6G_SER_CFG_SER_SWAP_CPMD BIT(6)
+#define HSIO_S6G_SER_CFG_SER_ALISEL(x) (((x) << 4) & GENMASK(5, 4))
+#define HSIO_S6G_SER_CFG_SER_ALISEL_M GENMASK(5, 4)
+#define HSIO_S6G_SER_CFG_SER_ALISEL_X(x) (((x) & GENMASK(5, 4)) >> 4)
+#define HSIO_S6G_SER_CFG_SER_ENHYS BIT(3)
+#define HSIO_S6G_SER_CFG_SER_BIG_WIN BIT(2)
+#define HSIO_S6G_SER_CFG_SER_EN_WIN BIT(1)
+#define HSIO_S6G_SER_CFG_SER_ENALI BIT(0)
+
+#define HSIO_S6G_COMMON_CFG_SYS_RST BIT(17)
+#define HSIO_S6G_COMMON_CFG_SE_DIV2_ENA BIT(16)
+#define HSIO_S6G_COMMON_CFG_SE_AUTO_SQUELCH_ENA BIT(15)
+#define HSIO_S6G_COMMON_CFG_ENA_LANE BIT(14)
+#define HSIO_S6G_COMMON_CFG_PWD_RX BIT(13)
+#define HSIO_S6G_COMMON_CFG_PWD_TX BIT(12)
+#define HSIO_S6G_COMMON_CFG_LANE_CTRL(x) (((x) << 9) & GENMASK(11, 9))
+#define HSIO_S6G_COMMON_CFG_LANE_CTRL_M GENMASK(11, 9)
+#define HSIO_S6G_COMMON_CFG_LANE_CTRL_X(x) (((x) & GENMASK(11, 9)) >> 9)
+#define HSIO_S6G_COMMON_CFG_ENA_DIRECT BIT(8)
+#define HSIO_S6G_COMMON_CFG_ENA_ELOOP BIT(7)
+#define HSIO_S6G_COMMON_CFG_ENA_FLOOP BIT(6)
+#define HSIO_S6G_COMMON_CFG_ENA_ILOOP BIT(5)
+#define HSIO_S6G_COMMON_CFG_ENA_PLOOP BIT(4)
+#define HSIO_S6G_COMMON_CFG_HRATE BIT(3)
+#define HSIO_S6G_COMMON_CFG_QRATE BIT(2)
+#define HSIO_S6G_COMMON_CFG_IF_MODE(x) ((x) & GENMASK(1, 0))
+#define HSIO_S6G_COMMON_CFG_IF_MODE_M GENMASK(1, 0)
+
+#define HSIO_S6G_PLL_CFG_PLL_ENA_OFFS(x) (((x) << 16) & GENMASK(17, 16))
+#define HSIO_S6G_PLL_CFG_PLL_ENA_OFFS_M GENMASK(17, 16)
+#define HSIO_S6G_PLL_CFG_PLL_ENA_OFFS_X(x) (((x) & GENMASK(17, 16)) >> 16)
+#define HSIO_S6G_PLL_CFG_PLL_DIV4 BIT(15)
+#define HSIO_S6G_PLL_CFG_PLL_ENA_ROT BIT(14)
+#define HSIO_S6G_PLL_CFG_PLL_FSM_CTRL_DATA(x) (((x) << 6) & GENMASK(13, 6))
+#define HSIO_S6G_PLL_CFG_PLL_FSM_CTRL_DATA_M GENMASK(13, 6)
+#define HSIO_S6G_PLL_CFG_PLL_FSM_CTRL_DATA_X(x) (((x) & GENMASK(13, 6)) >> 6)
+#define HSIO_S6G_PLL_CFG_PLL_FSM_ENA BIT(5)
+#define HSIO_S6G_PLL_CFG_PLL_FSM_FORCE_SET_ENA BIT(4)
+#define HSIO_S6G_PLL_CFG_PLL_FSM_OOR_RECAL_ENA BIT(3)
+#define HSIO_S6G_PLL_CFG_PLL_RB_DATA_SEL BIT(2)
+#define HSIO_S6G_PLL_CFG_PLL_ROT_DIR BIT(1)
+#define HSIO_S6G_PLL_CFG_PLL_ROT_FRQ BIT(0)
+
+#define HSIO_S6G_ACJTAG_CFG_ACJTAG_INIT_DATA_N BIT(5)
+#define HSIO_S6G_ACJTAG_CFG_ACJTAG_INIT_DATA_P BIT(4)
+#define HSIO_S6G_ACJTAG_CFG_ACJTAG_INIT_CLK BIT(3)
+#define HSIO_S6G_ACJTAG_CFG_OB_DIRECT BIT(2)
+#define HSIO_S6G_ACJTAG_CFG_ACJTAG_ENA BIT(1)
+#define HSIO_S6G_ACJTAG_CFG_JTAG_CTRL_ENA BIT(0)
+
+#define HSIO_S6G_GP_CFG_GP_MSB(x) (((x) << 16) & GENMASK(31, 16))
+#define HSIO_S6G_GP_CFG_GP_MSB_M GENMASK(31, 16)
+#define HSIO_S6G_GP_CFG_GP_MSB_X(x) (((x) & GENMASK(31, 16)) >> 16)
+#define HSIO_S6G_GP_CFG_GP_LSB(x) ((x) & GENMASK(15, 0))
+#define HSIO_S6G_GP_CFG_GP_LSB_M GENMASK(15, 0)
+
+#define HSIO_S6G_IB_STATUS0_IB_CAL_DONE BIT(8)
+#define HSIO_S6G_IB_STATUS0_IB_HP_GAIN_ACT BIT(7)
+#define HSIO_S6G_IB_STATUS0_IB_MID_GAIN_ACT BIT(6)
+#define HSIO_S6G_IB_STATUS0_IB_LP_GAIN_ACT BIT(5)
+#define HSIO_S6G_IB_STATUS0_IB_OFFSET_ACT BIT(4)
+#define HSIO_S6G_IB_STATUS0_IB_OFFSET_VLD BIT(3)
+#define HSIO_S6G_IB_STATUS0_IB_OFFSET_ERR BIT(2)
+#define HSIO_S6G_IB_STATUS0_IB_OFFSDIR BIT(1)
+#define HSIO_S6G_IB_STATUS0_IB_SIG_DET BIT(0)
+
+#define HSIO_S6G_IB_STATUS1_IB_HP_GAIN_STAT(x) (((x) << 18) & GENMASK(23, 18))
+#define HSIO_S6G_IB_STATUS1_IB_HP_GAIN_STAT_M GENMASK(23, 18)
+#define HSIO_S6G_IB_STATUS1_IB_HP_GAIN_STAT_X(x) (((x) & GENMASK(23, 18)) >> 18)
+#define HSIO_S6G_IB_STATUS1_IB_MID_GAIN_STAT(x) (((x) << 12) & GENMASK(17, 12))
+#define HSIO_S6G_IB_STATUS1_IB_MID_GAIN_STAT_M GENMASK(17, 12)
+#define HSIO_S6G_IB_STATUS1_IB_MID_GAIN_STAT_X(x) (((x) & GENMASK(17, 12)) >> 12)
+#define HSIO_S6G_IB_STATUS1_IB_LP_GAIN_STAT(x) (((x) << 6) & GENMASK(11, 6))
+#define HSIO_S6G_IB_STATUS1_IB_LP_GAIN_STAT_M GENMASK(11, 6)
+#define HSIO_S6G_IB_STATUS1_IB_LP_GAIN_STAT_X(x) (((x) & GENMASK(11, 6)) >> 6)
+#define HSIO_S6G_IB_STATUS1_IB_OFFSET_STAT(x) ((x) & GENMASK(5, 0))
+#define HSIO_S6G_IB_STATUS1_IB_OFFSET_STAT_M GENMASK(5, 0)
+
+#define HSIO_S6G_ACJTAG_STATUS_ACJTAG_CAPT_DATA_N BIT(2)
+#define HSIO_S6G_ACJTAG_STATUS_ACJTAG_CAPT_DATA_P BIT(1)
+#define HSIO_S6G_ACJTAG_STATUS_IB_DIRECT BIT(0)
+
+#define HSIO_S6G_PLL_STATUS_PLL_CAL_NOT_DONE BIT(10)
+#define HSIO_S6G_PLL_STATUS_PLL_CAL_ERR BIT(9)
+#define HSIO_S6G_PLL_STATUS_PLL_OUT_OF_RANGE_ERR BIT(8)
+#define HSIO_S6G_PLL_STATUS_PLL_RB_DATA(x) ((x) & GENMASK(7, 0))
+#define HSIO_S6G_PLL_STATUS_PLL_RB_DATA_M GENMASK(7, 0)
+
+#define HSIO_S6G_REVID_SERDES_REV(x) (((x) << 26) & GENMASK(31, 26))
+#define HSIO_S6G_REVID_SERDES_REV_M GENMASK(31, 26)
+#define HSIO_S6G_REVID_SERDES_REV_X(x) (((x) & GENMASK(31, 26)) >> 26)
+#define HSIO_S6G_REVID_RCPLL_REV(x) (((x) << 21) & GENMASK(25, 21))
+#define HSIO_S6G_REVID_RCPLL_REV_M GENMASK(25, 21)
+#define HSIO_S6G_REVID_RCPLL_REV_X(x) (((x) & GENMASK(25, 21)) >> 21)
+#define HSIO_S6G_REVID_SER_REV(x) (((x) << 16) & GENMASK(20, 16))
+#define HSIO_S6G_REVID_SER_REV_M GENMASK(20, 16)
+#define HSIO_S6G_REVID_SER_REV_X(x) (((x) & GENMASK(20, 16)) >> 16)
+#define HSIO_S6G_REVID_DES_REV(x) (((x) << 10) & GENMASK(15, 10))
+#define HSIO_S6G_REVID_DES_REV_M GENMASK(15, 10)
+#define HSIO_S6G_REVID_DES_REV_X(x) (((x) & GENMASK(15, 10)) >> 10)
+#define HSIO_S6G_REVID_OB_REV(x) (((x) << 5) & GENMASK(9, 5))
+#define HSIO_S6G_REVID_OB_REV_M GENMASK(9, 5)
+#define HSIO_S6G_REVID_OB_REV_X(x) (((x) & GENMASK(9, 5)) >> 5)
+#define HSIO_S6G_REVID_IB_REV(x) ((x) & GENMASK(4, 0))
+#define HSIO_S6G_REVID_IB_REV_M GENMASK(4, 0)
+
+#define HSIO_MCB_S6G_ADDR_CFG_SERDES6G_WR_ONE_SHOT BIT(31)
+#define HSIO_MCB_S6G_ADDR_CFG_SERDES6G_RD_ONE_SHOT BIT(30)
+#define HSIO_MCB_S6G_ADDR_CFG_SERDES6G_ADDR(x) ((x) & GENMASK(24, 0))
+#define HSIO_MCB_S6G_ADDR_CFG_SERDES6G_ADDR_M GENMASK(24, 0)
+
+#define HSIO_HW_CFG_DEV2G5_10_MODE BIT(6)
+#define HSIO_HW_CFG_DEV1G_9_MODE BIT(5)
+#define HSIO_HW_CFG_DEV1G_6_MODE BIT(4)
+#define HSIO_HW_CFG_DEV1G_5_MODE BIT(3)
+#define HSIO_HW_CFG_DEV1G_4_MODE BIT(2)
+#define HSIO_HW_CFG_PCIE_ENA BIT(1)
+#define HSIO_HW_CFG_QSGMII_ENA BIT(0)
+
+#define HSIO_HW_QSGMII_CFG_SHYST_DIS BIT(3)
+#define HSIO_HW_QSGMII_CFG_E_DET_ENA BIT(2)
+#define HSIO_HW_QSGMII_CFG_USE_I1_ENA BIT(1)
+#define HSIO_HW_QSGMII_CFG_FLIP_LANES BIT(0)
+
+#define HSIO_HW_QSGMII_STAT_DELAY_VAR_X200PS(x) (((x) << 1) & GENMASK(6, 1))
+#define HSIO_HW_QSGMII_STAT_DELAY_VAR_X200PS_M GENMASK(6, 1)
+#define HSIO_HW_QSGMII_STAT_DELAY_VAR_X200PS_X(x) (((x) & GENMASK(6, 1)) >> 1)
+#define HSIO_HW_QSGMII_STAT_SYNC BIT(0)
+
+#define HSIO_CLK_CFG_CLKDIV_PHY(x) (((x) << 1) & GENMASK(8, 1))
+#define HSIO_CLK_CFG_CLKDIV_PHY_M GENMASK(8, 1)
+#define HSIO_CLK_CFG_CLKDIV_PHY_X(x) (((x) & GENMASK(8, 1)) >> 1)
+#define HSIO_CLK_CFG_CLKDIV_PHY_DIS BIT(0)
+
+#define HSIO_TEMP_SENSOR_CTRL_FORCE_TEMP_RD BIT(5)
+#define HSIO_TEMP_SENSOR_CTRL_FORCE_RUN BIT(4)
+#define HSIO_TEMP_SENSOR_CTRL_FORCE_NO_RST BIT(3)
+#define HSIO_TEMP_SENSOR_CTRL_FORCE_POWER_UP BIT(2)
+#define HSIO_TEMP_SENSOR_CTRL_FORCE_CLK BIT(1)
+#define HSIO_TEMP_SENSOR_CTRL_SAMPLE_ENA BIT(0)
+
+#define HSIO_TEMP_SENSOR_CFG_RUN_WID(x) (((x) << 8) & GENMASK(15, 8))
+#define HSIO_TEMP_SENSOR_CFG_RUN_WID_M GENMASK(15, 8)
+#define HSIO_TEMP_SENSOR_CFG_RUN_WID_X(x) (((x) & GENMASK(15, 8)) >> 8)
+#define HSIO_TEMP_SENSOR_CFG_SAMPLE_PER(x) ((x) & GENMASK(7, 0))
+#define HSIO_TEMP_SENSOR_CFG_SAMPLE_PER_M GENMASK(7, 0)
+
+#define HSIO_TEMP_SENSOR_STAT_TEMP_VALID BIT(8)
+#define HSIO_TEMP_SENSOR_STAT_TEMP(x) ((x) & GENMASK(7, 0))
+#define HSIO_TEMP_SENSOR_STAT_TEMP_M GENMASK(7, 0)
+
+#endif
--
git-series 0.9.1
^ permalink raw reply related
* [PATCH net-next 03/10] net: mscc: ocelot: get HSIO regmap from syscon
From: Quentin Schulz @ 2018-07-30 12:43 UTC (permalink / raw)
To: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, davem
Cc: kishon, andrew, f.fainelli, linux-mips, devicetree, linux-kernel,
netdev, allan.nielsen, thomas.petazzoni, Quentin Schulz
In-Reply-To: <cover.aa759035f6eefdd0bb2a5ae335dab5bd5399bd46.1532954208.git-series.quentin.schulz@bootlin.com>
HSIO address space was moved to a syscon, hence we need to get the
regmap of this address space from there and no more from the device
node.
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
drivers/net/ethernet/mscc/ocelot_board.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 26bb3b1..b7d755b 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -9,6 +9,7 @@
#include <linux/netdevice.h>
#include <linux/of_mdio.h>
#include <linux/of_platform.h>
+#include <linux/mfd/syscon.h>
#include <linux/skbuff.h>
#include "ocelot.h"
@@ -162,6 +163,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct device_node *ports, *portnp;
struct ocelot *ocelot;
+ struct regmap *hsio;
u32 val;
struct {
@@ -173,7 +175,6 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
{ QSYS, "qsys" },
{ ANA, "ana" },
{ QS, "qs" },
- { HSIO, "hsio" },
};
if (!np && !pdev->dev.platform_data)
@@ -196,6 +197,14 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
ocelot->targets[res[i].id] = target;
}
+ hsio = syscon_regmap_lookup_by_compatible("mscc,ocelot-hsio");
+ if (IS_ERR(hsio)) {
+ dev_err(&pdev->dev, "missing hsio syscon\n");
+ return PTR_ERR(hsio);
+ }
+
+ ocelot->targets[HSIO] = hsio;
+
err = ocelot_chip_init(ocelot);
if (err)
return err;
--
git-series 0.9.1
^ permalink raw reply related
* [PATCH net-next 02/10] dt-bindings: net: ocelot: remove hsio from the list of register address spaces
From: Quentin Schulz @ 2018-07-30 12:43 UTC (permalink / raw)
To: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, davem
Cc: kishon, andrew, f.fainelli, linux-mips, devicetree, linux-kernel,
netdev, allan.nielsen, thomas.petazzoni, Quentin Schulz
In-Reply-To: <cover.aa759035f6eefdd0bb2a5ae335dab5bd5399bd46.1532954208.git-series.quentin.schulz@bootlin.com>
HSIO register address space should be handled outside of the MAC
controller as there are some registers for PLL5 configuring,
SerDes/switch port muxing and a thermal sensor IP, so let's remove it.
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
Documentation/devicetree/bindings/mips/mscc.txt | 16 ++++++++++++-
Documentation/devicetree/bindings/net/mscc-ocelot.txt | 9 ++-----
2 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/mips/mscc.txt b/Documentation/devicetree/bindings/mips/mscc.txt
index ae15ec3..bc817e9 100644
--- a/Documentation/devicetree/bindings/mips/mscc.txt
+++ b/Documentation/devicetree/bindings/mips/mscc.txt
@@ -41,3 +41,19 @@ Example:
compatible = "mscc,ocelot-cpu-syscon", "syscon";
reg = <0x70000000 0x2c>;
};
+
+o HSIO regs:
+
+The SoC has a few registers (HSIO) handling miscellaneous functionalities:
+configuration and status of PLL5, RCOMP, SyncE, SerDes configurations and
+status, SerDes muxing and a thermal sensor.
+
+Required properties:
+- compatible: Should be "mscc,ocelot-hsio", "syscon", "simple-mfd"
+- reg : Should contain registers location and length
+
+Example:
+ syscon@10d0000 {
+ compatible = "mscc,ocelot-hsio", "syscon", "simple-mfd";
+ reg = <0x10d0000 0x10000>;
+ };
diff --git a/Documentation/devicetree/bindings/net/mscc-ocelot.txt b/Documentation/devicetree/bindings/net/mscc-ocelot.txt
index 0a84711..9e5c17d 100644
--- a/Documentation/devicetree/bindings/net/mscc-ocelot.txt
+++ b/Documentation/devicetree/bindings/net/mscc-ocelot.txt
@@ -12,7 +12,6 @@ Required properties:
- "sys"
- "rew"
- "qs"
- - "hsio"
- "qsys"
- "ana"
- "portX" with X from 0 to the number of last port index available on that
@@ -45,7 +44,6 @@ Example:
reg = <0x1010000 0x10000>,
<0x1030000 0x10000>,
<0x1080000 0x100>,
- <0x10d0000 0x10000>,
<0x11e0000 0x100>,
<0x11f0000 0x100>,
<0x1200000 0x100>,
@@ -59,10 +57,9 @@ Example:
<0x1280000 0x100>,
<0x1800000 0x80000>,
<0x1880000 0x10000>;
- reg-names = "sys", "rew", "qs", "hsio", "port0",
- "port1", "port2", "port3", "port4", "port5",
- "port6", "port7", "port8", "port9", "port10",
- "qsys", "ana";
+ reg-names = "sys", "rew", "qs", "port0", "port1", "port2",
+ "port3", "port4", "port5", "port6", "port7",
+ "port8", "port9", "port10", "qsys", "ana";
interrupts = <21 22>;
interrupt-names = "xtr", "inj";
--
git-series 0.9.1
^ permalink raw reply related
* [PATCH net-next 01/10] MIPS: mscc: ocelot: make HSIO registers address range a syscon
From: Quentin Schulz @ 2018-07-30 12:43 UTC (permalink / raw)
To: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, davem
Cc: kishon, andrew, f.fainelli, linux-mips, devicetree, linux-kernel,
netdev, allan.nielsen, thomas.petazzoni, Quentin Schulz
In-Reply-To: <cover.aa759035f6eefdd0bb2a5ae335dab5bd5399bd46.1532954208.git-series.quentin.schulz@bootlin.com>
HSIO contains registers for PLL5 configuration, SerDes/switch port
muxing and a thermal sensor, hence we can't keep it in the switch DT
node.
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
arch/mips/boot/dts/mscc/ocelot.dtsi | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/arch/mips/boot/dts/mscc/ocelot.dtsi b/arch/mips/boot/dts/mscc/ocelot.dtsi
index afe8fc9..c51663a 100644
--- a/arch/mips/boot/dts/mscc/ocelot.dtsi
+++ b/arch/mips/boot/dts/mscc/ocelot.dtsi
@@ -96,7 +96,6 @@
reg = <0x1010000 0x10000>,
<0x1030000 0x10000>,
<0x1080000 0x100>,
- <0x10d0000 0x10000>,
<0x11e0000 0x100>,
<0x11f0000 0x100>,
<0x1200000 0x100>,
@@ -110,10 +109,10 @@
<0x1280000 0x100>,
<0x1800000 0x80000>,
<0x1880000 0x10000>;
- reg-names = "sys", "rew", "qs", "hsio", "port0",
- "port1", "port2", "port3", "port4", "port5",
- "port6", "port7", "port8", "port9", "port10",
- "qsys", "ana";
+ reg-names = "sys", "rew", "qs", "port0", "port1",
+ "port2", "port3", "port4", "port5", "port6",
+ "port7", "port8", "port9", "port10", "qsys",
+ "ana";
interrupts = <21 22>;
interrupt-names = "xtr", "inj";
@@ -220,5 +219,10 @@
pinctrl-0 = <&miim1>;
status = "disabled";
};
+
+ hsio: syscon@10d0000 {
+ compatible = "mscc,ocelot-hsio", "syscon", "simple-mfd";
+ reg = <0x10d0000 0x10000>;
+ };
};
};
--
git-series 0.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox