mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 11:03:07 -04:00
net: usb: cdc_ether: add quirk for AMI BMC stale link events
On AMD Genoa/Turin platforms the BMC-provided USB-Ethernet gadget (American Megatrends, VID 0x046b PID 0xffb0) intermittently fails to respond to ARP after AC cold boot. usbmon captures a stale NETWORK_CONNECTION(off) immediately followed by NETWORK_CONNECTION(on) on the interrupt endpoint (~130us apart) after enumeration. Because alloc_netdev() leaves __LINK_STATE_NOCARRIER cleared, netif_carrier_ok() returns true when the spurious OFF arrives, so usbnet_cdc_status() cannot recognise it as redundant and schedules EVENT_LINK_CHANGE. __handle_link_change() then calls unlink_urbs(), killing ~60 rx URBs whose payload has already been DMA'd into memory — xHCI trace confirms them completing as -ECONNRESET with non-zero residual length. rx_complete() drops these unconditionally. The following ON restores the carrier and re-submits URBs, but the ARP reply is already lost; the interface looks "up but silent" until ifdown/ifup. Fix this by adding a device-specific quirk with FLAG_LINK_INTR set, which makes usbnet_probe() call netif_carrier_off() after bind. With initial carrier == OFF, usbnet_cdc_status() recognises the spurious OFF as matching the current state and drops it; the subsequent ON is the first real event and brings the link up cleanly without ever tearing down the rx queue. The scheduled link-change kevent is harmless because EVENT_DEV_OPEN is not yet set at probe time. This is applied as a device-specific quirk rather than a change to the shared cdc_info driver_info because some CDC devices never send NETWORK_CONNECTION notifications; forcing carrier off for them would leave the link permanently DOWN. Restricting the change to this VID/PID keeps that class of device untouched. Tested on Genoa and Turin across 100+ AC cold boot cycles; ping first-packet success rate went from intermittent to 100%. Signed-off-by: Jinhui Guo <guojinhui.liam@bytedance.com> Link: https://patch.msgid.link/20260730051341.24930-1-guojinhui.liam@bytedance.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
90359b5288
commit
089ca284af
@@ -538,6 +538,16 @@ static const struct driver_info cdc_info = {
|
||||
.manage_power = usbnet_manage_power,
|
||||
};
|
||||
|
||||
static const struct driver_info ami_bmc_info = {
|
||||
.description = "AMI BMC USB Ethernet",
|
||||
.flags = FLAG_ETHER | FLAG_POINTTOPOINT | FLAG_LINK_INTR,
|
||||
.bind = usbnet_cdc_bind,
|
||||
.unbind = usbnet_cdc_unbind,
|
||||
.status = usbnet_cdc_status,
|
||||
.set_rx_mode = usbnet_cdc_update_filter,
|
||||
.manage_power = usbnet_manage_power,
|
||||
};
|
||||
|
||||
static const struct driver_info zte_cdc_info = {
|
||||
.description = "ZTE CDC Ethernet Device",
|
||||
.flags = FLAG_ETHER | FLAG_POINTTOPOINT,
|
||||
@@ -946,6 +956,12 @@ static const struct usb_device_id products[] = {
|
||||
USB_CDC_SUBCLASS_ETHERNET,
|
||||
USB_CDC_PROTO_NONE),
|
||||
.driver_info = (unsigned long)&wwan_info,
|
||||
}, {
|
||||
/* AMI BMC gadget */
|
||||
USB_DEVICE_AND_INTERFACE_INFO(0x046b, 0xffb0, USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET,
|
||||
USB_CDC_PROTO_NONE),
|
||||
.driver_info = (unsigned long)&ami_bmc_info,
|
||||
}, {
|
||||
USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
|
||||
USB_CDC_PROTO_NONE),
|
||||
|
||||
Reference in New Issue
Block a user