summaryrefslogtreecommitdiff
path: root/src/mm-plugin-manager.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2014-06-02 09:25:36 +0200
committerAleksander Morgado <aleksander@aleksander.es>2014-06-02 17:41:49 +0200
commitc9dc702eaa50ea54981b1bcfb9e2f2492a2f9b33 (patch)
tree73056a0c170c5987d16459857b82df49732c5af0 /src/mm-plugin-manager.c
parent239ab6ca6b6e8af45a25a32692cdc10e5f0071f1 (diff)
downloadModemManager-c9dc702eaa50ea54981b1bcfb9e2f2492a2f9b33.tar.gz
plugin-manager: fix defer-until-suggested probing tasks
If a task is marked as defer-until-suggested (e.g. a wwan port) and there was already a 'best' plugin set in the parent device, use it to complete the deferred task. This may happen in e.g. MBIM devices if the WWAN port arrives later than the already probed /dev/cdc-wdm character device.
Diffstat (limited to 'src/mm-plugin-manager.c')
-rw-r--r--src/mm-plugin-manager.c165
1 files changed, 99 insertions, 66 deletions
diff --git a/src/mm-plugin-manager.c b/src/mm-plugin-manager.c
index 8c2fc3177..73aa74948 100644
--- a/src/mm-plugin-manager.c
+++ b/src/mm-plugin-manager.c
@@ -331,6 +331,84 @@ deferred_support_check_idle (PortProbeContext *port_probe_ctx)
}
static void
+suggest_single_port_probe_result (PortProbeContext *target_port_probe_ctx,
+ MMPlugin *suggested_plugin,
+ gboolean reschedule_deferred)
+{
+ gboolean forbidden_icera;
+
+ /* Plugin suggestions serve two different purposes here:
+ * 1) Finish all the probes which were deferred until suggested.
+ * 2) Suggest to other probes which plugin to test next.
+ *
+ * The exception here is when we suggest the GENERIC plugin.
+ * In this case, only purpose (1) is applied, this is, only
+ * the deferred until suggested probes get finished.
+ */
+
+ if (target_port_probe_ctx->best_plugin || target_port_probe_ctx->suggested_plugin)
+ return;
+
+ /* Complete tasks which were deferred until suggested */
+ if (target_port_probe_ctx->defer_until_suggested) {
+ /* Reset the defer until suggested flag; we consider this
+ * cancelled probe completed now. */
+ target_port_probe_ctx->defer_until_suggested = FALSE;
+
+ if (suggested_plugin) {
+ mm_dbg ("(Plugin Manager) (%s) [%s] deferred task completed, got suggested plugin",
+ mm_plugin_get_name (suggested_plugin),
+ g_udev_device_get_name (target_port_probe_ctx->port));
+ /* Advance to the suggested plugin and re-check support there */
+ target_port_probe_ctx->suggested_plugin = g_object_ref (suggested_plugin);
+ target_port_probe_ctx->current = g_list_find (target_port_probe_ctx->current,
+ target_port_probe_ctx->suggested_plugin);
+ } else {
+ mm_dbg ("(Plugin Manager) [%s] deferred task cancelled, no suggested plugin",
+ g_udev_device_get_name (target_port_probe_ctx->port));
+ target_port_probe_ctx->best_plugin = NULL;
+ target_port_probe_ctx->current = NULL;
+ }
+
+ /* Schedule checking support, which will end the operation */
+ if (reschedule_deferred) {
+ g_assert (target_port_probe_ctx->defer_id == 0);
+ target_port_probe_ctx->defer_id = g_idle_add ((GSourceFunc)deferred_support_check_idle,
+ target_port_probe_ctx);
+ }
+ return;
+ }
+
+ /* If no plugin being suggested, done */
+ if (!suggested_plugin)
+ return;
+
+ /* The GENERIC plugin is NEVER suggested to others */
+ if (g_str_equal (mm_plugin_get_name (suggested_plugin), MM_PLUGIN_GENERIC_NAME))
+ return;
+
+ /* If the plugin has MM_PLUGIN_FORBIDDEN_ICERA set, we do *not* suggest
+ * the plugin to others. Icera devices may not reply to the icera probing
+ * in all ports, so if other ports need to be tested for icera support,
+ * they should all go on. */
+ g_object_get (suggested_plugin,
+ MM_PLUGIN_FORBIDDEN_ICERA, &forbidden_icera,
+ NULL);
+ if (forbidden_icera)
+ return;
+
+ /* We should *not* cancel probing in the port if the plugin being
+ * checked right now is not the one being suggested. Each port
+ * should run its probing independently, and we'll later decide
+ * which result applies to the whole device.
+ */
+ mm_dbg ("(Plugin Manager) (%s) [%s] suggested plugin for port",
+ mm_plugin_get_name (suggested_plugin),
+ g_udev_device_get_name (target_port_probe_ctx->port));
+ target_port_probe_ctx->suggested_plugin = g_object_ref (suggested_plugin);
+}
+
+static void
suggest_port_probe_result (FindDeviceSupportContext *ctx,
PortProbeContext *origin,
MMPlugin *suggested_plugin)
@@ -340,72 +418,8 @@ suggest_port_probe_result (FindDeviceSupportContext *ctx,
for (l = ctx->running_probes; l; l = g_list_next (l)) {
PortProbeContext *port_probe_ctx = l->data;
- /* Plugin suggestions serve two different purposes here:
- * 1) Finish all the probes which were deferred until suggested.
- * 2) Suggest to other probes which plugin to test next.
- *
- * The exception here is when we suggest the GENERIC plugin.
- * In this case, only purpose (1) is applied, this is, only
- * the deferred until suggested probes get finished.
- */
-
- if (port_probe_ctx != origin &&
- !port_probe_ctx->best_plugin &&
- !port_probe_ctx->suggested_plugin) {
- /* If we got a task deferred until a suggestion comes,
- * complete it */
- if (port_probe_ctx->defer_until_suggested) {
- /* Reset the defer until suggested flag; we consider this
- * cancelled probe completed now. */
- port_probe_ctx->defer_until_suggested = FALSE;
-
- if (suggested_plugin) {
- mm_dbg ("(Plugin Manager) (%s) [%s] deferred task completed, got suggested plugin",
- mm_plugin_get_name (suggested_plugin),
- g_udev_device_get_name (port_probe_ctx->port));
- /* Advance to the suggested plugin and re-check support there */
- port_probe_ctx->suggested_plugin = g_object_ref (suggested_plugin);
- port_probe_ctx->current = g_list_find (port_probe_ctx->current,
- port_probe_ctx->suggested_plugin);
- } else {
- mm_dbg ("(Plugin Manager) [%s] deferred task cancelled, no suggested plugin",
- g_udev_device_get_name (port_probe_ctx->port));
- port_probe_ctx->best_plugin = NULL;
- port_probe_ctx->current = NULL;
- }
-
- /* Schedule checking support, which will end the operation */
- g_assert (port_probe_ctx->defer_id == 0);
- port_probe_ctx->defer_id = g_idle_add ((GSourceFunc)deferred_support_check_idle,
- port_probe_ctx);
- }
- /* We should *not* cancel probing in the port if the plugin being
- * checked right now is not the one being suggested. Each port
- * should run its probing independently, and we'll later decide
- * which result applies to the whole device.
- */
- else if (suggested_plugin &&
- /* The GENERIC plugin is NEVER suggested to others */
- !g_str_equal (mm_plugin_get_name (suggested_plugin),
- MM_PLUGIN_GENERIC_NAME)) {
- gboolean forbidden_icera;
-
- /* If the plugin has MM_PLUGIN_FORBIDDEN_ICERA set, we do *not* suggest
- * the plugin to others. Icera devices may not reply to the icera probing
- * in all ports, so if other ports need to be tested for icera support,
- * they should all go on. */
- g_object_get (suggested_plugin,
- MM_PLUGIN_FORBIDDEN_ICERA, &forbidden_icera,
- NULL);
-
- if (!forbidden_icera) {
- mm_dbg ("(Plugin Manager) (%s) [%s] suggested plugin for port",
- mm_plugin_get_name (suggested_plugin),
- g_udev_device_get_name (port_probe_ctx->port));
- port_probe_ctx->suggested_plugin = g_object_ref (suggested_plugin);
- }
- }
- }
+ if (port_probe_ctx != origin)
+ suggest_single_port_probe_result (port_probe_ctx, suggested_plugin, TRUE);
}
}
@@ -508,6 +522,25 @@ plugin_supports_port_ready (MMPlugin *plugin,
case MM_PLUGIN_SUPPORTS_PORT_DEFER_UNTIL_SUGGESTED:
+ /* If we're deferred until suggested, but there is already a plugin
+ * suggested in the parent device context, grab it. This may happen if
+ * e.g. a wwan interface arrives *after* a port has already been probed.
+ */
+ if (!port_probe_ctx->suggested_plugin) {
+ MMPlugin *device_plugin;
+
+ /* Get info about the currently scheduled plugin in the device */
+ device_plugin = (MMPlugin *)mm_device_peek_plugin (port_probe_ctx->parent_ctx->device);
+ if (device_plugin) {
+ mm_dbg ("(Plugin Manager) (%s) [%s] task deferred until result suggested and got suggested plugin",
+ mm_plugin_get_name (device_plugin),
+ g_udev_device_get_name (port_probe_ctx->port));
+ /* Flag it as deferred before suggesting probe result */
+ port_probe_ctx->defer_until_suggested = TRUE;
+ suggest_single_port_probe_result (port_probe_ctx, device_plugin, FALSE);
+ }
+ }
+
/* If we arrived here and we already have a plugin suggested, use it */
if (port_probe_ctx->suggested_plugin) {
if (port_probe_ctx->suggested_plugin == plugin) {