From a80fc06d1885e1512101914ac0282d8d15bc4843 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Fri, 10 Feb 2017 23:10:27 +0100 Subject: qmi-firmware-update: explicitly async-close QmiDevice before exiting After an update operation, before exiting, we MUST close the QmiDevice using the asynchronous method, so that we wait for the inner 'MBIM close' message (when QMI over MBIM is being used). We don't want to leave the 'MBIM close done' message unread, as that seems to interfere with the next 'MBIM open' sequence. This sequence is incorrect: qmi-firmware-update ... --> mbim close (exit without reading response) qmi-firmware-update --> mbim open (seq 1) <-- mbim close done --> mbim open (seq 2) --> mbim open (seq 3) --> mbim open (seq 4) ... (times out) This sequence is correct: qmi-firmware-update ... --> mbim close <-- mbim close done (exit) qmi-firmware-update --> mbim open (seq 1) <-- mbim open done ... --- src/qmi-firmware-update/qfu-updater.c | 66 +++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/qmi-firmware-update/qfu-updater.c b/src/qmi-firmware-update/qfu-updater.c index 8323f40..ead15c9 100644 --- a/src/qmi-firmware-update/qfu-updater.c +++ b/src/qmi-firmware-update/qfu-updater.c @@ -96,6 +96,7 @@ typedef enum { RUN_CONTEXT_STEP_WAIT_FOR_CDC_WDM, RUN_CONTEXT_STEP_WAIT_FOR_BOOT, RUN_CONTEXT_STEP_QMI_CLIENT_AFTER, + RUN_CONTEXT_STEP_CLEANUP_QMI_DEVICE_FULL, RUN_CONTEXT_STEP_LAST } RunContextStep; @@ -354,6 +355,67 @@ run_context_step_next_no_idle (GTask *task, RunContextStep next) } static void +close_ready (QmiDevice *dev, + GAsyncResult *res, + GTask *task) +{ + RunContext *ctx; + GError *error = NULL; + + ctx = (RunContext *) g_task_get_task_data (task); + + if (!qmi_device_close_finish (dev, res, &error)) { + g_warning ("[qfu-updater] couldn't close device: %s", error->message); + g_error_free (error); + } else + g_debug ("[qfu-updater] closed"); + + /* Go on */ + run_context_step_next (task, ctx->step + 1); +} + +static void +release_client_ready (QmiDevice *dev, + GAsyncResult *res, + GTask *task) +{ + RunContext *ctx; + GError *error = NULL; + + ctx = (RunContext *) g_task_get_task_data (task); + + if (!qmi_device_release_client_finish (dev, res, &error)) { + g_warning ("[qfu-updater] couldn't release client: %s", error->message); + g_error_free (error); + } else + g_debug ("[qfu-updater] client released"); + + qmi_device_close_async (ctx->qmi_device, + 10, + g_task_get_cancellable (task), + (GAsyncReadyCallback) close_ready, + task); + g_clear_object (&ctx->qmi_device); +} + +static void +run_context_step_cleanup_qmi_device_full (GTask *task) +{ + RunContext *ctx; + + ctx = (RunContext *) g_task_get_task_data (task); + + qmi_device_release_client (ctx->qmi_device, + QMI_CLIENT (ctx->qmi_client), + QMI_DEVICE_RELEASE_CLIENT_FLAGS_RELEASE_CID, + 10, + g_task_get_cancellable (task), + (GAsyncReadyCallback) release_client_ready, + task); + g_clear_object (&ctx->qmi_client); +} + +static void new_client_dms_after_ready (gpointer unused, GAsyncResult *res, GTask *task) @@ -778,7 +840,6 @@ run_context_step_cleanup_qmi_device (GTask *task) g_object_unref (tmp); } - static void reseter_run_ready (QfuReseter *reseter, GAsyncResult *res, @@ -1264,8 +1325,9 @@ static const RunContextStepFunc run_context_step_func[] = { [RUN_CONTEXT_STEP_CLEANUP_IMAGE] = run_context_step_cleanup_image, [RUN_CONTEXT_STEP_CLEANUP_QDL_DEVICE] = run_context_step_cleanup_qdl_device, [RUN_CONTEXT_STEP_WAIT_FOR_CDC_WDM] = run_context_step_wait_for_cdc_wdm, - [RUN_CONTEXT_STEP_QMI_CLIENT_AFTER] = run_context_step_qmi_client_after, [RUN_CONTEXT_STEP_WAIT_FOR_BOOT] = run_context_step_wait_for_boot, + [RUN_CONTEXT_STEP_QMI_CLIENT_AFTER] = run_context_step_qmi_client_after, + [RUN_CONTEXT_STEP_CLEANUP_QMI_DEVICE_FULL] = run_context_step_cleanup_qmi_device_full, }; G_STATIC_ASSERT (G_N_ELEMENTS (run_context_step_func) == RUN_CONTEXT_STEP_LAST); -- cgit v1.1