aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h4
-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
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c16
7 files changed, 55 insertions, 112 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 267e48a2915e..139de90c2aaf 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -59,6 +59,7 @@ config IWLDVM
59 59
60config IWLMVM 60config IWLMVM
61 tristate "Intel Wireless WiFi MVM Firmware support" 61 tristate "Intel Wireless WiFi MVM Firmware support"
62 select BACKPORT_WANT_DEV_COREDUMP
62 help 63 help
63 This is the driver that supports the MVM firmware which is 64 This is the driver that supports the MVM firmware which is
64 currently only available for 7260 and 3160 devices. 65 currently only available for 7260 and 3160 devices.
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index d8fc548c0d6c..0768f83e709d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -535,9 +535,7 @@ struct iwl_trans_ops {
535 void (*ref)(struct iwl_trans *trans); 535 void (*ref)(struct iwl_trans *trans);
536 void (*unref)(struct iwl_trans *trans); 536 void (*unref)(struct iwl_trans *trans);
537 537
538#ifdef CONFIG_IWLWIFI_DEBUGFS
539 struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans); 538 struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans);
540#endif
541}; 539};
542 540
543/** 541/**
@@ -704,7 +702,6 @@ static inline void iwl_trans_unref(struct iwl_trans *trans)
704 trans->ops->unref(trans); 702 trans->ops->unref(trans);
705} 703}
706 704
707#ifdef CONFIG_IWLWIFI_DEBUGFS
708static inline struct iwl_trans_dump_data * 705static inline struct iwl_trans_dump_data *
709iwl_trans_dump_data(struct iwl_trans *trans) 706iwl_trans_dump_data(struct iwl_trans *trans)
710{ 707{
@@ -712,7 +709,6 @@ iwl_trans_dump_data(struct iwl_trans *trans)
712 return NULL; 709 return NULL;
713 return trans->ops->dump_data(trans); 710 return trans->ops->dump_data(trans);
714} 711}
715#endif
716 712
717static inline int iwl_trans_send_cmd(struct iwl_trans *trans, 713static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
718 struct iwl_host_cmd *cmd) 714 struct iwl_host_cmd *cmd)
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
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 8027138c47e9..40a290603ead 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1764,6 +1764,13 @@ err:
1764 IWL_ERR(trans, "failed to create the trans debugfs entry\n"); 1764 IWL_ERR(trans, "failed to create the trans debugfs entry\n");
1765 return -ENOMEM; 1765 return -ENOMEM;
1766} 1766}
1767#else
1768static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
1769 struct dentry *dir)
1770{
1771 return 0;
1772}
1773#endif /*CONFIG_IWLWIFI_DEBUGFS */
1767 1774
1768static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd) 1775static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
1769{ 1776{
@@ -2042,13 +2049,6 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
2042 2049
2043 return dump_data; 2050 return dump_data;
2044} 2051}
2045#else
2046static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
2047 struct dentry *dir)
2048{
2049 return 0;
2050}
2051#endif /*CONFIG_IWLWIFI_DEBUGFS */
2052 2052
2053static const struct iwl_trans_ops trans_ops_pcie = { 2053static const struct iwl_trans_ops trans_ops_pcie = {
2054 .start_hw = iwl_trans_pcie_start_hw, 2054 .start_hw = iwl_trans_pcie_start_hw,
@@ -2085,9 +2085,7 @@ static const struct iwl_trans_ops trans_ops_pcie = {
2085 .release_nic_access = iwl_trans_pcie_release_nic_access, 2085 .release_nic_access = iwl_trans_pcie_release_nic_access,
2086 .set_bits_mask = iwl_trans_pcie_set_bits_mask, 2086 .set_bits_mask = iwl_trans_pcie_set_bits_mask,
2087 2087
2088#ifdef CONFIG_IWLWIFI_DEBUGFS
2089 .dump_data = iwl_trans_pcie_dump_data, 2088 .dump_data = iwl_trans_pcie_dump_data,
2090#endif
2091}; 2089};
2092 2090
2093struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, 2091struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,