Commit b03d7d0f authored by Wey-Yi Guy's avatar Wey-Yi Guy Committed by John W. Linville

iwlwifi: on-screen event log dump

This feature enables the on-screen uCode event log dump. The original
method will append the event log to syslog; with this capability,
we also enable the user to write script to capture the
events which provide additional flexibility to help uCode debugging

Method
1) change to debugfs directory (sys/kernel/debug/phyX/iwlagn/data)
2) #cat log_event
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a9e1cb6a
...@@ -227,7 +227,8 @@ extern void iwl3945_rx_replenish(void *data); ...@@ -227,7 +227,8 @@ extern void iwl3945_rx_replenish(void *data);
extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,int left); struct ieee80211_hdr *hdr,int left);
extern void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log); extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
char **buf, bool display);
extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv);
/* /*
......
...@@ -1832,8 +1832,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) ...@@ -1832,8 +1832,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
* iwl_print_event_log - Dump error event log to syslog * iwl_print_event_log - Dump error event log to syslog
* *
*/ */
static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
u32 num_events, u32 mode) u32 num_events, u32 mode,
int pos, char **buf, size_t bufsz)
{ {
u32 i; u32 i;
u32 base; /* SRAM byte address of event log header */ u32 base; /* SRAM byte address of event log header */
...@@ -1843,7 +1844,7 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, ...@@ -1843,7 +1844,7 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
unsigned long reg_flags; unsigned long reg_flags;
if (num_events == 0) if (num_events == 0)
return; return pos;
if (priv->ucode_type == UCODE_INIT) if (priv->ucode_type == UCODE_INIT)
base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
else else
...@@ -1871,27 +1872,44 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, ...@@ -1871,27 +1872,44 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
if (mode == 0) { if (mode == 0) {
/* data, ev */ /* data, ev */
trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); if (bufsz) {
IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); pos += scnprintf(*buf + pos, bufsz - pos,
"EVT_LOG:0x%08x:%04u\n",
time, ev);
} else {
trace_iwlwifi_dev_ucode_event(priv, 0,
time, ev);
IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n",
time, ev);
}
} else { } else {
data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
if (bufsz) {
pos += scnprintf(*buf + pos, bufsz - pos,
"EVT_LOGT:%010u:0x%08x:%04u\n",
time, data, ev);
} else {
IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
time, data, ev); time, data, ev);
trace_iwlwifi_dev_ucode_event(priv, time, data, ev); trace_iwlwifi_dev_ucode_event(priv, time,
data, ev);
}
} }
} }
/* Allow device to power down */ /* Allow device to power down */
iwl_release_nic_access(priv); iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->reg_lock, reg_flags); spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
return pos;
} }
/** /**
* iwl_print_last_event_logs - Dump the newest # of event log to syslog * iwl_print_last_event_logs - Dump the newest # of event log to syslog
*/ */
static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
u32 num_wraps, u32 next_entry, u32 num_wraps, u32 next_entry,
u32 size, u32 mode) u32 size, u32 mode,
int pos, char **buf, size_t bufsz)
{ {
/* /*
* display the newest DEFAULT_LOG_ENTRIES entries * display the newest DEFAULT_LOG_ENTRIES entries
...@@ -1899,21 +1917,26 @@ static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, ...@@ -1899,21 +1917,26 @@ static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
*/ */
if (num_wraps) { if (num_wraps) {
if (next_entry < size) { if (next_entry < size) {
iwl_print_event_log(priv, pos = iwl_print_event_log(priv,
capacity - (size - next_entry), capacity - (size - next_entry),
size - next_entry, mode); size - next_entry, mode,
iwl_print_event_log(priv, 0, pos, buf, bufsz);
next_entry, mode); pos = iwl_print_event_log(priv, 0,
next_entry, mode,
pos, buf, bufsz);
} else } else
iwl_print_event_log(priv, next_entry - size, pos = iwl_print_event_log(priv, next_entry - size,
size, mode); size, mode, pos, buf, bufsz);
} else { } else {
if (next_entry < size) if (next_entry < size) {
iwl_print_event_log(priv, 0, next_entry, mode); pos = iwl_print_event_log(priv, 0, next_entry,
else mode, pos, buf, bufsz);
iwl_print_event_log(priv, next_entry - size, } else {
size, mode); pos = iwl_print_event_log(priv, next_entry - size,
size, mode, pos, buf, bufsz);
} }
}
return pos;
} }
/* For sanity check only. Actual size is determined by uCode, typ. 512 */ /* For sanity check only. Actual size is determined by uCode, typ. 512 */
...@@ -1921,7 +1944,8 @@ static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, ...@@ -1921,7 +1944,8 @@ static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
char **buf, bool display)
{ {
u32 base; /* SRAM byte address of event log header */ u32 base; /* SRAM byte address of event log header */
u32 capacity; /* event log capacity in # entries */ u32 capacity; /* event log capacity in # entries */
...@@ -1929,6 +1953,8 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) ...@@ -1929,6 +1953,8 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
u32 num_wraps; /* # times uCode wrapped to top of log */ u32 num_wraps; /* # times uCode wrapped to top of log */
u32 next_entry; /* index of next entry to be written by uCode */ u32 next_entry; /* index of next entry to be written by uCode */
u32 size; /* # entries that we'll print */ u32 size; /* # entries that we'll print */
int pos = 0;
size_t bufsz = 0;
if (priv->ucode_type == UCODE_INIT) if (priv->ucode_type == UCODE_INIT)
base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
...@@ -1939,7 +1965,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) ...@@ -1939,7 +1965,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
IWL_ERR(priv, IWL_ERR(priv,
"Invalid event log pointer 0x%08X for %s uCode\n", "Invalid event log pointer 0x%08X for %s uCode\n",
base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
return; return pos;
} }
/* event log header */ /* event log header */
...@@ -1965,7 +1991,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) ...@@ -1965,7 +1991,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
/* bail out if nothing in log */ /* bail out if nothing in log */
if (size == 0) { if (size == 0) {
IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
return; return pos;
} }
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
...@@ -1980,6 +2006,15 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) ...@@ -1980,6 +2006,15 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
size); size);
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
if (display) {
if (full_log)
bufsz = capacity * 48;
else
bufsz = size * 48;
*buf = kmalloc(bufsz, GFP_KERNEL);
if (!*buf)
return pos;
}
if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
/* /*
* if uCode has wrapped back to top of log, * if uCode has wrapped back to top of log,
...@@ -1987,17 +2022,22 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) ...@@ -1987,17 +2022,22 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
* i.e the next one that uCode would fill. * i.e the next one that uCode would fill.
*/ */
if (num_wraps) if (num_wraps)
iwl_print_event_log(priv, next_entry, pos = iwl_print_event_log(priv, next_entry,
capacity - next_entry, mode); capacity - next_entry, mode,
pos, buf, bufsz);
/* (then/else) start at top of log */ /* (then/else) start at top of log */
iwl_print_event_log(priv, 0, next_entry, mode); pos = iwl_print_event_log(priv, 0,
next_entry, mode, pos, buf, bufsz);
} else } else
iwl_print_last_event_logs(priv, capacity, num_wraps, pos = iwl_print_last_event_logs(priv, capacity, num_wraps,
next_entry, size, mode); next_entry, size, mode,
pos, buf, bufsz);
#else #else
iwl_print_last_event_logs(priv, capacity, num_wraps, pos = iwl_print_last_event_logs(priv, capacity, num_wraps,
next_entry, size, mode); next_entry, size, mode,
pos, buf, bufsz);
#endif #endif
return pos;
} }
/** /**
......
...@@ -1365,7 +1365,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv) ...@@ -1365,7 +1365,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
priv->cfg->ops->lib->dump_nic_error_log(priv); priv->cfg->ops->lib->dump_nic_error_log(priv);
if (priv->cfg->ops->lib->dump_csr) if (priv->cfg->ops->lib->dump_csr)
priv->cfg->ops->lib->dump_csr(priv); priv->cfg->ops->lib->dump_csr(priv);
priv->cfg->ops->lib->dump_nic_event_log(priv, false); priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)
iwl_print_rx_config_cmd(priv); iwl_print_rx_config_cmd(priv);
......
...@@ -169,7 +169,8 @@ struct iwl_lib_ops { ...@@ -169,7 +169,8 @@ struct iwl_lib_ops {
int (*is_valid_rtc_data_addr)(u32 addr); int (*is_valid_rtc_data_addr)(u32 addr);
/* 1st ucode load */ /* 1st ucode load */
int (*load_ucode)(struct iwl_priv *priv); int (*load_ucode)(struct iwl_priv *priv);
void (*dump_nic_event_log)(struct iwl_priv *priv, bool full_log); int (*dump_nic_event_log)(struct iwl_priv *priv,
bool full_log, char **buf, bool display);
void (*dump_nic_error_log)(struct iwl_priv *priv); void (*dump_nic_error_log)(struct iwl_priv *priv);
void (*dump_csr)(struct iwl_priv *priv); void (*dump_csr)(struct iwl_priv *priv);
int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); int (*set_channel_switch)(struct iwl_priv *priv, u16 channel);
...@@ -582,7 +583,8 @@ int iwl_pci_resume(struct pci_dev *pdev); ...@@ -582,7 +583,8 @@ int iwl_pci_resume(struct pci_dev *pdev);
* Error Handling Debugging * Error Handling Debugging
******************************************************/ ******************************************************/
void iwl_dump_nic_error_log(struct iwl_priv *priv); void iwl_dump_nic_error_log(struct iwl_priv *priv);
void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log); int iwl_dump_nic_event_log(struct iwl_priv *priv,
bool full_log, char **buf, bool display);
void iwl_dump_csr(struct iwl_priv *priv); void iwl_dump_csr(struct iwl_priv *priv);
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
void iwl_print_rx_config_cmd(struct iwl_priv *priv); void iwl_print_rx_config_cmd(struct iwl_priv *priv);
......
...@@ -420,6 +420,23 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, ...@@ -420,6 +420,23 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
return ret; return ret;
} }
static ssize_t iwl_dbgfs_log_event_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
char *buf;
int pos = 0;
ssize_t ret = -ENOMEM;
pos = priv->cfg->ops->lib->dump_nic_event_log(priv, true, &buf, true);
if (pos && buf) {
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
}
return ret;
}
static ssize_t iwl_dbgfs_log_event_write(struct file *file, static ssize_t iwl_dbgfs_log_event_write(struct file *file,
const char __user *user_buf, const char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
...@@ -436,7 +453,8 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, ...@@ -436,7 +453,8 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
if (sscanf(buf, "%d", &event_log_flag) != 1) if (sscanf(buf, "%d", &event_log_flag) != 1)
return -EFAULT; return -EFAULT;
if (event_log_flag == 1) if (event_log_flag == 1)
priv->cfg->ops->lib->dump_nic_event_log(priv, true); priv->cfg->ops->lib->dump_nic_event_log(priv, true,
NULL, false);
return count; return count;
} }
...@@ -859,7 +877,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, ...@@ -859,7 +877,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
} }
DEBUGFS_READ_WRITE_FILE_OPS(sram); DEBUGFS_READ_WRITE_FILE_OPS(sram);
DEBUGFS_WRITE_FILE_OPS(log_event); DEBUGFS_READ_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(nvm); DEBUGFS_READ_FILE_OPS(nvm);
DEBUGFS_READ_FILE_OPS(stations); DEBUGFS_READ_FILE_OPS(stations);
DEBUGFS_READ_FILE_OPS(channels); DEBUGFS_READ_FILE_OPS(channels);
...@@ -1965,7 +1983,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) ...@@ -1965,7 +1983,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv); DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv);
DEBUGFS_ADD_FILE(nvm, data, S_IRUSR); DEBUGFS_ADD_FILE(nvm, data, S_IRUSR);
DEBUGFS_ADD_FILE(sram, data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(sram, data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(log_event, data, S_IWUSR); DEBUGFS_ADD_FILE(log_event, data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(stations, data, S_IRUSR); DEBUGFS_ADD_FILE(stations, data, S_IRUSR);
DEBUGFS_ADD_FILE(channels, data, S_IRUSR); DEBUGFS_ADD_FILE(channels, data, S_IRUSR);
DEBUGFS_ADD_FILE(status, data, S_IRUSR); DEBUGFS_ADD_FILE(status, data, S_IRUSR);
......
...@@ -1560,8 +1560,9 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv) ...@@ -1560,8 +1560,9 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
* iwl3945_print_event_log - Dump error event log to syslog * iwl3945_print_event_log - Dump error event log to syslog
* *
*/ */
static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
u32 num_events, u32 mode) u32 num_events, u32 mode,
int pos, char **buf, size_t bufsz)
{ {
u32 i; u32 i;
u32 base; /* SRAM byte address of event log header */ u32 base; /* SRAM byte address of event log header */
...@@ -1571,7 +1572,7 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, ...@@ -1571,7 +1572,7 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
unsigned long reg_flags; unsigned long reg_flags;
if (num_events == 0) if (num_events == 0)
return; return pos;
base = le32_to_cpu(priv->card_alive.log_event_table_ptr); base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
...@@ -1597,26 +1598,43 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, ...@@ -1597,26 +1598,43 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
if (mode == 0) { if (mode == 0) {
/* data, ev */ /* data, ev */
if (bufsz) {
pos += scnprintf(*buf + pos, bufsz - pos,
"0x%08x:%04u\n",
time, ev);
} else {
IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); trace_iwlwifi_dev_ucode_event(priv, 0,
time, ev);
}
} else { } else {
data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev); if (bufsz) {
trace_iwlwifi_dev_ucode_event(priv, time, data, ev); pos += scnprintf(*buf + pos, bufsz - pos,
"%010u:0x%08x:%04u\n",
time, data, ev);
} else {
IWL_ERR(priv, "%010u\t0x%08x\t%04u\n",
time, data, ev);
trace_iwlwifi_dev_ucode_event(priv, time,
data, ev);
}
} }
} }
/* Allow device to power down */ /* Allow device to power down */
iwl_release_nic_access(priv); iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->reg_lock, reg_flags); spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
return pos;
} }
/** /**
* iwl3945_print_last_event_logs - Dump the newest # of event log to syslog * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog
*/ */
static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
u32 num_wraps, u32 next_entry, u32 num_wraps, u32 next_entry,
u32 size, u32 mode) u32 size, u32 mode,
int pos, char **buf, size_t bufsz)
{ {
/* /*
* display the newest DEFAULT_LOG_ENTRIES entries * display the newest DEFAULT_LOG_ENTRIES entries
...@@ -1624,21 +1642,28 @@ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, ...@@ -1624,21 +1642,28 @@ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
*/ */
if (num_wraps) { if (num_wraps) {
if (next_entry < size) { if (next_entry < size) {
iwl3945_print_event_log(priv, pos = iwl3945_print_event_log(priv,
capacity - (size - next_entry), capacity - (size - next_entry),
size - next_entry, mode); size - next_entry, mode,
iwl3945_print_event_log(priv, 0, pos, buf, bufsz);
next_entry, mode); pos = iwl3945_print_event_log(priv, 0,
next_entry, mode,
pos, buf, bufsz);
} else } else
iwl3945_print_event_log(priv, next_entry - size, pos = iwl3945_print_event_log(priv, next_entry - size,
size, mode); size, mode,
pos, buf, bufsz);
} else { } else {
if (next_entry < size) if (next_entry < size)
iwl3945_print_event_log(priv, 0, next_entry, mode); pos = iwl3945_print_event_log(priv, 0,
next_entry, mode,
pos, buf, bufsz);
else else
iwl3945_print_event_log(priv, next_entry - size, pos = iwl3945_print_event_log(priv, next_entry - size,
size, mode); size, mode,
pos, buf, bufsz);
} }
return pos;
} }
/* For sanity check only. Actual size is determined by uCode, typ. 512 */ /* For sanity check only. Actual size is determined by uCode, typ. 512 */
...@@ -1646,7 +1671,8 @@ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, ...@@ -1646,7 +1671,8 @@ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
#define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
char **buf, bool display)
{ {
u32 base; /* SRAM byte address of event log header */ u32 base; /* SRAM byte address of event log header */
u32 capacity; /* event log capacity in # entries */ u32 capacity; /* event log capacity in # entries */
...@@ -1654,11 +1680,13 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) ...@@ -1654,11 +1680,13 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
u32 num_wraps; /* # times uCode wrapped to top of log */ u32 num_wraps; /* # times uCode wrapped to top of log */
u32 next_entry; /* index of next entry to be written by uCode */ u32 next_entry; /* index of next entry to be written by uCode */
u32 size; /* # entries that we'll print */ u32 size; /* # entries that we'll print */
int pos = 0;
size_t bufsz = 0;
base = le32_to_cpu(priv->card_alive.log_event_table_ptr); base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
if (!iwl3945_hw_valid_rtc_data_addr(base)) { if (!iwl3945_hw_valid_rtc_data_addr(base)) {
IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
return; return pos;
} }
/* event log header */ /* event log header */
...@@ -1684,7 +1712,7 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) ...@@ -1684,7 +1712,7 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
/* bail out if nothing in log */ /* bail out if nothing in log */
if (size == 0) { if (size == 0) {
IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
return; return pos;
} }
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
...@@ -1700,25 +1728,38 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) ...@@ -1700,25 +1728,38 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
size); size);
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
if (display) {
if (full_log)
bufsz = capacity * 48;
else
bufsz = size * 48;
*buf = kmalloc(bufsz, GFP_KERNEL);
if (!*buf)
return pos;
}
if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
/* if uCode has wrapped back to top of log, /* if uCode has wrapped back to top of log,
* start at the oldest entry, * start at the oldest entry,
* i.e the next one that uCode would fill. * i.e the next one that uCode would fill.
*/ */
if (num_wraps) if (num_wraps)
iwl3945_print_event_log(priv, next_entry, pos = iwl3945_print_event_log(priv, next_entry,
capacity - next_entry, mode); capacity - next_entry, mode,
pos, buf, bufsz);
/* (then/else) start at top of log */ /* (then/else) start at top of log */
iwl3945_print_event_log(priv, 0, next_entry, mode); pos = iwl3945_print_event_log(priv, 0, next_entry, mode,
pos, buf, bufsz);
} else } else
iwl3945_print_last_event_logs(priv, capacity, num_wraps, pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
next_entry, size, mode); next_entry, size, mode,
pos, buf, bufsz);
#else #else
iwl3945_print_last_event_logs(priv, capacity, num_wraps, pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
next_entry, size, mode); next_entry, size, mode,
pos, buf, bufsz);
#endif #endif
return pos;
} }
static void iwl3945_irq_tasklet(struct iwl_priv *priv) static void iwl3945_irq_tasklet(struct iwl_priv *priv)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment