aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c79
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c57
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h5
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c5
4 files changed, 47 insertions, 99 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 2a61baca5081..51b7116965ed 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -121,78 +121,6 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
121 return ret; 121 return ret;
122} 122}
123 123
124static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file)
125{
126 struct iwl_mvm *mvm = inode->i_private;
127 int ret;
128
129 if (!mvm)
130 return -EINVAL;
131
132 mutex_lock(&mvm->mutex);
133 if (!mvm->fw_error_dump) {
134 ret = -ENODATA;
135 goto out;
136 }
137
138 file->private_data = mvm->fw_error_dump;
139 mvm->fw_error_dump = NULL;
140 ret = 0;
141
142out:
143 mutex_unlock(&mvm->mutex);
144 return ret;
145}
146
147static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
148 char __user *user_buf,
149 size_t count, loff_t *ppos)
150{
151 struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
152 ssize_t bytes_read = 0;
153 ssize_t bytes_read_trans = 0;
154
155 if (*ppos < dump_ptrs->op_mode_len)
156 bytes_read +=
157 simple_read_from_buffer(user_buf, count, ppos,
158 dump_ptrs->op_mode_ptr,
159 dump_ptrs->op_mode_len);
160
161 if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len)
162 return bytes_read;
163
164 if (dump_ptrs->trans_ptr) {
165 *ppos -= dump_ptrs->op_mode_len;
166 bytes_read_trans =
167 simple_read_from_buffer(user_buf + bytes_read,
168 count - bytes_read, ppos,
169 dump_ptrs->trans_ptr->data,
170 dump_ptrs->trans_ptr->len);
171 *ppos += dump_ptrs->op_mode_len;
172
173 if (bytes_read_trans >= 0)
174 bytes_read += bytes_read_trans;
175 else if (!bytes_read)
176 /* propagate the failure */
177 return bytes_read_trans;
178 }
179
180 return bytes_read;
181
182}
183
184static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
185 struct file *file)
186{
187 struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
188
189 vfree(dump_ptrs->op_mode_ptr);
190 vfree(dump_ptrs->trans_ptr);
191 kfree(dump_ptrs);
192
193 return 0;
194}
195
196static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, 124static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
197 size_t count, loff_t *ppos) 125 size_t count, loff_t *ppos)
198{ 126{
@@ -1535,12 +1463,6 @@ MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
1535MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); 1463MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
1536MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); 1464MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
1537 1465
1538static const struct file_operations iwl_dbgfs_fw_error_dump_ops = {
1539 .open = iwl_dbgfs_fw_error_dump_open,
1540 .read = iwl_dbgfs_fw_error_dump_read,
1541 .release = iwl_dbgfs_fw_error_dump_release,
1542};
1543
1544#ifdef CONFIG_IWLWIFI_BCAST_FILTERING 1466#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
1545MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); 1467MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
1546MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); 1468MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
@@ -1567,7 +1489,6 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
1567 S_IWUSR | S_IRUSR); 1489 S_IWUSR | S_IRUSR);
1568 MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR); 1490 MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR);
1569 MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); 1491 MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
1570 MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR);
1571 MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); 1492 MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
1572 MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); 1493 MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
1573 MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, 1494 MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 14be10829510..3276b31898da 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -69,6 +69,7 @@
69#include <linux/etherdevice.h> 69#include <linux/etherdevice.h>
70#include <linux/ip.h> 70#include <linux/ip.h>
71#include <linux/if_arp.h> 71#include <linux/if_arp.h>
72#include <linux/devcoredump.h>
72#include <net/mac80211.h> 73#include <net/mac80211.h>
73#include <net/ieee80211_radiotap.h> 74#include <net/ieee80211_radiotap.h>
74#include <net/tcp.h> 75#include <net/tcp.h>
@@ -679,10 +680,51 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
679 memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data)); 680 memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
680} 681}
681 682
682#ifdef CONFIG_IWLWIFI_DEBUGFS 683static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count,
684 const void *data, size_t datalen)
685{
686 const struct iwl_mvm_dump_ptrs *dump_ptrs = data;
687 ssize_t bytes_read;
688 ssize_t bytes_read_trans;
689
690 if (offset < dump_ptrs->op_mode_len) {
691 bytes_read = min_t(ssize_t, count,
692 dump_ptrs->op_mode_len - offset);
693 memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset,
694 bytes_read);
695 offset += bytes_read;
696 count -= bytes_read;
697
698 if (count == 0)
699 return bytes_read;
700 } else {
701 bytes_read = 0;
702 }
703
704 if (!dump_ptrs->trans_ptr)
705 return bytes_read;
706
707 offset -= dump_ptrs->op_mode_len;
708 bytes_read_trans = min_t(ssize_t, count,
709 dump_ptrs->trans_ptr->len - offset);
710 memcpy(buffer + bytes_read,
711 (u8 *)dump_ptrs->trans_ptr->data + offset,
712 bytes_read_trans);
713
714 return bytes_read + bytes_read_trans;
715}
716
717static void iwl_mvm_free_coredump(const void *data)
718{
719 const struct iwl_mvm_dump_ptrs *fw_error_dump = data;
720
721 vfree(fw_error_dump->op_mode_ptr);
722 vfree(fw_error_dump->trans_ptr);
723 kfree(fw_error_dump);
724}
725
683void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) 726void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
684{ 727{
685 static char *env[] = { "DRIVER=iwlwifi", "EVENT=error_dump", NULL };
686 struct iwl_fw_error_dump_file *dump_file; 728 struct iwl_fw_error_dump_file *dump_file;
687 struct iwl_fw_error_dump_data *dump_data; 729 struct iwl_fw_error_dump_data *dump_data;
688 struct iwl_fw_error_dump_info *dump_info; 730 struct iwl_fw_error_dump_info *dump_info;
@@ -695,10 +737,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
695 737
696 lockdep_assert_held(&mvm->mutex); 738 lockdep_assert_held(&mvm->mutex);
697 739
698 if (mvm->fw_error_dump) 740 fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
699 return;
700
701 fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL);
702 if (!fw_error_dump) 741 if (!fw_error_dump)
703 return; 742 return;
704 743
@@ -773,12 +812,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
773 if (fw_error_dump->trans_ptr) 812 if (fw_error_dump->trans_ptr)
774 file_len += fw_error_dump->trans_ptr->len; 813 file_len += fw_error_dump->trans_ptr->len;
775 dump_file->file_len = cpu_to_le32(file_len); 814 dump_file->file_len = cpu_to_le32(file_len);
776 mvm->fw_error_dump = fw_error_dump;
777 815
778 /* notify the userspace about the error we had */ 816 dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0,
779 kobject_uevent_env(&mvm->hw->wiphy->dev.kobj, KOBJ_CHANGE, env); 817 GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump);
780} 818}
781#endif
782 819
783static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) 820static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
784{ 821{
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index d14dc061d1c2..256765accbc6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -648,7 +648,6 @@ struct iwl_mvm {
648 /* -1 for always, 0 for never, >0 for that many times */ 648 /* -1 for always, 0 for never, >0 for that many times */
649 s8 restart_fw; 649 s8 restart_fw;
650 struct work_struct fw_error_dump_wk; 650 struct work_struct fw_error_dump_wk;
651 struct iwl_mvm_dump_ptrs *fw_error_dump;
652 651
653#ifdef CONFIG_IWLWIFI_LEDS 652#ifdef CONFIG_IWLWIFI_LEDS
654 struct led_classdev led; 653 struct led_classdev led;
@@ -1216,10 +1215,6 @@ void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
1216struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm); 1215struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
1217 1216
1218void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error); 1217void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
1219#ifdef CONFIG_IWLWIFI_DEBUGFS
1220void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm); 1218void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
1221#else
1222static inline void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) {}
1223#endif
1224 1219
1225#endif /* __IWL_MVM_H__ */ 1220#endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index 91b28e869969..bd52ecfabedb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -587,11 +587,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
587 ieee80211_unregister_hw(mvm->hw); 587 ieee80211_unregister_hw(mvm->hw);
588 588
589 kfree(mvm->scan_cmd); 589 kfree(mvm->scan_cmd);
590 if (mvm->fw_error_dump) {
591 vfree(mvm->fw_error_dump->op_mode_ptr);
592 vfree(mvm->fw_error_dump->trans_ptr);
593 kfree(mvm->fw_error_dump);
594 }
595 kfree(mvm->mcast_filter_cmd); 590 kfree(mvm->mcast_filter_cmd);
596 mvm->mcast_filter_cmd = NULL; 591 mvm->mcast_filter_cmd = NULL;
597 592