soc: qcom: service-notifier: Use per-indication structs for PDR
When an indication is received from a PD during PDR, the transaction ID, and other information relevant to that particular indication, are saved inside the QMI data structure for that PD. As a consequence of there being one indication structure for all indications, if the PD sends back-to-back indications, then it is possible for the information pertaining to the first indication to be overwritten. Thus, allocate an indication data structure for each indication that arrives, to prevent the indication state from being corrupted because of the reception of another indication from the same PD. Change-Id: I68830773a186123c7d840056931176892e458f04 Signed-off-by: Isaac J. Manjarres <isaacm@codeaurora.org>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user