diff options
author | Ester Kummer <ester.kummer@intel.com> | 2008-05-15 01:54:18 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-21 21:48:07 -0400 |
commit | 189a2b5942d62bd18e1e01772c4c784253f5dd16 (patch) | |
tree | d5f85b77bccc796651d73243db76aa717d1f309c | |
parent | 6ba879562289bcad537a2374754ef750307c7d32 (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.c | 101 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debug.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debugfs.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 114 |
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 | } |
1056 | EXPORT_SYMBOL(iwl_verify_ucode); | 1056 | EXPORT_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 | */ | ||
1066 | void 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 | } | ||
1103 | EXPORT_SYMBOL(iwl_print_event_log); | ||
1104 | |||
1105 | |||
1106 | void 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 | } | ||
1156 | EXPORT_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 | ||
234 | int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); | 234 | int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); |
235 | |||
236 | /***************************************************** | ||
237 | * Error Handling Debugging | ||
238 | ******************************************************/ | ||
239 | void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | ||
240 | u32 num_events, u32 mode); | ||
241 | void 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); \ | ||
97 | static 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 | ||
335 | static 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 | |||
327 | DEBUGFS_READ_WRITE_FILE_OPS(sram); | 356 | DEBUGFS_READ_WRITE_FILE_OPS(sram); |
357 | DEBUGFS_WRITE_FILE_OPS(log_event); | ||
328 | DEBUGFS_READ_FILE_OPS(eeprom); | 358 | DEBUGFS_READ_FILE_OPS(eeprom); |
329 | DEBUGFS_READ_FILE_OPS(stations); | 359 | DEBUGFS_READ_FILE_OPS(stations); |
330 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 360 | DEBUGFS_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 | */ | ||
2702 | static 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 | |||
2740 | static 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 | ||
5641 | static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log); | 5544 | static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log); |
5642 | 5545 | ||
5643 | static 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 | |||
5655 | static 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) | |||
5700 | static struct attribute *iwl4965_sysfs_entries[] = { | 5589 | static 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 |