/* * msm_rpm_log_copy() - Copies messages from a volatile circular buffer in * the RPM's shared memory into a private local buffer * msg_buffer: pointer to local buffer (string) * buf_len: length of local buffer in bytes * read_start_idx: index into shared memory buffer * * Return value: number of bytes written to the local buffer * * Copies messages stored in a circular buffer in the RPM Message Memory into * a specified local buffer. The RPM processor is unaware of these reading * efforts, so care is taken to make sure that messages are valid both before * and after reading. The RPM processor utilizes a ULog driver to write the * log. The RPM processor maintains tail and head indices. These correspond * to the next byte to write into, and the first valid byte, respectively. * Both indices increase monotonically (except for rollover). * * Messages take the form of [(u32)length] [(char)data0,1,...] in which the * length specifies the number of payload bytes. Messages must be 4 byte * aligned, so padding is added at the end of a message as needed. * * Print format: * - 0xXX, 0xXX, 0xXX * - 0xXX * etc... */ static u32 msm_rpm_log_copy(const struct msm_rpm_log_platform_data *pdata, char *msg_buffer, u32 buf_len, u32 *read_idx) { u32 head_idx, tail_idx; u32 pos = 0; u32 i = 0; u32 msg_len; u32 pos_start; char temp[4]; tail_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES, MSM_RPM_LOG_TAIL); head_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES, MSM_RPM_LOG_HEAD); /* loop while the remote buffer has valid messages left to read */ while (tail_idx - head_idx > 0 && tail_idx - *read_idx > 0) { head_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES, MSM_RPM_LOG_HEAD); tail_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES, MSM_RPM_LOG_TAIL); /* check if the message to be read is valid */ if (tail_idx - *read_idx > tail_idx - head_idx) { *read_idx = head_idx; continue; } /* * Ensure that all indices are 4 byte aligned. * This conditions is required to interact with a ULog buffer * properly. */ if (!IS_ALIGNED((tail_idx | head_idx | *read_idx), 4)) break; msg_len = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_BUFFER, ((*read_idx) & pdata->log_len_mask) >> 2); /* Message length for 8974 is first 2 bytes. * Exclude message length and format from message length. */ if (pdata->version == VERSION_8974) { msg_len = (msg_len & RPM_ULOG_LENGTH_MASK) >> RPM_ULOG_LENGTH_SHIFT; msg_len -= 4; } /* handle messages that claim to be longer than the log */ if (PADDED_LENGTH(msg_len) > tail_idx - *read_idx - 4) msg_len = tail_idx - *read_idx - 4; /* check that the local buffer has enough space for this msg */ if (pos + PRINTED_LENGTH(msg_len) > buf_len) break; pos_start = pos; pos += scnprintf(msg_buffer + pos, buf_len - pos, "- "); /* copy message payload to local buffer */ for (i = 0; i < msg_len; i++) { /* read from shared memory 4 bytes at a time */ if (IS_ALIGNED(i, 4)) *((u32 *)temp) = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_BUFFER, ((*read_idx + 4 + i) & pdata->log_len_mask) >> 2); pos += scnprintf(msg_buffer + pos, buf_len - pos, "0x%02X, ", temp[i & 0x03]); } pos += scnprintf(msg_buffer + pos, buf_len - pos, "\n"); head_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES, MSM_RPM_LOG_HEAD); tail_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES, MSM_RPM_LOG_TAIL); /* roll back if message that was read is not still valid */ if (tail_idx - *read_idx > tail_idx - head_idx) pos = pos_start; *read_idx += PADDED_LENGTH(msg_len) + 4; }
static u32 msm_rpm_log_copy(const struct msm_rpm_log_platform_data *pdata, char *msg_buffer, u32 buf_len, u32 *read_idx) { u32 head_idx, tail_idx; u32 pos = 0; u32 i = 0; u32 msg_len; u32 pos_start; char temp[4]; tail_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES, MSM_RPM_LOG_TAIL); head_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES, MSM_RPM_LOG_HEAD); while (tail_idx - head_idx > 0 && tail_idx - *read_idx > 0) { head_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES, MSM_RPM_LOG_HEAD); if (tail_idx - *read_idx > tail_idx - head_idx) { *read_idx = head_idx; continue; } if (tail_idx - head_idx > pdata->log_len || !IS_ALIGNED((tail_idx | head_idx | *read_idx), 4)) break; msg_len = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_BUFFER, (*read_idx >> 2) & pdata->log_len_mask); if (PADDED_LENGTH(msg_len) > tail_idx - *read_idx - 4) msg_len = tail_idx - *read_idx - 4; if (pos + PRINTED_LENGTH(msg_len) > buf_len) break; pos_start = pos; pos += scnprintf(msg_buffer + pos, buf_len - pos, "- "); for (i = 0; i < msg_len; i++) { if (IS_ALIGNED(i, 4)) *((u32 *)temp) = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_BUFFER, ((*read_idx + 4 + i) >> 2) & pdata->log_len_mask); pos += scnprintf(msg_buffer + pos, buf_len - pos, "0x%02X, ", temp[i & 0x03]); } pos += scnprintf(msg_buffer + pos, buf_len - pos, "\n"); head_idx = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_INDICES, MSM_RPM_LOG_HEAD); if (tail_idx - *read_idx > tail_idx - head_idx) pos = pos_start; *read_idx += PADDED_LENGTH(msg_len) + 4; } return pos; }