forked from Minki/linux
iwlwifi: trigger event log from debugfs
This patch adds a trigger for event log printing to debugfs. It removes the triger from sysfs. Signed-off-by: Ester Kummer <ester.kummer@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
6ba8795622
commit
189a2b5942
@ -1055,3 +1055,104 @@ int iwl_verify_ucode(struct iwl_priv *priv)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iwl_verify_ucode);
|
EXPORT_SYMBOL(iwl_verify_ucode);
|
||||||
|
|
||||||
|
|
||||||
|
#define EVENT_START_OFFSET (4 * sizeof(u32))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iwl_print_event_log - Dump error event log to syslog
|
||||||
|
*
|
||||||
|
* NOTE: Must be called with iwl4965_grab_nic_access() already obtained!
|
||||||
|
*/
|
||||||
|
void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
||||||
|
u32 num_events, u32 mode)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
u32 base; /* SRAM byte address of event log header */
|
||||||
|
u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
|
||||||
|
u32 ptr; /* SRAM byte address of log data */
|
||||||
|
u32 ev, time, data; /* event log data */
|
||||||
|
|
||||||
|
if (num_events == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
|
||||||
|
|
||||||
|
if (mode == 0)
|
||||||
|
event_size = 2 * sizeof(u32);
|
||||||
|
else
|
||||||
|
event_size = 3 * sizeof(u32);
|
||||||
|
|
||||||
|
ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
|
||||||
|
|
||||||
|
/* "time" is actually "data" for mode 0 (no timestamp).
|
||||||
|
* place event id # at far right for easier visual parsing. */
|
||||||
|
for (i = 0; i < num_events; i++) {
|
||||||
|
ev = iwl_read_targ_mem(priv, ptr);
|
||||||
|
ptr += sizeof(u32);
|
||||||
|
time = iwl_read_targ_mem(priv, ptr);
|
||||||
|
ptr += sizeof(u32);
|
||||||
|
if (mode == 0)
|
||||||
|
IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
|
||||||
|
else {
|
||||||
|
data = iwl_read_targ_mem(priv, ptr);
|
||||||
|
ptr += sizeof(u32);
|
||||||
|
IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iwl_print_event_log);
|
||||||
|
|
||||||
|
|
||||||
|
void iwl_dump_nic_event_log(struct iwl_priv *priv)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
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 */
|
||||||
|
|
||||||
|
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
|
||||||
|
if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
|
||||||
|
IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = iwl_grab_nic_access(priv);
|
||||||
|
if (rc) {
|
||||||
|
IWL_WARNING("Can not read from adapter at this time.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* event log header */
|
||||||
|
capacity = iwl_read_targ_mem(priv, base);
|
||||||
|
mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
|
||||||
|
num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
|
||||||
|
next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
|
||||||
|
|
||||||
|
size = num_wraps ? capacity : next_entry;
|
||||||
|
|
||||||
|
/* bail out if nothing in log */
|
||||||
|
if (size == 0) {
|
||||||
|
IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
|
||||||
|
iwl_release_nic_access(priv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n",
|
||||||
|
size, num_wraps);
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
iwl_print_event_log(priv, next_entry,
|
||||||
|
capacity - next_entry, mode);
|
||||||
|
/* (then/else) start at top of log */
|
||||||
|
iwl_print_event_log(priv, 0, next_entry, mode);
|
||||||
|
|
||||||
|
iwl_release_nic_access(priv);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iwl_dump_nic_event_log);
|
||||||
|
|
||||||
|
|
||||||
|
@ -232,6 +232,14 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
|
|||||||
struct sk_buff *skb));
|
struct sk_buff *skb));
|
||||||
|
|
||||||
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
|
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
|
||||||
|
|
||||||
|
/*****************************************************
|
||||||
|
* Error Handling Debugging
|
||||||
|
******************************************************/
|
||||||
|
void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
||||||
|
u32 num_events, u32 mode);
|
||||||
|
void iwl_dump_nic_event_log(struct iwl_priv *priv);
|
||||||
|
|
||||||
/*************** DRIVER STATUS FUNCTIONS *****/
|
/*************** DRIVER STATUS FUNCTIONS *****/
|
||||||
|
|
||||||
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
|
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
|
||||||
|
@ -52,6 +52,7 @@ struct iwl_debugfs {
|
|||||||
struct dentry *file_stations;
|
struct dentry *file_stations;
|
||||||
struct dentry *file_rx_statistics;
|
struct dentry *file_rx_statistics;
|
||||||
struct dentry *file_tx_statistics;
|
struct dentry *file_tx_statistics;
|
||||||
|
struct dentry *file_log_event;
|
||||||
} dbgfs_data_files;
|
} dbgfs_data_files;
|
||||||
struct dir_rf_files {
|
struct dir_rf_files {
|
||||||
#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
|
#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
|
||||||
|
@ -92,6 +92,14 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
|||||||
.open = iwl_dbgfs_open_file_generic, \
|
.open = iwl_dbgfs_open_file_generic, \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define DEBUGFS_WRITE_FILE_OPS(name) \
|
||||||
|
DEBUGFS_WRITE_FUNC(name); \
|
||||||
|
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||||
|
.write = iwl_dbgfs_##name##_write, \
|
||||||
|
.open = iwl_dbgfs_open_file_generic, \
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
|
#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
|
||||||
DEBUGFS_READ_FUNC(name); \
|
DEBUGFS_READ_FUNC(name); \
|
||||||
DEBUGFS_WRITE_FUNC(name); \
|
DEBUGFS_WRITE_FUNC(name); \
|
||||||
@ -324,7 +332,29 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t iwl_dbgfs_log_event_write(struct file *file,
|
||||||
|
const char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct iwl_priv *priv = file->private_data;
|
||||||
|
u32 event_log_flag;
|
||||||
|
char buf[8];
|
||||||
|
int buf_size;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
buf_size = min(count, sizeof(buf) - 1);
|
||||||
|
if (copy_from_user(buf, user_buf, buf_size))
|
||||||
|
return -EFAULT;
|
||||||
|
if (sscanf(buf, "%d", &event_log_flag) != 1)
|
||||||
|
return -EFAULT;
|
||||||
|
if (event_log_flag == 1)
|
||||||
|
iwl_dump_nic_event_log(priv);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUGFS_READ_WRITE_FILE_OPS(sram);
|
DEBUGFS_READ_WRITE_FILE_OPS(sram);
|
||||||
|
DEBUGFS_WRITE_FILE_OPS(log_event);
|
||||||
DEBUGFS_READ_FILE_OPS(eeprom);
|
DEBUGFS_READ_FILE_OPS(eeprom);
|
||||||
DEBUGFS_READ_FILE_OPS(stations);
|
DEBUGFS_READ_FILE_OPS(stations);
|
||||||
DEBUGFS_READ_FILE_OPS(rx_statistics);
|
DEBUGFS_READ_FILE_OPS(rx_statistics);
|
||||||
@ -354,6 +384,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
|||||||
DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
|
DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
|
||||||
DEBUGFS_ADD_FILE(eeprom, data);
|
DEBUGFS_ADD_FILE(eeprom, data);
|
||||||
DEBUGFS_ADD_FILE(sram, data);
|
DEBUGFS_ADD_FILE(sram, data);
|
||||||
|
DEBUGFS_ADD_FILE(log_event, data);
|
||||||
DEBUGFS_ADD_FILE(stations, data);
|
DEBUGFS_ADD_FILE(stations, data);
|
||||||
DEBUGFS_ADD_FILE(rx_statistics, data);
|
DEBUGFS_ADD_FILE(rx_statistics, data);
|
||||||
DEBUGFS_ADD_FILE(tx_statistics, data);
|
DEBUGFS_ADD_FILE(tx_statistics, data);
|
||||||
@ -384,6 +415,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
|
|||||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
|
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
|
||||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
|
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
|
||||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
|
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
|
||||||
|
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
|
||||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
|
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
|
||||||
DEBUGFS_REMOVE(priv->dbgfs->dir_data);
|
DEBUGFS_REMOVE(priv->dbgfs->dir_data);
|
||||||
#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
|
#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
|
||||||
|
@ -2692,103 +2692,6 @@ static void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
|
|||||||
iwl_release_nic_access(priv);
|
iwl_release_nic_access(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EVENT_START_OFFSET (4 * sizeof(u32))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* iwl4965_print_event_log - Dump error event log to syslog
|
|
||||||
*
|
|
||||||
* NOTE: Must be called with iwl_grab_nic_access() already obtained!
|
|
||||||
*/
|
|
||||||
static void iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
|
||||||
u32 num_events, u32 mode)
|
|
||||||
{
|
|
||||||
u32 i;
|
|
||||||
u32 base; /* SRAM byte address of event log header */
|
|
||||||
u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
|
|
||||||
u32 ptr; /* SRAM byte address of log data */
|
|
||||||
u32 ev, time, data; /* event log data */
|
|
||||||
|
|
||||||
if (num_events == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
|
|
||||||
|
|
||||||
if (mode == 0)
|
|
||||||
event_size = 2 * sizeof(u32);
|
|
||||||
else
|
|
||||||
event_size = 3 * sizeof(u32);
|
|
||||||
|
|
||||||
ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
|
|
||||||
|
|
||||||
/* "time" is actually "data" for mode 0 (no timestamp).
|
|
||||||
* place event id # at far right for easier visual parsing. */
|
|
||||||
for (i = 0; i < num_events; i++) {
|
|
||||||
ev = iwl_read_targ_mem(priv, ptr);
|
|
||||||
ptr += sizeof(u32);
|
|
||||||
time = iwl_read_targ_mem(priv, ptr);
|
|
||||||
ptr += sizeof(u32);
|
|
||||||
if (mode == 0)
|
|
||||||
IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
|
|
||||||
else {
|
|
||||||
data = iwl_read_targ_mem(priv, ptr);
|
|
||||||
ptr += sizeof(u32);
|
|
||||||
IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iwl4965_dump_nic_event_log(struct iwl_priv *priv)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
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 */
|
|
||||||
|
|
||||||
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
|
|
||||||
if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
|
|
||||||
IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = iwl_grab_nic_access(priv);
|
|
||||||
if (rc) {
|
|
||||||
IWL_WARNING("Can not read from adapter at this time.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* event log header */
|
|
||||||
capacity = iwl_read_targ_mem(priv, base);
|
|
||||||
mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
|
|
||||||
num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
|
|
||||||
next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
|
|
||||||
|
|
||||||
size = num_wraps ? capacity : next_entry;
|
|
||||||
|
|
||||||
/* bail out if nothing in log */
|
|
||||||
if (size == 0) {
|
|
||||||
IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
|
|
||||||
iwl_release_nic_access(priv);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n",
|
|
||||||
size, num_wraps);
|
|
||||||
|
|
||||||
/* 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)
|
|
||||||
iwl4965_print_event_log(priv, next_entry,
|
|
||||||
capacity - next_entry, mode);
|
|
||||||
|
|
||||||
/* (then/else) start at top of log */
|
|
||||||
iwl4965_print_event_log(priv, 0, next_entry, mode);
|
|
||||||
|
|
||||||
iwl_release_nic_access(priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iwl4965_irq_handle_error - called for HW or SW error interrupt from card
|
* iwl4965_irq_handle_error - called for HW or SW error interrupt from card
|
||||||
*/
|
*/
|
||||||
@ -2803,7 +2706,7 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)
|
|||||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||||
if (priv->debug_level & IWL_DL_FW_ERRORS) {
|
if (priv->debug_level & IWL_DL_FW_ERRORS) {
|
||||||
iwl4965_dump_nic_error_log(priv);
|
iwl4965_dump_nic_error_log(priv);
|
||||||
iwl4965_dump_nic_event_log(priv);
|
iwl_dump_nic_event_log(priv);
|
||||||
iwl4965_print_rx_config_cmd(priv);
|
iwl4965_print_rx_config_cmd(priv);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -5640,20 +5543,6 @@ static ssize_t dump_error_log(struct device *d,
|
|||||||
|
|
||||||
static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
|
static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
|
||||||
|
|
||||||
static ssize_t dump_event_log(struct device *d,
|
|
||||||
struct device_attribute *attr,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
char *p = (char *)buf;
|
|
||||||
|
|
||||||
if (p[0] == '1')
|
|
||||||
iwl4965_dump_nic_event_log((struct iwl_priv *)d->driver_data);
|
|
||||||
|
|
||||||
return strnlen(buf, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* driver setup and teardown
|
* driver setup and teardown
|
||||||
@ -5700,7 +5589,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
|
|||||||
static struct attribute *iwl4965_sysfs_entries[] = {
|
static struct attribute *iwl4965_sysfs_entries[] = {
|
||||||
&dev_attr_channels.attr,
|
&dev_attr_channels.attr,
|
||||||
&dev_attr_dump_errors.attr,
|
&dev_attr_dump_errors.attr,
|
||||||
&dev_attr_dump_events.attr,
|
|
||||||
&dev_attr_flags.attr,
|
&dev_attr_flags.attr,
|
||||||
&dev_attr_filter_flags.attr,
|
&dev_attr_filter_flags.attr,
|
||||||
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
|
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
|
||||||
|
Loading…
Reference in New Issue
Block a user