enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
uint32_t payload[PAYLOAD_ARG_CNT],
uint32_t *value, size_t count);
-void pm_ipi_buff_read_callb(uint32_t *value, size_t count);
+enum pm_ret_status pm_ipi_buff_read_callb(uint32_t *value, size_t count);
void pm_ipi_irq_enable(const struct pm_proc *proc);
void pm_ipi_irq_clear(const struct pm_proc *proc);
uint32_t pm_ipi_irq_status(const struct pm_proc *proc);
*
* This callback function fills requested data in @value from ipi response
* buffer.
+ * @return Returns status, either success or error
*/
-void pm_ipi_buff_read_callb(uint32_t *value, size_t count)
+enum pm_ret_status pm_ipi_buff_read_callb(uint32_t *value, size_t count)
{
size_t i;
#if IPI_CRC_CHECK
+ uint32_t *payload_ptr = value;
size_t j;
unsigned int response_payload[PAYLOAD_ARG_CNT] = {0};
#endif
uintptr_t buffer_base = IPI_BUFFER_REMOTE_BASE +
IPI_BUFFER_TARGET_LOCAL_OFFSET +
IPI_BUFFER_REQ_OFFSET;
+ enum pm_ret_status ret = PM_RET_SUCCESS;
if (count > IPI_BUFFER_MAX_WORDS) {
count = IPI_BUFFER_MAX_WORDS;
calculate_crc(response_payload, IPI_W0_TO_W6_SIZE)) {
NOTICE("ERROR in CRC response payload value:0x%x\n",
response_payload[PAYLOAD_CRC_POS]);
+ ret = PM_RET_ERROR_INVALID_CRC;
+ /* Payload data is invalid as CRC validation failed
+ * Clear the payload to avoid leakage of data to upper layers
+ */
+ memset(payload_ptr, 0, count);
}
#endif
+ return ret;
}
/**
* 1 - Ack IPI after reading payload
*
* Read value from ipi buffer response buffer.
+ * @return Returns status, either success or error
*/
-void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag, uint32_t ack)
+enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag, uint32_t ack)
{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
/* Return if interrupt is not from PMU */
if (pm_ipi_irq_status(primary_proc) == 0) {
- return;
+ return ret;
}
- pm_ipi_buff_read_callb(data, count);
+ ret = pm_ipi_buff_read_callb(data, count);
if (ack != 0U) {
pm_ipi_irq_clear(primary_proc);
}
+
+ return ret;
}
/**
uintptr_t address, uint8_t ack, uint32_t flag);
enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t device_id,
uint8_t enable, uint32_t flag);
-void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag,
+enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag,
uint32_t ack);
enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param,
uint32_t value, uint32_t flag);
void *cookie)
{
uint32_t payload[4] = {0};
+ enum pm_ret_status ret;
VERBOSE("Received IPI FIQ from firmware\n");
(void)plat_ic_acknowledge_interrupt();
- pm_get_callbackdata(payload, ARRAY_SIZE(payload), 0, 0);
+ ret = pm_get_callbackdata(payload, ARRAY_SIZE(payload), 0, 0);
+ if (ret != PM_RET_SUCCESS) {
+ payload[0] = ret;
+ }
+
switch (payload[0]) {
case PM_INIT_SUSPEND_CB:
case PM_NOTIFY_CB:
notify_os();
}
break;
+ case PM_RET_ERROR_INVALID_CRC:
+ pm_ipi_irq_clear(primary_proc);
+ WARN("Invalid CRC in the payload\n");
+ break;
+
default:
pm_ipi_irq_clear(primary_proc);
WARN("Invalid IPI payload\n");
case PM_GET_CALLBACK_DATA:
{
uint32_t result[4] = {0};
+ enum pm_ret_status ret;
+
+ ret = pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag, 1U);
+ if (ret != 0) {
+ result[0] = ret;
+ }
- pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag, 1U);
SMC_RET2(handle,
(uint64_t)result[0] | ((uint64_t)result[1] << 32U),
(uint64_t)result[2] | ((uint64_t)result[3] << 32U));
* @data - array of PAYLOAD_ARG_CNT elements
*
* Read value from ipi buffer response buffer.
+ * @return Returns status, either success or error
*/
-void pm_get_callbackdata(uint32_t *data, size_t count)
+enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count)
{
+ enum pm_ret_status ret = PM_RET_SUCCESS;
/* Return if interrupt is not from PMU */
if (!pm_ipi_irq_status(primary_proc)) {
- return;
+ return ret;
}
- pm_ipi_buff_read_callb(data, count);
+ ret = pm_ipi_buff_read_callb(data, count);
pm_ipi_irq_clear(primary_proc);
+ return ret;
}
/**
uint32_t size,
uint32_t flags);
uint32_t pm_get_shutdown_scope(void);
-void pm_get_callbackdata(uint32_t *data, size_t count);
+enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count);
enum pm_ret_status pm_ioctl(enum pm_node_id nid,
uint32_t ioctl_id,
uint32_t arg1,
SMC_RET1(handle, (uint64_t)ret);
case PM_GET_CALLBACK_DATA:
- pm_get_callbackdata(result, ARRAY_SIZE(result));
+ ret = pm_get_callbackdata(result, ARRAY_SIZE(result));
+ if (ret != PM_RET_SUCCESS) {
+ result[0] = ret;
+ }
+
SMC_RET2(handle,
(uint64_t)result[0] | ((uint64_t)result[1] << 32),
(uint64_t)result[2] | ((uint64_t)result[3] << 32));