[PATCH 1/2] MM: disable(): Finish all disable commands before returning



This addresses some dubious behavior that was one source of a crash on
our systems.

    - Nathan
From 7e9aebaeb179be5a9093c74815af45b62cc849b7 Mon Sep 17 00:00:00 2001
From: Nathan Williams <njw chromium org>
Date: Thu, 3 Nov 2011 16:13:07 -0400
Subject: [PATCH 1/2] disable(): Finish all disable commands before returning

Rearrange the primary and secondary-port disable operations so that
there's a linear chain of callbacks rather than a second dangling
callback chain for the secondary port; it's possible for the primary
port operations to complete, and for the callback to finish and start
tearing down the entire device, before the secondary port commands
run.

Change-Id: Ia95a7eae574737cdec38b14d39786127be1b3184
---
 src/mm-generic-gsm.c |   40 +++++++++++++++++++++++++---------------
 1 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index a0eed39..423c8bb 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -2088,6 +2088,22 @@ disable_flash_done (MMSerialPort *port,
     g_free (cmd);
 }
 
+void
+mark_disabled (gpointer user_data)
+{
+    MMCallbackInfo *info = user_data;
+    MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
+
+    mm_modem_set_state (MM_MODEM (info->modem),
+                        MM_MODEM_STATE_DISABLING,
+                        MM_MODEM_STATE_REASON_NONE);
+
+    if (mm_port_get_connected (MM_PORT (priv->primary)))
+        mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, TRUE, disable_flash_done, info);
+    else
+        disable_flash_done (MM_SERIAL_PORT (priv->primary), NULL, info);
+}
+
 static void
 secondary_unsolicited_done (MMAtSerialPort *port,
                             GString *response,
@@ -2095,6 +2111,7 @@ secondary_unsolicited_done (MMAtSerialPort *port,
                             gpointer user_data)
 {
     mm_serial_port_close_force (MM_SERIAL_PORT (port));
+    mark_disabled (user_data);
 }
 
 static void
@@ -2132,13 +2149,6 @@ disable (MMModem *modem,
     update_lac_ci (self, 0, 0, 1);
     _internal_update_access_technology (self, MM_MODEM_GSM_ACCESS_TECH_UNKNOWN);
 
-    /* Clean up the secondary port if it's open */
-    if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary))) {
-        mm_at_serial_port_queue_command (priv->secondary, "+CREG=0", 3, NULL, NULL);
-        mm_at_serial_port_queue_command (priv->secondary, "+CGREG=0", 3, NULL, NULL);
-        mm_at_serial_port_queue_command (priv->secondary, "+CMER=0", 3, secondary_unsolicited_done, NULL);
-    }
-
     info = mm_callback_info_new (modem, callback, user_data);
 
     /* Cache the previous state so we can reset it if the operation fails */
@@ -2148,14 +2158,14 @@ disable (MMModem *modem,
                                GUINT_TO_POINTER (state),
                                NULL);
 
-    mm_modem_set_state (MM_MODEM (info->modem),
-                        MM_MODEM_STATE_DISABLING,
-                        MM_MODEM_STATE_REASON_NONE);
-
-    if (mm_port_get_connected (MM_PORT (priv->primary)))
-        mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, TRUE, disable_flash_done, info);
-    else
-        disable_flash_done (MM_SERIAL_PORT (priv->primary), NULL, info);
+    /* Clean up the secondary port if it's open */
+    if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary))) {
+        mm_dbg("Shutting down secondary port");
+        mm_at_serial_port_queue_command (priv->secondary, "+CREG=0", 3, NULL, NULL);
+        mm_at_serial_port_queue_command (priv->secondary, "+CGREG=0", 3, NULL, NULL);
+        mm_at_serial_port_queue_command (priv->secondary, "+CMER=0", 3, secondary_unsolicited_done, info);
+    } else
+        mark_disabled (info);
 }
 
 static void
-- 
1.7.3.1



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]