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

Reply via email to