diff options
author | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2009-08-07 18:41:39 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-14 09:13:46 -0400 |
commit | 20594eb0daa67f7a0cc19d74a1bafceb1bb09f4a (patch) | |
tree | 9ae022adef73139b524dcd7dde9c6f02809e8cf1 /drivers/net/wireless/iwlwifi/iwl-debugfs.c | |
parent | 7aafef1c6e2e24f9a10dc2972bf0ee70624ccc47 (diff) |
iwlwifi: new debugging feature for dumping data traffic
The traffic buffer will only beallocated and used if either bit 23
(IWL_DX_TX) or bit 24 (IWL_DL_RX) of "debug" is set;
example: "debug=0x800000" - log tx data traffic
"debug=0x1000000" - log rx data traffic
"debug=0x1800000" - log both tx and rx traffic
The traffic log will store the beginning portion (64 bytes) of the
latest 256 of tx and rx packets in the round-robbin buffer for
debugging,
user can examine the log through debugfs file.
How to display the current logged tx/rx traffic and txfifo and rxfifo
read/write point:
"cat traffic_log" in /sys/kernel/debug/ieee80211/phy0/iwlagn/debug
directory
By echo "0" to traffic_log file will empty the traffic log buffer and
reset both tx and rx taffic log index to 0.
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-debugfs.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debugfs.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 6748a3fb966..031538c4206 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -712,6 +712,104 @@ DEBUGFS_READ_FILE_OPS(led); | |||
712 | DEBUGFS_READ_FILE_OPS(thermal_throttling); | 712 | DEBUGFS_READ_FILE_OPS(thermal_throttling); |
713 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); | 713 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); |
714 | 714 | ||
715 | static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, | ||
716 | char __user *user_buf, | ||
717 | size_t count, loff_t *ppos) | ||
718 | { | ||
719 | struct iwl_priv *priv = file->private_data; | ||
720 | int pos = 0, ofs = 0; | ||
721 | int cnt = 0, entry; | ||
722 | struct iwl_tx_queue *txq; | ||
723 | struct iwl_queue *q; | ||
724 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
725 | char *buf; | ||
726 | int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + | ||
727 | (IWL_MAX_NUM_QUEUES * 32 * 8) + 400; | ||
728 | const u8 *ptr; | ||
729 | ssize_t ret; | ||
730 | |||
731 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
732 | if (!buf) { | ||
733 | IWL_ERR(priv, "Can not allocate buffer\n"); | ||
734 | return -ENOMEM; | ||
735 | } | ||
736 | pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); | ||
737 | for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { | ||
738 | txq = &priv->txq[cnt]; | ||
739 | q = &txq->q; | ||
740 | pos += scnprintf(buf + pos, bufsz - pos, | ||
741 | "q[%d]: read_ptr: %u, write_ptr: %u\n", | ||
742 | cnt, q->read_ptr, q->write_ptr); | ||
743 | } | ||
744 | if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) { | ||
745 | ptr = priv->tx_traffic; | ||
746 | pos += scnprintf(buf + pos, bufsz - pos, | ||
747 | "Tx Traffic idx: %u\n", priv->tx_traffic_idx); | ||
748 | for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { | ||
749 | for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; | ||
750 | entry++, ofs += 16) { | ||
751 | pos += scnprintf(buf + pos, bufsz - pos, | ||
752 | "0x%.4x ", ofs); | ||
753 | hex_dump_to_buffer(ptr + ofs, 16, 16, 2, | ||
754 | buf + pos, bufsz - pos, 0); | ||
755 | pos += strlen(buf); | ||
756 | if (bufsz - pos > 0) | ||
757 | buf[pos++] = '\n'; | ||
758 | } | ||
759 | } | ||
760 | } | ||
761 | |||
762 | pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); | ||
763 | pos += scnprintf(buf + pos, bufsz - pos, | ||
764 | "read: %u, write: %u\n", | ||
765 | rxq->read, rxq->write); | ||
766 | |||
767 | if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) { | ||
768 | ptr = priv->rx_traffic; | ||
769 | pos += scnprintf(buf + pos, bufsz - pos, | ||
770 | "Rx Traffic idx: %u\n", priv->rx_traffic_idx); | ||
771 | for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { | ||
772 | for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; | ||
773 | entry++, ofs += 16) { | ||
774 | pos += scnprintf(buf + pos, bufsz - pos, | ||
775 | "0x%.4x ", ofs); | ||
776 | hex_dump_to_buffer(ptr + ofs, 16, 16, 2, | ||
777 | buf + pos, bufsz - pos, 0); | ||
778 | pos += strlen(buf); | ||
779 | if (bufsz - pos > 0) | ||
780 | buf[pos++] = '\n'; | ||
781 | } | ||
782 | } | ||
783 | } | ||
784 | |||
785 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
786 | kfree(buf); | ||
787 | return ret; | ||
788 | } | ||
789 | |||
790 | static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, | ||
791 | const char __user *user_buf, | ||
792 | size_t count, loff_t *ppos) | ||
793 | { | ||
794 | struct iwl_priv *priv = file->private_data; | ||
795 | char buf[8]; | ||
796 | int buf_size; | ||
797 | int traffic_log; | ||
798 | |||
799 | memset(buf, 0, sizeof(buf)); | ||
800 | buf_size = min(count, sizeof(buf) - 1); | ||
801 | if (copy_from_user(buf, user_buf, buf_size)) | ||
802 | return -EFAULT; | ||
803 | if (sscanf(buf, "%d", &traffic_log) != 1) | ||
804 | return -EFAULT; | ||
805 | if (traffic_log == 0) | ||
806 | iwl_reset_traffic_log(priv); | ||
807 | |||
808 | return count; | ||
809 | } | ||
810 | |||
811 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | ||
812 | |||
715 | /* | 813 | /* |
716 | * Create the debugfs files and directories | 814 | * Create the debugfs files and directories |
717 | * | 815 | * |
@@ -738,6 +836,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
738 | 836 | ||
739 | DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); | 837 | DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); |
740 | DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); | 838 | DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); |
839 | DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv); | ||
741 | DEBUGFS_ADD_FILE(nvm, data); | 840 | DEBUGFS_ADD_FILE(nvm, data); |
742 | DEBUGFS_ADD_FILE(sram, data); | 841 | DEBUGFS_ADD_FILE(sram, data); |
743 | DEBUGFS_ADD_FILE(log_event, data); | 842 | DEBUGFS_ADD_FILE(log_event, data); |
@@ -753,6 +852,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
753 | #endif | 852 | #endif |
754 | DEBUGFS_ADD_FILE(thermal_throttling, data); | 853 | DEBUGFS_ADD_FILE(thermal_throttling, data); |
755 | DEBUGFS_ADD_FILE(disable_ht40, data); | 854 | DEBUGFS_ADD_FILE(disable_ht40, data); |
855 | DEBUGFS_ADD_FILE(traffic_log, debug); | ||
756 | DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); | 856 | DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); |
757 | DEBUGFS_ADD_BOOL(disable_chain_noise, rf, | 857 | DEBUGFS_ADD_BOOL(disable_chain_noise, rf, |
758 | &priv->disable_chain_noise_cal); | 858 | &priv->disable_chain_noise_cal); |
@@ -794,6 +894,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
794 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling); | 894 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling); |
795 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40); | 895 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40); |
796 | DEBUGFS_REMOVE(priv->dbgfs->dir_data); | 896 | DEBUGFS_REMOVE(priv->dbgfs->dir_data); |
897 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log); | ||
898 | DEBUGFS_REMOVE(priv->dbgfs->dir_debug); | ||
797 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); | 899 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); |
798 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); | 900 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); |
799 | if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || | 901 | if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || |