aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEster Kummer <ester.kummer@intel.com>2008-05-15 01:54:18 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-21 21:48:07 -0400
commit189a2b5942d62bd18e1e01772c4c784253f5dd16 (patch)
treed5f85b77bccc796651d73243db76aa717d1f309c
parent6ba879562289bcad537a2374754ef750307c7d32 (diff)
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>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c101
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c32
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c114
5 files changed, 143 insertions, 113 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 21f481ef1ce2..7e25ca45f671 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1055,3 +1055,104 @@ int iwl_verify_ucode(struct iwl_priv *priv)
1055} 1055}
1056EXPORT_SYMBOL(iwl_verify_ucode); 1056EXPORT_SYMBOL(iwl_verify_ucode);
1057 1057
1058
1059#define EVENT_START_OFFSET (4 * sizeof(u32))
1060
1061/**
1062 * iwl_print_event_log - Dump error event log to syslog
1063 *
1064 * NOTE: Must be called with iwl4965_grab_nic_access() already obtained!
1065 */
1066void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
1067 u32 num_events, u32 mode)
1068{
1069 u32 i;
1070 u32 base; /* SRAM byte address of event log header */
1071 u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
1072 u32 ptr; /* SRAM byte address of log data */
1073 u32 ev, time, data; /* event log data */
1074
1075 if (num_events == 0)
1076 return;
1077
1078 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
1079
1080 if (mode == 0)
1081 event_size = 2 * sizeof(u32);
1082 else
1083 event_size = 3 * sizeof(u32);
1084
1085 ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
1086
1087 /* "time" is actually "data" for mode 0 (no timestamp).
1088 * place event id # at far right for easier visual parsing. */
1089 for (i = 0; i < num_events; i++) {
1090 ev = iwl_read_targ_mem(priv, ptr);
1091 ptr += sizeof(u32);
1092 time = iwl_read_targ_mem(priv, ptr);
1093 ptr += sizeof(u32);
1094 if (mode == 0)
1095 IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
1096 else {
1097 data = iwl_read_targ_mem(priv, ptr);
1098 ptr += sizeof(u32);
1099 IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
1100 }
1101 }
1102}
1103EXPORT_SYMBOL(iwl_print_event_log);
1104
1105
1106void iwl_dump_nic_event_log(struct iwl_priv *priv)
1107{
1108 int rc;
1109 u32 base; /* SRAM byte address of event log header */
1110 u32 capacity; /* event log capacity in # entries */
1111 u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
1112 u32 num_wraps; /* # times uCode wrapped to top of log */
1113 u32 next_entry; /* index of next entry to be written by uCode */
1114 u32 size; /* # entries that we'll print */
1115
1116 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
1117 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
1118 IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
1119 return;
1120 }
1121
1122 rc = iwl_grab_nic_access(priv);
1123 if (rc) {
1124 IWL_WARNING("Can not read from adapter at this time.\n");
1125 return;
1126 }
1127
1128 /* event log header */
1129 capacity = iwl_read_targ_mem(priv, base);
1130 mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
1131 num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
1132 next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
1133
1134 size = num_wraps ? capacity : next_entry;
1135
1136 /* bail out if nothing in log */
1137 if (size == 0) {
1138 IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
1139 iwl_release_nic_access(priv);
1140 return;
1141 }
1142
1143 IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n",
1144 size, num_wraps);
1145
1146 /* if uCode has wrapped back to top of log, start at the oldest entry,
1147 * i.e the next one that uCode would fill. */
1148 if (num_wraps)
1149 iwl_print_event_log(priv, next_entry,
1150 capacity - next_entry, mode);
1151 /* (then/else) start at top of log */
1152 iwl_print_event_log(priv, 0, next_entry, mode);
1153
1154 iwl_release_nic_access(priv);
1155}
1156EXPORT_SYMBOL(iwl_dump_nic_event_log);
1157
1158
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 774aa7c8a82a..a8d062f7b87a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -232,6 +232,14 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
232 struct sk_buff *skb)); 232 struct sk_buff *skb));
233 233
234int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); 234int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
235
236/*****************************************************
237* Error Handling Debugging
238******************************************************/
239void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
240 u32 num_events, u32 mode);
241void iwl_dump_nic_event_log(struct iwl_priv *priv);
242
235/*************** DRIVER STATUS FUNCTIONS *****/ 243/*************** DRIVER STATUS FUNCTIONS *****/
236 244
237#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ 245#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index c3f8e90c5ba7..11de561c7bf8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -52,6 +52,7 @@ struct iwl_debugfs {
52 struct dentry *file_stations; 52 struct dentry *file_stations;
53 struct dentry *file_rx_statistics; 53 struct dentry *file_rx_statistics;
54 struct dentry *file_tx_statistics; 54 struct dentry *file_tx_statistics;
55 struct dentry *file_log_event;
55 } dbgfs_data_files; 56 } dbgfs_data_files;
56 struct dir_rf_files { 57 struct dir_rf_files {
57#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB 58#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index f7ec2009cdf9..c64e602bc9b6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -92,6 +92,14 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
92 .open = iwl_dbgfs_open_file_generic, \ 92 .open = iwl_dbgfs_open_file_generic, \
93}; 93};
94 94
95#define DEBUGFS_WRITE_FILE_OPS(name) \
96 DEBUGFS_WRITE_FUNC(name); \
97static const struct file_operations iwl_dbgfs_##name##_ops = { \
98 .write = iwl_dbgfs_##name##_write, \
99 .open = iwl_dbgfs_open_file_generic, \
100};
101
102
95#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ 103#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
96 DEBUGFS_READ_FUNC(name); \ 104 DEBUGFS_READ_FUNC(name); \
97 DEBUGFS_WRITE_FUNC(name); \ 105 DEBUGFS_WRITE_FUNC(name); \
@@ -324,7 +332,29 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file,
324 return ret; 332 return ret;
325} 333}
326 334
335static ssize_t iwl_dbgfs_log_event_write(struct file *file,
336 const char __user *user_buf,
337 size_t count, loff_t *ppos)
338{
339 struct iwl_priv *priv = file->private_data;
340 u32 event_log_flag;
341 char buf[8];
342 int buf_size;
343
344 memset(buf, 0, sizeof(buf));
345 buf_size = min(count, sizeof(buf) - 1);
346 if (copy_from_user(buf, user_buf, buf_size))
347 return -EFAULT;
348 if (sscanf(buf, "%d", &event_log_flag) != 1)
349 return -EFAULT;
350 if (event_log_flag == 1)
351 iwl_dump_nic_event_log(priv);
352
353 return count;
354}
355
327DEBUGFS_READ_WRITE_FILE_OPS(sram); 356DEBUGFS_READ_WRITE_FILE_OPS(sram);
357DEBUGFS_WRITE_FILE_OPS(log_event);
328DEBUGFS_READ_FILE_OPS(eeprom); 358DEBUGFS_READ_FILE_OPS(eeprom);
329DEBUGFS_READ_FILE_OPS(stations); 359DEBUGFS_READ_FILE_OPS(stations);
330DEBUGFS_READ_FILE_OPS(rx_statistics); 360DEBUGFS_READ_FILE_OPS(rx_statistics);
@@ -354,6 +384,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
354 DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); 384 DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
355 DEBUGFS_ADD_FILE(eeprom, data); 385 DEBUGFS_ADD_FILE(eeprom, data);
356 DEBUGFS_ADD_FILE(sram, data); 386 DEBUGFS_ADD_FILE(sram, data);
387 DEBUGFS_ADD_FILE(log_event, data);
357 DEBUGFS_ADD_FILE(stations, data); 388 DEBUGFS_ADD_FILE(stations, data);
358 DEBUGFS_ADD_FILE(rx_statistics, data); 389 DEBUGFS_ADD_FILE(rx_statistics, data);
359 DEBUGFS_ADD_FILE(tx_statistics, data); 390 DEBUGFS_ADD_FILE(tx_statistics, data);
@@ -384,6 +415,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
384 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics); 415 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
385 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics); 416 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
386 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); 417 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
418 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
387 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); 419 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
388 DEBUGFS_REMOVE(priv->dbgfs->dir_data); 420 DEBUGFS_REMOVE(priv->dbgfs->dir_data);
389#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB 421#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 05edde178302..48c59cbefb4a 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -2692,103 +2692,6 @@ static void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
2692 iwl_release_nic_access(priv); 2692 iwl_release_nic_access(priv);
2693} 2693}
2694 2694
2695#define EVENT_START_OFFSET (4 * sizeof(u32))
2696
2697/**
2698 * iwl4965_print_event_log - Dump error event log to syslog
2699 *
2700 * NOTE: Must be called with iwl_grab_nic_access() already obtained!
2701 */
2702static void iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
2703 u32 num_events, u32 mode)
2704{
2705 u32 i;
2706 u32 base; /* SRAM byte address of event log header */
2707 u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
2708 u32 ptr; /* SRAM byte address of log data */
2709 u32 ev, time, data; /* event log data */
2710
2711 if (num_events == 0)
2712 return;
2713
2714 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
2715
2716 if (mode == 0)
2717 event_size = 2 * sizeof(u32);
2718 else
2719 event_size = 3 * sizeof(u32);
2720
2721 ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
2722
2723 /* "time" is actually "data" for mode 0 (no timestamp).
2724 * place event id # at far right for easier visual parsing. */
2725 for (i = 0; i < num_events; i++) {
2726 ev = iwl_read_targ_mem(priv, ptr);
2727 ptr += sizeof(u32);
2728 time = iwl_read_targ_mem(priv, ptr);
2729 ptr += sizeof(u32);
2730 if (mode == 0)
2731 IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
2732 else {
2733 data = iwl_read_targ_mem(priv, ptr);
2734 ptr += sizeof(u32);
2735 IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
2736 }
2737 }
2738}
2739
2740static void iwl4965_dump_nic_event_log(struct iwl_priv *priv)
2741{
2742 int rc;
2743 u32 base; /* SRAM byte address of event log header */
2744 u32 capacity; /* event log capacity in # entries */
2745 u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
2746 u32 num_wraps; /* # times uCode wrapped to top of log */
2747 u32 next_entry; /* index of next entry to be written by uCode */
2748 u32 size; /* # entries that we'll print */
2749
2750 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
2751 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
2752 IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
2753 return;
2754 }
2755
2756 rc = iwl_grab_nic_access(priv);
2757 if (rc) {
2758 IWL_WARNING("Can not read from adapter at this time.\n");
2759 return;
2760 }
2761
2762 /* event log header */
2763 capacity = iwl_read_targ_mem(priv, base);
2764 mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
2765 num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
2766 next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
2767
2768 size = num_wraps ? capacity : next_entry;
2769
2770 /* bail out if nothing in log */
2771 if (size == 0) {
2772 IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
2773 iwl_release_nic_access(priv);
2774 return;
2775 }
2776
2777 IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n",
2778 size, num_wraps);
2779
2780 /* if uCode has wrapped back to top of log, start at the oldest entry,
2781 * i.e the next one that uCode would fill. */
2782 if (num_wraps)
2783 iwl4965_print_event_log(priv, next_entry,
2784 capacity - next_entry, mode);
2785
2786 /* (then/else) start at top of log */
2787 iwl4965_print_event_log(priv, 0, next_entry, mode);
2788
2789 iwl_release_nic_access(priv);
2790}
2791
2792/** 2695/**
2793 * iwl4965_irq_handle_error - called for HW or SW error interrupt from card 2696 * iwl4965_irq_handle_error - called for HW or SW error interrupt from card
2794 */ 2697 */
@@ -2803,7 +2706,7 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)
2803#ifdef CONFIG_IWLWIFI_DEBUG 2706#ifdef CONFIG_IWLWIFI_DEBUG
2804 if (priv->debug_level & IWL_DL_FW_ERRORS) { 2707 if (priv->debug_level & IWL_DL_FW_ERRORS) {
2805 iwl4965_dump_nic_error_log(priv); 2708 iwl4965_dump_nic_error_log(priv);
2806 iwl4965_dump_nic_event_log(priv); 2709 iwl_dump_nic_event_log(priv);
2807 iwl4965_print_rx_config_cmd(priv); 2710 iwl4965_print_rx_config_cmd(priv);
2808 } 2711 }
2809#endif 2712#endif
@@ -5640,20 +5543,6 @@ static ssize_t dump_error_log(struct device *d,
5640 5543
5641static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log); 5544static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
5642 5545
5643static ssize_t dump_event_log(struct device *d,
5644 struct device_attribute *attr,
5645 const char *buf, size_t count)
5646{
5647 char *p = (char *)buf;
5648
5649 if (p[0] == '1')
5650 iwl4965_dump_nic_event_log((struct iwl_priv *)d->driver_data);
5651
5652 return strnlen(buf, count);
5653}
5654
5655static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
5656
5657/***************************************************************************** 5546/*****************************************************************************
5658 * 5547 *
5659 * driver setup and teardown 5548 * driver setup and teardown
@@ -5700,7 +5589,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
5700static struct attribute *iwl4965_sysfs_entries[] = { 5589static struct attribute *iwl4965_sysfs_entries[] = {
5701 &dev_attr_channels.attr, 5590 &dev_attr_channels.attr,
5702 &dev_attr_dump_errors.attr, 5591 &dev_attr_dump_errors.attr,
5703 &dev_attr_dump_events.attr,
5704 &dev_attr_flags.attr, 5592 &dev_attr_flags.attr,
5705 &dev_attr_filter_flags.attr, 5593 &dev_attr_filter_flags.attr,
5706#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT 5594#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT