diff mbox series

qmi: Support dynamic service information

Message ID 20240227175739.1471333-1-denkenz@gmail.com (mailing list archive)
State Accepted
Headers show
Series qmi: Support dynamic service information | expand

Commit Message

Denis Kenzior Feb. 27, 2024, 5:57 p.m. UTC
On QMUX, service information is static.  It is obtained via a CTL
request and remains static for the duration of the connection.  With
QRTR, services can appear and disappear dynamically.  Support this by
converting the existing version_list / version_count member into a
queue.  struct qmi_version is now replaced by struct qmi_service_info
with additional qrtr specific attributes.
---
 drivers/qmimodem/qmi.c | 118 +++++++++++++++++++++++------------------
 1 file changed, 66 insertions(+), 52 deletions(-)

Comments

Denis Kenzior Feb. 28, 2024, 3:26 p.m. UTC | #1
On 2/27/24 11:57, Denis Kenzior wrote:
> On QMUX, service information is static.  It is obtained via a CTL
> request and remains static for the duration of the connection.  With
> QRTR, services can appear and disappear dynamically.  Support this by
> converting the existing version_list / version_count member into a
> queue.  struct qmi_version is now replaced by struct qmi_service_info
> with additional qrtr specific attributes.
> ---
>   drivers/qmimodem/qmi.c | 118 +++++++++++++++++++++++------------------
>   1 file changed, 66 insertions(+), 52 deletions(-)
> 

<snip>

Applied with the following change

> @@ -853,7 +881,7 @@ void qmi_device_free(struct qmi_device *device)
>   
>   	l_hashmap_destroy(device->service_list, service_destroy);
>   
> -	l_free(device->version_list);
> +	l_queue_destroy(device->service_infos, (l_queue_destroy_func_t) l_free);

This cast isn't necessary.

>   
>   	if (device->shutting_down)
>   		device->destroyed = true;

Regards,
-Denis
diff mbox series

Patch

diff --git a/drivers/qmimodem/qmi.c b/drivers/qmimodem/qmi.c
index 35751d7ce267..e58e46b5a6df 100644
--- a/drivers/qmimodem/qmi.c
+++ b/drivers/qmimodem/qmi.c
@@ -48,6 +48,15 @@  struct discovery {
 	qmi_destroy_func_t destroy;
 };
 
+struct qmi_service_info {
+	uint32_t service_type;
+	uint32_t qrtr_port;		/* Always 0 on qmux */
+	uint32_t qrtr_node;		/* Always 0 on qmux */
+	uint16_t major;
+	uint16_t minor;			/* Always 0 on qrtr */
+	uint32_t instance;		/* Always 0 on qmux */
+};
+
 struct qmi_request {
 	uint16_t tid;
 	uint8_t client;
@@ -57,13 +66,6 @@  struct qmi_request {
 	uint8_t data[];
 };
 
-struct qmi_version {
-	uint8_t type;
-	uint16_t major;
-	uint16_t minor;
-	const char *name;
-};
-
 struct qmi_device_ops {
 	int (*write)(struct qmi_device *device, struct qmi_request *req);
 	int (*discover)(struct qmi_device *device,
@@ -89,8 +91,7 @@  struct qmi_device {
 	uint16_t next_service_tid;
 	qmi_debug_func_t debug_func;
 	void *debug_data;
-	struct qmi_version *version_list;
-	uint8_t version_count;
+	struct l_queue *service_infos;
 	struct l_hashmap *service_list;
 	const struct qmi_device_ops *ops;
 	bool writer_active : 1;
@@ -184,6 +185,33 @@  void qmi_free(void *ptr)
 	l_free(ptr);
 }
 
+static bool qmi_service_info_matches(const void *data, const void *user)
+{
+	const struct qmi_service_info *info = data;
+	const struct qmi_service_info *match = user;
+
+	if (info->service_type != match->service_type)
+		return false;
+
+	if (info->qrtr_node != match->qrtr_node)
+		return false;
+
+	if (info->qrtr_port != match->qrtr_port)
+		return false;
+
+	return true;
+}
+
+static void __qmi_service_appeared(struct qmi_device *device,
+					const struct qmi_service_info *info)
+{
+	if (l_queue_find(device->service_infos, qmi_service_info_matches, info))
+		return;
+
+	l_queue_push_tail(device->service_infos,
+				l_memdup(info, sizeof(struct qmi_service_info)));
+}
+
 static struct qmi_request *__request_alloc(uint8_t service,
 				uint8_t client, uint16_t message,
 				const void *data,
@@ -822,7 +850,7 @@  static int qmi_device_init(struct qmi_device *device, int fd,
 	device->req_queue = l_queue_new();
 	device->service_queue = l_queue_new();
 	device->discovery_queue = l_queue_new();
-
+	device->service_infos = l_queue_new();
 	device->service_list = l_hashmap_new();
 
 	device->next_service_tid = 256;
@@ -853,7 +881,7 @@  void qmi_device_free(struct qmi_device *device)
 
 	l_hashmap_destroy(device->service_list, service_destroy);
 
-	l_free(device->version_list);
+	l_queue_destroy(device->service_infos, (l_queue_destroy_func_t) l_free);
 
 	if (device->shutting_down)
 		device->destroyed = true;
@@ -914,17 +942,18 @@  static const void *tlv_get(const void *data, uint16_t size,
 bool qmi_device_get_service_version(struct qmi_device *device, uint16_t type,
 					uint16_t *major, uint16_t *minor)
 {
-	struct qmi_version *info;
-	int i;
+	const struct l_queue_entry *entry;
 
-	for (i = 0, info = device->version_list;
-			i < device->version_count;
-			i++, info++) {
-		if (info->type == type) {
-			*major = info->major;
-			*minor = info->minor;
-			return true;
-		}
+	for (entry = l_queue_get_entries(device->service_infos);
+						entry; entry = entry->next) {
+		const struct qmi_service_info *info = entry->data;
+
+		if (info->service_type != type)
+			continue;
+
+		*major = info->major;
+		*minor = info->minor;
+		return true;
 	}
 
 	return false;
@@ -932,13 +961,13 @@  bool qmi_device_get_service_version(struct qmi_device *device, uint16_t type,
 
 bool qmi_device_has_service(struct qmi_device *device, uint16_t type)
 {
-	struct qmi_version *info;
-	int i;
+	const struct l_queue_entry *entry;
+
+	for (entry = l_queue_get_entries(device->service_infos);
+						entry; entry = entry->next) {
+		const struct qmi_service_info *info = entry->data;
 
-	for (i = 0, info = device->version_list;
-			i < device->version_count;
-			i++, info++) {
-		if (info->type == type)
+		if (info->service_type == type)
 			return true;
 	}
 
@@ -1440,13 +1469,8 @@  static void qmux_discover_callback(uint16_t message, uint16_t length,
 	const struct qmi_service_list *service_list;
 	const void *ptr;
 	uint16_t len;
-	struct qmi_version *list;
-	uint8_t count;
 	unsigned int i;
 
-	count = 0;
-	list = NULL;
-
 	result_code = tlv_get(buffer, length, 0x02, &len);
 	if (!result_code)
 		goto done;
@@ -1461,8 +1485,6 @@  static void qmux_discover_callback(uint16_t message, uint16_t length,
 	if (len < QMI_SERVICE_LIST_SIZE)
 		goto done;
 
-	list = l_malloc(sizeof(struct qmi_version) * service_list->count);
-
 	for (i = 0; i < service_list->count; i++) {
 		uint16_t major =
 			L_LE16_TO_CPU(service_list->services[i].major);
@@ -1470,6 +1492,7 @@  static void qmux_discover_callback(uint16_t message, uint16_t length,
 			L_LE16_TO_CPU(service_list->services[i].minor);
 		uint8_t type = service_list->services[i].type;
 		const char *name = __service_type_to_string(type);
+		struct qmi_service_info info;
 
 		if (name)
 			__debug_device(device, "found service [%s %d.%d]",
@@ -1484,12 +1507,12 @@  static void qmux_discover_callback(uint16_t message, uint16_t length,
 			continue;
 		}
 
-		list[count].type = type;
-		list[count].major = major;
-		list[count].minor = minor;
-		list[count].name = name;
+		memset(&info, 0, sizeof(info));
+		info.service_type = type;
+		info.major = major;
+		info.minor = minor;
 
-		count++;
+		__qmi_service_appeared(device, &info);
 	}
 
 	ptr = tlv_get(buffer, length, 0x10, &len);
@@ -1500,9 +1523,6 @@  static void qmux_discover_callback(uint16_t message, uint16_t length,
 	__debug_device(device, "version string: %s", qmux->version_str);
 
 done:
-	device->version_list = list;
-	device->version_count = count;
-
 	/* if the device support the QMI call SYNC over the CTL interface */
 	if ((qmux->control_major == 1 && qmux->control_minor >= 5) ||
 			qmux->control_major > 1) {
@@ -1552,7 +1572,7 @@  static int qmi_device_qmux_discover(struct qmi_device *device,
 
 	__debug_device(device, "device %p discover", device);
 
-	if (device->version_list)
+	if (l_queue_length(device->service_infos) > 0)
 		return -EALREADY;
 
 	data = l_new(struct discover_data, 1);
@@ -1702,9 +1722,8 @@  static int qmi_device_qmux_client_create(struct qmi_device *device,
 	struct qmux_client_create_data *data;
 	struct l_queue *shared;
 	unsigned int type_val = service_type;
-	int i;
 
-	if (!device->version_list)
+	if (!l_queue_length(device->service_infos))
 		return -ENOENT;
 
 	shared = l_queue_new();
@@ -1719,13 +1738,8 @@  static int qmi_device_qmux_client_create(struct qmi_device *device,
 
 	__debug_device(device, "service create [type=%d]", service_type);
 
-	for (i = 0; i < device->version_count; i++) {
-		if (device->version_list[i].type == data->type) {
-			data->major = device->version_list[i].major;
-			data->minor = device->version_list[i].minor;
-			break;
-		}
-	}
+	qmi_device_get_service_version(device, data->type,
+						&data->major, &data->minor);
 
 	req = __request_alloc(QMI_SERVICE_CONTROL, 0x00,
 			QMI_CTL_GET_CLIENT_ID,