From: Michal Pecio <michal.pecio@gmail.com>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: yicongsrfy@163.com, andrew+netdev@lunn.ch, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, linux-usb@vger.kernel.org,
netdev@vger.kernel.org, oliver@neukum.org, pabeni@redhat.com
Subject: Re: [PATCH net v5 2/3] net: usb: ax88179_178a: add USB device driver for config selection
Date: Sat, 18 Oct 2025 17:21:56 +0200 [thread overview]
Message-ID: <20251018172156.69e93897.michal.pecio@gmail.com> (raw)
In-Reply-To: <bda50568-a05d-4241-adbe-18efb2251d6e@rowland.harvard.edu>
On Fri, 17 Oct 2025 22:27:35 -0400, Alan Stern wrote:
> Without a reasonable clear and quick criterion for deciding when to
> favor vendor-specific configs in the USB core, there's little I can do.
> Having a quirks flag should help remove some of the indecision, since
> such flags are set by hand rather than by an automated procedure. But
> I'd still want to have a better idea of exactly what to do when the
> quirk flag is set.
Existing r8152-cfgselector and the planned ax88179-cfgselector
implement the following logic:
IF a device has particular IDs
(same id_table as in the vendor interface driver)
IF the vendor interface driver is loaded
(ensured by loading it together with cfgselector)
IF the vendor driver supports this device
(calls internal vendor driver code)
THEN select the vendor configuration
It was a PITA, but I have a working proof of concept for r8152.
Still missing is automatic reevaluation of configuration choice when
the vendor driver is loaded after device connection (e.g. by udev).
Those cfgselectors can do it because it seems that registering a new
device (but not interface) driver forces reevaluation.
---
drivers/net/usb/r8152.c | 13 ++++++-------
drivers/usb/core/driver.c | 23 +++++++++++++++++++++++
drivers/usb/core/generic.c | 17 +++++++++++++++--
include/linux/usb.h | 6 ++++++
4 files changed, 50 insertions(+), 9 deletions(-)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index a22d4bb2cf3b..1b016dd81949 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -10020,6 +10020,11 @@ static void rtl8152_disconnect(struct usb_interface *intf)
}
}
+static bool rtl8152_preferred(struct usb_device *udev)
+{
+ return __rtl_get_hw_ver(udev) != RTL_VER_UNKNOWN;
+}
+
/* table of devices that work with this driver */
static const struct usb_device_id rtl8152_table[] = {
/* Realtek */
@@ -10067,6 +10072,7 @@ static struct usb_driver rtl8152_driver = {
.name = MODULENAME,
.id_table = rtl8152_table,
.probe = rtl8152_probe,
+ .preferred = rtl8152_preferred,
.disconnect = rtl8152_disconnect,
.suspend = rtl8152_suspend,
.resume = rtl8152_resume,
@@ -10119,13 +10125,7 @@ static int __init rtl8152_driver_init(void)
{
int ret;
- ret = usb_register_device_driver(&rtl8152_cfgselector_driver, THIS_MODULE);
- if (ret)
- return ret;
-
ret = usb_register(&rtl8152_driver);
- if (ret)
- usb_deregister_device_driver(&rtl8152_cfgselector_driver);
return ret;
}
@@ -10133,7 +10133,6 @@ static int __init rtl8152_driver_init(void)
static void __exit rtl8152_driver_exit(void)
{
usb_deregister(&rtl8152_driver);
- usb_deregister_device_driver(&rtl8152_cfgselector_driver);
}
module_init(rtl8152_driver_init);
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index d29edc7c616a..eaf21c30eac1 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1119,6 +1119,29 @@ void usb_deregister(struct usb_driver *driver)
}
EXPORT_SYMBOL_GPL(usb_deregister);
+/**
+ * usb_driver_preferred - check if this is a preferred interface driver
+ * @drv: interface driver to check (device drivers are ignored)
+ * @udev: the device we are looking up a driver for
+ * Context: must be able to sleep
+ *
+ * TODO locking?
+ */
+bool usb_driver_preferred(struct device_driver *drv, struct usb_device *udev)
+{
+ struct usb_driver *usb_drv;
+
+ if (is_usb_device_driver(drv))
+ return false;
+
+ usb_drv = to_usb_driver(drv);
+
+ return usb_drv->preferred &&
+ usb_device_match_id(udev, usb_drv->id_table) &&
+ usb_drv->preferred(udev);
+}
+EXPORT_SYMBOL_GPL(usb_driver_preferred);
+
/* Forced unbinding of a USB interface driver, either because
* it doesn't support pre_reset/post_reset/reset_resume or
* because it doesn't support suspend/resume.
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index a48994e11ef3..1923e6f4923b 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -49,11 +49,17 @@ static bool is_uac3_config(struct usb_interface_descriptor *desc)
return desc->bInterfaceProtocol == UAC_VERSION_3;
}
+static int prefer_vendor(struct device_driver *drv, void *data)
+{
+ return usb_driver_preferred(drv, data);
+}
+
int usb_choose_configuration(struct usb_device *udev)
{
int i;
int num_configs;
int insufficient_power = 0;
+ bool class_found = false;
struct usb_host_config *c, *best;
struct usb_device_driver *udriver;
@@ -169,6 +175,12 @@ int usb_choose_configuration(struct usb_device *udev)
#endif
}
+ /* Check if we have a preferred vendor driver for this config */
+ else if (bus_for_each_drv(&usb_bus_type, NULL, (void *) udev, prefer_vendor)) {
+ best = c;
+ break;
+ }
+
/* From the remaining configs, choose the first one whose
* first interface is for a non-vendor-specific class.
* Reason: Linux is more likely to have a class driver
@@ -177,8 +189,9 @@ int usb_choose_configuration(struct usb_device *udev)
USB_CLASS_VENDOR_SPEC &&
(desc && desc->bInterfaceClass !=
USB_CLASS_VENDOR_SPEC)) {
- best = c;
- break;
+ if (!class_found)
+ best = c;
+ class_found = true;
}
/* If all the remaining configs are vendor-specific,
diff --git a/include/linux/usb.h b/include/linux/usb.h
index e85105939af8..1d2c5ebc81ab 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1202,6 +1202,8 @@ extern ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf);
* @post_reset: Called by usb_reset_device() after the device
* has been reset
* @shutdown: Called at shut-down time to quiesce the device.
+ * @preferred: Check if this driver is preferred over generic class drivers
+ * applicable to the device. May probe device with control transfers.
* @id_table: USB drivers use ID table to support hotplugging.
* Export this with MODULE_DEVICE_TABLE(usb,...). This must be set
* or your driver's probe function will never get called.
@@ -1255,6 +1257,8 @@ struct usb_driver {
void (*shutdown)(struct usb_interface *intf);
+ bool (*preferred)(struct usb_device *udev);
+
const struct usb_device_id *id_table;
const struct attribute_group **dev_groups;
@@ -1267,6 +1271,8 @@ struct usb_driver {
};
#define to_usb_driver(d) container_of_const(d, struct usb_driver, driver)
+extern bool usb_driver_preferred(struct device_driver *drv, struct usb_device *udev);
+
/**
* struct usb_device_driver - identifies USB device driver to usbcore
* @name: The driver name should be unique among USB drivers,
--
2.48.1
next prev parent reply other threads:[~2025-10-18 15:22 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-11 7:53 [PATCH net v5 0/3] ax88179 driver optimization yicongsrfy
2025-10-11 7:53 ` [PATCH net v5 1/3] net: usb: support quirks in cdc_ncm yicongsrfy
2025-10-11 7:53 ` [PATCH net v5 2/3] net: usb: ax88179_178a: add USB device driver for config selection yicongsrfy
2025-10-13 9:07 ` Michal Pecio
2025-10-17 2:42 ` yicongsrfy
2025-10-17 13:10 ` Alan Stern
2025-10-17 17:15 ` Michal Pecio
2025-10-18 2:27 ` Alan Stern
2025-10-18 15:21 ` Michal Pecio [this message]
2025-10-18 15:36 ` Alan Stern
2025-10-18 15:56 ` Michal Pecio
2025-10-20 15:56 ` Alan Stern
2025-10-20 16:23 ` Michal Pecio
2025-10-20 16:59 ` Alan Stern
2025-10-21 9:13 ` Oliver Neukum
2025-10-21 16:33 ` Alan Stern
2025-10-22 7:58 ` Oliver Neukum
2025-10-22 14:28 ` Alan Stern
2025-10-21 2:29 ` Yi Cong
2025-10-21 2:59 ` Alan Stern
2025-10-21 6:26 ` Yi Cong
2025-10-21 16:26 ` Alan Stern
2025-10-20 9:59 ` Oliver Neukum
2025-10-20 10:48 ` Greg KH
2025-10-20 15:59 ` Michal Pecio
2025-10-21 9:02 ` Oliver Neukum
2025-10-20 10:27 ` Oliver Neukum
2025-10-11 7:53 ` [PATCH net v5 3/3] Revert "net: usb: ax88179_178a: Bind only to vendor-specific interface" yicongsrfy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251018172156.69e93897.michal.pecio@gmail.com \
--to=michal.pecio@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=oliver@neukum.org \
--cc=pabeni@redhat.com \
--cc=stern@rowland.harvard.edu \
--cc=yicongsrfy@163.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).