Skip to content

Commit 3f1ac7a

Browse files
David Decotignydavem330
David Decotigny
authored andcommitted
net: ethtool: add new ETHTOOL_xLINKSETTINGS API
This patch defines a new ETHTOOL_GLINKSETTINGS/SLINKSETTINGS API, handled by the new get_link_ksettings/set_link_ksettings callbacks. This API provides support for most legacy ethtool_cmd fields, adds support for larger link mode masks (up to 4064 bits, variable length), and removes ethtool_cmd deprecated fields (transceiver/maxrxpkt/maxtxpkt). This API is deprecating the legacy ETHTOOL_GSET/SSET API and provides the following backward compatibility properties: - legacy ethtool with legacy drivers: no change, still using the get_settings/set_settings callbacks. - legacy ethtool with new get/set_link_ksettings drivers: the new driver callbacks are used, data internally converted to legacy ethtool_cmd. ETHTOOL_GSET will return only the 1st 32b of each link mode mask. ETHTOOL_SSET will fail if user tries to set the ethtool_cmd deprecated fields to non-0 (transceiver/maxrxpkt/maxtxpkt). A kernel warning is logged if driver sets higher bits. - future ethtool with legacy drivers: no change, still using the get_settings/set_settings callbacks, internally converted to new data structure. Deprecated fields (transceiver/maxrxpkt/maxtxpkt) will be ignored and seen as 0 from user space. Note that that "future" ethtool tool will not allow changes to these deprecated fields. - future ethtool with new drivers: direct call to the new callbacks. By "future" ethtool, what is meant is: - query: first try ETHTOOL_GLINKSETTINGS, and revert to ETHTOOL_GSET if fails - set: query first and remember which of ETHTOOL_GLINKSETTINGS or ETHTOOL_GSET was successful + if ETHTOOL_GLINKSETTINGS was successful, then change config with ETHTOOL_SLINKSETTINGS. A failure there is final (do not try ETHTOOL_SSET). + otherwise ETHTOOL_GSET was successful, change config with ETHTOOL_SSET. A failure there is final (do not try ETHTOOL_SLINKSETTINGS). The interaction user/kernel via the new API requires a small ETHTOOL_GLINKSETTINGS handshake first to agree on the length of the link mode bitmaps. If kernel doesn't agree with user, it returns the bitmap length it is expecting from user as a negative length (and cmd field is 0). When kernel and user agree, kernel returns valid info in all fields (ie. link mode length > 0 and cmd is ETHTOOL_GLINKSETTINGS). Data structure crossing user/kernel boundary is 32/64-bit agnostic. Converted internally to a legal kernel bitmap. The internal __ethtool_get_settings kernel helper will gradually be replaced by __ethtool_get_link_ksettings by the time the first "link_settings" drivers start to appear. So this patch doesn't change it, it will be removed before it needs to be changed. Signed-off-by: David Decotigny <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4813333 commit 3f1ac7a

File tree

3 files changed

+786
-80
lines changed

3 files changed

+786
-80
lines changed

include/linux/ethtool.h

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#ifndef _LINUX_ETHTOOL_H
1313
#define _LINUX_ETHTOOL_H
1414

15+
#include <linux/bitmap.h>
1516
#include <linux/compat.h>
1617
#include <uapi/linux/ethtool.h>
1718

@@ -40,9 +41,6 @@ struct compat_ethtool_rxnfc {
4041

4142
#include <linux/rculist.h>
4243

43-
extern int __ethtool_get_settings(struct net_device *dev,
44-
struct ethtool_cmd *cmd);
45-
4644
/**
4745
* enum ethtool_phys_id_state - indicator state for physical identification
4846
* @ETHTOOL_ID_INACTIVE: Physical ID indicator should be deactivated
@@ -97,13 +95,74 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
9795
return index % n_rx_rings;
9896
}
9997

98+
/* number of link mode bits/ulongs handled internally by kernel */
99+
#define __ETHTOOL_LINK_MODE_MASK_NBITS \
100+
(__ETHTOOL_LINK_MODE_LAST + 1)
101+
102+
/* declare a link mode bitmap */
103+
#define __ETHTOOL_DECLARE_LINK_MODE_MASK(name) \
104+
DECLARE_BITMAP(name, __ETHTOOL_LINK_MODE_MASK_NBITS)
105+
106+
/* drivers must ignore base.cmd and base.link_mode_masks_nwords
107+
* fields, but they are allowed to overwrite them (will be ignored).
108+
*/
109+
struct ethtool_link_ksettings {
110+
struct ethtool_link_settings base;
111+
struct {
112+
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
113+
__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
114+
__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising);
115+
} link_modes;
116+
};
117+
118+
/**
119+
* ethtool_link_ksettings_zero_link_mode - clear link_ksettings link mode mask
120+
* @ptr : pointer to struct ethtool_link_ksettings
121+
* @name : one of supported/advertising/lp_advertising
122+
*/
123+
#define ethtool_link_ksettings_zero_link_mode(ptr, name) \
124+
bitmap_zero((ptr)->link_modes.name, __ETHTOOL_LINK_MODE_MASK_NBITS)
125+
126+
/**
127+
* ethtool_link_ksettings_add_link_mode - set bit in link_ksettings
128+
* link mode mask
129+
* @ptr : pointer to struct ethtool_link_ksettings
130+
* @name : one of supported/advertising/lp_advertising
131+
* @mode : one of the ETHTOOL_LINK_MODE_*_BIT
132+
* (not atomic, no bound checking)
133+
*/
134+
#define ethtool_link_ksettings_add_link_mode(ptr, name, mode) \
135+
__set_bit(ETHTOOL_LINK_MODE_ ## mode ## _BIT, (ptr)->link_modes.name)
136+
137+
/**
138+
* ethtool_link_ksettings_test_link_mode - test bit in ksettings link mode mask
139+
* @ptr : pointer to struct ethtool_link_ksettings
140+
* @name : one of supported/advertising/lp_advertising
141+
* @mode : one of the ETHTOOL_LINK_MODE_*_BIT
142+
* (not atomic, no bound checking)
143+
*
144+
* Returns true/false.
145+
*/
146+
#define ethtool_link_ksettings_test_link_mode(ptr, name, mode) \
147+
test_bit(ETHTOOL_LINK_MODE_ ## mode ## _BIT, (ptr)->link_modes.name)
148+
149+
extern int
150+
__ethtool_get_link_ksettings(struct net_device *dev,
151+
struct ethtool_link_ksettings *link_ksettings);
152+
153+
/* DEPRECATED, use __ethtool_get_link_ksettings */
154+
extern int __ethtool_get_settings(struct net_device *dev,
155+
struct ethtool_cmd *cmd);
156+
100157
/**
101158
* struct ethtool_ops - optional netdev operations
102-
* @get_settings: Get various device settings including Ethernet link
159+
* @get_settings: DEPRECATED, use %get_link_ksettings/%set_link_ksettings
160+
* API. Get various device settings including Ethernet link
103161
* settings. The @cmd parameter is expected to have been cleared
104-
* before get_settings is called. Returns a negative error code or
105-
* zero.
106-
* @set_settings: Set various device settings including Ethernet link
162+
* before get_settings is called. Returns a negative error code
163+
* or zero.
164+
* @set_settings: DEPRECATED, use %get_link_ksettings/%set_link_ksettings
165+
* API. Set various device settings including Ethernet link
107166
* settings. Returns a negative error code or zero.
108167
* @get_drvinfo: Report driver/device information. Should only set the
109168
* @driver, @version, @fw_version and @bus_info fields. If not
@@ -211,6 +270,19 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
211270
* a TX queue has this number, return -EINVAL. If only a RX queue or a TX
212271
* queue has this number, ignore the inapplicable fields.
213272
* Returns a negative error code or zero.
273+
* @get_link_ksettings: When defined, takes precedence over the
274+
* %get_settings method. Get various device settings
275+
* including Ethernet link settings. The %cmd and
276+
* %link_mode_masks_nwords fields should be ignored (use
277+
* %__ETHTOOL_LINK_MODE_MASK_NBITS instead of the latter), any
278+
* change to them will be overwritten by kernel. Returns a
279+
* negative error code or zero.
280+
* @set_link_ksettings: When defined, takes precedence over the
281+
* %set_settings method. Set various device settings including
282+
* Ethernet link settings. The %cmd and %link_mode_masks_nwords
283+
* fields should be ignored (use %__ETHTOOL_LINK_MODE_MASK_NBITS
284+
* instead of the latter), any change to them will be overwritten
285+
* by kernel. Returns a negative error code or zero.
214286
*
215287
* All operations are optional (i.e. the function pointer may be set
216288
* to %NULL) and callers must take this into account. Callers must
@@ -293,6 +365,9 @@ struct ethtool_ops {
293365
struct ethtool_coalesce *);
294366
int (*set_per_queue_coalesce)(struct net_device *, u32,
295367
struct ethtool_coalesce *);
296-
368+
int (*get_link_ksettings)(struct net_device *,
369+
struct ethtool_link_ksettings *);
370+
int (*set_link_ksettings)(struct net_device *,
371+
const struct ethtool_link_ksettings *);
297372
};
298373
#endif /* _LINUX_ETHTOOL_H */

0 commit comments

Comments
 (0)