aboutsummaryrefslogtreecommitdiff
path: root/src/mm-plugin-manager.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksandermj@chromium.org>2024-03-06 13:47:55 +0000
committerAleksander Morgado <aleksandermj@chromium.org>2024-03-12 10:15:59 +0000
commitbd255849dcdbcaa3280033b0974a6a5e0473566e (patch)
tree128d517534eb046d521d471233ffd3c4b390d285 /src/mm-plugin-manager.c
parent07f1f5864204dfdf455067def863fcd20c8c6a26 (diff)
base-manager: reprobe device on late port additions
There is no guarantee from the kernel that the ports of a given device will all be notified via uevents on a timely manner. We assume it, but we cannot be completely sure. There are two main scenarios that we have been seen when the ports of a device are not notified close enough to each other: * A modem object is created, but not with the desired control protocol. E.g. a QMI or MBIM modem would end up controlled via AT commands if the cdc-wdm port was added too late. * A modem object is not created at all, and the device object was removed completely. E.g. when the net port addition in a QMI or MBIM modem happens too late. In order to avoid those cases, we will now fully reprobe all the ports of the device from scratch whenever a new valid port addition happens after the initial probing of the device has already been completed. If a modem object is available at that time, we will remove it right away.
Diffstat (limited to 'src/mm-plugin-manager.c')
-rw-r--r--src/mm-plugin-manager.c101
1 files changed, 59 insertions, 42 deletions
diff --git a/src/mm-plugin-manager.c b/src/mm-plugin-manager.c
index c2438664..0179e5d0 100644
--- a/src/mm-plugin-manager.c
+++ b/src/mm-plugin-manager.c
@@ -784,10 +784,9 @@ struct _DeviceContext {
* is reset to 0. */
guint extra_probing_time_id;
- /* Signal connection ids for the grabbed/released signals from the device.
- * These are the signals that will give us notifications of what ports are
- * available (or suddenly unavailable) in the device. */
- gulong grabbed_id;
+ /* Signal connection ids for the released signal from the device. This is a
+ * signal that will give us notifications of ports suddenly unavailable in
+ * the device. */
gulong released_id;
/* Port support check contexts being run */
@@ -800,7 +799,6 @@ device_context_unref (DeviceContext *device_context)
if (g_atomic_int_dec_and_test (&device_context->ref_count)) {
/* When the last reference is gone there must be no source scheduled and no
* pending port tasks. */
- g_assert (!device_context->grabbed_id);
g_assert (!device_context->released_id);
g_assert (!device_context->min_wait_time_id);
g_assert (!device_context->min_probing_time_id);
@@ -898,18 +896,13 @@ device_context_complete (DeviceContext *device_context)
/* Steal the task from the context */
g_assert (device_context->task);
- task = device_context->task;
- device_context->task = NULL;
+ task = g_steal_pointer (&device_context->task);
/* Log about the time required to complete the checks */
mm_obj_dbg (self, "task %s: finished in '%lf' seconds",
device_context->name, g_timer_elapsed (device_context->timer, NULL));
/* Remove signal handlers */
- if (device_context->grabbed_id) {
- g_signal_handler_disconnect (device_context->device, device_context->grabbed_id);
- device_context->grabbed_id = 0;
- }
if (device_context->released_id) {
g_signal_handler_disconnect (device_context->device, device_context->released_id);
device_context->released_id = 0;
@@ -1276,16 +1269,13 @@ device_context_port_released (DeviceContext *device_context,
}
static void
-device_context_port_grabbed (DeviceContext *device_context,
- MMKernelDevice *port)
+device_context_port_added (MMPluginManager *self,
+ DeviceContext *device_context,
+ MMKernelDevice *port)
{
- MMPluginManager *self;
- PortContext *port_context;
-
- /* Recover plugin manager */
- self = MM_PLUGIN_MANAGER (device_context->self);
+ PortContext *port_context;
- mm_obj_dbg (self, "task %s: port grabbed: %s",
+ mm_obj_dbg (self, "task %s: port added: %s",
device_context->name, mm_kernel_device_get_name (port));
/* Ignore if for any reason we still have it in the running list */
@@ -1311,7 +1301,7 @@ device_context_port_grabbed (DeviceContext *device_context,
(GSourceFunc) device_context_extra_probing_time_elapsed,
device_context);
- /* Setup a new port context for the newly grabbed port */
+ /* Setup a new port context for the newly added port */
port_context = port_context_new (self,
device_context->name,
device_context->device,
@@ -1332,7 +1322,7 @@ device_context_port_grabbed (DeviceContext *device_context,
/* Store the port reference in the list within the device */
device_context->port_contexts = g_list_prepend (device_context->port_contexts, port_context) ;
- /* If the port has been grabbed after the min wait timeout expired, launch
+ /* If the port has been added after the min wait timeout expired, launch
* probing directly */
device_context_run_port_context (device_context, port_context);
}
@@ -1394,17 +1384,12 @@ device_context_run (MMPluginManager *self,
gpointer user_data)
{
g_assert (!device_context->task);
- g_assert (!device_context->grabbed_id);
g_assert (!device_context->released_id);
g_assert (!device_context->min_wait_time_id);
g_assert (!device_context->min_probing_time_id);
g_assert (!device_context->extra_probing_time_id);
- /* Connect to device port grabbed/released notifications from the device */
- device_context->grabbed_id = g_signal_connect_swapped (device_context->device,
- MM_DEVICE_PORT_GRABBED,
- G_CALLBACK (device_context_port_grabbed),
- device_context);
+ /* Connect to device port released notifications from the device */
device_context->released_id = g_signal_connect_swapped (device_context->device,
MM_DEVICE_PORT_RELEASED,
G_CALLBACK (device_context_port_released),
@@ -1507,21 +1492,6 @@ plugin_manager_peek_device_context (MMPluginManager *self,
return NULL;
}
-gboolean
-mm_plugin_manager_device_support_check_cancel (MMPluginManager *self,
- MMDevice *device)
-{
- DeviceContext *device_context;
-
- /* If the device context isn't found, ignore the cancellation request. */
- device_context = plugin_manager_peek_device_context (self, device);
- if (!device_context)
- return FALSE;
-
- /* Request cancellation, will be completed asynchronously */
- return device_context_cancel (device_context);
-}
-
static void
device_context_run_ready (MMPluginManager *self,
GAsyncResult *res,
@@ -1599,6 +1569,53 @@ mm_plugin_manager_device_support_check (MMPluginManager *self,
}
/*****************************************************************************/
+/* Cancel the ongoing device support check, if any */
+
+gboolean
+mm_plugin_manager_device_support_check_cancel (MMPluginManager *self,
+ MMDevice *device)
+{
+ DeviceContext *device_context;
+
+ /* If the device context isn't found, ignore the cancellation request. */
+ device_context = plugin_manager_peek_device_context (self, device);
+ if (!device_context)
+ return FALSE;
+
+ /* Request cancellation, will be completed asynchronously */
+ return device_context_cancel (device_context);
+}
+
+/*****************************************************************************/
+/* Ask if there is an ongoing device support check */
+
+gboolean
+mm_plugin_manager_device_support_check_ongoing (MMPluginManager *self,
+ MMDevice *device)
+{
+ return !!plugin_manager_peek_device_context (self, device);
+}
+
+/*****************************************************************************/
+/* Report a new port to the ongoing device support check */
+
+gboolean
+mm_plugin_manager_device_support_check_add_port (MMPluginManager *self,
+ MMDevice *device,
+ MMKernelDevice *port)
+{
+ DeviceContext *device_context;
+
+ device_context = plugin_manager_peek_device_context (self, device);
+ if (device_context) {
+ device_context_port_added (self, device_context, port);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
/* Look for plugin */
MMPlugin *