diff --git a/msm/synx/ipclite.c b/msm/synx/ipclite.c index 90daaab0fd..969a52dd21 100644 --- a/msm/synx/ipclite.c +++ b/msm/synx/ipclite.c @@ -19,6 +19,8 @@ #include #include +#include + #include "ipclite_client.h" #include "ipclite.h" @@ -28,18 +30,152 @@ #define VMID_CDSP 30 #define GLOBAL_ATOMICS_ENABLED 1 #define GLOBAL_ATOMICS_DISABLED 0 +#define FIFO_FULL_RESERVE 8 +#define FIFO_ALIGNMENT 8 static struct ipclite_info *ipclite; static struct ipclite_client synx_client; static struct ipclite_client test_client; -struct ipclite_hw_mutex_ops *ipclite_hw_mutex; -struct mutex ssr_mutex; -uint32_t channel_status_info[IPCMEM_NUM_HOSTS]; +static struct ipclite_hw_mutex_ops *ipclite_hw_mutex; +static struct ipclite_debug_info *ipclite_dbg_info; +static struct ipclite_debug_struct *ipclite_dbg_struct; +static struct ipclite_debug_inmem_buf *ipclite_dbg_inmem; +static struct mutex ssr_mutex; +static struct kobject *sysfs_kobj; -u32 global_atomic_support = GLOBAL_ATOMICS_ENABLED; +static uint32_t channel_status_info[IPCMEM_NUM_HOSTS]; +static u32 global_atomic_support = GLOBAL_ATOMICS_ENABLED; +static uint32_t ipclite_debug_level = IPCLITE_ERR | IPCLITE_WARN | IPCLITE_INFO; +static uint32_t ipclite_debug_control = IPCLITE_DMESG_LOG, ipclite_debug_dump; -#define FIFO_FULL_RESERVE 8 -#define FIFO_ALIGNMENT 8 +static void IPCLITE_OS_INMEM_LOG(const char *psztStr, ...) +{ + uint32_t local_index = 0; + va_list pArgs; + + va_start(pArgs, psztStr); + + /* Incrementing the index atomically and storing the index in local variable */ + local_index = ipclite_global_atomic_inc((ipclite_atomic_int32_t *) + &ipclite_dbg_info->debug_log_index); + local_index %= IPCLITE_LOG_BUF_SIZE; + + /* Writes data on the index location */ + vsnprintf(ipclite_dbg_inmem->IPCLITELog[local_index], IPCLITE_LOG_MSG_SIZE, psztStr, pArgs); + + va_end(pArgs); +} + +static void ipclite_dump_debug_struct(void) +{ + int i, host; + struct ipclite_debug_struct *temp_dbg_struct; + + /* Check if debug structures are initialized */ + if (!ipclite_dbg_info || !ipclite_dbg_struct) { + pr_err("Debug Structures not initialized\n"); + return; + } + + /* Check if debug structures are enabled before printing */ + if (!(ipclite_debug_control & IPCLITE_DBG_STRUCT)) { + pr_err("Debug Structures not enabled\n"); + return; + } + + /* Dumping the debug structures */ + pr_info("------------------- Dumping IPCLite Debug Structure -------------------\n"); + + for (host = 0; host < IPCMEM_NUM_HOSTS; host++) { + if (ipclite->ipcmem.toc->recovery.configured_core[host]) { + temp_dbg_struct = (struct ipclite_debug_struct *) + (((char *)ipclite_dbg_struct) + + (sizeof(*temp_dbg_struct) * host)); + + pr_info("---------- Host ID: %d dbg_mem:%p ----------\n", + host, temp_dbg_struct); + pr_info("Total Signals Sent : %d Total Signals Received : %d\n", + temp_dbg_struct->dbg_info_overall.total_numsig_sent, + temp_dbg_struct->dbg_info_overall.total_numsig_recv); + pr_info("Last Signal Sent to Host ID : %d Last Signal Received from Host ID : %d\n", + temp_dbg_struct->dbg_info_overall.last_sent_host_id, + temp_dbg_struct->dbg_info_overall.last_recv_host_id); + pr_info("Last Signal ID Sent : %d Last Signal ID Received : %d\n", + temp_dbg_struct->dbg_info_overall.last_sigid_sent, + temp_dbg_struct->dbg_info_overall.last_sigid_recv); + + for (i = 0; i < IPCMEM_NUM_HOSTS; i++) { + if (ipclite->ipcmem.toc->recovery.configured_core[i]) { + pr_info("----------> Host ID : %d Host ID : %d Channel State: %d\n", + host, i, ipclite->ipcmem.toc->toc_entry[host][i].status); + pr_info("No. of Messages Sent : %d No. of Messages Received : %d\n", + temp_dbg_struct->dbg_info_host[i].numsig_sent, + temp_dbg_struct->dbg_info_host[i].numsig_recv); + pr_info("No. of Interrupts Received : %d\n", + temp_dbg_struct->dbg_info_host[i].num_intr); + pr_info("TX Write Index : %d TX Read Index : %d\n", + temp_dbg_struct->dbg_info_host[i].tx_wr_index, + temp_dbg_struct->dbg_info_host[i].tx_rd_index); + pr_info("TX Write Index[0] : %d TX Read Index[0] : %d\n", + temp_dbg_struct->dbg_info_host[i].prev_tx_wr_index[0], + temp_dbg_struct->dbg_info_host[i].prev_tx_rd_index[0]); + pr_info("TX Write Index[1] : %d TX Read Index[1] : %d\n", + temp_dbg_struct->dbg_info_host[i].prev_tx_wr_index[1], + temp_dbg_struct->dbg_info_host[i].prev_tx_rd_index[1]); + pr_info("RX Write Index : %d RX Read Index : %d\n", + temp_dbg_struct->dbg_info_host[i].rx_wr_index, + temp_dbg_struct->dbg_info_host[i].rx_rd_index); + pr_info("RX Write Index[0] : %d RX Read Index[0] : %d\n", + temp_dbg_struct->dbg_info_host[i].prev_rx_wr_index[0], + temp_dbg_struct->dbg_info_host[i].prev_rx_rd_index[0]); + pr_info("RX Write Index[1] : %d RX Read Index[1] : %d\n", + temp_dbg_struct->dbg_info_host[i].prev_rx_wr_index[1], + temp_dbg_struct->dbg_info_host[i].prev_rx_rd_index[1]); + } + } + } + } + return; +} + +static void ipclite_dump_inmem_logs(void) +{ + int i; + uint32_t local_index = 0; + + /* Check if debug and inmem structures are initialized */ + if (!ipclite_dbg_info || !ipclite_dbg_inmem) { + pr_err("Debug structures not initialized\n"); + return; + } + + /* Check if debug structures are enabled before printing */ + if (!(ipclite_debug_control & IPCLITE_INMEM_LOG)) { + pr_err("In-Memory Logs not enabled\n"); + return; + } + + /* Dumping the debug in-memory logs */ + pr_info("------------------- Dumping In-Memory Logs -------------------\n"); + + /* Storing the index atomically in local variable */ + local_index = ipclite_global_atomic_load_u32((ipclite_atomic_uint32_t *) + &ipclite_dbg_info->debug_log_index); + + /* Printing from current index till the end of buffer */ + for (i = local_index % IPCLITE_LOG_BUF_SIZE; i < IPCLITE_LOG_BUF_SIZE; i++) { + if (ipclite_dbg_inmem->IPCLITELog[i][0]) + pr_info("%s\n", ipclite_dbg_inmem->IPCLITELog[i]); + } + + /* Printing from 0th index to current-1 index */ + for (i = 0; i < local_index % IPCLITE_LOG_BUF_SIZE; i++) { + if (ipclite_dbg_inmem->IPCLITELog[i][0]) + pr_info("%s\n", ipclite_dbg_inmem->IPCLITELog[i]); + } + + return; +} static void ipclite_hw_mutex_acquire(void) { @@ -50,12 +186,14 @@ static void ipclite_hw_mutex_acquire(void) ret = hwspin_lock_timeout_irqsave(ipclite->hwlock, HWSPINLOCK_TIMEOUT, &ipclite->ipclite_hw_mutex->flags); - if (ret) - pr_err("Hw mutex lock acquire failed\n"); + if (ret) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Hw mutex lock acquire failed\n"); + return; + } ipclite->ipcmem.toc->recovery.global_atomic_hwlock_owner = IPCMEM_APPS; - pr_debug("Hw mutex lock acquired\n"); + IPCLITE_OS_LOG(IPCLITE_DBG, "Hw mutex lock acquired\n"); } } } @@ -68,7 +206,7 @@ static void ipclite_hw_mutex_release(void) IPCMEM_INVALID_HOST; hwspin_unlock_irqrestore(ipclite->hwlock, &ipclite->ipclite_hw_mutex->flags); - pr_debug("Hw mutex lock release\n"); + IPCLITE_OS_LOG(IPCLITE_DBG, "Hw mutex lock release\n"); } } } @@ -76,14 +214,12 @@ static void ipclite_hw_mutex_release(void) void ipclite_atomic_init_u32(ipclite_atomic_uint32_t *addr, uint32_t data) { atomic_set(addr, data); - pr_debug("%s new_val = %d\n", __func__, (*(uint32_t *)addr)); } EXPORT_SYMBOL(ipclite_atomic_init_u32); void ipclite_atomic_init_i32(ipclite_atomic_int32_t *addr, int32_t data) { atomic_set(addr, data); - pr_debug("%s new_val = %d\n", __func__, (*(int32_t *)addr)); } EXPORT_SYMBOL(ipclite_atomic_init_i32); @@ -93,7 +229,6 @@ void ipclite_global_atomic_store_u32(ipclite_atomic_uint32_t *addr, uint32_t dat ipclite->ipclite_hw_mutex->acquire(); atomic_set(addr, data); - pr_debug("%s new_val = %d\n", __func__, (*(uint32_t *)addr)); /* callback to release hw mutex lock if atomic support is not enabled */ ipclite->ipclite_hw_mutex->release(); @@ -106,7 +241,6 @@ void ipclite_global_atomic_store_i32(ipclite_atomic_int32_t *addr, int32_t data) ipclite->ipclite_hw_mutex->acquire(); atomic_set(addr, data); - pr_debug("%s new_val = %d\n", __func__, (*(int32_t *)addr)); /* callback to release hw mutex lock if atomic support is not enabled */ ipclite->ipclite_hw_mutex->release(); @@ -121,7 +255,6 @@ uint32_t ipclite_global_atomic_load_u32(ipclite_atomic_uint32_t *addr) ipclite->ipclite_hw_mutex->acquire(); ret = atomic_read(addr); - pr_debug("%s ret = %d, new_val = %d\n", __func__, ret, (*(uint32_t *)addr)); /* callback to release hw mutex lock if atomic support is not enabled */ ipclite->ipclite_hw_mutex->release(); @@ -138,7 +271,6 @@ int32_t ipclite_global_atomic_load_i32(ipclite_atomic_int32_t *addr) ipclite->ipclite_hw_mutex->acquire(); ret = atomic_read(addr); - pr_debug("%s ret = %d, new_val = %d\n", __func__, ret, (*(int32_t *)addr)); /* callback to release hw mutex lock if atomic support is not enabled */ ipclite->ipclite_hw_mutex->release(); @@ -156,7 +288,6 @@ uint32_t ipclite_global_test_and_set_bit(uint32_t nr, ipclite_atomic_uint32_t *a ipclite->ipclite_hw_mutex->acquire(); ret = atomic_fetch_or(mask, addr); - pr_debug("%s ret = %d, new_val = %d\n", __func__, ret, (*(uint32_t *)addr)); /* callback to release hw mutex lock if atomic support is not enabled */ ipclite->ipclite_hw_mutex->release(); @@ -174,7 +305,6 @@ uint32_t ipclite_global_test_and_clear_bit(uint32_t nr, ipclite_atomic_uint32_t ipclite->ipclite_hw_mutex->acquire(); ret = atomic_fetch_and(~mask, addr); - pr_debug("%s ret = %d, new_val = %d\n", __func__, ret, (*(uint32_t *)addr)); /* callback to release hw mutex lock if atomic support is not enabled */ ipclite->ipclite_hw_mutex->release(); @@ -191,7 +321,6 @@ int32_t ipclite_global_atomic_inc(ipclite_atomic_int32_t *addr) ipclite->ipclite_hw_mutex->acquire(); ret = atomic_fetch_add(1, addr); - pr_debug("%s ret = %d new_val = %d\n", __func__, ret, (*(int32_t *)addr)); /* callback to release hw mutex lock if atomic support is not enabled */ ipclite->ipclite_hw_mutex->release(); @@ -208,7 +337,6 @@ int32_t ipclite_global_atomic_dec(ipclite_atomic_int32_t *addr) ipclite->ipclite_hw_mutex->acquire(); ret = atomic_fetch_sub(1, addr); - pr_debug("%s ret = %d new_val = %d\n", __func__, ret, (*(int32_t *)addr)); /* callback to release hw mutex lock if atomic support is not enabled */ ipclite->ipclite_hw_mutex->release(); @@ -225,7 +353,9 @@ static size_t ipcmem_rx_avail(struct ipclite_fifo *rx_fifo) head = le32_to_cpu(*rx_fifo->head); tail = le32_to_cpu(*rx_fifo->tail); - pr_debug("head=%d, tail=%d\n", head, tail); + + IPCLITE_OS_LOG(IPCLITE_DBG, "head=%d, tail=%d\n", head, tail); + if (head < tail) len = rx_fifo->length - tail + head; else @@ -233,7 +363,9 @@ static size_t ipcmem_rx_avail(struct ipclite_fifo *rx_fifo) if (WARN_ON_ONCE(len > rx_fifo->length)) len = 0; - pr_debug("len=%d\n", len); + + IPCLITE_OS_LOG(IPCLITE_DBG, "len=%d\n", len); + return len; } @@ -260,7 +392,7 @@ static void ipcmem_rx_peak(struct ipclite_fifo *rx_fifo, } static void ipcmem_rx_advance(struct ipclite_fifo *rx_fifo, - size_t count) + size_t count, uint32_t core_id) { u32 tail; @@ -271,6 +403,24 @@ static void ipcmem_rx_advance(struct ipclite_fifo *rx_fifo, tail %= rx_fifo->length; *rx_fifo->tail = cpu_to_le32(tail); + + /* Storing the debug data in debug structures */ + if (ipclite_debug_control & IPCLITE_DBG_STRUCT) { + ipclite_dbg_struct->dbg_info_host[core_id].prev_rx_wr_index[1] = + ipclite_dbg_struct->dbg_info_host[core_id].prev_rx_wr_index[0]; + ipclite_dbg_struct->dbg_info_host[core_id].prev_rx_wr_index[0] = + ipclite_dbg_struct->dbg_info_host[core_id].rx_wr_index; + ipclite_dbg_struct->dbg_info_host[core_id].rx_wr_index = *rx_fifo->head; + + ipclite_dbg_struct->dbg_info_host[core_id].prev_rx_rd_index[1] = + ipclite_dbg_struct->dbg_info_host[core_id].prev_rx_rd_index[0]; + ipclite_dbg_struct->dbg_info_host[core_id].prev_rx_rd_index[0] = + ipclite_dbg_struct->dbg_info_host[core_id].rx_rd_index; + ipclite_dbg_struct->dbg_info_host[core_id].rx_rd_index = *rx_fifo->tail; + + ipclite_dbg_struct->dbg_info_overall.total_numsig_recv++; + ipclite_dbg_struct->dbg_info_host[core_id].numsig_recv++; + } } static size_t ipcmem_tx_avail(struct ipclite_fifo *tx_fifo) @@ -322,7 +472,7 @@ static unsigned int ipcmem_tx_write_one(struct ipclite_fifo *tx_fifo, } static void ipcmem_tx_write(struct ipclite_fifo *tx_fifo, - const void *data, size_t dlen) + const void *data, size_t dlen, uint32_t core_id, uint32_t signal_id) { unsigned int head; @@ -337,7 +487,29 @@ static void ipcmem_tx_write(struct ipclite_fifo *tx_fifo, wmb(); *tx_fifo->head = cpu_to_le32(head); - pr_debug("head = %d\n", *tx_fifo->head); + + IPCLITE_OS_LOG(IPCLITE_DBG, "head : %d core_id : %d signal_id : %d\n", + *tx_fifo->head, core_id, signal_id); + + /* Storing the debug data in debug structures */ + if (ipclite_debug_control & IPCLITE_DBG_STRUCT) { + ipclite_dbg_struct->dbg_info_host[core_id].prev_tx_wr_index[1] = + ipclite_dbg_struct->dbg_info_host[core_id].prev_tx_wr_index[0]; + ipclite_dbg_struct->dbg_info_host[core_id].prev_tx_wr_index[0] = + ipclite_dbg_struct->dbg_info_host[core_id].tx_wr_index; + ipclite_dbg_struct->dbg_info_host[core_id].tx_wr_index = *tx_fifo->head; + + ipclite_dbg_struct->dbg_info_host[core_id].prev_tx_rd_index[1] = + ipclite_dbg_struct->dbg_info_host[core_id].prev_tx_rd_index[0]; + ipclite_dbg_struct->dbg_info_host[core_id].prev_tx_rd_index[0] = + ipclite_dbg_struct->dbg_info_host[core_id].tx_rd_index; + ipclite_dbg_struct->dbg_info_host[core_id].tx_rd_index = *tx_fifo->tail; + + ipclite_dbg_struct->dbg_info_overall.total_numsig_sent++; + ipclite_dbg_struct->dbg_info_host[core_id].numsig_sent++; + ipclite_dbg_struct->dbg_info_overall.last_sent_host_id = core_id; + ipclite_dbg_struct->dbg_info_overall.last_sigid_sent = signal_id; + } } static size_t ipclite_rx_avail(struct ipclite_channel *channel) @@ -354,7 +526,7 @@ static void ipclite_rx_peak(struct ipclite_channel *channel, static void ipclite_rx_advance(struct ipclite_channel *channel, size_t count) { - channel->rx_fifo->advance(channel->rx_fifo, count); + channel->rx_fifo->advance(channel->rx_fifo, count, channel->remote_pid); } static size_t ipclite_tx_avail(struct ipclite_channel *channel) @@ -365,7 +537,8 @@ static size_t ipclite_tx_avail(struct ipclite_channel *channel) static void ipclite_tx_write(struct ipclite_channel *channel, const void *data, size_t dlen) { - channel->tx_fifo->write(channel->tx_fifo, data, dlen); + channel->tx_fifo->write(channel->tx_fifo, data, dlen, channel->remote_pid, + channel->irq_info->signal_id); } static int ipclite_rx_data(struct ipclite_channel *channel, size_t avail) @@ -374,7 +547,8 @@ static int ipclite_rx_data(struct ipclite_channel *channel, size_t avail) int ret = 0; if (avail < sizeof(data)) { - pr_err("Not enough data in fifo\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "Not enough data in fifo, Core : %d Signal : %d\n", + channel->remote_pid, channel->irq_info->signal_id); return -EAGAIN; } @@ -395,7 +569,8 @@ static int ipclite_rx_test_data(struct ipclite_channel *channel, size_t avail) int ret = 0; if (avail < sizeof(data)) { - pr_err("Not enough data in fifo\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "Not enough data in fifo, Core : %d Signal : %d\n", + channel->remote_pid, channel->irq_info->signal_id); return -EAGAIN; } @@ -418,10 +593,19 @@ static irqreturn_t ipclite_intr(int irq, void *data) int ret = 0; uint64_t msg; - pr_debug("Interrupt received\n"); irq_info = (struct ipclite_irq_info *)data; channel = container_of(irq_info, struct ipclite_channel, irq_info[irq_info->signal_id]); + IPCLITE_OS_LOG(IPCLITE_DBG, "Interrupt received from Core : %d Signal : %d\n", + channel->remote_pid, irq_info->signal_id); + + /* Storing the debug data in debug structures */ + if (ipclite_debug_control & IPCLITE_DBG_STRUCT) { + ipclite_dbg_struct->dbg_info_host[channel->remote_pid].num_intr++; + ipclite_dbg_struct->dbg_info_overall.last_recv_host_id = channel->remote_pid; + ipclite_dbg_struct->dbg_info_overall.last_sigid_recv = irq_info->signal_id; + } + if (irq_info->signal_id == IPCLITE_MSG_SIGNAL) { for (;;) { avail = ipclite_rx_avail(channel); @@ -430,10 +614,9 @@ static irqreturn_t ipclite_intr(int irq, void *data) ret = ipclite_rx_data(channel, avail); } - pr_debug("checking messages in rx_fifo done\n"); + IPCLITE_OS_LOG(IPCLITE_DBG, "checking messages in rx_fifo done\n"); } else if (irq_info->signal_id == IPCLITE_VERSION_SIGNAL) { - /* check_version_compatibility();*/ - pr_debug("version matching sequence completed\n"); + IPCLITE_OS_LOG(IPCLITE_DBG, "Versioning is currently not enabled\n"); } else if (irq_info->signal_id == IPCLITE_TEST_SIGNAL) { for (;;) { avail = ipclite_rx_avail(channel); @@ -442,10 +625,12 @@ static irqreturn_t ipclite_intr(int irq, void *data) ret = ipclite_rx_test_data(channel, avail); } - pr_debug("checking messages in rx_fifo done\n"); + IPCLITE_OS_LOG(IPCLITE_DBG, "checking messages in rx_fifo done\n"); } else { - pr_err("wrong interrupt signal received, signal_id =%d\n", irq_info->signal_id); + IPCLITE_OS_LOG(IPCLITE_ERR, "Wrong Interrupt Signal from core : %d signal : %d\n", + channel->remote_pid, irq_info->signal_id); } + return IRQ_HANDLED; } @@ -472,12 +657,12 @@ static int ipclite_tx(struct ipclite_channel *channel, return ret; } -int ipclite_ssr_update(int32_t proc_id) +static int ipclite_send_debug_info(int32_t proc_id) { int ret = 0; if (proc_id < 0 || proc_id >= IPCMEM_NUM_HOSTS) { - pr_debug("Invalid proc_id %d\n", proc_id); + IPCLITE_OS_LOG(IPCLITE_ERR, "Invalid proc_id : %d\n", proc_id); return -EINVAL; } @@ -485,33 +670,70 @@ int ipclite_ssr_update(int32_t proc_id) if (ipclite->ipcmem.toc->toc_entry[IPCMEM_APPS][proc_id].status == CHANNEL_ACTIVE) { channel_status_info[proc_id] = CHANNEL_ACTIVE; } else { - pr_err("Cannot send msg to remote client. Channel inactive\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot Send, Core %d is Inactive\n", proc_id); + return -IPCLITE_EINCHAN; + } + } + + ret = mbox_send_message(ipclite->channel[proc_id].irq_info[IPCLITE_DEBUG_SIGNAL].mbox_chan, + NULL); + if (ret < IPCLITE_SUCCESS) { + IPCLITE_OS_LOG(IPCLITE_ERR, + "Debug Signal sending failed to Core : %d Signal : %d ret : %d\n", + proc_id, IPCLITE_DEBUG_SIGNAL, ret); + return -IPCLITE_FAILURE; + } + + IPCLITE_OS_LOG(IPCLITE_DBG, + "Debug Signal send completed to core : %d signal : %d ret : %d\n", + proc_id, IPCLITE_DEBUG_SIGNAL, ret); + return IPCLITE_SUCCESS; +} + +int ipclite_ssr_update(int32_t proc_id) +{ + int ret = 0; + + if (proc_id < 0 || proc_id >= IPCMEM_NUM_HOSTS) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Invalid proc_id : %d\n", proc_id); + return -EINVAL; + } + + if (channel_status_info[proc_id] != CHANNEL_ACTIVE) { + if (ipclite->ipcmem.toc->toc_entry[IPCMEM_APPS][proc_id].status == CHANNEL_ACTIVE) { + channel_status_info[proc_id] = CHANNEL_ACTIVE; + } else { + IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot Send, Core %d is Inactive\n", proc_id); return -IPCLITE_EINCHAN; } } ret = mbox_send_message(ipclite->channel[proc_id].irq_info[IPCLITE_SSR_SIGNAL].mbox_chan, NULL); - if (ret < 0) { - pr_debug("Signal sending failed to core : %d ret : %d\n", proc_id, ret); - return ret; + if (ret < IPCLITE_SUCCESS) { + IPCLITE_OS_LOG(IPCLITE_ERR, + "SSR Signal sending failed to Core : %d Signal : %d ret : %d\n", + proc_id, IPCLITE_SSR_SIGNAL, ret); + return -IPCLITE_FAILURE; } - pr_debug("SSR update send completed with ret=%d\n", ret); - return ret; + IPCLITE_OS_LOG(IPCLITE_DBG, + "SSR Signal send completed to core : %d signal : %d ret : %d\n", + proc_id, IPCLITE_SSR_SIGNAL, ret); + return IPCLITE_SUCCESS; } void ipclite_recover(enum ipcmem_host_type core_id) { int ret, i, host, host0, host1; - pr_debug("IPCLite Recover - Crashed Core : %d\n", core_id); + IPCLITE_OS_LOG(IPCLITE_DBG, "IPCLite Recover - Crashed Core : %d\n", core_id); /* verify and reset the hw mutex lock */ if (core_id == ipclite->ipcmem.toc->recovery.global_atomic_hwlock_owner) { ipclite->ipcmem.toc->recovery.global_atomic_hwlock_owner = IPCMEM_INVALID_HOST; hwspin_unlock_raw(ipclite->hwlock); - pr_debug("HW Lock Reset\n"); + IPCLITE_OS_LOG(IPCLITE_DBG, "HW Lock Reset\n"); } mutex_lock(&ssr_mutex); @@ -530,9 +752,9 @@ void ipclite_recover(enum ipcmem_host_type core_id) channel_status_info[core_id] = ipclite->ipcmem.toc->toc_entry[host0][host1].status; } - pr_debug("Global Channel Status : [%d][%d] : %d\n", host0, host1, + IPCLITE_OS_LOG(IPCLITE_DBG, "Global Channel Status : [%d][%d] : %d\n", host0, host1, ipclite->ipcmem.toc->toc_entry[host0][host1].status); - pr_debug("Global Channel Status : [%d][%d] : %d\n", host1, host0, + IPCLITE_OS_LOG(IPCLITE_DBG, "Global Channel Status : [%d][%d] : %d\n", host1, host0, ipclite->ipcmem.toc->toc_entry[host1][host0].status); } @@ -540,8 +762,10 @@ void ipclite_recover(enum ipcmem_host_type core_id) *(ipclite->channel[core_id].tx_fifo->head) = 0; *(ipclite->channel[core_id].rx_fifo->tail) = 0; - pr_debug("TX Fifo Reset : %d\n", *(ipclite->channel[core_id].tx_fifo->head)); - pr_debug("RX Fifo Reset : %d\n", *(ipclite->channel[core_id].rx_fifo->tail)); + IPCLITE_OS_LOG(IPCLITE_DBG, "TX Fifo Reset : %d\n", + *(ipclite->channel[core_id].tx_fifo->head)); + IPCLITE_OS_LOG(IPCLITE_DBG, "RX Fifo Reset : %d\n", + *(ipclite->channel[core_id].rx_fifo->tail)); /* Increment the Global Channel Status for APPS and crashed core*/ ipclite_global_atomic_inc((ipclite_atomic_int32_t *) @@ -554,15 +778,24 @@ void ipclite_recover(enum ipcmem_host_type core_id) /* Update other cores about SSR */ for (host = 1; host < IPCMEM_NUM_HOSTS; host++) { - if (host != core_id) { + if (host != core_id && ipclite->ipcmem.toc->recovery.configured_core[host]) { ret = ipclite_ssr_update(host); - if (ret < 0) - pr_debug("Failed to send the SSR update %d\n", host); + if (ret < IPCLITE_SUCCESS) + IPCLITE_OS_LOG(IPCLITE_ERR, + "Failed to send SSR update to core : %d\n", host); else - pr_debug("SSR update sent to host %d\n", host); + IPCLITE_OS_LOG(IPCLITE_DBG, "SSR update sent to core %d\n", host); } } mutex_unlock(&ssr_mutex); + + /* Dump the debug information */ + if (ipclite_debug_dump & IPCLITE_DUMP_SSR) { + ipclite_dump_debug_struct(); + ipclite_dump_inmem_logs(); + } + + return; } EXPORT_SYMBOL(ipclite_recover); @@ -571,7 +804,7 @@ int ipclite_msg_send(int32_t proc_id, uint64_t data) int ret = 0; if (proc_id < 0 || proc_id >= IPCMEM_NUM_HOSTS) { - pr_err("Invalid proc_id %d\n", proc_id); + IPCLITE_OS_LOG(IPCLITE_ERR, "Invalid proc_id : %d\n", proc_id); return -EINVAL; } @@ -579,14 +812,16 @@ int ipclite_msg_send(int32_t proc_id, uint64_t data) if (ipclite->ipcmem.toc->toc_entry[IPCMEM_APPS][proc_id].status == CHANNEL_ACTIVE) { channel_status_info[proc_id] = CHANNEL_ACTIVE; } else { - pr_err("Cannot send msg to remote client. Channel inactive\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot Send, Core %d is Inactive\n", proc_id); return -IPCLITE_EINCHAN; } } ret = ipclite_tx(&ipclite->channel[proc_id], data, sizeof(data), IPCLITE_MSG_SIGNAL); - pr_debug("Message send completed with ret=%d\n", ret); + + IPCLITE_OS_LOG(IPCLITE_DBG, "Message send complete to core : %d signal : %d ret : %d\n", + proc_id, IPCLITE_MSG_SIGNAL, ret); return ret; } EXPORT_SYMBOL(ipclite_msg_send); @@ -594,13 +829,13 @@ EXPORT_SYMBOL(ipclite_msg_send); int ipclite_register_client(IPCLite_Client cb_func_ptr, void *priv) { if (!cb_func_ptr) { - pr_err("Invalid callback pointer\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "Invalid callback pointer\n"); return -EINVAL; } synx_client.callback = cb_func_ptr; synx_client.priv_data = priv; synx_client.reg_complete = 1; - pr_debug("Client Registration completed\n"); + IPCLITE_OS_LOG(IPCLITE_DBG, "Client Registration completed\n"); return 0; } EXPORT_SYMBOL(ipclite_register_client); @@ -610,7 +845,7 @@ int ipclite_test_msg_send(int32_t proc_id, uint64_t data) int ret = 0; if (proc_id < 0 || proc_id >= IPCMEM_NUM_HOSTS) { - pr_err("Invalid proc_id %d\n", proc_id); + IPCLITE_OS_LOG(IPCLITE_ERR, "Invalid proc_id : %d\n", proc_id); return -EINVAL; } @@ -618,14 +853,16 @@ int ipclite_test_msg_send(int32_t proc_id, uint64_t data) if (ipclite->ipcmem.toc->toc_entry[IPCMEM_APPS][proc_id].status == CHANNEL_ACTIVE) { channel_status_info[proc_id] = CHANNEL_ACTIVE; } else { - pr_err("Cannot send msg to remote client. Channel inactive\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot Send, Core %d is Inactive\n", proc_id); return -IPCLITE_EINCHAN; } } ret = ipclite_tx(&ipclite->channel[proc_id], data, sizeof(data), IPCLITE_TEST_SIGNAL); - pr_debug("Message send completed with ret=%d\n", ret); + + IPCLITE_OS_LOG(IPCLITE_DBG, "Test Msg send complete to core : %d signal : %d ret : %d\n", + proc_id, IPCLITE_TEST_SIGNAL, ret); return ret; } EXPORT_SYMBOL(ipclite_test_msg_send); @@ -633,13 +870,13 @@ EXPORT_SYMBOL(ipclite_test_msg_send); int ipclite_register_test_client(IPCLite_Client cb_func_ptr, void *priv) { if (!cb_func_ptr) { - pr_err("Invalid callback pointer\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "Invalid callback pointer\n"); return -EINVAL; } test_client.callback = cb_func_ptr; test_client.priv_data = priv; test_client.reg_complete = 1; - pr_debug("Test Client Registration Completed\n"); + IPCLITE_OS_LOG(IPCLITE_DBG, "Test Client Registration Completed\n"); return 0; } EXPORT_SYMBOL(ipclite_register_test_client); @@ -655,7 +892,7 @@ static int map_ipcmem(struct ipclite_info *ipclite, const char *name) np = of_parse_phandle(dev->of_node, name, 0); if (!np) { - pr_err("No %s specified\n", name); + IPCLITE_OS_LOG(IPCLITE_ERR, "No %s specified\n", name); return -EINVAL; } @@ -671,7 +908,7 @@ static int map_ipcmem(struct ipclite_info *ipclite, const char *name) if (!ipclite->ipcmem.mem.virt_base) return -ENOMEM; - pr_debug("aux_base = %lx, size=%d,virt_base=%p\n", + IPCLITE_OS_LOG(IPCLITE_DBG, "aux_base = %lx, size=%d,virt_base=%p\n", ipclite->ipcmem.mem.aux_base, ipclite->ipcmem.mem.size, ipclite->ipcmem.mem.virt_base); @@ -684,10 +921,10 @@ static void ipcmem_init(struct ipclite_mem *ipcmem) int i = 0; ipcmem->toc = ipcmem->mem.virt_base; - pr_debug("toc_base = %p\n", ipcmem->toc); + IPCLITE_OS_LOG(IPCLITE_DBG, "toc_base = %p\n", ipcmem->toc); ipcmem->toc->hdr.size = IPCMEM_TOC_SIZE; - pr_debug("toc->hdr.size = %d\n", ipcmem->toc->hdr.size); + IPCLITE_OS_LOG(IPCLITE_DBG, "toc->hdr.size = %d\n", ipcmem->toc->hdr.size); /*Fill in global partition details*/ ipcmem->toc->toc_entry_global = ipcmem_toc_global_partition_entry; @@ -695,13 +932,13 @@ static void ipcmem_init(struct ipclite_mem *ipcmem) ((char *)ipcmem->mem.virt_base + ipcmem_toc_global_partition_entry.base_offset); - pr_debug("base_offset =%x,ipcmem->global_partition = %p\n", + IPCLITE_OS_LOG(IPCLITE_DBG, "base_offset =%x,ipcmem->global_partition = %p\n", ipcmem_toc_global_partition_entry.base_offset, ipcmem->global_partition); ipcmem->global_partition->hdr = global_partition_hdr; - pr_debug("hdr.type = %x,hdr.offset = %x,hdr.size = %d\n", + IPCLITE_OS_LOG(IPCLITE_DBG, "hdr.type = %x,hdr.offset = %x,hdr.size = %d\n", ipcmem->global_partition->hdr.partition_type, ipcmem->global_partition->hdr.region_offset, ipcmem->global_partition->hdr.region_size); @@ -710,7 +947,7 @@ static void ipcmem_init(struct ipclite_mem *ipcmem) for (i = 0; i < MAX_PARTITION_COUNT; i++) { host0 = ipcmem_toc_partition_entries[i].host0; host1 = ipcmem_toc_partition_entries[i].host1; - pr_debug("host0 = %d, host1=%d\n", host0, host1); + IPCLITE_OS_LOG(IPCLITE_DBG, "host0 = %d, host1=%d\n", host0, host1); ipcmem->toc->toc_entry[host0][host1] = ipcmem_toc_partition_entries[i]; ipcmem->toc->toc_entry[host1][host0] = ipcmem_toc_partition_entries[i]; @@ -741,7 +978,7 @@ static void ipcmem_init(struct ipclite_mem *ipcmem) ((char *)ipcmem->mem.virt_base + ipcmem_toc_partition_entries[i].base_offset); - pr_debug("partition[%d] = %p,partition_base_offset[%d]=%lx\n", + IPCLITE_OS_LOG(IPCLITE_DBG, "partition[%d] = %p,partition_base_offset[%d]=%lx\n", i, ipcmem->partition[i], i, ipcmem_toc_partition_entries[i].base_offset); @@ -750,7 +987,7 @@ static void ipcmem_init(struct ipclite_mem *ipcmem) else ipcmem->partition[i]->hdr = default_partition_hdr; - pr_debug("hdr.type = %x,hdr.offset = %x,hdr.size = %d\n", + IPCLITE_OS_LOG(IPCLITE_DBG, "hdr.type = %x,hdr.offset = %x,hdr.size = %d\n", ipcmem->partition[i]->hdr.type, ipcmem->partition[i]->hdr.desc_offset, ipcmem->partition[i]->hdr.desc_size); @@ -760,7 +997,7 @@ static void ipcmem_init(struct ipclite_mem *ipcmem) wmb(); ipcmem->toc->hdr.init_done = IPCMEM_INIT_COMPLETED; - pr_debug("Ipcmem init completed\n"); + IPCLITE_OS_LOG(IPCLITE_DBG, "Ipcmem init completed\n"); } @@ -784,9 +1021,10 @@ static int ipclite_channel_irq_init(struct device *parent, struct device_node *n { int ret = 0; u32 index; - char strs[5][9] = {"msg", "mem-init", "version", "test", "ssr"}; struct ipclite_irq_info *irq_info; struct device *dev; + char strs[MAX_CHANNEL_SIGNALS][IPCLITE_SIGNAL_LABEL_SIZE] = { + "msg", "mem-init", "version", "test", "ssr", "debug"}; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) @@ -795,10 +1033,10 @@ static int ipclite_channel_irq_init(struct device *parent, struct device_node *n dev->parent = parent; dev->of_node = node; dev_set_name(dev, "%s:%pOFn", dev_name(parent->parent), node); - pr_debug("Registering %s device\n", dev_name(parent->parent)); + IPCLITE_OS_LOG(IPCLITE_DBG, "Registering %s device\n", dev_name(parent->parent)); ret = device_register(dev); if (ret) { - pr_err("failed to register ipclite child node\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "failed to register ipclite child node\n"); put_device(dev); return ret; } @@ -806,36 +1044,36 @@ static int ipclite_channel_irq_init(struct device *parent, struct device_node *n ret = of_property_read_u32(dev->of_node, "index", &index); if (ret) { - pr_err("failed to parse index\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "failed to parse index\n"); goto err_dev; } irq_info = &channel->irq_info[index]; - pr_debug("irq_info[%d]=%p\n", index, irq_info); + IPCLITE_OS_LOG(IPCLITE_DBG, "irq_info[%d]=%p\n", index, irq_info); irq_info->mbox_client.dev = dev; irq_info->mbox_client.knows_txdone = true; irq_info->mbox_chan = mbox_request_channel(&irq_info->mbox_client, 0); - pr_debug("irq_info[%d].mbox_chan=%p\n", index, irq_info->mbox_chan); + IPCLITE_OS_LOG(IPCLITE_DBG, "irq_info[%d].mbox_chan=%p\n", index, irq_info->mbox_chan); if (IS_ERR(irq_info->mbox_chan)) { if (PTR_ERR(irq_info->mbox_chan) != -EPROBE_DEFER) - pr_err("failed to acquire IPC channel\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "failed to acquire IPC channel\n"); goto err_dev; } snprintf(irq_info->irqname, 32, "ipclite-signal-%s", strs[index]); irq_info->irq = of_irq_get(dev->of_node, 0); - pr_debug("irq[%d] = %d\n", index, irq_info->irq); + IPCLITE_OS_LOG(IPCLITE_DBG, "irq[%d] = %d\n", index, irq_info->irq); irq_info->signal_id = index; ret = devm_request_irq(dev, irq_info->irq, ipclite_intr, IRQF_NO_SUSPEND | IRQF_SHARED, irq_info->irqname, irq_info); if (ret) { - pr_err("failed to request IRQ\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "failed to request IRQ\n"); goto err_dev; } - pr_debug("Interrupt init completed, ret = %d\n", ret); + IPCLITE_OS_LOG(IPCLITE_DBG, "Interrupt init completed, ret = %d\n", ret); return 0; err_dev: @@ -848,6 +1086,12 @@ int32_t get_global_partition_info(struct global_region_info *global_ipcmem) { struct ipcmem_global_partition *global_partition; + /* Check added to verify ipclite is initialized */ + if (!ipclite) { + IPCLITE_OS_LOG(IPCLITE_ERR, "IPCLite not initialized\n"); + return -ENOMEM; + } + if (!global_ipcmem) return -EINVAL; @@ -856,7 +1100,7 @@ int32_t get_global_partition_info(struct global_region_info *global_ipcmem) global_partition->hdr.region_offset); global_ipcmem->size = (size_t)(global_partition->hdr.region_size); - pr_debug("base = %p, size=%lx\n", global_ipcmem->virt_base, + IPCLITE_OS_LOG(IPCLITE_DBG, "base = %p, size=%lx\n", global_ipcmem->virt_base, global_ipcmem->size); return 0; } @@ -871,7 +1115,7 @@ static struct ipcmem_partition_header *get_ipcmem_partition_hdr(struct ipclite_m static void ipclite_channel_release(struct device *dev) { - pr_info("Releasing ipclite channel\n"); + IPCLITE_OS_LOG(IPCLITE_INFO, "Releasing ipclite channel\n"); kfree(dev); } @@ -901,10 +1145,10 @@ static int ipclite_channel_init(struct device *parent, dev->of_node = node; dev->release = ipclite_channel_release; dev_set_name(dev, "%s:%pOFn", dev_name(parent->parent), node); - pr_debug("Registering %s device\n", dev_name(parent->parent)); + IPCLITE_OS_LOG(IPCLITE_DBG, "Registering %s device\n", dev_name(parent->parent)); ret = device_register(dev); if (ret) { - pr_err("failed to register ipclite device\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "failed to register ipclite device\n"); put_device(dev); kfree(dev); return ret; @@ -918,7 +1162,7 @@ static int ipclite_channel_init(struct device *parent, dev_err(dev, "failed to parse qcom,remote-pid\n"); goto err_put_dev; } - pr_debug("remote_pid = %d, local_pid=%d\n", remote_pid, local_pid); + IPCLITE_OS_LOG(IPCLITE_DBG, "remote_pid = %d, local_pid=%d\n", remote_pid, local_pid); ipclite_hw_mutex = devm_kzalloc(dev, sizeof(*ipclite_hw_mutex), GFP_KERNEL); if (!ipclite_hw_mutex) { @@ -940,13 +1184,13 @@ static int ipclite_channel_init(struct device *parent, ret = -ENOMEM; goto err_put_dev; } - pr_debug("rx_fifo = %p, tx_fifo=%p\n", rx_fifo, tx_fifo); + IPCLITE_OS_LOG(IPCLITE_DBG, "rx_fifo = %p, tx_fifo=%p\n", rx_fifo, tx_fifo); partition_hdr = get_ipcmem_partition_hdr(ipclite->ipcmem, local_pid, remote_pid); - pr_debug("partition_hdr = %p\n", partition_hdr); + IPCLITE_OS_LOG(IPCLITE_DBG, "partition_hdr = %p\n", partition_hdr); descs = (u32 *)((char *)partition_hdr + partition_hdr->desc_offset); - pr_debug("descs = %p\n", descs); + IPCLITE_OS_LOG(IPCLITE_DBG, "descs = %p\n", descs); if (local_pid < remote_pid) { tx_fifo->fifo = (char *)partition_hdr + partition_hdr->fifo0_offset; @@ -999,13 +1243,13 @@ static int ipclite_channel_init(struct device *parent, ret = ipclite_channel_irq_init(dev, child, &ipclite->channel[remote_pid]); if (ret) { - pr_err("irq setup for ipclite channel failed\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "irq setup for ipclite channel failed\n"); goto err_put_dev; } } ipclite->ipcmem.toc->recovery.configured_core[remote_pid] = CONFIGURED_CORE; - pr_debug("Channel init completed, ret = %d\n", ret); + IPCLITE_OS_LOG(IPCLITE_DBG, "Channel init completed, ret = %d\n", ret); return ret; err_put_dev: @@ -1021,7 +1265,177 @@ static void probe_subsystem(struct device *dev, struct device_node *np) ret = ipclite_channel_init(dev, np); if (ret) - pr_err("IPCLite Channel init failed\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "IPCLite Channel init failed\n"); +} + +static ssize_t ipclite_dbg_lvl_write(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int ret = 0, host = 0; + + /* Parse the string from Sysfs Interface */ + ret = kstrtoint(buf, 0, &ipclite_debug_level); + if (ret < IPCLITE_SUCCESS) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Error parsing the sysfs value"); + return -IPCLITE_FAILURE; + } + + /* Check if debug structure is initialized */ + if (!ipclite_dbg_info) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Debug structures not initialized\n"); + return -ENOMEM; + } + + /* Update the Global Debug variable for FW cores */ + ipclite_dbg_info->debug_level = ipclite_debug_level; + + /* Memory Barrier to make sure all writes are completed */ + wmb(); + + /* Signal other cores for updating the debug information */ + for (host = 1; host < IPCMEM_NUM_HOSTS; host++) { + if (ipclite->ipcmem.toc->recovery.configured_core[host]) { + ret = ipclite_send_debug_info(host); + if (ret < IPCLITE_SUCCESS) + IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to send the debug info %d\n", + host); + else + IPCLITE_OS_LOG(IPCLITE_DBG, "Debug info sent to host %d\n", host); + } + } + + return count; +} + +static ssize_t ipclite_dbg_ctrl_write(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int ret = 0, host = 0; + + /* Parse the string from Sysfs Interface */ + ret = kstrtoint(buf, 0, &ipclite_debug_control); + if (ret < IPCLITE_SUCCESS) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Error parsing the sysfs value"); + return -IPCLITE_FAILURE; + } + + /* Check if debug structures are initialized */ + if (!ipclite_dbg_info || !ipclite_dbg_struct || !ipclite_dbg_inmem) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Debug structures not initialized\n"); + return -ENOMEM; + } + + /* Update the Global Debug variable for FW cores */ + ipclite_dbg_info->debug_control = ipclite_debug_control; + + /* Memory Barrier to make sure all writes are completed */ + wmb(); + + /* Signal other cores for updating the debug information */ + for (host = 1; host < IPCMEM_NUM_HOSTS; host++) { + if (ipclite->ipcmem.toc->recovery.configured_core[host]) { + ret = ipclite_send_debug_info(host); + if (ret < IPCLITE_SUCCESS) + IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to send the debug info %d\n", + host); + else + IPCLITE_OS_LOG(IPCLITE_DBG, "Debug info sent to host %d\n", host); + } + } + + return count; +} + +static ssize_t ipclite_dbg_dump_write(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int ret = 0; + + /* Parse the string from Sysfs Interface */ + ret = kstrtoint(buf, 0, &ipclite_debug_dump); + if (ret < IPCLITE_SUCCESS) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Error parsing the sysfs value"); + return -IPCLITE_FAILURE; + } + + /* Check if debug structures are initialized */ + if (!ipclite_dbg_info || !ipclite_dbg_struct || !ipclite_dbg_inmem) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Debug structures not initialized\n"); + return -ENOMEM; + } + + /* Dump the debug information */ + if (ipclite_debug_dump & IPCLITE_DUMP_DBG_STRUCT) + ipclite_dump_debug_struct(); + + if (ipclite_debug_dump & IPCLITE_DUMP_INMEM_LOG) + ipclite_dump_inmem_logs(); + + return count; +} + +struct kobj_attribute sysfs_dbg_lvl = __ATTR(ipclite_debug_level, 0660, + NULL, ipclite_dbg_lvl_write); +struct kobj_attribute sysfs_dbg_ctrl = __ATTR(ipclite_debug_control, 0660, + NULL, ipclite_dbg_ctrl_write); +struct kobj_attribute sysfs_dbg_dump = __ATTR(ipclite_debug_dump, 0660, + NULL, ipclite_dbg_dump_write); + +static int ipclite_debug_sysfs_setup(void) +{ + /* Creating a directory in /sys/kernel/ */ + sysfs_kobj = kobject_create_and_add("ipclite", kernel_kobj); + if (!sysfs_kobj) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot create and add sysfs directory\n"); + return -IPCLITE_FAILURE; + } + + /* Creating sysfs files/interfaces for debug */ + if (sysfs_create_file(sysfs_kobj, &sysfs_dbg_lvl.attr)) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot create sysfs debug level file\n"); + return -IPCLITE_FAILURE; + } + + if (sysfs_create_file(sysfs_kobj, &sysfs_dbg_ctrl.attr)) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot create sysfs debug control file\n"); + return -IPCLITE_FAILURE; + } + + if (sysfs_create_file(sysfs_kobj, &sysfs_dbg_dump.attr)) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot create sysfs debug dump file\n"); + return -IPCLITE_FAILURE; + } + + return IPCLITE_SUCCESS; +} + +static int ipclite_debug_info_setup(void) +{ + /* Setting up the Debug Structures */ + ipclite_dbg_info = (struct ipclite_debug_info *)(((char *)ipclite->ipcmem.mem.virt_base + + ipclite->ipcmem.mem.size) - IPCLITE_DEBUG_SIZE); + if (!ipclite_dbg_info) + return -EADDRNOTAVAIL; + + ipclite_dbg_struct = (struct ipclite_debug_struct *) + (((char *)ipclite_dbg_info + IPCLITE_DEBUG_INFO_SIZE) + + (sizeof(*ipclite_dbg_struct) * IPCMEM_APPS)); + if (!ipclite_dbg_struct) + return -EADDRNOTAVAIL; + + ipclite_dbg_inmem = (struct ipclite_debug_inmem_buf *) + (((char *)ipclite_dbg_info + IPCLITE_DEBUG_INFO_SIZE) + + (sizeof(*ipclite_dbg_struct) * IPCMEM_NUM_HOSTS)); + + if (!ipclite_dbg_inmem) + return -EADDRNOTAVAIL; + + IPCLITE_OS_LOG(IPCLITE_DBG, "virtual_base_ptr = %p total_size : %d debug_size : %d\n", + ipclite->ipcmem.mem.virt_base, ipclite->ipcmem.mem.size, IPCLITE_DEBUG_SIZE); + IPCLITE_OS_LOG(IPCLITE_DBG, "dbg_info : %p dbg_struct : %p dbg_inmem : %p\n", + ipclite_dbg_info, ipclite_dbg_struct, ipclite_dbg_inmem); + + return IPCLITE_SUCCESS; } static int ipclite_probe(struct platform_device *pdev) @@ -1048,22 +1462,23 @@ static int ipclite_probe(struct platform_device *pdev) ret = hwlock_id; goto error; } - pr_debug("Hwlock id retrieved, hwlock_id=%d\n", hwlock_id); + IPCLITE_OS_LOG(IPCLITE_DBG, "Hwlock id retrieved, hwlock_id=%d\n", hwlock_id); ipclite->hwlock = hwspin_lock_request_specific(hwlock_id); if (!ipclite->hwlock) { - pr_err("Failed to assign hwlock_id\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to assign hwlock_id\n"); ret = -ENXIO; goto error; } - pr_debug("Hwlock id assigned successfully, hwlock=%p\n", ipclite->hwlock); + IPCLITE_OS_LOG(IPCLITE_DBG, "Hwlock id assigned successfully, hwlock=%p\n", + ipclite->hwlock); /* Initializing Local Mutex Lock for SSR functionality */ mutex_init(&ssr_mutex); ret = map_ipcmem(ipclite, "memory-region"); if (ret) { - pr_err("failed to map ipcmem\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "failed to map ipcmem\n"); goto release; } mem = &(ipclite->ipcmem.mem); @@ -1071,12 +1486,26 @@ static int ipclite_probe(struct platform_device *pdev) ret = set_ipcmem_access_control(ipclite); if (ret) { - pr_err("failed to set access control policy\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "failed to set access control policy\n"); goto release; } ipcmem_init(&ipclite->ipcmem); + /* Set up sysfs for debug */ + ret = ipclite_debug_sysfs_setup(); + if (ret != IPCLITE_SUCCESS) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to Set up IPCLite Debug Sysfs\n"); + goto release; + } + + /* Mapping Debug Memory */ + ret = ipclite_debug_info_setup(); + if (ret != IPCLITE_SUCCESS) { + IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to Set up IPCLite Debug Structures\n"); + goto release; + } + /* Setup Channel for each Remote Subsystem */ for_each_available_child_of_node(pn, cn) probe_subsystem(&pdev->dev, cn); @@ -1099,7 +1528,7 @@ static int ipclite_probe(struct platform_device *pdev) GLOBAL_ATOMICS_DISABLED; } - pr_debug("global_atomic_support : %d\n", + IPCLITE_OS_LOG(IPCLITE_DBG, "global_atomic_support : %d\n", ipclite->ipcmem.toc->ipclite_features.global_atomic_support); /* hw mutex callbacks */ @@ -1112,7 +1541,11 @@ static int ipclite_probe(struct platform_device *pdev) /* initialize hwlock owner to invalid host */ ipclite->ipcmem.toc->recovery.global_atomic_hwlock_owner = IPCMEM_INVALID_HOST; - pr_info("IPCLite probe completed successfully\n"); + /* Update the Global Debug variable for FW cores */ + ipclite_dbg_info->debug_level = ipclite_debug_level; + ipclite_dbg_info->debug_control = ipclite_debug_control; + + IPCLITE_OS_LOG(IPCLITE_INFO, "IPCLite probe completed successfully\n"); return ret; mem_release: @@ -1125,7 +1558,7 @@ mem_release: release: kfree(ipclite); error: - pr_err("IPCLite probe failed\n"); + IPCLITE_OS_LOG(IPCLITE_ERR, "IPCLite probe failed\n"); return ret; } diff --git a/msm/synx/ipclite.h b/msm/synx/ipclite.h index 4d0a5d7232..3c1960ae90 100644 --- a/msm/synx/ipclite.h +++ b/msm/synx/ipclite.h @@ -14,7 +14,7 @@ #define ACTIVE_CHANNEL 0x1 #define IPCMEM_TOC_SIZE (4*1024) -#define MAX_CHANNEL_SIGNALS 5 +#define MAX_CHANNEL_SIGNALS 6 #define MAX_PARTITION_COUNT 11 /*11 partitions other than global partition*/ @@ -23,6 +23,7 @@ #define IPCLITE_VERSION_SIGNAL 2 #define IPCLITE_TEST_SIGNAL 3 #define IPCLITE_SSR_SIGNAL 4 +#define IPCLITE_DEBUG_SIGNAL 5 /** Flag definitions for the entries */ #define IPCMEM_TOC_ENTRY_FLAGS_ENABLE_READ_PROTECTION (0x01) @@ -45,8 +46,97 @@ #define CONFIGURED_CORE 1 +#define IPCLITE_DEBUG_SIZE (64 * 1024) +#define IPCLITE_DEBUG_INFO_SIZE 256 +#define IPCLITE_CORE_DBG_LABEL "APSS:" +#define IPCLITE_LOG_MSG_SIZE 100 +#define IPCLITE_LOG_BUF_SIZE 512 +#define IPCLITE_DBG_LABEL_SIZE 5 +#define IPCLITE_SIGNAL_LABEL_SIZE 10 +#define PREV_INDEX 2 + +#define IPCLITE_OS_LOG(__level, __fmt, arg...) \ + do { \ + if (ipclite_debug_level & __level) { \ + if (ipclite_debug_control & IPCLITE_DMESG_LOG) { \ + pr_info(IPCLITE_CORE_DBG_LABEL "%s:"__fmt, \ + ipclite_dbg_label[__level], ## arg); \ + } \ + if (ipclite_debug_control & IPCLITE_INMEM_LOG) { \ + IPCLITE_OS_INMEM_LOG(IPCLITE_CORE_DBG_LABEL "%s:"__fmt, \ + ipclite_dbg_label[__level], ## arg); \ + } \ + } \ + } while (0) + /*IPCMEM Structure Definitions*/ +enum ipclite_debug_level { + IPCLITE_ERR = 0x0001, + IPCLITE_WARN = 0x0002, + IPCLITE_INFO = 0x0004, + IPCLITE_DBG = 0x0008, +}; + +enum ipclite_debug_control { + IPCLITE_DMESG_LOG = 0x0001, + IPCLITE_DBG_STRUCT = 0x0002, + IPCLITE_INMEM_LOG = 0x0004, +}; + +enum ipclite_debug_dump { + IPCLITE_DUMP_DBG_STRUCT = 0x0001, + IPCLITE_DUMP_INMEM_LOG = 0x0002, + IPCLITE_DUMP_SSR = 0x0004, +}; + +static const char ipclite_dbg_label[][IPCLITE_DBG_LABEL_SIZE] = { + [IPCLITE_ERR] = "err", + [IPCLITE_WARN] = "warn", + [IPCLITE_INFO] = "info", + [IPCLITE_DBG] = "dbg" +}; + +struct ipclite_debug_info_host { + uint32_t numsig_sent; //no. of signals sent from the core + uint32_t numsig_recv; //no. of signals received on the core + uint32_t tx_wr_index; //write index of tx queue + uint32_t tx_rd_index; //read index of tx queue + uint32_t rx_wr_index; //write index of rx queue + uint32_t rx_rd_index; //read index of rx queue + uint32_t num_intr; //no. of interrupts received on the core + uint32_t prev_tx_wr_index[PREV_INDEX]; //previous write index of tx queue + uint32_t prev_tx_rd_index[PREV_INDEX]; //previous read index of tx queue + uint32_t prev_rx_wr_index[PREV_INDEX]; //previous write index of rx queue + uint32_t prev_rx_rd_index[PREV_INDEX]; //previous read index of rx queue +}; + +struct ipclite_debug_info_overall { + uint32_t total_numsig_sent; //total no. of signals sent + uint32_t total_numsig_recv; //total no. of signals received + uint32_t last_sent_host_id; //last signal sent to host + uint32_t last_recv_host_id; //last signal received from host + uint32_t last_sigid_sent; //last sent signal id + uint32_t last_sigid_recv; //last received signal id +}; + +struct ipclite_debug_info { + uint32_t debug_version; + uint32_t debug_level; + uint32_t debug_control; + uint32_t debug_dump; + uint32_t debug_log_index; +}; + +struct ipclite_debug_inmem_buf { + char IPCLITELog[IPCLITE_LOG_BUF_SIZE][IPCLITE_LOG_MSG_SIZE]; +}; + +struct ipclite_debug_struct { + struct ipclite_debug_info_overall dbg_info_overall; + struct ipclite_debug_info_host dbg_info_host[IPCMEM_NUM_HOSTS]; +}; + struct ipclite_features { uint32_t global_atomic_support; uint32_t version_finalised; @@ -130,13 +220,13 @@ struct ipclite_fifo { size_t (*avail)(struct ipclite_fifo *fifo); void (*peak)(struct ipclite_fifo *fifo, - void *data, size_t count); + void *data, size_t count); void (*advance)(struct ipclite_fifo *fifo, - size_t count); + size_t count, uint32_t core_id); void (*write)(struct ipclite_fifo *fifo, - const void *data, size_t dlen); + const void *data, size_t dlen, uint32_t core_id, uint32_t signal_id); void (*reset)(struct ipclite_fifo *fifo); }; diff --git a/msm/synx/ipclite_client.h b/msm/synx/ipclite_client.h index 37849db432..419d9e2330 100644 --- a/msm/synx/ipclite_client.h +++ b/msm/synx/ipclite_client.h @@ -30,7 +30,9 @@ enum ipcmem_host_type { /** * IPCLite return codes */ -#define IPCLITE_EINCHAN 9 /**< Inactive Channel */ +#define IPCLITE_SUCCESS 0 /*< Success > */ +#define IPCLITE_FAILURE 1 /*< Failure > */ +#define IPCLITE_EINCHAN 9 /*< Inactive Channel */ struct global_region_info { void *virt_base;