void IPC_FreeBuffer(IPC_Buffer Buffer) { IPC_Buffer_T *BufferPtr = IPC_BufferToPtr(Buffer); IPC_CPU_ID_T OwningCpu; if (BufferPtr == 0) { IPC_TRACE(IPC_Channel_Error, "IPC_FreeBuffer", "Invalid Buffer %08X", Buffer, 0, 0, 0); return; } if (BufferPtr->StatusCode == IPC_BUFFER_STATUS_FREE) { IPC_TRACE(IPC_Channel_Error, "IPC_FreeBuffer", "Repeated Free Buffer %08X", Buffer, 0, 0, 0); return; } OwningCpu = IPC_PoolOwningCpu(BufferPtr->Pool); BufferPtr->TimeStampFree = TIMER_GetValue(); BufferPtr->StatusCode = IPC_BUFFER_STATUS_FREE; if (OwningCpu == IPC_SM_CURRENT_CPU) { IPC_TRACE(IPC_Channel_Buffer, "IPC_FreeBuffer", "Buffer %08X, ID %d Same CPU ", Buffer, BufferPtr->BufferId, 0, 0); IPC_BufferReturn(Buffer, BufferPtr->Pool); } else { IPC_TRACE(IPC_Channel_Buffer, "IPC_FreeBuffer", "Buffer %08X, ID %d Other CPU", Buffer, BufferPtr->BufferId, 0, 0); IPC_SmFreeBuffer(Buffer, OwningCpu); } }
const char *show_box_cb(guiObject_t *obj, const void *data) { (void)obj; u8 idx = (long)data; #if HAS_RTC if (idx <= NUM_RTC) { u32 time = RTC_GetValue(); idx == 1 ? RTC_GetTimeFormatted(tempstring, time) : RTC_GetDateFormatted(tempstring, time); return tempstring; } #endif if (idx - NUM_RTC <= NUM_TIMERS) { TIMER_SetString(tempstring, TIMER_GetValue(idx - NUM_RTC - 1)); } else if(idx - NUM_RTC - NUM_TIMERS <= NUM_TELEM) { TELEMETRY_GetValueStr(tempstring, idx - NUM_RTC - NUM_TIMERS); } else { unsigned channel = idx - (NUM_RTC + NUM_TIMERS + NUM_TELEM + 1); s16 val_raw = MIXER_GetChannel(channel, APPLY_SAFETY | APPLY_SCALAR); s16 val_scale = MIXER_GetChannelDisplayScale(channel); const char* val_format = MIXER_GetChannelDisplayFormat(channel); sprintf(tempstring, val_format, val_raw/val_scale); } return tempstring; }
IPC_ReturnCode_T IPC_SendBuffer(IPC_Buffer Buffer, IPC_Priority_T Priority) { IPC_Buffer_T *BufferPtr = IPC_BufferToPtr(Buffer); IPC_TRACE(IPC_Channel_Buffer, "IPC_SendBuffer", "Buffer %d (%08X), Priority %d", BufferPtr->BufferId, Buffer, Priority, 0); if (BufferPtr == 0) { IPC_TRACE(IPC_Channel_Error, "IPC_SendBuffer", "Invalid Buffer %08X", Buffer, 0, 0, 0); return IPC_ERROR; } BufferPtr->TimeStampSend = TIMER_GetValue(); BufferPtr->StatusCode = IPC_BUFFER_STATUS_SENT; IPC_PoolAddBytesSent(BufferPtr->Pool, BufferPtr->DataSize + BufferPtr->HeaderSize); #ifdef IPC_BUFFER_STATS /* Debug output - turned off by default for performance */ if (BufferPtr->BufferId == 0 && 0 == LISR_Active) IPC_PoolDumpStats(BufferPtr->Pool); #endif IPC_SmSendBuffer(Buffer); return IPC_OK; }
/**************************************************************** * Called from the IPC interrupt service thread in ipc_server.c * to check if CP has crashed. * * @return int 0 if CP not crashed, 1 otherwise * *****************************************************************/ int IpcCPCrashCheck(void) { IPC_CrashCode_T CpCrashReason; IPC_U32 *Dump; crashCount = 0; if (!SmLocalControl.ConfiguredReported) { IPC_DEBUG(DBG_TRACE, "IPC Not Initialised\n"); return 0; } /* Get the crash reason and crash dump location */ CpCrashReason = SmLocalControl.SmControl->CrashCode; Dump = (void *)SmLocalControl.SmControl->CrashDump; if (IPC_CP_NOT_CRASHED != CpCrashReason && IPC_CP_MAX_CRASH_CODE > CpCrashReason && NULL != Dump) { crashCount++; IPC_DEBUG(DBG_ERROR, "CP Crashed!! CP Ticks[%ld] reason:%d count:%d Dump:0x%X\n", TIMER_GetValue(), CpCrashReason, crashCount, (unsigned int)Dump); if (crashCount > 1) return 0; return 1; } return 0; }
static void IPC_RaiseInterrupt(void) { IPC_U32 Cpu = IPC_CPU_ID_INDEX(IPC_SM_CURRENT_CPU); IPC_U32 IrqRaised = SmLocalControl.SmControl->IrqCounts[Cpu].IrqRaised; SmLocalControl.SmControl->IrqTime[Cpu][IrqRaised % 4].IrqRaiseTime = TIMER_GetValue(); SmLocalControl.SmControl->IrqCounts[Cpu].IrqRaised++; (*SmLocalControl.RaiseInterrupt)(); }
int RpcLog_DebugPrintf(char* fmt, ...) { #if 0 // blocked RPC LOG - jaesub.kim #ifdef CONFIG_BRCM_UNIFIED_LOGGING va_list ap; va_start(ap, fmt); vsnprintf(buf, MAX_BUF_SIZE, fmt, ap); va_end(ap); KRIL_DEBUG(DBG_INFO, "TS[%ld]%s\n", TIMER_GetValue(), buf); #else if(IsBasicCapi2LoggingEnable()) { va_list ap; va_start(ap, fmt); vsnprintf(buf, MAX_BUF_SIZE, fmt, ap); va_end(ap); pr_info("TS[%ld]%s",TIMER_GetValue(),buf); } #endif #endif return 1; }
void IPC_ApSleepModeSet(IPC_Boolean inSleep) { static IPC_U32 sleepCount = 0; static IPC_U32 resumeCount = 0; if (!inSleep) { IPC_AlignTime(); SmLocalControl.SmControl->ApSleepTime[resumeCount % 4].ResumeTime = TIMER_GetValue(); resumeCount ++; } else { SmLocalControl.SmControl->ApSleepTime[sleepCount % 4].SleepTime = TIMER_GetValue(); sleepCount ++; } IPC_TRACE(IPC_Channel_General, "IPC_ApSleepModeSet", "state %d time %u", inSleep, TIMER_GetValue(), 0, 0); }
s32 get_boxval(u8 idx) { #if HAS_RTC if (idx <= NUM_RTC) { u32 time = RTC_GetValue(); return idx == 1 ? RTC_GetTimeValue(time) : RTC_GetDateValue(time); } #endif if (idx - NUM_RTC <= NUM_TIMERS) return TIMER_GetValue(idx - NUM_RTC - 1); if(idx - NUM_RTC - NUM_TIMERS <= NUM_TELEM) return TELEMETRY_GetValue(idx - NUM_RTC - NUM_TIMERS); return RANGE_TO_PCT(MIXER_GetChannel(idx - (NUM_RTC + NUM_TIMERS + NUM_TELEM + 1), APPLY_SAFETY | APPLY_SCALAR)); }
const char *show_box_cb(guiObject_t *obj, const void *data) { (void)obj; u8 idx = (long)data; #if HAS_RTC if (idx <= NUM_RTC) { u32 time = RTC_GetValue(); idx == 1 ? RTC_GetTimeFormatted(tempstring, time) : RTC_GetDateFormatted(tempstring, time); return tempstring; } #endif if (idx - NUM_RTC <= NUM_TIMERS) { TIMER_SetString(tempstring, TIMER_GetValue(idx - NUM_RTC - 1)); } else if(idx - NUM_RTC - NUM_TIMERS <= NUM_TELEM) { TELEMETRY_GetValueStr(tempstring, idx - NUM_RTC - NUM_TIMERS); } else { sprintf(tempstring, "%3d%%", RANGE_TO_PCT(MIXER_GetChannel(idx - (NUM_RTC + NUM_TIMERS + NUM_TELEM + 1), APPLY_SAFETY | APPLY_SCALAR))); } return tempstring; }
void IPC_UpdateIrqStats(void) { IPC_U32 Cpu, PeerCpu; IPC_U32 IrqHandled, PeerIrqRaised; Cpu = IPC_CPU_ID_INDEX(IPC_SM_CURRENT_CPU); if (IPC_SM_CURRENT_CPU == IPC_AP_CPU) { PeerCpu = IPC_CPU_ID_INDEX(IPC_CP_CPU); } else { PeerCpu = IPC_CPU_ID_INDEX(IPC_AP_CPU); } IrqHandled = SmLocalControl.SmControl->IrqCounts[Cpu].IrqHandled; PeerIrqRaised = SmLocalControl.SmControl->IrqCounts[PeerCpu].IrqRaised; SmLocalControl.SmControl->IrqTime[Cpu][IrqHandled % 4].IrqHandleTime = TIMER_GetValue(); // save a copy of IRQ raise time to compare with IRQ handle time SmLocalControl.SmControl->IrqTime[Cpu][IrqHandled % 4].IrqRaiseTimeCopy = SmLocalControl.SmControl->IrqTime[PeerCpu][(PeerIrqRaised + 3) % 4].IrqRaiseTime; SmLocalControl.SmControl->IrqCounts[Cpu].IrqHandled++; }
/****************************************************************** * Utility function to retrieve full crash log from CP via simple * handshake protocol. * * ********************************************************************/ void DUMP_CP_assert_log(void) { UInt32 t1, i, size, retryCount; UInt8 *p; UInt32 packetCount = 0; void __iomem *AssertLogVAddr = NULL; struct file *sdDumpFile = NULL; int cpReset = SmLocalControl.SmControl->CrashCode == IPC_CP_SILENT_RESET_READY; /* put logging driver into crash dump mode; messages will be sent * straight out to MTT via RNDIS (or dump file) instead of buffering * in RING buffer (flood of crash dump info overloads ring buffer * otherwise,and we lose a lot of crash dump info) * NOTE: crash dump is put into SD by default; if SD file fails to open, * then we'll try sending it out RNDIS */ BCMLOG_StartCpCrashDump(sdDumpFile, cpReset); /* only grab RAM dump for CP reset case */ if (!cpReset) { retryCount = 0; while (1) { t1 = TIMER_GetValue(); /* signal to CP that we're ready to rx crash log... */ SmLocalControl.SmControl->CrashCode = IPC_AP_CLEAR_TO_SEND; /* wait for CP to "dump"; CrashCode field will be * set to physical address of current assert buf */ while (SmLocalControl.SmControl->CrashCode == IPC_AP_CLEAR_TO_SEND) { for (i = 0; i < 256; i++) ; if (TIMER_GetValue() - t1 > TICKS_ONE_SECOND * 20) break; } /* check for time out */ if (SmLocalControl.SmControl->CrashCode == IPC_AP_CLEAR_TO_SEND) { if (retryCount < MAX_CP_DUMP_RETRIES) { retryCount++; IPC_DEBUG( DBG_TRACE, "timeout %d, trying again..\n", (int)retryCount); continue; } else { /* no response from CP, * so get out of here */ IPC_DEBUG( DBG_ERROR, "Abort --- max retries %d reached\n", (int)retryCount); break; } } /* reset retry counter */ retryCount = 0; /* get virtual address of CP assert buffer */ AssertLogVAddr = ioremap_nocache( (UInt32) (SmLocalControl.SmControl->CrashCode), ASSERT_BUF_SIZE); if (NULL == AssertLogVAddr) { IPC_DEBUG(DBG_ERROR, "ioremap_nocache failed in DUMP_CP_assert_log\n"); break; } p = (UInt8 *)AssertLogVAddr; /* number of bytes in assert buffer */ size = (p[0] << 8) + p[1]; /* size of 0 means CP is done dumping assert log */ if (size == 0) { IPC_DEBUG(DBG_ERROR, "assert log size 0, exiting, packetCount:0x%x\n", (int)packetCount); iounmap(AssertLogVAddr); AssertLogVAddr = NULL; break; } /* sanity check for too beaucoup... */ if (size > ASSERT_BUF_SIZE - 2) { IPC_DEBUG(DBG_ERROR, "Abort --- improper size [%08x]=%d\n", SmLocalControl.SmControl->CrashCode, (int)size); iounmap(AssertLogVAddr); AssertLogVAddr = NULL; break; } /* send packet out to log * (MTT via RNDIS or crash dump file) */ BCMLOG_HandleCpCrashDumpData((const char *)(p + 2), size); packetCount++; iounmap(AssertLogVAddr); AssertLogVAddr = NULL; } } RpcDbgDumpHistoryLogging(2, 1); IPC_DEBUG(DBG_ERROR, "Starting CP RAM dump - do not power down...\n"); /* dump all CP memory to log */ DUMP_CPMemoryByList(dumped_crash_summary_ptr->mem_dump); IPC_DEBUG(DBG_ERROR, "CP RAM dump complete\n"); /* resume normal logging activities... */ BCMLOG_EndCpCrashDump(); if (BCMLOG_OUTDEV_SDCARD == BCMLOG_GetCpCrashLogDevice()) sys_sync(); IPC_DEBUG(DBG_ERROR, "CP crash dump complete\n"); if ((BCMLOG_OUTDEV_SDCARD == BCMLOG_GetCpCrashLogDevice()) && cp_crashed == 1 && !cpReset) abort(); }
/** * Utility function to retrieve full crash log from CP via simple handshake * protocol. * * ********************************************************************************/ void DUMP_CP_assert_log(void) { UInt32 t0, t1, i, size, retryCount; UInt8 *p; UInt32 packetCount = 0; void __iomem *AssertLogVAddr = NULL; struct file* sdDumpFile = NULL; mm_segment_t oldfs; struct timespec ts; struct rtc_time tm; char assertFileName[CP_CRASH_DUMP_MAX_LEN]; extern void abort(void); // need to tell kernel that pointers from within the // kernel address space are valid (needed to do // file ops from kernel) oldfs = get_fs(); set_fs (KERNEL_DS); if( BCMLOG_CPCRASH_SDCARD == BCMLOG_GetCpCrashDumpDevice() ) { // get current time getnstimeofday(&ts); rtc_time_to_tm(ts.tv_sec, &tm); snprintf(assertFileName, CP_CRASH_DUMP_MAX_LEN, "%s%s%d_%02d_%02d_%02d_%02d_%02d%s", CP_CRASH_DUMP_DIR, CP_CRASH_DUMP_BASE_FILE_NAME, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, CP_CRASH_DUMP_FILE_EXT ); sdDumpFile = filp_open( assertFileName, O_WRONLY|O_TRUNC|O_LARGEFILE|O_CREAT, 666); if ( IS_ERR(sdDumpFile) ) { IPC_DEBUG(DBG_ERROR,"failed to open sdDumpFile %s\n", assertFileName); sdDumpFile = NULL; } else { IPC_DEBUG(DBG_ERROR,"sdDumpFile %s opened OK\n",assertFileName); } } // put logging driver into crash dump mode; messages will be sent straight out to MTT via // RNDIS (or dump file) instead of buffering in RING buffer (flood of crash dump info // overloads ring buffer otherwise, and we lose a lot of crash dump info) // NOTE: crash dump is put into SD by default; if SD file fails to open, then we'll try // sending it out RNDIS BCMLOG_StartCpCrashDump( sdDumpFile ); retryCount = 0; t0 = TIMER_GetValue(); while (1) { t1 = TIMER_GetValue(); // signal to CP that we're ready to receive crash log... SmLocalControl.SmControl->CrashCode = IPC_AP_CLEAR_TO_SEND; // wait for CP to "dump"; CrashCode field will be set to physical address of current assert buf while (SmLocalControl.SmControl->CrashCode == IPC_AP_CLEAR_TO_SEND) { for (i=0; i<256; i++); if (TIMER_GetValue() - t1 > TICKS_ONE_SECOND * 20) break; } // check for time out if (SmLocalControl.SmControl->CrashCode == IPC_AP_CLEAR_TO_SEND) { if ( retryCount < MAX_CP_DUMP_RETRIES ) { retryCount++; IPC_DEBUG(DBG_ERROR,"timeout %d, trying again...\n", (int)retryCount); continue; } else { // no response from CP, so get out of here IPC_DEBUG(DBG_ERROR,"Abort --- max retries %d reached\n", (int)retryCount); break; } } // reset retry counter retryCount = 0; // get virtual address of CP assert buffer AssertLogVAddr = ioremap_nocache((UInt32)(SmLocalControl.SmControl->CrashCode), ASSERT_BUF_SIZE); if(NULL == AssertLogVAddr) { IPC_DEBUG(DBG_ERROR, "ioremap_nocache failed in DUMP_CP_assert_log\n"); break; } p = (UInt8 *)AssertLogVAddr; // number of bytes in assert buffer size = (p[0] << 8) + p[1]; // size of 0 means CP is done dumping assert log if (size == 0) { IPC_DEBUG(DBG_INFO, "assert log size 0, exiting, packetCount:0x%x\n", (int)packetCount); iounmap(AssertLogVAddr); AssertLogVAddr = NULL; break; } // sanity check for too beaucoup... if (size > ASSERT_BUF_SIZE - 2) { IPC_DEBUG(DBG_ERROR, "Abort --- improper size [%08x]=%d\n", SmLocalControl.SmControl->CrashCode, (int)size); iounmap(AssertLogVAddr); AssertLogVAddr = NULL; break; } // send packet out to log (MTT via RNDIS or crash dump file) BCMLOG_HandleCpCrashDumpData( (const char*)(p+2), size ); packetCount++; iounmap(AssertLogVAddr); AssertLogVAddr = NULL; #if 0 // **FIXME** this is Nucleus timeout code - do we want something similar // for Android? Maybe if we get to the point of restarting CP with // restarting AP if (TIMER_GetValue() - t0 > TICKS_ONE_SECOND * 10 * 60) { IPC_DEBUG(DBG_ERROR,"Abort --- CP assertion log too long\n"); break; } #endif } IPC_DEBUG(DBG_ERROR,"Starting CP RAM dump - do not power down...\n"); // dump all CP memory to log DUMP_CPMemoryByList( dumped_crash_summary_ptr->mem_dump ); IPC_DEBUG(DBG_ERROR,"CP RAM dump complete\n"); // resume normal logging activities... BCMLOG_EndCpCrashDump( ); if ( sdDumpFile ) { filp_close( sdDumpFile ,NULL ); } set_fs (oldfs); sys_sync(); IPC_DEBUG(DBG_ERROR,"CP crash dump complete\n"); if (BCMLOG_CPCRASH_MTD != BCMLOG_GetCpCrashDumpDevice()) abort(); #ifdef CONFIG_BRCM_KPANIC_UI_IND else lcdc_disp_img(IMG_INDEX_END_DUMP); //parameter 1: Draw the Kpanic Dump complete picture #endif }
IPC_Buffer IPC_AllocateBufferWait(IPC_BufferPool Pool, IPC_U32 MilliSeconds) { IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool); IPC_Buffer Buffer; IPC_ReturnCode_T errCode; UInt32 curTick, endTick; UInt32 beforeTick, afterTick; curTick = 0; endTick = MilliSeconds; while (curTick < endTick) { /* Try straight allocate first (saves event operations most of the time) */ Buffer = IPC_AllocateBuffer(Pool); if (Buffer) return Buffer; /* Check Event exists */ if (!PoolPtr->EmptyEvent) { /* Can't suspend without an event flag */ IPC_TRACE(IPC_Channel_Error, "IPC_AllocateBufferWait", "No Event Flag for Pool %08X", Pool, 0, 0, 0); return 0; } /* Clear event before waiting on it */ if (IPC_OK != IPC_EVENT_CLEAR(PoolPtr->EmptyEvent)) { IPC_TRACE(IPC_Channel_Error, "IPC_AllocateBufferWait", "Cannot clear Event Flag %08P for Pool %08X", PoolPtr->EmptyEvent, Pool, 0, 0); return 0; } /* Check in case the event was set before the clear */ Buffer = IPC_AllocateBuffer(Pool); if (Buffer) return Buffer; /* Now can safely wait for the event to be set * by the buffer free */ IPC_TRACE(IPC_Channel_FlowControl, "IPC_AllocateBufferWait", "Pool %08X Empty, waiting for %d Milliseconds, total=%d", Pool, (endTick - curTick), MilliSeconds, 0); beforeTick = TIMER_GetValue(); errCode = IPC_EVENT_WAIT(PoolPtr->EmptyEvent, (endTick - curTick)); afterTick = TIMER_GetValue(); /* Handle wrap around for 0xFFFFFFFF */ curTick += (UInt32)(afterTick - beforeTick); if (IPC_ERROR == errCode) { IPC_TRACE(IPC_Channel_Error, "IPC_AllocateBufferWait", "Error from IPC_EVENT_WAIT; Event Flag %08P for Pool %08X", PoolPtr->EmptyEvent, Pool, 0, 0); return 0; } else if (IPC_OK == errCode) { continue; /* retry */ } else { /* IPC_TIMEOUT */ break; } } return IPC_AllocateBuffer(Pool); }
IPC_Buffer IPC_AllocateBuffer(IPC_BufferPool Pool) { CRITICAL_REIGON_SETUP IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool); IPC_SmQEntry QElement; IPC_U32 BufferCount; IPC_Buffer Buffer; IPC_Boolean FlowControlCallNeeded = IPC_FALSE; if (!Pool) { IPC_TRACE(IPC_Channel_Error, "IPC_AllocateBuffer", "Invalid Pool %08X", Pool, 0, 0, 0); return 0; } CRITICAL_REIGON_ENTER(PoolPtr->Lock); QElement = IPC_QGetFirst(IPC_POOLFreeQ(Pool)); if (!QElement) { PoolPtr->FlowControlState = IPC_FLOW_STOP; PoolPtr->AllocationFailures++; CRITICAL_REIGON_LEAVE(PoolPtr->Lock); if (PoolPtr->DestinationEndpointId != IPC_EP_LogApps) IPC_TRACE(IPC_Channel_FlowControl, "IPC_ReportFlowControlEvent", "Pool %08X Empty, Allocations %d AllocationFailures %d FlowStopCalls %d", Pool, PoolPtr->Allocations, PoolPtr->AllocationFailures, PoolPtr->FlowStopCalls); return 0; } #ifdef IPC_DEBUG IPC_QAddBack(QElement, IPC_SmOffset(&PoolPtr->AllocatedBufferQ)); #endif BufferCount = --PoolPtr->FreeBuffers; /* Flow Control Check */ if (BufferCount == PoolPtr->FlowStopLimit) CHECK_FLOW_STATE(PoolPtr, IPC_FLOW_STOP, FlowControlCallNeeded) CRITICAL_REIGON_LEAVE(PoolPtr->Lock); if (FlowControlCallNeeded) IPC_ReportFlowControlEvent(PoolPtr, IPC_FLOW_STOP); Buffer = IPC_QEntryPtr(QElement)->Item; if (Buffer) { IPC_Buffer_T *BufferPtr = IPC_SmOffsetToPointer(IPC_Buffer_T, Buffer); BufferPtr->HeaderSize = 0; BufferPtr->DataSize = 0; BufferPtr->UserParameter = 0; BufferPtr->TimeStampAlloc = TIMER_GetValue(); BufferPtr->StatusCode = IPC_BUFFER_STATUS_ALLOC; BufferPtr->DataOffset = BufferPtr->DataBufferStart + IPC_PoolPtr(BufferPtr->Pool)->MaxHeaderSize; } IPC_TRACE(IPC_Channel_Buffer, "IPC_AllocateBuffer", "Buf %d (%08X) Pool %08X, %d Left", IPC_BufferId(Buffer), Buffer, Pool, BufferCount); /* Update Statistics */ PoolPtr->Allocations++; if (BufferCount < PoolPtr->LowWaterMark) PoolPtr->LowWaterMark = BufferCount; return Buffer; }