[PATCH] mm-broadband-modem-qmi: reprobe on qmi-proxy death

Eric Caruso ejcaruso at chromium.org
Fri Oct 20 17:10:47 UTC 2017


This allows us to reprobe the modem and respawn the
qmi-proxy in case it dies on us. This gets us access
to the modem and unsolicited notifications again. Do
this by connecting to the device-removed signal on
QmiDevice.
---
 configure.ac                 |  2 +-
 src/mm-broadband-modem-qmi.c | 70 ++++++++++++++++++++++++++++++++++++++++----
 src/mm-port-qmi.c            | 10 +++++++
 src/mm-port-qmi.h            |  2 ++
 4 files changed, 77 insertions(+), 7 deletions(-)

diff --git a/configure.ac b/configure.ac
index f432e81d..7d6bfd95 100644
--- a/configure.ac
+++ b/configure.ac
@@ -341,7 +341,7 @@ dnl-----------------------------------------------------------------------------
 dnl QMI support (enabled by default)
 dnl
 
-LIBQMI_VERSION=1.17.900
+LIBQMI_VERSION=1.19.1
 
 AC_ARG_WITH(qmi, AS_HELP_STRING([--without-qmi], [Build without QMI support]), [], [with_qmi=yes])
 AM_CONDITIONAL(WITH_QMI, test "x$with_qmi" = "xyes")
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 541a24cb..13facde4 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -126,6 +126,9 @@ struct _MMBroadbandModemQmiPrivate {
     /* Firmware helpers */
     GList *firmware_list;
     MMFirmwareProperties *current_firmware;
+
+    /* For notifying when the qmi-proxy connection is dead */
+    guint qmi_device_removed_id;
 };
 
 /*****************************************************************************/
@@ -11286,6 +11289,54 @@ parent_initialization_started (InitializationStartedContext *ctx)
         ctx);
 }
 
+static void
+qmi_device_removed_cb (QmiDevice *device,
+                       MMBroadbandModemQmi *self)
+{
+    /* Reprobe the modem here so we can get notifications back. */
+    mm_info ("Connection to qmi-proxy for %s lost, reprobing",
+             qmi_device_get_path_display (device));
+
+    g_signal_handler_disconnect (device, self->priv->qmi_device_removed_id);
+    self->priv->qmi_device_removed_id = 0;
+
+    mm_base_modem_set_reprobe (MM_BASE_MODEM (self), TRUE);
+    mm_base_modem_set_valid (MM_BASE_MODEM (self), FALSE);
+}
+
+static void
+track_qmi_device_removed (MMBroadbandModemQmi *self,
+                          MMPortQmi* qmi)
+{
+    QmiDevice *device;
+
+    device = mm_port_qmi_peek_device (qmi);
+    g_assert (device);
+
+    self->priv->qmi_device_removed_id = g_signal_connect (
+        device,
+        QMI_DEVICE_SIGNAL_REMOVED,
+        G_CALLBACK (qmi_device_removed_cb),
+        self);
+}
+
+static void
+untrack_qmi_device_removed (MMBroadbandModemQmi *self,
+                            MMPortQmi* qmi)
+{
+    QmiDevice *device;
+
+    if (self->priv->qmi_device_removed_id == 0)
+        return;
+
+    device = mm_port_qmi_peek_device (qmi);
+    if (!device)
+        return;
+
+    g_signal_handler_disconnect (device, self->priv->qmi_device_removed_id);
+    self->priv->qmi_device_removed_id = 0;
+}
+
 static void allocate_next_client (InitializationStartedContext *ctx);
 
 static void
@@ -11310,7 +11361,9 @@ static void
 allocate_next_client (InitializationStartedContext *ctx)
 {
     if (ctx->services[ctx->service_index] == QMI_SERVICE_UNKNOWN) {
-        /* Done we are, launch parent's callback */
+        /* Done we are, track device removal and launch parent's callback */
+        track_qmi_device_removed (MM_BROADBAND_MODEM_QMI (ctx->self),
+                                  ctx->qmi);
         parent_initialization_started (ctx);
         return;
     }
@@ -11391,7 +11444,10 @@ initialization_started (MMBroadbandModem *self,
     }
 
     if (mm_port_qmi_is_open (ctx->qmi)) {
-        /* Nothing to be done, just launch parent's callback */
+        /* Nothing to be done, just track device removal and launch parent's
+         * callback */
+        track_qmi_device_removed (MM_BROADBAND_MODEM_QMI (ctx->self),
+                                  ctx->qmi);
         parent_initialization_started (ctx);
         return;
     }
@@ -11447,10 +11503,12 @@ finalize (GObject *object)
     MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (object);
 
     qmi = mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self));
-    /* If we did open the QMI port during initialization, close it now */
-    if (qmi &&
-        mm_port_qmi_is_open (qmi)) {
-        mm_port_qmi_close (qmi);
+    if (qmi) {
+        /* Disconnect signal handler for qmi-proxy disappearing, if it exists */
+        untrack_qmi_device_removed (self, qmi);
+        /* If we did open the QMI port during initialization, close it now */
+        if (mm_port_qmi_is_open (qmi))
+            mm_port_qmi_close (qmi);
     }
 
     g_free (self->priv->imei);
diff --git a/src/mm-port-qmi.c b/src/mm-port-qmi.c
index e2f63054..129700c9 100644
--- a/src/mm-port-qmi.c
+++ b/src/mm-port-qmi.c
@@ -72,6 +72,16 @@ mm_port_qmi_get_client (MMPortQmi *self,
 
 /*****************************************************************************/
 
+QmiDevice *
+mm_port_qmi_peek_device (MMPortQmi *self)
+{
+    g_return_val_if_fail (MM_IS_PORT_QMI (self), NULL);
+
+    return self->priv->qmi_device;
+}
+
+/*****************************************************************************/
+
 typedef struct {
     ServiceInfo *info;
 } AllocateClientContext;
diff --git a/src/mm-port-qmi.h b/src/mm-port-qmi.h
index 2724140a..26818c84 100644
--- a/src/mm-port-qmi.h
+++ b/src/mm-port-qmi.h
@@ -82,6 +82,8 @@ QmiClient *mm_port_qmi_get_client  (MMPortQmi *self,
                                     QmiService service,
                                     MMPortQmiFlag flag);
 
+QmiDevice *mm_port_qmi_peek_device (MMPortQmi *self);
+
 gboolean mm_port_qmi_llp_is_raw_ip (MMPortQmi *self);
 
 #endif /* MM_PORT_QMI_H */
-- 
2.15.0.rc0.271.g36b669edcc-goog



More information about the ModemManager-devel mailing list