Seems to be this:
i) When the modem is first powered on, service discovery takes some
time (more than 5 seconds)
ii) The service discovery timeout fires before the QMI request
returns so discover_reply gets called before discover_callback and
things get cleaned up
iii) Then the QMI request returns and discover_callback gets called
even though the request has timed out in ii)
...and this is where things go wrong because the userdata pointer to
discover_callback is probably no longer valid.
How do we handle the QMI request returning a _late_ response, i.e.
after it technically has timed out? I'll dig a bit more...
/Jonas
Hi Jonas,
When I look at my personal patches, it seems I've already seen that.
Please find attached the patch I currently have in my setup on this subject.
Christophe
>From 15666c90d20ee7481d0180a8246c53e5a29d5bcd Mon Sep 17 00:00:00 2001
From: Christophe Ronco <c.ro...@kerlink.fr>
Date: Wed, 27 Sep 2017 10:38:50 +0200
Subject: [PATCH] qmi: remove request when it timeouts
When modem does not answer or answers slowly to a discovery request,
a timeout occurs.
In timeout callback, request should be removed from queues to avoid
treating answer if it arrives later.
---
drivers/qmimodem/qmi.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/drivers/qmimodem/qmi.c b/drivers/qmimodem/qmi.c
index c538cb9..65263d2 100644
--- a/drivers/qmimodem/qmi.c
+++ b/drivers/qmimodem/qmi.c
@@ -1073,6 +1073,7 @@ struct discover_data {
qmi_discover_func_t func;
void *user_data;
qmi_destroy_func_t destroy;
+ uint8_t tid;
guint timeout;
};
@@ -1181,14 +1182,38 @@ static gboolean discover_reply(gpointer user_data)
{
struct discover_data *data = user_data;
struct qmi_device *device = data->device;
+ unsigned int tid = (unsigned int)(data->tid);
+ GList *list;
+ struct qmi_request *req = NULL;
data->timeout = 0;
+ /* remove request from queues */
+ if (tid != 0) {
+ list = g_queue_find_custom(device->req_queue,
+ GUINT_TO_POINTER(tid), __request_compare);
+
+ if (list) {
+ req = list->data;
+ g_queue_delete_link(device->req_queue, list);
+ } else {
+ list = g_queue_find_custom(device->control_queue,
+ GUINT_TO_POINTER(tid), __request_compare);
+
+ if (list) {
+ req = list->data;
+ g_queue_delete_link(device->control_queue,
+ list);
+ }
+ }
+ }
+
if (data->func)
data->func(device->version_count,
device->version_list, data->user_data);
__qmi_device_discovery_complete(data->device, &data->super);
+ __request_free(req, NULL);
return FALSE;
}
@@ -1234,6 +1259,7 @@ bool qmi_device_discover(struct qmi_device *device, qmi_discover_func_t func,
hdr->type = 0x00;
hdr->transaction = device->next_control_tid++;
+ data->tid = hdr->transaction;
__request_submit(device, req, hdr->transaction);
--
2.7.4
_______________________________________________
ofono mailing list
ofono@ofono.org
https://lists.ofono.org/mailman/listinfo/ofono