aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/debugfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/debugfs.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c485
1 files changed, 475 insertions, 10 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 369d4c90e669..1b52deea6081 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -60,11 +60,14 @@
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 * 61 *
62 *****************************************************************************/ 62 *****************************************************************************/
63#include <linux/vmalloc.h>
64
63#include "mvm.h" 65#include "mvm.h"
64#include "sta.h" 66#include "sta.h"
65#include "iwl-io.h" 67#include "iwl-io.h"
66#include "iwl-prph.h" 68#include "iwl-prph.h"
67#include "debugfs.h" 69#include "debugfs.h"
70#include "fw-error-dump.h"
68 71
69static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, 72static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
70 size_t count, loff_t *ppos) 73 size_t count, loff_t *ppos)
@@ -90,7 +93,7 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
90static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf, 93static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
91 size_t count, loff_t *ppos) 94 size_t count, loff_t *ppos)
92{ 95{
93 struct ieee80211_sta *sta; 96 struct iwl_mvm_sta *mvmsta;
94 int sta_id, drain, ret; 97 int sta_id, drain, ret;
95 98
96 if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR) 99 if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
@@ -105,19 +108,63 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
105 108
106 mutex_lock(&mvm->mutex); 109 mutex_lock(&mvm->mutex);
107 110
108 sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], 111 mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
109 lockdep_is_held(&mvm->mutex)); 112
110 if (IS_ERR_OR_NULL(sta)) 113 if (!mvmsta)
111 ret = -ENOENT; 114 ret = -ENOENT;
112 else 115 else
113 ret = iwl_mvm_drain_sta(mvm, (void *)sta->drv_priv, drain) ? : 116 ret = iwl_mvm_drain_sta(mvm, mvmsta, drain) ? : count;
114 count;
115 117
116 mutex_unlock(&mvm->mutex); 118 mutex_unlock(&mvm->mutex);
117 119
118 return ret; 120 return ret;
119} 121}
120 122
123static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file)
124{
125 struct iwl_mvm *mvm = inode->i_private;
126 int ret;
127
128 if (!mvm)
129 return -EINVAL;
130
131 mutex_lock(&mvm->mutex);
132 if (!mvm->fw_error_dump) {
133 ret = -ENODATA;
134 goto out;
135 }
136
137 file->private_data = mvm->fw_error_dump;
138 mvm->fw_error_dump = NULL;
139 kfree(mvm->fw_error_sram);
140 mvm->fw_error_sram = NULL;
141 mvm->fw_error_sram_len = 0;
142 ret = 0;
143
144out:
145 mutex_unlock(&mvm->mutex);
146 return ret;
147}
148
149static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
150 char __user *user_buf,
151 size_t count, loff_t *ppos)
152{
153 struct iwl_fw_error_dump_file *dump_file = file->private_data;
154
155 return simple_read_from_buffer(user_buf, count, ppos,
156 dump_file,
157 le32_to_cpu(dump_file->file_len));
158}
159
160static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
161 struct file *file)
162{
163 vfree(file->private_data);
164
165 return 0;
166}
167
121static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, 168static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
122 size_t count, loff_t *ppos) 169 size_t count, loff_t *ppos)
123{ 170{
@@ -251,7 +298,7 @@ static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
251 } 298 }
252 299
253 mutex_lock(&mvm->mutex); 300 mutex_lock(&mvm->mutex);
254 ret = iwl_mvm_power_update_device_mode(mvm); 301 ret = iwl_mvm_power_update_device(mvm);
255 mutex_unlock(&mvm->mutex); 302 mutex_unlock(&mvm->mutex);
256 303
257 return ret ?: count; 304 return ret ?: count;
@@ -351,6 +398,9 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
351 le32_to_cpu(notif->secondary_ch_lut)); 398 le32_to_cpu(notif->secondary_ch_lut));
352 pos += scnprintf(buf+pos, bufsz-pos, "bt_activity_grading = %d\n", 399 pos += scnprintf(buf+pos, bufsz-pos, "bt_activity_grading = %d\n",
353 le32_to_cpu(notif->bt_activity_grading)); 400 le32_to_cpu(notif->bt_activity_grading));
401 pos += scnprintf(buf+pos, bufsz-pos,
402 "antenna isolation = %d CORUN LUT index = %d\n",
403 mvm->last_ant_isol, mvm->last_corun_lut);
354 404
355 mutex_unlock(&mvm->mutex); 405 mutex_unlock(&mvm->mutex);
356 406
@@ -393,6 +443,22 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
393 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 443 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
394} 444}
395 445
446static ssize_t
447iwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf,
448 size_t count, loff_t *ppos)
449{
450 u32 bt_tx_prio;
451
452 if (sscanf(buf, "%u", &bt_tx_prio) != 1)
453 return -EINVAL;
454 if (bt_tx_prio > 4)
455 return -EINVAL;
456
457 mvm->bt_tx_prio = bt_tx_prio;
458
459 return count;
460}
461
396#define PRINT_STATS_LE32(_str, _val) \ 462#define PRINT_STATS_LE32(_str, _val) \
397 pos += scnprintf(buf + pos, bufsz - pos, \ 463 pos += scnprintf(buf + pos, bufsz - pos, \
398 fmt_table, _str, \ 464 fmt_table, _str, \
@@ -532,6 +598,80 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
532} 598}
533#undef PRINT_STAT_LE32 599#undef PRINT_STAT_LE32
534 600
601static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
602 char __user *user_buf, size_t count,
603 loff_t *ppos,
604 struct iwl_mvm_frame_stats *stats)
605{
606 char *buff, *pos, *endpos;
607 int idx, i;
608 int ret;
609 static const size_t bufsz = 1024;
610
611 buff = kmalloc(bufsz, GFP_KERNEL);
612 if (!buff)
613 return -ENOMEM;
614
615 spin_lock_bh(&mvm->drv_stats_lock);
616
617 pos = buff;
618 endpos = pos + bufsz;
619
620 pos += scnprintf(pos, endpos - pos,
621 "Legacy/HT/VHT\t:\t%d/%d/%d\n",
622 stats->legacy_frames,
623 stats->ht_frames,
624 stats->vht_frames);
625 pos += scnprintf(pos, endpos - pos, "20/40/80\t:\t%d/%d/%d\n",
626 stats->bw_20_frames,
627 stats->bw_40_frames,
628 stats->bw_80_frames);
629 pos += scnprintf(pos, endpos - pos, "NGI/SGI\t\t:\t%d/%d\n",
630 stats->ngi_frames,
631 stats->sgi_frames);
632 pos += scnprintf(pos, endpos - pos, "SISO/MIMO2\t:\t%d/%d\n",
633 stats->siso_frames,
634 stats->mimo2_frames);
635 pos += scnprintf(pos, endpos - pos, "FAIL/SCSS\t:\t%d/%d\n",
636 stats->fail_frames,
637 stats->success_frames);
638 pos += scnprintf(pos, endpos - pos, "MPDUs agg\t:\t%d\n",
639 stats->agg_frames);
640 pos += scnprintf(pos, endpos - pos, "A-MPDUs\t\t:\t%d\n",
641 stats->ampdu_count);
642 pos += scnprintf(pos, endpos - pos, "Avg MPDUs/A-MPDU:\t%d\n",
643 stats->ampdu_count > 0 ?
644 (stats->agg_frames / stats->ampdu_count) : 0);
645
646 pos += scnprintf(pos, endpos - pos, "Last Rates\n");
647
648 idx = stats->last_frame_idx - 1;
649 for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) {
650 idx = (idx + 1) % ARRAY_SIZE(stats->last_rates);
651 if (stats->last_rates[idx] == 0)
652 continue;
653 pos += scnprintf(pos, endpos - pos, "Rate[%d]: ",
654 (int)(ARRAY_SIZE(stats->last_rates) - i));
655 pos += rs_pretty_print_rate(pos, stats->last_rates[idx]);
656 }
657 spin_unlock_bh(&mvm->drv_stats_lock);
658
659 ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
660 kfree(buff);
661
662 return ret;
663}
664
665static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file,
666 char __user *user_buf, size_t count,
667 loff_t *ppos)
668{
669 struct iwl_mvm *mvm = file->private_data;
670
671 return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos,
672 &mvm->drv_rx_stats);
673}
674
535static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, 675static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
536 size_t count, loff_t *ppos) 676 size_t count, loff_t *ppos)
537{ 677{
@@ -592,7 +732,7 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
592 return -EINVAL; 732 return -EINVAL;
593 if (scan_rx_ant > ANT_ABC) 733 if (scan_rx_ant > ANT_ABC)
594 return -EINVAL; 734 return -EINVAL;
595 if (scan_rx_ant & ~iwl_fw_valid_rx_ant(mvm->fw)) 735 if (scan_rx_ant & ~mvm->fw->valid_rx_ant)
596 return -EINVAL; 736 return -EINVAL;
597 737
598 mvm->scan_rx_ant = scan_rx_ant; 738 mvm->scan_rx_ant = scan_rx_ant;
@@ -600,6 +740,187 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
600 return count; 740 return count;
601} 741}
602 742
743#define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__)
744#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
745static ssize_t iwl_dbgfs_bcast_filters_read(struct file *file,
746 char __user *user_buf,
747 size_t count, loff_t *ppos)
748{
749 struct iwl_mvm *mvm = file->private_data;
750 struct iwl_bcast_filter_cmd cmd;
751 const struct iwl_fw_bcast_filter *filter;
752 char *buf;
753 int bufsz = 1024;
754 int i, j, pos = 0;
755 ssize_t ret;
756
757 buf = kzalloc(bufsz, GFP_KERNEL);
758 if (!buf)
759 return -ENOMEM;
760
761 mutex_lock(&mvm->mutex);
762 if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) {
763 ADD_TEXT("None\n");
764 mutex_unlock(&mvm->mutex);
765 goto out;
766 }
767 mutex_unlock(&mvm->mutex);
768
769 for (i = 0; cmd.filters[i].attrs[0].mask; i++) {
770 filter = &cmd.filters[i];
771
772 ADD_TEXT("Filter [%d]:\n", i);
773 ADD_TEXT("\tDiscard=%d\n", filter->discard);
774 ADD_TEXT("\tFrame Type: %s\n",
775 filter->frame_type ? "IPv4" : "Generic");
776
777 for (j = 0; j < ARRAY_SIZE(filter->attrs); j++) {
778 const struct iwl_fw_bcast_filter_attr *attr;
779
780 attr = &filter->attrs[j];
781 if (!attr->mask)
782 break;
783
784 ADD_TEXT("\tAttr [%d]: offset=%d (from %s), mask=0x%x, value=0x%x reserved=0x%x\n",
785 j, attr->offset,
786 attr->offset_type ? "IP End" :
787 "Payload Start",
788 be32_to_cpu(attr->mask),
789 be32_to_cpu(attr->val),
790 le16_to_cpu(attr->reserved1));
791 }
792 }
793out:
794 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
795 kfree(buf);
796 return ret;
797}
798
799static ssize_t iwl_dbgfs_bcast_filters_write(struct iwl_mvm *mvm, char *buf,
800 size_t count, loff_t *ppos)
801{
802 int pos, next_pos;
803 struct iwl_fw_bcast_filter filter = {};
804 struct iwl_bcast_filter_cmd cmd;
805 u32 filter_id, attr_id, mask, value;
806 int err = 0;
807
808 if (sscanf(buf, "%d %hhi %hhi %n", &filter_id, &filter.discard,
809 &filter.frame_type, &pos) != 3)
810 return -EINVAL;
811
812 if (filter_id >= ARRAY_SIZE(mvm->dbgfs_bcast_filtering.cmd.filters) ||
813 filter.frame_type > BCAST_FILTER_FRAME_TYPE_IPV4)
814 return -EINVAL;
815
816 for (attr_id = 0; attr_id < ARRAY_SIZE(filter.attrs);
817 attr_id++) {
818 struct iwl_fw_bcast_filter_attr *attr =
819 &filter.attrs[attr_id];
820
821 if (pos >= count)
822 break;
823
824 if (sscanf(&buf[pos], "%hhi %hhi %i %i %n",
825 &attr->offset, &attr->offset_type,
826 &mask, &value, &next_pos) != 4)
827 return -EINVAL;
828
829 attr->mask = cpu_to_be32(mask);
830 attr->val = cpu_to_be32(value);
831 if (mask)
832 filter.num_attrs++;
833
834 pos += next_pos;
835 }
836
837 mutex_lock(&mvm->mutex);
838 memcpy(&mvm->dbgfs_bcast_filtering.cmd.filters[filter_id],
839 &filter, sizeof(filter));
840
841 /* send updated bcast filtering configuration */
842 if (mvm->dbgfs_bcast_filtering.override &&
843 iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
844 err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC,
845 sizeof(cmd), &cmd);
846 mutex_unlock(&mvm->mutex);
847
848 return err ?: count;
849}
850
851static ssize_t iwl_dbgfs_bcast_filters_macs_read(struct file *file,
852 char __user *user_buf,
853 size_t count, loff_t *ppos)
854{
855 struct iwl_mvm *mvm = file->private_data;
856 struct iwl_bcast_filter_cmd cmd;
857 char *buf;
858 int bufsz = 1024;
859 int i, pos = 0;
860 ssize_t ret;
861
862 buf = kzalloc(bufsz, GFP_KERNEL);
863 if (!buf)
864 return -ENOMEM;
865
866 mutex_lock(&mvm->mutex);
867 if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) {
868 ADD_TEXT("None\n");
869 mutex_unlock(&mvm->mutex);
870 goto out;
871 }
872 mutex_unlock(&mvm->mutex);
873
874 for (i = 0; i < ARRAY_SIZE(cmd.macs); i++) {
875 const struct iwl_fw_bcast_mac *mac = &cmd.macs[i];
876
877 ADD_TEXT("Mac [%d]: discard=%d attached_filters=0x%x\n",
878 i, mac->default_discard, mac->attached_filters);
879 }
880out:
881 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
882 kfree(buf);
883 return ret;
884}
885
886static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
887 char *buf, size_t count,
888 loff_t *ppos)
889{
890 struct iwl_bcast_filter_cmd cmd;
891 struct iwl_fw_bcast_mac mac = {};
892 u32 mac_id, attached_filters;
893 int err = 0;
894
895 if (!mvm->bcast_filters)
896 return -ENOENT;
897
898 if (sscanf(buf, "%d %hhi %i", &mac_id, &mac.default_discard,
899 &attached_filters) != 3)
900 return -EINVAL;
901
902 if (mac_id >= ARRAY_SIZE(cmd.macs) ||
903 mac.default_discard > 1 ||
904 attached_filters >= BIT(ARRAY_SIZE(cmd.filters)))
905 return -EINVAL;
906
907 mac.attached_filters = cpu_to_le16(attached_filters);
908
909 mutex_lock(&mvm->mutex);
910 memcpy(&mvm->dbgfs_bcast_filtering.cmd.macs[mac_id],
911 &mac, sizeof(mac));
912
913 /* send updated bcast filtering configuration */
914 if (mvm->dbgfs_bcast_filtering.override &&
915 iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
916 err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC,
917 sizeof(cmd), &cmd);
918 mutex_unlock(&mvm->mutex);
919
920 return err ?: count;
921}
922#endif
923
603#ifdef CONFIG_PM_SLEEP 924#ifdef CONFIG_PM_SLEEP
604static ssize_t iwl_dbgfs_d3_sram_write(struct iwl_mvm *mvm, char *buf, 925static ssize_t iwl_dbgfs_d3_sram_write(struct iwl_mvm *mvm, char *buf,
605 size_t count, loff_t *ppos) 926 size_t count, loff_t *ppos)
@@ -658,15 +979,117 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
658} 979}
659#endif 980#endif
660 981
982#define PRINT_MVM_REF(ref) do { \
983 if (test_bit(ref, mvm->ref_bitmap)) \
984 pos += scnprintf(buf + pos, bufsz - pos, \
985 "\t(0x%lx) %s\n", \
986 BIT(ref), #ref); \
987} while (0)
988
989static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
990 char __user *user_buf,
991 size_t count, loff_t *ppos)
992{
993 struct iwl_mvm *mvm = file->private_data;
994 int pos = 0;
995 char buf[256];
996 const size_t bufsz = sizeof(buf);
997
998 pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%lx\n",
999 mvm->ref_bitmap[0]);
1000
1001 PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
1002 PRINT_MVM_REF(IWL_MVM_REF_SCAN);
1003 PRINT_MVM_REF(IWL_MVM_REF_ROC);
1004 PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT);
1005 PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS);
1006 PRINT_MVM_REF(IWL_MVM_REF_USER);
1007
1008 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1009}
1010
1011static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
1012 size_t count, loff_t *ppos)
1013{
1014 unsigned long value;
1015 int ret;
1016 bool taken;
1017
1018 ret = kstrtoul(buf, 10, &value);
1019 if (ret < 0)
1020 return ret;
1021
1022 mutex_lock(&mvm->mutex);
1023
1024 taken = test_bit(IWL_MVM_REF_USER, mvm->ref_bitmap);
1025 if (value == 1 && !taken)
1026 iwl_mvm_ref(mvm, IWL_MVM_REF_USER);
1027 else if (value == 0 && taken)
1028 iwl_mvm_unref(mvm, IWL_MVM_REF_USER);
1029 else
1030 ret = -EINVAL;
1031
1032 mutex_unlock(&mvm->mutex);
1033
1034 if (ret < 0)
1035 return ret;
1036 return count;
1037}
1038
661#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ 1039#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
662 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm) 1040 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
663#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ 1041#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
664 _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm) 1042 _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
665#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) do { \ 1043#define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do { \
666 if (!debugfs_create_file(#name, mode, parent, mvm, \ 1044 if (!debugfs_create_file(alias, mode, parent, mvm, \
667 &iwl_dbgfs_##name##_ops)) \ 1045 &iwl_dbgfs_##name##_ops)) \
668 goto err; \ 1046 goto err; \
669 } while (0) 1047 } while (0)
1048#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
1049 MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
1050
1051static ssize_t
1052iwl_dbgfs_prph_reg_read(struct file *file,
1053 char __user *user_buf,
1054 size_t count, loff_t *ppos)
1055{
1056 struct iwl_mvm *mvm = file->private_data;
1057 int pos = 0;
1058 char buf[32];
1059 const size_t bufsz = sizeof(buf);
1060
1061 if (!mvm->dbgfs_prph_reg_addr)
1062 return -EINVAL;
1063
1064 pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
1065 mvm->dbgfs_prph_reg_addr,
1066 iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
1067
1068 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1069}
1070
1071static ssize_t
1072iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
1073 size_t count, loff_t *ppos)
1074{
1075 u8 args;
1076 u32 value;
1077
1078 args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
1079 /* if we only want to set the reg address - nothing more to do */
1080 if (args == 1)
1081 goto out;
1082
1083 /* otherwise, make sure we have both address and value */
1084 if (args != 2)
1085 return -EINVAL;
1086
1087 iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
1088out:
1089 return count;
1090}
1091
1092MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
670 1093
671/* Device wide debugfs entries */ 1094/* Device wide debugfs entries */
672MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16); 1095MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
@@ -677,9 +1100,23 @@ MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
677MVM_DEBUGFS_READ_FILE_OPS(bt_cmd); 1100MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
678MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64); 1101MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
679MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); 1102MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
1103MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
680MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10); 1104MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
681MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10); 1105MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
1106MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
682MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); 1107MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
1108MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
1109
1110static const struct file_operations iwl_dbgfs_fw_error_dump_ops = {
1111 .open = iwl_dbgfs_fw_error_dump_open,
1112 .read = iwl_dbgfs_fw_error_dump_read,
1113 .release = iwl_dbgfs_fw_error_dump_release,
1114};
1115
1116#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
1117MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
1118MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
1119#endif
683 1120
684#ifdef CONFIG_PM_SLEEP 1121#ifdef CONFIG_PM_SLEEP
685MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); 1122MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
@@ -687,24 +1124,52 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
687 1124
688int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) 1125int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
689{ 1126{
1127 struct dentry *bcast_dir __maybe_unused;
690 char buf[100]; 1128 char buf[100];
691 1129
1130 spin_lock_init(&mvm->drv_stats_lock);
1131
692 mvm->debugfs_dir = dbgfs_dir; 1132 mvm->debugfs_dir = dbgfs_dir;
693 1133
694 MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, S_IWUSR); 1134 MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, S_IWUSR);
695 MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR); 1135 MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR);
696 MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR); 1136 MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
697 MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); 1137 MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
1138 MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR);
698 MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); 1139 MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
699 MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); 1140 MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
700 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD) 1141 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)
701 MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, 1142 MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
702 S_IRUSR | S_IWUSR); 1143 S_IRUSR | S_IWUSR);
703 MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR); 1144 MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR);
1145 MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR);
704 MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); 1146 MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
705 MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR); 1147 MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR);
1148 MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, S_IWUSR);
706 MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, 1149 MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir,
707 S_IWUSR | S_IRUSR); 1150 S_IWUSR | S_IRUSR);
1151 MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
1152 MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
1153
1154#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
1155 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) {
1156 bcast_dir = debugfs_create_dir("bcast_filtering",
1157 mvm->debugfs_dir);
1158 if (!bcast_dir)
1159 goto err;
1160
1161 if (!debugfs_create_bool("override", S_IRUSR | S_IWUSR,
1162 bcast_dir,
1163 &mvm->dbgfs_bcast_filtering.override))
1164 goto err;
1165
1166 MVM_DEBUGFS_ADD_FILE_ALIAS("filters", bcast_filters,
1167 bcast_dir, S_IWUSR | S_IRUSR);
1168 MVM_DEBUGFS_ADD_FILE_ALIAS("macs", bcast_filters_macs,
1169 bcast_dir, S_IWUSR | S_IRUSR);
1170 }
1171#endif
1172
708#ifdef CONFIG_PM_SLEEP 1173#ifdef CONFIG_PM_SLEEP
709 MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); 1174 MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
710 MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR); 1175 MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR);