Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 736e2de0 authored by Runmin Wang's avatar Runmin Wang
Browse files

soc: qcom: pil: Update the service-locator to the new QMI interface



Update the service-locator to use the upstream QMI interface.

Change-Id: I398dad133a77701309677674ae1b920d7f472bdf
Signed-off-by: default avatarRunmin Wang <runminw@codeaurora.org>
parent f81ad3ba
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ config QPNP_PBS

config MSM_SERVICE_LOCATOR
	bool "Service Locator"
	depends on MSM_QMI_INTERFACE
	depends on QCOM_QMI_HELPERS
	help
	  The Service Locator provides a library to retrieve location
	  information given a service identifier. Location here translates
+20 −22
Original line number Diff line number Diff line
/*
 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015,2017-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -14,9 +14,7 @@
#ifndef SERVICE_LOCATOR_V01_H
#define SERVICE_LOCATOR_V01_H

#include <linux/qmi_encdec.h>

#include <soc/qcom/msm_qmi_interface.h>
#include <linux/soc/qcom/qmi.h>
#include <soc/qcom/service-locator.h>

#define SERVREG_LOC_SERVICE_ID_V01 0x40
@@ -44,13 +42,13 @@ struct qmi_servreg_loc_indication_register_req_msg_v01 {
	uint8_t enable_database_updated_indication;
};
#define QMI_SERVREG_LOC_INDICATION_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 4
struct elem_info qmi_servreg_loc_indication_register_req_msg_v01_ei[];
struct qmi_elem_info qmi_servreg_loc_indication_register_req_msg_v01_ei[];

struct qmi_servreg_loc_indication_register_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
};
#define QMI_SERVREG_LOC_INDICATION_REGISTER_RESP_MSG_V01_MAX_MSG_LEN 7
struct elem_info qmi_servreg_loc_indication_register_resp_msg_v01_ei[];
struct qmi_elem_info qmi_servreg_loc_indication_register_resp_msg_v01_ei[];

struct qmi_servreg_loc_get_domain_list_req_msg_v01 {
	char service_name[QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1];
@@ -58,7 +56,7 @@ struct qmi_servreg_loc_get_domain_list_req_msg_v01 {
	uint32_t domain_offset;
};
#define QMI_SERVREG_LOC_GET_DOMAIN_LIST_REQ_MSG_V01_MAX_MSG_LEN 74
struct elem_info qmi_servreg_loc_get_domain_list_req_msg_v01_ei[];
struct qmi_elem_info qmi_servreg_loc_get_domain_list_req_msg_v01_ei[];

struct qmi_servreg_loc_get_domain_list_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
@@ -72,7 +70,7 @@ struct qmi_servreg_loc_get_domain_list_resp_msg_v01 {
				domain_list[QMI_SERVREG_LOC_LIST_LENGTH_V01];
};
#define QMI_SERVREG_LOC_GET_DOMAIN_LIST_RESP_MSG_V01_MAX_MSG_LEN 2389
struct elem_info qmi_servreg_loc_get_domain_list_resp_msg_v01_ei[];
struct qmi_elem_info qmi_servreg_loc_get_domain_list_resp_msg_v01_ei[];

struct qmi_servreg_loc_register_service_list_req_msg_v01 {
	char domain_name[QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1];
@@ -81,19 +79,19 @@ struct qmi_servreg_loc_register_service_list_req_msg_v01 {
				service_list[QMI_SERVREG_LOC_LIST_LENGTH_V01];
};
#define QMI_SERVREG_LOC_REGISTER_SERVICE_LIST_REQ_MSG_V01_MAX_MSG_LEN 2439
struct elem_info qmi_servreg_loc_register_service_list_req_msg_v01_ei[];
struct qmi_elem_info qmi_servreg_loc_register_service_list_req_msg_v01_ei[];

struct qmi_servreg_loc_register_service_list_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
};
#define QMI_SERVREG_LOC_REGISTER_SERVICE_LIST_RESP_MSG_V01_MAX_MSG_LEN 7
struct elem_info qmi_servreg_loc_register_service_list_resp_msg_v01_ei[];
struct qmi_elem_info qmi_servreg_loc_register_service_list_resp_msg_v01_ei[];

struct qmi_servreg_loc_database_updated_ind_msg_v01 {
	char placeholder;
};
#define QMI_SERVREG_LOC_DATABASE_UPDATED_IND_MSG_V01_MAX_MSG_LEN 0
struct elem_info qmi_servreg_loc_database_updated_ind_msg_v01_ei[];
struct qmi_elem_info qmi_servreg_loc_database_updated_ind_msg_v01_ei[];

#define QMI_EOTI_DATA_TYPE	\
{				\
@@ -106,7 +104,7 @@ struct elem_info qmi_servreg_loc_database_updated_ind_msg_v01_ei[];
	.ei_array  = NULL,	\
},

static struct elem_info servreg_loc_entry_v01_ei[] = {
static struct qmi_elem_info servreg_loc_entry_v01_ei[] = {
	{
		.data_type      = QMI_STRING,
		.elem_len       = QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1,
@@ -146,7 +144,7 @@ static struct elem_info servreg_loc_entry_v01_ei[] = {
	QMI_EOTI_DATA_TYPE
};

struct elem_info qmi_servreg_loc_indication_register_req_msg_v01_ei[] = {
struct qmi_elem_info qmi_servreg_loc_indication_register_req_msg_v01_ei[] = {
	{
		.data_type      = QMI_OPT_FLAG,
		.elem_len       = 1,
@@ -170,7 +168,7 @@ struct elem_info qmi_servreg_loc_indication_register_req_msg_v01_ei[] = {
	QMI_EOTI_DATA_TYPE
};

struct elem_info qmi_servreg_loc_indication_register_resp_msg_v01_ei[] = {
struct qmi_elem_info qmi_servreg_loc_indication_register_resp_msg_v01_ei[] = {
	{
		.data_type      = QMI_STRUCT,
		.elem_len       = 1,
@@ -180,12 +178,12 @@ struct elem_info qmi_servreg_loc_indication_register_resp_msg_v01_ei[] = {
		.offset         = offsetof(struct
			qmi_servreg_loc_indication_register_resp_msg_v01,
			resp),
		.ei_array      = get_qmi_response_type_v01_ei(),
		.ei_array      = qmi_response_type_v01_ei,
	},
	QMI_EOTI_DATA_TYPE
};

struct elem_info qmi_servreg_loc_get_domain_list_req_msg_v01_ei[] = {
struct qmi_elem_info qmi_servreg_loc_get_domain_list_req_msg_v01_ei[] = {
	{
		.data_type      = QMI_STRING,
		.elem_len       = QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1,
@@ -219,7 +217,7 @@ struct elem_info qmi_servreg_loc_get_domain_list_req_msg_v01_ei[] = {
	QMI_EOTI_DATA_TYPE
};

struct elem_info qmi_servreg_loc_get_domain_list_resp_msg_v01_ei[] = {
struct qmi_elem_info qmi_servreg_loc_get_domain_list_resp_msg_v01_ei[] = {
	{
		.data_type      = QMI_STRUCT,
		.elem_len       = 1,
@@ -229,7 +227,7 @@ struct elem_info qmi_servreg_loc_get_domain_list_resp_msg_v01_ei[] = {
		.offset         = offsetof(struct
				qmi_servreg_loc_get_domain_list_resp_msg_v01,
				resp),
		.ei_array      = get_qmi_response_type_v01_ei(),
		.ei_array      = qmi_response_type_v01_ei,
	},
	{
		.data_type      = QMI_OPT_FLAG,
@@ -305,7 +303,7 @@ struct elem_info qmi_servreg_loc_get_domain_list_resp_msg_v01_ei[] = {
	QMI_EOTI_DATA_TYPE
};

struct elem_info qmi_servreg_loc_register_service_list_req_msg_v01_ei[] = {
struct qmi_elem_info qmi_servreg_loc_register_service_list_req_msg_v01_ei[] = {
	{
		.data_type      = QMI_STRING,
		.elem_len       = QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1,
@@ -340,7 +338,7 @@ struct elem_info qmi_servreg_loc_register_service_list_req_msg_v01_ei[] = {
	QMI_EOTI_DATA_TYPE
};

struct elem_info qmi_servreg_loc_register_service_list_resp_msg_v01_ei[] = {
struct qmi_elem_info qmi_servreg_loc_register_service_list_resp_msg_v01_ei[] = {
	{
		.data_type      = QMI_STRUCT,
		.elem_len       = 1,
@@ -350,12 +348,12 @@ struct elem_info qmi_servreg_loc_register_service_list_resp_msg_v01_ei[] = {
		.offset         = offsetof(struct
			qmi_servreg_loc_register_service_list_resp_msg_v01,
			resp),
		.ei_array      = get_qmi_response_type_v01_ei(),
		.ei_array      = qmi_response_type_v01_ei,
	},
	QMI_EOTI_DATA_TYPE
};

struct elem_info qmi_servreg_loc_database_updated_ind_msg_v01_ei[] = {
struct qmi_elem_info qmi_servreg_loc_database_updated_ind_msg_v01_ei[] = {
	QMI_EOTI_DATA_TYPE
};

+56 −121
Original line number Diff line number Diff line
/*
 * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -25,7 +25,7 @@
#include <linux/delay.h>
#include <linux/workqueue.h>

#include <soc/qcom/msm_qmi_interface.h>
#include <linux/soc/qcom/qmi.h>
#include <soc/qcom/service-locator.h>
#include "service-locator-private.h"

@@ -43,21 +43,14 @@ static bool service_inited;

module_param_named(enable, locator_status, uint, 0644);

static void service_locator_svc_arrive(struct work_struct *work);
static void service_locator_svc_exit(struct work_struct *work);
static void service_locator_recv_msg(struct work_struct *work);
static void pd_locator_work(struct work_struct *work);

struct workqueue_struct *servloc_wq;

struct pd_qmi_data {
	struct work_struct svc_arrive;
	struct work_struct svc_exit;
	struct work_struct svc_rcv_msg;
	struct notifier_block notifier;
	struct completion service_available;
	struct mutex service_mutex;
	struct qmi_handle *clnt_handle;
	struct qmi_handle clnt_handle;
	bool connected;
	struct sockaddr_qrtr s_addr;
};

struct pd_qmi_work {
@@ -70,92 +63,34 @@ struct pd_qmi_data service_locator;

/* Please refer soc/qcom/service-locator.h for use about APIs defined here */

static int service_locator_svc_event_notify(struct notifier_block *this,
				      unsigned long code,
				      void *_cmd)
{
	switch (code) {
	case QMI_SERVER_ARRIVE:
		queue_work(servloc_wq, &service_locator.svc_arrive);
		break;
	case QMI_SERVER_EXIT:
		queue_work(servloc_wq, &service_locator.svc_exit);
		break;
	default:
		break;
	}
	return 0;
}

static void service_locator_clnt_notify(struct qmi_handle *handle,
			     enum qmi_event_type event, void *notify_priv)
{
	switch (event) {
	case QMI_RECV_MSG:
		schedule_work(&service_locator.svc_rcv_msg);
		break;
	default:
		break;
	}
}

static void service_locator_svc_arrive(struct work_struct *work)
static int service_locator_new_server(struct qmi_handle *qmi,
		struct qmi_service *svc)
{
	int rc = 0;

	/* Create a Local client port for QMI communication */
	mutex_lock(&service_locator.service_mutex);
	service_locator.clnt_handle =
			qmi_handle_create(service_locator_clnt_notify, NULL);
	if (!service_locator.clnt_handle) {
		service_locator.clnt_handle = NULL;
		complete_all(&service_locator.service_available);
		mutex_unlock(&service_locator.service_mutex);
		pr_err("Service locator QMI client handle alloc failed!\n");
		return;
	}

	/* Connect to service */
	rc = qmi_connect_to_service(service_locator.clnt_handle,
		SERVREG_LOC_SERVICE_ID_V01, SERVREG_LOC_SERVICE_VERS_V01,
		SERVREG_LOC_SERVICE_INSTANCE_ID);
	if (rc) {
		qmi_handle_destroy(service_locator.clnt_handle);
		service_locator.clnt_handle = NULL;
		complete_all(&service_locator.service_available);
		mutex_unlock(&service_locator.service_mutex);
		pr_err("Unable to connnect to service rc:%d\n", rc);
		return;
	}
	service_locator.s_addr.sq_family = AF_QIPCRTR;
	service_locator.s_addr.sq_node = svc->node;
	service_locator.s_addr.sq_port = svc->port;
	service_locator.connected = true;
	if (!service_inited)
		complete_all(&service_locator.service_available);
	mutex_unlock(&service_locator.service_mutex);
	pr_info("Connection established with the Service locator\n");
	return 0;
}

static void service_locator_svc_exit(struct work_struct *work)
static void service_locator_del_server(struct qmi_handle *qmi,
		struct qmi_service *svc)
{
	mutex_lock(&service_locator.service_mutex);
	qmi_handle_destroy(service_locator.clnt_handle);
	service_locator.clnt_handle = NULL;
	service_locator.connected = false;
	complete_all(&service_locator.service_available);
	mutex_unlock(&service_locator.service_mutex);
	pr_info("Connection with service locator lost\n");
}

static void service_locator_recv_msg(struct work_struct *work)
{
	int ret;

	do {
		pr_debug("Notified about a Receive event\n");
		ret = qmi_recv_msg(service_locator.clnt_handle);
		if (ret < 0)
			pr_err("Error receiving message rc:%d. Retrying...\n",
								ret);
	} while (ret == 0);

}
static struct qmi_ops server_ops = {
	.new_server = service_locator_new_server,
	.del_server = service_locator_del_server,
};

static void store_get_domain_list_response(struct pd_qmi_client_data *pd,
		struct qmi_servreg_loc_get_domain_list_resp_msg_v01 *resp,
@@ -175,25 +110,44 @@ static void store_get_domain_list_response(struct pd_qmi_client_data *pd,
	}
}

static int servreg_loc_send_msg(struct msg_desc *req_desc,
		struct msg_desc *resp_desc,
static int servreg_loc_send_msg(
		struct qmi_servreg_loc_get_domain_list_req_msg_v01 *req,
		struct qmi_servreg_loc_get_domain_list_resp_msg_v01 *resp,
		struct pd_qmi_client_data *pd)
{
	int rc;

	struct qmi_txn txn;
	/*
	 * Send msg and get response. There is a chance that the service went
	 * away since the time we last checked for it to be available and
	 * actually made this call. In that case the call just fails.
	 */
	rc = qmi_send_req_wait(service_locator.clnt_handle, req_desc, req,
		sizeof(*req), resp_desc, resp, sizeof(*resp),
		msecs_to_jiffies(QMI_SERVREG_LOC_SERVER_TIMEOUT));
	rc = qmi_txn_init(&service_locator.clnt_handle, &txn,
			qmi_servreg_loc_get_domain_list_resp_msg_v01_ei, &resp);
	if (rc < 0) {
		pr_err("QMI tx init failed for client %s, ret - %d\n",
			pd->client_name, rc);
		return rc;
	}

	rc = qmi_send_request(&service_locator.clnt_handle,
			&service_locator.s_addr,
			&txn, QMI_SERVREG_LOC_GET_DOMAIN_LIST_REQ_V01,
			QMI_SERVREG_LOC_GET_DOMAIN_LIST_REQ_MSG_V01_MAX_MSG_LEN,
			qmi_servreg_loc_get_domain_list_req_msg_v01_ei,
			&req);
	if (rc < 0) {
		pr_err("QMI send req failed for client %s, ret - %d\n",
			pd->client_name, rc);
		qmi_txn_cancel(&txn);
		return rc;
	}

	rc = qmi_txn_wait(&txn,
			msecs_to_jiffies(QMI_SERVREG_LOC_SERVER_TIMEOUT));
	if (rc < 0) {
		pr_err("QMI qmi txn wait failed for client %s, ret - %d\n",
			pd->client_name, rc);
		return rc;
	}

@@ -208,13 +162,12 @@ static int servreg_loc_send_msg(struct msg_desc *req_desc,

static int service_locator_send_msg(struct pd_qmi_client_data *pd)
{
	struct msg_desc req_desc, resp_desc;
	struct qmi_servreg_loc_get_domain_list_resp_msg_v01 *resp = NULL;
	struct qmi_servreg_loc_get_domain_list_req_msg_v01 *req = NULL;
	int rc;
	int db_rev_count = 0, domains_read = 0;

	if (!service_locator.clnt_handle) {
	if (!service_locator.connected) {
		pr_err("Service locator not available!\n");
		return -EAGAIN;
	}
@@ -235,16 +188,6 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd)
		rc = -ENOMEM;
		goto out;
	}
	/* Prepare req and response message formats */
	req_desc.msg_id = QMI_SERVREG_LOC_GET_DOMAIN_LIST_REQ_V01;
	req_desc.max_msg_len =
		QMI_SERVREG_LOC_GET_DOMAIN_LIST_REQ_MSG_V01_MAX_MSG_LEN;
	req_desc.ei_array = qmi_servreg_loc_get_domain_list_req_msg_v01_ei;

	resp_desc.msg_id = QMI_SERVREG_LOC_GET_DOMAIN_LIST_RESP_V01;
	resp_desc.max_msg_len =
		QMI_SERVREG_LOC_GET_DOMAIN_LIST_RESP_MSG_V01_MAX_MSG_LEN;
	resp_desc.ei_array = qmi_servreg_loc_get_domain_list_resp_msg_v01_ei;

	/* Prepare req and response message */
	strlcpy(req->service_name, pd->service_name,
@@ -255,8 +198,7 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd)
	pd->domain_list = NULL;
	do {
		req->domain_offset += domains_read;
		rc = servreg_loc_send_msg(&req_desc, &resp_desc, req, resp,
					pd);
		rc = servreg_loc_send_msg(req, resp, pd);
		if (rc < 0) {
			pr_err("send msg failed rc:%d\n", rc);
			goto out;
@@ -313,30 +255,23 @@ static int init_service_locator(void)
	if (service_inited)
		goto inited;

	service_locator.notifier.notifier_call =
					service_locator_svc_event_notify;
	init_completion(&service_locator.service_available);
	mutex_init(&service_locator.service_mutex);

	servloc_wq = create_singlethread_workqueue("servloc_wq");
	if (!servloc_wq) {
		rc = -ENOMEM;
		pr_err("Could not create workqueue\n");
		goto inited;
	}

	INIT_WORK(&service_locator.svc_arrive, service_locator_svc_arrive);
	INIT_WORK(&service_locator.svc_exit, service_locator_svc_exit);
	INIT_WORK(&service_locator.svc_rcv_msg, service_locator_recv_msg);
	service_locator.connected = false;

	rc = qmi_svc_event_notifier_register(SERVREG_LOC_SERVICE_ID_V01,
		SERVREG_LOC_SERVICE_VERS_V01, SERVREG_LOC_SERVICE_INSTANCE_ID,
		&service_locator.notifier);
	rc = qmi_handle_init(&service_locator.clnt_handle,
			QMI_SERVREG_LOC_GET_DOMAIN_LIST_REQ_MSG_V01_MAX_MSG_LEN,
			&server_ops, NULL);
	if (rc < 0) {
		pr_err("Notifier register failed rc:%d\n", rc);
		pr_err("Service locator QMI handle init failed rc:%d\n", rc);
		goto inited;
	}

	qmi_add_lookup(&service_locator.clnt_handle,
			SERVREG_LOC_SERVICE_ID_V01,
			SERVREG_LOC_SERVICE_VERS_V01,
			SERVREG_LOC_SERVICE_INSTANCE_ID);

	wait_for_completion(&service_locator.service_available);
	service_inited = true;
	mutex_unlock(&service_init_mutex);