From e20b5b61a36bd5b80eea064c0f2e73285dbe0d3b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 1 Apr 2011 22:52:34 +0100 Subject: ethtool: Convert struct ethtool_ops comment to kernel-doc format Signed-off-by: Ben Hutchings --- include/linux/ethtool.h | 80 ++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 45 deletions(-) (limited to 'include/linux/ethtool.h') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c8fcbdd2b0e7..ab12f84c17bd 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -683,63 +683,53 @@ void ethtool_ntuple_flush(struct net_device *dev); bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); /** - * ðtool_ops - Alter and report network device settings - * get_settings: Get device-specific settings - * set_settings: Set device-specific settings - * get_drvinfo: Report driver information - * get_regs: Get device registers - * get_wol: Report whether Wake-on-Lan is enabled - * set_wol: Turn Wake-on-Lan on or off - * get_msglevel: Report driver message level - * set_msglevel: Set driver message level - * nway_reset: Restart autonegotiation - * get_link: Get link status - * get_eeprom: Read data from the device EEPROM - * set_eeprom: Write data to the device EEPROM - * get_coalesce: Get interrupt coalescing parameters - * set_coalesce: Set interrupt coalescing parameters - * get_ringparam: Report ring sizes - * set_ringparam: Set ring sizes - * get_pauseparam: Report pause parameters - * set_pauseparam: Set pause parameters - * get_rx_csum: Report whether receive checksums are turned on or off - * set_rx_csum: Turn receive checksum on or off - * get_tx_csum: Report whether transmit checksums are turned on or off - * set_tx_csum: Turn transmit checksums on or off - * get_sg: Report whether scatter-gather is enabled - * set_sg: Turn scatter-gather on or off - * get_tso: Report whether TCP segmentation offload is enabled - * set_tso: Turn TCP segmentation offload on or off - * get_ufo: Report whether UDP fragmentation offload is enabled - * set_ufo: Turn UDP fragmentation offload on or off - * self_test: Run specified self-tests - * get_strings: Return a set of strings that describe the requested objects - * phys_id: Identify the device - * get_stats: Return statistics about the device - * get_flags: get 32-bit flags bitmap - * set_flags: set 32-bit flags bitmap - * - * Description: - * - * get_settings: + * struct ethtool_ops - Alter and report network device settings + * @get_settings: Get device-specific settings. * @get_settings is passed an ðtool_cmd to fill in. It returns * an negative errno or zero. - * - * set_settings: + * @set_settings: Set device-specific settings. * @set_settings is passed an ðtool_cmd and should attempt to set * all the settings this device supports. It may return an error value * if something goes wrong (otherwise 0). - * - * get_eeprom: + * @get_drvinfo: Report driver information + * @get_regs: Get device registers + * @get_wol: Report whether Wake-on-Lan is enabled + * @set_wol: Turn Wake-on-Lan on or off + * @get_msglevel: Report driver message level + * @set_msglevel: Set driver message level + * @nway_reset: Restart autonegotiation + * @get_link: Get link status + * @get_eeprom: Read data from the device EEPROM. * Should fill in the magic field. Don't need to check len for zero * or wraparound. Fill in the data argument with the eeprom values * from offset to offset + len. Update len to the amount read. * Returns an error or zero. - * - * set_eeprom: + * @set_eeprom: Write data to the device EEPROM. * Should validate the magic field. Don't need to check len for zero * or wraparound. Update len to the amount written. Returns an error * or zero. + * @get_coalesce: Get interrupt coalescing parameters + * @set_coalesce: Set interrupt coalescing parameters + * @get_ringparam: Report ring sizes + * @set_ringparam: Set ring sizes + * @get_pauseparam: Report pause parameters + * @set_pauseparam: Set pause parameters + * @get_rx_csum: Report whether receive checksums are turned on or off + * @set_rx_csum: Turn receive checksum on or off + * @get_tx_csum: Report whether transmit checksums are turned on or off + * @set_tx_csum: Turn transmit checksums on or off + * @get_sg: Report whether scatter-gather is enabled + * @set_sg: Turn scatter-gather on or off + * @get_tso: Report whether TCP segmentation offload is enabled + * @set_tso: Turn TCP segmentation offload on or off + * @get_ufo: Report whether UDP fragmentation offload is enabled + * @set_ufo: Turn UDP fragmentation offload on or off + * @self_test: Run specified self-tests + * @get_strings: Return a set of strings that describe the requested objects + * @phys_id: Identify the device + * @get_stats: Return statistics about the device + * @get_flags: get 32-bit flags bitmap + * @set_flags: set 32-bit flags bitmap */ struct ethtool_ops { int (*get_settings)(struct net_device *, struct ethtool_cmd *); -- cgit v1.2.3 From 8717d07b1143e0f150921f5bd7cfe7af579a995a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 1 Apr 2011 23:57:41 +0100 Subject: ethtool: Fill out and update comment for struct ethtool_ops Briefly document all operations (except get_rx_ntuple), including whether they may return an error code and whether they are deprecated. Also mention some things that should be handled by the ethtool core rather than by drivers. Briefly document general requirements for callers. Signed-off-by: Ben Hutchings --- include/linux/ethtool.h | 124 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 93 insertions(+), 31 deletions(-) (limited to 'include/linux/ethtool.h') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index ab12f84c17bd..ead7dcb1bf1e 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -683,22 +683,28 @@ void ethtool_ntuple_flush(struct net_device *dev); bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); /** - * struct ethtool_ops - Alter and report network device settings - * @get_settings: Get device-specific settings. - * @get_settings is passed an ðtool_cmd to fill in. It returns - * an negative errno or zero. - * @set_settings: Set device-specific settings. - * @set_settings is passed an ðtool_cmd and should attempt to set - * all the settings this device supports. It may return an error value - * if something goes wrong (otherwise 0). - * @get_drvinfo: Report driver information + * struct ethtool_ops - optional netdev operations + * @get_settings: Get various device settings including Ethernet link + * settings. Returns a negative error code or zero. + * @set_settings: Set various device settings including Ethernet link + * settings. Returns a negative error code or zero. + * @get_drvinfo: Report driver/device information. Should only set the + * @driver, @version, @fw_version and @bus_info fields. If not + * implemented, the @driver and @bus_info fields will be filled in + * according to the netdev's parent device. + * @get_regs_len: Get buffer length required for @get_regs * @get_regs: Get device registers * @get_wol: Report whether Wake-on-Lan is enabled - * @set_wol: Turn Wake-on-Lan on or off - * @get_msglevel: Report driver message level + * @set_wol: Turn Wake-on-Lan on or off. Returns a negative error code + * or zero. + * @get_msglevel: Report driver message level. This should be the value + * of the @msg_enable field used by netif logging functions. * @set_msglevel: Set driver message level - * @nway_reset: Restart autonegotiation - * @get_link: Get link status + * @nway_reset: Restart autonegotiation. Returns a negative error code + * or zero. + * @get_link: Report whether physical link is up. Will only be called if + * the netdev is up. Should usually be set to ethtool_op_get_link(), + * which uses netif_carrier_ok(). * @get_eeprom: Read data from the device EEPROM. * Should fill in the magic field. Don't need to check len for zero * or wraparound. Fill in the data argument with the eeprom values @@ -708,28 +714,84 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * Should validate the magic field. Don't need to check len for zero * or wraparound. Update len to the amount written. Returns an error * or zero. - * @get_coalesce: Get interrupt coalescing parameters - * @set_coalesce: Set interrupt coalescing parameters + * @get_coalesce: Get interrupt coalescing parameters. Returns a negative + * error code or zero. + * @set_coalesce: Set interrupt coalescing parameters. Returns a negative + * error code or zero. * @get_ringparam: Report ring sizes - * @set_ringparam: Set ring sizes + * @set_ringparam: Set ring sizes. Returns a negative error code or zero. * @get_pauseparam: Report pause parameters - * @set_pauseparam: Set pause parameters - * @get_rx_csum: Report whether receive checksums are turned on or off - * @set_rx_csum: Turn receive checksum on or off - * @get_tx_csum: Report whether transmit checksums are turned on or off - * @set_tx_csum: Turn transmit checksums on or off - * @get_sg: Report whether scatter-gather is enabled - * @set_sg: Turn scatter-gather on or off - * @get_tso: Report whether TCP segmentation offload is enabled - * @set_tso: Turn TCP segmentation offload on or off - * @get_ufo: Report whether UDP fragmentation offload is enabled - * @set_ufo: Turn UDP fragmentation offload on or off + * @set_pauseparam: Set pause parameters. Returns a negative error code + * or zero. + * @get_rx_csum: Deprecated in favour of the netdev feature %NETIF_F_RXCSUM. + * Report whether receive checksums are turned on or off. + * @set_rx_csum: Deprecated in favour of generic netdev features. Turn + * receive checksum on or off. Returns a negative error code or zero. + * @get_tx_csum: Deprecated as redundant. Report whether transmit checksums + * are turned on or off. + * @set_tx_csum: Deprecated in favour of generic netdev features. Turn + * transmit checksums on or off. Returns a egative error code or zero. + * @get_sg: Deprecated as redundant. Report whether scatter-gather is + * enabled. + * @set_sg: Deprecated in favour of generic netdev features. Turn + * scatter-gather on or off. Returns a negative error code or zero. + * @get_tso: Deprecated as redundant. Report whether TCP segmentation + * offload is enabled. + * @set_tso: Deprecated in favour of generic netdev features. Turn TCP + * segmentation offload on or off. Returns a negative error code or zero. * @self_test: Run specified self-tests * @get_strings: Return a set of strings that describe the requested objects - * @phys_id: Identify the device - * @get_stats: Return statistics about the device - * @get_flags: get 32-bit flags bitmap - * @set_flags: set 32-bit flags bitmap + * @phys_id: Identify the physical device, e.g. by flashing an LED + * attached to it until interrupted by a signal or the given time + * (in seconds) elapses. If the given time is zero, use a default + * time limit. Returns a negative error code or zero. Being + * interrupted by a signal is not an error. + * @get_ethtool_stats: Return extended statistics about the device. + * This is only useful if the device maintains statistics not + * included in &struct rtnl_link_stats64. + * @begin: Function to be called before any other operation. Returns a + * negative error code or zero. + * @complete: Function to be called after any other operation except + * @begin. Will be called even if the other operation failed. + * @get_ufo: Deprecated as redundant. Report whether UDP fragmentation + * offload is enabled. + * @set_ufo: Deprecated in favour of generic netdev features. Turn UDP + * fragmentation offload on or off. Returns a negative error code or zero. + * @get_flags: Deprecated as redundant. Report features included in + * &enum ethtool_flags that are enabled. + * @set_flags: Deprecated in favour of generic netdev features. Turn + * features included in &enum ethtool_flags on or off. Returns a + * negative error code or zero. + * @get_priv_flags: Report driver-specific feature flags. + * @set_priv_flags: Set driver-specific feature flags. Returns a negative + * error code or zero. + * @get_sset_count: Get number of strings that @get_strings will write. + * @get_rxnfc: Get RX flow classification rules. Returns a negative + * error code or zero. + * @set_rxnfc: Set RX flow classification rules. Returns a negative + * error code or zero. + * @flash_device: Write a firmware image to device's flash memory. + * Returns a negative error code or zero. + * @reset: Reset (part of) the device, as specified by a bitmask of + * flags from &enum ethtool_reset_flags. Returns a negative + * error code or zero. + * @set_rx_ntuple: Set an RX n-tuple rule. Returns a negative error code + * or zero. + * @get_rx_ntuple: Deprecated. + * @get_rxfh_indir: Get the contents of the RX flow hash indirection table. + * Returns a negative error code or zero. + * @set_rxfh_indir: Set the contents of the RX flow hash indirection table. + * Returns a negative error code or zero. + * + * All operations are optional (i.e. the function pointer may be set + * to %NULL) and callers must take this into account. Callers must + * hold the RTNL, except that for @get_drvinfo the caller may or may + * not hold the RTNL. + * + * See the structures used by these operations for further documentation. + * + * See &struct net_device and &struct net_device_ops for documentation + * of the generic netdev features interface. */ struct ethtool_ops { int (*get_settings)(struct net_device *, struct ethtool_cmd *); -- cgit v1.2.3 From 68f512f21a64c9b264df6c61a9333e7890faf74b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 2 Apr 2011 00:35:15 +0100 Subject: ethtool: Change ETHTOOL_PHYS_ID implementation to allow dropping RTNL The ethtool ETHTOOL_PHYS_ID command runs for an arbitrarily long period of time, holding the RTNL lock. This blocks routing updates, device enumeration, and various important operations that one might want to keep running while hunting for the flashing LED. We need to drop the RTNL lock during this operation, but currently the core implementation is a thin wrapper around a driver operation and drivers may well depend upon holding the lock. Define a new driver operation 'set_phys_id' with an argument that sets the ID indicator on/off/inactive/active (the last optional, for any driver or firmware that prefers to handle blinking asynchronously). When this is defined, the ethtool core drops the lock while waiting and only acquires it around calls to this operation. Deprecate the 'phys_id' operation in favour of this. It can be removed once all in-tree drivers are converted. Signed-off-by: Ben Hutchings --- include/linux/ethtool.h | 30 ++++++++++++++++++++++++++- net/core/ethtool.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 3 deletions(-) (limited to 'include/linux/ethtool.h') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index ead7dcb1bf1e..c04d1316d221 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -663,6 +663,22 @@ struct ethtool_rx_ntuple_list { unsigned int count; }; +/** + * enum ethtool_phys_id_state - indicator state for physical identification + * @ETHTOOL_ID_INACTIVE: Physical ID indicator should be deactivated + * @ETHTOOL_ID_ACTIVE: Physical ID indicator should be activated + * @ETHTOOL_ID_ON: LED should be turned on (used iff %ETHTOOL_ID_ACTIVE + * is not supported) + * @ETHTOOL_ID_OFF: LED should be turned off (used iff %ETHTOOL_ID_ACTIVE + * is not supported) + */ +enum ethtool_phys_id_state { + ETHTOOL_ID_INACTIVE, + ETHTOOL_ID_ACTIVE, + ETHTOOL_ID_ON, + ETHTOOL_ID_OFF +}; + struct net_device; /* Some generic methods drivers may use in their ethtool_ops */ @@ -741,7 +757,18 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * segmentation offload on or off. Returns a negative error code or zero. * @self_test: Run specified self-tests * @get_strings: Return a set of strings that describe the requested objects - * @phys_id: Identify the physical device, e.g. by flashing an LED + * @set_phys_id: Identify the physical devices, e.g. by flashing an LED + * attached to it. The implementation may update the indicator + * asynchronously or synchronously, but in either case it must return + * quickly. It is initially called with the argument %ETHTOOL_ID_ACTIVE, + * and must either activate asynchronous updates or return -%EINVAL. + * If it returns -%EINVAL then it will be called again at intervals with + * argument %ETHTOOL_ID_ON or %ETHTOOL_ID_OFF and should set the state of + * the indicator accordingly. Finally, it is called with the argument + * %ETHTOOL_ID_INACTIVE and must deactivate the indicator. Returns a + * negative error code or zero. + * @phys_id: Deprecated in favour of @set_phys_id. + * Identify the physical device, e.g. by flashing an LED * attached to it until interrupted by a signal or the given time * (in seconds) elapses. If the given time is zero, use a default * time limit. Returns a negative error code or zero. Being @@ -830,6 +857,7 @@ struct ethtool_ops { int (*set_tso)(struct net_device *, u32); void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); void (*get_strings)(struct net_device *, u32 stringset, u8 *); + int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state); int (*phys_id)(struct net_device *, u32); void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 74ead9eca126..1c95f0fb8b3a 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include /* * Some useful ethtool_ops methods that're device independent. @@ -1618,14 +1620,63 @@ out: static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) { struct ethtool_value id; + static bool busy; + int rc; - if (!dev->ethtool_ops->phys_id) + if (!dev->ethtool_ops->set_phys_id && !dev->ethtool_ops->phys_id) return -EOPNOTSUPP; + if (busy) + return -EBUSY; + if (copy_from_user(&id, useraddr, sizeof(id))) return -EFAULT; - return dev->ethtool_ops->phys_id(dev, id.data); + if (!dev->ethtool_ops->set_phys_id) + /* Do it the old way */ + return dev->ethtool_ops->phys_id(dev, id.data); + + rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ACTIVE); + if (rc && rc != -EINVAL) + return rc; + + /* Drop the RTNL lock while waiting, but prevent reentry or + * removal of the device. + */ + busy = true; + dev_hold(dev); + rtnl_unlock(); + + if (rc == 0) { + /* Driver will handle this itself */ + schedule_timeout_interruptible( + id.data ? id.data : MAX_SCHEDULE_TIMEOUT); + } else { + /* Driver expects to be called periodically */ + do { + rtnl_lock(); + rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ON); + rtnl_unlock(); + if (rc) + break; + schedule_timeout_interruptible(HZ / 2); + + rtnl_lock(); + rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_OFF); + rtnl_unlock(); + if (rc) + break; + schedule_timeout_interruptible(HZ / 2); + } while (!signal_pending(current) && + (id.data == 0 || --id.data != 0)); + } + + rtnl_lock(); + dev_put(dev); + busy = false; + + (void)dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_INACTIVE); + return rc; } static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) -- cgit v1.2.3 From 127fe533ae56d7f4e7b5011869870982eba25723 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 8 Apr 2011 18:01:59 +0000 Subject: v3 ethtool: add ntuple flow specifier data to network flow classifier This change is meant to add an ntuple data extensions to the rx network flow classification specifiers. The idea is to allow ntuple to be displayed via the network flow classification interface. The first patch had some left over stuff from the original flow extension flags I had added. That bit is removed in this patch. The second had some left over comments that stated we ignored bits in the masks when we actually match them. This work is based on input from Ben Hutchings. Signed-off-by: Alexander Duyck Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/ethtool.h | 53 +++++++++++++++++++++++++++++-------------------- net/socket.c | 14 ++++++------- 2 files changed, 39 insertions(+), 28 deletions(-) (limited to 'include/linux/ethtool.h') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c04d1316d221..c7eff13d2f34 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -380,27 +380,42 @@ struct ethtool_usrip4_spec { __u8 proto; }; +union ethtool_flow_union { + struct ethtool_tcpip4_spec tcp_ip4_spec; + struct ethtool_tcpip4_spec udp_ip4_spec; + struct ethtool_tcpip4_spec sctp_ip4_spec; + struct ethtool_ah_espip4_spec ah_ip4_spec; + struct ethtool_ah_espip4_spec esp_ip4_spec; + struct ethtool_usrip4_spec usr_ip4_spec; + struct ethhdr ether_spec; + __u8 hdata[60]; +}; + +struct ethtool_flow_ext { + __be16 vlan_etype; + __be16 vlan_tci; + __be32 data[2]; +}; + /** * struct ethtool_rx_flow_spec - specification for RX flow filter * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW * @h_u: Flow fields to match (dependent on @flow_type) - * @m_u: Masks for flow field bits to be ignored + * @h_ext: Additional fields to match + * @m_u: Masks for flow field bits to be matched + * @m_ext: Masks for additional field bits to be matched + * Note, all additional fields must be ignored unless @flow_type + * includes the %FLOW_EXT flag. * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC * if packets should be discarded * @location: Index of filter in hardware table */ struct ethtool_rx_flow_spec { __u32 flow_type; - union { - struct ethtool_tcpip4_spec tcp_ip4_spec; - struct ethtool_tcpip4_spec udp_ip4_spec; - struct ethtool_tcpip4_spec sctp_ip4_spec; - struct ethtool_ah_espip4_spec ah_ip4_spec; - struct ethtool_ah_espip4_spec esp_ip4_spec; - struct ethtool_usrip4_spec usr_ip4_spec; - struct ethhdr ether_spec; - __u8 hdata[72]; - } h_u, m_u; + union ethtool_flow_union h_u; + struct ethtool_flow_ext h_ext; + union ethtool_flow_union m_u; + struct ethtool_flow_ext m_ext; __u64 ring_cookie; __u32 location; }; @@ -458,16 +473,10 @@ struct ethtool_rxnfc { struct compat_ethtool_rx_flow_spec { u32 flow_type; - union { - struct ethtool_tcpip4_spec tcp_ip4_spec; - struct ethtool_tcpip4_spec udp_ip4_spec; - struct ethtool_tcpip4_spec sctp_ip4_spec; - struct ethtool_ah_espip4_spec ah_ip4_spec; - struct ethtool_ah_espip4_spec esp_ip4_spec; - struct ethtool_usrip4_spec usr_ip4_spec; - struct ethhdr ether_spec; - u8 hdata[72]; - } h_u, m_u; + union ethtool_flow_union h_u; + struct ethtool_flow_ext h_ext; + union ethtool_flow_union m_u; + struct ethtool_flow_ext m_ext; compat_u64 ring_cookie; u32 location; }; @@ -1072,6 +1081,8 @@ struct ethtool_ops { #define IPV4_FLOW 0x10 /* hash only */ #define IPV6_FLOW 0x11 /* hash only */ #define ETHER_FLOW 0x12 /* spec only (ether_spec) */ +/* Flag to enable additional fields in struct ethtool_rx_flow_spec */ +#define FLOW_EXT 0x80000000 /* L3-L4 network traffic flow hash options */ #define RXH_L2DA (1 << 1) diff --git a/net/socket.c b/net/socket.c index 5212447c86e7..575c84f2af19 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2643,13 +2643,13 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) return -EFAULT; if (convert_in) { - /* We expect there to be holes between fs.m_u and + /* We expect there to be holes between fs.m_ext and * fs.ring_cookie and at the end of fs, but nowhere else. */ - BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_u) + - sizeof(compat_rxnfc->fs.m_u) != - offsetof(struct ethtool_rxnfc, fs.m_u) + - sizeof(rxnfc->fs.m_u)); + BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) + + sizeof(compat_rxnfc->fs.m_ext) != + offsetof(struct ethtool_rxnfc, fs.m_ext) + + sizeof(rxnfc->fs.m_ext)); BUILD_BUG_ON( offsetof(struct compat_ethtool_rxnfc, fs.location) - offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != @@ -2657,7 +2657,7 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) offsetof(struct ethtool_rxnfc, fs.ring_cookie)); if (copy_in_user(rxnfc, compat_rxnfc, - (void *)(&rxnfc->fs.m_u + 1) - + (void *)(&rxnfc->fs.m_ext + 1) - (void *)rxnfc) || copy_in_user(&rxnfc->fs.ring_cookie, &compat_rxnfc->fs.ring_cookie, @@ -2674,7 +2674,7 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) if (convert_out) { if (copy_in_user(compat_rxnfc, rxnfc, - (const void *)(&rxnfc->fs.m_u + 1) - + (const void *)(&rxnfc->fs.m_ext + 1) - (const void *)rxnfc) || copy_in_user(&compat_rxnfc->fs.ring_cookie, &rxnfc->fs.ring_cookie, -- cgit v1.2.3 From 8b5933c380fc66a6311739f9b36a812383f82141 Mon Sep 17 00:00:00 2001 From: amit salecha Date: Thu, 7 Apr 2011 01:58:42 +0000 Subject: net: ethtool support to configure number of channels Ethtool support to configure RX, TX and other channels. combined field in struct ethtool_channels to reflect set of channel (RX, TX or other). Other channel can be link interrupts, SR-IOV coordination etc. ETHTOOL_GCHANNELS will report max and current number of RX channels, max and current number of TX channels, max and current number of other channel or max and current number of combined channel. Number of channel can be modify upto max number of channel through ETHTOOL_SCHANNELS command. Ben Hutchings: o define 'combined' and 'other' types. Most multiqueue drivers pair up RX and TX queues so that most channels combine RX and TX work. o Please could you use a kernel-doc comment to describe the structure. Signed-off-by: Amit Kumar Salecha Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/ethtool.h | 36 ++++++++++++++++++++++++++++++++++++ net/core/ethtool.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) (limited to 'include/linux/ethtool.h') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 12cfbd0be2ee..ad22a68c2e5d 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -229,6 +229,34 @@ struct ethtool_ringparam { __u32 tx_pending; }; +/** + * struct ethtool_channels - configuring number of network channel + * @cmd: ETHTOOL_{G,S}CHANNELS + * @max_rx: Read only. Maximum number of receive channel the driver support. + * @max_tx: Read only. Maximum number of transmit channel the driver support. + * @max_other: Read only. Maximum number of other channel the driver support. + * @max_combined: Read only. Maximum number of combined channel the driver + * support. Set of queues RX, TX or other. + * @rx_count: Valid values are in the range 1 to the max_rx. + * @tx_count: Valid values are in the range 1 to the max_tx. + * @other_count: Valid values are in the range 1 to the max_other. + * @combined_count: Valid values are in the range 1 to the max_combined. + * + * This can be used to configure RX, TX and other channels. + */ + +struct ethtool_channels { + __u32 cmd; + __u32 max_rx; + __u32 max_tx; + __u32 max_other; + __u32 max_combined; + __u32 rx_count; + __u32 tx_count; + __u32 other_count; + __u32 combined_count; +}; + /* for configuring link flow control parameters */ struct ethtool_pauseparam { __u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ @@ -818,6 +846,9 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * Returns a negative error code or zero. * @set_rxfh_indir: Set the contents of the RX flow hash indirection table. * Returns a negative error code or zero. + * @get_channels: Get number of channels. + * @set_channels: Set number of channels. Returns a negative error code or + * zero. * * All operations are optional (i.e. the function pointer may be set * to %NULL) and callers must take this into account. Callers must @@ -891,6 +922,9 @@ struct ethtool_ops { struct ethtool_rxfh_indir *); int (*set_rxfh_indir)(struct net_device *, const struct ethtool_rxfh_indir *); + void (*get_channels)(struct net_device *, struct ethtool_channels *); + int (*set_channels)(struct net_device *, struct ethtool_channels *); + }; #endif /* __KERNEL__ */ @@ -959,6 +993,8 @@ struct ethtool_ops { #define ETHTOOL_GFEATURES 0x0000003a /* Get device offload settings */ #define ETHTOOL_SFEATURES 0x0000003b /* Change device offload settings */ +#define ETHTOOL_GCHANNELS 0x0000003c /* Get no of channels */ +#define ETHTOOL_SCHANNELS 0x0000003d /* Set no of channels */ /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 43ef09fedd6e..41dee2de13ad 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1446,6 +1446,35 @@ static int ethtool_set_ringparam(struct net_device *dev, void __user *useraddr) return dev->ethtool_ops->set_ringparam(dev, &ringparam); } +static noinline_for_stack int ethtool_get_channels(struct net_device *dev, + void __user *useraddr) +{ + struct ethtool_channels channels = { .cmd = ETHTOOL_GCHANNELS }; + + if (!dev->ethtool_ops->get_channels) + return -EOPNOTSUPP; + + dev->ethtool_ops->get_channels(dev, &channels); + + if (copy_to_user(useraddr, &channels, sizeof(channels))) + return -EFAULT; + return 0; +} + +static noinline_for_stack int ethtool_set_channels(struct net_device *dev, + void __user *useraddr) +{ + struct ethtool_channels channels; + + if (!dev->ethtool_ops->set_channels) + return -EOPNOTSUPP; + + if (copy_from_user(&channels, useraddr, sizeof(channels))) + return -EFAULT; + + return dev->ethtool_ops->set_channels(dev, &channels); +} + static int ethtool_get_pauseparam(struct net_device *dev, void __user *useraddr) { struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; @@ -2007,6 +2036,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_SGRO: rc = ethtool_set_one_feature(dev, useraddr, ethcmd); break; + case ETHTOOL_GCHANNELS: + rc = ethtool_get_channels(dev, useraddr); + break; + case ETHTOOL_SCHANNELS: + rc = ethtool_set_channels(dev, useraddr); + break; default: rc = -EOPNOTSUPP; } -- cgit v1.2.3 From fce55922f5299a04c0a56b170a141fab34f13465 Mon Sep 17 00:00:00 2001 From: "Allan, Bruce W" Date: Wed, 13 Apr 2011 13:09:10 +0000 Subject: ethtool: allow custom interval for physical identification When physical identification of an adapter is done by toggling the mechanism on and off through software utilizing the set_phys_id operation, it is done with a fixed duration for both on and off states. Some drivers may want to set a custom duration for the on/off intervals. This patch changes the API so the return code from the driver's entry point when it is called with ETHTOOL_ID_ACTIVE can specify the frequency at which to cycle the on/off states, and updates the drivers that have already been converted to use the new set_phys_id and use the synchronous method for identifying an adapter. The physical identification frequency set in the updated drivers is based on how it was done prior to the introduction of set_phys_id. Compile tested only. Also fixes a compiler warning in sfc. v2: drivers do not return -EINVAL for ETHOOL_ID_ACTIVE v3: fold patchset into single patch and cleanup per Ben's feedback Signed-off-by: Bruce Allan Cc: Ben Hutchings Cc: Sathya Perla Cc: Subbu Seetharaman Cc: Ajit Khaparde Cc: Michael Chan Cc: Eilon Greenstein Cc: Divy Le Ray Cc: Don Fry Cc: Jon Mason Cc: Solarflare linux maintainers Cc: Steve Hodgson Cc: Stephen Hemminger Cc: Matt Carlson Acked-by: Jon Mason Acked-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/benet/be_ethtool.c | 2 +- drivers/net/bnx2.c | 2 +- drivers/net/bnx2x/bnx2x_ethtool.c | 2 +- drivers/net/cxgb3/cxgb3_main.c | 2 +- drivers/net/ewrk3.c | 2 +- drivers/net/niu.c | 2 +- drivers/net/pcnet32.c | 2 +- drivers/net/s2io.c | 2 +- drivers/net/sfc/ethtool.c | 6 +++--- drivers/net/skge.c | 2 +- drivers/net/sky2.c | 2 +- drivers/net/tg3.c | 2 +- include/linux/ethtool.h | 6 ++++-- net/core/ethtool.c | 31 ++++++++++++++++--------------- 14 files changed, 34 insertions(+), 31 deletions(-) (limited to 'include/linux/ethtool.h') diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 96f5502e0ef7..80226e4801f3 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -516,7 +516,7 @@ be_set_phys_id(struct net_device *netdev, case ETHTOOL_ID_ACTIVE: be_cmd_get_beacon_state(adapter, adapter->hba_port_num, &adapter->beacon_state); - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 0a52079bafef..bf729ee6acbd 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7473,7 +7473,7 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state) bp->leds_save = REG_RD(bp, BNX2_MISC_CFG); REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC); - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE | diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index ad7d91e499f4..0a5e88d6ba2c 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c @@ -2025,7 +2025,7 @@ static int bnx2x_set_phys_id(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: bnx2x_set_led(&bp->link_params, &bp->link_vars, diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 802c7a7c3b25..a087e0691dce 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1757,7 +1757,7 @@ static int set_phys_id(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_OFF: t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, 0); diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index c7ce4438e923..17b6027d8be8 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -1618,7 +1618,7 @@ static int ewrk3_set_phys_id(struct net_device *dev, /* Prevent ISR from twiddling the LED */ lp->led_mask = 0; spin_unlock_irq(&lp->hw_lock); - return -EINVAL; + return 2; /* cycle on/off twice per second */ case ETHTOOL_ID_ON: cr = inb(EWRK3_CR); diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 3fa1e9cdb4a8..ea2272f0f37e 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -7896,7 +7896,7 @@ static int niu_set_phys_id(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: np->orig_led_state = niu_led_state_save(np); - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: niu_force_led(np, 1); diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index e89afb929740..0a1efbae1bc0 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1038,7 +1038,7 @@ static int pcnet32_set_phys_id(struct net_device *dev, for (i = 4; i < 8; i++) lp->save_regs[i - 4] = a->read_bcr(ioaddr, i); spin_unlock_irqrestore(&lp->lock, flags); - return -EINVAL; + return 2; /* cycle on/off twice per second */ case ETHTOOL_ID_ON: case ETHTOOL_ID_OFF: diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 2d5cc6142c04..2302d9743744 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5541,7 +5541,7 @@ static int s2io_ethtool_set_led(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: sp->adapt_ctrl_org = readq(&bar0->gpio_control); - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: s2io_set_led(sp, true); diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 644f7c1d6e7b..5d8468fc5804 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -182,7 +182,7 @@ static int efx_ethtool_phys_id(struct net_device *net_dev, enum ethtool_phys_id_state state) { struct efx_nic *efx = netdev_priv(net_dev); - enum efx_led_mode mode; + enum efx_led_mode mode = EFX_LED_DEFAULT; switch (state) { case ETHTOOL_ID_ON: @@ -194,8 +194,8 @@ static int efx_ethtool_phys_id(struct net_device *net_dev, case ETHTOOL_ID_INACTIVE: mode = EFX_LED_DEFAULT; break; - default: - return -EINVAL; + case ETHTOOL_ID_ACTIVE: + return 1; /* cycle on/off once per second */ } efx->type->set_id_led(efx, mode); diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 310dcbce2519..176d784cbb54 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -753,7 +753,7 @@ static int skge_set_phys_id(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: - return -EINVAL; + return 2; /* cycle on/off twice per second */ case ETHTOOL_ID_ON: skge_led(skge, LED_MODE_TST); diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index a4b8fe564eb0..c8d045114c66 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3813,7 +3813,7 @@ static int sky2_set_phys_id(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_INACTIVE: sky2_led(sky2, MO_LED_NORM); break; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 10fa476fede3..9915734ac3e9 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10384,7 +10384,7 @@ static int tg3_set_phys_id(struct net_device *dev, switch (state) { case ETHTOOL_ID_ACTIVE: - return -EINVAL; + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE | diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index ad22a68c2e5d..9de31274341d 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -798,8 +798,10 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * attached to it. The implementation may update the indicator * asynchronously or synchronously, but in either case it must return * quickly. It is initially called with the argument %ETHTOOL_ID_ACTIVE, - * and must either activate asynchronous updates or return -%EINVAL. - * If it returns -%EINVAL then it will be called again at intervals with + * and must either activate asynchronous updates and return zero, return + * a negative error or return a positive frequency for synchronous + * indication (e.g. 1 for one on/off cycle per second). If it returns + * a frequency then it will be called again at intervals with the * argument %ETHTOOL_ID_ON or %ETHTOOL_ID_OFF and should set the state of * the indicator accordingly. Finally, it is called with the argument * %ETHTOOL_ID_INACTIVE and must deactivate the indicator. Returns a diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 41dee2de13ad..13d79f5a86e5 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1669,7 +1669,7 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) return dev->ethtool_ops->phys_id(dev, id.data); rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ACTIVE); - if (rc && rc != -EINVAL) + if (rc < 0) return rc; /* Drop the RTNL lock while waiting, but prevent reentry or @@ -1684,21 +1684,22 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) schedule_timeout_interruptible( id.data ? (id.data * HZ) : MAX_SCHEDULE_TIMEOUT); } else { - /* Driver expects to be called periodically */ + /* Driver expects to be called at twice the frequency in rc */ + int n = rc * 2, i, interval = HZ / n; + + /* Count down seconds */ do { - rtnl_lock(); - rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ON); - rtnl_unlock(); - if (rc) - break; - schedule_timeout_interruptible(HZ / 2); - - rtnl_lock(); - rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_OFF); - rtnl_unlock(); - if (rc) - break; - schedule_timeout_interruptible(HZ / 2); + /* Count down iterations per second */ + i = n; + do { + rtnl_lock(); + rc = dev->ethtool_ops->set_phys_id(dev, + (i & 1) ? ETHTOOL_ID_OFF : ETHTOOL_ID_ON); + rtnl_unlock(); + if (rc) + break; + schedule_timeout_interruptible(interval); + } while (!signal_pending(current) && --i != 0); } while (!signal_pending(current) && (id.data == 0 || --id.data != 0)); } -- cgit v1.2.3 From 36504605432996590f889e33d47e2d9c581f7569 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:37 +0000 Subject: ethtool: cosmetics: enforce const-ness in ethtool_cmd_speed The 'ep' argument of ethtool_cmd_speed is not altered: advertise it in protoype. +Indentation fix. Also add comments to advise using the ethtool_cmd_speed API to get/set the link speed. Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- include/linux/ethtool.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'include/linux/ethtool.h') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 9de31274341d..7e6e0a89ca26 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -24,7 +24,10 @@ struct ethtool_cmd { __u32 cmd; __u32 supported; /* Features this interface supports */ __u32 advertising; /* Features this interface advertises */ - __u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */ + __u16 speed; /* The forced speed (lower bits) in + * Mbps. Please use + * ethtool_cmd_speed()/_set() to + * access it */ __u8 duplex; /* Duplex, half or full */ __u8 port; /* Which connector port */ __u8 phy_address; @@ -33,7 +36,10 @@ struct ethtool_cmd { __u8 mdio_support; __u32 maxtxpkt; /* Tx pkts before generating tx int */ __u32 maxrxpkt; /* Rx pkts before generating rx int */ - __u16 speed_hi; + __u16 speed_hi; /* The forced speed (upper + * bits) in Mbps. Please use + * ethtool_cmd_speed()/_set() to + * access it */ __u8 eth_tp_mdix; __u8 reserved2; __u32 lp_advertising; /* Features the link partner advertises */ @@ -41,14 +47,14 @@ struct ethtool_cmd { }; static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep, - __u32 speed) + __u32 speed) { ep->speed = (__u16)speed; ep->speed_hi = (__u16)(speed >> 16); } -static inline __u32 ethtool_cmd_speed(struct ethtool_cmd *ep) +static inline __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep) { return (ep->speed_hi << 16) | ep->speed; } -- cgit v1.2.3 From 8ae6daca85c8bbd6a32c382db5e2a2a989f8bed2 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:38 +0000 Subject: ethtool: Call ethtool's get/set_settings callbacks with cleaned data This makes sure that when a driver calls the ethtool's get/set_settings() callback of another driver, the data passed to it is clean. This guarantees that speed_hi will be zeroed correctly if the called callback doesn't explicitely set it: we are sure we don't get a corrupted speed from the underlying driver. We also take care of setting the cmd field appropriately (ETHTOOL_GSET/SSET). This applies to dev_ethtool_get_settings(), which now makes sure it sets up that ethtool command parameter correctly before passing it to drivers. This also means that whoever calls dev_ethtool_get_settings() does not have to clean the ethtool command parameter. This function also becomes an exported symbol instead of an inline. All drivers visible to make allyesconfig under x86_64 have been updated. Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- arch/mips/txx9/generic/setup_tx4939.c | 21 ++++++++------------- drivers/net/e100.c | 2 +- drivers/net/mdio.c | 3 +++ drivers/net/mii.c | 3 +++ drivers/net/pch_gbe/pch_gbe_main.c | 6 +++--- drivers/net/pch_gbe/pch_gbe_phy.c | 2 +- drivers/net/pcnet32.c | 16 ++++++++-------- drivers/net/sfc/mdio_10g.c | 4 ++-- drivers/net/stmmac/stmmac_ethtool.c | 5 ++--- drivers/net/usb/asix.c | 28 +++++++++++++++------------- drivers/net/usb/dm9601.c | 6 +++--- drivers/net/usb/smsc75xx.c | 7 ++++--- drivers/net/usb/smsc95xx.c | 7 ++++--- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 11 +++++++---- drivers/scsi/fcoe/fcoe.c | 11 +++++++---- include/linux/ethtool.h | 4 +++- include/linux/netdevice.h | 9 ++------- include/rdma/ib_addr.h | 13 +++++++------ net/core/dev.c | 24 ++++++++++++++++++++++++ net/core/net-sysfs.c | 24 ++++++++++-------------- 20 files changed, 117 insertions(+), 89 deletions(-) (limited to 'include/linux/ethtool.h') diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c index 3dc19f482959..e9f95dcde379 100644 --- a/arch/mips/txx9/generic/setup_tx4939.c +++ b/arch/mips/txx9/generic/setup_tx4939.c @@ -318,19 +318,15 @@ void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask) } #if defined(CONFIG_TC35815) || defined(CONFIG_TC35815_MODULE) -static int tx4939_get_eth_speed(struct net_device *dev) +static u32 tx4939_get_eth_speed(struct net_device *dev) { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - int speed = 100; /* default 100Mbps */ - int err; - if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) - return speed; - err = dev->ethtool_ops->get_settings(dev, &cmd); - if (err < 0) - return speed; - speed = cmd.speed == SPEED_100 ? 100 : 10; - return speed; + struct ethtool_cmd cmd; + if (dev_ethtool_get_settings(dev, &cmd)) + return 100; /* default 100Mbps */ + + return ethtool_cmd_speed(&cmd); } + static int tx4939_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) @@ -343,8 +339,7 @@ static int tx4939_netdev_event(struct notifier_block *this, else if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(1)) bit = TX4939_PCFG_SPEED1; if (bit) { - int speed = tx4939_get_eth_speed(dev); - if (speed == 100) + if (tx4939_get_eth_speed(dev) == 100) txx9_set64(&tx4939_ccfgptr->pcfg, bit); else txx9_clear64(&tx4939_ccfgptr->pcfg, bit); diff --git a/drivers/net/e100.c b/drivers/net/e100.c index b0aa9e68990a..66ba596a4d37 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1668,7 +1668,7 @@ static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) static void e100_watchdog(unsigned long data) { struct nic *nic = (struct nic *)data; - struct ethtool_cmd cmd; + struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; netif_printk(nic, timer, KERN_DEBUG, nic->netdev, "right now = %ld\n", jiffies); diff --git a/drivers/net/mdio.c b/drivers/net/mdio.c index e85bf04cf813..f2d10abd0403 100644 --- a/drivers/net/mdio.c +++ b/drivers/net/mdio.c @@ -176,6 +176,9 @@ static u32 mdio45_get_an(const struct mdio_if_info *mdio, u16 addr) * @npage_adv: Modes currently advertised on next pages * @npage_lpa: Modes advertised by link partner on next pages * + * The @ecmd parameter is expected to have been cleared before calling + * mdio45_ethtool_gset_npage(). + * * Since the CSRs for auto-negotiation using next pages are not fully * standardised, this function does not attempt to decode them. The * caller must pass them in. diff --git a/drivers/net/mii.c b/drivers/net/mii.c index 0a6c6a2e7550..05acca78f63a 100644 --- a/drivers/net/mii.c +++ b/drivers/net/mii.c @@ -58,6 +58,9 @@ static u32 mii_get_an(struct mii_if_info *mii, u16 addr) * @mii: MII interface * @ecmd: requested ethtool_cmd * + * The @ecmd parameter is expected to have been cleared before calling + * mii_ethtool_gset(). + * * Returns 0 for success, negative on error. */ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index 4cc9872f5ec4..f3e4b0adae93 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c @@ -888,12 +888,12 @@ static void pch_gbe_watchdog(unsigned long data) struct pch_gbe_adapter *adapter = (struct pch_gbe_adapter *)data; struct net_device *netdev = adapter->netdev; struct pch_gbe_hw *hw = &adapter->hw; - struct ethtool_cmd cmd; pr_debug("right now = %ld\n", jiffies); pch_gbe_update_stats(adapter); if ((mii_link_ok(&adapter->mii)) && (!netif_carrier_ok(netdev))) { + struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; netdev->tx_queue_len = adapter->tx_queue_len; /* mii library handles link maintenance tasks */ if (mii_ethtool_gset(&adapter->mii, &cmd)) { @@ -903,7 +903,7 @@ static void pch_gbe_watchdog(unsigned long data) PCH_GBE_WATCHDOG_PERIOD)); return; } - hw->mac.link_speed = cmd.speed; + hw->mac.link_speed = ethtool_cmd_speed(&cmd); hw->mac.link_duplex = cmd.duplex; /* Set the RGMII control. */ pch_gbe_set_rgmii_ctrl(adapter, hw->mac.link_speed, @@ -913,7 +913,7 @@ static void pch_gbe_watchdog(unsigned long data) hw->mac.link_duplex); netdev_dbg(netdev, "Link is Up %d Mbps %s-Duplex\n", - cmd.speed, + hw->mac.link_speed, cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); netif_carrier_on(netdev); netif_wake_queue(netdev); diff --git a/drivers/net/pch_gbe/pch_gbe_phy.c b/drivers/net/pch_gbe/pch_gbe_phy.c index 923a687acd30..9a8207f686fd 100644 --- a/drivers/net/pch_gbe/pch_gbe_phy.c +++ b/drivers/net/pch_gbe/pch_gbe_phy.c @@ -247,7 +247,7 @@ inline void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw) void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw) { struct pch_gbe_adapter *adapter; - struct ethtool_cmd cmd; + struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; int ret; u16 mii_reg; diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 0a1efbae1bc0..b48aba9e4227 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -2099,7 +2099,7 @@ static int pcnet32_open(struct net_device *dev) int first_phy = -1; u16 bmcr; u32 bcr9; - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; /* * There is really no good other way to handle multiple PHYs @@ -2115,9 +2115,9 @@ static int pcnet32_open(struct net_device *dev) ecmd.port = PORT_MII; ecmd.transceiver = XCVR_INTERNAL; ecmd.autoneg = AUTONEG_DISABLE; - ecmd.speed = - lp-> - options & PCNET32_PORT_100 ? SPEED_100 : SPEED_10; + ethtool_cmd_speed_set(&ecmd, + (lp->options & PCNET32_PORT_100) ? + SPEED_100 : SPEED_10); bcr9 = lp->a.read_bcr(ioaddr, 9); if (lp->options & PCNET32_PORT_FD) { @@ -2763,11 +2763,11 @@ static void pcnet32_check_media(struct net_device *dev, int verbose) netif_carrier_on(dev); if (lp->mii) { if (netif_msg_link(lp)) { - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { + .cmd = ETHTOOL_GSET }; mii_ethtool_gset(&lp->mii_if, &ecmd); - netdev_info(dev, "link up, %sMbps, %s-duplex\n", - (ecmd.speed == SPEED_100) - ? "100" : "10", + netdev_info(dev, "link up, %uMbps, %s-duplex\n", + ethtool_cmd_speed(&ecmd), (ecmd.duplex == DUPLEX_FULL) ? "full" : "half"); } diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index 19e68c26d103..71159145b4bf 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c @@ -232,12 +232,12 @@ void efx_mdio_set_mmds_lpower(struct efx_nic *efx, */ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - struct ethtool_cmd prev; + struct ethtool_cmd prev = { .cmd = ETHTOOL_GSET }; efx->phy_op->get_settings(efx, &prev); if (ecmd->advertising == prev.advertising && - ecmd->speed == prev.speed && + ethtool_cmd_speed(ecmd) == ethtool_cmd_speed(&prev) && ecmd->duplex == prev.duplex && ecmd->port == prev.port && ecmd->autoneg == prev.autoneg) diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index 0e61ac8707cb..6f5aaeb986ff 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c @@ -237,13 +237,12 @@ stmmac_set_pauseparam(struct net_device *netdev, if (phy->autoneg) { if (netif_running(netdev)) { - struct ethtool_cmd cmd; + struct ethtool_cmd cmd = { .cmd = ETHTOOL_SSET }; /* auto-negotiation automatically restarted */ - cmd.cmd = ETHTOOL_NWAY_RST; cmd.supported = phy->supported; cmd.advertising = phy->advertising; cmd.autoneg = phy->autoneg; - cmd.speed = phy->speed; + ethtool_cmd_speed_set(&cmd, phy->speed); cmd.duplex = phy->duplex; cmd.phy_address = phy->addr; ret = phy_ethtool_sset(phy, &cmd); diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 6140b56cce53..6998aa6b7bb7 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -847,7 +847,7 @@ static void ax88172_set_multicast(struct net_device *net) static int ax88172_link_reset(struct usbnet *dev) { u8 mode; - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; mii_check_media(&dev->mii, 1, 1); mii_ethtool_gset(&dev->mii, &ecmd); @@ -856,8 +856,8 @@ static int ax88172_link_reset(struct usbnet *dev) if (ecmd.duplex != DUPLEX_FULL) mode |= ~AX88172_MEDIUM_FD; - netdev_dbg(dev->net, "ax88172_link_reset() speed: %d duplex: %d setting mode to 0x%04x\n", - ecmd.speed, ecmd.duplex, mode); + netdev_dbg(dev->net, "ax88172_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n", + ethtool_cmd_speed(&ecmd), ecmd.duplex, mode); asix_write_medium_mode(dev, mode); @@ -947,20 +947,20 @@ static const struct ethtool_ops ax88772_ethtool_ops = { static int ax88772_link_reset(struct usbnet *dev) { u16 mode; - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; mii_check_media(&dev->mii, 1, 1); mii_ethtool_gset(&dev->mii, &ecmd); mode = AX88772_MEDIUM_DEFAULT; - if (ecmd.speed != SPEED_100) + if (ethtool_cmd_speed(&ecmd) != SPEED_100) mode &= ~AX_MEDIUM_PS; if (ecmd.duplex != DUPLEX_FULL) mode &= ~AX_MEDIUM_FD; - netdev_dbg(dev->net, "ax88772_link_reset() speed: %d duplex: %d setting mode to 0x%04x\n", - ecmd.speed, ecmd.duplex, mode); + netdev_dbg(dev->net, "ax88772_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n", + ethtool_cmd_speed(&ecmd), ecmd.duplex, mode); asix_write_medium_mode(dev, mode); @@ -1173,18 +1173,20 @@ static int marvell_led_status(struct usbnet *dev, u16 speed) static int ax88178_link_reset(struct usbnet *dev) { u16 mode; - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; struct asix_data *data = (struct asix_data *)&dev->data; + u32 speed; netdev_dbg(dev->net, "ax88178_link_reset()\n"); mii_check_media(&dev->mii, 1, 1); mii_ethtool_gset(&dev->mii, &ecmd); mode = AX88178_MEDIUM_DEFAULT; + speed = ethtool_cmd_speed(&ecmd); - if (ecmd.speed == SPEED_1000) + if (speed == SPEED_1000) mode |= AX_MEDIUM_GM; - else if (ecmd.speed == SPEED_100) + else if (speed == SPEED_100) mode |= AX_MEDIUM_PS; else mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM); @@ -1196,13 +1198,13 @@ static int ax88178_link_reset(struct usbnet *dev) else mode &= ~AX_MEDIUM_FD; - netdev_dbg(dev->net, "ax88178_link_reset() speed: %d duplex: %d setting mode to 0x%04x\n", - ecmd.speed, ecmd.duplex, mode); + netdev_dbg(dev->net, "ax88178_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n", + speed, ecmd.duplex, mode); asix_write_medium_mode(dev, mode); if (data->phymode == PHY_MODE_MARVELL && data->ledmode) - marvell_led_status(dev, ecmd.speed); + marvell_led_status(dev, speed); return 0; } diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 5002f5be47be..1d93133e9b74 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -599,13 +599,13 @@ static void dm9601_status(struct usbnet *dev, struct urb *urb) static int dm9601_link_reset(struct usbnet *dev) { - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; mii_check_media(&dev->mii, 1, 1); mii_ethtool_gset(&dev->mii, &ecmd); - netdev_dbg(dev->net, "link_reset() speed: %d duplex: %d\n", - ecmd.speed, ecmd.duplex); + netdev_dbg(dev->net, "link_reset() speed: %u duplex: %d\n", + ethtool_cmd_speed(&ecmd), ecmd.duplex); return 0; } diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 860a20c938b4..15b3d6888ae9 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -503,7 +503,7 @@ static int smsc75xx_update_flowcontrol(struct usbnet *dev, u8 duplex, static int smsc75xx_link_reset(struct usbnet *dev) { struct mii_if_info *mii = &dev->mii; - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; u16 lcladv, rmtadv; int ret; @@ -519,8 +519,9 @@ static int smsc75xx_link_reset(struct usbnet *dev) lcladv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); rmtadv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_LPA); - netif_dbg(dev, link, dev->net, "speed: %d duplex: %d lcladv: %04x" - " rmtadv: %04x", ecmd.speed, ecmd.duplex, lcladv, rmtadv); + netif_dbg(dev, link, dev->net, "speed: %u duplex: %d lcladv: %04x" + " rmtadv: %04x", ethtool_cmd_speed(&ecmd), + ecmd.duplex, lcladv, rmtadv); return smsc75xx_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv); } diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 24f4b3739dd2..b374a9997908 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -457,7 +457,7 @@ static int smsc95xx_link_reset(struct usbnet *dev) { struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); struct mii_if_info *mii = &dev->mii; - struct ethtool_cmd ecmd; + struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; unsigned long flags; u16 lcladv, rmtadv; u32 intdata; @@ -472,8 +472,9 @@ static int smsc95xx_link_reset(struct usbnet *dev) lcladv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA); - netif_dbg(dev, link, dev->net, "speed: %d duplex: %d lcladv: %04x rmtadv: %04x\n", - ecmd.speed, ecmd.duplex, lcladv, rmtadv); + netif_dbg(dev, link, dev->net, + "speed: %u duplex: %d lcladv: %04x rmtadv: %04x\n", + ethtool_cmd_speed(&ecmd), ecmd.duplex, lcladv, rmtadv); spin_lock_irqsave(&pdata->mac_cr_lock, flags); if (ecmd.duplex != DUPLEX_FULL) { diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index e2e647509a73..cd050196a163 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -664,7 +664,7 @@ static void bnx2fc_link_speed_update(struct fc_lport *lport) struct fcoe_port *port = lport_priv(lport); struct bnx2fc_hba *hba = port->priv; struct net_device *netdev = hba->netdev; - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; + struct ethtool_cmd ecmd; if (!dev_ethtool_get_settings(netdev, &ecmd)) { lport->link_supported_speeds &= @@ -675,12 +675,15 @@ static void bnx2fc_link_speed_update(struct fc_lport *lport) if (ecmd.supported & SUPPORTED_10000baseT_Full) lport->link_supported_speeds |= FC_PORTSPEED_10GBIT; - if (ecmd.speed == SPEED_1000) + switch (ethtool_cmd_speed(&ecmd)) { + case SPEED_1000: lport->link_speed = FC_PORTSPEED_1GBIT; - if (ecmd.speed == SPEED_10000) + break; + case SPEED_10000: lport->link_speed = FC_PORTSPEED_10GBIT; + break; + } } - return; } static int bnx2fc_link_ok(struct fc_lport *lport) { diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index bde6ee5333eb..04f346b562da 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -2026,7 +2026,7 @@ out_nodev: int fcoe_link_speed_update(struct fc_lport *lport) { struct net_device *netdev = fcoe_netdev(lport); - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; + struct ethtool_cmd ecmd; if (!dev_ethtool_get_settings(netdev, &ecmd)) { lport->link_supported_speeds &= @@ -2037,11 +2037,14 @@ int fcoe_link_speed_update(struct fc_lport *lport) if (ecmd.supported & SUPPORTED_10000baseT_Full) lport->link_supported_speeds |= FC_PORTSPEED_10GBIT; - if (ecmd.speed == SPEED_1000) + switch (ethtool_cmd_speed(&ecmd)) { + case SPEED_1000: lport->link_speed = FC_PORTSPEED_1GBIT; - if (ecmd.speed == SPEED_10000) + break; + case SPEED_10000: lport->link_speed = FC_PORTSPEED_10GBIT; - + break; + } return 0; } return -1; diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 7e6e0a89ca26..4194a2067a14 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -744,7 +744,9 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); /** * struct ethtool_ops - optional netdev operations * @get_settings: Get various device settings including Ethernet link - * settings. Returns a negative error code or zero. + * settings. The @cmd parameter is expected to have been cleared + * before get_settings is called. Returns a negative error code or + * zero. * @set_settings: Set various device settings including Ethernet link * settings. Returns a negative error code or zero. * @get_drvinfo: Report driver/device information. Should only set the diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e03af35843bc..d5de66af46f9 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2597,13 +2597,8 @@ static inline int netif_is_bond_slave(struct net_device *dev) extern struct pernet_operations __net_initdata loopback_net_ops; -static inline int dev_ethtool_get_settings(struct net_device *dev, - struct ethtool_cmd *cmd) -{ - if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) - return -EOPNOTSUPP; - return dev->ethtool_ops->get_settings(dev, cmd); -} +int dev_ethtool_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd); static inline u32 dev_ethtool_get_rx_csum(struct net_device *dev) { diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h index b5fc9f39122b..ae8c68f30f1b 100644 --- a/include/rdma/ib_addr.h +++ b/include/rdma/ib_addr.h @@ -217,18 +217,19 @@ static inline enum ib_mtu iboe_get_mtu(int mtu) static inline int iboe_get_rate(struct net_device *dev) { struct ethtool_cmd cmd; + u32 speed; - if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings || - dev->ethtool_ops->get_settings(dev, &cmd)) + if (dev_ethtool_get_settings(dev, &cmd)) return IB_RATE_PORT_CURRENT; - if (cmd.speed >= 40000) + speed = ethtool_cmd_speed(&cmd); + if (speed >= 40000) return IB_RATE_40_GBPS; - else if (cmd.speed >= 30000) + else if (speed >= 30000) return IB_RATE_30_GBPS; - else if (cmd.speed >= 20000) + else if (speed >= 20000) return IB_RATE_20_GBPS; - else if (cmd.speed >= 10000) + else if (speed >= 10000) return IB_RATE_10_GBPS; else return IB_RATE_PORT_CURRENT; diff --git a/net/core/dev.c b/net/core/dev.c index 7db99b52679f..e95dc30110eb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4495,6 +4495,30 @@ void dev_set_rx_mode(struct net_device *dev) netif_addr_unlock_bh(dev); } +/** + * dev_ethtool_get_settings - call device's ethtool_ops::get_settings() + * @dev: device + * @cmd: memory area for ethtool_ops::get_settings() result + * + * The cmd arg is initialized properly (cleared and + * ethtool_cmd::cmd field set to ETHTOOL_GSET). + * + * Return device's ethtool_ops::get_settings() result value or + * -EOPNOTSUPP when device doesn't expose + * ethtool_ops::get_settings() operation. + */ +int dev_ethtool_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) + return -EOPNOTSUPP; + + memset(cmd, 0, sizeof(struct ethtool_cmd)); + cmd->cmd = ETHTOOL_GSET; + return dev->ethtool_ops->get_settings(dev, cmd); +} +EXPORT_SYMBOL(dev_ethtool_get_settings); + /** * dev_get_flags - get flags reported to userspace * @dev: device diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 5ceb257e860c..381813eae46c 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -28,6 +28,7 @@ static const char fmt_hex[] = "%#x\n"; static const char fmt_long_hex[] = "%#lx\n"; static const char fmt_dec[] = "%d\n"; +static const char fmt_udec[] = "%u\n"; static const char fmt_ulong[] = "%lu\n"; static const char fmt_u64[] = "%llu\n"; @@ -145,13 +146,10 @@ static ssize_t show_speed(struct device *dev, if (!rtnl_trylock()) return restart_syscall(); - if (netif_running(netdev) && - netdev->ethtool_ops && - netdev->ethtool_ops->get_settings) { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - - if (!netdev->ethtool_ops->get_settings(netdev, &cmd)) - ret = sprintf(buf, fmt_dec, ethtool_cmd_speed(&cmd)); + if (netif_running(netdev)) { + struct ethtool_cmd cmd; + if (!dev_ethtool_get_settings(netdev, &cmd)) + ret = sprintf(buf, fmt_udec, ethtool_cmd_speed(&cmd)); } rtnl_unlock(); return ret; @@ -166,13 +164,11 @@ static ssize_t show_duplex(struct device *dev, if (!rtnl_trylock()) return restart_syscall(); - if (netif_running(netdev) && - netdev->ethtool_ops && - netdev->ethtool_ops->get_settings) { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - - if (!netdev->ethtool_ops->get_settings(netdev, &cmd)) - ret = sprintf(buf, "%s\n", cmd.duplex ? "full" : "half"); + if (netif_running(netdev)) { + struct ethtool_cmd cmd; + if (!dev_ethtool_get_settings(netdev, &cmd)) + ret = sprintf(buf, "%s\n", + cmd.duplex ? "full" : "half"); } rtnl_unlock(); return ret; -- cgit v1.2.3 From 1ab7b6ac2709d0eb05a7144cd0e14faa3a7ea162 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 14 Apr 2011 23:46:06 -0700 Subject: ethtool: remove phys_id from ethtool_ops After that all the upstream kernel drivers now use phys_id, and the old ethtool_ops interface (phys_id) can be removed. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/ethtool.h | 7 ------- net/core/ethtool.c | 6 +----- 2 files changed, 1 insertion(+), 12 deletions(-) (limited to 'include/linux/ethtool.h') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 4194a2067a14..d659fdc77eb3 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -814,12 +814,6 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * the indicator accordingly. Finally, it is called with the argument * %ETHTOOL_ID_INACTIVE and must deactivate the indicator. Returns a * negative error code or zero. - * @phys_id: Deprecated in favour of @set_phys_id. - * Identify the physical device, e.g. by flashing an LED - * attached to it until interrupted by a signal or the given time - * (in seconds) elapses. If the given time is zero, use a default - * time limit. Returns a negative error code or zero. Being - * interrupted by a signal is not an error. * @get_ethtool_stats: Return extended statistics about the device. * This is only useful if the device maintains statistics not * included in &struct rtnl_link_stats64. @@ -908,7 +902,6 @@ struct ethtool_ops { void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); void (*get_strings)(struct net_device *, u32 stringset, u8 *); int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state); - int (*phys_id)(struct net_device *, u32); void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *); int (*begin)(struct net_device *); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index d8b1a8d85a96..927819d92248 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1655,7 +1655,7 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) static bool busy; int rc; - if (!dev->ethtool_ops->set_phys_id && !dev->ethtool_ops->phys_id) + if (!dev->ethtool_ops->set_phys_id) return -EOPNOTSUPP; if (busy) @@ -1664,10 +1664,6 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) if (copy_from_user(&id, useraddr, sizeof(id))) return -EFAULT; - if (!dev->ethtool_ops->set_phys_id) - /* Do it the old way */ - return dev->ethtool_ops->phys_id(dev, id.data); - rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ACTIVE); if (rc < 0) return rc; -- cgit v1.2.3 From 57cc71bc3c0cf18bfd1b7bc8cd0eb6c303da24c5 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Mon, 2 May 2011 21:30:08 +0000 Subject: ethtool: Add 20G bit definitions Add 20G supported and advertising bit definitions. 20G will be supported with the 57840 chips. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein ------ include/linux/ethtool.h | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) Signed-off-by: David S. Miller --- include/linux/ethtool.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux/ethtool.h') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index d659fdc77eb3..bd0b50b85f06 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -1025,6 +1025,8 @@ struct ethtool_ops { #define SUPPORTED_10000baseKX4_Full (1 << 18) #define SUPPORTED_10000baseKR_Full (1 << 19) #define SUPPORTED_10000baseR_FEC (1 << 20) +#define SUPPORTED_20000baseMLD2_Full (1 << 21) +#define SUPPORTED_20000baseKR2_Full (1 << 22) /* Indicates what features are advertised by the interface. */ #define ADVERTISED_10baseT_Half (1 << 0) @@ -1048,6 +1050,8 @@ struct ethtool_ops { #define ADVERTISED_10000baseKX4_Full (1 << 18) #define ADVERTISED_10000baseKR_Full (1 << 19) #define ADVERTISED_10000baseR_FEC (1 << 20) +#define ADVERTISED_20000baseMLD2_Full (1 << 21) +#define ADVERTISED_20000baseKR2_Full (1 << 22) /* The following are all involved in forcing a particular link * mode for the device for setting things. When getting the -- cgit v1.2.3 From 29dd54b72ba8c5ad0dd6dd33584449b5953f700b Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Thu, 12 May 2011 12:48:32 +0000 Subject: ethtool: Added support for FW dump Added code to take FW dump via ethtool. Dump level can be controlled via setting the dump flag. A get function is provided to query the current setting of the dump flag. Dump data is obtained from the driver via a separate get function. Changes from v3: Fixed buffer length issue in ethtool_get_dump_data function. Updated kernel doc for ethtool_dump struct and get_dump_flag function. Changes from v2: Provided separate commands for get flag and data. Check for minimum of the two buffer length obtained via ethtool and driver and use that for dump buffer Pass up the driver return error codes up to the caller. Added kernel doc comments. Signed-off-by: Anirban Chakraborty Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/ethtool.h | 31 +++++++++++++++++ net/core/ethtool.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) (limited to 'include/linux/ethtool.h') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index bd0b50b85f06..c6a850ab2ec5 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -601,6 +601,26 @@ struct ethtool_flash { char data[ETHTOOL_FLASH_MAX_FILENAME]; }; +/** + * struct ethtool_dump - used for retrieving, setting device dump + * @cmd: Command number - %ETHTOOL_GET_DUMP_FLAG, %ETHTOOL_GET_DUMP_DATA, or + * %ETHTOOL_SET_DUMP + * @version: FW version of the dump, filled in by driver + * @flag: driver dependent flag for dump setting, filled in by driver during + * get and filled in by ethtool for set operation + * @len: length of dump data, used as the length of the user buffer on entry to + * %ETHTOOL_GET_DUMP_DATA and this is returned as dump length by driver + * for %ETHTOOL_GET_DUMP_FLAG command + * @data: data collected for get dump data operation + */ +struct ethtool_dump { + __u32 cmd; + __u32 version; + __u32 flag; + __u32 len; + __u8 data[0]; +}; + /* for returning and changing feature sets */ /** @@ -853,6 +873,10 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * @get_channels: Get number of channels. * @set_channels: Set number of channels. Returns a negative error code or * zero. + * @get_dump_flag: Get dump flag indicating current dump length, version, + * and flag of the device. + * @get_dump_data: Get dump data. + * @set_dump: Set dump specific flags to the device. * * All operations are optional (i.e. the function pointer may be set * to %NULL) and callers must take this into account. Callers must @@ -927,6 +951,10 @@ struct ethtool_ops { const struct ethtool_rxfh_indir *); void (*get_channels)(struct net_device *, struct ethtool_channels *); int (*set_channels)(struct net_device *, struct ethtool_channels *); + int (*get_dump_flag)(struct net_device *, struct ethtool_dump *); + int (*get_dump_data)(struct net_device *, + struct ethtool_dump *, void *); + int (*set_dump)(struct net_device *, struct ethtool_dump *); }; #endif /* __KERNEL__ */ @@ -998,6 +1026,9 @@ struct ethtool_ops { #define ETHTOOL_SFEATURES 0x0000003b /* Change device offload settings */ #define ETHTOOL_GCHANNELS 0x0000003c /* Get no of channels */ #define ETHTOOL_SCHANNELS 0x0000003d /* Set no of channels */ +#define ETHTOOL_SET_DUMP 0x0000003e /* Set dump settings */ +#define ETHTOOL_GET_DUMP_FLAG 0x0000003f /* Get dump settings */ +#define ETHTOOL_GET_DUMP_DATA 0x00000040 /* Get dump data */ /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET diff --git a/net/core/ethtool.c b/net/core/ethtool.c index b8c2b10f397a..b8c2bcfee6af 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1823,6 +1823,87 @@ static noinline_for_stack int ethtool_flash_device(struct net_device *dev, return dev->ethtool_ops->flash_device(dev, &efl); } +static int ethtool_set_dump(struct net_device *dev, + void __user *useraddr) +{ + struct ethtool_dump dump; + + if (!dev->ethtool_ops->set_dump) + return -EOPNOTSUPP; + + if (copy_from_user(&dump, useraddr, sizeof(dump))) + return -EFAULT; + + return dev->ethtool_ops->set_dump(dev, &dump); +} + +static int ethtool_get_dump_flag(struct net_device *dev, + void __user *useraddr) +{ + int ret; + struct ethtool_dump dump; + const struct ethtool_ops *ops = dev->ethtool_ops; + + if (!dev->ethtool_ops->get_dump_flag) + return -EOPNOTSUPP; + + if (copy_from_user(&dump, useraddr, sizeof(dump))) + return -EFAULT; + + ret = ops->get_dump_flag(dev, &dump); + if (ret) + return ret; + + if (copy_to_user(useraddr, &dump, sizeof(dump))) + return -EFAULT; + return 0; +} + +static int ethtool_get_dump_data(struct net_device *dev, + void __user *useraddr) +{ + int ret; + __u32 len; + struct ethtool_dump dump, tmp; + const struct ethtool_ops *ops = dev->ethtool_ops; + void *data = NULL; + + if (!dev->ethtool_ops->get_dump_data || + !dev->ethtool_ops->get_dump_flag) + return -EOPNOTSUPP; + + if (copy_from_user(&dump, useraddr, sizeof(dump))) + return -EFAULT; + + memset(&tmp, 0, sizeof(tmp)); + tmp.cmd = ETHTOOL_GET_DUMP_FLAG; + ret = ops->get_dump_flag(dev, &tmp); + if (ret) + return ret; + + len = (tmp.len > dump.len) ? dump.len : tmp.len; + if (!len) + return -EFAULT; + + data = vzalloc(tmp.len); + if (!data) + return -ENOMEM; + ret = ops->get_dump_data(dev, &dump, data); + if (ret) + goto out; + + if (copy_to_user(useraddr, &dump, sizeof(dump))) { + ret = -EFAULT; + goto out; + } + useraddr += offsetof(struct ethtool_dump, data); + if (copy_to_user(useraddr, data, len)) + ret = -EFAULT; +out: + vfree(data); + return ret; +} + /* The main entry point in this file. Called from net/core/dev.c */ int dev_ethtool(struct net *net, struct ifreq *ifr) @@ -2039,6 +2120,15 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_SCHANNELS: rc = ethtool_set_channels(dev, useraddr); break; + case ETHTOOL_SET_DUMP: + rc = ethtool_set_dump(dev, useraddr); + break; + case ETHTOOL_GET_DUMP_FLAG: + rc = ethtool_get_dump_flag(dev, useraddr); + break; + case ETHTOOL_GET_DUMP_DATA: + rc = ethtool_get_dump_data(dev, useraddr); + break; default: rc = -EOPNOTSUPP; } -- cgit v1.2.3 From b4c8cc88c18213688268d1d53a51d97ce2f19a64 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Thu, 9 Jun 2011 15:05:48 -0700 Subject: ethtool.h: fix typos Signed-off-by: Yegor Yefremov Signed-off-by: David S. Miller --- include/linux/ethtool.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux/ethtool.h') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index c6a850ab2ec5..439b173c5882 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -268,7 +268,7 @@ struct ethtool_pauseparam { __u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ /* If the link is being auto-negotiated (via ethtool_cmd.autoneg - * being true) the user may set 'autonet' here non-zero to have the + * being true) the user may set 'autoneg' here non-zero to have the * pause parameters be auto-negotiated too. In such a case, the * {rx,tx}_pause values below determine what capabilities are * advertised. @@ -811,7 +811,7 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); * @get_tx_csum: Deprecated as redundant. Report whether transmit checksums * are turned on or off. * @set_tx_csum: Deprecated in favour of generic netdev features. Turn - * transmit checksums on or off. Returns a egative error code or zero. + * transmit checksums on or off. Returns a negative error code or zero. * @get_sg: Deprecated as redundant. Report whether scatter-gather is * enabled. * @set_sg: Deprecated in favour of generic netdev features. Turn @@ -1087,7 +1087,7 @@ struct ethtool_ops { /* The following are all involved in forcing a particular link * mode for the device for setting things. When getting the * devices settings, these indicate the current mode and whether - * it was foced up into this mode or autonegotiated. + * it was forced up into this mode or autonegotiated. */ /* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */ -- cgit v1.2.3