aboutsummaryrefslogtreecommitdiff
path: root/src/mm-base-manager.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2020-11-06 12:27:40 +0100
committerAleksander Morgado <aleksander@aleksander.es>2020-11-13 08:57:06 +0000
commit950abbf8ee8624827d63a0d0186beac81232e8f6 (patch)
tree675ff1b0231b196af7530041d167cca7eb4d17fa /src/mm-base-manager.c
parent519df2544b04ccbc9cf87fbfbdbbaf44edeef75b (diff)
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.
Diffstat (limited to 'src/mm-base-manager.c')
-rw-r--r--src/mm-base-manager.c142
1 files changed, 30 insertions, 112 deletions
diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c
index b8adcdbc..87eddc34 100644
--- a/src/mm-base-manager.c
+++ b/src/mm-base-manager.c
@@ -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,46 +214,13 @@ static void
device_removed (MMBaseManager *self,
MMKernelDevice *kernel_device)
{
- MMDevice *device;
- const gchar *subsys;
- const gchar *name;
+ 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) {
- /* 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);
- {
- mm_obj_info (self, "port %s released by device '%s'", name, mm_device_get_uid (device));
- mm_device_release_port (device, kernel_device);
-
- /* If port probe list gets empty, remove the device object iself */
- if (!mm_device_peek_port_probe_list (device)) {
- mm_obj_dbg (self, "removing empty device '%s'", mm_device_get_uid (device));
- if (mm_plugin_manager_device_support_check_cancel (self->priv->plugin_manager, device))
- mm_obj_dbg (self, "device support check has been cancelled");
-
- /* The device may have already been removed from the tracking HT, we
- * just try to remove it and if it fails, we ignore it */
- mm_device_remove_modem (device);
- g_hash_table_remove (self->priv->devices, mm_device_get_uid (device));
- }
- }
- g_object_unref (device);
- return;
- }
-
+ device = find_device_by_port (self, kernel_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
@@ -269,33 +229,27 @@ device_removed (MMBaseManager *self,
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
+ /* 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);
- /* 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));
+ 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);
+
+ /* If port probe list gets empty, remove the device object iself */
+ if (!mm_device_peek_port_probe_list (device)) {
+ mm_obj_dbg (self, "removing empty device '%s'", mm_device_get_uid (device));
+ if (mm_plugin_manager_device_support_check_cancel (self->priv->plugin_manager, device))
+ mm_obj_dbg (self, "device support check has been cancelled");
+
+ /* The device may have already been removed from the tracking HT, we
+ * just try to remove it and if it fails, we ignore it */
mm_device_remove_modem (device);
g_hash_table_remove (self->priv->devices, mm_device_get_uid (device));
- return;
}
}
@@ -451,37 +405,17 @@ handle_kernel_event (MMBaseManager *self,
#if defined WITH_UDEV
static void
-handle_uevent (GUdevClient *client,
- const gchar *action,
- GUdevDevice *device,
- gpointer user_data)
+handle_uevent (MMBaseManager *self,
+ const gchar *action,
+ 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,25 +473,9 @@ 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);
+ start_device_added (self, G_UDEV_DEVICE (iter->data), manual_scan);
g_object_unref (G_OBJECT (iter->data));
}
g_list_free (devices);
@@ -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 */