int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, char **buf, bool display) { u32 base; /* SRAM byte address of event log header */ u32 capacity; /* event log capacity in # entries */ u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ u32 num_wraps; /* # times uCode wrapped to top of log */ u32 next_entry; /* index of next entry to be written by uCode */ u32 size; /* # entries that we'll print */ u32 logsize; int pos = 0; size_t bufsz = 0; struct iwl_priv *priv = priv(trans); base = priv->device_pointers.log_event_table; if (priv->ucode_type == IWL_UCODE_INIT) { logsize = priv->init_evtlog_size; if (!base) base = priv->init_evtlog_ptr; } else { logsize = priv->inst_evtlog_size; if (!base) base = priv->inst_evtlog_ptr; } if (!iwlagn_hw_valid_rtc_data_addr(base)) { IWL_ERR(trans, "Invalid event log pointer 0x%08X for %s uCode\n", base, (priv->ucode_type == IWL_UCODE_INIT) ? "Init" : "RT"); return -EINVAL; } /* event log header */ capacity = iwl_read_targ_mem(bus(trans), base); mode = iwl_read_targ_mem(bus(trans), base + (1 * sizeof(u32))); num_wraps = iwl_read_targ_mem(bus(trans), base + (2 * sizeof(u32))); next_entry = iwl_read_targ_mem(bus(trans), base + (3 * sizeof(u32))); if (capacity > logsize) { IWL_ERR(trans, "Log capacity %d is bogus, limit to %d " "entries\n", capacity, logsize); capacity = logsize; } if (next_entry > logsize) { IWL_ERR(trans, "Log write index %d is bogus, limit to %d\n", next_entry, logsize); next_entry = logsize; } size = num_wraps ? capacity : next_entry; /* bail out if nothing in log */ if (size == 0) { IWL_ERR(trans, "Start IWL Event Log Dump: nothing in log\n"); return pos; } #ifdef CONFIG_IWLWIFI_DEBUG if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log) size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; #else size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; #endif IWL_ERR(trans, "Start IWL Event Log Dump: display last %u entries\n", size); #ifdef CONFIG_IWLWIFI_DEBUG if (display) { if (full_log) bufsz = capacity * 48; else bufsz = size * 48; *buf = kmalloc(bufsz, GFP_KERNEL); if (!*buf) return -ENOMEM; } if ((iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) || full_log) { /* * if uCode has wrapped back to top of log, * start at the oldest entry, * i.e the next one that uCode would fill. */ if (num_wraps) pos = iwl_print_event_log(trans, next_entry, capacity - next_entry, mode, pos, buf, bufsz); /* (then/else) start at top of log */ pos = iwl_print_event_log(trans, 0, next_entry, mode, pos, buf, bufsz); } else pos = iwl_print_last_event_logs(trans, capacity, num_wraps, next_entry, size, mode, pos, buf, bufsz); #else pos = iwl_print_last_event_logs(trans, capacity, num_wraps, next_entry, size, mode, pos, buf, bufsz); #endif return pos; }
int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, char **buf, bool display) { u32 base; /* */ u32 capacity; /* */ u32 mode; /* */ u32 num_wraps; /* */ u32 next_entry; /* */ u32 size; /* */ u32 logsize; int pos = 0; size_t bufsz = 0; base = trans->shrd->device_pointers.log_event_table; if (trans->shrd->ucode_type == IWL_UCODE_INIT) { logsize = trans->shrd->fw->init_evtlog_size; if (!base) base = trans->shrd->fw->init_evtlog_ptr; } else { logsize = trans->shrd->fw->inst_evtlog_size; if (!base) base = trans->shrd->fw->inst_evtlog_ptr; } if (!iwlagn_hw_valid_rtc_data_addr(base)) { IWL_ERR(trans, "Invalid event log pointer 0x%08X for %s uCode\n", base, (trans->shrd->ucode_type == IWL_UCODE_INIT) ? "Init" : "RT"); return -EINVAL; } /* */ capacity = iwl_read_targ_mem(trans, base); mode = iwl_read_targ_mem(trans, base + (1 * sizeof(u32))); num_wraps = iwl_read_targ_mem(trans, base + (2 * sizeof(u32))); next_entry = iwl_read_targ_mem(trans, base + (3 * sizeof(u32))); if (capacity > logsize) { IWL_ERR(trans, "Log capacity %d is bogus, limit to %d " "entries\n", capacity, logsize); capacity = logsize; } if (next_entry > logsize) { IWL_ERR(trans, "Log write index %d is bogus, limit to %d\n", next_entry, logsize); next_entry = logsize; } size = num_wraps ? capacity : next_entry; /* */ if (size == 0) { IWL_ERR(trans, "Start IWL Event Log Dump: nothing in log\n"); return pos; } #ifdef CONFIG_IWLWIFI_DEBUG if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log) size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; #else size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; #endif IWL_ERR(trans, "Start IWL Event Log Dump: display last %u entries\n", size); #ifdef CONFIG_IWLWIFI_DEBUG if (display) { if (full_log) bufsz = capacity * 48; else bufsz = size * 48; *buf = kmalloc(bufsz, GFP_KERNEL); if (!*buf) return -ENOMEM; } if (iwl_have_debug_level(IWL_DL_FW_ERRORS) || full_log) { /* */ if (num_wraps) pos = iwl_print_event_log(trans, next_entry, capacity - next_entry, mode, pos, buf, bufsz); /* */ pos = iwl_print_event_log(trans, 0, next_entry, mode, pos, buf, bufsz); } else pos = iwl_print_last_event_logs(trans, capacity, num_wraps, next_entry, size, mode, pos, buf, bufsz); #else pos = iwl_print_last_event_logs(trans, capacity, num_wraps, next_entry, size, mode, pos, buf, bufsz); #endif return pos; }