diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c index d5637f8ec162..b993566e6666 100644 --- a/drivers/soc/qcom/service-notifier.c +++ b/drivers/soc/qcom/service-notifier.c @@ -73,9 +73,10 @@ static LIST_HEAD(service_list); static DEFINE_MUTEX(service_list_lock); struct ind_req_resp { - char service_path[SERVREG_NOTIF_NAME_LENGTH]; int transaction_id; int curr_state; + struct work_struct ind_ack; + struct qmi_client_info *client_data; }; /* @@ -91,7 +92,6 @@ struct qmi_client_info { int instance_id; char service_path[SERVREG_NOTIF_NAME_LENGTH]; enum pd_subsys_state subsys_state; - struct work_struct ind_ack; struct work_struct new_server; struct work_struct del_server; struct workqueue_struct *svc_event_wq; @@ -102,7 +102,6 @@ struct qmi_client_info { struct notifier_block ssr_notifier; bool service_connected; struct list_head list; - struct ind_req_resp ind_msg; struct sockaddr_qrtr s_addr; }; static LIST_HEAD(qmi_client_list); @@ -140,8 +139,9 @@ static int service_notif_queue_notification(struct service_notif_info static void send_ind_ack(struct work_struct *work) { - struct qmi_client_info *data = container_of(work, - struct qmi_client_info, ind_ack); + struct ind_req_resp *ind_info = container_of(work, struct ind_req_resp, + ind_ack); + struct qmi_client_info *data = ind_info->client_data; struct qmi_servreg_notif_set_ack_req_msg_v01 req; struct qmi_servreg_notif_set_ack_resp_msg_v01 resp = { { 0, 0 } }; struct qmi_txn txn; @@ -149,29 +149,29 @@ static void send_ind_ack(struct work_struct *work) enum pd_subsys_state state = USER_PD_STATE_CHANGE; int rc; - service_notif = _find_service_info(data->ind_msg.service_path); + service_notif = _find_service_info(data->service_path); if (!service_notif) - return; - if ((int)data->ind_msg.curr_state < QMI_STATE_MIN_VAL || - (int)data->ind_msg.curr_state > QMI_STATE_MAX_VAL) + goto out; + if ((int)ind_info->curr_state < QMI_STATE_MIN_VAL || + (int)ind_info->curr_state > QMI_STATE_MAX_VAL) pr_err("Unexpected indication notification state %d\n", - data->ind_msg.curr_state); + ind_info->curr_state); else { mutex_lock(¬if_add_lock); mutex_lock(&service_list_lock); rc = service_notif_queue_notification(service_notif, - data->ind_msg.curr_state, &state); + ind_info->curr_state, &state); if (rc & NOTIFY_STOP_MASK) pr_err("Notifier callback aborted for %s with error %d\n", - data->ind_msg.service_path, rc); - service_notif->curr_state = data->ind_msg.curr_state; + data->service_path, rc); + service_notif->curr_state = ind_info->curr_state; mutex_unlock(&service_list_lock); mutex_unlock(¬if_add_lock); } - req.transaction_id = data->ind_msg.transaction_id; + req.transaction_id = ind_info->transaction_id; snprintf(req.service_name, ARRAY_SIZE(req.service_name), "%s", - data->ind_msg.service_path); + data->service_path); rc = qmi_txn_init(&data->clnt_handle, &txn, qmi_servreg_notif_set_ack_resp_msg_v01_ei, @@ -179,8 +179,8 @@ static void send_ind_ack(struct work_struct *work) if (rc < 0) { pr_err("%s QMI tx init failed , ret - %d\n", - data->ind_msg.service_path, rc); - return; + data->service_path, rc); + goto out; } rc = qmi_send_request(&data->clnt_handle, &data->s_addr, @@ -190,24 +190,26 @@ static void send_ind_ack(struct work_struct *work) &req); if (rc < 0) { pr_err("%s: QMI send ACK failed, ret - %d\n", - data->ind_msg.service_path, rc); + data->service_path, rc); qmi_txn_cancel(&txn); - return; + goto out; } rc = qmi_txn_wait(&txn, msecs_to_jiffies(SERVER_TIMEOUT)); if (rc < 0) { pr_err("%s: QMI qmi txn wait failed, ret - %d\n", - data->ind_msg.service_path, rc); - return; + data->service_path, rc); + goto out; } /* Check the response */ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) pr_err("QMI request failed 0x%x\n", resp.resp.error); pr_info("Indication ACKed for transid %d, service %s, instance %d!\n", - data->ind_msg.transaction_id, data->ind_msg.service_path, + ind_info->transaction_id, data->service_path, data->instance_id); +out: + kfree(ind_info); } static void root_service_service_ind_cb(struct qmi_handle *qmi, @@ -218,17 +220,20 @@ static void root_service_service_ind_cb(struct qmi_handle *qmi, struct qmi_client_info, clnt_handle); struct qmi_servreg_notif_state_updated_ind_msg_v01 ind_msg = *((struct qmi_servreg_notif_state_updated_ind_msg_v01 *)data); + struct ind_req_resp *ind_info = kmalloc(sizeof(*ind_info), GFP_KERNEL); + + if (!ind_info) + return; pr_info("Indication received from %s, state: 0x%x, trans-id: %d\n", ind_msg.service_name, ind_msg.curr_state, ind_msg.transaction_id); - qmi_data->ind_msg.transaction_id = ind_msg.transaction_id; - qmi_data->ind_msg.curr_state = ind_msg.curr_state; - snprintf(qmi_data->ind_msg.service_path, - ARRAY_SIZE(qmi_data->ind_msg.service_path), "%s", - ind_msg.service_name); - queue_work(qmi_data->ind_ack_wq, &qmi_data->ind_ack); + ind_info->transaction_id = ind_msg.transaction_id; + ind_info->curr_state = ind_msg.curr_state; + ind_info->client_data = qmi_data; + INIT_WORK(&ind_info->ind_ack, send_ind_ack); + queue_work(qmi_data->ind_ack_wq, &ind_info->ind_ack); } static int send_notif_listener_msg_req(struct service_notif_info *service_notif, @@ -251,7 +256,7 @@ static int send_notif_listener_msg_req(struct service_notif_info *service_notif, if (rc < 0) { pr_err("%s QMI tx init failed , ret - %d\n", - data->ind_msg.service_path, rc); + service_notif->service_path, rc); return rc; } @@ -513,7 +518,6 @@ static void *add_service_notif(const char *service_path, int instance_id, goto exit; } - INIT_WORK(&qmi_data->ind_ack, send_ind_ack); INIT_WORK(&qmi_data->new_server, new_server_work); INIT_WORK(&qmi_data->del_server, del_server_work); @@ -586,8 +590,7 @@ static int send_pd_restart_req(const char *service_path, &resp); if (rc < 0) { - pr_err("%s QMI tx init failed , ret - %d\n", - data->ind_msg.service_path, rc); + pr_err("%s QMI tx init failed , ret - %d\n", service_path, rc); return rc; }