Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (C) 2020 The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include "pdr_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) struct pdr_service {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 	char service_name[SERVREG_NAME_LENGTH + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 	char service_path[SERVREG_NAME_LENGTH + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 	struct sockaddr_qrtr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	unsigned int instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	unsigned int service;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	u8 service_data_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	u32 service_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	bool need_notifier_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	bool need_notifier_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	bool need_locator_lookup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	bool service_connected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) struct pdr_handle {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	struct qmi_handle locator_hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	struct qmi_handle notifier_hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	struct sockaddr_qrtr locator_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	struct list_head lookups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	struct list_head indack_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	/* control access to pdr lookup/indack lists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct mutex list_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	/* serialize pd status invocation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	struct mutex status_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	/* control access to the locator state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	bool locator_init_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	struct work_struct locator_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	struct work_struct notifier_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	struct work_struct indack_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	struct workqueue_struct *notifier_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	struct workqueue_struct *indack_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	void (*status)(int state, char *service_path, void *priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	void *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) struct pdr_list_node {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	enum servreg_service_state curr_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	u16 transaction_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	struct pdr_service *pds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) static int pdr_locator_new_server(struct qmi_handle *qmi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 				  struct qmi_service *svc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	struct pdr_handle *pdr = container_of(qmi, struct pdr_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 					      locator_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	struct pdr_service *pds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	/* Create a local client port for QMI communication */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	pdr->locator_addr.sq_family = AF_QIPCRTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	pdr->locator_addr.sq_node = svc->node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	pdr->locator_addr.sq_port = svc->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	mutex_lock(&pdr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	pdr->locator_init_complete = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	mutex_unlock(&pdr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	/* Service pending lookup requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	mutex_lock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	list_for_each_entry(pds, &pdr->lookups, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		if (pds->need_locator_lookup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 			schedule_work(&pdr->locator_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	mutex_unlock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) static void pdr_locator_del_server(struct qmi_handle *qmi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 				   struct qmi_service *svc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	struct pdr_handle *pdr = container_of(qmi, struct pdr_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 					      locator_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	mutex_lock(&pdr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	pdr->locator_init_complete = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	mutex_unlock(&pdr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	pdr->locator_addr.sq_node = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	pdr->locator_addr.sq_port = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static struct qmi_ops pdr_locator_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	.new_server = pdr_locator_new_server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	.del_server = pdr_locator_del_server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int pdr_register_listener(struct pdr_handle *pdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 				 struct pdr_service *pds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 				 bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	struct servreg_register_listener_resp resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	struct servreg_register_listener_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	struct qmi_txn txn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	ret = qmi_txn_init(&pdr->notifier_hdl, &txn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 			   servreg_register_listener_resp_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			   &resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	req.enable = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	strcpy(req.service_path, pds->service_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	ret = qmi_send_request(&pdr->notifier_hdl, &pds->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			       &txn, SERVREG_REGISTER_LISTENER_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 			       SERVREG_REGISTER_LISTENER_REQ_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			       servreg_register_listener_req_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 			       &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		qmi_txn_cancel(&txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	ret = qmi_txn_wait(&txn, 5 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		pr_err("PDR: %s register listener txn wait failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		       pds->service_path, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		pr_err("PDR: %s register listener failed: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		       pds->service_path, resp.resp.error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	pds->state = resp.curr_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void pdr_notifier_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	struct pdr_handle *pdr = container_of(work, struct pdr_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 					      notifier_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	struct pdr_service *pds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	mutex_lock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	list_for_each_entry(pds, &pdr->lookups, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		if (pds->service_connected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			if (!pds->need_notifier_register)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 			pds->need_notifier_register = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 			ret = pdr_register_listener(pdr, pds, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 			if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 				pds->state = SERVREG_SERVICE_STATE_DOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 			if (!pds->need_notifier_remove)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			pds->need_notifier_remove = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			pds->state = SERVREG_SERVICE_STATE_DOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		mutex_lock(&pdr->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		pdr->status(pds->state, pds->service_path, pdr->priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		mutex_unlock(&pdr->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	mutex_unlock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static int pdr_notifier_new_server(struct qmi_handle *qmi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 				   struct qmi_service *svc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	struct pdr_handle *pdr = container_of(qmi, struct pdr_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 					      notifier_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	struct pdr_service *pds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	mutex_lock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	list_for_each_entry(pds, &pdr->lookups, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		if (pds->service == svc->service &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		    pds->instance == svc->instance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 			pds->service_connected = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			pds->need_notifier_register = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 			pds->addr.sq_family = AF_QIPCRTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 			pds->addr.sq_node = svc->node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 			pds->addr.sq_port = svc->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 			queue_work(pdr->notifier_wq, &pdr->notifier_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	mutex_unlock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static void pdr_notifier_del_server(struct qmi_handle *qmi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 				    struct qmi_service *svc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	struct pdr_handle *pdr = container_of(qmi, struct pdr_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 					      notifier_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	struct pdr_service *pds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	mutex_lock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	list_for_each_entry(pds, &pdr->lookups, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		if (pds->service == svc->service &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		    pds->instance == svc->instance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 			pds->service_connected = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 			pds->need_notifier_remove = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 			pds->addr.sq_node = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			pds->addr.sq_port = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 			queue_work(pdr->notifier_wq, &pdr->notifier_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	mutex_unlock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static struct qmi_ops pdr_notifier_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	.new_server = pdr_notifier_new_server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	.del_server = pdr_notifier_del_server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static int pdr_send_indack_msg(struct pdr_handle *pdr, struct pdr_service *pds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 			       u16 tid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	struct servreg_set_ack_resp resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	struct servreg_set_ack_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	struct qmi_txn txn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	ret = qmi_txn_init(&pdr->notifier_hdl, &txn, servreg_set_ack_resp_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 			   &resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	req.transaction_id = tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	strcpy(req.service_path, pds->service_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	ret = qmi_send_request(&pdr->notifier_hdl, &pds->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			       &txn, SERVREG_SET_ACK_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 			       SERVREG_SET_ACK_REQ_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			       servreg_set_ack_req_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 			       &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	/* Skip waiting for response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	qmi_txn_cancel(&txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static void pdr_indack_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	struct pdr_handle *pdr = container_of(work, struct pdr_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 					      indack_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	struct pdr_list_node *ind, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	struct pdr_service *pds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	list_for_each_entry_safe(ind, tmp, &pdr->indack_list, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		pds = ind->pds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		mutex_lock(&pdr->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		pds->state = ind->curr_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		pdr->status(pds->state, pds->service_path, pdr->priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		mutex_unlock(&pdr->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		/* Ack the indication after clients release the PD resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		pdr_send_indack_msg(pdr, pds, ind->transaction_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		mutex_lock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		list_del(&ind->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		mutex_unlock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		kfree(ind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static void pdr_indication_cb(struct qmi_handle *qmi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 			      struct sockaddr_qrtr *sq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 			      struct qmi_txn *txn, const void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	struct pdr_handle *pdr = container_of(qmi, struct pdr_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 					      notifier_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	const struct servreg_state_updated_ind *ind_msg = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	struct pdr_list_node *ind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	struct pdr_service *pds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	if (!ind_msg || !ind_msg->service_path[0] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	    strlen(ind_msg->service_path) > SERVREG_NAME_LENGTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	mutex_lock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	list_for_each_entry(pds, &pdr->lookups, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		if (strcmp(pds->service_path, ind_msg->service_path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	mutex_unlock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	pr_info("PDR: Indication received from %s, state: 0x%x, trans-id: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		ind_msg->service_path, ind_msg->curr_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		ind_msg->transaction_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	ind = kzalloc(sizeof(*ind), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	if (!ind)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	ind->transaction_id = ind_msg->transaction_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	ind->curr_state = ind_msg->curr_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	ind->pds = pds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	mutex_lock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	list_add_tail(&ind->node, &pdr->indack_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	mutex_unlock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	queue_work(pdr->indack_wq, &pdr->indack_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static struct qmi_msg_handler qmi_indication_handler[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		.type = QMI_INDICATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		.msg_id = SERVREG_STATE_UPDATED_IND_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		.ei = servreg_state_updated_ind_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		.decoded_size = sizeof(struct servreg_state_updated_ind),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		.fn = pdr_indication_cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 			       struct servreg_get_domain_list_resp *resp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 			       struct pdr_handle *pdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	struct qmi_txn txn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	ret = qmi_txn_init(&pdr->locator_hdl, &txn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 			   servreg_get_domain_list_resp_ei, resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	ret = qmi_send_request(&pdr->locator_hdl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			       &pdr->locator_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 			       &txn, SERVREG_GET_DOMAIN_LIST_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 			       SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 			       servreg_get_domain_list_req_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 			       req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		qmi_txn_cancel(&txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	ret = qmi_txn_wait(&txn, 5 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		pr_err("PDR: %s get domain list txn wait failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		       req->service_name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		pr_err("PDR: %s get domain list failed: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		       req->service_name, resp->resp.error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	struct servreg_get_domain_list_resp *resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	struct servreg_get_domain_list_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	struct servreg_location_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	int domains_read = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	if (!resp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	/* Prepare req message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	strcpy(req.service_name, pds->service_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	req.domain_offset_valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	req.domain_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		req.domain_offset = domains_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		ret = pdr_get_domain_list(&req, resp, pdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		for (i = domains_read; i < resp->domain_list_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 			entry = &resp->domain_list[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 			if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 			if (!strcmp(entry->name, pds->service_path)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 				pds->service_data_valid = entry->service_data_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 				pds->service_data = entry->service_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 				pds->instance = entry->instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		/* Update ret to indicate that the service is not yet found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		ret = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		/* Always read total_domains from the response msg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 		if (resp->domain_list_len > resp->total_domains)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 			resp->domain_list_len = resp->total_domains;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 		domains_read += resp->domain_list_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	} while (domains_read < resp->total_domains);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	kfree(resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static void pdr_notify_lookup_failure(struct pdr_handle *pdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 				      struct pdr_service *pds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 				      int err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	pr_err("PDR: service lookup for %s failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	       pds->service_name, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	if (err == -ENXIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	list_del(&pds->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	pds->state = SERVREG_LOCATOR_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	mutex_lock(&pdr->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	pdr->status(pds->state, pds->service_path, pdr->priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	mutex_unlock(&pdr->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	kfree(pds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static void pdr_locator_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	struct pdr_handle *pdr = container_of(work, struct pdr_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 					      locator_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	struct pdr_service *pds, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	/* Bail out early if the SERVREG LOCATOR QMI service is not up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	mutex_lock(&pdr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	if (!pdr->locator_init_complete) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		mutex_unlock(&pdr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		pr_debug("PDR: SERVICE LOCATOR service not available\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	mutex_unlock(&pdr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	mutex_lock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	list_for_each_entry_safe(pds, tmp, &pdr->lookups, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		if (!pds->need_locator_lookup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 		ret = pdr_locate_service(pdr, pds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 			pdr_notify_lookup_failure(pdr, pds, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		ret = qmi_add_lookup(&pdr->notifier_hdl, pds->service, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 				     pds->instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 			pdr_notify_lookup_failure(pdr, pds, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		pds->need_locator_lookup = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	mutex_unlock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)  * pdr_add_lookup() - register a tracking request for a PD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)  * @pdr:		PDR client handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)  * @service_name:	service name of the tracking request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)  * @service_path:	service path of the tracking request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)  * Registering a pdr lookup allows for tracking the life cycle of the PD.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)  * Return: pdr_service object on success, ERR_PTR on failure. -EALREADY is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)  * returned if a lookup is already in progress for the given service path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 				   const char *service_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 				   const char *service_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	struct pdr_service *pds, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	if (IS_ERR_OR_NULL(pdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	if (!service_name || strlen(service_name) > SERVREG_NAME_LENGTH ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	    !service_path || strlen(service_path) > SERVREG_NAME_LENGTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	pds = kzalloc(sizeof(*pds), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	if (!pds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	pds->service = SERVREG_NOTIFIER_SERVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	strcpy(pds->service_name, service_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	strcpy(pds->service_path, service_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	pds->need_locator_lookup = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	mutex_lock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	list_for_each_entry(tmp, &pdr->lookups, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 		if (strcmp(tmp->service_path, service_path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		mutex_unlock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		ret = -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	list_add(&pds->node, &pdr->lookups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	mutex_unlock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	schedule_work(&pdr->locator_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	return pds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	kfree(pds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) EXPORT_SYMBOL(pdr_add_lookup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)  * pdr_restart_pd() - restart PD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)  * @pdr:	PDR client handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)  * @pds:	PD service handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)  * Restarts the PD tracked by the PDR client handle for a given service path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)  * Return: 0 on success, negative errno on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) int pdr_restart_pd(struct pdr_handle *pdr, struct pdr_service *pds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	struct servreg_restart_pd_resp resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	struct servreg_restart_pd_req req = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	struct sockaddr_qrtr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	struct pdr_service *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	struct qmi_txn txn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	if (IS_ERR_OR_NULL(pdr) || IS_ERR_OR_NULL(pds))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	mutex_lock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	list_for_each_entry(tmp, &pdr->lookups, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		if (tmp != pds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 		if (!pds->service_connected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		/* Prepare req message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 		strcpy(req.service_path, pds->service_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 		addr = pds->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	mutex_unlock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	if (!req.service_path[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	ret = qmi_txn_init(&pdr->notifier_hdl, &txn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 			   servreg_restart_pd_resp_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 			   &resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	ret = qmi_send_request(&pdr->notifier_hdl, &addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 			       &txn, SERVREG_RESTART_PD_REQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 			       SERVREG_RESTART_PD_REQ_MAX_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 			       servreg_restart_pd_req_ei, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 		qmi_txn_cancel(&txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	ret = qmi_txn_wait(&txn, 5 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		pr_err("PDR: %s PD restart txn wait failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 		       req.service_path, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	/* Check response if PDR is disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	if (resp.resp.result == QMI_RESULT_FAILURE_V01 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	    resp.resp.error == QMI_ERR_DISABLED_V01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 		pr_err("PDR: %s PD restart is disabled: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 		       req.service_path, resp.resp.error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	/* Check the response for other error case*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 		pr_err("PDR: %s request for PD restart failed: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 		       req.service_path, resp.resp.error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 		return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) EXPORT_SYMBOL(pdr_restart_pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)  * pdr_handle_alloc() - initialize the PDR client handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)  * @status:	function to be called on PD state change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)  * @priv:	handle for client's use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)  * Initializes the PDR client handle to allow for tracking/restart of PDs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)  * Return: pdr_handle object on success, ERR_PTR on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct pdr_handle *pdr_handle_alloc(void (*status)(int state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 						   char *service_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 						   void *priv), void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	struct pdr_handle *pdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	if (!status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	pdr = kzalloc(sizeof(*pdr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	if (!pdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	pdr->status = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 	pdr->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 	mutex_init(&pdr->status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	mutex_init(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	mutex_init(&pdr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	INIT_LIST_HEAD(&pdr->lookups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	INIT_LIST_HEAD(&pdr->indack_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	INIT_WORK(&pdr->locator_work, pdr_locator_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	INIT_WORK(&pdr->notifier_work, pdr_notifier_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	INIT_WORK(&pdr->indack_work, pdr_indack_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	pdr->notifier_wq = create_singlethread_workqueue("pdr_notifier_wq");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 	if (!pdr->notifier_wq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 		goto free_pdr_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 	pdr->indack_wq = alloc_ordered_workqueue("pdr_indack_wq", WQ_HIGHPRI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	if (!pdr->indack_wq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 		goto destroy_notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	ret = qmi_handle_init(&pdr->locator_hdl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 			      SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 			      &pdr_locator_ops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 		goto destroy_indack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	ret = qmi_add_lookup(&pdr->locator_hdl, SERVREG_LOCATOR_SERVICE, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 		goto release_qmi_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	ret = qmi_handle_init(&pdr->notifier_hdl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 			      SERVREG_STATE_UPDATED_IND_MAX_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 			      &pdr_notifier_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 			      qmi_indication_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 		goto release_qmi_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	return pdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) release_qmi_handle:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	qmi_handle_release(&pdr->locator_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) destroy_indack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	destroy_workqueue(pdr->indack_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) destroy_notifier:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	destroy_workqueue(pdr->notifier_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) free_pdr_handle:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	kfree(pdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) EXPORT_SYMBOL(pdr_handle_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)  * pdr_handle_release() - release the PDR client handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)  * @pdr:	PDR client handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)  * Cleans up pending tracking requests and releases the underlying qmi handles.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) void pdr_handle_release(struct pdr_handle *pdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	struct pdr_service *pds, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	if (IS_ERR_OR_NULL(pdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 	mutex_lock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	list_for_each_entry_safe(pds, tmp, &pdr->lookups, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 		list_del(&pds->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 		kfree(pds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	mutex_unlock(&pdr->list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 	cancel_work_sync(&pdr->locator_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 	cancel_work_sync(&pdr->notifier_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	cancel_work_sync(&pdr->indack_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	destroy_workqueue(pdr->notifier_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	destroy_workqueue(pdr->indack_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 	qmi_handle_release(&pdr->locator_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	qmi_handle_release(&pdr->notifier_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 	kfree(pdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) EXPORT_SYMBOL(pdr_handle_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) MODULE_DESCRIPTION("Qualcomm Protection Domain Restart helpers");