broadband-modem-qmi: reset all QMI/NET ports on initialization
If the daemon boots and it finds already existing modems in the system (i.e. not hotplugged), we will attempt to reset all QMI/NET ports, so that the state in which the ports are is a known one. This logic allows us to cleanup any possible existing network link if e.g. the daemon crashes and is restarted by the system.
This commit is contained in:
@@ -9661,6 +9661,113 @@ signal_load_values (MMIfaceModemSignal *self,
|
||||
signal_load_values_context_step (task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Reset data interfaces during initialization */
|
||||
|
||||
typedef struct {
|
||||
GList *ports;
|
||||
MMPort *data;
|
||||
MMPortQmi *qmi;
|
||||
} ResetPortsContext;
|
||||
|
||||
static void
|
||||
reset_ports_context_free (ResetPortsContext *ctx)
|
||||
{
|
||||
g_assert (!ctx->data);
|
||||
g_assert (!ctx->qmi);
|
||||
g_list_free_full (ctx->ports, g_object_unref);
|
||||
g_slice_free (ResetPortsContext, ctx);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
reset_ports_finish (MMBroadbandModemQmi *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (res), error);
|
||||
}
|
||||
|
||||
static void reset_next_port (GTask *task);
|
||||
|
||||
static void
|
||||
port_qmi_reset_ready (MMPortQmi *qmi,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
MMBroadbandModemQmi *self;
|
||||
ResetPortsContext *ctx;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
self = g_task_get_source_object (task);
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
if (!mm_port_qmi_reset_finish (qmi, res, &error))
|
||||
mm_obj_warn (self, "couldn't reset QMI port '%s' with data interface '%s': %s",
|
||||
mm_port_get_device (MM_PORT (ctx->qmi)),
|
||||
mm_port_get_device (ctx->data),
|
||||
error->message);
|
||||
|
||||
g_clear_object (&ctx->data);
|
||||
g_clear_object (&ctx->qmi);
|
||||
reset_next_port (task);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_next_port (GTask *task)
|
||||
{
|
||||
MMBroadbandModemQmi *self;
|
||||
ResetPortsContext *ctx;
|
||||
|
||||
self = g_task_get_source_object (task);
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
if (!ctx->ports) {
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
/* steal full data port reference from list head */
|
||||
ctx->data = ctx->ports->data;
|
||||
ctx->ports = g_list_delete_link (ctx->ports, ctx->ports);
|
||||
|
||||
ctx->qmi = mm_broadband_modem_qmi_get_port_qmi_for_data (self, ctx->data, NULL, NULL);
|
||||
if (!ctx->qmi) {
|
||||
mm_obj_dbg (self, "no QMI port associated to data port '%s': ignoring data interface reset",
|
||||
mm_port_get_device (ctx->data));
|
||||
g_clear_object (&ctx->data);
|
||||
reset_next_port (task);
|
||||
return;
|
||||
}
|
||||
|
||||
mm_obj_dbg (self, "running QMI port '%s' reset with data interface '%s'",
|
||||
mm_port_get_device (MM_PORT (ctx->qmi)), mm_port_get_device (ctx->data));
|
||||
|
||||
mm_port_qmi_reset (ctx->qmi,
|
||||
ctx->data,
|
||||
(GAsyncReadyCallback) port_qmi_reset_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_ports (MMBroadbandModemQmi *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
ResetPortsContext *ctx;
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
ctx = g_slice_new0 (ResetPortsContext);
|
||||
g_task_set_task_data (task, ctx, (GDestroyNotify)reset_ports_context_free);
|
||||
|
||||
ctx->ports = mm_base_modem_find_ports (MM_BASE_MODEM (self),
|
||||
MM_PORT_SUBSYS_UNKNOWN,
|
||||
MM_PORT_TYPE_NET);
|
||||
|
||||
reset_next_port (task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* First enabling step */
|
||||
|
||||
@@ -9961,7 +10068,7 @@ allocate_next_client (GTask *task)
|
||||
if (ctx->service_index == G_N_ELEMENTS (qmi_services)) {
|
||||
GError *error = NULL;
|
||||
|
||||
/* Done we are, track device removal and launch parent's callback */
|
||||
/* Done we are, track device removal and launch next step */
|
||||
if (!track_qmi_device_removed (self, ctx->qmi, &error)) {
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
@@ -10028,6 +10135,54 @@ qmi_port_open_ready (MMPortQmi *qmi,
|
||||
allocate_next_client (task);
|
||||
}
|
||||
|
||||
static void
|
||||
initialization_open_port (GTask *task)
|
||||
{
|
||||
InitializationStartedContext *ctx;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
mm_port_qmi_open (ctx->qmi,
|
||||
TRUE,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)qmi_port_open_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_ports_ready (MMBroadbandModemQmi *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!reset_ports_finish (self, res, &error)) {
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
initialization_open_port (task);
|
||||
}
|
||||
|
||||
static void
|
||||
initialization_reset_ports (GTask *task)
|
||||
{
|
||||
MMBroadbandModemQmi *self;
|
||||
|
||||
self = g_task_get_source_object (task);
|
||||
|
||||
/* reseting the data interfaces is really only needed if the device
|
||||
* hasn't been hotplugged */
|
||||
if (mm_base_modem_get_hotplugged (MM_BASE_MODEM (self))) {
|
||||
mm_obj_dbg (self, "not running data interface reset procedure: device is hotplugged");
|
||||
initialization_open_port (task);
|
||||
return;
|
||||
}
|
||||
|
||||
reset_ports (self, (GAsyncReadyCallback)reset_ports_ready, task);
|
||||
}
|
||||
|
||||
static void
|
||||
initialization_started (MMBroadbandModem *self,
|
||||
GAsyncReadyCallback callback,
|
||||
@@ -10066,12 +10221,7 @@ initialization_started (MMBroadbandModem *self,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now open our QMI port */
|
||||
mm_port_qmi_open (ctx->qmi,
|
||||
TRUE,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)qmi_port_open_ready,
|
||||
task);
|
||||
initialization_reset_ports (task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
Reference in New Issue
Block a user