core: stop monitoring the 'usb' subsystem

Back in Linux < 3.6 days, the cdc-wdm ports exposed by the QMI driver
were flagged as owned by the 'usb' subsystem. That changed in 3.6 when
the subsystem was renamed to 'usbmisc':

  https://mail.gnome.org/archives/networkmanager-list/2012-June/msg00125.html

This patch removes all monitoring of the 'usb' subsystem completely,
which is anyway a valid subsystem but for which we shouldn't need any
special handling. Right now, with newer kernels, we were using that
monitoring exclusively to get notified of full USB device remove
events, which is really not required as we already process the port
removals one by one.

We simplify the logic everywhere that attempted to match either the
'usb' or 'usbmisc' subsystems, and we no longer require the explicit
checks for the port name being named 'cdc-wdm[0-9]*' in the code, as
that is already taken care of by the ID_MM_CANDIDATE udev tag rule.
This commit is contained in:
Aleksander Morgado
2020-11-06 12:27:40 +01:00
parent 519df2544b
commit 950abbf8ee
26 changed files with 55 additions and 143 deletions

View File

@@ -68,7 +68,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendor_ids[] = { 0x16d5, 0 };
return MM_PLUGIN (

View File

@@ -67,7 +67,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendor_ids[] = { 0x2020, 0 };
return MM_PLUGIN (

View File

@@ -181,7 +181,7 @@ grab_port (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const gchar *vendor_strings[] = { "cinterion", "siemens", NULL };
static const guint16 vendor_ids[] = { 0x1e2d, 0x0681, 0 };
static const MMAsyncMethod custom_init = {

View File

@@ -491,7 +491,7 @@ grab_port (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendors[] = { 0x413c, 0 };
static const MMAsyncMethod custom_init = {
.async = G_CALLBACK (dell_custom_init),

View File

@@ -67,7 +67,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendor_ids[] = { 0x2001, 0 };
return MM_PLUGIN (

View File

@@ -101,7 +101,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendor_ids[] = { 0x2cb7, 0 };
static const gchar *drivers[] = { "cdc_mbim", "qmi_wwan", NULL };

View File

@@ -98,7 +98,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendors[] = { 0x0489, 0 };
return MM_PLUGIN (

View File

@@ -91,7 +91,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
return MM_PLUGIN (
g_object_new (MM_TYPE_PLUGIN_GENERIC,

View File

@@ -82,7 +82,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendor_ids[] = { 0x305a, 0 };
static const gchar *drivers[] = { "qmi_wwan", "cdc_mbim", NULL };

View File

@@ -556,8 +556,7 @@ fallback_primary_cdcwdm (MMPlugin *self,
if (!mm_port_probe_is_at (probe))
continue;
if (g_str_has_prefix (mm_port_probe_get_port_subsys (probe), "usb") &&
g_str_has_prefix (mm_port_probe_get_port_name (probe), "cdc-wdm")) {
if (g_str_equal (mm_port_probe_get_port_subsys (probe), "usbmisc")) {
mm_obj_dbg (self, "fallback port type hint applied to first cdc-wmd port found");
g_object_set_data (G_OBJECT (probe), TAG_AT_PORT_FLAGS, GUINT_TO_POINTER (MM_PORT_SERIAL_AT_FLAG_PRIMARY));
return 1;
@@ -700,7 +699,7 @@ grab_port (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendor_ids[] = { 0x12d1, 0 };
static const MMAsyncMethod custom_init = {
.async = G_CALLBACK (huawei_custom_init),

View File

@@ -70,7 +70,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const gchar *udev_tags[] = {
"ID_MM_ERICSSON_MBM",
NULL

View File

@@ -76,7 +76,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendors[] = { 0x1410, 0 };
static const mm_uint16_pair forbidden_products[] = { { 0x1410, 0x9010 }, /* Novatel E362 */
{ 0, 0 } };

View File

@@ -130,7 +130,7 @@ grab_port (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendor_ids[] = { 0x106c, 0 };
return MM_PLUGIN (

View File

@@ -81,7 +81,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const gchar *vendor_strings[] = { "quectel", NULL };
static const guint16 vendor_ids[] = { 0x2c7c, 0 };

View File

@@ -104,7 +104,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendor_ids[] = { 0x1199, 0 };
static const gchar *drivers[] = { "qmi_wwan", "cdc_mbim", NULL };

View File

@@ -68,7 +68,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendor_ids[] = { 0x1e0e, /* A-Link (for now) */
0 };

View File

@@ -87,7 +87,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
/* Vendors: Telit */
static const guint16 vendor_ids[] = { 0x1bc7, 0 };
static const gchar *vendor_strings[] = { "telit", NULL };

View File

@@ -67,7 +67,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendor_ids[] = { 0x2357, 0 };
return MM_PLUGIN (

View File

@@ -215,7 +215,7 @@ create_modem (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
/* Vendors: TAMobile and Olivetti */
static const guint16 vendor_ids[] = { 0x1bbb, 0x0b3c, 0 };
/* Only handle X22X tagged devices here. */

View File

@@ -144,7 +144,7 @@ grab_port (MMPlugin *self,
G_MODULE_EXPORT MMPlugin *
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
static const guint16 vendor_ids[] = { 0x19d2, 0 };
return MM_PLUGIN (

View File

@@ -15,7 +15,6 @@ KERNEL=="rfcomm*", DEVPATH=="*/virtual/*", GOTO="mm_candidate_end"
SUBSYSTEM=="tty", ENV{ID_MM_CANDIDATE}="1"
SUBSYSTEM=="net", ENV{ID_MM_CANDIDATE}="1"
KERNEL=="cdc-wdm*", SUBSYSTEM=="usb", ENV{ID_MM_CANDIDATE}="1"
KERNEL=="cdc-wdm*", SUBSYSTEM=="usbmisc", ENV{ID_MM_CANDIDATE}="1"
KERNEL=="cdc-wdm[0-9]*", SUBSYSTEM=="usbmisc", ENV{ID_MM_CANDIDATE}="1"
LABEL="mm_candidate_end"

View File

@@ -143,13 +143,6 @@ find_device_by_physdev_uid (MMBaseManager *self,
return g_hash_table_lookup (self->priv->devices, physdev_uid);
}
static MMDevice *
find_device_by_kernel_device (MMBaseManager *manager,
MMKernelDevice *kernel_device)
{
return find_device_by_physdev_uid (manager, mm_kernel_device_get_physdev_uid (kernel_device));
}
/*****************************************************************************/
typedef struct {
@@ -221,27 +214,29 @@ static void
device_removed (MMBaseManager *self,
MMKernelDevice *kernel_device)
{
MMDevice *device;
const gchar *subsys;
g_autoptr(MMDevice) device = NULL;
const gchar *name;
g_return_if_fail (kernel_device != NULL);
subsys = mm_kernel_device_get_subsystem (kernel_device);
name = mm_kernel_device_get_name (kernel_device);
if (!g_str_has_prefix (subsys, "usb") ||
(name && g_str_has_prefix (name, "cdc-wdm"))) {
/* Handle tty/net/wdm port removal */
device = find_device_by_port (self, kernel_device);
if (device) {
if (!device) {
/* If the device was inhibited and the port is gone, untrack it.
* This is only needed for ports that were tracked out of device objects.
* In this case we don't rely on the physdev uid, as API-reported
* remove kernel events may not include uid. */
device_inhibited_untrack_port (self, kernel_device);
return;
}
/* The callbacks triggered when the port is released or device support is
* cancelled may end up unreffing the device or removing it from the HT, and
* so in order to make sure the reference is still valid when we call
* support_check_cancel() and g_hash_table_remove(), we hold a full reference
* ourselves. */
g_object_ref (device);
{
name = mm_kernel_device_get_name (kernel_device);
mm_obj_info (self, "port %s released by device '%s'", name, mm_device_get_uid (device));
mm_device_release_port (device, kernel_device);
@@ -256,47 +251,6 @@ device_removed (MMBaseManager *self,
mm_device_remove_modem (device);
g_hash_table_remove (self->priv->devices, mm_device_get_uid (device));
}
}
g_object_unref (device);
return;
}
/* If the device was inhibited and the port is gone, untrack it.
* This is only needed for ports that were tracked out of device objects.
* In this case we don't rely on the physdev uid, as API-reported
* remove kernel events may not include uid. */
device_inhibited_untrack_port (self, kernel_device);
return;
}
#if defined WITH_UDEV
/* When a USB modem is switching its USB configuration, udev may deliver
* the remove events of USB interfaces associated with the old USB
* configuration and the add events of USB interfaces associated with the
* new USB configuration in an interleaved fashion. As we don't want a
* remove event of an USB interface trigger the removal of a MMDevice for
* the special case being handled here, we ignore any remove event with
* DEVTYPE != usb_device.
*/
if (g_strcmp0 (mm_kernel_device_get_property (kernel_device, "DEVTYPE"), "usb_device") != 0)
return;
#endif
/* This case is designed to handle the case where, at least with kernel 2.6.31, unplugging
* an in-use ttyACMx device results in udev generating remove events for the usb, but the
* ttyACMx device (subsystem tty) is not removed, since it was in-use. So if we have not
* found a modem for the port (above), we're going to look here to see if we have a modem
* associated with the newly removed device. If so, we'll remove the modem, since the
* device has been removed. That way, if the device is reinserted later, we'll go through
* the process of exporting it.
*/
device = find_device_by_kernel_device (self, kernel_device);
if (device) {
mm_obj_dbg (self, "removing device '%s'", mm_device_get_uid (device));
mm_device_remove_modem (device);
g_hash_table_remove (self->priv->devices, mm_device_get_uid (device));
return;
}
}
static void
@@ -451,37 +405,17 @@ handle_kernel_event (MMBaseManager *self,
#if defined WITH_UDEV
static void
handle_uevent (GUdevClient *client,
handle_uevent (MMBaseManager *self,
const gchar *action,
GUdevDevice *device,
gpointer user_data)
GUdevDevice *device)
{
MMBaseManager *self;
const gchar *subsys;
const gchar *name;
MMKernelDevice *kernel_device;
self = MM_BASE_MANAGER (user_data);
g_return_if_fail (action != NULL);
/* A bit paranoid */
subsys = g_udev_device_get_subsystem (device);
g_return_if_fail (subsys != NULL);
g_return_if_fail (g_str_equal (subsys, "tty") || g_str_equal (subsys, "net") || g_str_has_prefix (subsys, "usb"));
g_autoptr(MMKernelDevice) kernel_device = NULL;
kernel_device = mm_kernel_device_udev_new (device);
/* We only care about tty/net and usb/cdc-wdm devices when adding modem ports,
* but for remove, also handle usb parent device remove events
*/
name = mm_kernel_device_get_name (kernel_device);
if ( (g_str_equal (action, "add") || g_str_equal (action, "move") || g_str_equal (action, "change"))
&& (!g_str_has_prefix (subsys, "usb") || (name && g_str_has_prefix (name, "cdc-wdm"))))
if (g_str_equal (action, "add") || g_str_equal (action, "move") || g_str_equal (action, "change"))
device_added (self, kernel_device, TRUE, FALSE);
else if (g_str_equal (action, "remove"))
device_removed (self, kernel_device);
g_object_unref (kernel_device);
}
typedef struct {
@@ -539,24 +473,8 @@ process_scan (MMBaseManager *self,
}
g_list_free (devices);
devices = g_udev_client_query_by_subsystem (self->priv->udev, "usb");
for (iter = devices; iter; iter = g_list_next (iter)) {
const gchar *name;
name = g_udev_device_get_name (G_UDEV_DEVICE (iter->data));
if (name && g_str_has_prefix (name, "cdc-wdm"))
start_device_added (self, G_UDEV_DEVICE (iter->data), manual_scan);
g_object_unref (G_OBJECT (iter->data));
}
g_list_free (devices);
/* Newer kernels report 'usbmisc' subsystem */
devices = g_udev_client_query_by_subsystem (self->priv->udev, "usbmisc");
for (iter = devices; iter; iter = g_list_next (iter)) {
const gchar *name;
name = g_udev_device_get_name (G_UDEV_DEVICE (iter->data));
if (name && g_str_has_prefix (name, "cdc-wdm"))
start_device_added (self, G_UDEV_DEVICE (iter->data), manual_scan);
g_object_unref (G_OBJECT (iter->data));
}
@@ -1449,7 +1367,7 @@ mm_base_manager_init (MMBaseManager *self)
#if defined WITH_UDEV
{
const gchar *subsys[5] = { "tty", "net", "usb", "usbmisc", NULL };
const gchar *subsys[5] = { "tty", "net", "usbmisc", NULL };
/* Setup UDev client */
self->priv->udev = g_udev_client_new (subsys);
@@ -1484,7 +1402,7 @@ initable_init (GInitable *initable,
#if defined WITH_UDEV
/* If autoscan enabled, list for udev events */
if (self->priv->auto_scan)
g_signal_connect (self->priv->udev, "uevent", G_CALLBACK (handle_uevent), initable);
g_signal_connect_swapped (self->priv->udev, "uevent", G_CALLBACK (handle_uevent), initable);
#endif
/* Create filter */

View File

@@ -276,7 +276,7 @@ mm_base_modem_grab_port (MMBaseModem *self,
port = base_modem_create_net_port (self, name);
else if (g_str_equal (subsys, "tty"))
port = base_modem_create_tty_port (self, name, kernel_device, ptype);
else if (g_str_has_prefix (subsys, "usb") && g_str_has_prefix (name, "cdc-wdm"))
else if (g_str_equal (subsys, "usbmisc"))
port = base_modem_create_usbmisc_port (self, name, ptype);
else if (g_str_equal (subsys, "virtual"))
port = base_modem_create_virtual_port (self, name);

View File

@@ -194,7 +194,7 @@ mm_filter_port (MMFilter *self,
/* If this is a cdc-wdm device, we always allow it */
if ((self->priv->enabled_rules & MM_FILTER_RULE_USBMISC) &&
(g_strcmp0 (subsystem, "usb") == 0 || g_strcmp0 (subsystem, "usbmisc") == 0)) {
(g_strcmp0 (subsystem, "usbmisc") == 0)) {
mm_obj_dbg (self, "(%s/%s) port allowed: usbmisc device", subsystem, name);
return TRUE;
}

View File

@@ -217,10 +217,6 @@ apply_subsystem_filter (MMPlugin *self,
for (i = 0; self->priv->subsystems[i]; i++) {
if (g_str_equal (subsys, self->priv->subsystems[i]))
break;
/* New kernels may report as 'usbmisc' the subsystem */
else if (g_str_equal (self->priv->subsystems[i], "usb") &&
g_str_equal (subsys, "usbmisc"))
break;
}
/* If we didn't match any subsystem: unsupported */

View File

@@ -1271,7 +1271,7 @@ serial_open_at (MMPortProbe *self)
gpointer parser;
MMPortSubsys subsys = MM_PORT_SUBSYS_TTY;
if (g_str_has_prefix (mm_kernel_device_get_subsystem (self->priv->port), "usb"))
if (g_str_equal (mm_kernel_device_get_subsystem (self->priv->port), "usbmisc"))
subsys = MM_PORT_SUBSYS_USBMISC;
ctx->serial = MM_PORT_SERIAL (mm_port_serial_at_new (mm_kernel_device_get_name (self->priv->port), subsys));