int ipc_protocol_tq_msg_send(struct iosm_protocol *ipc_protocol, enum ipc_msg_prep_type msg_type, union ipc_msg_prep_args *prep_args, struct ipc_rsp *response)
{ int index = ipc_protocol_msg_prep(ipc_protocol->imem, msg_type,
prep_args);
/* Store reference towards caller specified response in response ring * and signal CP
*/ if (index >= 0 && index < IPC_MEM_MSG_ENTRIES) {
ipc_protocol->rsp_ring[index] = response;
ipc_protocol_msg_hp_update(ipc_protocol->imem);
}
/* Remove reference to a response. This is typically used when a requestor timed * out and is no longer interested in the response.
*/ staticint ipc_protocol_tq_msg_remove(struct iosm_imem *ipc_imem, int arg, void *msg, size_t size)
{ struct iosm_protocol *ipc_protocol = ipc_imem->ipc_protocol;
ipc_protocol->rsp_ring[arg] = NULL; return 0;
}
int ipc_protocol_msg_send(struct iosm_protocol *ipc_protocol, enum ipc_msg_prep_type prep, union ipc_msg_prep_args *prep_args)
{ struct ipc_call_msg_send_args send_args; unsignedint exec_timeout; struct ipc_rsp response; int index;
/* Allocate and prepare message to be sent in tasklet context. * A positive index returned form tasklet_call references the message * in case it needs to be cancelled when there is a timeout.
*/
index = ipc_task_queue_send_task(ipc_protocol->imem,
ipc_protocol_tq_msg_send_cb, 0,
&send_args, 0, true);
/* Wait for the device to respond to the message */ switch (wait_for_completion_timeout(&response.completion,
msecs_to_jiffies(exec_timeout))) { case 0: /* Timeout, there was no response from the device. * Remove the reference to the local response completion * object as we are no longer interested in the response.
*/
ipc_task_queue_send_task(ipc_protocol->imem,
ipc_protocol_tq_msg_remove, index,
NULL, 0, true);
dev_err(ipc_protocol->dev, "msg timeout");
ipc_uevent_send(ipc_protocol->pcie->dev, UEVENT_MDM_TIMEOUT); break; default: /* We got a response in time; check completion status: */ if (response.status != IPC_MEM_MSG_CS_SUCCESS) {
dev_err(ipc_protocol->dev, "msg completion status error %d",
response.status); return -EIO;
}
}
if (ipc_status != IPC_MEM_DEVICE_IPC_RUNNING) {
dev_err(ipc_protocol->dev, "irq ignored, CP IPC state is %d, should be RUNNING",
ipc_status);
/* Stop further processing. */ returnfalse;
}
/* Get a copy of the requested PM state by the device and the local * device PM state.
*/
requested = ipc_protocol_pm_dev_get_sleep_notification(ipc_protocol);
if (!ipc_pm_wait_for_device_active(&ipc_protocol->pm)) {
ipc_uevent_send(ipc_protocol->pcie->dev, UEVENT_MDM_TIMEOUT); goto err;
}
/* Send the sleep message for sync sys calls. */
dev_dbg(ipc_protocol->dev, "send TARGET_HOST, ENTER_SLEEP"); if (ipc_protocol_msg_send_host_sleep(ipc_protocol,
IPC_HOST_SLEEP_ENTER_SLEEP)) { /* Sending ENTER_SLEEP message failed, we are still active */
ipc_protocol->pm.host_pm_state = IPC_MEM_HOST_PM_ACTIVE; goto err;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.