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