Commit 1f7b6172 authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by John W. Linville

iwlagn: move isr_statistics to transport layer

It is accessed by the transport layer only, hence the move.
The debugfs handlers that accessed it moved to the transport layer too.
The rx_handlers part of it stayed in the upper layer and a special debugfs
has been added for it

Also add missing includes to iwl-commands.h.
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e4ef84d9
...@@ -69,6 +69,9 @@ ...@@ -69,6 +69,9 @@
#ifndef __iwl_commands_h__ #ifndef __iwl_commands_h__
#define __iwl_commands_h__ #define __iwl_commands_h__
#include <linux/etherdevice.h>
#include <linux/ieee80211.h>
struct iwl_priv; struct iwl_priv;
/* uCode version contains 4 values: Major/Minor/API/Serial */ /* uCode version contains 4 values: Major/Minor/API/Serial */
......
...@@ -1121,11 +1121,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) ...@@ -1121,11 +1121,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
&statistics_cmd); &statistics_cmd);
} }
void iwl_clear_isr_stats(struct iwl_priv *priv)
{
memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
}
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params) const struct ieee80211_tx_queue_params *params)
{ {
......
...@@ -387,8 +387,6 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, ...@@ -387,8 +387,6 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
} }
#endif #endif
void iwl_clear_isr_stats(struct iwl_priv *priv);
/***************************************************** /*****************************************************
* GEOS * GEOS
******************************************************/ ******************************************************/
......
...@@ -556,11 +556,12 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, ...@@ -556,11 +556,12 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos); return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
} }
static ssize_t iwl_dbgfs_interrupt_read(struct file *file, static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) { size_t count, loff_t *ppos) {
struct iwl_priv *priv = file->private_data; struct iwl_priv *priv = file->private_data;
int pos = 0; int pos = 0;
int cnt = 0; int cnt = 0;
char *buf; char *buf;
...@@ -573,61 +574,25 @@ static ssize_t iwl_dbgfs_interrupt_read(struct file *file, ...@@ -573,61 +574,25 @@ static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
return -ENOMEM; return -ENOMEM;
} }
pos += scnprintf(buf + pos, bufsz - pos,
"Interrupt Statistics Report:\n");
pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
priv->isr_stats.hw);
pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
priv->isr_stats.sw);
if (priv->isr_stats.sw || priv->isr_stats.hw) {
pos += scnprintf(buf + pos, bufsz - pos,
"\tLast Restarting Code: 0x%X\n",
priv->isr_stats.err_code);
}
#ifdef CONFIG_IWLWIFI_DEBUG
pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
priv->isr_stats.sch);
pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
priv->isr_stats.alive);
#endif
pos += scnprintf(buf + pos, bufsz - pos,
"HW RF KILL switch toggled:\t %u\n",
priv->isr_stats.rfkill);
pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
priv->isr_stats.ctkill);
pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
priv->isr_stats.wakeup);
pos += scnprintf(buf + pos, bufsz - pos,
"Rx command responses:\t\t %u\n",
priv->isr_stats.rx);
for (cnt = 0; cnt < REPLY_MAX; cnt++) { for (cnt = 0; cnt < REPLY_MAX; cnt++) {
if (priv->isr_stats.rx_handlers[cnt] > 0) if (priv->rx_handlers_stats[cnt] > 0)
pos += scnprintf(buf + pos, bufsz - pos, pos += scnprintf(buf + pos, bufsz - pos,
"\tRx handler[%36s]:\t\t %u\n", "\tRx handler[%36s]:\t\t %u\n",
get_cmd_string(cnt), get_cmd_string(cnt),
priv->isr_stats.rx_handlers[cnt]); priv->rx_handlers_stats[cnt]);
} }
pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
priv->isr_stats.tx);
pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
priv->isr_stats.unhandled);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf); kfree(buf);
return ret; return ret;
} }
static ssize_t iwl_dbgfs_interrupt_write(struct file *file, static ssize_t iwl_dbgfs_rx_handlers_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)
{ {
struct iwl_priv *priv = file->private_data; struct iwl_priv *priv = file->private_data;
char buf[8]; char buf[8];
int buf_size; int buf_size;
u32 reset_flag; u32 reset_flag;
...@@ -639,7 +604,8 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, ...@@ -639,7 +604,8 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
if (sscanf(buf, "%x", &reset_flag) != 1) if (sscanf(buf, "%x", &reset_flag) != 1)
return -EFAULT; return -EFAULT;
if (reset_flag == 0) if (reset_flag == 0)
iwl_clear_isr_stats(priv); memset(&priv->rx_handlers_stats[0], 0,
sizeof(priv->rx_handlers_stats));
return count; return count;
} }
...@@ -834,7 +800,7 @@ DEBUGFS_READ_FILE_OPS(nvm); ...@@ -834,7 +800,7 @@ 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);
DEBUGFS_READ_FILE_OPS(status); DEBUGFS_READ_FILE_OPS(status);
DEBUGFS_READ_WRITE_FILE_OPS(interrupt); DEBUGFS_READ_WRITE_FILE_OPS(rx_handlers);
DEBUGFS_READ_FILE_OPS(qos); DEBUGFS_READ_FILE_OPS(qos);
DEBUGFS_READ_FILE_OPS(thermal_throttling); DEBUGFS_READ_FILE_OPS(thermal_throttling);
DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
...@@ -2471,7 +2437,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) ...@@ -2471,7 +2437,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_handlers, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
......
...@@ -810,22 +810,6 @@ enum iwl_pa_type { ...@@ -810,22 +810,6 @@ enum iwl_pa_type {
IWL_PA_INTERNAL = 1, IWL_PA_INTERNAL = 1,
}; };
/* interrupt statistics */
struct isr_statistics {
u32 hw;
u32 sw;
u32 err_code;
u32 sch;
u32 alive;
u32 rfkill;
u32 ctkill;
u32 wakeup;
u32 rx;
u32 rx_handlers[REPLY_MAX];
u32 tx;
u32 unhandled;
};
/* reply_tx_statistics (for _agn devices) */ /* reply_tx_statistics (for _agn devices) */
struct reply_tx_error_statistics { struct reply_tx_error_statistics {
u32 pp_delay; u32 pp_delay;
...@@ -1155,6 +1139,9 @@ struct iwl_priv { ...@@ -1155,6 +1139,9 @@ struct iwl_priv {
/* jiffies when last recovery from statistics was performed */ /* jiffies when last recovery from statistics was performed */
unsigned long rx_statistics_jiffies; unsigned long rx_statistics_jiffies;
/*counters */
u32 rx_handlers_stats[REPLY_MAX];
/* force reset */ /* force reset */
struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
...@@ -1258,10 +1245,6 @@ struct iwl_priv { ...@@ -1258,10 +1245,6 @@ struct iwl_priv {
struct traffic_stats tx_stats; struct traffic_stats tx_stats;
struct traffic_stats rx_stats; struct traffic_stats rx_stats;
/* counts interrupts */
/* TODO: move to the transport layer */
struct isr_statistics isr_stats;
struct iwl_power_mgr power_data; struct iwl_power_mgr power_data;
struct iwl_tt_mgmt thermal_throttle; struct iwl_tt_mgmt thermal_throttle;
......
...@@ -1020,7 +1020,7 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) ...@@ -1020,7 +1020,7 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
* handle those that need handling via function in * handle those that need handling via function in
* rx_handlers table. See iwl_setup_rx_handlers() */ * rx_handlers table. See iwl_setup_rx_handlers() */
if (priv->rx_handlers[pkt->hdr.cmd]) { if (priv->rx_handlers[pkt->hdr.cmd]) {
priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; priv->rx_handlers_stats[pkt->hdr.cmd]++;
priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
} else { } else {
/* No handling needed */ /* No handling needed */
......
...@@ -32,6 +32,24 @@ ...@@ -32,6 +32,24 @@
/*This file includes the declaration that are internal to the /*This file includes the declaration that are internal to the
* trans_pcie layer */ * trans_pcie layer */
/**
* struct isr_statistics - interrupt statistics
*
*/
struct isr_statistics {
u32 hw;
u32 sw;
u32 err_code;
u32 sch;
u32 alive;
u32 rfkill;
u32 ctkill;
u32 wakeup;
u32 rx;
u32 tx;
u32 unhandled;
};
/** /**
* struct iwl_rx_queue - Rx queue * struct iwl_rx_queue - Rx queue
* @bd: driver's pointer to buffer of receive buffer descriptors (rbd) * @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
...@@ -88,6 +106,7 @@ struct iwl_trans_pcie { ...@@ -88,6 +106,7 @@ struct iwl_trans_pcie {
u32 inta; u32 inta;
bool use_ict; bool use_ict;
struct tasklet_struct irq_tasklet; struct tasklet_struct irq_tasklet;
struct isr_statistics isr_stats;
u32 inta_mask; u32 inta_mask;
}; };
......
...@@ -569,6 +569,9 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv) ...@@ -569,6 +569,9 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
{ {
u32 base; u32 base;
struct iwl_error_event_table table; struct iwl_error_event_table table;
struct iwl_trans *trans = trans(priv);
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
base = priv->device_pointers.error_event_table; base = priv->device_pointers.error_event_table;
if (priv->ucode_type == IWL_UCODE_INIT) { if (priv->ucode_type == IWL_UCODE_INIT) {
...@@ -596,7 +599,7 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv) ...@@ -596,7 +599,7 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
priv->shrd->status, table.valid); priv->shrd->status, table.valid);
} }
priv->isr_stats.err_code = table.error_id; trans_pcie->isr_stats.err_code = table.error_id;
trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low, trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low,
table.data1, table.data2, table.line, table.data1, table.data2, table.line,
...@@ -905,6 +908,8 @@ void iwl_irq_tasklet(struct iwl_trans *trans) ...@@ -905,6 +908,8 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie = struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans); IWL_TRANS_GET_PCIE_TRANS(trans);
struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
spin_lock_irqsave(&trans->shrd->lock, flags); spin_lock_irqsave(&trans->shrd->lock, flags);
...@@ -945,7 +950,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) ...@@ -945,7 +950,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
/* Tell the device to stop sending interrupts */ /* Tell the device to stop sending interrupts */
iwl_disable_interrupts(trans); iwl_disable_interrupts(trans);
priv(trans)->isr_stats.hw++; isr_stats->hw++;
iwl_irq_handle_error(priv(trans)); iwl_irq_handle_error(priv(trans));
handled |= CSR_INT_BIT_HW_ERR; handled |= CSR_INT_BIT_HW_ERR;
...@@ -959,13 +964,13 @@ void iwl_irq_tasklet(struct iwl_trans *trans) ...@@ -959,13 +964,13 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
if (inta & CSR_INT_BIT_SCD) { if (inta & CSR_INT_BIT_SCD) {
IWL_DEBUG_ISR(trans, "Scheduler finished to transmit " IWL_DEBUG_ISR(trans, "Scheduler finished to transmit "
"the frame/frames.\n"); "the frame/frames.\n");
priv(trans)->isr_stats.sch++; isr_stats->sch++;
} }
/* Alive notification via Rx interrupt will do the real work */ /* Alive notification via Rx interrupt will do the real work */
if (inta & CSR_INT_BIT_ALIVE) { if (inta & CSR_INT_BIT_ALIVE) {
IWL_DEBUG_ISR(trans, "Alive interrupt\n"); IWL_DEBUG_ISR(trans, "Alive interrupt\n");
priv(trans)->isr_stats.alive++; isr_stats->alive++;
} }
} }
#endif #endif
...@@ -982,7 +987,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) ...@@ -982,7 +987,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
IWL_WARN(trans, "RF_KILL bit toggled to %s.\n", IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
hw_rf_kill ? "disable radio" : "enable radio"); hw_rf_kill ? "disable radio" : "enable radio");
priv(trans)->isr_stats.rfkill++; isr_stats->rfkill++;
/* driver only loads ucode once setting the interface up. /* driver only loads ucode once setting the interface up.
* the driver allows loading the ucode even if the radio * the driver allows loading the ucode even if the radio
...@@ -1006,7 +1011,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) ...@@ -1006,7 +1011,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
/* Chip got too hot and stopped itself */ /* Chip got too hot and stopped itself */
if (inta & CSR_INT_BIT_CT_KILL) { if (inta & CSR_INT_BIT_CT_KILL) {
IWL_ERR(trans, "Microcode CT kill error detected.\n"); IWL_ERR(trans, "Microcode CT kill error detected.\n");
priv(trans)->isr_stats.ctkill++; isr_stats->ctkill++;
handled |= CSR_INT_BIT_CT_KILL; handled |= CSR_INT_BIT_CT_KILL;
} }
...@@ -1014,7 +1019,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) ...@@ -1014,7 +1019,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
if (inta & CSR_INT_BIT_SW_ERR) { if (inta & CSR_INT_BIT_SW_ERR) {
IWL_ERR(trans, "Microcode SW error detected. " IWL_ERR(trans, "Microcode SW error detected. "
" Restarting 0x%X.\n", inta); " Restarting 0x%X.\n", inta);
priv(trans)->isr_stats.sw++; isr_stats->sw++;
iwl_irq_handle_error(priv(trans)); iwl_irq_handle_error(priv(trans));
handled |= CSR_INT_BIT_SW_ERR; handled |= CSR_INT_BIT_SW_ERR;
} }
...@@ -1027,7 +1032,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) ...@@ -1027,7 +1032,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
iwl_txq_update_write_ptr(priv(trans), iwl_txq_update_write_ptr(priv(trans),
&priv(trans)->txq[i]); &priv(trans)->txq[i]);
priv(trans)->isr_stats.wakeup++; isr_stats->wakeup++;
handled |= CSR_INT_BIT_WAKEUP; handled |= CSR_INT_BIT_WAKEUP;
} }
...@@ -1075,14 +1080,14 @@ void iwl_irq_tasklet(struct iwl_trans *trans) ...@@ -1075,14 +1080,14 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
iwl_write8(priv(trans), CSR_INT_PERIODIC_REG, iwl_write8(priv(trans), CSR_INT_PERIODIC_REG,
CSR_INT_PERIODIC_ENA); CSR_INT_PERIODIC_ENA);
priv(trans)->isr_stats.rx++; isr_stats->rx++;
} }
/* This "Tx" DMA channel is used only for loading uCode */ /* This "Tx" DMA channel is used only for loading uCode */
if (inta & CSR_INT_BIT_FH_TX) { if (inta & CSR_INT_BIT_FH_TX) {
iwl_write32(priv(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); iwl_write32(priv(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK);
IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); IWL_DEBUG_ISR(trans, "uCode load interrupt\n");
priv(trans)->isr_stats.tx++; isr_stats->tx++;
handled |= CSR_INT_BIT_FH_TX; handled |= CSR_INT_BIT_FH_TX;
/* Wake up uCode load routine, now that load is complete */ /* Wake up uCode load routine, now that load is complete */
priv(trans)->ucode_write_complete = 1; priv(trans)->ucode_write_complete = 1;
...@@ -1091,7 +1096,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) ...@@ -1091,7 +1096,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
if (inta & ~handled) { if (inta & ~handled) {
IWL_ERR(trans, "Unhandled INTA bits 0x%08x\n", inta & ~handled); IWL_ERR(trans, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
priv(trans)->isr_stats.unhandled++; isr_stats->unhandled++;
} }
if (inta & ~(trans_pcie->inta_mask)) { if (inta & ~(trans_pcie->inta_mask)) {
......
...@@ -1496,8 +1496,95 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, ...@@ -1496,8 +1496,95 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
return count; return count;
} }
static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos) {
struct iwl_trans *trans = file->private_data;
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
int pos = 0;
char *buf;
int bufsz = 24 * 64; /* 24 items * 64 char per item */
ssize_t ret;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(trans, "Can not allocate Buffer\n");
return -ENOMEM;
}
pos += scnprintf(buf + pos, bufsz - pos,
"Interrupt Statistics Report:\n");
pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
isr_stats->hw);
pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
isr_stats->sw);
if (isr_stats->sw || isr_stats->hw) {
pos += scnprintf(buf + pos, bufsz - pos,
"\tLast Restarting Code: 0x%X\n",
isr_stats->err_code);
}
#ifdef CONFIG_IWLWIFI_DEBUG
pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
isr_stats->sch);
pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
isr_stats->alive);
#endif
pos += scnprintf(buf + pos, bufsz - pos,
"HW RF KILL switch toggled:\t %u\n", isr_stats->rfkill);
pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
isr_stats->ctkill);
pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
isr_stats->wakeup);
pos += scnprintf(buf + pos, bufsz - pos,
"Rx command responses:\t\t %u\n", isr_stats->rx);
pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
isr_stats->tx);
pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
isr_stats->unhandled);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
}
static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_trans *trans = file->private_data;
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
char buf[8];
int buf_size;
u32 reset_flag;
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, "%x", &reset_flag) != 1)
return -EFAULT;
if (reset_flag == 0)
memset(isr_stats, 0, sizeof(*isr_stats));
return count;
}
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
DEBUGFS_READ_WRITE_FILE_OPS(log_event); DEBUGFS_READ_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
DEBUGFS_READ_FILE_OPS(rx_queue); DEBUGFS_READ_FILE_OPS(rx_queue);
DEBUGFS_READ_FILE_OPS(tx_queue); DEBUGFS_READ_FILE_OPS(tx_queue);
...@@ -1512,6 +1599,7 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, ...@@ -1512,6 +1599,7 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR);
DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR);
DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR);
return 0; return 0;
} }
#else #else
......
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