1 | /* |
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> |
3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above |
6 | * copyright notice and this permission notice appear in all copies. |
7 | * |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ |
16 | |
17 | #ifndef _WCN36XX_H_ |
18 | #define _WCN36XX_H_ |
19 | |
20 | #include <linux/completion.h> |
21 | #include <linux/in6.h> |
22 | #include <linux/printk.h> |
23 | #include <linux/spinlock.h> |
24 | #include <net/mac80211.h> |
25 | |
26 | #include "hal.h" |
27 | #include "smd.h" |
28 | #include "txrx.h" |
29 | #include "dxe.h" |
30 | #include "pmc.h" |
31 | #include "debug.h" |
32 | |
33 | #define WLAN_NV_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin" |
34 | #define WCN36XX_AGGR_BUFFER_SIZE 64 |
35 | |
36 | extern unsigned int wcn36xx_dbg_mask; |
37 | |
38 | enum wcn36xx_debug_mask { |
39 | WCN36XX_DBG_DXE = 0x00000001, |
40 | WCN36XX_DBG_DXE_DUMP = 0x00000002, |
41 | WCN36XX_DBG_SMD = 0x00000004, |
42 | WCN36XX_DBG_SMD_DUMP = 0x00000008, |
43 | WCN36XX_DBG_RX = 0x00000010, |
44 | WCN36XX_DBG_RX_DUMP = 0x00000020, |
45 | WCN36XX_DBG_TX = 0x00000040, |
46 | WCN36XX_DBG_TX_DUMP = 0x00000080, |
47 | WCN36XX_DBG_HAL = 0x00000100, |
48 | WCN36XX_DBG_HAL_DUMP = 0x00000200, |
49 | WCN36XX_DBG_MAC = 0x00000400, |
50 | WCN36XX_DBG_BEACON = 0x00000800, |
51 | WCN36XX_DBG_BEACON_DUMP = 0x00001000, |
52 | WCN36XX_DBG_PMC = 0x00002000, |
53 | WCN36XX_DBG_PMC_DUMP = 0x00004000, |
54 | WCN36XX_DBG_TESTMODE = 0x00008000, |
55 | WCN36XX_DBG_TESTMODE_DUMP = 0x00010000, |
56 | WCN36XX_DBG_ANY = 0xffffffff, |
57 | }; |
58 | |
59 | #define wcn36xx_err(fmt, arg...) \ |
60 | printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg) |
61 | |
62 | #define wcn36xx_warn(fmt, arg...) \ |
63 | printk(KERN_WARNING pr_fmt("WARNING " fmt), ##arg) |
64 | |
65 | #define wcn36xx_info(fmt, arg...) \ |
66 | printk(KERN_INFO pr_fmt(fmt), ##arg) |
67 | |
68 | #define wcn36xx_dbg(mask, fmt, arg...) do { \ |
69 | if (wcn36xx_dbg_mask & mask) \ |
70 | printk(KERN_DEBUG pr_fmt(fmt), ##arg); \ |
71 | } while (0) |
72 | |
73 | #define wcn36xx_dbg_dump(mask, prefix_str, buf, len) do { \ |
74 | if (wcn36xx_dbg_mask & mask) \ |
75 | print_hex_dump(KERN_DEBUG, pr_fmt(prefix_str), \ |
76 | DUMP_PREFIX_OFFSET, 32, 1, \ |
77 | buf, len, false); \ |
78 | } while (0) |
79 | |
80 | enum wcn36xx_ampdu_state { |
81 | WCN36XX_AMPDU_NONE, |
82 | WCN36XX_AMPDU_INIT, |
83 | WCN36XX_AMPDU_START, |
84 | WCN36XX_AMPDU_OPERATIONAL, |
85 | }; |
86 | |
87 | #define HW_VALUE_PHY_SHIFT 8 |
88 | #define HW_VALUE_PHY(hw_value) ((hw_value) >> HW_VALUE_PHY_SHIFT) |
89 | #define HW_VALUE_CHANNEL(hw_value) ((hw_value) & 0xFF) |
90 | #define WCN36XX_HW_CHANNEL(__wcn)\ |
91 | HW_VALUE_CHANNEL(__wcn->hw->conf.chandef.chan->hw_value) |
92 | #define WCN36XX_BAND(__wcn) (__wcn->hw->conf.chandef.chan->band) |
93 | #define WCN36XX_CENTER_FREQ(__wcn) (__wcn->hw->conf.chandef.chan->center_freq) |
94 | #define WCN36XX_LISTEN_INTERVAL(__wcn) (__wcn->hw->conf.listen_interval) |
95 | #define WCN36XX_FLAGS(__wcn) (__wcn->hw->flags) |
96 | #define WCN36XX_MAX_POWER(__wcn) (__wcn->hw->conf.chandef.chan->max_power) |
97 | |
98 | #define RF_UNKNOWN 0x0000 |
99 | #define RF_IRIS_WCN3620 0x3620 |
100 | #define RF_IRIS_WCN3660 0x3660 |
101 | #define RF_IRIS_WCN3680 0x3680 |
102 | |
103 | static inline void buff_to_be(u32 *buf, size_t len) |
104 | { |
105 | int i; |
106 | for (i = 0; i < len; i++) |
107 | buf[i] = cpu_to_be32(buf[i]); |
108 | } |
109 | |
110 | struct nv_data { |
111 | int is_valid; |
112 | u8 table; |
113 | }; |
114 | |
115 | /** |
116 | * struct wcn36xx_vif - holds VIF related fields |
117 | * |
118 | * @bss_index: bss_index is initially set to 0xFF. bss_index is received from |
119 | * HW after first config_bss call and must be used in delete_bss and |
120 | * enter/exit_bmps. |
121 | */ |
122 | struct wcn36xx_vif { |
123 | struct list_head list; |
124 | u8 dtim_period; |
125 | enum ani_ed_type encrypt_type; |
126 | bool is_joining; |
127 | bool sta_assoc; |
128 | struct wcn36xx_hal_mac_ssid ssid; |
129 | enum wcn36xx_hal_bss_type bss_type; |
130 | |
131 | /* Power management */ |
132 | enum wcn36xx_power_state pw_state; |
133 | |
134 | u8 bss_index; |
135 | /* Returned from WCN36XX_HAL_ADD_STA_SELF_RSP */ |
136 | u8 self_sta_index; |
137 | u8 self_dpu_desc_index; |
138 | u8 self_ucast_dpu_sign; |
139 | |
140 | #if IS_ENABLED(CONFIG_IPV6) |
141 | /* IPv6 addresses for WoWLAN */ |
142 | struct in6_addr target_ipv6_addrs[WCN36XX_HAL_IPV6_OFFLOAD_ADDR_MAX]; |
143 | unsigned long tentative_addrs[BITS_TO_LONGS(WCN36XX_HAL_IPV6_OFFLOAD_ADDR_MAX)]; |
144 | int num_target_ipv6_addrs; |
145 | #endif |
146 | /* WoWLAN GTK rekey data */ |
147 | struct { |
148 | u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN]; |
149 | __le64 replay_ctr; |
150 | bool valid; |
151 | } rekey_data; |
152 | |
153 | struct list_head sta_list; |
154 | |
155 | int bmps_fail_ct; |
156 | }; |
157 | |
158 | /** |
159 | * struct wcn36xx_sta - holds STA related fields |
160 | * |
161 | * @tid: traffic ID that is used during AMPDU and in TX BD. |
162 | * @sta_index: STA index is returned from HW after config_sta call and is |
163 | * used in both SMD channel and TX BD. |
164 | * @dpu_desc_index: DPU descriptor index is returned from HW after config_sta |
165 | * call and is used in TX BD. |
166 | * @bss_sta_index: STA index is returned from HW after config_bss call and is |
167 | * used in both SMD channel and TX BD. See table bellow when it is used. |
168 | * @bss_dpu_desc_index: DPU descriptor index is returned from HW after |
169 | * config_bss call and is used in TX BD. |
170 | * ______________________________________________ |
171 | * | | STA | AP | |
172 | * |______________|_____________|_______________| |
173 | * | TX BD |bss_sta_index| sta_index | |
174 | * |______________|_____________|_______________| |
175 | * |all SMD calls |bss_sta_index| sta_index | |
176 | * |______________|_____________|_______________| |
177 | * |smd_delete_sta| sta_index | sta_index | |
178 | * |______________|_____________|_______________| |
179 | */ |
180 | struct wcn36xx_sta { |
181 | struct list_head list; |
182 | struct wcn36xx_vif *vif; |
183 | u16 aid; |
184 | u16 tid; |
185 | u8 sta_index; |
186 | u8 dpu_desc_index; |
187 | u8 ucast_dpu_sign; |
188 | u8 bss_sta_index; |
189 | u8 bss_dpu_desc_index; |
190 | bool is_data_encrypted; |
191 | /* Rates */ |
192 | struct wcn36xx_hal_supported_rates_v1 supported_rates; |
193 | |
194 | spinlock_t ampdu_lock; /* protects next two fields */ |
195 | enum wcn36xx_ampdu_state ampdu_state[16]; |
196 | int non_agg_frame_ct; |
197 | }; |
198 | |
199 | struct wcn36xx_dxe_ch; |
200 | |
201 | struct wcn36xx_chan_survey { |
202 | s8 ; |
203 | u8 snr; |
204 | }; |
205 | |
206 | struct wcn36xx { |
207 | struct ieee80211_hw *hw; |
208 | struct device *dev; |
209 | struct list_head vif_list; |
210 | |
211 | const char *nv_file; |
212 | const struct firmware *nv; |
213 | |
214 | u8 fw_revision; |
215 | u8 fw_version; |
216 | u8 fw_minor; |
217 | u8 fw_major; |
218 | u32 fw_feat_caps[WCN36XX_HAL_CAPS_SIZE]; |
219 | bool is_pronto; |
220 | bool is_pronto_v3; |
221 | |
222 | /* extra byte for the NULL termination */ |
223 | u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1]; |
224 | u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH + 1]; |
225 | |
226 | bool first_boot; |
227 | |
228 | /* IRQs */ |
229 | int tx_irq; |
230 | int rx_irq; |
231 | void __iomem *ccu_base; |
232 | void __iomem *dxe_base; |
233 | |
234 | struct rpmsg_endpoint *smd_channel; |
235 | |
236 | struct qcom_smem_state *tx_enable_state; |
237 | unsigned tx_enable_state_bit; |
238 | struct qcom_smem_state *tx_rings_empty_state; |
239 | unsigned tx_rings_empty_state_bit; |
240 | |
241 | /* prevents concurrent FW reconfiguration */ |
242 | struct mutex conf_mutex; |
243 | |
244 | /* |
245 | * smd_buf must be protected with smd_mutex to garantee |
246 | * that all messages are sent one after another |
247 | */ |
248 | u8 *hal_buf; |
249 | size_t hal_rsp_len; |
250 | struct mutex hal_mutex; |
251 | struct completion hal_rsp_compl; |
252 | struct workqueue_struct *hal_ind_wq; |
253 | struct work_struct hal_ind_work; |
254 | spinlock_t hal_ind_lock; |
255 | struct list_head hal_ind_queue; |
256 | |
257 | struct cfg80211_scan_request *scan_req; |
258 | bool sw_scan; |
259 | u8 sw_scan_opchannel; |
260 | bool sw_scan_init; |
261 | u8 sw_scan_channel; |
262 | struct ieee80211_vif *sw_scan_vif; |
263 | struct mutex scan_lock; |
264 | bool scan_aborted; |
265 | |
266 | /* DXE channels */ |
267 | struct wcn36xx_dxe_ch dxe_tx_l_ch; /* TX low */ |
268 | struct wcn36xx_dxe_ch dxe_tx_h_ch; /* TX high */ |
269 | struct wcn36xx_dxe_ch dxe_rx_l_ch; /* RX low */ |
270 | struct wcn36xx_dxe_ch dxe_rx_h_ch; /* RX high */ |
271 | |
272 | /* For synchronization of DXE resources from BH, IRQ and WQ contexts */ |
273 | spinlock_t dxe_lock; |
274 | bool queues_stopped; |
275 | |
276 | /* Memory pools */ |
277 | struct wcn36xx_dxe_mem_pool mgmt_mem_pool; |
278 | struct wcn36xx_dxe_mem_pool data_mem_pool; |
279 | |
280 | struct sk_buff *tx_ack_skb; |
281 | struct timer_list tx_ack_timer; |
282 | |
283 | /* For A-MSDU re-aggregation */ |
284 | struct sk_buff_head amsdu; |
285 | |
286 | /* RF module */ |
287 | unsigned rf_id; |
288 | |
289 | #ifdef CONFIG_WCN36XX_DEBUGFS |
290 | /* Debug file system entry */ |
291 | struct wcn36xx_dfs_entry dfs; |
292 | #endif /* CONFIG_WCN36XX_DEBUGFS */ |
293 | |
294 | struct ieee80211_supported_band *band; |
295 | struct ieee80211_channel *channel; |
296 | |
297 | spinlock_t survey_lock; /* protects chan_survey */ |
298 | struct wcn36xx_chan_survey *chan_survey; |
299 | }; |
300 | |
301 | static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn, |
302 | u8 major, |
303 | u8 minor, |
304 | u8 version, |
305 | u8 revision) |
306 | { |
307 | return (wcn->fw_major == major && |
308 | wcn->fw_minor == minor && |
309 | wcn->fw_version == version && |
310 | wcn->fw_revision == revision); |
311 | } |
312 | void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates); |
313 | void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates); |
314 | |
315 | static inline |
316 | struct ieee80211_sta *wcn36xx_priv_to_sta(struct wcn36xx_sta *sta_priv) |
317 | { |
318 | return container_of((void *)sta_priv, struct ieee80211_sta, drv_priv); |
319 | } |
320 | |
321 | static inline |
322 | struct wcn36xx_vif *wcn36xx_vif_to_priv(struct ieee80211_vif *vif) |
323 | { |
324 | return (struct wcn36xx_vif *) vif->drv_priv; |
325 | } |
326 | |
327 | static inline |
328 | struct ieee80211_vif *wcn36xx_priv_to_vif(struct wcn36xx_vif *vif_priv) |
329 | { |
330 | return container_of((void *) vif_priv, struct ieee80211_vif, drv_priv); |
331 | } |
332 | |
333 | static inline |
334 | struct wcn36xx_sta *wcn36xx_sta_to_priv(struct ieee80211_sta *sta) |
335 | { |
336 | return (struct wcn36xx_sta *)sta->drv_priv; |
337 | } |
338 | |
339 | #endif /* _WCN36XX_H_ */ |
340 | |