diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/debugfs.c | 79 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 57 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/ops.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/trans.c | 16 |
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 | ||
60 | config IWLMVM | 60 | config 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 | ||
708 | static inline struct iwl_trans_dump_data * | 705 | static inline struct iwl_trans_dump_data * |
709 | iwl_trans_dump_data(struct iwl_trans *trans) | 706 | iwl_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 | ||
717 | static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | 713 | static 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 | ||
124 | static 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 | |||
142 | out: | ||
143 | mutex_unlock(&mvm->mutex); | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static 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 | |||
184 | static 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 | |||
196 | static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, | 124 | static 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); | |||
1535 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); | 1463 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); |
1536 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); | 1464 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); |
1537 | 1465 | ||
1538 | static 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 |
1545 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); | 1467 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); |
1546 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); | 1468 | MVM_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 | 683 | static 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 | |||
717 | static 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 | |||
683 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | 726 | void 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 | ||
783 | static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) | 820 | static 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, | |||
1216 | struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm); | 1215 | struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm); |
1217 | 1216 | ||
1218 | void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error); | 1217 | void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error); |
1219 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
1220 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm); | 1218 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm); |
1221 | #else | ||
1222 | static 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 | ||
1768 | static 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 | ||
1768 | static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd) | 1775 | static 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 | ||
2046 | static 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 | ||
2053 | static const struct iwl_trans_ops trans_ops_pcie = { | 2053 | static 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 | ||
2093 | struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | 2091 | struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, |