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

Commit 4d3cc7e5 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: service-notifier: Use per-indication structs for PDR"

parents 0b5dcc39 1db0ea5f
Loading
Loading
Loading
Loading
+44 −44
Original line number Diff line number Diff line
@@ -73,9 +73,10 @@ static LIST_HEAD(service_list);
static DEFINE_MUTEX(service_list_lock);

struct ind_req_resp {
	char service_path[SERVREG_NOTIF_NAME_LENGTH];
	int transaction_id;
	int curr_state;
	struct work_struct ind_ack;
	struct qmi_client_info *client_data;
};

/*
@@ -91,23 +92,21 @@ struct qmi_client_info {
	int instance_id;
	char service_path[SERVREG_NOTIF_NAME_LENGTH];
	enum pd_subsys_state subsys_state;
	struct work_struct ind_ack;
	struct work_struct new_server;
	struct work_struct del_server;
	struct workqueue_struct *svc_event_wq;
	struct workqueue_struct *ind_ack_wq;
	struct qmi_handle clnt_handle;
	struct notifier_block notifier;
	void *ssr_handle;
	struct notifier_block ssr_notifier;
	bool service_connected;
	struct list_head list;
	struct ind_req_resp ind_msg;
	struct sockaddr_qrtr s_addr;
};
static LIST_HEAD(qmi_client_list);
static DEFINE_MUTEX(qmi_list_lock);
static DEFINE_MUTEX(notif_add_lock);
static struct workqueue_struct *pdr_wq;

static struct service_notif_info *_find_service_info(const char *service_path)
{
@@ -140,8 +139,9 @@ static int service_notif_queue_notification(struct service_notif_info

static void send_ind_ack(struct work_struct *work)
{
	struct qmi_client_info *data = container_of(work,
					struct qmi_client_info, ind_ack);
	struct ind_req_resp *ind_info = container_of(work, struct ind_req_resp,
						     ind_ack);
	struct qmi_client_info *data = ind_info->client_data;
	struct qmi_servreg_notif_set_ack_req_msg_v01 req;
	struct qmi_servreg_notif_set_ack_resp_msg_v01 resp = { { 0, 0 } };
	struct qmi_txn txn;
@@ -149,29 +149,29 @@ static void send_ind_ack(struct work_struct *work)
	enum pd_subsys_state state = USER_PD_STATE_CHANGE;
	int rc;

	service_notif = _find_service_info(data->ind_msg.service_path);
	service_notif = _find_service_info(data->service_path);
	if (!service_notif)
		return;
	if ((int)data->ind_msg.curr_state < QMI_STATE_MIN_VAL ||
		(int)data->ind_msg.curr_state > QMI_STATE_MAX_VAL)
		goto out;
	if ((int)ind_info->curr_state < QMI_STATE_MIN_VAL ||
		(int)ind_info->curr_state > QMI_STATE_MAX_VAL)
		pr_err("Unexpected indication notification state %d\n",
			data->ind_msg.curr_state);
			ind_info->curr_state);
	else {
		mutex_lock(&notif_add_lock);
		mutex_lock(&service_list_lock);
		rc = service_notif_queue_notification(service_notif,
			data->ind_msg.curr_state, &state);
			ind_info->curr_state, &state);
		if (rc & NOTIFY_STOP_MASK)
			pr_err("Notifier callback aborted for %s with error %d\n",
				data->ind_msg.service_path, rc);
		service_notif->curr_state = data->ind_msg.curr_state;
				data->service_path, rc);
		service_notif->curr_state = ind_info->curr_state;
		mutex_unlock(&service_list_lock);
		mutex_unlock(&notif_add_lock);
	}

	req.transaction_id = data->ind_msg.transaction_id;
	req.transaction_id = ind_info->transaction_id;
	snprintf(req.service_name, ARRAY_SIZE(req.service_name), "%s",
						data->ind_msg.service_path);
						data->service_path);

	rc = qmi_txn_init(&data->clnt_handle, &txn,
			qmi_servreg_notif_set_ack_resp_msg_v01_ei,
@@ -179,8 +179,8 @@ static void send_ind_ack(struct work_struct *work)

	if (rc < 0) {
		pr_err("%s QMI tx init failed , ret - %d\n",
			data->ind_msg.service_path, rc);
		return;
			data->service_path, rc);
		goto out;
	}

	rc = qmi_send_request(&data->clnt_handle, &data->s_addr,
@@ -190,24 +190,26 @@ static void send_ind_ack(struct work_struct *work)
			&req);
	if (rc < 0) {
		pr_err("%s: QMI send ACK failed, ret - %d\n",
				data->ind_msg.service_path, rc);
				data->service_path, rc);
		qmi_txn_cancel(&txn);
		return;
		goto out;
	}

	rc = qmi_txn_wait(&txn, msecs_to_jiffies(SERVER_TIMEOUT));
	if (rc < 0) {
		pr_err("%s: QMI qmi txn wait failed, ret - %d\n",
				data->ind_msg.service_path, rc);
		return;
		       data->service_path, rc);
		goto out;
	}

	/* Check the response */
	if (resp.resp.result != QMI_RESULT_SUCCESS_V01)
		pr_err("QMI request failed 0x%x\n", resp.resp.error);
	pr_info("Indication ACKed for transid %d, service %s, instance %d!\n",
		data->ind_msg.transaction_id, data->ind_msg.service_path,
		ind_info->transaction_id, data->service_path,
		data->instance_id);
out:
	kfree(ind_info);
}

static void root_service_service_ind_cb(struct qmi_handle *qmi,
@@ -218,17 +220,20 @@ static void root_service_service_ind_cb(struct qmi_handle *qmi,
				struct qmi_client_info, clnt_handle);
	struct qmi_servreg_notif_state_updated_ind_msg_v01 ind_msg =
		*((struct qmi_servreg_notif_state_updated_ind_msg_v01 *)data);
	struct ind_req_resp *ind_info = kmalloc(sizeof(*ind_info), GFP_KERNEL);

	if (!ind_info)
		return;

	pr_info("Indication received from %s, state: 0x%x, trans-id: %d\n",
		ind_msg.service_name, ind_msg.curr_state,
		ind_msg.transaction_id);

	qmi_data->ind_msg.transaction_id = ind_msg.transaction_id;
	qmi_data->ind_msg.curr_state = ind_msg.curr_state;
	snprintf(qmi_data->ind_msg.service_path,
		ARRAY_SIZE(qmi_data->ind_msg.service_path), "%s",
		ind_msg.service_name);
	queue_work(pdr_wq, &qmi_data->ind_ack);
	ind_info->transaction_id = ind_msg.transaction_id;
	ind_info->curr_state = ind_msg.curr_state;
	ind_info->client_data = qmi_data;
	INIT_WORK(&ind_info->ind_ack, send_ind_ack);
	queue_work(qmi_data->ind_ack_wq, &ind_info->ind_ack);
}

static int send_notif_listener_msg_req(struct service_notif_info *service_notif,
@@ -251,7 +256,7 @@ static int send_notif_listener_msg_req(struct service_notif_info *service_notif,

	if (rc < 0) {
		pr_err("%s QMI tx init failed , ret - %d\n",
			data->ind_msg.service_path, rc);
			service_notif->service_path, rc);
		return rc;
	}

@@ -506,8 +511,13 @@ static void *add_service_notif(const char *service_path, int instance_id,
		rc = -ENOMEM;
		goto exit;
	}
	qmi_data->ind_ack_wq = alloc_ordered_workqueue("%s_pdr_wq", WQ_HIGHPRI,
						       subsys);
	if (!qmi_data->ind_ack_wq) {
		rc = -ENOMEM;
		goto exit;
	}

	INIT_WORK(&qmi_data->ind_ack, send_ind_ack);
	INIT_WORK(&qmi_data->new_server, new_server_work);
	INIT_WORK(&qmi_data->del_server, del_server_work);

@@ -554,6 +564,8 @@ static void *add_service_notif(const char *service_path, int instance_id,

	return service_notif;
exit:
	if (qmi_data->ind_ack_wq)
		destroy_workqueue(qmi_data->ind_ack_wq);
	if (qmi_data->svc_event_wq)
		destroy_workqueue(qmi_data->svc_event_wq);
	kfree(qmi_data);
@@ -578,8 +590,7 @@ static int send_pd_restart_req(const char *service_path,
			&resp);

	if (rc < 0) {
		pr_err("%s QMI tx init failed , ret - %d\n",
			data->ind_msg.service_path, rc);
		pr_err("%s QMI tx init failed , ret - %d\n", service_path, rc);
		return rc;
	}

@@ -708,14 +719,3 @@ int service_notif_unregister_notifier(void *service_notif_handle,
				&service_notif->service_notif_rcvr_list, nb);
}
EXPORT_SYMBOL(service_notif_unregister_notifier);

static int __init service_notif_init(void)
{

	pdr_wq = alloc_workqueue("pdr_wq", WQ_CPU_INTENSIVE | WQ_UNBOUND |
				 WQ_HIGHPRI, 0);
	BUG_ON(!pdr_wq);

	return 0;
}
arch_initcall(service_notif_init);
+2 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 */
/*
 * Process Domain Service Notifier API header
@@ -15,6 +15,7 @@ enum qmi_servreg_notif_service_state_enum_type_v01 {
	QMI_SERVREG_NOTIF_SERVICE_STATE_ENUM_TYPE_MAX_VAL_V01 = INT_MAX,
	SERVREG_NOTIF_SERVICE_STATE_DOWN_V01 = 0x0FFFFFFF,
	SERVREG_NOTIF_SERVICE_STATE_UP_V01 = 0x1FFFFFFF,
	SERVREG_NOTIF_SERVICE_STATE_EARLY_DOWN_V01 = 0x2FFFFFFF,
	SERVREG_NOTIF_SERVICE_STATE_UNINIT_V01 = 0x7FFFFFFF,
};