[PATCH] huawei: delay processing of network initiated bearer disconnection

Aleksander Morgado aleksander at lanedo.com
Wed Sep 18 23:56:27 PDT 2013


On 19/09/13 03:53, Prathmesh Prabhu wrote:
> Network initiated bearer disconnection is notified by MU736 through the NDISTAT
> unsolicited event. Due to a firmware bug, this event is created prematurely.
> This CL delays processing of this event. If the event is handled before the
> modem actually disconnects the bearer, a reconnect attempt can leave the modem
> in a broken state.


Just wondering; wouldn't it make sense to have the bearer in
MM_BEARER_STATUS_DISCONNECTING state once we receive a network-initiated
disconnection notification? That would leave the bearer in disconnecting
state for the 4s delay until we notify fully disconnected. Could you
check if that makes sense?


> ---
>  plugins/huawei/mm-broadband-bearer-huawei.c | 53 +++++++++++++++++++++++++++--
>  1 file changed, 51 insertions(+), 2 deletions(-)
> 
> diff --git a/plugins/huawei/mm-broadband-bearer-huawei.c b/plugins/huawei/mm-broadband-bearer-huawei.c
> index 233102f..9207a58 100644
> --- a/plugins/huawei/mm-broadband-bearer-huawei.c
> +++ b/plugins/huawei/mm-broadband-bearer-huawei.c
> @@ -36,6 +36,8 @@ G_DEFINE_TYPE (MMBroadbandBearerHuawei, mm_broadband_bearer_huawei, MM_TYPE_BROA
>  struct _MMBroadbandBearerHuaweiPrivate {
>      gpointer connect_pending;
>      gpointer disconnect_pending;
> +    /* Tag for the post task for network initiated disconnect */
> +    guint network_disconnect_pending_id;
>  };
>  
>  /*****************************************************************************/
> @@ -231,6 +233,11 @@ connect_3gpp_context_step (Connect3gppContext *ctx)
>          return;
>      }
>  
> +    /* Network initiated disconnect should not be outstanding at this point,
> +     * because it interferes with the connect attempt.
> +     */
> +    g_assert (ctx->self->priv->network_disconnect_pending_id == 0);
> +
>      switch (ctx->step) {
>      case CONNECT_3GPP_CONTEXT_STEP_FIRST: {
>          MMBearerIpFamily ip_family;
> @@ -597,6 +604,11 @@ disconnect_3gpp_context_step (Disconnect3gppContext *ctx)
>          return;
>  
>      case DISCONNECT_3GPP_CONTEXT_STEP_LAST:
> +        if (ctx->self->priv->network_disconnect_pending_id != 0) {
> +            g_source_remove (ctx->self->priv->network_disconnect_pending_id);
> +            ctx->self->priv->network_disconnect_pending_id = 0;
> +        }
> +
>          /* Clear context */
>          ctx->self->priv->disconnect_pending = NULL;
>          /* Set data port as result */
> @@ -638,6 +650,16 @@ disconnect_3gpp (MMBroadbandBearer *self,
>  }
>  
>  /*****************************************************************************/
> +/* Disconnect 3GPP on network initiated request */
> +
> +static gboolean
> +network_disconnect_3gpp_delayed (MMBroadbandBearerHuawei *self)
> +{
> +    mm_dbg ("Disconnect bearer '%s' on network request.", mm_bearer_get_path (MM_BEARER (self)));
> +    mm_bearer_report_disconnection (MM_BEARER (self));
> +    self->priv->network_disconnect_pending_id = 0;
> +    return FALSE;
> +}
>  
>  void
>  mm_broadband_bearer_huawei_report_connection_status (MMBroadbandBearerHuawei *self,
> @@ -652,8 +674,21 @@ mm_broadband_bearer_huawei_report_connection_status (MMBroadbandBearerHuawei *se
>      /* We already use ^NDISSTATQRY? to poll the connection status, so only
>       * handle network-initiated disconnection here. */
>      if (!connected) {
> -        mm_dbg ("Disconnect bearer '%s'", mm_bearer_get_path (MM_BEARER (self)));
> -        mm_bearer_report_disconnection (MM_BEARER (self));
> +        /* Ignore multiple disconnect signals, while we're still processing one */
> +        if (self->priv->network_disconnect_pending_id != 0)
> +          return;
> +
> +        mm_dbg ("Post delayed task to disconnect bearer '%s'", mm_bearer_get_path (MM_BEARER (self)));
> +        /* A firmware bug in MU736 causes the network initiated network
> +         * disconnect signal to fire prematurely. We must give modem a little
> +         * time to actually disconnect the bearer. Otherwise, it is possible to
> +         * confuse the modem if a reconnect is attempted too soon.
> +         *
> +         * Since this is a small timeout, we currently do this for all Huawei modems.
> +         */
> +        self->priv->network_disconnect_pending_id = g_timeout_add_seconds (4,
> +                                                                           (GSourceFunc) network_disconnect_3gpp_delayed,
> +                                                                           self);
>      }
>  }
>  
> @@ -679,6 +714,19 @@ mm_broadband_bearer_huawei_new_finish (GAsyncResult *res,
>      return MM_BEARER (bearer);
>  }
>  
> +static void
> +dispose (GObject *object)
> +{
> +    MMBroadbandBearerHuawei *self = MM_BROADBAND_BEARER_HUAWEI (object);
> +
> +    if (self->priv->network_disconnect_pending_id != 0) {
> +        g_source_remove (self->priv->network_disconnect_pending_id);
> +        self->priv->network_disconnect_pending_id = 0;
> +    }
> +
> +    G_OBJECT_CLASS (mm_broadband_bearer_huawei_parent_class)->dispose (object);
> +}
> +
>  void
>  mm_broadband_bearer_huawei_new (MMBroadbandModemHuawei *modem,
>                                  MMBearerProperties *config,
> @@ -715,6 +763,7 @@ mm_broadband_bearer_huawei_class_init (MMBroadbandBearerHuaweiClass *klass)
>  
>      g_type_class_add_private (object_class, sizeof (MMBroadbandBearerHuaweiPrivate));
>  
> +    object_class->dispose = dispose;
>      broadband_bearer_class->connect_3gpp = connect_3gpp;
>      broadband_bearer_class->connect_3gpp_finish = connect_3gpp_finish;
>      broadband_bearer_class->disconnect_3gpp = disconnect_3gpp;
> 


-- 
Aleksander


More information about the ModemManager-devel mailing list