iwmc3200wifi: Add a last_fw_err debugfs entry
In order to check what was the last fw error we got accross resets, we add this debugfs entry. It displays the complete ASSERT information. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Родитель
d210176eaa
Коммит
04e715cd46
|
@ -108,6 +108,8 @@ struct iwm_debugfs {
|
|||
struct dentry *txq_dentry;
|
||||
struct dentry *tx_credit_dentry;
|
||||
struct dentry *rx_ticket_dentry;
|
||||
|
||||
struct dentry *fw_err_dentry;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IWM_DEBUG
|
||||
|
|
|
@ -98,7 +98,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_modules,
|
|||
iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write,
|
||||
"%llu\n");
|
||||
|
||||
static int iwm_txrx_open(struct inode *inode, struct file *filp)
|
||||
static int iwm_generic_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
filp->private_data = inode->i_private;
|
||||
return 0;
|
||||
|
@ -289,25 +289,111 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwm_debugfs_fw_err_read(struct file *filp,
|
||||
char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
||||
struct iwm_priv *iwm = filp->private_data;
|
||||
char buf[512];
|
||||
int buf_len = 512;
|
||||
size_t len = 0;
|
||||
|
||||
if (*ppos != 0)
|
||||
return 0;
|
||||
if (count < sizeof(buf))
|
||||
return -ENOSPC;
|
||||
|
||||
if (!iwm->last_fw_err)
|
||||
return -ENOMEM;
|
||||
|
||||
if (iwm->last_fw_err->line_num == 0)
|
||||
goto out;
|
||||
|
||||
len += snprintf(buf + len, buf_len - len, "%cMAC FW ERROR:\n",
|
||||
(le32_to_cpu(iwm->last_fw_err->category) == UMAC_SYS_ERR_CAT_LMAC)
|
||||
? 'L' : 'U');
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tCategory: %d\n",
|
||||
le32_to_cpu(iwm->last_fw_err->category));
|
||||
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tStatus: 0x%x\n",
|
||||
le32_to_cpu(iwm->last_fw_err->status));
|
||||
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tPC: 0x%x\n",
|
||||
le32_to_cpu(iwm->last_fw_err->pc));
|
||||
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tblink1: %d\n",
|
||||
le32_to_cpu(iwm->last_fw_err->blink1));
|
||||
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tblink2: %d\n",
|
||||
le32_to_cpu(iwm->last_fw_err->blink2));
|
||||
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tilink1: %d\n",
|
||||
le32_to_cpu(iwm->last_fw_err->ilink1));
|
||||
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tilink2: %d\n",
|
||||
le32_to_cpu(iwm->last_fw_err->ilink2));
|
||||
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tData1: 0x%x\n",
|
||||
le32_to_cpu(iwm->last_fw_err->data1));
|
||||
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tData2: 0x%x\n",
|
||||
le32_to_cpu(iwm->last_fw_err->data2));
|
||||
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tLine number: %d\n",
|
||||
le32_to_cpu(iwm->last_fw_err->line_num));
|
||||
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tUMAC status: 0x%x\n",
|
||||
le32_to_cpu(iwm->last_fw_err->umac_status));
|
||||
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tLMAC status: 0x%x\n",
|
||||
le32_to_cpu(iwm->last_fw_err->lmac_status));
|
||||
|
||||
len += snprintf(buf + len, buf_len - len,
|
||||
"\tSDIO status: 0x%x\n",
|
||||
le32_to_cpu(iwm->last_fw_err->sdio_status));
|
||||
|
||||
out:
|
||||
|
||||
return simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
|
||||
}
|
||||
|
||||
static const struct file_operations iwm_debugfs_txq_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = iwm_txrx_open,
|
||||
.open = iwm_generic_open,
|
||||
.read = iwm_debugfs_txq_read,
|
||||
};
|
||||
|
||||
static const struct file_operations iwm_debugfs_tx_credit_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = iwm_txrx_open,
|
||||
.open = iwm_generic_open,
|
||||
.read = iwm_debugfs_tx_credit_read,
|
||||
};
|
||||
|
||||
static const struct file_operations iwm_debugfs_rx_ticket_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = iwm_txrx_open,
|
||||
.open = iwm_generic_open,
|
||||
.read = iwm_debugfs_rx_ticket_read,
|
||||
};
|
||||
|
||||
static const struct file_operations iwm_debugfs_fw_err_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = iwm_generic_open,
|
||||
.read = iwm_debugfs_fw_err_read,
|
||||
};
|
||||
|
||||
int iwm_debugfs_init(struct iwm_priv *iwm)
|
||||
{
|
||||
int i, result;
|
||||
|
@ -423,6 +509,16 @@ int iwm_debugfs_init(struct iwm_priv *iwm)
|
|||
goto error;
|
||||
}
|
||||
|
||||
iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200,
|
||||
iwm->dbg.dbgdir, iwm,
|
||||
&iwm_debugfs_fw_err_fops);
|
||||
result = PTR_ERR(iwm->dbg.fw_err_dentry);
|
||||
if (IS_ERR(iwm->dbg.fw_err_dentry) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create last FW err: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
@ -441,6 +537,7 @@ void iwm_debugfs_exit(struct iwm_priv *iwm)
|
|||
debugfs_remove(iwm->dbg.txq_dentry);
|
||||
debugfs_remove(iwm->dbg.tx_credit_dentry);
|
||||
debugfs_remove(iwm->dbg.rx_ticket_dentry);
|
||||
debugfs_remove(iwm->dbg.fw_err_dentry);
|
||||
if (iwm->bus_ops->debugfs_exit)
|
||||
iwm->bus_ops->debugfs_exit(iwm);
|
||||
|
||||
|
|
|
@ -289,6 +289,8 @@ struct iwm_priv {
|
|||
u8 *resp_ie;
|
||||
int resp_ie_len;
|
||||
|
||||
struct iwm_fw_error_hdr *last_fw_err;
|
||||
|
||||
char private[0] __attribute__((__aligned__(NETDEV_ALIGN)));
|
||||
};
|
||||
|
||||
|
|
|
@ -260,6 +260,11 @@ int iwm_priv_init(struct iwm_priv *iwm)
|
|||
iwm->watchdog.data = (unsigned long)iwm;
|
||||
mutex_init(&iwm->mutex);
|
||||
|
||||
iwm->last_fw_err = kzalloc(sizeof(struct iwm_fw_error_hdr),
|
||||
GFP_KERNEL);
|
||||
if (iwm->last_fw_err == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -271,6 +276,7 @@ void iwm_priv_deinit(struct iwm_priv *iwm)
|
|||
destroy_workqueue(iwm->txq[i].wq);
|
||||
|
||||
destroy_workqueue(iwm->rx_wq);
|
||||
kfree(iwm->last_fw_err);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -102,6 +102,8 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,
|
|||
error = (struct iwm_umac_notif_error *)buf;
|
||||
fw_err = &error->err;
|
||||
|
||||
memcpy(iwm->last_fw_err, fw_err, sizeof(struct iwm_fw_error_hdr));
|
||||
|
||||
IWM_ERR(iwm, "%cMAC FW ERROR:\n",
|
||||
(le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U');
|
||||
IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category));
|
||||
|
|
Загрузка…
Ссылка в новой задаче