mirror of
https://github.com/openwrt/openwrt.git
synced 2025-03-23 12:35:33 +00:00
kernel: backport fixes for realtek r8152
Fixes issues with RTL8156 2.5G USB adapters - # ethtool eth1 Settings for eth1: 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 Port: Twisted Pair PHYAD: 0 Transceiver: internal Auto-negotiation: off MDI-X: Unknown Current message level: 0x00000007 (7) drv probe link Link detected: yes - # - r8152: break the loop when the budget is exhausted - r8152: Block future register access if register access fails - r8152: Rename RTL8152_UNPLUG to RTL8152_INACCESSIBLE - r8152: add vendor/device ID pair for D-Link DUB-E250 - r8152: try to use a normal budget - r8152: set bp in bulk - r8152: adjust generic_ocp_write function - r8152: fix the autosuspend doesn't work - r8152: Add __GFP_NOWARN to big allocations - r8152: reduce the control transfer of rtl8152_get_version() - r8152: remove rtl_vendor_mode function - r8152: avoid to change cfg for all devices - r8152: add USB device driver for config selection - r8152: use napi_gro_frags - cdc_ether: no need to blacklist any r8152 devices - cdc_ether: add u-blox 0x1313 composition Build system: x86_64 Build-tested: bcm2711, rockchip, x86/64 Run-tested: bcm2711/RPi4B, rockchip/nanopi r2s, x86/64 Signed-off-by: Marty Jones <mj8263788@gmail.com>
This commit is contained in:
parent
cb86e313d3
commit
34d2964554
@ -0,0 +1,229 @@
|
||||
From ec51fbd1b8a2bca2948dede99c14ec63dc57ff6b Mon Sep 17 00:00:00 2001
|
||||
From: Bjørn Mork <bjorn@mork.no>
|
||||
Date: Fri, 6 Jan 2023 17:07:38 +0100
|
||||
Subject: [PATCH] r8152: add USB device driver for config selection
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Subclassing the generic USB device driver to override the
|
||||
default configuration selection regardless of matching interface
|
||||
drivers.
|
||||
|
||||
The r815x family devices expose a vendor specific function which
|
||||
the r8152 interface driver wants to handle. This is the preferred
|
||||
device mode. Additionally one or more USB class functions are
|
||||
usually supported for hosts lacking a vendor specific driver. The
|
||||
choice is USB configuration based, with one alternate function per
|
||||
configuration.
|
||||
|
||||
Example device with both NCM and ECM alternate cfgs:
|
||||
|
||||
T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=5000 MxCh= 0
|
||||
D: Ver= 3.20 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 3
|
||||
P: Vendor=0bda ProdID=8156 Rev=31.00
|
||||
S: Manufacturer=Realtek
|
||||
S: Product=USB 10/100/1G/2.5G LAN
|
||||
S: SerialNumber=001000001
|
||||
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=256mA
|
||||
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=00 Driver=r8152
|
||||
E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
|
||||
E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
|
||||
E: Ad=83(I) Atr=03(Int.) MxPS= 2 Ivl=128ms
|
||||
C: #Ifs= 2 Cfg#= 2 Atr=a0 MxPwr=256mA
|
||||
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=0d Prot=00 Driver=
|
||||
E: Ad=83(I) Atr=03(Int.) MxPS= 16 Ivl=128ms
|
||||
I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=01 Driver=
|
||||
I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=01 Driver=
|
||||
E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
|
||||
E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
|
||||
C: #Ifs= 2 Cfg#= 3 Atr=a0 MxPwr=256mA
|
||||
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=06 Prot=00 Driver=
|
||||
E: Ad=83(I) Atr=03(Int.) MxPS= 16 Ivl=128ms
|
||||
I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=00 Driver=
|
||||
I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=
|
||||
E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
|
||||
E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
|
||||
|
||||
A problem with this is that Linux will prefer class functions over
|
||||
vendor specific functions. Using the above example, Linux defaults
|
||||
to cfg #2, running the device in a sub-optimal NCM mode.
|
||||
|
||||
Previously we've attempted to work around the problem by
|
||||
blacklisting the devices in the ECM class driver "cdc_ether", and
|
||||
matching on the ECM class function in the vendor specific interface
|
||||
driver. The latter has been used to switch back to the vendor
|
||||
specific configuration when the driver is probed for a class
|
||||
function.
|
||||
|
||||
This workaround has several issues;
|
||||
- class driver blacklists is additional maintanence cruft in an
|
||||
unrelated driver
|
||||
- class driver blacklists prevents users from optionally running
|
||||
the devices in class mode
|
||||
- each device needs double match entries in the vendor driver
|
||||
- the initial probing as a class function slows down device
|
||||
discovery
|
||||
|
||||
Now these issues have become even worse with the introduction of
|
||||
firmware supporting both NCM and ECM, where NCM ends up as the
|
||||
default mode in Linux. To use the same workaround, we now have
|
||||
to blacklist the devices in to two different class drivers and
|
||||
add yet another match entry to the vendor specific driver.
|
||||
|
||||
This patch implements an alternative workaround strategy -
|
||||
independent of the interface drivers. It avoids adding a
|
||||
blacklist to the cdc_ncm driver and will let us remove the
|
||||
existing blacklist from the cdc_ether driver.
|
||||
|
||||
As an additional bonus, removing the blacklists allow users to
|
||||
select one of the other device modes if wanted.
|
||||
|
||||
Signed-off-by: Bjørn Mork <bjorn@mork.no>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 113 ++++++++++++++++++++++++++++------------
|
||||
1 file changed, 81 insertions(+), 32 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -9625,6 +9625,9 @@ static int rtl8152_probe(struct usb_inte
|
||||
if (version == RTL_VER_UNKNOWN)
|
||||
return -ENODEV;
|
||||
|
||||
+ if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
if (!rtl_vendor_mode(intf))
|
||||
return -ENODEV;
|
||||
|
||||
@@ -9834,43 +9837,35 @@ static void rtl8152_disconnect(struct us
|
||||
}
|
||||
}
|
||||
|
||||
-#define REALTEK_USB_DEVICE(vend, prod) { \
|
||||
- USB_DEVICE_INTERFACE_CLASS(vend, prod, USB_CLASS_VENDOR_SPEC), \
|
||||
-}, \
|
||||
-{ \
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(vend, prod, USB_CLASS_COMM, \
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), \
|
||||
-}
|
||||
|
||||
/* table of devices that work with this driver */
|
||||
static const struct usb_device_id rtl8152_table[] = {
|
||||
/* Realtek */
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8050),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8053),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8155),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8156),
|
||||
+ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8050) },
|
||||
+ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8053) },
|
||||
+ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8152) },
|
||||
+ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8153) },
|
||||
+ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8155) },
|
||||
+ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8156) },
|
||||
|
||||
/* Microsoft */
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0c5e),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3054),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3062),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3069),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3082),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x721e),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0xa387),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_TPLINK, 0x0601),
|
||||
+ { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab) },
|
||||
+ { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6) },
|
||||
+ { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927) },
|
||||
+ { USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x304f) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3054) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3062) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3069) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3082) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x7205) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x720c) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x7214) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x721e) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0xa387) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041) },
|
||||
+ { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) },
|
||||
+ { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -9890,7 +9885,61 @@ static struct usb_driver rtl8152_driver
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
};
|
||||
|
||||
-module_usb_driver(rtl8152_driver);
|
||||
+static int rtl8152_cfgselector_probe(struct usb_device *udev)
|
||||
+{
|
||||
+ struct usb_host_config *c;
|
||||
+ int i, num_configs;
|
||||
+
|
||||
+ /* The vendor mode is not always config #1, so to find it out. */
|
||||
+ c = udev->config;
|
||||
+ num_configs = udev->descriptor.bNumConfigurations;
|
||||
+ for (i = 0; i < num_configs; (i++, c++)) {
|
||||
+ struct usb_interface_descriptor *desc = NULL;
|
||||
+
|
||||
+ if (!c->desc.bNumInterfaces)
|
||||
+ continue;
|
||||
+ desc = &c->intf_cache[0]->altsetting->desc;
|
||||
+ if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (i == num_configs)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ if (usb_set_configuration(udev, c->desc.bConfigurationValue)) {
|
||||
+ dev_err(&udev->dev, "Failed to set configuration %d\n",
|
||||
+ c->desc.bConfigurationValue);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct usb_device_driver rtl8152_cfgselector_driver = {
|
||||
+ .name = MODULENAME "-cfgselector",
|
||||
+ .probe = rtl8152_cfgselector_probe,
|
||||
+ .id_table = rtl8152_table,
|
||||
+ .generic_subclass = 1,
|
||||
+};
|
||||
+
|
||||
+static int __init rtl8152_driver_init(void)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = usb_register_device_driver(&rtl8152_cfgselector_driver, THIS_MODULE);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ return usb_register(&rtl8152_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit rtl8152_driver_exit(void)
|
||||
+{
|
||||
+ usb_deregister(&rtl8152_driver);
|
||||
+ usb_deregister_device_driver(&rtl8152_cfgselector_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(rtl8152_driver_init);
|
||||
+module_exit(rtl8152_driver_exit);
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
@ -0,0 +1,158 @@
|
||||
From 69649ef8405320f81497f4757faac8234f61b167 Mon Sep 17 00:00:00 2001
|
||||
From: Bjørn Mork <bjorn@mork.no>
|
||||
Date: Fri, 6 Jan 2023 17:07:39 +0100
|
||||
Subject: [PATCH] cdc_ether: no need to blacklist any r8152 devices
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The r8152 driver does not need this anymore.
|
||||
|
||||
Dropping blacklist entries adds optional support for these
|
||||
devices in ECM mode.
|
||||
|
||||
The 8153 devices are handled by the r8153_ecm driver when
|
||||
in ECM mode, and must still be blacklisted here.
|
||||
|
||||
Signed-off-by: Bjørn Mork <bjorn@mork.no>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/cdc_ether.c | 114 ------------------------------------
|
||||
1 file changed, 114 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/cdc_ether.c
|
||||
+++ b/drivers/net/usb/cdc_ether.c
|
||||
@@ -767,13 +767,6 @@ static const struct usb_device_id produc
|
||||
.driver_info = 0,
|
||||
},
|
||||
|
||||
-/* Realtek RTL8152 Based USB 2.0 Ethernet Adapters */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
/* Realtek RTL8153 Based USB 3.0 Ethernet Adapters */
|
||||
{
|
||||
USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM,
|
||||
@@ -781,119 +774,12 @@ static const struct usb_device_id produc
|
||||
.driver_info = 0,
|
||||
},
|
||||
|
||||
-/* Samsung USB Ethernet Adapters */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, 0xa101, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-#if IS_ENABLED(CONFIG_USB_RTL8152)
|
||||
-/* Linksys USB3GIGV1 Ethernet Adapter */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LINKSYS_VENDOR_ID, 0x0041, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-#endif
|
||||
-
|
||||
-/* Lenovo ThinkPad OneLink+ Dock (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3054, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* ThinkPad USB-C Dock (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* ThinkPad Thunderbolt 3 Dock (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3069, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* ThinkPad Thunderbolt 3 Dock Gen 2 (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3082, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* Lenovo USB C to Ethernet Adapter (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x720c, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* Lenovo USB-C Travel Hub (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7214, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
/* Lenovo Powered USB-C Travel Hub (4X90S92381, based on Realtek RTL8153) */
|
||||
{
|
||||
USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x721e, USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
.driver_info = 0,
|
||||
},
|
||||
-
|
||||
-/* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* Microsoft Surface 2 dock (based on Realtek RTL8152) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07ab, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153B) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x0927, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
|
||||
/* Aquantia AQtion USB to 5GbE Controller (based on AQC111U) */
|
||||
{
|
@ -0,0 +1,64 @@
|
||||
From 0d4cda805a183bbe523f2407edb5c14ade50b841 Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Tue, 17 Jan 2023 11:03:44 +0800
|
||||
Subject: [PATCH] r8152: avoid to change cfg for all devices
|
||||
|
||||
The rtl8152_cfgselector_probe() should set the USB configuration to the
|
||||
vendor mode only for the devices which the driver (r8152) supports.
|
||||
Otherwise, no driver would be used for such devices.
|
||||
|
||||
Fixes: ec51fbd1b8a2 ("r8152: add USB device driver for config selection")
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Reviewed-by: Simon Horman <simon.horman@corigine.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 20 +++++++++++++++++---
|
||||
1 file changed, 17 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -9531,9 +9531,8 @@ static int rtl_fw_init(struct r8152 *tp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-u8 rtl8152_get_version(struct usb_interface *intf)
|
||||
+static u8 __rtl_get_hw_ver(struct usb_device *udev)
|
||||
{
|
||||
- struct usb_device *udev = interface_to_usbdev(intf);
|
||||
u32 ocp_data = 0;
|
||||
__le32 *tmp;
|
||||
u8 version;
|
||||
@@ -9603,10 +9602,19 @@ u8 rtl8152_get_version(struct usb_interf
|
||||
break;
|
||||
default:
|
||||
version = RTL_VER_UNKNOWN;
|
||||
- dev_info(&intf->dev, "Unknown version 0x%04x\n", ocp_data);
|
||||
+ dev_info(&udev->dev, "Unknown version 0x%04x\n", ocp_data);
|
||||
break;
|
||||
}
|
||||
|
||||
+ return version;
|
||||
+}
|
||||
+
|
||||
+u8 rtl8152_get_version(struct usb_interface *intf)
|
||||
+{
|
||||
+ u8 version;
|
||||
+
|
||||
+ version = __rtl_get_hw_ver(interface_to_usbdev(intf));
|
||||
+
|
||||
dev_dbg(&intf->dev, "Detected version 0x%04x\n", version);
|
||||
|
||||
return version;
|
||||
@@ -9890,6 +9898,12 @@ static int rtl8152_cfgselector_probe(str
|
||||
struct usb_host_config *c;
|
||||
int i, num_configs;
|
||||
|
||||
+ /* Switch the device to vendor mode, if and only if the vendor mode
|
||||
+ * driver supports it.
|
||||
+ */
|
||||
+ if (__rtl_get_hw_ver(udev) == RTL_VER_UNKNOWN)
|
||||
+ return 0;
|
||||
+
|
||||
/* The vendor mode is not always config #1, so to find it out. */
|
||||
c = udev->config;
|
||||
num_configs = udev->descriptor.bNumConfigurations;
|
@ -0,0 +1,71 @@
|
||||
From 95a4c1d617b92cdc4522297741b56e8f6cd01a1e Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Thu, 19 Jan 2023 15:40:42 +0800
|
||||
Subject: [PATCH] r8152: remove rtl_vendor_mode function
|
||||
|
||||
After commit ec51fbd1b8a2 ("r8152: add USB device driver for
|
||||
config selection"), the code about changing USB configuration
|
||||
in rtl_vendor_mode() wouldn't be run anymore. Therefore, the
|
||||
function could be removed.
|
||||
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 39 +--------------------------------------
|
||||
1 file changed, 1 insertion(+), 38 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -8267,43 +8267,6 @@ static bool rtl_check_vendor_ok(struct u
|
||||
return true;
|
||||
}
|
||||
|
||||
-static bool rtl_vendor_mode(struct usb_interface *intf)
|
||||
-{
|
||||
- struct usb_host_interface *alt = intf->cur_altsetting;
|
||||
- struct usb_device *udev;
|
||||
- struct usb_host_config *c;
|
||||
- int i, num_configs;
|
||||
-
|
||||
- if (alt->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC)
|
||||
- return rtl_check_vendor_ok(intf);
|
||||
-
|
||||
- /* The vendor mode is not always config #1, so to find it out. */
|
||||
- udev = interface_to_usbdev(intf);
|
||||
- c = udev->config;
|
||||
- num_configs = udev->descriptor.bNumConfigurations;
|
||||
- if (num_configs < 2)
|
||||
- return false;
|
||||
-
|
||||
- for (i = 0; i < num_configs; (i++, c++)) {
|
||||
- struct usb_interface_descriptor *desc = NULL;
|
||||
-
|
||||
- if (c->desc.bNumInterfaces > 0)
|
||||
- desc = &c->intf_cache[0]->altsetting->desc;
|
||||
- else
|
||||
- continue;
|
||||
-
|
||||
- if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
|
||||
- usb_driver_set_configuration(udev, c->desc.bConfigurationValue);
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (i == num_configs)
|
||||
- dev_err(&intf->dev, "Unexpected Device\n");
|
||||
-
|
||||
- return false;
|
||||
-}
|
||||
-
|
||||
static int rtl8152_pre_reset(struct usb_interface *intf)
|
||||
{
|
||||
struct r8152 *tp = usb_get_intfdata(intf);
|
||||
@@ -9636,7 +9599,7 @@ static int rtl8152_probe(struct usb_inte
|
||||
if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
|
||||
return -ENODEV;
|
||||
|
||||
- if (!rtl_vendor_mode(intf))
|
||||
+ if (!rtl_check_vendor_ok(intf))
|
||||
return -ENODEV;
|
||||
|
||||
usb_reset_device(udev);
|
@ -0,0 +1,46 @@
|
||||
From 02767440e1dda9861a11ca1dbe0f19a760b1d5c2 Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Thu, 19 Jan 2023 15:40:43 +0800
|
||||
Subject: [PATCH] r8152: reduce the control transfer of rtl8152_get_version()
|
||||
|
||||
Reduce the control transfer by moving calling rtl8152_get_version() in
|
||||
rtl8152_probe(). This could prevent from calling rtl8152_get_version()
|
||||
for unnecessary situations. For example, after setting config #2 for the
|
||||
device, there are two interfaces and rtl8152_probe() may be called
|
||||
twice. However, we don't need to call rtl8152_get_version() for this
|
||||
situation.
|
||||
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -9588,20 +9588,21 @@ static int rtl8152_probe(struct usb_inte
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
- u8 version = rtl8152_get_version(intf);
|
||||
struct r8152 *tp;
|
||||
struct net_device *netdev;
|
||||
+ u8 version;
|
||||
int ret;
|
||||
|
||||
- if (version == RTL_VER_UNKNOWN)
|
||||
- return -ENODEV;
|
||||
-
|
||||
if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
|
||||
return -ENODEV;
|
||||
|
||||
if (!rtl_check_vendor_ok(intf))
|
||||
return -ENODEV;
|
||||
|
||||
+ version = rtl8152_get_version(intf);
|
||||
+ if (version == RTL_VER_UNKNOWN)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
usb_reset_device(udev);
|
||||
netdev = alloc_etherdev(sizeof(struct r8152));
|
||||
if (!netdev) {
|
@ -0,0 +1,55 @@
|
||||
From 5cc33f139e11b893ff6dc60d8a0ae865a65521ac Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Anderson <dianders@chromium.org>
|
||||
Date: Thu, 6 Apr 2023 17:14:26 -0700
|
||||
Subject: [PATCH] r8152: Add __GFP_NOWARN to big allocations
|
||||
|
||||
When memory is a little tight on my system, it's pretty easy to see
|
||||
warnings that look like this.
|
||||
|
||||
ksoftirqd/0: page allocation failure: order:3, mode:0x40a20(GFP_ATOMIC|__GFP_COMP), nodemask=(null),cpuset=/,mems_allowed=0
|
||||
...
|
||||
Call trace:
|
||||
dump_backtrace+0x0/0x1e8
|
||||
show_stack+0x20/0x2c
|
||||
dump_stack_lvl+0x60/0x78
|
||||
dump_stack+0x18/0x38
|
||||
warn_alloc+0x104/0x174
|
||||
__alloc_pages+0x588/0x67c
|
||||
alloc_rx_agg+0xa0/0x190 [r8152 ...]
|
||||
r8152_poll+0x270/0x760 [r8152 ...]
|
||||
__napi_poll+0x44/0x1ec
|
||||
net_rx_action+0x100/0x300
|
||||
__do_softirq+0xec/0x38c
|
||||
run_ksoftirqd+0x38/0xec
|
||||
smpboot_thread_fn+0xb8/0x248
|
||||
kthread+0x134/0x154
|
||||
ret_from_fork+0x10/0x20
|
||||
|
||||
On a fragmented system it's normal that order 3 allocations will
|
||||
sometimes fail, especially atomic ones. The driver handles these
|
||||
failures fine and the WARN just creates spam in the logs for this
|
||||
case. The __GFP_NOWARN flag is exactly for this situation, so add it
|
||||
to the allocation.
|
||||
|
||||
NOTE: my testing is on a 5.15 system, but there should be no reason
|
||||
that this would be fundamentally different on a mainline kernel.
|
||||
|
||||
Signed-off-by: Douglas Anderson <dianders@chromium.org>
|
||||
Acked-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Link: https://lore.kernel.org/r/20230406171411.1.I84dbef45786af440fd269b71e9436a96a8e7a152@changeid
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -1944,7 +1944,7 @@ static struct rx_agg *alloc_rx_agg(struc
|
||||
if (!rx_agg)
|
||||
return NULL;
|
||||
|
||||
- rx_agg->page = alloc_pages(mflags | __GFP_COMP, order);
|
||||
+ rx_agg->page = alloc_pages(mflags | __GFP_COMP | __GFP_NOWARN, order);
|
||||
if (!rx_agg->page)
|
||||
goto free_rx;
|
||||
|
@ -0,0 +1,24 @@
|
||||
From 0fbd79c01a9a657348f7032df70c57a406468c86 Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Tue, 2 May 2023 11:36:27 +0800
|
||||
Subject: [PATCH] r8152: fix the autosuspend doesn't work
|
||||
|
||||
Set supports_autosuspend = 1 for the rtl8152_cfgselector_driver.
|
||||
|
||||
Fixes: ec51fbd1b8a2 ("r8152: add USB device driver for config selection")
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -9898,6 +9898,7 @@ static struct usb_device_driver rtl8152_
|
||||
.probe = rtl8152_cfgselector_probe,
|
||||
.id_table = rtl8152_table,
|
||||
.generic_subclass = 1,
|
||||
+ .supports_autosuspend = 1,
|
||||
};
|
||||
|
||||
static int __init rtl8152_driver_init(void)
|
@ -0,0 +1,70 @@
|
||||
From 57df0fb9d511f91202114813e90128d65c0589f0 Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Wed, 26 Jul 2023 11:08:07 +0800
|
||||
Subject: [PATCH] r8152: adjust generic_ocp_write function
|
||||
|
||||
Reduce the control transfer if all bytes of first or the last DWORD are
|
||||
written.
|
||||
|
||||
The original method is to split the control transfer into three parts
|
||||
(the first DWORD, middle continuous data, and the last DWORD). However,
|
||||
they could be combined if whole bytes of the first DWORD or last DWORD
|
||||
are written. That is, the first DWORD or the last DWORD could be combined
|
||||
with the middle continuous data, if the byte_en is 0xff.
|
||||
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Link: https://lore.kernel.org/r/20230726030808.9093-418-nic_swsd@realtek.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 29 ++++++++++++++++++-----------
|
||||
1 file changed, 18 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -1310,16 +1310,24 @@ static int generic_ocp_write(struct r815
|
||||
byteen_end = byteen & BYTE_EN_END_MASK;
|
||||
|
||||
byen = byteen_start | (byteen_start << 4);
|
||||
- ret = set_registers(tp, index, type | byen, 4, data);
|
||||
- if (ret < 0)
|
||||
- goto error1;
|
||||
-
|
||||
- index += 4;
|
||||
- data += 4;
|
||||
- size -= 4;
|
||||
|
||||
- if (size) {
|
||||
+ /* Split the first DWORD if the byte_en is not 0xff */
|
||||
+ if (byen != BYTE_EN_DWORD) {
|
||||
+ ret = set_registers(tp, index, type | byen, 4, data);
|
||||
+ if (ret < 0)
|
||||
+ goto error1;
|
||||
+
|
||||
+ index += 4;
|
||||
+ data += 4;
|
||||
size -= 4;
|
||||
+ }
|
||||
+
|
||||
+ if (size) {
|
||||
+ byen = byteen_end | (byteen_end >> 4);
|
||||
+
|
||||
+ /* Split the last DWORD if the byte_en is not 0xff */
|
||||
+ if (byen != BYTE_EN_DWORD)
|
||||
+ size -= 4;
|
||||
|
||||
while (size) {
|
||||
if (size > limit) {
|
||||
@@ -1346,10 +1354,9 @@ static int generic_ocp_write(struct r815
|
||||
}
|
||||
}
|
||||
|
||||
- byen = byteen_end | (byteen_end >> 4);
|
||||
- ret = set_registers(tp, index, type | byen, 4, data);
|
||||
- if (ret < 0)
|
||||
- goto error1;
|
||||
+ /* Set the last DWORD */
|
||||
+ if (byen != BYTE_EN_DWORD)
|
||||
+ ret = set_registers(tp, index, type | byen, 4, data);
|
||||
}
|
||||
|
||||
error1:
|
@ -0,0 +1,129 @@
|
||||
From e5c266a61186b462c388c53a3564c375e72f2244 Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Wed, 26 Jul 2023 11:08:08 +0800
|
||||
Subject: [PATCH] r8152: set bp in bulk
|
||||
|
||||
PLA_BP_0 ~ PLA_BP_15 (0xfc28 ~ 0xfc46) are continuous registers, so we
|
||||
could combine the control transfers into one control transfer.
|
||||
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Link: https://lore.kernel.org/r/20230726030808.9093-419-nic_swsd@realtek.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 75 ++++++++++++++---------------------------
|
||||
1 file changed, 25 insertions(+), 50 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -3977,29 +3977,10 @@ static void rtl_reset_bmu(struct r8152 *
|
||||
/* Clear the bp to stop the firmware before loading a new one */
|
||||
static void rtl_clear_bp(struct r8152 *tp, u16 type)
|
||||
{
|
||||
- switch (tp->version) {
|
||||
- case RTL_VER_01:
|
||||
- case RTL_VER_02:
|
||||
- case RTL_VER_07:
|
||||
- break;
|
||||
- case RTL_VER_03:
|
||||
- case RTL_VER_04:
|
||||
- case RTL_VER_05:
|
||||
- case RTL_VER_06:
|
||||
- ocp_write_byte(tp, type, PLA_BP_EN, 0);
|
||||
- break;
|
||||
- case RTL_VER_14:
|
||||
- ocp_write_word(tp, type, USB_BP2_EN, 0);
|
||||
+ u16 bp[16] = {0};
|
||||
+ u16 bp_num;
|
||||
|
||||
- ocp_write_word(tp, type, USB_BP_8, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_9, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_10, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_11, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_12, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_13, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_14, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_15, 0);
|
||||
- break;
|
||||
+ switch (tp->version) {
|
||||
case RTL_VER_08:
|
||||
case RTL_VER_09:
|
||||
case RTL_VER_10:
|
||||
@@ -4007,32 +3988,31 @@ static void rtl_clear_bp(struct r8152 *t
|
||||
case RTL_VER_12:
|
||||
case RTL_VER_13:
|
||||
case RTL_VER_15:
|
||||
- default:
|
||||
if (type == MCU_TYPE_USB) {
|
||||
ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0);
|
||||
-
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_8, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_9, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_10, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_11, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_12, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_13, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_14, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_15, 0);
|
||||
- } else {
|
||||
- ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0);
|
||||
+ bp_num = 16;
|
||||
+ break;
|
||||
}
|
||||
+ fallthrough;
|
||||
+ case RTL_VER_03:
|
||||
+ case RTL_VER_04:
|
||||
+ case RTL_VER_05:
|
||||
+ case RTL_VER_06:
|
||||
+ ocp_write_byte(tp, type, PLA_BP_EN, 0);
|
||||
+ fallthrough;
|
||||
+ case RTL_VER_01:
|
||||
+ case RTL_VER_02:
|
||||
+ case RTL_VER_07:
|
||||
+ bp_num = 8;
|
||||
+ break;
|
||||
+ case RTL_VER_14:
|
||||
+ default:
|
||||
+ ocp_write_word(tp, type, USB_BP2_EN, 0);
|
||||
+ bp_num = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
- ocp_write_word(tp, type, PLA_BP_0, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_1, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_2, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_3, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_4, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_5, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_6, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_7, 0);
|
||||
+ generic_ocp_write(tp, PLA_BP_0, BYTE_EN_DWORD, bp_num << 1, bp, type);
|
||||
|
||||
/* wait 3 ms to make sure the firmware is stopped */
|
||||
usleep_range(3000, 6000);
|
||||
@@ -5009,10 +4989,9 @@ static void rtl8152_fw_phy_nc_apply(stru
|
||||
|
||||
static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac)
|
||||
{
|
||||
- u16 bp_en_addr, bp_index, type, bp_num, fw_ver_reg;
|
||||
+ u16 bp_en_addr, type, fw_ver_reg;
|
||||
u32 length;
|
||||
u8 *data;
|
||||
- int i;
|
||||
|
||||
switch (__le32_to_cpu(mac->blk_hdr.type)) {
|
||||
case RTL_FW_PLA:
|
||||
@@ -5054,12 +5033,8 @@ static void rtl8152_fw_mac_apply(struct
|
||||
ocp_write_word(tp, type, __le16_to_cpu(mac->bp_ba_addr),
|
||||
__le16_to_cpu(mac->bp_ba_value));
|
||||
|
||||
- bp_index = __le16_to_cpu(mac->bp_start);
|
||||
- bp_num = __le16_to_cpu(mac->bp_num);
|
||||
- for (i = 0; i < bp_num; i++) {
|
||||
- ocp_write_word(tp, type, bp_index, __le16_to_cpu(mac->bp[i]));
|
||||
- bp_index += 2;
|
||||
- }
|
||||
+ generic_ocp_write(tp, __le16_to_cpu(mac->bp_start), BYTE_EN_DWORD,
|
||||
+ __le16_to_cpu(mac->bp_num) << 1, mac->bp, type);
|
||||
|
||||
bp_en_addr = __le16_to_cpu(mac->bp_en_addr);
|
||||
if (bp_en_addr)
|
@ -0,0 +1,39 @@
|
||||
From 72f93a3136ee18fd59fa6579f84c07e93424681e Mon Sep 17 00:00:00 2001
|
||||
From: Antonio Napolitano <anton@polit.no>
|
||||
Date: Sat, 26 Aug 2023 01:05:50 +0200
|
||||
Subject: [PATCH] r8152: add vendor/device ID pair for D-Link DUB-E250
|
||||
|
||||
The D-Link DUB-E250 is an RTL8156 based 2.5G Ethernet controller.
|
||||
|
||||
Add the vendor and product ID values to the driver. This makes Ethernet
|
||||
work with the adapter.
|
||||
|
||||
Signed-off-by: Antonio Napolitano <anton@polit.no>
|
||||
Link: https://lore.kernel.org/r/CV200KJEEUPC.WPKAHXCQJ05I@mercurius
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 1 +
|
||||
include/linux/usb/r8152.h | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
|
||||
--- a/include/linux/usb/r8152.h
|
||||
+++ b/include/linux/usb/r8152.h
|
||||
@@ -29,6 +29,7 @@
|
||||
#define VENDOR_ID_LINKSYS 0x13b1
|
||||
#define VENDOR_ID_NVIDIA 0x0955
|
||||
#define VENDOR_ID_TPLINK 0x2357
|
||||
+#define VENDOR_ID_DLINK 0x2001
|
||||
|
||||
#if IS_REACHABLE(CONFIG_USB_RTL8152)
|
||||
extern u8 rtl8152_get_version(struct usb_interface *intf);
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -9820,6 +9820,7 @@ static const struct usb_device_id rtl815
|
||||
{ USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041) },
|
||||
{ USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) },
|
||||
{ USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) },
|
||||
+ { USB_DEVICE(VENDOR_ID_DLINK, 0xb301) },
|
||||
{}
|
||||
};
|
||||
|
@ -0,0 +1,447 @@
|
||||
From 715f67f33af45ce2cc3a5b1ef133cc8c8e7787b0 Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Anderson <dianders@chromium.org>
|
||||
Date: Fri, 20 Oct 2023 14:06:58 -0700
|
||||
Subject: [PATCH] r8152: Rename RTL8152_UNPLUG to RTL8152_INACCESSIBLE
|
||||
|
||||
Whenever the RTL8152_UNPLUG is set that just tells the driver that all
|
||||
accesses will fail and we should just immediately bail. A future patch
|
||||
will use this same concept at a time when the driver hasn't actually
|
||||
been unplugged but is about to be reset. Rename the flag in
|
||||
preparation for the future patch.
|
||||
|
||||
This is a no-op change and just a search and replace.
|
||||
|
||||
Signed-off-by: Douglas Anderson <dianders@chromium.org>
|
||||
Reviewed-by: Grant Grundler <grundler@chromium.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 96 ++++++++++++++++++++---------------------
|
||||
1 file changed, 48 insertions(+), 48 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -763,7 +763,7 @@ enum rtl_register_content {
|
||||
|
||||
/* rtl8152 flags */
|
||||
enum rtl8152_flags {
|
||||
- RTL8152_UNPLUG = 0,
|
||||
+ RTL8152_INACCESSIBLE = 0,
|
||||
RTL8152_SET_RX_MODE,
|
||||
WORK_ENABLE,
|
||||
RTL8152_LINK_CHG,
|
||||
@@ -1241,7 +1241,7 @@ int set_registers(struct r8152 *tp, u16
|
||||
static void rtl_set_unplug(struct r8152 *tp)
|
||||
{
|
||||
if (tp->udev->state == USB_STATE_NOTATTACHED) {
|
||||
- set_bit(RTL8152_UNPLUG, &tp->flags);
|
||||
+ set_bit(RTL8152_INACCESSIBLE, &tp->flags);
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
}
|
||||
@@ -1252,7 +1252,7 @@ static int generic_ocp_read(struct r8152
|
||||
u16 limit = 64;
|
||||
int ret = 0;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
/* both size and indix must be 4 bytes align */
|
||||
@@ -1296,7 +1296,7 @@ static int generic_ocp_write(struct r815
|
||||
u16 byteen_start, byteen_end, byen;
|
||||
u16 limit = 512;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
/* both size and indix must be 4 bytes align */
|
||||
@@ -1533,7 +1533,7 @@ static int read_mii_word(struct net_devi
|
||||
struct r8152 *tp = netdev_priv(netdev);
|
||||
int ret;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
if (phy_id != R8152_PHY_ID)
|
||||
@@ -1549,7 +1549,7 @@ void write_mii_word(struct net_device *n
|
||||
{
|
||||
struct r8152 *tp = netdev_priv(netdev);
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
if (phy_id != R8152_PHY_ID)
|
||||
@@ -1754,7 +1754,7 @@ static void read_bulk_callback(struct ur
|
||||
if (!tp)
|
||||
return;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
if (!test_bit(WORK_ENABLE, &tp->flags))
|
||||
@@ -1846,7 +1846,7 @@ static void write_bulk_callback(struct u
|
||||
if (!test_bit(WORK_ENABLE, &tp->flags))
|
||||
return;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
if (!skb_queue_empty(&tp->tx_queue))
|
||||
@@ -1867,7 +1867,7 @@ static void intr_callback(struct urb *ur
|
||||
if (!test_bit(WORK_ENABLE, &tp->flags))
|
||||
return;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
switch (status) {
|
||||
@@ -2611,7 +2611,7 @@ static void bottom_half(struct tasklet_s
|
||||
{
|
||||
struct r8152 *tp = from_tasklet(tp, t, tx_tl);
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
if (!test_bit(WORK_ENABLE, &tp->flags))
|
||||
@@ -2654,7 +2654,7 @@ int r8152_submit_rx(struct r8152 *tp, st
|
||||
int ret;
|
||||
|
||||
/* The rx would be stopped, so skip submitting */
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags) ||
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags) ||
|
||||
!test_bit(WORK_ENABLE, &tp->flags) || !netif_carrier_ok(tp->netdev))
|
||||
return 0;
|
||||
|
||||
@@ -3050,7 +3050,7 @@ static int rtl_enable(struct r8152 *tp)
|
||||
|
||||
static int rtl8152_enable(struct r8152 *tp)
|
||||
{
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
set_tx_qlen(tp);
|
||||
@@ -3137,7 +3137,7 @@ static int rtl8153_enable(struct r8152 *
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
set_tx_qlen(tp);
|
||||
@@ -3169,7 +3169,7 @@ static void rtl_disable(struct r8152 *tp
|
||||
u32 ocp_data;
|
||||
int i;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
|
||||
rtl_drop_queued_tx(tp);
|
||||
return;
|
||||
}
|
||||
@@ -3623,7 +3623,7 @@ static u16 r8153_phy_status(struct r8152
|
||||
}
|
||||
|
||||
msleep(20);
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3655,7 +3655,7 @@ static void r8153b_ups_en(struct r8152 *
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 500; i++) {
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
|
||||
AUTOLOAD_DONE)
|
||||
@@ -3697,7 +3697,7 @@ static void r8153c_ups_en(struct r8152 *
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 500; i++) {
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
|
||||
AUTOLOAD_DONE)
|
||||
@@ -4042,8 +4042,8 @@ static int rtl_phy_patch_request(struct
|
||||
for (i = 0; wait && i < 5000; i++) {
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
- break;
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
+ return -ENODEV;
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
ocp_data = ocp_reg_read(tp, OCP_PHY_PATCH_STAT);
|
||||
@@ -6001,7 +6001,7 @@ static int rtl8156_enable(struct r8152 *
|
||||
u32 ocp_data;
|
||||
u16 speed;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
r8156_fc_parameter(tp);
|
||||
@@ -6059,7 +6059,7 @@ static int rtl8156b_enable(struct r8152
|
||||
u32 ocp_data;
|
||||
u16 speed;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
set_tx_qlen(tp);
|
||||
@@ -6245,7 +6245,7 @@ out:
|
||||
|
||||
static void rtl8152_up(struct r8152 *tp)
|
||||
{
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8152_aldps_en(tp, false);
|
||||
@@ -6255,7 +6255,7 @@ static void rtl8152_up(struct r8152 *tp)
|
||||
|
||||
static void rtl8152_down(struct r8152 *tp)
|
||||
{
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
|
||||
rtl_drop_queued_tx(tp);
|
||||
return;
|
||||
}
|
||||
@@ -6270,7 +6270,7 @@ static void rtl8153_up(struct r8152 *tp)
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153_u1u2en(tp, false);
|
||||
@@ -6310,7 +6310,7 @@ static void rtl8153_down(struct r8152 *t
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
|
||||
rtl_drop_queued_tx(tp);
|
||||
return;
|
||||
}
|
||||
@@ -6331,7 +6331,7 @@ static void rtl8153b_up(struct r8152 *tp
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153b_u1u2en(tp, false);
|
||||
@@ -6355,7 +6355,7 @@ static void rtl8153b_down(struct r8152 *
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
|
||||
rtl_drop_queued_tx(tp);
|
||||
return;
|
||||
}
|
||||
@@ -6392,7 +6392,7 @@ static void rtl8153c_up(struct r8152 *tp
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153b_u1u2en(tp, false);
|
||||
@@ -6473,7 +6473,7 @@ static void rtl8156_up(struct r8152 *tp)
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153b_u1u2en(tp, false);
|
||||
@@ -6546,7 +6546,7 @@ static void rtl8156_down(struct r8152 *t
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
|
||||
rtl_drop_queued_tx(tp);
|
||||
return;
|
||||
}
|
||||
@@ -6684,7 +6684,7 @@ static void rtl_work_func_t(struct work_
|
||||
/* If the device is unplugged or !netif_running(), the workqueue
|
||||
* doesn't need to wake the device, and could return directly.
|
||||
*/
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags) || !netif_running(tp->netdev))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags) || !netif_running(tp->netdev))
|
||||
return;
|
||||
|
||||
if (usb_autopm_get_interface(tp->intf) < 0)
|
||||
@@ -6723,7 +6723,7 @@ static void rtl_hw_phy_work_func_t(struc
|
||||
{
|
||||
struct r8152 *tp = container_of(work, struct r8152, hw_phy_work.work);
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
if (usb_autopm_get_interface(tp->intf) < 0)
|
||||
@@ -6850,7 +6850,7 @@ static int rtl8152_close(struct net_devi
|
||||
netif_stop_queue(netdev);
|
||||
|
||||
res = usb_autopm_get_interface(tp->intf);
|
||||
- if (res < 0 || test_bit(RTL8152_UNPLUG, &tp->flags)) {
|
||||
+ if (res < 0 || test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
|
||||
rtl_drop_queued_tx(tp);
|
||||
rtl_stop_rx(tp);
|
||||
} else {
|
||||
@@ -6883,7 +6883,7 @@ static void r8152b_init(struct r8152 *tp
|
||||
u32 ocp_data;
|
||||
u16 data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
data = r8152_mdio_read(tp, MII_BMCR);
|
||||
@@ -6927,7 +6927,7 @@ static void r8153_init(struct r8152 *tp)
|
||||
u16 data;
|
||||
int i;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153_u1u2en(tp, false);
|
||||
@@ -6938,7 +6938,7 @@ static void r8153_init(struct r8152 *tp)
|
||||
break;
|
||||
|
||||
msleep(20);
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -7067,7 +7067,7 @@ static void r8153b_init(struct r8152 *tp
|
||||
u16 data;
|
||||
int i;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153b_u1u2en(tp, false);
|
||||
@@ -7078,7 +7078,7 @@ static void r8153b_init(struct r8152 *tp
|
||||
break;
|
||||
|
||||
msleep(20);
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -7149,7 +7149,7 @@ static void r8153c_init(struct r8152 *tp
|
||||
u16 data;
|
||||
int i;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153b_u1u2en(tp, false);
|
||||
@@ -7169,7 +7169,7 @@ static void r8153c_init(struct r8152 *tp
|
||||
break;
|
||||
|
||||
msleep(20);
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7998,7 +7998,7 @@ static void r8156_init(struct r8152 *tp)
|
||||
u16 data;
|
||||
int i;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_ECM_OP);
|
||||
@@ -8019,7 +8019,7 @@ static void r8156_init(struct r8152 *tp)
|
||||
break;
|
||||
|
||||
msleep(20);
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8094,7 +8094,7 @@ static void r8156b_init(struct r8152 *tp
|
||||
u16 data;
|
||||
int i;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_ECM_OP);
|
||||
@@ -8128,7 +8128,7 @@ static void r8156b_init(struct r8152 *tp
|
||||
break;
|
||||
|
||||
msleep(20);
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9153,7 +9153,7 @@ static int rtl8152_ioctl(struct net_devi
|
||||
struct mii_ioctl_data *data = if_mii(rq);
|
||||
int res;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
res = usb_autopm_get_interface(tp->intf);
|
||||
@@ -9255,7 +9255,7 @@ static const struct net_device_ops rtl81
|
||||
|
||||
static void rtl8152_unload(struct r8152 *tp)
|
||||
{
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
if (tp->version != RTL_VER_01)
|
||||
@@ -9264,7 +9264,7 @@ static void rtl8152_unload(struct r8152
|
||||
|
||||
static void rtl8153_unload(struct r8152 *tp)
|
||||
{
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153_power_cut_en(tp, false);
|
||||
@@ -9272,7 +9272,7 @@ static void rtl8153_unload(struct r8152
|
||||
|
||||
static void rtl8153b_unload(struct r8152 *tp)
|
||||
{
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153b_power_cut_en(tp, false);
|
@ -0,0 +1,398 @@
|
||||
From d9962b0d42029bcb40fe3c38bce06d1870fa4df4 Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Anderson <dianders@chromium.org>
|
||||
Date: Fri, 20 Oct 2023 14:06:59 -0700
|
||||
Subject: [PATCH] r8152: Block future register access if register access fails
|
||||
|
||||
Even though the functions to read/write registers can fail, most of
|
||||
the places in the r8152 driver that read/write register values don't
|
||||
check error codes. The lack of error code checking is problematic in
|
||||
at least two ways.
|
||||
|
||||
The first problem is that the r8152 driver often uses code patterns
|
||||
similar to this:
|
||||
x = read_register()
|
||||
x = x | SOME_BIT;
|
||||
write_register(x);
|
||||
|
||||
...with the above pattern, if the read_register() fails and returns
|
||||
garbage then we'll end up trying to write modified garbage back to the
|
||||
Realtek adapter. If the write_register() succeeds that's bad. Note
|
||||
that as of commit f53a7ad18959 ("r8152: Set memory to all 0xFFs on
|
||||
failed reg reads") the "garbage" returned by read_register() will at
|
||||
least be consistent garbage, but it is still garbage.
|
||||
|
||||
It turns out that this problem is very serious. Writing garbage to
|
||||
some of the hardware registers on the Ethernet adapter can put the
|
||||
adapter in such a bad state that it needs to be power cycled (fully
|
||||
unplugged and plugged in again) before it can enumerate again.
|
||||
|
||||
The second problem is that the r8152 driver generally has functions
|
||||
that are long sequences of register writes. Assuming everything will
|
||||
be OK if a random register write fails in the middle isn't a great
|
||||
assumption.
|
||||
|
||||
One might wonder if the above two problems are real. You could ask if
|
||||
we would really have a successful write after a failed read. It turns
|
||||
out that the answer appears to be "yes, this can happen". In fact,
|
||||
we've seen at least two distinct failure modes where this happens.
|
||||
|
||||
On a sc7180-trogdor Chromebook if you drop into kdb for a while and
|
||||
then resume, you can see:
|
||||
1. We get a "Tx timeout"
|
||||
2. The "Tx timeout" queues up a USB reset.
|
||||
3. In rtl8152_pre_reset() we try to reinit the hardware.
|
||||
4. The first several (2-9) register accesses fail with a timeout, then
|
||||
things recover.
|
||||
|
||||
The above test case was actually fixed by the patch ("r8152: Increase
|
||||
USB control msg timeout to 5000ms as per spec") but at least shows
|
||||
that we really can see successful calls after failed ones.
|
||||
|
||||
On a different (AMD) based Chromebook with a particular adapter, we
|
||||
found that during reboot tests we'd also sometimes get a transitory
|
||||
failure. In this case we saw -EPIPE being returned sometimes. Retrying
|
||||
worked, but retrying is not always safe for all register accesses
|
||||
since reading/writing some registers might have side effects (like
|
||||
registers that clear on read).
|
||||
|
||||
Let's fully lock out all register access if a register access fails.
|
||||
When we do this, we'll try to queue up a USB reset and try to unlock
|
||||
register access after the reset. This is slightly tricker than it
|
||||
sounds since the r8152 driver has an optimized reset sequence that
|
||||
only works reliably after probe happens. In order to handle this, we
|
||||
avoid the optimized reset if probe didn't finish. Instead, we simply
|
||||
retry the probe routine in this case.
|
||||
|
||||
When locking out access, we'll use the existing infrastructure that
|
||||
the driver was using when it detected we were unplugged. This keeps us
|
||||
from getting stuck in delay loops in some parts of the driver.
|
||||
|
||||
Signed-off-by: Douglas Anderson <dianders@chromium.org>
|
||||
Reviewed-by: Grant Grundler <grundler@chromium.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 207 ++++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 176 insertions(+), 31 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -772,6 +772,9 @@ enum rtl8152_flags {
|
||||
SCHEDULE_TASKLET,
|
||||
GREEN_ETHERNET,
|
||||
RX_EPROTO,
|
||||
+ IN_PRE_RESET,
|
||||
+ PROBED_WITH_NO_ERRORS,
|
||||
+ PROBE_SHOULD_RETRY,
|
||||
};
|
||||
|
||||
#define DEVICE_ID_THINKPAD_ONELINK_PLUS_DOCK 0x3054
|
||||
@@ -949,6 +952,8 @@ struct r8152 {
|
||||
u8 version;
|
||||
u8 duplex;
|
||||
u8 autoneg;
|
||||
+
|
||||
+ unsigned int reg_access_reset_count;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1196,6 +1201,96 @@ static unsigned int agg_buf_sz = 16384;
|
||||
|
||||
#define RTL_LIMITED_TSO_SIZE (size_to_mtu(agg_buf_sz) - sizeof(struct tx_desc))
|
||||
|
||||
+/* If register access fails then we block access and issue a reset. If this
|
||||
+ * happens too many times in a row without a successful access then we stop
|
||||
+ * trying to reset and just leave access blocked.
|
||||
+ */
|
||||
+#define REGISTER_ACCESS_MAX_RESETS 3
|
||||
+
|
||||
+static void rtl_set_inaccessible(struct r8152 *tp)
|
||||
+{
|
||||
+ set_bit(RTL8152_INACCESSIBLE, &tp->flags);
|
||||
+ smp_mb__after_atomic();
|
||||
+}
|
||||
+
|
||||
+static void rtl_set_accessible(struct r8152 *tp)
|
||||
+{
|
||||
+ clear_bit(RTL8152_INACCESSIBLE, &tp->flags);
|
||||
+ smp_mb__after_atomic();
|
||||
+}
|
||||
+
|
||||
+static
|
||||
+int r8152_control_msg(struct r8152 *tp, unsigned int pipe, __u8 request,
|
||||
+ __u8 requesttype, __u16 value, __u16 index, void *data,
|
||||
+ __u16 size, const char *msg_tag)
|
||||
+{
|
||||
+ struct usb_device *udev = tp->udev;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ret = usb_control_msg(udev, pipe, request, requesttype,
|
||||
+ value, index, data, size,
|
||||
+ USB_CTRL_GET_TIMEOUT);
|
||||
+
|
||||
+ /* No need to issue a reset to report an error if the USB device got
|
||||
+ * unplugged; just return immediately.
|
||||
+ */
|
||||
+ if (ret == -ENODEV)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* If the write was successful then we're done */
|
||||
+ if (ret >= 0) {
|
||||
+ tp->reg_access_reset_count = 0;
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ dev_err(&udev->dev,
|
||||
+ "Failed to %s %d bytes at %#06x/%#06x (%d)\n",
|
||||
+ msg_tag, size, value, index, ret);
|
||||
+
|
||||
+ /* Block all future register access until we reset. Much of the code
|
||||
+ * in the driver doesn't check for errors. Notably, many parts of the
|
||||
+ * driver do a read/modify/write of a register value without
|
||||
+ * confirming that the read succeeded. Writing back modified garbage
|
||||
+ * like this can fully wedge the adapter, requiring a power cycle.
|
||||
+ */
|
||||
+ rtl_set_inaccessible(tp);
|
||||
+
|
||||
+ /* If probe hasn't yet finished, then we'll request a retry of the
|
||||
+ * whole probe routine if we get any control transfer errors. We
|
||||
+ * never have to clear this bit since we free/reallocate the whole "tp"
|
||||
+ * structure if we retry probe.
|
||||
+ */
|
||||
+ if (!test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) {
|
||||
+ set_bit(PROBE_SHOULD_RETRY, &tp->flags);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Failing to access registers in pre-reset is not surprising since we
|
||||
+ * wouldn't be resetting if things were behaving normally. The register
|
||||
+ * access we do in pre-reset isn't truly mandatory--we're just reusing
|
||||
+ * the disable() function and trying to be nice by powering the
|
||||
+ * adapter down before resetting it. Thus, if we're in pre-reset,
|
||||
+ * we'll return right away and not try to queue up yet another reset.
|
||||
+ * We know the post-reset is already coming.
|
||||
+ */
|
||||
+ if (test_bit(IN_PRE_RESET, &tp->flags))
|
||||
+ return ret;
|
||||
+
|
||||
+ if (tp->reg_access_reset_count < REGISTER_ACCESS_MAX_RESETS) {
|
||||
+ usb_queue_reset_device(tp->intf);
|
||||
+ tp->reg_access_reset_count++;
|
||||
+ } else if (tp->reg_access_reset_count == REGISTER_ACCESS_MAX_RESETS) {
|
||||
+ dev_err(&udev->dev,
|
||||
+ "Tried to reset %d times; giving up.\n",
|
||||
+ REGISTER_ACCESS_MAX_RESETS);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static
|
||||
int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
|
||||
{
|
||||
@@ -1206,9 +1301,10 @@ int get_registers(struct r8152 *tp, u16
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
- ret = usb_control_msg(tp->udev, tp->pipe_ctrl_in,
|
||||
- RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
|
||||
- value, index, tmp, size, USB_CTRL_GET_TIMEOUT);
|
||||
+ ret = r8152_control_msg(tp, tp->pipe_ctrl_in,
|
||||
+ RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
|
||||
+ value, index, tmp, size, "read");
|
||||
+
|
||||
if (ret < 0)
|
||||
memset(data, 0xff, size);
|
||||
else
|
||||
@@ -1229,9 +1325,9 @@ int set_registers(struct r8152 *tp, u16
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
- ret = usb_control_msg(tp->udev, tp->pipe_ctrl_out,
|
||||
- RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
|
||||
- value, index, tmp, size, USB_CTRL_SET_TIMEOUT);
|
||||
+ ret = r8152_control_msg(tp, tp->pipe_ctrl_out,
|
||||
+ RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
|
||||
+ value, index, tmp, size, "write");
|
||||
|
||||
kfree(tmp);
|
||||
|
||||
@@ -1240,10 +1336,8 @@ int set_registers(struct r8152 *tp, u16
|
||||
|
||||
static void rtl_set_unplug(struct r8152 *tp)
|
||||
{
|
||||
- if (tp->udev->state == USB_STATE_NOTATTACHED) {
|
||||
- set_bit(RTL8152_INACCESSIBLE, &tp->flags);
|
||||
- smp_mb__after_atomic();
|
||||
- }
|
||||
+ if (tp->udev->state == USB_STATE_NOTATTACHED)
|
||||
+ rtl_set_inaccessible(tp);
|
||||
}
|
||||
|
||||
static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
|
||||
@@ -8254,7 +8348,7 @@ static int rtl8152_pre_reset(struct usb_
|
||||
struct r8152 *tp = usb_get_intfdata(intf);
|
||||
struct net_device *netdev;
|
||||
|
||||
- if (!tp)
|
||||
+ if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags))
|
||||
return 0;
|
||||
|
||||
netdev = tp->netdev;
|
||||
@@ -8269,7 +8363,9 @@ static int rtl8152_pre_reset(struct usb_
|
||||
napi_disable(&tp->napi);
|
||||
if (netif_carrier_ok(netdev)) {
|
||||
mutex_lock(&tp->control);
|
||||
+ set_bit(IN_PRE_RESET, &tp->flags);
|
||||
tp->rtl_ops.disable(tp);
|
||||
+ clear_bit(IN_PRE_RESET, &tp->flags);
|
||||
mutex_unlock(&tp->control);
|
||||
}
|
||||
|
||||
@@ -8282,9 +8378,11 @@ static int rtl8152_post_reset(struct usb
|
||||
struct net_device *netdev;
|
||||
struct sockaddr sa;
|
||||
|
||||
- if (!tp)
|
||||
+ if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags))
|
||||
return 0;
|
||||
|
||||
+ rtl_set_accessible(tp);
|
||||
+
|
||||
/* reset the MAC address in case of policy change */
|
||||
if (determine_ethernet_addr(tp, &sa) >= 0) {
|
||||
rtnl_lock();
|
||||
@@ -9482,17 +9580,29 @@ static u8 __rtl_get_hw_ver(struct usb_de
|
||||
__le32 *tmp;
|
||||
u8 version;
|
||||
int ret;
|
||||
+ int i;
|
||||
|
||||
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||||
if (!tmp)
|
||||
return 0;
|
||||
|
||||
- ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
- RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
|
||||
- PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp),
|
||||
- USB_CTRL_GET_TIMEOUT);
|
||||
- if (ret > 0)
|
||||
- ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK;
|
||||
+ /* Retry up to 3 times in case there is a transitory error. We do this
|
||||
+ * since retrying a read of the version is always safe and this
|
||||
+ * function doesn't take advantage of r8152_control_msg().
|
||||
+ */
|
||||
+ for (i = 0; i < 3; i++) {
|
||||
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
+ RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
|
||||
+ PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp),
|
||||
+ USB_CTRL_GET_TIMEOUT);
|
||||
+ if (ret > 0) {
|
||||
+ ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (i != 0 && ret > 0)
|
||||
+ dev_warn(&udev->dev, "Needed %d retries to read version\n", i);
|
||||
|
||||
kfree(tmp);
|
||||
|
||||
@@ -9566,25 +9676,14 @@ u8 rtl8152_get_version(struct usb_interf
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rtl8152_get_version);
|
||||
|
||||
-static int rtl8152_probe(struct usb_interface *intf,
|
||||
- const struct usb_device_id *id)
|
||||
+static int rtl8152_probe_once(struct usb_interface *intf,
|
||||
+ const struct usb_device_id *id, u8 version)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct r8152 *tp;
|
||||
struct net_device *netdev;
|
||||
- u8 version;
|
||||
int ret;
|
||||
|
||||
- if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
|
||||
- return -ENODEV;
|
||||
-
|
||||
- if (!rtl_check_vendor_ok(intf))
|
||||
- return -ENODEV;
|
||||
-
|
||||
- version = rtl8152_get_version(intf);
|
||||
- if (version == RTL_VER_UNKNOWN)
|
||||
- return -ENODEV;
|
||||
-
|
||||
usb_reset_device(udev);
|
||||
netdev = alloc_etherdev(sizeof(struct r8152));
|
||||
if (!netdev) {
|
||||
@@ -9757,10 +9856,20 @@ static int rtl8152_probe(struct usb_inte
|
||||
else
|
||||
device_set_wakeup_enable(&udev->dev, false);
|
||||
|
||||
+ /* If we saw a control transfer error while probing then we may
|
||||
+ * want to try probe() again. Consider this an error.
|
||||
+ */
|
||||
+ if (test_bit(PROBE_SHOULD_RETRY, &tp->flags))
|
||||
+ goto out2;
|
||||
+
|
||||
+ set_bit(PROBED_WITH_NO_ERRORS, &tp->flags);
|
||||
netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION);
|
||||
|
||||
return 0;
|
||||
|
||||
+out2:
|
||||
+ unregister_netdev(netdev);
|
||||
+
|
||||
out1:
|
||||
tasklet_kill(&tp->tx_tl);
|
||||
cancel_delayed_work_sync(&tp->hw_phy_work);
|
||||
@@ -9769,10 +9878,46 @@ out1:
|
||||
rtl8152_release_firmware(tp);
|
||||
usb_set_intfdata(intf, NULL);
|
||||
out:
|
||||
+ if (test_bit(PROBE_SHOULD_RETRY, &tp->flags))
|
||||
+ ret = -EAGAIN;
|
||||
+
|
||||
free_netdev(netdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+#define RTL8152_PROBE_TRIES 3
|
||||
+
|
||||
+static int rtl8152_probe(struct usb_interface *intf,
|
||||
+ const struct usb_device_id *id)
|
||||
+{
|
||||
+ u8 version;
|
||||
+ int ret;
|
||||
+ int i;
|
||||
+
|
||||
+ if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ if (!rtl_check_vendor_ok(intf))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ version = rtl8152_get_version(intf);
|
||||
+ if (version == RTL_VER_UNKNOWN)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ for (i = 0; i < RTL8152_PROBE_TRIES; i++) {
|
||||
+ ret = rtl8152_probe_once(intf, id, version);
|
||||
+ if (ret != -EAGAIN)
|
||||
+ break;
|
||||
+ }
|
||||
+ if (ret == -EAGAIN) {
|
||||
+ dev_err(&intf->dev,
|
||||
+ "r8152 failed probe after %d tries; giving up\n", i);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static void rtl8152_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct r8152 *tp = usb_get_intfdata(intf);
|
@ -0,0 +1,83 @@
|
||||
From 66eee612a1ba39f9a76a9ace4a34d012044767fb Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Tue, 26 Sep 2023 19:17:13 +0800
|
||||
Subject: [PATCH] r8152: break the loop when the budget is exhausted
|
||||
|
||||
[ Upstream commit 2cf51f931797d9a47e75d999d0993a68cbd2a560 ]
|
||||
|
||||
A bulk transfer of the USB may contain many packets. And, the total
|
||||
number of the packets in the bulk transfer may be more than budget.
|
||||
|
||||
Originally, only budget packets would be handled by napi_gro_receive(),
|
||||
and the other packets would be queued in the driver for next schedule.
|
||||
|
||||
This patch would break the loop about getting next bulk transfer, when
|
||||
the budget is exhausted. That is, only the current bulk transfer would
|
||||
be handled, and the other bulk transfers would be queued for next
|
||||
schedule. Besides, the packets which are more than the budget in the
|
||||
current bulk trasnfer would be still queued in the driver, as the
|
||||
original method.
|
||||
|
||||
In addition, a bulk transfer wouldn't contain more than 400 packets, so
|
||||
the check of queue length is unnecessary. Therefore, I replace it with
|
||||
WARN_ON_ONCE().
|
||||
|
||||
Fixes: cf74eb5a5bc8 ("eth: r8152: try to use a normal budget")
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Link: https://lore.kernel.org/r/20230926111714.9448-433-nic_swsd@realtek.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
Signed-off-by: Sasha Levin <sashal@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 18 +++++++++++++-----
|
||||
1 file changed, 13 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -2539,7 +2539,7 @@ static int rx_bottom(struct r8152 *tp, i
|
||||
}
|
||||
}
|
||||
|
||||
- if (list_empty(&tp->rx_done))
|
||||
+ if (list_empty(&tp->rx_done) || work_done >= budget)
|
||||
goto out1;
|
||||
|
||||
clear_bit(RX_EPROTO, &tp->flags);
|
||||
@@ -2555,6 +2555,15 @@ static int rx_bottom(struct r8152 *tp, i
|
||||
struct urb *urb;
|
||||
u8 *rx_data;
|
||||
|
||||
+ /* A bulk transfer of USB may contain may packets, so the
|
||||
+ * total packets may more than the budget. Deal with all
|
||||
+ * packets in current bulk transfer, and stop to handle the
|
||||
+ * next bulk transfer until next schedule, if budget is
|
||||
+ * exhausted.
|
||||
+ */
|
||||
+ if (work_done >= budget)
|
||||
+ break;
|
||||
+
|
||||
list_del_init(cursor);
|
||||
|
||||
agg = list_entry(cursor, struct rx_agg, list);
|
||||
@@ -2574,9 +2583,7 @@ static int rx_bottom(struct r8152 *tp, i
|
||||
unsigned int pkt_len, rx_frag_head_sz;
|
||||
struct sk_buff *skb;
|
||||
|
||||
- /* limit the skb numbers for rx_queue */
|
||||
- if (unlikely(skb_queue_len(&tp->rx_queue) >= 1000))
|
||||
- break;
|
||||
+ WARN_ON_ONCE(skb_queue_len(&tp->rx_queue) >= 1000);
|
||||
|
||||
pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
|
||||
if (pkt_len < ETH_ZLEN)
|
||||
@@ -2654,9 +2661,10 @@ submit:
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Splice the remained list back to rx_done for next schedule */
|
||||
if (!list_empty(&rx_queue)) {
|
||||
spin_lock_irqsave(&tp->rx_lock, flags);
|
||||
- list_splice_tail(&rx_queue, &tp->rx_done);
|
||||
+ list_splice(&rx_queue, &tp->rx_done);
|
||||
spin_unlock_irqrestore(&tp->rx_lock, flags);
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
From 1b0fce8c8e69485e49a7d34aac3d4c2a2aa15d62 Mon Sep 17 00:00:00 2001
|
||||
From: Davide Tronchin <davide.tronchin.94@gmail.com>
|
||||
Date: Thu, 29 Jun 2023 12:37:36 +0200
|
||||
Subject: [PATCH] net: usb: cdc_ether: add u-blox 0x1313 composition.
|
||||
|
||||
Add CDC-ECM support for LARA-R6 01B.
|
||||
|
||||
The new LARA-R6 product variant identified by the "01B" string can be
|
||||
configured (by AT interface) in three different USB modes:
|
||||
* Default mode (Vendor ID: 0x1546 Product ID: 0x1311) with 4 serial
|
||||
interfaces
|
||||
* RmNet mode (Vendor ID: 0x1546 Product ID: 0x1312) with 4 serial
|
||||
interfaces and 1 RmNet virtual network interface
|
||||
* CDC-ECM mode (Vendor ID: 0x1546 Product ID: 0x1313) with 4 serial
|
||||
interface and 1 CDC-ECM virtual network interface
|
||||
The first 4 interfaces of all the 3 configurations (default, RmNet, ECM)
|
||||
are the same.
|
||||
|
||||
In CDC-ECM mode LARA-R6 01B exposes the following interfaces:
|
||||
If 0: Diagnostic
|
||||
If 1: AT parser
|
||||
If 2: AT parser
|
||||
If 3: AT parset/alternative functions
|
||||
If 4: CDC-ECM interface
|
||||
|
||||
Signed-off-by: Davide Tronchin <davide.tronchin.94@gmail.com>
|
||||
Reviewed-by: Simon Horman <simon.horman@corigine.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/cdc_ether.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
--- a/drivers/net/usb/cdc_ether.c
|
||||
+++ b/drivers/net/usb/cdc_ether.c
|
||||
@@ -878,6 +878,12 @@ static const struct usb_device_id produc
|
||||
USB_CDC_PROTO_NONE),
|
||||
.driver_info = (unsigned long)&wwan_info,
|
||||
}, {
|
||||
+ /* U-blox LARA-R6 01B */
|
||||
+ USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1313, USB_CLASS_COMM,
|
||||
+ USB_CDC_SUBCLASS_ETHERNET,
|
||||
+ USB_CDC_PROTO_NONE),
|
||||
+ .driver_info = (unsigned long)&wwan_info,
|
||||
+}, {
|
||||
/* ZTE modules */
|
||||
USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET,
|
@ -0,0 +1,229 @@
|
||||
From ec51fbd1b8a2bca2948dede99c14ec63dc57ff6b Mon Sep 17 00:00:00 2001
|
||||
From: Bjørn Mork <bjorn@mork.no>
|
||||
Date: Fri, 6 Jan 2023 17:07:38 +0100
|
||||
Subject: [PATCH] r8152: add USB device driver for config selection
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Subclassing the generic USB device driver to override the
|
||||
default configuration selection regardless of matching interface
|
||||
drivers.
|
||||
|
||||
The r815x family devices expose a vendor specific function which
|
||||
the r8152 interface driver wants to handle. This is the preferred
|
||||
device mode. Additionally one or more USB class functions are
|
||||
usually supported for hosts lacking a vendor specific driver. The
|
||||
choice is USB configuration based, with one alternate function per
|
||||
configuration.
|
||||
|
||||
Example device with both NCM and ECM alternate cfgs:
|
||||
|
||||
T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=5000 MxCh= 0
|
||||
D: Ver= 3.20 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 3
|
||||
P: Vendor=0bda ProdID=8156 Rev=31.00
|
||||
S: Manufacturer=Realtek
|
||||
S: Product=USB 10/100/1G/2.5G LAN
|
||||
S: SerialNumber=001000001
|
||||
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=256mA
|
||||
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=00 Driver=r8152
|
||||
E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
|
||||
E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
|
||||
E: Ad=83(I) Atr=03(Int.) MxPS= 2 Ivl=128ms
|
||||
C: #Ifs= 2 Cfg#= 2 Atr=a0 MxPwr=256mA
|
||||
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=0d Prot=00 Driver=
|
||||
E: Ad=83(I) Atr=03(Int.) MxPS= 16 Ivl=128ms
|
||||
I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=01 Driver=
|
||||
I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=01 Driver=
|
||||
E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
|
||||
E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
|
||||
C: #Ifs= 2 Cfg#= 3 Atr=a0 MxPwr=256mA
|
||||
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=06 Prot=00 Driver=
|
||||
E: Ad=83(I) Atr=03(Int.) MxPS= 16 Ivl=128ms
|
||||
I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=00 Driver=
|
||||
I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=
|
||||
E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
|
||||
E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
|
||||
|
||||
A problem with this is that Linux will prefer class functions over
|
||||
vendor specific functions. Using the above example, Linux defaults
|
||||
to cfg #2, running the device in a sub-optimal NCM mode.
|
||||
|
||||
Previously we've attempted to work around the problem by
|
||||
blacklisting the devices in the ECM class driver "cdc_ether", and
|
||||
matching on the ECM class function in the vendor specific interface
|
||||
driver. The latter has been used to switch back to the vendor
|
||||
specific configuration when the driver is probed for a class
|
||||
function.
|
||||
|
||||
This workaround has several issues;
|
||||
- class driver blacklists is additional maintanence cruft in an
|
||||
unrelated driver
|
||||
- class driver blacklists prevents users from optionally running
|
||||
the devices in class mode
|
||||
- each device needs double match entries in the vendor driver
|
||||
- the initial probing as a class function slows down device
|
||||
discovery
|
||||
|
||||
Now these issues have become even worse with the introduction of
|
||||
firmware supporting both NCM and ECM, where NCM ends up as the
|
||||
default mode in Linux. To use the same workaround, we now have
|
||||
to blacklist the devices in to two different class drivers and
|
||||
add yet another match entry to the vendor specific driver.
|
||||
|
||||
This patch implements an alternative workaround strategy -
|
||||
independent of the interface drivers. It avoids adding a
|
||||
blacklist to the cdc_ncm driver and will let us remove the
|
||||
existing blacklist from the cdc_ether driver.
|
||||
|
||||
As an additional bonus, removing the blacklists allow users to
|
||||
select one of the other device modes if wanted.
|
||||
|
||||
Signed-off-by: Bjørn Mork <bjorn@mork.no>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 113 ++++++++++++++++++++++++++++------------
|
||||
1 file changed, 81 insertions(+), 32 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -9661,6 +9661,9 @@ static int rtl8152_probe(struct usb_inte
|
||||
if (version == RTL_VER_UNKNOWN)
|
||||
return -ENODEV;
|
||||
|
||||
+ if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
if (!rtl_vendor_mode(intf))
|
||||
return -ENODEV;
|
||||
|
||||
@@ -9861,43 +9864,35 @@ static void rtl8152_disconnect(struct us
|
||||
}
|
||||
}
|
||||
|
||||
-#define REALTEK_USB_DEVICE(vend, prod) { \
|
||||
- USB_DEVICE_INTERFACE_CLASS(vend, prod, USB_CLASS_VENDOR_SPEC), \
|
||||
-}, \
|
||||
-{ \
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(vend, prod, USB_CLASS_COMM, \
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), \
|
||||
-}
|
||||
|
||||
/* table of devices that work with this driver */
|
||||
static const struct usb_device_id rtl8152_table[] = {
|
||||
/* Realtek */
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8050),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8053),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8155),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8156),
|
||||
+ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8050) },
|
||||
+ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8053) },
|
||||
+ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8152) },
|
||||
+ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8153) },
|
||||
+ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8155) },
|
||||
+ { USB_DEVICE(VENDOR_ID_REALTEK, 0x8156) },
|
||||
|
||||
/* Microsoft */
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0c5e),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3054),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3062),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3069),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3082),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x721e),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0xa387),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff),
|
||||
- REALTEK_USB_DEVICE(VENDOR_ID_TPLINK, 0x0601),
|
||||
+ { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab) },
|
||||
+ { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6) },
|
||||
+ { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927) },
|
||||
+ { USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x304f) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3054) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3062) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3069) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3082) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x7205) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x720c) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x7214) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x721e) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0xa387) },
|
||||
+ { USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041) },
|
||||
+ { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) },
|
||||
+ { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -9917,7 +9912,61 @@ static struct usb_driver rtl8152_driver
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
};
|
||||
|
||||
-module_usb_driver(rtl8152_driver);
|
||||
+static int rtl8152_cfgselector_probe(struct usb_device *udev)
|
||||
+{
|
||||
+ struct usb_host_config *c;
|
||||
+ int i, num_configs;
|
||||
+
|
||||
+ /* The vendor mode is not always config #1, so to find it out. */
|
||||
+ c = udev->config;
|
||||
+ num_configs = udev->descriptor.bNumConfigurations;
|
||||
+ for (i = 0; i < num_configs; (i++, c++)) {
|
||||
+ struct usb_interface_descriptor *desc = NULL;
|
||||
+
|
||||
+ if (!c->desc.bNumInterfaces)
|
||||
+ continue;
|
||||
+ desc = &c->intf_cache[0]->altsetting->desc;
|
||||
+ if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (i == num_configs)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ if (usb_set_configuration(udev, c->desc.bConfigurationValue)) {
|
||||
+ dev_err(&udev->dev, "Failed to set configuration %d\n",
|
||||
+ c->desc.bConfigurationValue);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct usb_device_driver rtl8152_cfgselector_driver = {
|
||||
+ .name = MODULENAME "-cfgselector",
|
||||
+ .probe = rtl8152_cfgselector_probe,
|
||||
+ .id_table = rtl8152_table,
|
||||
+ .generic_subclass = 1,
|
||||
+};
|
||||
+
|
||||
+static int __init rtl8152_driver_init(void)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = usb_register_device_driver(&rtl8152_cfgselector_driver, THIS_MODULE);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ return usb_register(&rtl8152_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit rtl8152_driver_exit(void)
|
||||
+{
|
||||
+ usb_deregister(&rtl8152_driver);
|
||||
+ usb_deregister_device_driver(&rtl8152_cfgselector_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(rtl8152_driver_init);
|
||||
+module_exit(rtl8152_driver_exit);
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
@ -0,0 +1,158 @@
|
||||
From 69649ef8405320f81497f4757faac8234f61b167 Mon Sep 17 00:00:00 2001
|
||||
From: Bjørn Mork <bjorn@mork.no>
|
||||
Date: Fri, 6 Jan 2023 17:07:39 +0100
|
||||
Subject: [PATCH] cdc_ether: no need to blacklist any r8152 devices
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The r8152 driver does not need this anymore.
|
||||
|
||||
Dropping blacklist entries adds optional support for these
|
||||
devices in ECM mode.
|
||||
|
||||
The 8153 devices are handled by the r8153_ecm driver when
|
||||
in ECM mode, and must still be blacklisted here.
|
||||
|
||||
Signed-off-by: Bjørn Mork <bjorn@mork.no>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/cdc_ether.c | 114 ------------------------------------
|
||||
1 file changed, 114 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/cdc_ether.c
|
||||
+++ b/drivers/net/usb/cdc_ether.c
|
||||
@@ -768,13 +768,6 @@ static const struct usb_device_id produc
|
||||
.driver_info = 0,
|
||||
},
|
||||
|
||||
-/* Realtek RTL8152 Based USB 2.0 Ethernet Adapters */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
/* Realtek RTL8153 Based USB 3.0 Ethernet Adapters */
|
||||
{
|
||||
USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM,
|
||||
@@ -782,119 +775,12 @@ static const struct usb_device_id produc
|
||||
.driver_info = 0,
|
||||
},
|
||||
|
||||
-/* Samsung USB Ethernet Adapters */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, 0xa101, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-#if IS_ENABLED(CONFIG_USB_RTL8152)
|
||||
-/* Linksys USB3GIGV1 Ethernet Adapter */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LINKSYS_VENDOR_ID, 0x0041, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-#endif
|
||||
-
|
||||
-/* Lenovo ThinkPad OneLink+ Dock (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3054, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* ThinkPad USB-C Dock (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* ThinkPad Thunderbolt 3 Dock (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3069, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* ThinkPad Thunderbolt 3 Dock Gen 2 (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3082, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* Lenovo USB C to Ethernet Adapter (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x720c, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* Lenovo USB-C Travel Hub (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7214, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
/* Lenovo Powered USB-C Travel Hub (4X90S92381, based on Realtek RTL8153) */
|
||||
{
|
||||
USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x721e, USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
.driver_info = 0,
|
||||
},
|
||||
-
|
||||
-/* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* Microsoft Surface 2 dock (based on Realtek RTL8152) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07ab, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153B) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x0927, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
-
|
||||
-/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
|
||||
-{
|
||||
- USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM,
|
||||
- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
- .driver_info = 0,
|
||||
-},
|
||||
|
||||
/* Aquantia AQtion USB to 5GbE Controller (based on AQC111U) */
|
||||
{
|
@ -0,0 +1,64 @@
|
||||
From 0d4cda805a183bbe523f2407edb5c14ade50b841 Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Tue, 17 Jan 2023 11:03:44 +0800
|
||||
Subject: [PATCH] r8152: avoid to change cfg for all devices
|
||||
|
||||
The rtl8152_cfgselector_probe() should set the USB configuration to the
|
||||
vendor mode only for the devices which the driver (r8152) supports.
|
||||
Otherwise, no driver would be used for such devices.
|
||||
|
||||
Fixes: ec51fbd1b8a2 ("r8152: add USB device driver for config selection")
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Reviewed-by: Simon Horman <simon.horman@corigine.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 20 +++++++++++++++++---
|
||||
1 file changed, 17 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -9542,9 +9542,8 @@ static int rtl_fw_init(struct r8152 *tp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-u8 rtl8152_get_version(struct usb_interface *intf)
|
||||
+static u8 __rtl_get_hw_ver(struct usb_device *udev)
|
||||
{
|
||||
- struct usb_device *udev = interface_to_usbdev(intf);
|
||||
u32 ocp_data = 0;
|
||||
__le32 *tmp;
|
||||
u8 version;
|
||||
@@ -9614,10 +9613,19 @@ u8 rtl8152_get_version(struct usb_interf
|
||||
break;
|
||||
default:
|
||||
version = RTL_VER_UNKNOWN;
|
||||
- dev_info(&intf->dev, "Unknown version 0x%04x\n", ocp_data);
|
||||
+ dev_info(&udev->dev, "Unknown version 0x%04x\n", ocp_data);
|
||||
break;
|
||||
}
|
||||
|
||||
+ return version;
|
||||
+}
|
||||
+
|
||||
+u8 rtl8152_get_version(struct usb_interface *intf)
|
||||
+{
|
||||
+ u8 version;
|
||||
+
|
||||
+ version = __rtl_get_hw_ver(interface_to_usbdev(intf));
|
||||
+
|
||||
dev_dbg(&intf->dev, "Detected version 0x%04x\n", version);
|
||||
|
||||
return version;
|
||||
@@ -9917,6 +9925,12 @@ static int rtl8152_cfgselector_probe(str
|
||||
struct usb_host_config *c;
|
||||
int i, num_configs;
|
||||
|
||||
+ /* Switch the device to vendor mode, if and only if the vendor mode
|
||||
+ * driver supports it.
|
||||
+ */
|
||||
+ if (__rtl_get_hw_ver(udev) == RTL_VER_UNKNOWN)
|
||||
+ return 0;
|
||||
+
|
||||
/* The vendor mode is not always config #1, so to find it out. */
|
||||
c = udev->config;
|
||||
num_configs = udev->descriptor.bNumConfigurations;
|
@ -0,0 +1,71 @@
|
||||
From 95a4c1d617b92cdc4522297741b56e8f6cd01a1e Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Thu, 19 Jan 2023 15:40:42 +0800
|
||||
Subject: [PATCH] r8152: remove rtl_vendor_mode function
|
||||
|
||||
After commit ec51fbd1b8a2 ("r8152: add USB device driver for
|
||||
config selection"), the code about changing USB configuration
|
||||
in rtl_vendor_mode() wouldn't be run anymore. Therefore, the
|
||||
function could be removed.
|
||||
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 39 +--------------------------------------
|
||||
1 file changed, 1 insertion(+), 38 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -8274,43 +8274,6 @@ static bool rtl_check_vendor_ok(struct u
|
||||
return true;
|
||||
}
|
||||
|
||||
-static bool rtl_vendor_mode(struct usb_interface *intf)
|
||||
-{
|
||||
- struct usb_host_interface *alt = intf->cur_altsetting;
|
||||
- struct usb_device *udev;
|
||||
- struct usb_host_config *c;
|
||||
- int i, num_configs;
|
||||
-
|
||||
- if (alt->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC)
|
||||
- return rtl_check_vendor_ok(intf);
|
||||
-
|
||||
- /* The vendor mode is not always config #1, so to find it out. */
|
||||
- udev = interface_to_usbdev(intf);
|
||||
- c = udev->config;
|
||||
- num_configs = udev->descriptor.bNumConfigurations;
|
||||
- if (num_configs < 2)
|
||||
- return false;
|
||||
-
|
||||
- for (i = 0; i < num_configs; (i++, c++)) {
|
||||
- struct usb_interface_descriptor *desc = NULL;
|
||||
-
|
||||
- if (c->desc.bNumInterfaces > 0)
|
||||
- desc = &c->intf_cache[0]->altsetting->desc;
|
||||
- else
|
||||
- continue;
|
||||
-
|
||||
- if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
|
||||
- usb_driver_set_configuration(udev, c->desc.bConfigurationValue);
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (i == num_configs)
|
||||
- dev_err(&intf->dev, "Unexpected Device\n");
|
||||
-
|
||||
- return false;
|
||||
-}
|
||||
-
|
||||
static int rtl8152_pre_reset(struct usb_interface *intf)
|
||||
{
|
||||
struct r8152 *tp = usb_get_intfdata(intf);
|
||||
@@ -9672,7 +9635,7 @@ static int rtl8152_probe(struct usb_inte
|
||||
if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
|
||||
return -ENODEV;
|
||||
|
||||
- if (!rtl_vendor_mode(intf))
|
||||
+ if (!rtl_check_vendor_ok(intf))
|
||||
return -ENODEV;
|
||||
|
||||
usb_reset_device(udev);
|
@ -0,0 +1,46 @@
|
||||
From 02767440e1dda9861a11ca1dbe0f19a760b1d5c2 Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Thu, 19 Jan 2023 15:40:43 +0800
|
||||
Subject: [PATCH] r8152: reduce the control transfer of rtl8152_get_version()
|
||||
|
||||
Reduce the control transfer by moving calling rtl8152_get_version() in
|
||||
rtl8152_probe(). This could prevent from calling rtl8152_get_version()
|
||||
for unnecessary situations. For example, after setting config #2 for the
|
||||
device, there are two interfaces and rtl8152_probe() may be called
|
||||
twice. However, we don't need to call rtl8152_get_version() for this
|
||||
situation.
|
||||
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -9624,20 +9624,21 @@ static int rtl8152_probe(struct usb_inte
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
- u8 version = rtl8152_get_version(intf);
|
||||
struct r8152 *tp;
|
||||
struct net_device *netdev;
|
||||
+ u8 version;
|
||||
int ret;
|
||||
|
||||
- if (version == RTL_VER_UNKNOWN)
|
||||
- return -ENODEV;
|
||||
-
|
||||
if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
|
||||
return -ENODEV;
|
||||
|
||||
if (!rtl_check_vendor_ok(intf))
|
||||
return -ENODEV;
|
||||
|
||||
+ version = rtl8152_get_version(intf);
|
||||
+ if (version == RTL_VER_UNKNOWN)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
usb_reset_device(udev);
|
||||
netdev = alloc_etherdev(sizeof(struct r8152));
|
||||
if (!netdev) {
|
@ -0,0 +1,55 @@
|
||||
From 5cc33f139e11b893ff6dc60d8a0ae865a65521ac Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Anderson <dianders@chromium.org>
|
||||
Date: Thu, 6 Apr 2023 17:14:26 -0700
|
||||
Subject: [PATCH] r8152: Add __GFP_NOWARN to big allocations
|
||||
|
||||
When memory is a little tight on my system, it's pretty easy to see
|
||||
warnings that look like this.
|
||||
|
||||
ksoftirqd/0: page allocation failure: order:3, mode:0x40a20(GFP_ATOMIC|__GFP_COMP), nodemask=(null),cpuset=/,mems_allowed=0
|
||||
...
|
||||
Call trace:
|
||||
dump_backtrace+0x0/0x1e8
|
||||
show_stack+0x20/0x2c
|
||||
dump_stack_lvl+0x60/0x78
|
||||
dump_stack+0x18/0x38
|
||||
warn_alloc+0x104/0x174
|
||||
__alloc_pages+0x588/0x67c
|
||||
alloc_rx_agg+0xa0/0x190 [r8152 ...]
|
||||
r8152_poll+0x270/0x760 [r8152 ...]
|
||||
__napi_poll+0x44/0x1ec
|
||||
net_rx_action+0x100/0x300
|
||||
__do_softirq+0xec/0x38c
|
||||
run_ksoftirqd+0x38/0xec
|
||||
smpboot_thread_fn+0xb8/0x248
|
||||
kthread+0x134/0x154
|
||||
ret_from_fork+0x10/0x20
|
||||
|
||||
On a fragmented system it's normal that order 3 allocations will
|
||||
sometimes fail, especially atomic ones. The driver handles these
|
||||
failures fine and the WARN just creates spam in the logs for this
|
||||
case. The __GFP_NOWARN flag is exactly for this situation, so add it
|
||||
to the allocation.
|
||||
|
||||
NOTE: my testing is on a 5.15 system, but there should be no reason
|
||||
that this would be fundamentally different on a mainline kernel.
|
||||
|
||||
Signed-off-by: Douglas Anderson <dianders@chromium.org>
|
||||
Acked-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Link: https://lore.kernel.org/r/20230406171411.1.I84dbef45786af440fd269b71e9436a96a8e7a152@changeid
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -1947,7 +1947,7 @@ static struct rx_agg *alloc_rx_agg(struc
|
||||
if (!rx_agg)
|
||||
return NULL;
|
||||
|
||||
- rx_agg->page = alloc_pages(mflags | __GFP_COMP, order);
|
||||
+ rx_agg->page = alloc_pages(mflags | __GFP_COMP | __GFP_NOWARN, order);
|
||||
if (!rx_agg->page)
|
||||
goto free_rx;
|
||||
|
@ -0,0 +1,24 @@
|
||||
From 0fbd79c01a9a657348f7032df70c57a406468c86 Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Tue, 2 May 2023 11:36:27 +0800
|
||||
Subject: [PATCH] r8152: fix the autosuspend doesn't work
|
||||
|
||||
Set supports_autosuspend = 1 for the rtl8152_cfgselector_driver.
|
||||
|
||||
Fixes: ec51fbd1b8a2 ("r8152: add USB device driver for config selection")
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -9925,6 +9925,7 @@ static struct usb_device_driver rtl8152_
|
||||
.probe = rtl8152_cfgselector_probe,
|
||||
.id_table = rtl8152_table,
|
||||
.generic_subclass = 1,
|
||||
+ .supports_autosuspend = 1,
|
||||
};
|
||||
|
||||
static int __init rtl8152_driver_init(void)
|
@ -0,0 +1,70 @@
|
||||
From 57df0fb9d511f91202114813e90128d65c0589f0 Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Wed, 26 Jul 2023 11:08:07 +0800
|
||||
Subject: [PATCH] r8152: adjust generic_ocp_write function
|
||||
|
||||
Reduce the control transfer if all bytes of first or the last DWORD are
|
||||
written.
|
||||
|
||||
The original method is to split the control transfer into three parts
|
||||
(the first DWORD, middle continuous data, and the last DWORD). However,
|
||||
they could be combined if whole bytes of the first DWORD or last DWORD
|
||||
are written. That is, the first DWORD or the last DWORD could be combined
|
||||
with the middle continuous data, if the byte_en is 0xff.
|
||||
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Link: https://lore.kernel.org/r/20230726030808.9093-418-nic_swsd@realtek.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 29 ++++++++++++++++++-----------
|
||||
1 file changed, 18 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -1313,16 +1313,24 @@ static int generic_ocp_write(struct r815
|
||||
byteen_end = byteen & BYTE_EN_END_MASK;
|
||||
|
||||
byen = byteen_start | (byteen_start << 4);
|
||||
- ret = set_registers(tp, index, type | byen, 4, data);
|
||||
- if (ret < 0)
|
||||
- goto error1;
|
||||
-
|
||||
- index += 4;
|
||||
- data += 4;
|
||||
- size -= 4;
|
||||
|
||||
- if (size) {
|
||||
+ /* Split the first DWORD if the byte_en is not 0xff */
|
||||
+ if (byen != BYTE_EN_DWORD) {
|
||||
+ ret = set_registers(tp, index, type | byen, 4, data);
|
||||
+ if (ret < 0)
|
||||
+ goto error1;
|
||||
+
|
||||
+ index += 4;
|
||||
+ data += 4;
|
||||
size -= 4;
|
||||
+ }
|
||||
+
|
||||
+ if (size) {
|
||||
+ byen = byteen_end | (byteen_end >> 4);
|
||||
+
|
||||
+ /* Split the last DWORD if the byte_en is not 0xff */
|
||||
+ if (byen != BYTE_EN_DWORD)
|
||||
+ size -= 4;
|
||||
|
||||
while (size) {
|
||||
if (size > limit) {
|
||||
@@ -1349,10 +1357,9 @@ static int generic_ocp_write(struct r815
|
||||
}
|
||||
}
|
||||
|
||||
- byen = byteen_end | (byteen_end >> 4);
|
||||
- ret = set_registers(tp, index, type | byen, 4, data);
|
||||
- if (ret < 0)
|
||||
- goto error1;
|
||||
+ /* Set the last DWORD */
|
||||
+ if (byen != BYTE_EN_DWORD)
|
||||
+ ret = set_registers(tp, index, type | byen, 4, data);
|
||||
}
|
||||
|
||||
error1:
|
@ -0,0 +1,129 @@
|
||||
From e5c266a61186b462c388c53a3564c375e72f2244 Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Wed, 26 Jul 2023 11:08:08 +0800
|
||||
Subject: [PATCH] r8152: set bp in bulk
|
||||
|
||||
PLA_BP_0 ~ PLA_BP_15 (0xfc28 ~ 0xfc46) are continuous registers, so we
|
||||
could combine the control transfers into one control transfer.
|
||||
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Link: https://lore.kernel.org/r/20230726030808.9093-419-nic_swsd@realtek.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 75 ++++++++++++++---------------------------
|
||||
1 file changed, 25 insertions(+), 50 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -3984,29 +3984,10 @@ static void rtl_reset_bmu(struct r8152 *
|
||||
/* Clear the bp to stop the firmware before loading a new one */
|
||||
static void rtl_clear_bp(struct r8152 *tp, u16 type)
|
||||
{
|
||||
- switch (tp->version) {
|
||||
- case RTL_VER_01:
|
||||
- case RTL_VER_02:
|
||||
- case RTL_VER_07:
|
||||
- break;
|
||||
- case RTL_VER_03:
|
||||
- case RTL_VER_04:
|
||||
- case RTL_VER_05:
|
||||
- case RTL_VER_06:
|
||||
- ocp_write_byte(tp, type, PLA_BP_EN, 0);
|
||||
- break;
|
||||
- case RTL_VER_14:
|
||||
- ocp_write_word(tp, type, USB_BP2_EN, 0);
|
||||
+ u16 bp[16] = {0};
|
||||
+ u16 bp_num;
|
||||
|
||||
- ocp_write_word(tp, type, USB_BP_8, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_9, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_10, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_11, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_12, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_13, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_14, 0);
|
||||
- ocp_write_word(tp, type, USB_BP_15, 0);
|
||||
- break;
|
||||
+ switch (tp->version) {
|
||||
case RTL_VER_08:
|
||||
case RTL_VER_09:
|
||||
case RTL_VER_10:
|
||||
@@ -4014,32 +3995,31 @@ static void rtl_clear_bp(struct r8152 *t
|
||||
case RTL_VER_12:
|
||||
case RTL_VER_13:
|
||||
case RTL_VER_15:
|
||||
- default:
|
||||
if (type == MCU_TYPE_USB) {
|
||||
ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0);
|
||||
-
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_8, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_9, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_10, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_11, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_12, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_13, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_14, 0);
|
||||
- ocp_write_word(tp, MCU_TYPE_USB, USB_BP_15, 0);
|
||||
- } else {
|
||||
- ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0);
|
||||
+ bp_num = 16;
|
||||
+ break;
|
||||
}
|
||||
+ fallthrough;
|
||||
+ case RTL_VER_03:
|
||||
+ case RTL_VER_04:
|
||||
+ case RTL_VER_05:
|
||||
+ case RTL_VER_06:
|
||||
+ ocp_write_byte(tp, type, PLA_BP_EN, 0);
|
||||
+ fallthrough;
|
||||
+ case RTL_VER_01:
|
||||
+ case RTL_VER_02:
|
||||
+ case RTL_VER_07:
|
||||
+ bp_num = 8;
|
||||
+ break;
|
||||
+ case RTL_VER_14:
|
||||
+ default:
|
||||
+ ocp_write_word(tp, type, USB_BP2_EN, 0);
|
||||
+ bp_num = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
- ocp_write_word(tp, type, PLA_BP_0, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_1, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_2, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_3, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_4, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_5, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_6, 0);
|
||||
- ocp_write_word(tp, type, PLA_BP_7, 0);
|
||||
+ generic_ocp_write(tp, PLA_BP_0, BYTE_EN_DWORD, bp_num << 1, bp, type);
|
||||
|
||||
/* wait 3 ms to make sure the firmware is stopped */
|
||||
usleep_range(3000, 6000);
|
||||
@@ -5016,10 +4996,9 @@ static void rtl8152_fw_phy_nc_apply(stru
|
||||
|
||||
static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac)
|
||||
{
|
||||
- u16 bp_en_addr, bp_index, type, bp_num, fw_ver_reg;
|
||||
+ u16 bp_en_addr, type, fw_ver_reg;
|
||||
u32 length;
|
||||
u8 *data;
|
||||
- int i;
|
||||
|
||||
switch (__le32_to_cpu(mac->blk_hdr.type)) {
|
||||
case RTL_FW_PLA:
|
||||
@@ -5061,12 +5040,8 @@ static void rtl8152_fw_mac_apply(struct
|
||||
ocp_write_word(tp, type, __le16_to_cpu(mac->bp_ba_addr),
|
||||
__le16_to_cpu(mac->bp_ba_value));
|
||||
|
||||
- bp_index = __le16_to_cpu(mac->bp_start);
|
||||
- bp_num = __le16_to_cpu(mac->bp_num);
|
||||
- for (i = 0; i < bp_num; i++) {
|
||||
- ocp_write_word(tp, type, bp_index, __le16_to_cpu(mac->bp[i]));
|
||||
- bp_index += 2;
|
||||
- }
|
||||
+ generic_ocp_write(tp, __le16_to_cpu(mac->bp_start), BYTE_EN_DWORD,
|
||||
+ __le16_to_cpu(mac->bp_num) << 1, mac->bp, type);
|
||||
|
||||
bp_en_addr = __le16_to_cpu(mac->bp_en_addr);
|
||||
if (bp_en_addr)
|
@ -0,0 +1,39 @@
|
||||
From cf74eb5a5bc867258e7d0b0d1c3c4a60e1e3de2f Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Kicinski <kuba@kernel.org>
|
||||
Date: Mon, 14 Aug 2023 08:35:21 -0700
|
||||
Subject: [PATCH] eth: r8152: try to use a normal budget
|
||||
|
||||
Mario reports that loading r8152 on his system leads to a:
|
||||
|
||||
netif_napi_add_weight() called with weight 256
|
||||
|
||||
warning getting printed. We don't have any solid data
|
||||
on why such high budget was chosen, and it may cause
|
||||
stalls in processing other softirqs and rt threads.
|
||||
So try to switch back to the default (64) weight.
|
||||
|
||||
If this slows down someone's system we should investigate
|
||||
which part of stopping starting the NAPI poll in this
|
||||
driver are expensive.
|
||||
|
||||
Reported-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Link: https://lore.kernel.org/all/0bfd445a-81f7-f702-08b0-bd5a72095e49@amd.com/
|
||||
Acked-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Link: https://lore.kernel.org/r/20230814153521.2697982-1-kuba@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -9770,8 +9770,7 @@ static int rtl8152_probe(struct usb_inte
|
||||
|
||||
usb_set_intfdata(intf, tp);
|
||||
|
||||
- netif_napi_add_weight(netdev, &tp->napi, r8152_poll,
|
||||
- tp->support_2500full ? 256 : 64);
|
||||
+ netif_napi_add(netdev, &tp->napi, r8152_poll);
|
||||
|
||||
ret = register_netdev(netdev);
|
||||
if (ret != 0) {
|
@ -0,0 +1,39 @@
|
||||
From 72f93a3136ee18fd59fa6579f84c07e93424681e Mon Sep 17 00:00:00 2001
|
||||
From: Antonio Napolitano <anton@polit.no>
|
||||
Date: Sat, 26 Aug 2023 01:05:50 +0200
|
||||
Subject: [PATCH] r8152: add vendor/device ID pair for D-Link DUB-E250
|
||||
|
||||
The D-Link DUB-E250 is an RTL8156 based 2.5G Ethernet controller.
|
||||
|
||||
Add the vendor and product ID values to the driver. This makes Ethernet
|
||||
work with the adapter.
|
||||
|
||||
Signed-off-by: Antonio Napolitano <anton@polit.no>
|
||||
Link: https://lore.kernel.org/r/CV200KJEEUPC.WPKAHXCQJ05I@mercurius
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 1 +
|
||||
include/linux/usb/r8152.h | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
|
||||
--- a/include/linux/usb/r8152.h
|
||||
+++ b/include/linux/usb/r8152.h
|
||||
@@ -29,6 +29,7 @@
|
||||
#define VENDOR_ID_LINKSYS 0x13b1
|
||||
#define VENDOR_ID_NVIDIA 0x0955
|
||||
#define VENDOR_ID_TPLINK 0x2357
|
||||
+#define VENDOR_ID_DLINK 0x2001
|
||||
|
||||
#if IS_REACHABLE(CONFIG_USB_RTL8152)
|
||||
extern u8 rtl8152_get_version(struct usb_interface *intf);
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -9846,6 +9846,7 @@ static const struct usb_device_id rtl815
|
||||
{ USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041) },
|
||||
{ USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) },
|
||||
{ USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) },
|
||||
+ { USB_DEVICE(VENDOR_ID_DLINK, 0xb301) },
|
||||
{}
|
||||
};
|
||||
|
@ -0,0 +1,447 @@
|
||||
From 715f67f33af45ce2cc3a5b1ef133cc8c8e7787b0 Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Anderson <dianders@chromium.org>
|
||||
Date: Fri, 20 Oct 2023 14:06:58 -0700
|
||||
Subject: [PATCH] r8152: Rename RTL8152_UNPLUG to RTL8152_INACCESSIBLE
|
||||
|
||||
Whenever the RTL8152_UNPLUG is set that just tells the driver that all
|
||||
accesses will fail and we should just immediately bail. A future patch
|
||||
will use this same concept at a time when the driver hasn't actually
|
||||
been unplugged but is about to be reset. Rename the flag in
|
||||
preparation for the future patch.
|
||||
|
||||
This is a no-op change and just a search and replace.
|
||||
|
||||
Signed-off-by: Douglas Anderson <dianders@chromium.org>
|
||||
Reviewed-by: Grant Grundler <grundler@chromium.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 96 ++++++++++++++++++++---------------------
|
||||
1 file changed, 48 insertions(+), 48 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -763,7 +763,7 @@ enum rtl_register_content {
|
||||
|
||||
/* rtl8152 flags */
|
||||
enum rtl8152_flags {
|
||||
- RTL8152_UNPLUG = 0,
|
||||
+ RTL8152_INACCESSIBLE = 0,
|
||||
RTL8152_SET_RX_MODE,
|
||||
WORK_ENABLE,
|
||||
RTL8152_LINK_CHG,
|
||||
@@ -1244,7 +1244,7 @@ int set_registers(struct r8152 *tp, u16
|
||||
static void rtl_set_unplug(struct r8152 *tp)
|
||||
{
|
||||
if (tp->udev->state == USB_STATE_NOTATTACHED) {
|
||||
- set_bit(RTL8152_UNPLUG, &tp->flags);
|
||||
+ set_bit(RTL8152_INACCESSIBLE, &tp->flags);
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
}
|
||||
@@ -1255,7 +1255,7 @@ static int generic_ocp_read(struct r8152
|
||||
u16 limit = 64;
|
||||
int ret = 0;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
/* both size and indix must be 4 bytes align */
|
||||
@@ -1299,7 +1299,7 @@ static int generic_ocp_write(struct r815
|
||||
u16 byteen_start, byteen_end, byen;
|
||||
u16 limit = 512;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
/* both size and indix must be 4 bytes align */
|
||||
@@ -1536,7 +1536,7 @@ static int read_mii_word(struct net_devi
|
||||
struct r8152 *tp = netdev_priv(netdev);
|
||||
int ret;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
if (phy_id != R8152_PHY_ID)
|
||||
@@ -1552,7 +1552,7 @@ void write_mii_word(struct net_device *n
|
||||
{
|
||||
struct r8152 *tp = netdev_priv(netdev);
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
if (phy_id != R8152_PHY_ID)
|
||||
@@ -1757,7 +1757,7 @@ static void read_bulk_callback(struct ur
|
||||
if (!tp)
|
||||
return;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
if (!test_bit(WORK_ENABLE, &tp->flags))
|
||||
@@ -1849,7 +1849,7 @@ static void write_bulk_callback(struct u
|
||||
if (!test_bit(WORK_ENABLE, &tp->flags))
|
||||
return;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
if (!skb_queue_empty(&tp->tx_queue))
|
||||
@@ -1870,7 +1870,7 @@ static void intr_callback(struct urb *ur
|
||||
if (!test_bit(WORK_ENABLE, &tp->flags))
|
||||
return;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
switch (status) {
|
||||
@@ -2614,7 +2614,7 @@ static void bottom_half(struct tasklet_s
|
||||
{
|
||||
struct r8152 *tp = from_tasklet(tp, t, tx_tl);
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
if (!test_bit(WORK_ENABLE, &tp->flags))
|
||||
@@ -2657,7 +2657,7 @@ int r8152_submit_rx(struct r8152 *tp, st
|
||||
int ret;
|
||||
|
||||
/* The rx would be stopped, so skip submitting */
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags) ||
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags) ||
|
||||
!test_bit(WORK_ENABLE, &tp->flags) || !netif_carrier_ok(tp->netdev))
|
||||
return 0;
|
||||
|
||||
@@ -3057,7 +3057,7 @@ static int rtl_enable(struct r8152 *tp)
|
||||
|
||||
static int rtl8152_enable(struct r8152 *tp)
|
||||
{
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
set_tx_qlen(tp);
|
||||
@@ -3144,7 +3144,7 @@ static int rtl8153_enable(struct r8152 *
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
set_tx_qlen(tp);
|
||||
@@ -3176,7 +3176,7 @@ static void rtl_disable(struct r8152 *tp
|
||||
u32 ocp_data;
|
||||
int i;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
|
||||
rtl_drop_queued_tx(tp);
|
||||
return;
|
||||
}
|
||||
@@ -3630,7 +3630,7 @@ static u16 r8153_phy_status(struct r8152
|
||||
}
|
||||
|
||||
msleep(20);
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3662,7 +3662,7 @@ static void r8153b_ups_en(struct r8152 *
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 500; i++) {
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
|
||||
AUTOLOAD_DONE)
|
||||
@@ -3704,7 +3704,7 @@ static void r8153c_ups_en(struct r8152 *
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 500; i++) {
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
|
||||
AUTOLOAD_DONE)
|
||||
@@ -4049,8 +4049,8 @@ static int rtl_phy_patch_request(struct
|
||||
for (i = 0; wait && i < 5000; i++) {
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
- break;
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
+ return -ENODEV;
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
ocp_data = ocp_reg_read(tp, OCP_PHY_PATCH_STAT);
|
||||
@@ -6008,7 +6008,7 @@ static int rtl8156_enable(struct r8152 *
|
||||
u32 ocp_data;
|
||||
u16 speed;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
r8156_fc_parameter(tp);
|
||||
@@ -6066,7 +6066,7 @@ static int rtl8156b_enable(struct r8152
|
||||
u32 ocp_data;
|
||||
u16 speed;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
set_tx_qlen(tp);
|
||||
@@ -6252,7 +6252,7 @@ out:
|
||||
|
||||
static void rtl8152_up(struct r8152 *tp)
|
||||
{
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8152_aldps_en(tp, false);
|
||||
@@ -6262,7 +6262,7 @@ static void rtl8152_up(struct r8152 *tp)
|
||||
|
||||
static void rtl8152_down(struct r8152 *tp)
|
||||
{
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
|
||||
rtl_drop_queued_tx(tp);
|
||||
return;
|
||||
}
|
||||
@@ -6277,7 +6277,7 @@ static void rtl8153_up(struct r8152 *tp)
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153_u1u2en(tp, false);
|
||||
@@ -6317,7 +6317,7 @@ static void rtl8153_down(struct r8152 *t
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
|
||||
rtl_drop_queued_tx(tp);
|
||||
return;
|
||||
}
|
||||
@@ -6338,7 +6338,7 @@ static void rtl8153b_up(struct r8152 *tp
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153b_u1u2en(tp, false);
|
||||
@@ -6362,7 +6362,7 @@ static void rtl8153b_down(struct r8152 *
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
|
||||
rtl_drop_queued_tx(tp);
|
||||
return;
|
||||
}
|
||||
@@ -6399,7 +6399,7 @@ static void rtl8153c_up(struct r8152 *tp
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153b_u1u2en(tp, false);
|
||||
@@ -6480,7 +6480,7 @@ static void rtl8156_up(struct r8152 *tp)
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153b_u1u2en(tp, false);
|
||||
@@ -6553,7 +6553,7 @@ static void rtl8156_down(struct r8152 *t
|
||||
{
|
||||
u32 ocp_data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
|
||||
rtl_drop_queued_tx(tp);
|
||||
return;
|
||||
}
|
||||
@@ -6691,7 +6691,7 @@ static void rtl_work_func_t(struct work_
|
||||
/* If the device is unplugged or !netif_running(), the workqueue
|
||||
* doesn't need to wake the device, and could return directly.
|
||||
*/
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags) || !netif_running(tp->netdev))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags) || !netif_running(tp->netdev))
|
||||
return;
|
||||
|
||||
if (usb_autopm_get_interface(tp->intf) < 0)
|
||||
@@ -6730,7 +6730,7 @@ static void rtl_hw_phy_work_func_t(struc
|
||||
{
|
||||
struct r8152 *tp = container_of(work, struct r8152, hw_phy_work.work);
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
if (usb_autopm_get_interface(tp->intf) < 0)
|
||||
@@ -6857,7 +6857,7 @@ static int rtl8152_close(struct net_devi
|
||||
netif_stop_queue(netdev);
|
||||
|
||||
res = usb_autopm_get_interface(tp->intf);
|
||||
- if (res < 0 || test_bit(RTL8152_UNPLUG, &tp->flags)) {
|
||||
+ if (res < 0 || test_bit(RTL8152_INACCESSIBLE, &tp->flags)) {
|
||||
rtl_drop_queued_tx(tp);
|
||||
rtl_stop_rx(tp);
|
||||
} else {
|
||||
@@ -6890,7 +6890,7 @@ static void r8152b_init(struct r8152 *tp
|
||||
u32 ocp_data;
|
||||
u16 data;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
data = r8152_mdio_read(tp, MII_BMCR);
|
||||
@@ -6934,7 +6934,7 @@ static void r8153_init(struct r8152 *tp)
|
||||
u16 data;
|
||||
int i;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153_u1u2en(tp, false);
|
||||
@@ -6945,7 +6945,7 @@ static void r8153_init(struct r8152 *tp)
|
||||
break;
|
||||
|
||||
msleep(20);
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -7074,7 +7074,7 @@ static void r8153b_init(struct r8152 *tp
|
||||
u16 data;
|
||||
int i;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153b_u1u2en(tp, false);
|
||||
@@ -7085,7 +7085,7 @@ static void r8153b_init(struct r8152 *tp
|
||||
break;
|
||||
|
||||
msleep(20);
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -7156,7 +7156,7 @@ static void r8153c_init(struct r8152 *tp
|
||||
u16 data;
|
||||
int i;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153b_u1u2en(tp, false);
|
||||
@@ -7176,7 +7176,7 @@ static void r8153c_init(struct r8152 *tp
|
||||
break;
|
||||
|
||||
msleep(20);
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8005,7 +8005,7 @@ static void r8156_init(struct r8152 *tp)
|
||||
u16 data;
|
||||
int i;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_ECM_OP);
|
||||
@@ -8026,7 +8026,7 @@ static void r8156_init(struct r8152 *tp)
|
||||
break;
|
||||
|
||||
msleep(20);
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8101,7 +8101,7 @@ static void r8156b_init(struct r8152 *tp
|
||||
u16 data;
|
||||
int i;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_ECM_OP);
|
||||
@@ -8135,7 +8135,7 @@ static void r8156b_init(struct r8152 *tp
|
||||
break;
|
||||
|
||||
msleep(20);
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9164,7 +9164,7 @@ static int rtl8152_ioctl(struct net_devi
|
||||
struct mii_ioctl_data *data = if_mii(rq);
|
||||
int res;
|
||||
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return -ENODEV;
|
||||
|
||||
res = usb_autopm_get_interface(tp->intf);
|
||||
@@ -9266,7 +9266,7 @@ static const struct net_device_ops rtl81
|
||||
|
||||
static void rtl8152_unload(struct r8152 *tp)
|
||||
{
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
if (tp->version != RTL_VER_01)
|
||||
@@ -9275,7 +9275,7 @@ static void rtl8152_unload(struct r8152
|
||||
|
||||
static void rtl8153_unload(struct r8152 *tp)
|
||||
{
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153_power_cut_en(tp, false);
|
||||
@@ -9283,7 +9283,7 @@ static void rtl8153_unload(struct r8152
|
||||
|
||||
static void rtl8153b_unload(struct r8152 *tp)
|
||||
{
|
||||
- if (test_bit(RTL8152_UNPLUG, &tp->flags))
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
return;
|
||||
|
||||
r8153b_power_cut_en(tp, false);
|
@ -0,0 +1,398 @@
|
||||
From d9962b0d42029bcb40fe3c38bce06d1870fa4df4 Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Anderson <dianders@chromium.org>
|
||||
Date: Fri, 20 Oct 2023 14:06:59 -0700
|
||||
Subject: [PATCH] r8152: Block future register access if register access fails
|
||||
|
||||
Even though the functions to read/write registers can fail, most of
|
||||
the places in the r8152 driver that read/write register values don't
|
||||
check error codes. The lack of error code checking is problematic in
|
||||
at least two ways.
|
||||
|
||||
The first problem is that the r8152 driver often uses code patterns
|
||||
similar to this:
|
||||
x = read_register()
|
||||
x = x | SOME_BIT;
|
||||
write_register(x);
|
||||
|
||||
...with the above pattern, if the read_register() fails and returns
|
||||
garbage then we'll end up trying to write modified garbage back to the
|
||||
Realtek adapter. If the write_register() succeeds that's bad. Note
|
||||
that as of commit f53a7ad18959 ("r8152: Set memory to all 0xFFs on
|
||||
failed reg reads") the "garbage" returned by read_register() will at
|
||||
least be consistent garbage, but it is still garbage.
|
||||
|
||||
It turns out that this problem is very serious. Writing garbage to
|
||||
some of the hardware registers on the Ethernet adapter can put the
|
||||
adapter in such a bad state that it needs to be power cycled (fully
|
||||
unplugged and plugged in again) before it can enumerate again.
|
||||
|
||||
The second problem is that the r8152 driver generally has functions
|
||||
that are long sequences of register writes. Assuming everything will
|
||||
be OK if a random register write fails in the middle isn't a great
|
||||
assumption.
|
||||
|
||||
One might wonder if the above two problems are real. You could ask if
|
||||
we would really have a successful write after a failed read. It turns
|
||||
out that the answer appears to be "yes, this can happen". In fact,
|
||||
we've seen at least two distinct failure modes where this happens.
|
||||
|
||||
On a sc7180-trogdor Chromebook if you drop into kdb for a while and
|
||||
then resume, you can see:
|
||||
1. We get a "Tx timeout"
|
||||
2. The "Tx timeout" queues up a USB reset.
|
||||
3. In rtl8152_pre_reset() we try to reinit the hardware.
|
||||
4. The first several (2-9) register accesses fail with a timeout, then
|
||||
things recover.
|
||||
|
||||
The above test case was actually fixed by the patch ("r8152: Increase
|
||||
USB control msg timeout to 5000ms as per spec") but at least shows
|
||||
that we really can see successful calls after failed ones.
|
||||
|
||||
On a different (AMD) based Chromebook with a particular adapter, we
|
||||
found that during reboot tests we'd also sometimes get a transitory
|
||||
failure. In this case we saw -EPIPE being returned sometimes. Retrying
|
||||
worked, but retrying is not always safe for all register accesses
|
||||
since reading/writing some registers might have side effects (like
|
||||
registers that clear on read).
|
||||
|
||||
Let's fully lock out all register access if a register access fails.
|
||||
When we do this, we'll try to queue up a USB reset and try to unlock
|
||||
register access after the reset. This is slightly tricker than it
|
||||
sounds since the r8152 driver has an optimized reset sequence that
|
||||
only works reliably after probe happens. In order to handle this, we
|
||||
avoid the optimized reset if probe didn't finish. Instead, we simply
|
||||
retry the probe routine in this case.
|
||||
|
||||
When locking out access, we'll use the existing infrastructure that
|
||||
the driver was using when it detected we were unplugged. This keeps us
|
||||
from getting stuck in delay loops in some parts of the driver.
|
||||
|
||||
Signed-off-by: Douglas Anderson <dianders@chromium.org>
|
||||
Reviewed-by: Grant Grundler <grundler@chromium.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 207 ++++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 176 insertions(+), 31 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -772,6 +772,9 @@ enum rtl8152_flags {
|
||||
SCHEDULE_TASKLET,
|
||||
GREEN_ETHERNET,
|
||||
RX_EPROTO,
|
||||
+ IN_PRE_RESET,
|
||||
+ PROBED_WITH_NO_ERRORS,
|
||||
+ PROBE_SHOULD_RETRY,
|
||||
};
|
||||
|
||||
#define DEVICE_ID_LENOVO_USB_C_TRAVEL_HUB 0x721e
|
||||
@@ -952,6 +955,8 @@ struct r8152 {
|
||||
u8 version;
|
||||
u8 duplex;
|
||||
u8 autoneg;
|
||||
+
|
||||
+ unsigned int reg_access_reset_count;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1199,6 +1204,96 @@ static unsigned int agg_buf_sz = 16384;
|
||||
|
||||
#define RTL_LIMITED_TSO_SIZE (size_to_mtu(agg_buf_sz) - sizeof(struct tx_desc))
|
||||
|
||||
+/* If register access fails then we block access and issue a reset. If this
|
||||
+ * happens too many times in a row without a successful access then we stop
|
||||
+ * trying to reset and just leave access blocked.
|
||||
+ */
|
||||
+#define REGISTER_ACCESS_MAX_RESETS 3
|
||||
+
|
||||
+static void rtl_set_inaccessible(struct r8152 *tp)
|
||||
+{
|
||||
+ set_bit(RTL8152_INACCESSIBLE, &tp->flags);
|
||||
+ smp_mb__after_atomic();
|
||||
+}
|
||||
+
|
||||
+static void rtl_set_accessible(struct r8152 *tp)
|
||||
+{
|
||||
+ clear_bit(RTL8152_INACCESSIBLE, &tp->flags);
|
||||
+ smp_mb__after_atomic();
|
||||
+}
|
||||
+
|
||||
+static
|
||||
+int r8152_control_msg(struct r8152 *tp, unsigned int pipe, __u8 request,
|
||||
+ __u8 requesttype, __u16 value, __u16 index, void *data,
|
||||
+ __u16 size, const char *msg_tag)
|
||||
+{
|
||||
+ struct usb_device *udev = tp->udev;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (test_bit(RTL8152_INACCESSIBLE, &tp->flags))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ret = usb_control_msg(udev, pipe, request, requesttype,
|
||||
+ value, index, data, size,
|
||||
+ USB_CTRL_GET_TIMEOUT);
|
||||
+
|
||||
+ /* No need to issue a reset to report an error if the USB device got
|
||||
+ * unplugged; just return immediately.
|
||||
+ */
|
||||
+ if (ret == -ENODEV)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* If the write was successful then we're done */
|
||||
+ if (ret >= 0) {
|
||||
+ tp->reg_access_reset_count = 0;
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ dev_err(&udev->dev,
|
||||
+ "Failed to %s %d bytes at %#06x/%#06x (%d)\n",
|
||||
+ msg_tag, size, value, index, ret);
|
||||
+
|
||||
+ /* Block all future register access until we reset. Much of the code
|
||||
+ * in the driver doesn't check for errors. Notably, many parts of the
|
||||
+ * driver do a read/modify/write of a register value without
|
||||
+ * confirming that the read succeeded. Writing back modified garbage
|
||||
+ * like this can fully wedge the adapter, requiring a power cycle.
|
||||
+ */
|
||||
+ rtl_set_inaccessible(tp);
|
||||
+
|
||||
+ /* If probe hasn't yet finished, then we'll request a retry of the
|
||||
+ * whole probe routine if we get any control transfer errors. We
|
||||
+ * never have to clear this bit since we free/reallocate the whole "tp"
|
||||
+ * structure if we retry probe.
|
||||
+ */
|
||||
+ if (!test_bit(PROBED_WITH_NO_ERRORS, &tp->flags)) {
|
||||
+ set_bit(PROBE_SHOULD_RETRY, &tp->flags);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Failing to access registers in pre-reset is not surprising since we
|
||||
+ * wouldn't be resetting if things were behaving normally. The register
|
||||
+ * access we do in pre-reset isn't truly mandatory--we're just reusing
|
||||
+ * the disable() function and trying to be nice by powering the
|
||||
+ * adapter down before resetting it. Thus, if we're in pre-reset,
|
||||
+ * we'll return right away and not try to queue up yet another reset.
|
||||
+ * We know the post-reset is already coming.
|
||||
+ */
|
||||
+ if (test_bit(IN_PRE_RESET, &tp->flags))
|
||||
+ return ret;
|
||||
+
|
||||
+ if (tp->reg_access_reset_count < REGISTER_ACCESS_MAX_RESETS) {
|
||||
+ usb_queue_reset_device(tp->intf);
|
||||
+ tp->reg_access_reset_count++;
|
||||
+ } else if (tp->reg_access_reset_count == REGISTER_ACCESS_MAX_RESETS) {
|
||||
+ dev_err(&udev->dev,
|
||||
+ "Tried to reset %d times; giving up.\n",
|
||||
+ REGISTER_ACCESS_MAX_RESETS);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static
|
||||
int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
|
||||
{
|
||||
@@ -1209,9 +1304,10 @@ int get_registers(struct r8152 *tp, u16
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
- ret = usb_control_msg(tp->udev, tp->pipe_ctrl_in,
|
||||
- RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
|
||||
- value, index, tmp, size, USB_CTRL_GET_TIMEOUT);
|
||||
+ ret = r8152_control_msg(tp, tp->pipe_ctrl_in,
|
||||
+ RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
|
||||
+ value, index, tmp, size, "read");
|
||||
+
|
||||
if (ret < 0)
|
||||
memset(data, 0xff, size);
|
||||
else
|
||||
@@ -1232,9 +1328,9 @@ int set_registers(struct r8152 *tp, u16
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
- ret = usb_control_msg(tp->udev, tp->pipe_ctrl_out,
|
||||
- RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
|
||||
- value, index, tmp, size, USB_CTRL_SET_TIMEOUT);
|
||||
+ ret = r8152_control_msg(tp, tp->pipe_ctrl_out,
|
||||
+ RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
|
||||
+ value, index, tmp, size, "write");
|
||||
|
||||
kfree(tmp);
|
||||
|
||||
@@ -1243,10 +1339,8 @@ int set_registers(struct r8152 *tp, u16
|
||||
|
||||
static void rtl_set_unplug(struct r8152 *tp)
|
||||
{
|
||||
- if (tp->udev->state == USB_STATE_NOTATTACHED) {
|
||||
- set_bit(RTL8152_INACCESSIBLE, &tp->flags);
|
||||
- smp_mb__after_atomic();
|
||||
- }
|
||||
+ if (tp->udev->state == USB_STATE_NOTATTACHED)
|
||||
+ rtl_set_inaccessible(tp);
|
||||
}
|
||||
|
||||
static int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
|
||||
@@ -8261,7 +8355,7 @@ static int rtl8152_pre_reset(struct usb_
|
||||
struct r8152 *tp = usb_get_intfdata(intf);
|
||||
struct net_device *netdev;
|
||||
|
||||
- if (!tp)
|
||||
+ if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags))
|
||||
return 0;
|
||||
|
||||
netdev = tp->netdev;
|
||||
@@ -8276,7 +8370,9 @@ static int rtl8152_pre_reset(struct usb_
|
||||
napi_disable(&tp->napi);
|
||||
if (netif_carrier_ok(netdev)) {
|
||||
mutex_lock(&tp->control);
|
||||
+ set_bit(IN_PRE_RESET, &tp->flags);
|
||||
tp->rtl_ops.disable(tp);
|
||||
+ clear_bit(IN_PRE_RESET, &tp->flags);
|
||||
mutex_unlock(&tp->control);
|
||||
}
|
||||
|
||||
@@ -8289,9 +8385,11 @@ static int rtl8152_post_reset(struct usb
|
||||
struct net_device *netdev;
|
||||
struct sockaddr sa;
|
||||
|
||||
- if (!tp)
|
||||
+ if (!tp || !test_bit(PROBED_WITH_NO_ERRORS, &tp->flags))
|
||||
return 0;
|
||||
|
||||
+ rtl_set_accessible(tp);
|
||||
+
|
||||
/* reset the MAC address in case of policy change */
|
||||
if (determine_ethernet_addr(tp, &sa) >= 0) {
|
||||
rtnl_lock();
|
||||
@@ -9493,17 +9591,29 @@ static u8 __rtl_get_hw_ver(struct usb_de
|
||||
__le32 *tmp;
|
||||
u8 version;
|
||||
int ret;
|
||||
+ int i;
|
||||
|
||||
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||||
if (!tmp)
|
||||
return 0;
|
||||
|
||||
- ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
- RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
|
||||
- PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp),
|
||||
- USB_CTRL_GET_TIMEOUT);
|
||||
- if (ret > 0)
|
||||
- ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK;
|
||||
+ /* Retry up to 3 times in case there is a transitory error. We do this
|
||||
+ * since retrying a read of the version is always safe and this
|
||||
+ * function doesn't take advantage of r8152_control_msg().
|
||||
+ */
|
||||
+ for (i = 0; i < 3; i++) {
|
||||
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
+ RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
|
||||
+ PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp),
|
||||
+ USB_CTRL_GET_TIMEOUT);
|
||||
+ if (ret > 0) {
|
||||
+ ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (i != 0 && ret > 0)
|
||||
+ dev_warn(&udev->dev, "Needed %d retries to read version\n", i);
|
||||
|
||||
kfree(tmp);
|
||||
|
||||
@@ -9602,25 +9712,14 @@ static bool rtl8152_supports_lenovo_macp
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int rtl8152_probe(struct usb_interface *intf,
|
||||
- const struct usb_device_id *id)
|
||||
+static int rtl8152_probe_once(struct usb_interface *intf,
|
||||
+ const struct usb_device_id *id, u8 version)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct r8152 *tp;
|
||||
struct net_device *netdev;
|
||||
- u8 version;
|
||||
int ret;
|
||||
|
||||
- if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
|
||||
- return -ENODEV;
|
||||
-
|
||||
- if (!rtl_check_vendor_ok(intf))
|
||||
- return -ENODEV;
|
||||
-
|
||||
- version = rtl8152_get_version(intf);
|
||||
- if (version == RTL_VER_UNKNOWN)
|
||||
- return -ENODEV;
|
||||
-
|
||||
usb_reset_device(udev);
|
||||
netdev = alloc_etherdev(sizeof(struct r8152));
|
||||
if (!netdev) {
|
||||
@@ -9783,10 +9882,20 @@ static int rtl8152_probe(struct usb_inte
|
||||
else
|
||||
device_set_wakeup_enable(&udev->dev, false);
|
||||
|
||||
+ /* If we saw a control transfer error while probing then we may
|
||||
+ * want to try probe() again. Consider this an error.
|
||||
+ */
|
||||
+ if (test_bit(PROBE_SHOULD_RETRY, &tp->flags))
|
||||
+ goto out2;
|
||||
+
|
||||
+ set_bit(PROBED_WITH_NO_ERRORS, &tp->flags);
|
||||
netif_info(tp, probe, netdev, "%s\n", DRIVER_VERSION);
|
||||
|
||||
return 0;
|
||||
|
||||
+out2:
|
||||
+ unregister_netdev(netdev);
|
||||
+
|
||||
out1:
|
||||
tasklet_kill(&tp->tx_tl);
|
||||
cancel_delayed_work_sync(&tp->hw_phy_work);
|
||||
@@ -9795,10 +9904,46 @@ out1:
|
||||
rtl8152_release_firmware(tp);
|
||||
usb_set_intfdata(intf, NULL);
|
||||
out:
|
||||
+ if (test_bit(PROBE_SHOULD_RETRY, &tp->flags))
|
||||
+ ret = -EAGAIN;
|
||||
+
|
||||
free_netdev(netdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+#define RTL8152_PROBE_TRIES 3
|
||||
+
|
||||
+static int rtl8152_probe(struct usb_interface *intf,
|
||||
+ const struct usb_device_id *id)
|
||||
+{
|
||||
+ u8 version;
|
||||
+ int ret;
|
||||
+ int i;
|
||||
+
|
||||
+ if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ if (!rtl_check_vendor_ok(intf))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ version = rtl8152_get_version(intf);
|
||||
+ if (version == RTL_VER_UNKNOWN)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ for (i = 0; i < RTL8152_PROBE_TRIES; i++) {
|
||||
+ ret = rtl8152_probe_once(intf, id, version);
|
||||
+ if (ret != -EAGAIN)
|
||||
+ break;
|
||||
+ }
|
||||
+ if (ret == -EAGAIN) {
|
||||
+ dev_err(&intf->dev,
|
||||
+ "r8152 failed probe after %d tries; giving up\n", i);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static void rtl8152_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct r8152 *tp = usb_get_intfdata(intf);
|
@ -0,0 +1,83 @@
|
||||
From 66eee612a1ba39f9a76a9ace4a34d012044767fb Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Tue, 26 Sep 2023 19:17:13 +0800
|
||||
Subject: [PATCH] r8152: break the loop when the budget is exhausted
|
||||
|
||||
[ Upstream commit 2cf51f931797d9a47e75d999d0993a68cbd2a560 ]
|
||||
|
||||
A bulk transfer of the USB may contain many packets. And, the total
|
||||
number of the packets in the bulk transfer may be more than budget.
|
||||
|
||||
Originally, only budget packets would be handled by napi_gro_receive(),
|
||||
and the other packets would be queued in the driver for next schedule.
|
||||
|
||||
This patch would break the loop about getting next bulk transfer, when
|
||||
the budget is exhausted. That is, only the current bulk transfer would
|
||||
be handled, and the other bulk transfers would be queued for next
|
||||
schedule. Besides, the packets which are more than the budget in the
|
||||
current bulk trasnfer would be still queued in the driver, as the
|
||||
original method.
|
||||
|
||||
In addition, a bulk transfer wouldn't contain more than 400 packets, so
|
||||
the check of queue length is unnecessary. Therefore, I replace it with
|
||||
WARN_ON_ONCE().
|
||||
|
||||
Fixes: cf74eb5a5bc8 ("eth: r8152: try to use a normal budget")
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Link: https://lore.kernel.org/r/20230926111714.9448-433-nic_swsd@realtek.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
Signed-off-by: Sasha Levin <sashal@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 18 +++++++++++++-----
|
||||
1 file changed, 13 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -2542,7 +2542,7 @@ static int rx_bottom(struct r8152 *tp, i
|
||||
}
|
||||
}
|
||||
|
||||
- if (list_empty(&tp->rx_done))
|
||||
+ if (list_empty(&tp->rx_done) || work_done >= budget)
|
||||
goto out1;
|
||||
|
||||
clear_bit(RX_EPROTO, &tp->flags);
|
||||
@@ -2558,6 +2558,15 @@ static int rx_bottom(struct r8152 *tp, i
|
||||
struct urb *urb;
|
||||
u8 *rx_data;
|
||||
|
||||
+ /* A bulk transfer of USB may contain may packets, so the
|
||||
+ * total packets may more than the budget. Deal with all
|
||||
+ * packets in current bulk transfer, and stop to handle the
|
||||
+ * next bulk transfer until next schedule, if budget is
|
||||
+ * exhausted.
|
||||
+ */
|
||||
+ if (work_done >= budget)
|
||||
+ break;
|
||||
+
|
||||
list_del_init(cursor);
|
||||
|
||||
agg = list_entry(cursor, struct rx_agg, list);
|
||||
@@ -2577,9 +2586,7 @@ static int rx_bottom(struct r8152 *tp, i
|
||||
unsigned int pkt_len, rx_frag_head_sz;
|
||||
struct sk_buff *skb;
|
||||
|
||||
- /* limit the skb numbers for rx_queue */
|
||||
- if (unlikely(skb_queue_len(&tp->rx_queue) >= 1000))
|
||||
- break;
|
||||
+ WARN_ON_ONCE(skb_queue_len(&tp->rx_queue) >= 1000);
|
||||
|
||||
pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
|
||||
if (pkt_len < ETH_ZLEN)
|
||||
@@ -2657,9 +2664,10 @@ submit:
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Splice the remained list back to rx_done for next schedule */
|
||||
if (!list_empty(&rx_queue)) {
|
||||
spin_lock_irqsave(&tp->rx_lock, flags);
|
||||
- list_splice_tail(&rx_queue, &tp->rx_done);
|
||||
+ list_splice(&rx_queue, &tp->rx_done);
|
||||
spin_unlock_irqrestore(&tp->rx_lock, flags);
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
From 1b0fce8c8e69485e49a7d34aac3d4c2a2aa15d62 Mon Sep 17 00:00:00 2001
|
||||
From: Davide Tronchin <davide.tronchin.94@gmail.com>
|
||||
Date: Thu, 29 Jun 2023 12:37:36 +0200
|
||||
Subject: [PATCH] net: usb: cdc_ether: add u-blox 0x1313 composition.
|
||||
|
||||
Add CDC-ECM support for LARA-R6 01B.
|
||||
|
||||
The new LARA-R6 product variant identified by the "01B" string can be
|
||||
configured (by AT interface) in three different USB modes:
|
||||
* Default mode (Vendor ID: 0x1546 Product ID: 0x1311) with 4 serial
|
||||
interfaces
|
||||
* RmNet mode (Vendor ID: 0x1546 Product ID: 0x1312) with 4 serial
|
||||
interfaces and 1 RmNet virtual network interface
|
||||
* CDC-ECM mode (Vendor ID: 0x1546 Product ID: 0x1313) with 4 serial
|
||||
interface and 1 CDC-ECM virtual network interface
|
||||
The first 4 interfaces of all the 3 configurations (default, RmNet, ECM)
|
||||
are the same.
|
||||
|
||||
In CDC-ECM mode LARA-R6 01B exposes the following interfaces:
|
||||
If 0: Diagnostic
|
||||
If 1: AT parser
|
||||
If 2: AT parser
|
||||
If 3: AT parset/alternative functions
|
||||
If 4: CDC-ECM interface
|
||||
|
||||
Signed-off-by: Davide Tronchin <davide.tronchin.94@gmail.com>
|
||||
Reviewed-by: Simon Horman <simon.horman@corigine.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/cdc_ether.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
--- a/drivers/net/usb/cdc_ether.c
|
||||
+++ b/drivers/net/usb/cdc_ether.c
|
||||
@@ -879,6 +879,12 @@ static const struct usb_device_id produc
|
||||
USB_CDC_PROTO_NONE),
|
||||
.driver_info = (unsigned long)&wwan_info,
|
||||
}, {
|
||||
+ /* U-blox LARA-R6 01B */
|
||||
+ USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1313, USB_CLASS_COMM,
|
||||
+ USB_CDC_SUBCLASS_ETHERNET,
|
||||
+ USB_CDC_PROTO_NONE),
|
||||
+ .driver_info = (unsigned long)&wwan_info,
|
||||
+}, {
|
||||
/* ZTE modules */
|
||||
USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET,
|
@ -0,0 +1,122 @@
|
||||
From 788d30daa8f97f06166b6a63f0e51f2a4c2f036a Mon Sep 17 00:00:00 2001
|
||||
From: Hayes Wang <hayeswang@realtek.com>
|
||||
Date: Tue, 26 Sep 2023 19:17:14 +0800
|
||||
Subject: [PATCH] r8152: use napi_gro_frags
|
||||
|
||||
Use napi_gro_frags() for the skb of fragments when the work_done is less
|
||||
than budget.
|
||||
|
||||
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
|
||||
Link: https://lore.kernel.org/r/20230926111714.9448-434-nic_swsd@realtek.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/usb/r8152.c | 67 ++++++++++++++++++++++++++++++-----------
|
||||
1 file changed, 50 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/r8152.c
|
||||
+++ b/drivers/net/usb/r8152.c
|
||||
@@ -2583,8 +2583,9 @@ static int rx_bottom(struct r8152 *tp, i
|
||||
while (urb->actual_length > len_used) {
|
||||
struct net_device *netdev = tp->netdev;
|
||||
struct net_device_stats *stats = &netdev->stats;
|
||||
- unsigned int pkt_len, rx_frag_head_sz;
|
||||
+ unsigned int pkt_len, rx_frag_head_sz, len;
|
||||
struct sk_buff *skb;
|
||||
+ bool use_frags;
|
||||
|
||||
WARN_ON_ONCE(skb_queue_len(&tp->rx_queue) >= 1000);
|
||||
|
||||
@@ -2597,45 +2598,77 @@ static int rx_bottom(struct r8152 *tp, i
|
||||
break;
|
||||
|
||||
pkt_len -= ETH_FCS_LEN;
|
||||
+ len = pkt_len;
|
||||
rx_data += sizeof(struct rx_desc);
|
||||
|
||||
- if (!agg_free || tp->rx_copybreak > pkt_len)
|
||||
- rx_frag_head_sz = pkt_len;
|
||||
+ if (!agg_free || tp->rx_copybreak > len)
|
||||
+ use_frags = false;
|
||||
else
|
||||
- rx_frag_head_sz = tp->rx_copybreak;
|
||||
+ use_frags = true;
|
||||
+
|
||||
+ if (use_frags) {
|
||||
+ /* If the budget is exhausted, the packet
|
||||
+ * would be queued in the driver. That is,
|
||||
+ * napi_gro_frags() wouldn't be called, so
|
||||
+ * we couldn't use napi_get_frags().
|
||||
+ */
|
||||
+ if (work_done >= budget) {
|
||||
+ rx_frag_head_sz = tp->rx_copybreak;
|
||||
+ skb = napi_alloc_skb(napi,
|
||||
+ rx_frag_head_sz);
|
||||
+ } else {
|
||||
+ rx_frag_head_sz = 0;
|
||||
+ skb = napi_get_frags(napi);
|
||||
+ }
|
||||
+ } else {
|
||||
+ rx_frag_head_sz = 0;
|
||||
+ skb = napi_alloc_skb(napi, len);
|
||||
+ }
|
||||
|
||||
- skb = napi_alloc_skb(napi, rx_frag_head_sz);
|
||||
if (!skb) {
|
||||
stats->rx_dropped++;
|
||||
goto find_next_rx;
|
||||
}
|
||||
|
||||
skb->ip_summed = r8152_rx_csum(tp, rx_desc);
|
||||
- memcpy(skb->data, rx_data, rx_frag_head_sz);
|
||||
- skb_put(skb, rx_frag_head_sz);
|
||||
- pkt_len -= rx_frag_head_sz;
|
||||
- rx_data += rx_frag_head_sz;
|
||||
- if (pkt_len) {
|
||||
+ rtl_rx_vlan_tag(rx_desc, skb);
|
||||
+
|
||||
+ if (use_frags) {
|
||||
+ if (rx_frag_head_sz) {
|
||||
+ memcpy(skb->data, rx_data,
|
||||
+ rx_frag_head_sz);
|
||||
+ skb_put(skb, rx_frag_head_sz);
|
||||
+ len -= rx_frag_head_sz;
|
||||
+ rx_data += rx_frag_head_sz;
|
||||
+ skb->protocol = eth_type_trans(skb,
|
||||
+ netdev);
|
||||
+ }
|
||||
+
|
||||
skb_add_rx_frag(skb, 0, agg->page,
|
||||
agg_offset(agg, rx_data),
|
||||
- pkt_len,
|
||||
- SKB_DATA_ALIGN(pkt_len));
|
||||
+ len, SKB_DATA_ALIGN(len));
|
||||
get_page(agg->page);
|
||||
+ } else {
|
||||
+ memcpy(skb->data, rx_data, len);
|
||||
+ skb_put(skb, len);
|
||||
+ skb->protocol = eth_type_trans(skb, netdev);
|
||||
}
|
||||
|
||||
- skb->protocol = eth_type_trans(skb, netdev);
|
||||
- rtl_rx_vlan_tag(rx_desc, skb);
|
||||
if (work_done < budget) {
|
||||
+ if (use_frags)
|
||||
+ napi_gro_frags(napi);
|
||||
+ else
|
||||
+ napi_gro_receive(napi, skb);
|
||||
+
|
||||
work_done++;
|
||||
stats->rx_packets++;
|
||||
- stats->rx_bytes += skb->len;
|
||||
- napi_gro_receive(napi, skb);
|
||||
+ stats->rx_bytes += pkt_len;
|
||||
} else {
|
||||
__skb_queue_tail(&tp->rx_queue, skb);
|
||||
}
|
||||
|
||||
find_next_rx:
|
||||
- rx_data = rx_agg_align(rx_data + pkt_len + ETH_FCS_LEN);
|
||||
+ rx_data = rx_agg_align(rx_data + len + ETH_FCS_LEN);
|
||||
rx_desc = (struct rx_desc *)rx_data;
|
||||
len_used = agg_offset(agg, rx_data);
|
||||
len_used += sizeof(struct rx_desc);
|
@ -22,7 +22,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/uaccess.h>
|
||||
@@ -6896,6 +6897,22 @@ static void rtl_tally_reset(struct r8152
|
||||
@@ -6980,6 +6981,22 @@ static void rtl_tally_reset(struct r8152
|
||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data);
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
static void r8152b_init(struct r8152 *tp)
|
||||
{
|
||||
u32 ocp_data;
|
||||
@@ -6937,6 +6954,8 @@ static void r8152b_init(struct r8152 *tp
|
||||
@@ -7021,6 +7038,8 @@ static void r8152b_init(struct r8152 *tp
|
||||
ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
|
||||
ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
|
||||
ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
|
||||
@ -54,7 +54,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
}
|
||||
|
||||
static void r8153_init(struct r8152 *tp)
|
||||
@@ -7077,6 +7096,8 @@ static void r8153_init(struct r8152 *tp)
|
||||
@@ -7161,6 +7180,8 @@ static void r8153_init(struct r8152 *tp)
|
||||
tp->coalesce = COALESCE_SLOW;
|
||||
break;
|
||||
}
|
||||
@ -63,7 +63,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
}
|
||||
|
||||
static void r8153b_init(struct r8152 *tp)
|
||||
@@ -7159,6 +7180,8 @@ static void r8153b_init(struct r8152 *tp
|
||||
@@ -7243,6 +7264,8 @@ static void r8153b_init(struct r8152 *tp
|
||||
rtl_tally_reset(tp);
|
||||
|
||||
tp->coalesce = 15000; /* 15 us */
|
||||
|
@ -22,7 +22,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/uaccess.h>
|
||||
@@ -6903,6 +6904,22 @@ static void rtl_tally_reset(struct r8152
|
||||
@@ -7020,6 +7021,22 @@ static void rtl_tally_reset(struct r8152
|
||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data);
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
static void r8152b_init(struct r8152 *tp)
|
||||
{
|
||||
u32 ocp_data;
|
||||
@@ -6944,6 +6961,8 @@ static void r8152b_init(struct r8152 *tp
|
||||
@@ -7061,6 +7078,8 @@ static void r8152b_init(struct r8152 *tp
|
||||
ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
|
||||
ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
|
||||
ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
|
||||
@ -54,7 +54,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
}
|
||||
|
||||
static void r8153_init(struct r8152 *tp)
|
||||
@@ -7084,6 +7103,8 @@ static void r8153_init(struct r8152 *tp)
|
||||
@@ -7201,6 +7220,8 @@ static void r8153_init(struct r8152 *tp)
|
||||
tp->coalesce = COALESCE_SLOW;
|
||||
break;
|
||||
}
|
||||
@ -63,7 +63,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
}
|
||||
|
||||
static void r8153b_init(struct r8152 *tp)
|
||||
@@ -7166,6 +7187,8 @@ static void r8153b_init(struct r8152 *tp
|
||||
@@ -7283,6 +7304,8 @@ static void r8153b_init(struct r8152 *tp
|
||||
rtl_tally_reset(tp);
|
||||
|
||||
tp->coalesce = 15000; /* 15 us */
|
||||
|
Loading…
x
Reference in New Issue
Block a user