^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");