Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 189a2b59 authored by Ester Kummer's avatar Ester Kummer Committed by John W. Linville
Browse files

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: default avatarEster Kummer <ester.kummer@intel.com>
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 6ba87956
Loading
Loading
Loading
Loading
+101 −0
Original line number Original line Diff line number Diff line
@@ -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);

+8 −0
Original line number Original line Diff line number Diff line
@@ -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 */
+1 −0
Original line number Original line Diff line number Diff line
@@ -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
+32 −0
Original line number Original line Diff line number Diff line
@@ -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
+1 −113
Original line number Original line Diff line number Diff line
@@ -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