iwlwifi: mvm: send udev event upon firmware error to dump logs
When the firmware asserts, the driver will dump the firmware state to an internal buffer. This buffer is kept aside until it is dumped through debugfs. Once an external application fetched the data, the buffer is freed and a new buffer can be allocated in case another assert occurs. A udev event is sent to trigger an external application. A simple rule like: DRIVER=="iwlwifi", ACTION=="change", RUN+="/sbin/dump_sram.sh" can fetch the data from debugfs. Here is my dump_sram.sh: phyname=$(basename ${DEVPATH}) date=$(date +%F_%H_%M) filename=/var/log/iwl-sram-${phyname}-${date}.bin cat /sys/kernel/debug/ieee80211/${phyname}/iwlwifi/iwlmvm/fw_error_dump > ${filename} The current SRAM size is 80KB so, currently: $ ls -lh iwl-sram-phy0-2014-03-16_13_14.bin -rw-r--r-- 1 emmanuel emmanuel 81K Mar 16 13:15 iwl-sram-phy0-2014-03-16_13_14.bin and after compression: $ ls -lh iwl-sram-phy0-2014-03-16_13_14.bin.xz -rw-r--r-- 1 emmanuel emmanuel 13K Mar 16 13:15 iwl-sram-phy0-2014-03-16_13_14.bin.xz Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
This commit is contained in:
@@ -65,6 +65,7 @@
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "debugfs.h"
|
||||
#include "fw-error-dump.h"
|
||||
|
||||
static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
@@ -117,6 +118,51 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct iwl_mvm *mvm = inode->i_private;
|
||||
int ret;
|
||||
|
||||
if (!mvm)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
if (!mvm->fw_error_dump) {
|
||||
ret = -ENODATA;
|
||||
goto out;
|
||||
}
|
||||
|
||||
file->private_data = mvm->fw_error_dump;
|
||||
mvm->fw_error_dump = NULL;
|
||||
kfree(mvm->fw_error_sram);
|
||||
mvm->fw_error_sram = NULL;
|
||||
mvm->fw_error_sram_len = 0;
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_fw_error_dump_file *dump_file = file->private_data;
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos,
|
||||
dump_file,
|
||||
le32_to_cpu(dump_file->file_len));
|
||||
}
|
||||
|
||||
static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
|
||||
struct file *file)
|
||||
{
|
||||
vfree(file->private_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
@@ -1042,6 +1088,12 @@ MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
|
||||
|
||||
static const struct file_operations iwl_dbgfs_fw_error_dump_ops = {
|
||||
.open = iwl_dbgfs_fw_error_dump_open,
|
||||
.read = iwl_dbgfs_fw_error_dump_read,
|
||||
.release = iwl_dbgfs_fw_error_dump_release,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
|
||||
@@ -1064,6 +1116,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||
MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)
|
||||
|
Reference in New Issue
Block a user