<div dir="ltr"><div>Thanks Aleksander,</div><div><br></div>Verified that the final patch here on top of <div><br></div><div>[PATCH v4 1/2] bearer: consolidate unsolicited connection status reports</div><div><br></div><div>
work correctly w.r.t. Huawei MU736, i.e., connect/disconnect/network initiated disconnect operations all work correctly.</div>
<div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Sep 20, 2013 at 10:29 AM, Aleksander Morgado <span dir="ltr"><<a href="mailto:aleksander@lanedo.com" target="_blank">aleksander@lanedo.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>Originally developed by:<br>
Prathmesh Prabhu <<a href="mailto:pprabhu@chromium.org" target="_blank">pprabhu@chromium.org</a>><br>
Ben Chan <<a href="mailto:benchan@chromium.org" target="_blank">benchan@chromium.org</a>><br>
<br>
Huawei MU736 prematurely fires a ^NDISSTAT unsolicited message upon a<br>
network-initiated disconnection. The modem can go into a bad state if a<br>
reconnect attempt happens before the disconnection completes. This patch works<br>
around the issue by delaying the reporting of the disconnection.<br>
---<br>
plugins/huawei/mm-broadband-bearer-huawei.c | 56 ++++++++++++++++++++++++++++-<br>
</div> plugins/huawei/mm-broadband-modem-huawei.c | 7 ++--<br>
src/mm-bearer.h | 1 +<br>
3 files changed, 61 insertions(+), 3 deletions(-)<br>
<div><div><br>
diff --git a/plugins/huawei/mm-broadband-bearer-huawei.c b/plugins/huawei/mm-broadband-bearer-huawei.c<br>
index 2d8f0cd..deb91ca 100644<br>
--- a/plugins/huawei/mm-broadband-bearer-huawei.c<br>
+++ b/plugins/huawei/mm-broadband-bearer-huawei.c<br>
@@ -37,6 +37,8 @@ G_DEFINE_TYPE (MMBroadbandBearerHuawei, mm_broadband_bearer_huawei, MM_TYPE_BROA<br>
struct _MMBroadbandBearerHuaweiPrivate {<br>
gpointer connect_pending;<br>
gpointer disconnect_pending;<br>
+ /* Tag for the post task for network-initiated disconnect */<br>
+ guint network_disconnect_pending_id;<br>
};<br>
<br>
/*****************************************************************************/<br>
@@ -232,6 +234,11 @@ connect_3gpp_context_step (Connect3gppContext *ctx)<br>
return;<br>
}<br>
<br>
+ /* Network-initiated disconnect should not be outstanding at this point,<br>
+ * because it interferes with the connect attempt.<br>
+ */<br>
+ g_assert (ctx->self->priv->network_disconnect_pending_id == 0);<br>
+<br>
switch (ctx->step) {<br>
case CONNECT_3GPP_CONTEXT_STEP_FIRST: {<br>
MMBearerIpFamily ip_family;<br>
@@ -598,6 +605,11 @@ disconnect_3gpp_context_step (Disconnect3gppContext *ctx)<br>
return;<br>
<br>
case DISCONNECT_3GPP_CONTEXT_STEP_LAST:<br>
+ if (ctx->self->priv->network_disconnect_pending_id != 0) {<br>
+ g_source_remove (ctx->self->priv->network_disconnect_pending_id);<br>
+ ctx->self->priv->network_disconnect_pending_id = 0;<br>
+ }<br>
+<br>
/* Clear context */<br>
ctx->self->priv->disconnect_pending = NULL;<br>
/* Set data port as result */<br>
@@ -640,6 +652,18 @@ disconnect_3gpp (MMBroadbandBearer *self,<br>
<br>
/*****************************************************************************/<br>
<br>
+static gboolean<br>
+network_disconnect_3gpp_delayed (MMBroadbandBearerHuawei *self)<br>
+{<br>
+ mm_dbg ("Disconnect bearer '%s' on network request.",<br>
+ mm_bearer_get_path (MM_BEARER (self)));<br>
+<br>
+ self->priv->network_disconnect_pending_id = 0;<br>
+ mm_bearer_report_connection_status (MM_BEARER (self),<br>
+ MM_BEARER_CONNECTION_STATUS_DISCONNECTED);<br>
+ return FALSE;<br>
+}<br>
+<br>
static void<br>
report_connection_status (MMBearer *bearer,<br>
MMBearerConnectionStatus status)<br>
@@ -647,6 +671,7 @@ report_connection_status (MMBearer *bearer,<br>
MMBroadbandBearerHuawei *self = MM_BROADBAND_BEARER_HUAWEI (bearer);<br>
<br>
g_assert (status == MM_BEARER_CONNECTION_STATUS_CONNECTED ||<br>
+ status == MM_BEARER_CONNECTION_STATUS_DISCONNECTING ||<br>
status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED);<br>
<br>
/* When a pending connection / disconnection attempt is in progress, we use<br>
@@ -664,7 +689,22 @@ report_connection_status (MMBearer *bearer,<br>
<br>
/* We already use ^NDISSTATQRY? to poll the connection status, so only<br>
* handle network-initiated disconnection here. */<br>
- mm_dbg ("Disconnect bearer '%s'", mm_bearer_get_path (MM_BEARER (self)));<br>
+ if (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTING) {<br>
+ /* MM_BEARER_CONNECTION_STATUS_DISCONNECTING is used to indicate that the<br>
+ * reporting of disconnection should be delayed. See MMBroadbandModemHuawei's<br>
+ * bearer_report_connection_status for details. */<br>
+ if (self->priv->network_disconnect_pending_id == 0) {<br>
+ mm_dbg ("Delay network-initiated disconnection of bearer '%s'",<br>
+ mm_bearer_get_path (MM_BEARER (self)));<br>
+ self->priv->network_disconnect_pending_id = (g_timeout_add_seconds (<br>
+ 4,<br>
+ (GSourceFunc) network_disconnect_3gpp_delayed,<br>
+ self));<br>
+ }<br>
+ return;<br>
+ }<br>
+<br>
+ /* Report disconnected right away */<br>
MM_BEARER_CLASS (mm_broadband_bearer_huawei_parent_class)->report_connection_status (<br>
bearer,<br>
MM_BEARER_CONNECTION_STATUS_DISCONNECTED);<br>
@@ -692,6 +732,19 @@ mm_broadband_bearer_huawei_new_finish (GAsyncResult *res,<br>
return MM_BEARER (bearer);<br>
}<br>
<br>
+static void<br>
+dispose (GObject *object)<br>
+{<br>
+ MMBroadbandBearerHuawei *self = MM_BROADBAND_BEARER_HUAWEI (object);<br>
+<br>
+ if (self->priv->network_disconnect_pending_id != 0) {<br>
+ g_source_remove (self->priv->network_disconnect_pending_id);<br>
+ self->priv->network_disconnect_pending_id = 0;<br>
+ }<br>
+<br>
+ G_OBJECT_CLASS (mm_broadband_bearer_huawei_parent_class)->dispose (object);<br>
+}<br>
+<br>
void<br>
mm_broadband_bearer_huawei_new (MMBroadbandModemHuawei *modem,<br>
MMBearerProperties *config,<br>
@@ -728,6 +781,7 @@ mm_broadband_bearer_huawei_class_init (MMBroadbandBearerHuaweiClass *klass)<br>
<br>
g_type_class_add_private (object_class, sizeof (MMBroadbandBearerHuaweiPrivate));<br>
<br>
+ object_class->dispose = dispose;<br>
bearer_class->report_connection_status = report_connection_status;<br>
broadband_bearer_class->connect_3gpp = connect_3gpp;<br>
broadband_bearer_class->connect_3gpp_finish = connect_3gpp_finish;<br>
</div></div>diff --git a/plugins/huawei/mm-broadband-modem-huawei.c b/plugins/huawei/mm-broadband-modem-huawei.c<br>
index f93f5a1..4f231df 100644<br>
--- a/plugins/huawei/mm-broadband-modem-huawei.c<br>
+++ b/plugins/huawei/mm-broadband-modem-huawei.c<br>
@@ -1525,11 +1525,14 @@ bearer_report_connection_status (MMBearer *bearer,<br>
{<br>
if (ndisstat_result->ipv4_available) {<br>
/* TODO: MMBroadbandBearerHuawei does not currently support IPv6.<br>
- * When it does, we should check the IP family associated with each bearer. */<br>
+ * When it does, we should check the IP family associated with each bearer.<br>
+ *<br>
+ * Also, send DISCONNECTING so that we give some time before actually<br>
+ * disconnecting the connection */<br>
mm_bearer_report_connection_status (bearer,<br>
ndisstat_result->ipv4_connected ?<br>
MM_BEARER_CONNECTION_STATUS_CONNECTED :<br>
- MM_BEARER_CONNECTION_STATUS_DISCONNECTED);<br>
+ MM_BEARER_CONNECTION_STATUS_DISCONNECTING);<br>
<div><div> }<br>
}<br>
<br>
diff --git a/src/mm-bearer.h b/src/mm-bearer.h<br>
index dc217c5..c1bcaee 100644<br>
--- a/src/mm-bearer.h<br>
+++ b/src/mm-bearer.h<br>
@@ -70,6 +70,7 @@ typedef enum { /*< underscore_name=mm_bearer_status >*/<br>
typedef enum { /*< underscore_name=mm_bearer_connection_status >*/<br>
MM_BEARER_CONNECTION_STATUS_UNKNOWN,<br>
MM_BEARER_CONNECTION_STATUS_DISCONNECTED,<br>
+ MM_BEARER_CONNECTION_STATUS_DISCONNECTING,<br>
MM_BEARER_CONNECTION_STATUS_CONNECTED,<br>
MM_BEARER_CONNECTION_STATUS_CONNECTION_FAILED,<br>
} MMBearerConnectionStatus;<br>
--<br>
1.8.3.1<br>
</div></div></blockquote></div><br></div></div>