Commit | Line | Data |
---|---|---|
2f89a5d7 GBA |
1 | /****************************************************************************** |
2 | * | |
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | |
4 | * redistributing this file, you may do so under either license. | |
5 | * | |
6 | * GPL LICENSE SUMMARY | |
7 | * | |
8 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. | |
9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | |
7174beb6 | 10 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
2f89a5d7 GBA |
11 | * |
12 | * This program is free software; you can redistribute it and/or modify | |
13 | * it under the terms of version 2 of the GNU General Public License as | |
14 | * published by the Free Software Foundation. | |
15 | * | |
16 | * This program is distributed in the hope that it will be useful, but | |
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | * General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License | |
22 | * along with this program; | |
23 | * | |
24 | * The full GNU General Public License is included in this distribution | |
25 | * in the file called COPYING. | |
26 | * | |
27 | * Contact Information: | |
d01c5366 | 28 | * Intel Linux Wireless <linuxwifi@intel.com> |
2f89a5d7 GBA |
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
30 | * | |
31 | * BSD LICENSE | |
32 | * | |
33 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | |
34 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | |
7174beb6 | 35 | * Copyright(c) 2015 - 2017 Intel Deutschland GmbH |
2f89a5d7 GBA |
36 | * All rights reserved. |
37 | * | |
38 | * Redistribution and use in source and binary forms, with or without | |
39 | * modification, are permitted provided that the following conditions | |
40 | * are met: | |
41 | * | |
42 | * * Redistributions of source code must retain the above copyright | |
43 | * notice, this list of conditions and the following disclaimer. | |
44 | * * Redistributions in binary form must reproduce the above copyright | |
45 | * notice, this list of conditions and the following disclaimer in | |
46 | * the documentation and/or other materials provided with the | |
47 | * distribution. | |
48 | * * Neither the name Intel Corporation nor the names of its | |
49 | * contributors may be used to endorse or promote products derived | |
50 | * from this software without specific prior written permission. | |
51 | * | |
52 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
53 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
54 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
55 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
56 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
57 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
58 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
59 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
60 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
61 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
62 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
63 | * | |
64 | *****************************************************************************/ | |
65 | ||
7174beb6 JB |
66 | #ifndef __iwl_fw_dbg_h__ |
67 | #define __iwl_fw_dbg_h__ | |
68 | #include <linux/workqueue.h> | |
69 | #include <net/cfg80211.h> | |
70 | #include "runtime.h" | |
1efc3843 GBA |
71 | #include "iwl-prph.h" |
72 | #include "iwl-io.h" | |
7174beb6 JB |
73 | #include "file.h" |
74 | #include "error-dump.h" | |
75 | ||
76 | /** | |
77 | * struct iwl_fw_dump_desc - describes the dump | |
78 | * @len: length of trig_desc->data | |
79 | * @trig_desc: the description of the dump | |
80 | */ | |
81 | struct iwl_fw_dump_desc { | |
82 | size_t len; | |
83 | /* must be last */ | |
84 | struct iwl_fw_error_dump_trigger_desc trig_desc; | |
85 | }; | |
86 | ||
87 | extern const struct iwl_fw_dump_desc iwl_dump_desc_assert; | |
88 | ||
89 | static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt) | |
90 | { | |
91 | if (fwrt->dump.desc != &iwl_dump_desc_assert) | |
92 | kfree(fwrt->dump.desc); | |
93 | fwrt->dump.desc = NULL; | |
94 | } | |
95 | ||
96 | void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt); | |
97 | int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, | |
98 | const struct iwl_fw_dump_desc *desc, | |
99 | const struct iwl_fw_dbg_trigger_tlv *trigger); | |
100 | int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, | |
101 | enum iwl_fw_dbg_trigger trig, | |
102 | const char *str, size_t len, | |
103 | const struct iwl_fw_dbg_trigger_tlv *trigger); | |
104 | int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, | |
105 | struct iwl_fw_dbg_trigger_tlv *trigger, | |
106 | const char *fmt, ...) __printf(3, 4); | |
107 | int iwl_fw_start_dbg_conf(struct iwl_fw_runtime *fwrt, u8 id); | |
2f89a5d7 GBA |
108 | |
109 | #define iwl_fw_dbg_trigger_enabled(fw, id) ({ \ | |
110 | void *__dbg_trigger = (fw)->dbg_trigger_tlv[(id)]; \ | |
111 | unlikely(__dbg_trigger); \ | |
112 | }) | |
113 | ||
114 | static inline struct iwl_fw_dbg_trigger_tlv* | |
115 | _iwl_fw_dbg_get_trigger(const struct iwl_fw *fw, enum iwl_fw_dbg_trigger id) | |
116 | { | |
117 | return fw->dbg_trigger_tlv[id]; | |
118 | } | |
119 | ||
120 | #define iwl_fw_dbg_get_trigger(fw, id) ({ \ | |
121 | BUILD_BUG_ON(!__builtin_constant_p(id)); \ | |
122 | BUILD_BUG_ON((id) >= FW_DBG_TRIGGER_MAX); \ | |
123 | _iwl_fw_dbg_get_trigger((fw), (id)); \ | |
124 | }) | |
125 | ||
126 | static inline bool | |
127 | iwl_fw_dbg_trigger_vif_match(struct iwl_fw_dbg_trigger_tlv *trig, | |
7174beb6 | 128 | struct wireless_dev *wdev) |
2f89a5d7 GBA |
129 | { |
130 | u32 trig_vif = le32_to_cpu(trig->vif_type); | |
131 | ||
36064795 | 132 | return trig_vif == IWL_FW_DBG_CONF_VIF_ANY || |
7174beb6 | 133 | wdev->iftype == trig_vif; |
2f89a5d7 GBA |
134 | } |
135 | ||
136 | static inline bool | |
7174beb6 | 137 | iwl_fw_dbg_trigger_stop_conf_match(struct iwl_fw_runtime *fwrt, |
2f89a5d7 GBA |
138 | struct iwl_fw_dbg_trigger_tlv *trig) |
139 | { | |
140 | return ((trig->mode & IWL_FW_DBG_TRIGGER_STOP) && | |
7174beb6 JB |
141 | (fwrt->dump.conf == FW_DBG_INVALID || |
142 | (BIT(fwrt->dump.conf) & le32_to_cpu(trig->stop_conf_ids)))); | |
2f89a5d7 GBA |
143 | } |
144 | ||
a977a150 | 145 | static inline bool |
7174beb6 | 146 | iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, |
a977a150 GBA |
147 | struct iwl_fw_dbg_trigger_tlv *trig) |
148 | { | |
149 | unsigned long wind_jiff = | |
150 | msecs_to_jiffies(le16_to_cpu(trig->trig_dis_ms)); | |
151 | u32 id = le32_to_cpu(trig->id); | |
152 | ||
153 | /* If this is the first event checked, jump to update start ts */ | |
7174beb6 JB |
154 | if (fwrt->dump.non_collect_ts_start[id] && |
155 | (time_after(fwrt->dump.non_collect_ts_start[id] + wind_jiff, | |
a977a150 GBA |
156 | jiffies))) |
157 | return true; | |
158 | ||
7174beb6 | 159 | fwrt->dump.non_collect_ts_start[id] = jiffies; |
a977a150 GBA |
160 | return false; |
161 | } | |
162 | ||
2f89a5d7 | 163 | static inline bool |
7174beb6 JB |
164 | iwl_fw_dbg_trigger_check_stop(struct iwl_fw_runtime *fwrt, |
165 | struct wireless_dev *wdev, | |
2f89a5d7 GBA |
166 | struct iwl_fw_dbg_trigger_tlv *trig) |
167 | { | |
7174beb6 | 168 | if (wdev && !iwl_fw_dbg_trigger_vif_match(trig, wdev)) |
2f89a5d7 GBA |
169 | return false; |
170 | ||
7174beb6 JB |
171 | if (iwl_fw_dbg_no_trig_window(fwrt, trig)) { |
172 | IWL_WARN(fwrt, "Trigger %d occurred while no-collect window.\n", | |
a977a150 GBA |
173 | trig->id); |
174 | return false; | |
175 | } | |
176 | ||
7174beb6 | 177 | return iwl_fw_dbg_trigger_stop_conf_match(fwrt, trig); |
2f89a5d7 GBA |
178 | } |
179 | ||
180 | static inline void | |
7174beb6 JB |
181 | _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt, |
182 | struct wireless_dev *wdev, | |
2f89a5d7 GBA |
183 | struct iwl_fw_dbg_trigger_tlv *trigger) |
184 | { | |
185 | if (!trigger) | |
186 | return; | |
187 | ||
7174beb6 | 188 | if (!iwl_fw_dbg_trigger_check_stop(fwrt, wdev, trigger)) |
2f89a5d7 GBA |
189 | return; |
190 | ||
7174beb6 | 191 | iwl_fw_dbg_collect_trig(fwrt, trigger, NULL); |
2f89a5d7 GBA |
192 | } |
193 | ||
7174beb6 JB |
194 | #define iwl_fw_dbg_trigger_simple_stop(fwrt, wdev, trig) \ |
195 | _iwl_fw_dbg_trigger_simple_stop((fwrt), (wdev), \ | |
196 | iwl_fw_dbg_get_trigger((fwrt)->fw,\ | |
2f89a5d7 GBA |
197 | (trig))) |
198 | ||
1efc3843 GBA |
199 | static inline void iwl_fw_dbg_stop_recording(struct iwl_fw_runtime *fwrt) |
200 | { | |
201 | if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | |
202 | iwl_set_bits_prph(fwrt->trans, MON_BUFF_SAMPLE_CTL, 0x100); | |
203 | } else { | |
204 | iwl_write_prph(fwrt->trans, DBGC_IN_SAMPLE, 0); | |
205 | udelay(100); | |
206 | iwl_write_prph(fwrt->trans, DBGC_OUT_CTRL, 0); | |
207 | } | |
208 | } | |
209 | ||
7174beb6 JB |
210 | static inline void iwl_fw_dump_conf_clear(struct iwl_fw_runtime *fwrt) |
211 | { | |
212 | fwrt->dump.conf = FW_DBG_INVALID; | |
213 | } | |
214 | ||
215 | void iwl_fw_error_dump_wk(struct work_struct *work); | |
216 | ||
217 | static inline void iwl_fw_flush_dump(struct iwl_fw_runtime *fwrt) | |
218 | { | |
219 | flush_delayed_work(&fwrt->dump.wk); | |
220 | } | |
221 | ||
222 | static inline void iwl_fw_cancel_dump(struct iwl_fw_runtime *fwrt) | |
223 | { | |
224 | cancel_delayed_work_sync(&fwrt->dump.wk); | |
225 | } | |
226 | ||
227 | #endif /* __iwl_fw_dbg_h__ */ |