Merge branch 'usbnet-speed'
Grant Grundler says: ==================== usbnet: speed reporting for devices without MDIO This series introduces support for USB network devices that report speed as a part of their protocol, not emulating an MII to be accessed over MDIO. v2: rebased on recent upstream changes v3: incorporated hints on naming and comments v4: fix misplaced hunks; reword some commit messages; add same change for cdc_ether v4-repost: added "net-next" to subject and Andrew Lunn's Reviewed-by I'm reposting Oliver Neukum's <oneukum@suse.com> patch series with fix ups for "misplaced hunks" (landed in the wrong patches). Please fixup the "author" if "git am" fails to attribute the patches 1-3 (of 4) to Oliver. I've tested v4 series with "5.12-rc3+" kernel on Intel NUC6i5SYB and + Sabrent NT-S25G. Google Pixelbook Go (chromeos-4.4 kernel) + Alpha Network AUE2500C were connected directly to the NT-S25G to get 2.5Gbps link rate: Settings for enx002427880815: Supported ports: [ ] Supported link modes: Not reported Supported pause frame use: No Supports auto-negotiation: No Supported FEC modes: Not reported Advertised link modes: Not reported Advertised pause frame use: No Advertised auto-negotiation: No Advertised FEC modes: Not reported Speed: 2500Mb/s Duplex: Half Auto-negotiation: off Port: Twisted Pair PHYAD: 0 Transceiver: internal MDI-X: Unknown Current message level: 0x00000007 (7) drv probe link Link detected: yes "Duplex" is a lie since we get no information about it. I expect "Auto-Negotiation" is always true for cdc_ncm and cdc_ether devices and perhaps someone knows offhand how to have ethtool report "true" instead. But this is good step in the right direction. base-commit: 1c273e10bc0cc7efb933e0ca10e260cdfc9f0b8c ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
b3feb439f2
@ -125,8 +125,8 @@ static const struct ethtool_ops ax88172_ethtool_ops = {
|
||||
.get_eeprom = asix_get_eeprom,
|
||||
.set_eeprom = asix_set_eeprom,
|
||||
.nway_reset = usbnet_nway_reset,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings_mii,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings_mii,
|
||||
};
|
||||
|
||||
static void ax88172_set_multicast(struct net_device *net)
|
||||
@ -291,8 +291,8 @@ static const struct ethtool_ops ax88772_ethtool_ops = {
|
||||
.get_eeprom = asix_get_eeprom,
|
||||
.set_eeprom = asix_set_eeprom,
|
||||
.nway_reset = usbnet_nway_reset,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings_mii,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings_mii,
|
||||
};
|
||||
|
||||
static int ax88772_link_reset(struct usbnet *dev)
|
||||
@ -782,8 +782,8 @@ static const struct ethtool_ops ax88178_ethtool_ops = {
|
||||
.get_eeprom = asix_get_eeprom,
|
||||
.set_eeprom = asix_set_eeprom,
|
||||
.nway_reset = usbnet_nway_reset,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings_mii,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings_mii,
|
||||
};
|
||||
|
||||
static int marvell_phy_init(struct usbnet *dev)
|
||||
|
@ -92,6 +92,18 @@ void usbnet_cdc_update_filter(struct usbnet *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usbnet_cdc_update_filter);
|
||||
|
||||
/* We need to override usbnet_*_link_ksettings in bind() */
|
||||
static const struct ethtool_ops cdc_ether_ethtool_ops = {
|
||||
.get_link = usbnet_get_link,
|
||||
.nway_reset = usbnet_nway_reset,
|
||||
.get_drvinfo = usbnet_get_drvinfo,
|
||||
.get_msglevel = usbnet_get_msglevel,
|
||||
.set_msglevel = usbnet_set_msglevel,
|
||||
.get_ts_info = ethtool_op_get_ts_info,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings_internal,
|
||||
.set_link_ksettings = NULL,
|
||||
};
|
||||
|
||||
/* probes control interface, claims data interface, collects the bulk
|
||||
* endpoints, activates data interface (if needed), maybe sets MTU.
|
||||
* all pure cdc, except for certain firmware workarounds, and knowing
|
||||
@ -310,6 +322,9 @@ skip:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* override ethtool_ops */
|
||||
dev->net->ethtool_ops = &cdc_ether_ethtool_ops;
|
||||
|
||||
return 0;
|
||||
|
||||
bad_desc:
|
||||
@ -379,12 +394,10 @@ EXPORT_SYMBOL_GPL(usbnet_cdc_unbind);
|
||||
* (by Brad Hards) talked with, with more functionality.
|
||||
*/
|
||||
|
||||
static void dumpspeed(struct usbnet *dev, __le32 *speeds)
|
||||
static void speed_change(struct usbnet *dev, __le32 *speeds)
|
||||
{
|
||||
netif_info(dev, timer, dev->net,
|
||||
"link speeds: %u kbps up, %u kbps down\n",
|
||||
__le32_to_cpu(speeds[0]) / 1000,
|
||||
__le32_to_cpu(speeds[1]) / 1000);
|
||||
dev->tx_speed = __le32_to_cpu(speeds[0]);
|
||||
dev->rx_speed = __le32_to_cpu(speeds[1]);
|
||||
}
|
||||
|
||||
void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
|
||||
@ -396,7 +409,7 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
|
||||
|
||||
/* SPEED_CHANGE can get split into two 8-byte packets */
|
||||
if (test_and_clear_bit(EVENT_STS_SPLIT, &dev->flags)) {
|
||||
dumpspeed(dev, (__le32 *) urb->transfer_buffer);
|
||||
speed_change(dev, (__le32 *) urb->transfer_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -413,7 +426,7 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
|
||||
if (urb->actual_length != (sizeof(*event) + 8))
|
||||
set_bit(EVENT_STS_SPLIT, &dev->flags);
|
||||
else
|
||||
dumpspeed(dev, (__le32 *) &event[1]);
|
||||
speed_change(dev, (__le32 *) &event[1]);
|
||||
break;
|
||||
/* USB_CDC_NOTIFY_RESPONSE_AVAILABLE can happen too (e.g. RNDIS),
|
||||
* but there are no standard formats for the response data.
|
||||
|
@ -133,17 +133,17 @@ static void cdc_ncm_get_strings(struct net_device __always_unused *netdev, u32 s
|
||||
static void cdc_ncm_update_rxtx_max(struct usbnet *dev, u32 new_rx, u32 new_tx);
|
||||
|
||||
static const struct ethtool_ops cdc_ncm_ethtool_ops = {
|
||||
.get_link = usbnet_get_link,
|
||||
.nway_reset = usbnet_nway_reset,
|
||||
.get_drvinfo = usbnet_get_drvinfo,
|
||||
.get_msglevel = usbnet_get_msglevel,
|
||||
.set_msglevel = usbnet_set_msglevel,
|
||||
.get_ts_info = ethtool_op_get_ts_info,
|
||||
.get_sset_count = cdc_ncm_get_sset_count,
|
||||
.get_strings = cdc_ncm_get_strings,
|
||||
.get_ethtool_stats = cdc_ncm_get_ethtool_stats,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings,
|
||||
.get_link = usbnet_get_link,
|
||||
.nway_reset = usbnet_nway_reset,
|
||||
.get_drvinfo = usbnet_get_drvinfo,
|
||||
.get_msglevel = usbnet_get_msglevel,
|
||||
.set_msglevel = usbnet_set_msglevel,
|
||||
.get_ts_info = ethtool_op_get_ts_info,
|
||||
.get_sset_count = cdc_ncm_get_sset_count,
|
||||
.get_strings = cdc_ncm_get_strings,
|
||||
.get_ethtool_stats = cdc_ncm_get_ethtool_stats,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings_internal,
|
||||
.set_link_ksettings = NULL,
|
||||
};
|
||||
|
||||
static u32 cdc_ncm_check_rx_max(struct usbnet *dev, u32 new_rx)
|
||||
@ -1825,33 +1825,9 @@ static void
|
||||
cdc_ncm_speed_change(struct usbnet *dev,
|
||||
struct usb_cdc_speed_change *data)
|
||||
{
|
||||
uint32_t rx_speed = le32_to_cpu(data->DLBitRRate);
|
||||
uint32_t tx_speed = le32_to_cpu(data->ULBitRate);
|
||||
|
||||
/* if the speed hasn't changed, don't report it.
|
||||
* RTL8156 shipped before 2021 sends notification about every 32ms.
|
||||
*/
|
||||
if (dev->rx_speed == rx_speed && dev->tx_speed == tx_speed)
|
||||
return;
|
||||
|
||||
dev->rx_speed = rx_speed;
|
||||
dev->tx_speed = tx_speed;
|
||||
|
||||
/*
|
||||
* Currently the USB-NET API does not support reporting the actual
|
||||
* device speed. Do print it instead.
|
||||
*/
|
||||
if ((tx_speed > 1000000) && (rx_speed > 1000000)) {
|
||||
netif_info(dev, link, dev->net,
|
||||
"%u mbit/s downlink %u mbit/s uplink\n",
|
||||
(unsigned int)(rx_speed / 1000000U),
|
||||
(unsigned int)(tx_speed / 1000000U));
|
||||
} else {
|
||||
netif_info(dev, link, dev->net,
|
||||
"%u kbit/s downlink %u kbit/s uplink\n",
|
||||
(unsigned int)(rx_speed / 1000U),
|
||||
(unsigned int)(tx_speed / 1000U));
|
||||
}
|
||||
/* RTL8156 shipped before 2021 sends notification about every 32ms. */
|
||||
dev->rx_speed = le32_to_cpu(data->DLBitRRate);
|
||||
dev->tx_speed = le32_to_cpu(data->ULBitRate);
|
||||
}
|
||||
|
||||
static void cdc_ncm_status(struct usbnet *dev, struct urb *urb)
|
||||
@ -1877,6 +1853,9 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb)
|
||||
* USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be
|
||||
* sent by device after USB_CDC_NOTIFY_SPEED_CHANGE.
|
||||
*/
|
||||
/* RTL8156 shipped before 2021 sends notification about
|
||||
* every 32ms. Don't forward notification if state is same.
|
||||
*/
|
||||
if (netif_carrier_ok(dev->net) != !!event->wValue)
|
||||
usbnet_link_change(dev, !!event->wValue, 0);
|
||||
break;
|
||||
|
@ -282,8 +282,8 @@ static const struct ethtool_ops dm9601_ethtool_ops = {
|
||||
.get_eeprom_len = dm9601_get_eeprom_len,
|
||||
.get_eeprom = dm9601_get_eeprom,
|
||||
.nway_reset = usbnet_nway_reset,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings_mii,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings_mii,
|
||||
};
|
||||
|
||||
static void dm9601_set_multicast(struct net_device *net)
|
||||
|
@ -452,8 +452,8 @@ static const struct ethtool_ops mcs7830_ethtool_ops = {
|
||||
.get_msglevel = usbnet_get_msglevel,
|
||||
.set_msglevel = usbnet_set_msglevel,
|
||||
.nway_reset = usbnet_nway_reset,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings_mii,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings_mii,
|
||||
};
|
||||
|
||||
static const struct net_device_ops mcs7830_netdev_ops = {
|
||||
|
@ -629,8 +629,8 @@ static const struct ethtool_ops sierra_net_ethtool_ops = {
|
||||
.get_msglevel = usbnet_get_msglevel,
|
||||
.set_msglevel = usbnet_set_msglevel,
|
||||
.nway_reset = usbnet_nway_reset,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings_mii,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings_mii,
|
||||
};
|
||||
|
||||
static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)
|
||||
|
@ -741,8 +741,8 @@ static const struct ethtool_ops smsc75xx_ethtool_ops = {
|
||||
.set_eeprom = smsc75xx_ethtool_set_eeprom,
|
||||
.get_wol = smsc75xx_ethtool_get_wol,
|
||||
.set_wol = smsc75xx_ethtool_set_wol,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings_mii,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings_mii,
|
||||
};
|
||||
|
||||
static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
|
||||
|
@ -250,8 +250,8 @@ static const struct ethtool_ops sr9700_ethtool_ops = {
|
||||
.get_eeprom_len = sr9700_get_eeprom_len,
|
||||
.get_eeprom = sr9700_get_eeprom,
|
||||
.nway_reset = usbnet_nway_reset,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings_mii,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings_mii,
|
||||
};
|
||||
|
||||
static void sr9700_set_multicast(struct net_device *netdev)
|
||||
|
@ -527,8 +527,8 @@ static const struct ethtool_ops sr9800_ethtool_ops = {
|
||||
.get_eeprom_len = sr_get_eeprom_len,
|
||||
.get_eeprom = sr_get_eeprom,
|
||||
.nway_reset = usbnet_nway_reset,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings_mii,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings_mii,
|
||||
};
|
||||
|
||||
static int sr9800_link_reset(struct usbnet *dev)
|
||||
|
@ -944,7 +944,10 @@ EXPORT_SYMBOL_GPL(usbnet_open);
|
||||
* they'll probably want to use this base set.
|
||||
*/
|
||||
|
||||
int usbnet_get_link_ksettings(struct net_device *net,
|
||||
/* These methods are written on the assumption that the device
|
||||
* uses MII
|
||||
*/
|
||||
int usbnet_get_link_ksettings_mii(struct net_device *net,
|
||||
struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
@ -956,9 +959,30 @@ int usbnet_get_link_ksettings(struct net_device *net,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usbnet_get_link_ksettings);
|
||||
EXPORT_SYMBOL_GPL(usbnet_get_link_ksettings_mii);
|
||||
|
||||
int usbnet_set_link_ksettings(struct net_device *net,
|
||||
int usbnet_get_link_ksettings_internal(struct net_device *net,
|
||||
struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
|
||||
/* the assumption that speed is equal on tx and rx
|
||||
* is deeply engrained into the networking layer.
|
||||
* For wireless stuff it is not true.
|
||||
* We assume that rx_speed matters more.
|
||||
*/
|
||||
if (dev->rx_speed != SPEED_UNSET)
|
||||
cmd->base.speed = dev->rx_speed / 1000000;
|
||||
else if (dev->tx_speed != SPEED_UNSET)
|
||||
cmd->base.speed = dev->tx_speed / 1000000;
|
||||
else
|
||||
cmd->base.speed = SPEED_UNKNOWN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usbnet_get_link_ksettings_internal);
|
||||
|
||||
int usbnet_set_link_ksettings_mii(struct net_device *net,
|
||||
const struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
struct usbnet *dev = netdev_priv(net);
|
||||
@ -978,7 +1002,7 @@ int usbnet_set_link_ksettings(struct net_device *net,
|
||||
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usbnet_set_link_ksettings);
|
||||
EXPORT_SYMBOL_GPL(usbnet_set_link_ksettings_mii);
|
||||
|
||||
u32 usbnet_get_link (struct net_device *net)
|
||||
{
|
||||
@ -1043,8 +1067,8 @@ static const struct ethtool_ops usbnet_ethtool_ops = {
|
||||
.get_msglevel = usbnet_get_msglevel,
|
||||
.set_msglevel = usbnet_set_msglevel,
|
||||
.get_ts_info = ethtool_op_get_ts_info,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings,
|
||||
.get_link_ksettings = usbnet_get_link_ksettings_mii,
|
||||
.set_link_ksettings = usbnet_set_link_ksettings_mii,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -1661,6 +1685,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
|
||||
dev->intf = udev;
|
||||
dev->driver_info = info;
|
||||
dev->driver_name = name;
|
||||
dev->rx_speed = SPEED_UNSET;
|
||||
dev->tx_speed = SPEED_UNSET;
|
||||
|
||||
net->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
|
||||
if (!net->tstats)
|
||||
|
@ -53,6 +53,9 @@ struct usbnet {
|
||||
u32 hard_mtu; /* count any extra framing */
|
||||
size_t rx_urb_size; /* size for rx urbs */
|
||||
struct mii_if_info mii;
|
||||
long rx_speed; /* If MII not used */
|
||||
long tx_speed; /* If MII not used */
|
||||
# define SPEED_UNSET -1
|
||||
|
||||
/* various kinds of pending driver work */
|
||||
struct sk_buff_head rxq;
|
||||
@ -81,8 +84,6 @@ struct usbnet {
|
||||
# define EVENT_LINK_CHANGE 11
|
||||
# define EVENT_SET_RX_MODE 12
|
||||
# define EVENT_NO_IP_ALIGN 13
|
||||
u32 rx_speed; /* in bps - NOT Mbps */
|
||||
u32 tx_speed; /* in bps - NOT Mbps */
|
||||
};
|
||||
|
||||
static inline struct usb_driver *driver_of(struct usb_interface *intf)
|
||||
@ -267,10 +268,12 @@ extern void usbnet_pause_rx(struct usbnet *);
|
||||
extern void usbnet_resume_rx(struct usbnet *);
|
||||
extern void usbnet_purge_paused_rxq(struct usbnet *);
|
||||
|
||||
extern int usbnet_get_link_ksettings(struct net_device *net,
|
||||
extern int usbnet_get_link_ksettings_mii(struct net_device *net,
|
||||
struct ethtool_link_ksettings *cmd);
|
||||
extern int usbnet_set_link_ksettings(struct net_device *net,
|
||||
extern int usbnet_set_link_ksettings_mii(struct net_device *net,
|
||||
const struct ethtool_link_ksettings *cmd);
|
||||
extern int usbnet_get_link_ksettings_internal(struct net_device *net,
|
||||
struct ethtool_link_ksettings *cmd);
|
||||
extern u32 usbnet_get_link(struct net_device *net);
|
||||
extern u32 usbnet_get_msglevel(struct net_device *);
|
||||
extern void usbnet_set_msglevel(struct net_device *, u32);
|
||||
|
Loading…
x
Reference in New Issue
Block a user