diff mbox series

[v2,14/33] qmi: qmux: Make shared service creation generic

Message ID 20240618200231.1129282-14-denkenz@gmail.com (mailing list archive)
State Superseded
Headers show
Series [v2,01/33] qmi: Remove qmi_free() | expand

Commit Message

Denis Kenzior June 18, 2024, 8:01 p.m. UTC
The underlying QMUX protocol does not have a concept of a shared or
non-shared service.  Services are accessed via clients, with each client
having its own state tracked by the service implementation.  Some state
is shared amongst all clients.  The shared service concept was local to
the qmi_device implementation, enabling multiple atom drivers to request
a handle to a given service, and for that handle to share the client
service handle at the protocol level.

Services meant to be shared are now created and managed at the modem
driver level.  Services that require a dedicated service client handle
(such as in the case of gprs_context atom driver) will obtain such
handles from the modem driver in the future.

Remove qmi_service_create_shared() API and introduce a QMUX specific
qmux_device_create_client() API in its stead.  The new API will
generically handle creation of new service clients at the QMUX protocol
level.

While here, also remove the now unused client_create method from the
qmi_device_ops structure and rename qmux_client_create_reply() to
qmux_client_create_timeout()
---
 drivers/qmimodem/qmi.c | 233 ++++++++---------------------------------
 drivers/qmimodem/qmi.h |  12 ++-
 plugins/gobi.c         |   6 +-
 3 files changed, 51 insertions(+), 200 deletions(-)
diff mbox series

Patch

diff --git a/drivers/qmimodem/qmi.c b/drivers/qmimodem/qmi.c
index 9fdc209edf7c..89645c1d6704 100644
--- a/drivers/qmimodem/qmi.c
+++ b/drivers/qmimodem/qmi.c
@@ -64,10 +64,6 @@  struct qmi_device_ops {
 	int (*discover)(struct qmi_device *device,
 			qmi_discover_func_t discover_func,
 			void *user, qmi_destroy_func_t destroy);
-	int (*client_create)(struct qmi_device *device,
-				uint16_t service_type,
-				qmi_create_func_t func,
-				void *user, qmi_destroy_func_t destroy);
 	void (*client_release)(struct qmi_device *device,
 				uint16_t service_type, uint16_t client_id);
 	int (*shutdown)(struct qmi_device *device,
@@ -106,7 +102,6 @@  struct qmi_device_qmux {
 	unsigned int release_users;
 	uint8_t next_control_tid;
 	struct l_queue *control_queue;
-	struct l_queue *pending_families;
 };
 
 struct service_family {
@@ -1410,17 +1405,6 @@  done:
 	l_free(family);
 }
 
-struct service_create_shared_data {
-	struct discovery super;
-	uint16_t service_type;
-	struct service_family *family;
-	struct qmi_device *device;
-	qmi_create_func_t func;
-	void *user_data;
-	qmi_destroy_func_t destroy;
-	struct l_idle *idle;
-};
-
 static uint8_t __ctl_request_submit(struct qmi_device_qmux *qmux,
 					struct qmi_request *req)
 {
@@ -1484,79 +1468,6 @@  static struct qmi_service *service_create(struct service_family *family)
 	return service;
 }
 
-static void service_create_shared_idle_cb(struct l_idle *idle, void *user_data)
-{
-	struct service_create_shared_data *data = user_data;
-	struct qmi_service *service = service_create(data->family);
-
-	DISCOVERY_DONE(data, service, data->user_data);
-}
-
-static void service_create_shared_reply(struct service_create_shared_data *data,
-					struct service_family *family)
-{
-	struct qmi_service *service = NULL;
-
-	if (family)
-		service = service_create(family);
-
-	DISCOVERY_DONE(data, service, data->user_data);
-}
-
-static bool pending_family_match(const void *data, const void *user_data)
-{
-	const struct service_create_shared_data *shared_data = data;
-	uint16_t service_type = L_PTR_TO_UINT(user_data);
-
-	return shared_data->service_type == service_type;
-}
-
-struct pending_family_reply_if_match_info {
-	uint16_t service_type;
-	struct service_family *family;
-};
-
-static bool pending_family_reply_if_match(void *data, void *user_data)
-{
-	struct service_create_shared_data *shared_data = data;
-	const struct pending_family_reply_if_match_info *info = user_data;
-
-	if (pending_family_match(data, L_UINT_TO_PTR(info->service_type))) {
-		service_create_shared_reply(shared_data, info->family);
-		return true;
-	}
-
-	return false;
-}
-
-static void service_create_shared_pending_reply(struct qmi_device_qmux *qmux,
-						uint16_t service_type,
-						struct service_family *family)
-{	struct pending_family_reply_if_match_info info = {
-		.service_type = service_type,
-		.family = family,
-	};
-
-	l_queue_foreach_remove(qmux->pending_families,
-					pending_family_reply_if_match, &info);
-}
-
-static void service_create_shared_data_free(void *user_data)
-{
-	struct service_create_shared_data *data = user_data;
-
-	if (data->idle)
-		l_idle_remove(data->idle);
-
-	if (data->family)
-		service_family_unref(data->family);
-
-	if (data->destroy)
-		data->destroy(data->user_data);
-
-	l_free(data);
-}
-
 static struct qmi_request *find_control_request(struct qmi_device_qmux *qmux,
 						uint16_t tid)
 {
@@ -1737,7 +1648,9 @@  struct qmux_client_create_data {
 	uint8_t type;
 	uint16_t major;
 	uint16_t minor;
-	qmi_create_func_t func;
+	qmi_qmux_device_create_client_func_t func;
+	void *user_data;
+	qmi_destroy_func_t destroy;
 	struct l_timeout *timeout;
 	uint16_t tid;
 };
@@ -1749,10 +1662,14 @@  static void qmux_client_create_data_free(void *user_data)
 	if (data->timeout)
 		l_timeout_remove(data->timeout);
 
+	if (data->destroy)
+		data->destroy(data->user_data);
+
 	l_free(data);
 }
 
-static void qmux_client_create_reply(struct l_timeout *timeout, void *user_data)
+static void qmux_client_create_timeout(struct l_timeout *timeout,
+							void *user_data)
 {
 	struct qmux_client_create_data *data = user_data;
 	struct qmi_device *device = data->device;
@@ -1760,20 +1677,17 @@  static void qmux_client_create_reply(struct l_timeout *timeout, void *user_data)
 		l_container_of(device, struct qmi_device_qmux, super);
 	struct qmi_request *req;
 
-	DBG("");
-
-	service_create_shared_pending_reply(qmux, data->type, NULL);
-
-	/* remove request from queues */
-	req = find_control_request(qmux, data->tid);
+	__debug_device(device, "client creation timed out");
 
 	l_timeout_remove(data->timeout);
 	data->timeout = NULL;
 
-	DISCOVERY_DONE(data, NULL, NULL);
-
+	/* remove request from queues */
+	req = find_control_request(qmux, data->tid);
 	if (req)
 		__request_free(req);
+
+	DISCOVERY_DONE(data, NULL, data->user_data);
 }
 
 static void qmux_client_create_callback(uint16_t message, uint16_t length,
@@ -1781,9 +1695,8 @@  static void qmux_client_create_callback(uint16_t message, uint16_t length,
 {
 	struct qmux_client_create_data *data = user_data;
 	struct qmi_device *device = data->device;
-	struct qmi_device_qmux *qmux =
-		l_container_of(device, struct qmi_device_qmux, super);
 	struct service_family *family = NULL;
+	struct qmi_service *service = NULL;
 	struct qmi_service_info info;
 	const struct qmi_result_code *result_code;
 	const struct qmi_client_id *client_id;
@@ -1817,72 +1730,63 @@  static void qmux_client_create_callback(uint16_t message, uint16_t length,
 	hash_id = family_list_create_hash(family->info.service_type,
 							family->client_id);
 	l_hashmap_insert(device->family_list, L_UINT_TO_PTR(hash_id), family);
-	l_hashmap_insert(device->family_list,
-				L_UINT_TO_PTR(family->info.service_type),
-				family);
+
 done:
-	service_create_shared_pending_reply(qmux, data->type, family);
 	if (family)
-		service_family_unref(family);
+		service = service_create(family);
+
+	DISCOVERY_DONE(data, service, data->user_data);
 
-	DISCOVERY_DONE(data, NULL, NULL);
+	if (family)
+		service_family_unref(family);
 }
 
-static int qmi_device_qmux_client_create(struct qmi_device *device,
-					uint16_t service_type,
-					qmi_create_func_t func, void *user_data,
-					qmi_destroy_func_t destroy)
+bool qmi_qmux_device_create_client(struct qmi_device *device,
+				uint16_t service_type,
+				qmi_qmux_device_create_client_func_t func,
+				void *user_data, qmi_destroy_func_t destroy)
 {
-	struct qmi_device_qmux *qmux =
-		l_container_of(device, struct qmi_device_qmux, super);
 	unsigned char client_req[] = { 0x01, 0x01, 0x00, service_type };
+	const struct qmi_service_info *info;
+	struct qmi_device_qmux *qmux;
 	struct qmi_request *req;
-	struct service_create_shared_data *shared_data;
 	struct qmux_client_create_data *create_data;
-	bool create_in_progress;
 
-	if (!l_queue_length(device->service_infos))
-		return -ENOENT;
+	if (!device || !func)
+		return false;
 
-	create_in_progress = l_queue_find(qmux->pending_families,
-						pending_family_match,
-						L_UINT_TO_PTR(service_type));
+	if (service_type == QMI_SERVICE_CONTROL)
+		return false;
 
-	shared_data = l_new(struct service_create_shared_data, 1);
-	shared_data->super.destroy = service_create_shared_data_free;
-	shared_data->service_type = service_type;
-	shared_data->device = device;
-	shared_data->func = func;
-	shared_data->user_data = user_data;
-	shared_data->destroy = destroy;
-	l_queue_push_tail(qmux->pending_families, shared_data);
+	info = __find_service_info_by_type(device, service_type);
+	if (!info)
+		return false;
 
-	if (create_in_progress)
-		return 0;
+	qmux = l_container_of(device, struct qmi_device_qmux, super);
 
 	create_data = l_new(struct qmux_client_create_data, 1);
 	create_data->super.destroy = qmux_client_create_data_free;
 	create_data->device = device;
 	create_data->type = service_type;
+	create_data->major = info->major;
+	create_data->minor = info->minor;
+	create_data->func = func;
+	create_data->user_data = user_data;
+	create_data->destroy = destroy;
 
 	__debug_device(device, "service create [type=%d]", service_type);
 
-	qmi_device_get_service_version(device, create_data->type,
-						&create_data->major,
-						&create_data->minor);
-
 	req = __control_request_alloc(QMI_CTL_GET_CLIENT_ID,
 					client_req, sizeof(client_req),
 					qmux_client_create_callback,
 					create_data);
 
 	create_data->tid = __ctl_request_submit(qmux, req);
-	create_data->timeout = l_timeout_create(8, qmux_client_create_reply,
+	create_data->timeout = l_timeout_create(8, qmux_client_create_timeout,
 							create_data, NULL);
 
 	__qmi_device_discovery_started(device, &create_data->super);
-
-	return 0;
+	return true;
 }
 
 static void qmux_client_release_callback(uint16_t message, uint16_t length,
@@ -1971,8 +1875,6 @@  static void qmi_device_qmux_destroy(struct qmi_device *device)
 	struct qmi_device_qmux *qmux =
 		l_container_of(device, struct qmi_device_qmux, super);
 
-	l_queue_destroy(qmux->pending_families,
-		(l_queue_destroy_func_t) service_create_shared_data_free);
 	l_queue_destroy(qmux->control_queue, __request_free);
 
 	if (qmux->shutdown_idle)
@@ -1985,7 +1887,6 @@  static void qmi_device_qmux_destroy(struct qmi_device *device)
 static const struct qmi_device_ops qmux_ops = {
 	.write = qmi_device_qmux_write,
 	.discover = qmi_device_qmux_discover,
-	.client_create = qmi_device_qmux_client_create,
 	.client_release = qmi_device_qmux_client_release,
 	.shutdown = qmi_device_qmux_shutdown,
 	.destroy = qmi_device_qmux_destroy,
@@ -2010,7 +1911,6 @@  struct qmi_device *qmi_qmux_device_new(const char *device)
 
 	qmux->next_control_tid = 1;
 	qmux->control_queue = l_queue_new();
-	qmux->pending_families = l_queue_new();
 	l_io_set_read_handler(qmux->super.io, received_qmux_data, qmux, NULL);
 
 	return &qmux->super;
@@ -2304,7 +2204,6 @@  static void qmi_device_qrtr_destroy(struct qmi_device *device)
 static const struct qmi_device_ops qrtr_ops = {
 	.write = qmi_device_qrtr_write,
 	.discover = qmi_device_qrtr_discover,
-	.client_create = NULL,
 	.client_release = NULL,
 	.shutdown = NULL,
 	.destroy = qmi_device_qrtr_destroy,
@@ -2630,56 +2529,6 @@  bool qmi_result_get_uint64(struct qmi_result *result, uint8_t type,
 	return true;
 }
 
-bool qmi_service_create_shared(struct qmi_device *device, uint16_t type,
-			qmi_create_func_t func, void *user_data,
-			qmi_destroy_func_t destroy)
-{
-	struct service_create_shared_data *data;
-	struct service_family *family;
-
-	if (!device || !func)
-		return false;
-
-	if (type == QMI_SERVICE_CONTROL)
-		return false;
-
-	family = l_hashmap_lookup(device->family_list, L_UINT_TO_PTR(type));
-	if (!family) {
-		const struct qmi_service_info *info;
-
-		if (device->ops->client_create) {
-			int r;
-
-			r = device->ops->client_create(device, type, func,
-							user_data, destroy);
-			return r == 0;
-		}
-
-		info = __find_service_info_by_type(device, type);
-		if (!info)
-			return false;
-
-		family = service_family_create(device, info, 0);
-		l_hashmap_insert(device->family_list, L_UINT_TO_PTR(type),
-							family);
-	}
-
-	data = l_new(struct service_create_shared_data, 1);
-
-	data->super.destroy = service_create_shared_data_free;
-	data->device = device;
-	data->func = func;
-	data->user_data = user_data;
-	data->destroy = destroy;
-	data->family = service_family_ref(family);
-	data->idle = l_idle_create(service_create_shared_idle_cb, data, NULL);
-
-	/* Not really discovery... just tracking the idle callback. */
-	__qmi_device_discovery_started(device, &data->super);
-
-	return true;
-}
-
 const char *qmi_service_get_identifier(struct qmi_service *service)
 {
 	if (!service)
diff --git a/drivers/qmimodem/qmi.h b/drivers/qmimodem/qmi.h
index 966d4f354d6e..90e83a4dbebd 100644
--- a/drivers/qmimodem/qmi.h
+++ b/drivers/qmimodem/qmi.h
@@ -65,12 +65,19 @@  struct qmi_service;
 typedef void (*qmi_debug_func_t)(const char *str, void *user_data);
 typedef void (*qmi_shutdown_func_t)(void *user_data);
 typedef void (*qmi_discover_func_t)(void *user_data);
+typedef void (*qmi_qmux_device_create_client_func_t)(struct qmi_service *,
+							void *user_data);
 
 typedef void (*qmi_service_result_func_t)(struct qmi_result *, void *);
 
 struct qmi_device *qmi_qmux_device_new(const char *device);
 void qmi_device_free(struct qmi_device *device);
 
+bool qmi_qmux_device_create_client(struct qmi_device *device,
+				uint16_t service_type,
+				qmi_qmux_device_create_client_func_t func,
+				void *user_data, qmi_destroy_func_t destroy);
+
 void qmi_device_set_debug(struct qmi_device *device,
 				qmi_debug_func_t func, void *user_data);
 
@@ -130,11 +137,6 @@  void qmi_result_print_tlvs(struct qmi_result *result);
 
 int qmi_error_to_ofono_cme(int qmi_error);
 
-typedef void (*qmi_create_func_t)(struct qmi_service *service, void *user_data);
-
-bool qmi_service_create_shared(struct qmi_device *device,
-				uint16_t type, qmi_create_func_t func,
-				void *user_data, qmi_destroy_func_t destroy);
 struct qmi_service *qmi_service_clone(struct qmi_service *service);
 void qmi_service_free(struct qmi_service *service);
 
diff --git a/plugins/gobi.c b/plugins/gobi.c
index 5463a46edecb..23d16e251196 100644
--- a/plugins/gobi.c
+++ b/plugins/gobi.c
@@ -419,7 +419,7 @@  static void request_service_cb(struct qmi_service *service, void *user_data)
 	if (data->cur_service_request == data->num_service_requests) {
 		DBG("All services requested, proceeding to create WDA");
 
-		if (qmi_service_create_shared(data->device, QMI_SERVICE_WDA,
+		if (qmi_qmux_device_create_client(data->device, QMI_SERVICE_WDA,
 						create_wda_cb, modem, NULL))
 			return;
 
@@ -429,7 +429,7 @@  static void request_service_cb(struct qmi_service *service, void *user_data)
 	req = &data->service_requests[data->cur_service_request];
 	DBG("Requesting: %u", req->service_type);
 
-	if (qmi_service_create_shared(data->device, req->service_type,
+	if (qmi_qmux_device_create_client(data->device, req->service_type,
 					request_service_cb, modem, NULL))
 		return;
 
@@ -482,7 +482,7 @@  static void discover_cb(void *user_data)
 	if (data->features & GOBI_UIM)
 		add_service_request(data, &data->uim, QMI_SERVICE_UIM);
 
-	if (qmi_service_create_shared(data->device, QMI_SERVICE_DMS,
+	if (qmi_qmux_device_create_client(data->device, QMI_SERVICE_DMS,
 					request_service_cb, modem, NULL) > 0)
 		return;
 error: