1 /*
2 * WSM host interfaces for XRadio drivers
3 *
4 * Copyright (c) 2013
5 * Xradio Technology Co., Ltd. <www.xradiotech.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12 #include <linux/skbuff.h>
13 #include <linux/wait.h>
14 #include <linux/skbuff.h>
15 #include <linux/delay.h>
16 #include <linux/sched.h>
17 #include <linux/random.h>
18
19 #include "xradio.h"
20 #include "wsm.h"
21 #include "bh.h"
22 #include "sbus.h"
23 #include "itp.h"
24 #ifdef ROAM_OFFLOAD
25 #include "sta.h"
26 #endif /*ROAM_OFFLOAD*/
27
28 #ifdef SUPPORT_FW_DBG_INF
29 #include "fw_dbg_inf.h"
30 #endif /*SUPPORT_FW_DBG_INF*/
31
32
33 /* With respect to interrupt loss, timeout in FW is 2s in some cases. */
34 #define WSM_CMD_TIMEOUT (3 * HZ)
35 #define WSM_CMD_JOIN_TIMEOUT (7 * HZ) /* Join timeout is 5 sec. in FW */
36 #define WSM_CMD_START_TIMEOUT (7 * HZ)
37 #define WSM_CMD_RESET_TIMEOUT (7 * HZ) /* 2 sec. timeout was observed. */
38 #define WSM_CMD_DEFAULT_TIMEOUT (3 * HZ)
39 #define WSM_SKIP(buf, size) \
40 do { \
41 if (unlikely((buf)->data + size > (buf)->end)) \
42 goto underflow; \
43 (buf)->data += size; \
44 } while (0)
45
46 #define WSM_GET(buf, ptr, size) \
47 do { \
48 if (unlikely((buf)->data + size > (buf)->end)) \
49 goto underflow; \
50 memcpy(ptr, (buf)->data, size); \
51 (buf)->data += size; \
52 } while (0)
53
54 #define __WSM_GET(buf, type, cvt) \
55 ({ \
56 type val; \
57 if (unlikely((buf)->data + sizeof(type) > (buf)->end)) \
58 goto underflow; \
59 val = cvt(*(type *)(buf)->data); \
60 (buf)->data += sizeof(type); \
61 val; \
62 })
63
64 #define WSM_GET8(buf) __WSM_GET(buf, u8, (u8))
65 #define WSM_GET16(buf) __WSM_GET(buf, u16, __le16_to_cpu)
66 #define WSM_GET32(buf) __WSM_GET(buf, u32, __le32_to_cpu)
67
68 #define WSM_PUT(buf, ptr, size) \
69 do { \
70 if (unlikely((buf)->data + size > (buf)->end)) \
71 if (unlikely(wsm_buf_reserve((buf), size))) \
72 goto nomem; \
73 memcpy((buf)->data, ptr, size); \
74 (buf)->data += size; \
75 } while (0)
76
77 #define __WSM_PUT(buf, val, type, cvt) \
78 do { \
79 if (unlikely((buf)->data + sizeof(type) > (buf)->end)) \
80 if (unlikely(wsm_buf_reserve((buf), sizeof(type)))) \
81 goto nomem; \
82 *(type *)(buf)->data = cvt(val); \
83 (buf)->data += sizeof(type); \
84 } while (0)
85
86 #define WSM_PUT8(buf, val) __WSM_PUT(buf, val, u8, (u8))
87 #define WSM_PUT16(buf, val) __WSM_PUT(buf, val, u16, __cpu_to_le16)
88 #define WSM_PUT32(buf, val) __WSM_PUT(buf, val, u32, __cpu_to_le32)
89
90 static void wsm_buf_reset(struct wsm_buf *buf);
91 static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size);
92 static int get_interface_id_scanning(struct xradio_common *hw_priv);
93
94 static int wsm_cmd_send(struct xradio_common *hw_priv,
95 struct wsm_buf *buf,
96 void *arg, u16 cmd, long tmo, int if_id);
97
98 static struct xradio_vif
99 *wsm_get_interface_for_tx(struct xradio_common *hw_priv);
100
wsm_cmd_lock(struct xradio_common * hw_priv)101 static inline void wsm_cmd_lock(struct xradio_common *hw_priv)
102 {
103 down(&hw_priv->wsm_cmd_sema);
104 }
105
wsm_cmd_unlock(struct xradio_common * hw_priv)106 static inline void wsm_cmd_unlock(struct xradio_common *hw_priv)
107 {
108 up(&hw_priv->wsm_cmd_sema);
109 }
110
wsm_oper_lock(struct xradio_common * hw_priv)111 static inline void wsm_oper_lock(struct xradio_common *hw_priv)
112 {
113 down(&hw_priv->wsm_oper_lock);
114 }
115
wsm_oper_unlock(struct xradio_common * hw_priv)116 static inline void wsm_oper_unlock(struct xradio_common *hw_priv)
117 {
118 up(&hw_priv->wsm_oper_lock);
119 }
120
121 /* ******************************************************************** */
122 /* WSM API implementation */
123
wsm_generic_confirm(struct xradio_common * hw_priv,void * arg,struct wsm_buf * buf)124 static int wsm_generic_confirm(struct xradio_common *hw_priv,
125 void *arg,
126 struct wsm_buf *buf)
127 {
128 u32 status = WSM_GET32(buf);
129 if (status != WSM_STATUS_SUCCESS)
130 return status;
131 return 0;
132
133 underflow:
134 SYS_WARN(1);
135 return -EINVAL;
136 }
137
138 #if (DGB_XRADIO_HWT)
wsm_hwt_cmd(struct xradio_common * hw_priv,void * arg,size_t arg_size)139 int wsm_hwt_cmd(struct xradio_common *hw_priv, void *arg, size_t arg_size)
140 {
141 int ret = 0;
142 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
143
144 wsm_cmd_lock(hw_priv);
145 WSM_PUT(buf, arg, arg_size);
146 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0004, WSM_CMD_TIMEOUT, -1);
147 wsm_cmd_unlock(hw_priv);
148
149 return ret;
150
151 nomem:
152 wsm_cmd_unlock(hw_priv);
153 return -ENOMEM;
154 }
155 #endif
156
wsm_fw_dbg(struct xradio_common * hw_priv,void * arg,size_t arg_size)157 int wsm_fw_dbg(struct xradio_common *hw_priv, void *arg, size_t arg_size)
158 {
159 int ret = 0;
160
161 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
162
163 wsm_cmd_lock(hw_priv);
164
165 WSM_PUT(buf, arg, arg_size);
166
167 ret = wsm_cmd_send(hw_priv, buf, arg, 0x0025, WSM_CMD_TIMEOUT, -1);
168
169 wsm_cmd_unlock(hw_priv);
170
171 return ret;
172
173 nomem:
174 wsm_cmd_unlock(hw_priv);
175 return -ENOMEM;
176
177 }
178
wsm_fw_dbg_confirm(struct xradio_common * hw_priv,void * arg,struct wsm_buf * buf)179 static int wsm_fw_dbg_confirm(struct xradio_common *hw_priv,
180 void *arg, struct wsm_buf *buf)
181 {
182 #ifdef SUPPORT_FW_DBG_INF
183 return xradio_fw_dbg_confirm((void *)(buf->data), arg);
184 #else
185 return 0;
186 #endif
187 }
188
wsm_fw_dbg_indicate(struct xradio_common * hw_priv,struct wsm_buf * buf)189 static int wsm_fw_dbg_indicate(struct xradio_common *hw_priv,
190 struct wsm_buf *buf)
191 {
192 #ifdef SUPPORT_FW_DBG_INF
193 return xradio_fw_dbg_indicate((void *)(buf->data));
194 #else
195 return 0;
196 #endif
197 }
198
199 #ifdef CONFIG_XRADIO_ETF
wsm_etf_cmd(struct xradio_common * hw_priv,struct wsm_hdr * arg)200 int wsm_etf_cmd(struct xradio_common *hw_priv, struct wsm_hdr *arg)
201 {
202 int ret = 0;
203 wsm_printk(XRADIO_DBG_MSG, "%s >>> 0x%.4X (%d)\n",
204 __func__, arg->id, arg->len);
205
206 #ifdef HW_RESTART
207 if (unlikely(hw_priv->hw_restart)) {
208 wsm_printk(XRADIO_DBG_ERROR, "%s hw reset!>>> 0x%.4X (%d)\n",
209 __func__, arg->id, arg->len);
210 return ETF_ERR_DRIVER_HANG; /*return success, don't process cmd in power off.*/
211 }
212 #endif
213 if (unlikely(hw_priv->bh_error)) {
214 wsm_printk(XRADIO_DBG_ERROR, "%s bh error!>>> 0x%.4X (%d)\n",
215 __func__, arg->id, arg->len);
216 return ETF_ERR_DRIVER_HANG;
217 }
218
219 wsm_cmd_lock(hw_priv);
220 spin_lock(&hw_priv->wsm_cmd.lock);
221 SYS_BUG(hw_priv->wsm_cmd.ptr);
222 hw_priv->wsm_cmd.done = 0;
223 hw_priv->wsm_cmd.ptr = (u8 *)arg;
224 hw_priv->wsm_cmd.len = arg->len;
225 hw_priv->wsm_cmd.arg = NULL;
226 hw_priv->wsm_cmd.cmd = arg->id;
227 spin_unlock(&hw_priv->wsm_cmd.lock);
228 xradio_bh_wakeup(hw_priv);
229
230 if (unlikely(hw_priv->bh_error)) {
231 /* Do not wait for timeout if BH is dead. Exit immediately. */
232 ret = ETF_ERR_DRIVER_HANG;
233 } else {
234 /*Set max timeout.*/
235 long tmo = WSM_CMD_TIMEOUT;
236 unsigned long wsm_cmd_max_tmo = jiffies + tmo;
237 /* Firmware prioritizes data traffic over control confirm.
238 * Loop below checks if data was RXed and increases timeout
239 * accordingly. */
240 do {
241 /* It's safe to use unprotected access to wsm_cmd.done here */
242 ret = wait_event_timeout(hw_priv->wsm_cmd_wq,
243 hw_priv->wsm_cmd.done, tmo);
244
245 /* check time since last rxed and max timeout.*/
246 } while (!ret &&
247 time_before_eq(jiffies, hw_priv->rx_timestamp+tmo) &&
248 time_before(jiffies, wsm_cmd_max_tmo));
249
250 }
251 spin_lock(&hw_priv->wsm_cmd.lock);
252 if (unlikely(hw_priv->wsm_cmd.ptr != NULL)) {
253 hw_priv->wsm_cmd.ptr = NULL;
254 wsm_printk(XRADIO_DBG_ERROR, "%s cmd didn't send!>>> 0x%.4X (%d)\n",
255 __func__, arg->id, arg->len);
256 ret = ETF_ERR_DRIVER_HANG;
257 } else {
258 wsm_printk(XRADIO_DBG_NIY, "%s cmd send finish(%d)!>>> 0x%.4X (%d)\n",
259 __func__, ret, arg->id, arg->len);
260 ret = 0;
261 }
262 spin_unlock(&hw_priv->wsm_cmd.lock);
263
264 wsm_cmd_unlock(hw_priv);
265 return ret;
266 }
267 #endif
268
269 #ifdef XR_RRM /*RadioResourceMeasurement*/
wsm_start_measure_requset(struct xradio_common * hw_priv,MEASUREMENT_PARAMETERS * arg,int if_id)270 static int wsm_start_measure_requset(struct xradio_common *hw_priv,
271 MEASUREMENT_PARAMETERS *arg,
272 int if_id)
273 {
274 int ret;
275 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
276
277 wsm_cmd_lock(hw_priv);
278
279 WSM_PUT(buf, arg, sizeof(*arg));
280 ret = wsm_cmd_send(hw_priv, buf, arg, 0x000E, WSM_CMD_TIMEOUT, if_id);
281
282 wsm_cmd_unlock(hw_priv);
283 return ret;
284
285 nomem:
286 wsm_cmd_unlock(hw_priv);
287 return -ENOMEM;
288
289 }
290
wsm_11k_measure_requset(struct xradio_common * hw_priv,u8 measure_type,u16 ChannelNum,u16 Duration)291 int wsm_11k_measure_requset(struct xradio_common *hw_priv,
292 u8 measure_type,
293 u16 ChannelNum,
294 u16 Duration)
295 {
296 int ret;
297 u8 type, sub_type;
298 MEASUREMENT_PARAMETERS rrm_paras;
299 LMAC_MEAS_REQUEST *rrm_req = &rrm_paras.MeasurementRequest;
300 /* LMAC_MEAS_CHANNEL_LOAD_PARAMS *rrm_req = &rrm_paras.MeasurementRequest; */
301 rrm_paras.TxPowerLevel = 0x11;
302 rrm_paras.DurationMandatory = 0x22;
303 rrm_paras.MeasurementRequestLength = 0x33;
304
305 type = (measure_type&0xf0)>>4;
306 sub_type = measure_type&0xf;
307 rrm_paras.MeasurementType = type;
308 /* if (measure_type == ChannelLoadMeasurement) { */
309 if (type == ChannelLoadMeasurement) {
310 rrm_req->ChannelLoadParams.Reserved = 0;
311 rrm_req->ChannelLoadParams.ChannelLoadCCA = sub_type;
312 rrm_req->ChannelLoadParams.ChannelNum = ChannelNum;
313 /*valid when channelload measure, interval bettween request&start */
314 rrm_req->ChannelLoadParams.RandomInterval = 0;
315 /*unit:1TU=1024us */
316 rrm_req->ChannelLoadParams.MeasurementDuration = Duration;
317 rrm_req->ChannelLoadParams.MeasurementStartTimel = 0;
318 rrm_req->ChannelLoadParams.MeasurementStartTimeh = 0;
319 } else if (type == NoiseHistrogramMeasurement) {
320 rrm_req->NoisHistogramParams.Reserved = 0;
321 rrm_req->NoisHistogramParams.IpiRpi = sub_type;
322 rrm_req->NoisHistogramParams.ChannelNum = ChannelNum;
323 rrm_req->NoisHistogramParams.RandomInterval = 0;
324 rrm_req->NoisHistogramParams.MeasurementDuration = Duration;
325 rrm_req->NoisHistogramParams.MeasurementStartTimel = 0;
326 rrm_req->NoisHistogramParams.MeasurementStartTimeh = 0;
327 }
328 ret = wsm_start_measure_requset(hw_priv, &rrm_paras, 0);
329
330 return ret;
331 }
332
333
334 #endif /*RadioResourceMeasurement */
wsm_configuration(struct xradio_common * hw_priv,struct wsm_configuration * arg,int if_id)335 int wsm_configuration(struct xradio_common *hw_priv,
336 struct wsm_configuration *arg,
337 int if_id)
338 {
339 int ret;
340 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
341
342 wsm_cmd_lock(hw_priv);
343
344 WSM_PUT32(buf, arg->dot11MaxTransmitMsduLifeTime);
345 WSM_PUT32(buf, arg->dot11MaxReceiveLifeTime);
346 WSM_PUT32(buf, arg->dot11RtsThreshold);
347
348 /* DPD block. */
349 WSM_PUT16(buf, arg->dpdData_size + 12);
350 WSM_PUT16(buf, 1); /* DPD version */
351 WSM_PUT(buf, arg->dot11StationId, ETH_ALEN);
352 WSM_PUT16(buf, 5); /* DPD flags */
353 WSM_PUT(buf, arg->dpdData, arg->dpdData_size);
354
355 ret = wsm_cmd_send(hw_priv, buf, arg, 0x0009, WSM_CMD_TIMEOUT, if_id);
356
357 wsm_cmd_unlock(hw_priv);
358 return ret;
359
360 nomem:
361 wsm_cmd_unlock(hw_priv);
362 return -ENOMEM;
363 }
364
wsm_configuration_confirm(struct xradio_common * hw_priv,struct wsm_configuration * arg,struct wsm_buf * buf)365 static int wsm_configuration_confirm(struct xradio_common *hw_priv,
366 struct wsm_configuration *arg,
367 struct wsm_buf *buf)
368 {
369 int i;
370 int status;
371
372 status = WSM_GET32(buf);
373 if (SYS_WARN(status != WSM_STATUS_SUCCESS))
374 return -EINVAL;
375
376 WSM_GET(buf, arg->dot11StationId, ETH_ALEN);
377 arg->dot11FrequencyBandsSupported = WSM_GET8(buf);
378 WSM_SKIP(buf, 1);
379 arg->supportedRateMask = WSM_GET32(buf);
380 for (i = 0; i < 2; ++i) {
381 arg->txPowerRange[i].min_power_level = WSM_GET32(buf);
382 arg->txPowerRange[i].max_power_level = WSM_GET32(buf);
383 arg->txPowerRange[i].stepping = WSM_GET32(buf);
384 }
385 return 0;
386
387 underflow:
388 SYS_WARN(1);
389 return -EINVAL;
390 }
391
392 /* ******************************************************************** */
393 /*forcing upper layer to restart wifi.*/
wsm_upper_restart(struct xradio_common * hw_priv)394 void wsm_upper_restart(struct xradio_common *hw_priv)
395 {
396 wsm_printk(XRADIO_DBG_ERROR, "%s\n", __func__);
397
398 #ifdef ERROR_HANG_DRIVER
399 if (error_hang_driver) {
400 wsm_printk(XRADIO_DBG_ERROR, "%s error_hang_driver\n", __func__);
401 return ; /*do not restart for error debug.*/
402 }
403 #endif
404
405 #ifdef CONFIG_PM
406 xradio_pm_stay_awake(&hw_priv->pm_state, 3*HZ);
407 #endif
408
409 #if defined(CONFIG_XRADIO_USE_EXTENSIONS) && 0
410 spin_lock(&hw_priv->vif_list_lock);
411 xradio_for_each_vif(hw_priv, priv, i) {
412 if (!priv)
413 continue;
414 /*ieee80211_driver_hang_notify(priv->vif, GFP_KERNEL); */
415 wsm_printk(XRADIO_DBG_WARN, "%s driver_hang_notify\n", __func__);
416 }
417 spin_unlock(&hw_priv->vif_list_lock);
418 #elif defined(HW_RESTART)
419 /* We shall not schedule restart_work to system kthread in such case:
420 * 1. while there is a restart_work is pending
421 * 2. while driver is not ready, for the case insmod drv failed, should not restart
422 * 3. while restart_work is running
423 */
424 if (work_pending(&hw_priv->hw_restart_work) || (!hw_priv->driver_ready) ||
425 hw_priv->hw_restart_work_running) {
426 return;
427 } else {
428 wsm_cmd_lock(hw_priv);
429 hw_priv->hw_restart = true;
430 wsm_cmd_unlock(hw_priv);
431 /* wait for scan complete.*/
432 wsm_printk(XRADIO_DBG_WARN, "Wait for scan complete!\n");
433 down(&hw_priv->scan.lock);
434 down(&hw_priv->conf_lock);
435 /* Unlock wsm_oper_lock since no confirms of wsm_oper_locks.*/
436 if (down_trylock(&hw_priv->wsm_oper_lock))
437 wsm_printk(XRADIO_DBG_WARN, "oper_lock may be locked!\n");
438 up(&hw_priv->wsm_oper_lock);
439 up(&hw_priv->conf_lock);
440 up(&hw_priv->scan.lock);
441 msleep(200);
442 wsm_cmd_lock(hw_priv);
443 if (!hw_priv->exit_sync) {
444 if (schedule_work(&hw_priv->hw_restart_work) > 0)
445 wsm_printk(XRADIO_DBG_WARN,
446 "%s schedule restart_work!\n", __func__);
447 else
448 wsm_printk(XRADIO_DBG_ERROR, "%s restart_work failed!\n",
449 __func__);
450
451 } else {
452 wsm_printk(XRADIO_DBG_WARN,
453 "%s Don't restart_work because driver exit!\n", __func__);
454 }
455 wsm_cmd_unlock(hw_priv);
456 return;
457 }
458 #endif
459 }
460
wsm_query_work(struct work_struct * work)461 void wsm_query_work(struct work_struct *work)
462 {
463 struct xradio_common *hw_priv =
464 container_of(work, struct xradio_common, query_work);
465 u8 ret[100] = {0};
466 wsm_printk(XRADIO_DBG_ALWY, "%s\n", __func__);
467
468 *(u32 *)&ret[0] = hw_priv->query_packetID;
469 wsm_read_mib(hw_priv, WSM_MIB_ID_REQ_PKT_STATUS,
470 (void *)&ret[0], sizeof(ret), 4);
471 if (!ret[4]) {
472 wsm_printk(XRADIO_DBG_ALWY,
473 "QuerypktID=0x%08x, status=0x%x, retry=%d, flags=0x%x, " \
474 "PktDebug=0x%x, pktqueue=0x%x, ext1=%d, ext2=%d, " \
475 "ext3=%d, ext4=0x%x, ext5=0x%x\n",
476 *(u32 *)&ret[0], ret[6], ret[7], *(u32 *)&ret[8],
477 *(u32 *)&ret[12], ret[44], ret[45], ret[46],
478 ret[47], ret[48], ret[49]);
479 wsm_printk(XRADIO_DBG_ALWY,
480 "interdebug=0x%x, 0x%x, 0x%x, Soure=0x%x, 0x%x, 0x%x\n" \
481 "interuse=%d, external=%d, TxOutstanding=%d, " \
482 "QueueStatus=0x%x, BA0=0x%x, BA1=0x%x\n" \
483 "ScanStatus=0x%x, scanNULL=0x%x, " \
484 "wr_state=0x%x, 0x%x, 0x%x, 0x%x, " \
485 "wr_cnt=0x%04x, 0x%04x, 0x%04x, 0x%04x\n",
486 *(u32 *)&ret[16], *(u32 *)&ret[20], *(u32 *)&ret[24], ret[28],
487 ret[29], ret[30], ret[32], ret[33], ret[34],
488 ret[35], *(u32 *)&ret[36], *(u32 *)&ret[40],
489 ret[50], ret[51], ret[52], ret[53], ret[54], ret[55],
490 *(u16 *)&ret[56], *(u16 *)&ret[58], *(u16 *)&ret[60],
491 *(u16 *)&ret[62]);
492 wsm_printk(XRADIO_DBG_ALWY,
493 "FW time:request=%d, now=%d, queue=%d, complete=%d\n",
494 *(u32 *)&ret[64], *(u32 *)&ret[68],
495 *(u32 *)&ret[72], *(u32 *)&ret[76]);
496 } else {
497 ret[5] = 0;
498 wsm_printk(XRADIO_DBG_ALWY, "No req packid=0x%08x!\n", *(u32 *)&ret[0]);
499 }
500 /*hardware error occurs, try to restart wifi.*/
501 if (ret[5] & 0x4) {
502 wsm_printk(XRADIO_DBG_ERROR, "Hardware need to reset 0x%x.\n", ret[5]);
503 hw_priv->bh_error = 1;
504 #ifdef BH_USE_SEMAPHORE
505 up(&hw_priv->bh_sem);
506 #else
507 wake_up(&hw_priv->bh_wq);
508 #endif
509 }
510 hw_priv->query_packetID = 0;
511 }
512
513 /* ******************************************************************** */
514
wsm_reset(struct xradio_common * hw_priv,const struct wsm_reset * arg,int if_id)515 int wsm_reset(struct xradio_common *hw_priv, const struct wsm_reset *arg,
516 int if_id)
517 {
518 int ret;
519 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
520 u16 cmd = 0x000A | WSM_TX_LINK_ID(arg->link_id);
521
522 wsm_cmd_lock(hw_priv);
523
524 WSM_PUT32(buf, arg->reset_statistics ? 0 : 1);
525 ret = wsm_cmd_send(hw_priv, buf, NULL, cmd, WSM_CMD_RESET_TIMEOUT,
526 if_id);
527 wsm_cmd_unlock(hw_priv);
528 return ret;
529
530 nomem:
531 wsm_cmd_unlock(hw_priv);
532 return -ENOMEM;
533 }
534
535 /* ******************************************************************** */
536
537 struct wsm_mib {
538 u16 mibId;
539 void *buf;
540 size_t buf_size;
541 };
542
wsm_read_mib(struct xradio_common * hw_priv,u16 mibId,void * _buf,size_t buf_size,size_t arg_size)543 int wsm_read_mib(struct xradio_common *hw_priv, u16 mibId, void *_buf,
544 size_t buf_size, size_t arg_size)
545 {
546 int ret;
547 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
548 struct wsm_mib mib_buf = {
549 .mibId = mibId,
550 .buf = _buf,
551 .buf_size = buf_size,
552 };
553 wsm_cmd_lock(hw_priv);
554
555 WSM_PUT16(buf, mibId);
556 WSM_PUT16(buf, arg_size);
557 WSM_PUT(buf, _buf, arg_size);
558
559 ret = wsm_cmd_send(hw_priv, buf, &mib_buf, 0x0005, WSM_CMD_TIMEOUT, -1);
560 wsm_cmd_unlock(hw_priv);
561 return ret;
562
563 nomem:
564 wsm_cmd_unlock(hw_priv);
565 return -ENOMEM;
566 }
567
wsm_read_mib_confirm(struct xradio_common * hw_priv,struct wsm_mib * arg,struct wsm_buf * buf)568 static int wsm_read_mib_confirm(struct xradio_common *hw_priv,
569 struct wsm_mib *arg,
570 struct wsm_buf *buf)
571 {
572 u16 size;
573 if (SYS_WARN(WSM_GET32(buf) != WSM_STATUS_SUCCESS))
574 return -EINVAL;
575
576 if (SYS_WARN(WSM_GET16(buf) != arg->mibId))
577 return -EINVAL;
578
579 size = WSM_GET16(buf);
580 if (size > arg->buf_size)
581 size = arg->buf_size;
582
583 WSM_GET(buf, arg->buf, size);
584 arg->buf_size = size;
585 return 0;
586
587 underflow:
588 SYS_WARN(1);
589 return -EINVAL;
590 }
591
592 /* ******************************************************************** */
593
wsm_write_mib(struct xradio_common * hw_priv,u16 mibId,void * _buf,size_t buf_size,int if_id)594 int wsm_write_mib(struct xradio_common *hw_priv, u16 mibId, void *_buf,
595 size_t buf_size, int if_id)
596 {
597 int ret;
598 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
599 struct wsm_mib mib_buf = {
600 .mibId = mibId,
601 .buf = _buf,
602 .buf_size = buf_size,
603 };
604
605 wsm_cmd_lock(hw_priv);
606
607 WSM_PUT16(buf, mibId);
608 WSM_PUT16(buf, buf_size);
609 WSM_PUT(buf, _buf, buf_size);
610
611 ret = wsm_cmd_send(hw_priv, buf, &mib_buf, 0x0006, WSM_CMD_TIMEOUT,
612 if_id);
613 wsm_cmd_unlock(hw_priv);
614 return ret;
615
616 nomem:
617 wsm_cmd_unlock(hw_priv);
618 return -ENOMEM;
619 }
620
wsm_write_mib_confirm(struct xradio_common * hw_priv,struct wsm_mib * arg,struct wsm_buf * buf,int interface_link_id)621 static int wsm_write_mib_confirm(struct xradio_common *hw_priv,
622 struct wsm_mib *arg,
623 struct wsm_buf *buf,
624 int interface_link_id)
625 {
626 int ret;
627 int i;
628 struct xradio_vif *priv;
629 ret = wsm_generic_confirm(hw_priv, arg, buf);
630 if (ret)
631 return ret;
632
633 /*wsm_set_operational_mode confirm.*/
634 if (arg->mibId == 0x1006) {
635 const char *p = arg->buf;
636 bool powersave_enabled = (p[0] & 0x0F) ? true : false;
637
638 /* update vif PM status. */
639 priv = xrwl_hwpriv_to_vifpriv(hw_priv, interface_link_id);
640 if (priv) {
641 xradio_enable_powersave(priv, powersave_enabled);
642 spin_unlock(&priv->vif_lock);
643 }
644
645 /* HW powersave base on vif except for generic vif. */
646 spin_lock(&hw_priv->vif_list_lock);
647 xradio_for_each_vif(hw_priv, priv, i) {
648 #ifdef P2P_MULTIVIF
649 if ((i == (XRWL_MAX_VIFS - 1)) || !priv)
650 #else
651 if (!priv)
652 #endif
653 continue;
654 powersave_enabled &= !!priv->powersave_enabled;
655 }
656 hw_priv->powersave_enabled = powersave_enabled;
657 spin_unlock(&hw_priv->vif_list_lock);
658
659 }
660 return 0;
661 }
662
663 /* ******************************************************************** */
664
wsm_scan(struct xradio_common * hw_priv,const struct wsm_scan * arg,int if_id)665 int wsm_scan(struct xradio_common *hw_priv, const struct wsm_scan *arg,
666 int if_id)
667 {
668 int i;
669 int ret;
670 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
671
672 if (unlikely(arg->numOfChannels > 48))
673 return -EINVAL;
674
675 if (unlikely(arg->numOfSSIDs > WSM_SCAN_MAX_NUM_OF_SSIDS))
676 return -EINVAL;
677
678 if (unlikely(arg->band > 1))
679 return -EINVAL;
680
681 wsm_oper_lock(hw_priv);
682 wsm_cmd_lock(hw_priv);
683
684 #ifdef SUPPORT_HT40
685
686 WSM_PUT8(buf, arg->band);
687 WSM_PUT8(buf, arg->scanFlags);
688 WSM_PUT16(buf, arg->TransmitRateEntry);
689 WSM_PUT32(buf, arg->autoScanInterval);
690 WSM_PUT8(buf, arg->numOfProbeRequests);
691 WSM_PUT8(buf, arg->numOfChannels);
692 WSM_PUT8(buf, arg->numOfSSIDs);
693 WSM_PUT8(buf, arg->probeDelay);
694
695 #else
696
697 WSM_PUT8(buf, arg->band);
698 WSM_PUT8(buf, arg->scanType);
699 WSM_PUT8(buf, arg->scanFlags);
700 WSM_PUT8(buf, arg->maxTransmitRate);
701 WSM_PUT32(buf, arg->autoScanInterval);
702 WSM_PUT8(buf, arg->numOfProbeRequests);
703 WSM_PUT8(buf, arg->numOfChannels);
704 WSM_PUT8(buf, arg->numOfSSIDs);
705 WSM_PUT8(buf, arg->probeDelay);
706
707 #endif
708
709 for (i = 0; i < arg->numOfChannels; ++i) {
710 WSM_PUT16(buf, arg->ch[i].number);
711 WSM_PUT16(buf, 0);
712 WSM_PUT32(buf, arg->ch[i].minChannelTime);
713 WSM_PUT32(buf, arg->ch[i].maxChannelTime);
714 WSM_PUT32(buf, 0);
715 }
716
717 for (i = 0; i < arg->numOfSSIDs; ++i) {
718 WSM_PUT32(buf, arg->ssids[i].length);
719 WSM_PUT(buf, &arg->ssids[i].ssid[0],
720 sizeof(arg->ssids[i].ssid));
721 }
722
723 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0007, WSM_CMD_TIMEOUT,
724 if_id);
725 wsm_cmd_unlock(hw_priv);
726 if (ret)
727 wsm_oper_unlock(hw_priv);
728 #ifdef HW_RESTART
729 else if (hw_priv->hw_restart)
730 wsm_oper_unlock(hw_priv);
731 #endif
732 return ret;
733
734 nomem:
735 wsm_cmd_unlock(hw_priv);
736 wsm_oper_unlock(hw_priv);
737 return -ENOMEM;
738 }
739
740 /* ******************************************************************** */
741
wsm_stop_scan(struct xradio_common * hw_priv,int if_id)742 int wsm_stop_scan(struct xradio_common *hw_priv, int if_id)
743 {
744 int ret;
745 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
746 wsm_cmd_lock(hw_priv);
747 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0008, WSM_CMD_TIMEOUT,
748 if_id);
749 wsm_cmd_unlock(hw_priv);
750 return ret;
751 }
752
753
wsm_tx_confirm(struct xradio_common * hw_priv,struct wsm_buf * buf,int interface_link_id)754 static int wsm_tx_confirm(struct xradio_common *hw_priv,
755 struct wsm_buf *buf,
756 int interface_link_id)
757 {
758 struct wsm_tx_confirm tx_confirm;
759
760 #ifdef SUPPORT_HT40
761
762 tx_confirm.packetID = WSM_GET32(buf);
763 tx_confirm.status = WSM_GET32(buf);
764 tx_confirm.txedRateEntry = WSM_GET16(buf);
765 tx_confirm.ackFailures = WSM_GET8(buf);
766 tx_confirm.flags = WSM_GET8(buf);
767 tx_confirm.RateTry[0] = WSM_GET16(buf);
768 tx_confirm.RateTry[1] = WSM_GET16(buf);
769 tx_confirm.RateTry[2] = WSM_GET16(buf);
770 tx_confirm.RateTry[3] = WSM_GET16(buf);
771 tx_confirm.RateTry[4] = WSM_GET16(buf);
772 tx_confirm.RateTry[5] = WSM_GET16(buf);
773 tx_confirm.mediaDelay = WSM_GET32(buf);
774 tx_confirm.txQueueDelay = WSM_GET32(buf);
775
776 #else
777
778 tx_confirm.packetID = WSM_GET32(buf);
779 tx_confirm.status = WSM_GET32(buf);
780 tx_confirm.txedRate = WSM_GET8(buf);
781 tx_confirm.ackFailures = WSM_GET8(buf);
782 tx_confirm.flags = WSM_GET16(buf);
783 tx_confirm.rate_try[0] = WSM_GET32(buf);
784 tx_confirm.rate_try[1] = WSM_GET32(buf);
785 tx_confirm.rate_try[2] = WSM_GET32(buf);
786 tx_confirm.mediaDelay = WSM_GET32(buf);
787 tx_confirm.txQueueDelay = WSM_GET32(buf);
788
789 #endif
790
791 wsm_printk(XRADIO_DBG_NIY, "mediaDelay=%d, QueueDelay=%d.\n",
792 tx_confirm.mediaDelay, tx_confirm.txQueueDelay);
793 xradio_debug_tx_delay(tx_confirm.mediaDelay, tx_confirm.txQueueDelay);
794
795 if (is_hardware_xradio(hw_priv)) {
796 /* TODO:COMBO:linkID will be stored in packetID*/
797 /* TODO:COMBO: Extract traffic resumption map */
798 tx_confirm.if_id = xradio_queue_get_if_id(tx_confirm.packetID);
799 tx_confirm.link_id = xradio_queue_get_link_id(
800 tx_confirm.packetID);
801 } else {
802 tx_confirm.link_id = interface_link_id;
803 tx_confirm.if_id = 0;
804 }
805
806 #if 0
807 wsm_release_vif_tx_buffer(hw_priv, tx_confirm.if_id, 1);
808 #endif
809
810 if (hw_priv->wsm_cbc.tx_confirm)
811 hw_priv->wsm_cbc.tx_confirm(hw_priv, &tx_confirm);
812 return 0;
813
814 underflow:
815 SYS_WARN(1);
816 return -EINVAL;
817 }
818
wsm_multi_tx_confirm(struct xradio_common * hw_priv,struct wsm_buf * buf,int interface_link_id)819 static int wsm_multi_tx_confirm(struct xradio_common *hw_priv,
820 struct wsm_buf *buf, int interface_link_id)
821 {
822 struct xradio_vif *priv;
823 int ret;
824 int count;
825 int i;
826
827 count = WSM_GET32(buf);
828 #if 0
829 if (SYS_WARN(count <= 0))
830 return -EINVAL;
831 else if (count > 1) {
832 ret = wsm_release_tx_buffer(hw_priv, count - 1);
833 if (ret < 0)
834 return ret;
835 else if (ret > 0)
836 xradio_bh_wakeup(hw_priv);
837 }
838 #endif
839
840 DBG_ARRY_ADD(dbg_txconfirm, count-1);
841
842 priv = xrwl_hwpriv_to_vifpriv(hw_priv, interface_link_id);
843 if (priv) {
844 xradio_debug_txed_multi(priv, count);
845 spin_unlock(&priv->vif_lock);
846 }
847 for (i = 0; i < count; ++i) {
848 ret = wsm_tx_confirm(hw_priv, buf, interface_link_id);
849 if (ret)
850 return ret;
851 }
852 return ret;
853
854 underflow:
855 SYS_WARN(1);
856 return -EINVAL;
857 }
858
859 /* ******************************************************************** */
860
wsm_join_confirm(struct xradio_common * hw_priv,struct wsm_join * arg,struct wsm_buf * buf)861 static int wsm_join_confirm(struct xradio_common *hw_priv,
862 struct wsm_join *arg,
863 struct wsm_buf *buf)
864 {
865 u32 status = WSM_GET32(buf);
866
867 wsm_printk(XRADIO_DBG_TRC, "%s", __func__);
868 if (status != WSM_STATUS_SUCCESS) {
869 wsm_printk(XRADIO_DBG_ERROR, "wsm_join_confirm err : %d\n", status);
870 wsm_printk(XRADIO_DBG_ERROR, "wsm_join_confirm minPowerLevel : %d\n", WSM_GET32(buf));
871 wsm_printk(XRADIO_DBG_ERROR, "wsm_join_confirm maxPowerLevel : %d\n", WSM_GET32(buf));
872 return -EINVAL;
873 }
874 arg->minPowerLevel = WSM_GET32(buf);
875 arg->maxPowerLevel = WSM_GET32(buf);
876
877 return 0;
878
879 underflow:
880 SYS_WARN(1);
881 return -EINVAL;
882 }
883
wsm_join(struct xradio_common * hw_priv,struct wsm_join * arg,int if_id)884 int wsm_join(struct xradio_common *hw_priv, struct wsm_join *arg,
885 int if_id)
886 /*TODO: combo: make it work per vif.*/
887 {
888 int ret;
889 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
890 wsm_printk(XRADIO_DBG_TRC, "%s", __func__);
891
892 wsm_oper_lock(hw_priv);
893 wsm_cmd_lock(hw_priv);
894
895 #ifdef SUPPORT_HT40
896
897 WSM_PUT16(buf, *(u16 *)(&arg->PhyModeCfg));
898 WSM_PUT16(buf, arg->channelNumber);
899 WSM_PUT(buf, &arg->bssid[0], sizeof(arg->bssid));
900 WSM_PUT16(buf, arg->atimWindow);
901 WSM_PUT8(buf, arg->mode);
902 WSM_PUT8(buf, arg->probeForJoin);
903 WSM_PUT8(buf, arg->dtimPeriod);
904 WSM_PUT8(buf, arg->flags);
905 WSM_PUT32(buf, arg->ssidLength);
906 WSM_PUT(buf, &arg->ssid[0], sizeof(arg->ssid));
907 WSM_PUT32(buf, arg->beaconInterval);
908 WSM_PUT32(buf, arg->basicRateSet);
909
910 #else
911
912 WSM_PUT8(buf, arg->mode);
913 WSM_PUT8(buf, arg->band);
914 WSM_PUT16(buf, arg->channelNumber);
915 WSM_PUT(buf, &arg->bssid[0], sizeof(arg->bssid));
916 WSM_PUT16(buf, arg->atimWindow);
917 WSM_PUT8(buf, arg->preambleType);
918 WSM_PUT8(buf, arg->probeForJoin);
919 WSM_PUT8(buf, arg->dtimPeriod);
920 WSM_PUT8(buf, arg->flags);
921 WSM_PUT32(buf, arg->ssidLength);
922 WSM_PUT(buf, &arg->ssid[0], sizeof(arg->ssid));
923 WSM_PUT32(buf, arg->beaconInterval);
924 WSM_PUT32(buf, arg->basicRateSet);
925
926 #endif
927 hw_priv->tx_burst_idx = -1;
928 ret = wsm_cmd_send(hw_priv, buf, arg, 0x000B, WSM_CMD_JOIN_TIMEOUT,
929 if_id);
930 wsm_cmd_unlock(hw_priv);
931 wsm_oper_unlock(hw_priv); /*confirm, not indcation.*/
932 return ret;
933
934 nomem:
935 wsm_cmd_unlock(hw_priv);
936 wsm_oper_unlock(hw_priv);
937 return -ENOMEM;
938 }
939
940 /* ******************************************************************** */
941
wsm_set_bss_params(struct xradio_common * hw_priv,const struct wsm_set_bss_params * arg,int if_id)942 int wsm_set_bss_params(struct xradio_common *hw_priv,
943 const struct wsm_set_bss_params *arg,
944 int if_id)
945 {
946 int ret;
947 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
948
949 wsm_cmd_lock(hw_priv);
950
951 WSM_PUT8(buf, 0);
952 WSM_PUT8(buf, arg->beaconLostCount);
953 WSM_PUT16(buf, arg->aid);
954 WSM_PUT32(buf, arg->operationalRateSet);
955
956 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0011, WSM_CMD_TIMEOUT,
957 if_id);
958
959 wsm_cmd_unlock(hw_priv);
960 return ret;
961
962 nomem:
963 wsm_cmd_unlock(hw_priv);
964 return -ENOMEM;
965 }
966
967 /* ******************************************************************** */
968
wsm_add_key(struct xradio_common * hw_priv,const struct wsm_add_key * arg,int if_id)969 int wsm_add_key(struct xradio_common *hw_priv, const struct wsm_add_key *arg,
970 int if_id)
971 {
972 int ret;
973 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
974
975 wsm_cmd_lock(hw_priv);
976
977 WSM_PUT(buf, arg, sizeof(*arg));
978
979 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x000C, WSM_CMD_TIMEOUT,
980 if_id);
981
982 wsm_cmd_unlock(hw_priv);
983 return ret;
984
985 nomem:
986 wsm_cmd_unlock(hw_priv);
987 return -ENOMEM;
988 }
989
990 /* ******************************************************************** */
991
wsm_remove_key(struct xradio_common * hw_priv,const struct wsm_remove_key * arg,int if_id)992 int wsm_remove_key(struct xradio_common *hw_priv,
993 const struct wsm_remove_key *arg, int if_id)
994 {
995 int ret;
996 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
997
998 wsm_cmd_lock(hw_priv);
999
1000 WSM_PUT8(buf, arg->entryIndex);
1001 WSM_PUT8(buf, 0);
1002 WSM_PUT16(buf, 0);
1003
1004 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x000D, WSM_CMD_TIMEOUT,
1005 if_id);
1006
1007 wsm_cmd_unlock(hw_priv);
1008 return ret;
1009
1010 nomem:
1011 wsm_cmd_unlock(hw_priv);
1012 return -ENOMEM;
1013 }
1014
1015 /* ******************************************************************** */
1016
wsm_set_tx_queue_params(struct xradio_common * hw_priv,const struct wsm_set_tx_queue_params * arg,u8 id,int if_id)1017 int wsm_set_tx_queue_params(struct xradio_common *hw_priv,
1018 const struct wsm_set_tx_queue_params *arg,
1019 u8 id, int if_id)
1020 {
1021 int ret;
1022 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
1023 u8 queue_id_to_wmm_aci[] = {3, 2, 0, 1};
1024
1025 wsm_cmd_lock(hw_priv);
1026
1027 WSM_PUT8(buf, queue_id_to_wmm_aci[id]);
1028 WSM_PUT8(buf, 0);
1029 WSM_PUT8(buf, arg->ackPolicy);
1030 WSM_PUT8(buf, 0);
1031 WSM_PUT32(buf, arg->maxTransmitLifetime);
1032 WSM_PUT16(buf, arg->allowedMediumTime);
1033 WSM_PUT16(buf, 0);
1034
1035 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0012, WSM_CMD_TIMEOUT, if_id);
1036
1037 wsm_cmd_unlock(hw_priv);
1038 return ret;
1039
1040 nomem:
1041 wsm_cmd_unlock(hw_priv);
1042 return -ENOMEM;
1043 }
1044
1045 /* ******************************************************************** */
1046
wsm_set_edca_params(struct xradio_common * hw_priv,const struct wsm_edca_params * arg,int if_id)1047 int wsm_set_edca_params(struct xradio_common *hw_priv,
1048 const struct wsm_edca_params *arg,
1049 int if_id)
1050 {
1051 int ret;
1052 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
1053
1054 wsm_cmd_lock(hw_priv);
1055
1056 /* Implemented according to specification. */
1057
1058 WSM_PUT16(buf, arg->params[3].cwMin);
1059 WSM_PUT16(buf, arg->params[2].cwMin);
1060 WSM_PUT16(buf, arg->params[1].cwMin);
1061 WSM_PUT16(buf, arg->params[0].cwMin);
1062
1063 WSM_PUT16(buf, arg->params[3].cwMax);
1064 WSM_PUT16(buf, arg->params[2].cwMax);
1065 WSM_PUT16(buf, arg->params[1].cwMax);
1066 WSM_PUT16(buf, arg->params[0].cwMax);
1067
1068 WSM_PUT8(buf, arg->params[3].aifns);
1069 WSM_PUT8(buf, arg->params[2].aifns);
1070 WSM_PUT8(buf, arg->params[1].aifns);
1071 WSM_PUT8(buf, arg->params[0].aifns);
1072
1073 WSM_PUT16(buf, arg->params[3].txOpLimit);
1074 WSM_PUT16(buf, arg->params[2].txOpLimit);
1075 WSM_PUT16(buf, arg->params[1].txOpLimit);
1076 WSM_PUT16(buf, arg->params[0].txOpLimit);
1077
1078 WSM_PUT32(buf, arg->params[3].maxReceiveLifetime);
1079 WSM_PUT32(buf, arg->params[2].maxReceiveLifetime);
1080 WSM_PUT32(buf, arg->params[1].maxReceiveLifetime);
1081 WSM_PUT32(buf, arg->params[0].maxReceiveLifetime);
1082
1083 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0013, WSM_CMD_TIMEOUT, if_id);
1084 wsm_cmd_unlock(hw_priv);
1085 return ret;
1086
1087 nomem:
1088 wsm_cmd_unlock(hw_priv);
1089 return -ENOMEM;
1090 }
1091
1092 /* ******************************************************************** */
1093
wsm_switch_channel(struct xradio_common * hw_priv,const struct wsm_switch_channel * arg,int if_id)1094 int wsm_switch_channel(struct xradio_common *hw_priv,
1095 const struct wsm_switch_channel *arg,
1096 int if_id)
1097 {
1098 int ret;
1099 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
1100
1101 wsm_lock_tx(hw_priv);
1102 wsm_cmd_lock(hw_priv);
1103
1104 WSM_PUT8(buf, arg->channelMode);
1105 WSM_PUT8(buf, arg->channelSwitchCount);
1106 WSM_PUT16(buf, arg->newChannelNumber);
1107
1108 hw_priv->channel_switch_in_progress = 1;
1109
1110 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0016, WSM_CMD_TIMEOUT, if_id);
1111 wsm_cmd_unlock(hw_priv);
1112 if (ret) {
1113 wsm_unlock_tx(hw_priv);
1114 hw_priv->channel_switch_in_progress = 0;
1115 }
1116 return ret;
1117
1118 nomem:
1119 wsm_cmd_unlock(hw_priv);
1120 wsm_unlock_tx(hw_priv);
1121 return -ENOMEM;
1122 }
1123
1124 /* ******************************************************************** */
1125
wsm_set_pm(struct xradio_common * hw_priv,const struct wsm_set_pm * arg,int if_id)1126 int wsm_set_pm(struct xradio_common *hw_priv, const struct wsm_set_pm *arg,
1127 int if_id)
1128 {
1129 int ret;
1130 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
1131
1132 wsm_oper_lock(hw_priv);
1133
1134 wsm_cmd_lock(hw_priv);
1135
1136 WSM_PUT8(buf, arg->pmMode);
1137 WSM_PUT8(buf, arg->fastPsmIdlePeriod);
1138 WSM_PUT8(buf, arg->apPsmChangePeriod);
1139 WSM_PUT8(buf, arg->minAutoPsPollPeriod);
1140
1141 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0010, WSM_CMD_TIMEOUT, if_id);
1142
1143 wsm_cmd_unlock(hw_priv);
1144 if (ret)
1145 wsm_oper_unlock(hw_priv);
1146 #ifdef HW_RESTART
1147 else if (hw_priv->hw_restart)
1148 wsm_oper_unlock(hw_priv);
1149 #endif
1150 return ret;
1151
1152 nomem:
1153 wsm_cmd_unlock(hw_priv);
1154 wsm_oper_unlock(hw_priv);
1155 return -ENOMEM;
1156 }
1157
1158 /* ******************************************************************** */
1159
wsm_start(struct xradio_common * hw_priv,const struct wsm_start * arg,int if_id)1160 int wsm_start(struct xradio_common *hw_priv, const struct wsm_start *arg,
1161 int if_id)
1162 {
1163 int ret;
1164 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
1165
1166 wsm_cmd_lock(hw_priv);
1167
1168 #ifdef SUPPORT_HT40
1169
1170 WSM_PUT16(buf, *(u16 *)(&arg->PhyModeCfg));
1171 WSM_PUT16(buf, arg->channelNumber);
1172 WSM_PUT32(buf, arg->CTWindow);
1173 WSM_PUT32(buf, arg->beaconInterval);
1174 WSM_PUT8(buf, arg->mode);
1175 WSM_PUT8(buf, arg->DTIMPeriod);
1176 WSM_PUT8(buf, arg->probeDelay);
1177 WSM_PUT8(buf, arg->ssidLength);
1178 WSM_PUT(buf, arg->ssid, sizeof(arg->ssid));
1179 WSM_PUT32(buf, arg->basicRateSet);
1180
1181 #else
1182
1183 WSM_PUT8(buf, arg->mode);
1184 WSM_PUT8(buf, arg->band);
1185 WSM_PUT16(buf, arg->channelNumber);
1186 WSM_PUT32(buf, arg->CTWindow);
1187 WSM_PUT32(buf, arg->beaconInterval);
1188 WSM_PUT8(buf, arg->DTIMPeriod);
1189 WSM_PUT8(buf, arg->preambleType);
1190 WSM_PUT8(buf, arg->probeDelay);
1191 WSM_PUT8(buf, arg->ssidLength);
1192 WSM_PUT(buf, arg->ssid, sizeof(arg->ssid));
1193 WSM_PUT32(buf, arg->basicRateSet);
1194
1195 #endif
1196
1197 hw_priv->tx_burst_idx = -1;
1198 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0017, WSM_CMD_START_TIMEOUT,
1199 if_id);
1200
1201 wsm_cmd_unlock(hw_priv);
1202 return ret;
1203
1204 nomem:
1205 wsm_cmd_unlock(hw_priv);
1206 return -ENOMEM;
1207 }
1208
1209 #if 0
1210 /* This API is no longer present in WSC */
1211 /* ******************************************************************** */
1212
1213 int wsm_beacon_transmit(struct xradio_common *hw_priv,
1214 const struct wsm_beacon_transmit *arg,
1215 int if_id)
1216 {
1217 int ret;
1218 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
1219
1220 wsm_cmd_lock(hw_priv);
1221
1222 WSM_PUT32(buf, arg->enableBeaconing ? 1 : 0);
1223
1224 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0018, WSM_CMD_TIMEOUT, if_id);
1225
1226 wsm_cmd_unlock(hw_priv);
1227 return ret;
1228
1229 nomem:
1230 wsm_cmd_unlock(hw_priv);
1231 return -ENOMEM;
1232 }
1233 #endif
1234
1235 /* ******************************************************************** */
1236
wsm_start_find(struct xradio_common * hw_priv,int if_id)1237 int wsm_start_find(struct xradio_common *hw_priv, int if_id)
1238 {
1239 int ret;
1240 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
1241
1242 wsm_cmd_lock(hw_priv);
1243 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x0019, WSM_CMD_TIMEOUT, if_id);
1244 wsm_cmd_unlock(hw_priv);
1245 return ret;
1246 }
1247
1248 /* ******************************************************************** */
1249
wsm_stop_find(struct xradio_common * hw_priv,int if_id)1250 int wsm_stop_find(struct xradio_common *hw_priv, int if_id)
1251 {
1252 int ret;
1253 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
1254
1255 wsm_cmd_lock(hw_priv);
1256 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x001A, WSM_CMD_TIMEOUT, if_id);
1257 wsm_cmd_unlock(hw_priv);
1258 return ret;
1259 }
1260
1261 /* ******************************************************************** */
1262
wsm_map_link(struct xradio_common * hw_priv,const struct wsm_map_link * arg,int if_id)1263 int wsm_map_link(struct xradio_common *hw_priv, const struct wsm_map_link *arg,
1264 int if_id)
1265 {
1266 int ret;
1267 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
1268 u16 cmd = 0x001C;
1269
1270 wsm_cmd_lock(hw_priv);
1271
1272 WSM_PUT(buf, &arg->mac_addr[0], sizeof(arg->mac_addr));
1273
1274 if (is_hardware_xradio(hw_priv)) {
1275 WSM_PUT8(buf, arg->unmap);
1276 WSM_PUT8(buf, arg->link_id);
1277 } else {
1278 cmd |= WSM_TX_LINK_ID(arg->link_id);
1279 WSM_PUT16(buf, 0);
1280 }
1281
1282 ret = wsm_cmd_send(hw_priv, buf, NULL, cmd, WSM_CMD_TIMEOUT, if_id);
1283
1284 wsm_cmd_unlock(hw_priv);
1285 return ret;
1286
1287 nomem:
1288 wsm_cmd_unlock(hw_priv);
1289 return -ENOMEM;
1290 }
1291
1292 /* ******************************************************************** */
1293
wsm_update_ie(struct xradio_common * hw_priv,const struct wsm_update_ie * arg,int if_id)1294 int wsm_update_ie(struct xradio_common *hw_priv,
1295 const struct wsm_update_ie *arg, int if_id)
1296 {
1297 int ret;
1298 struct wsm_buf *buf = &hw_priv->wsm_cmd_buf;
1299
1300 wsm_cmd_lock(hw_priv);
1301
1302 WSM_PUT16(buf, arg->what);
1303 WSM_PUT16(buf, arg->count);
1304 WSM_PUT(buf, arg->ies, arg->length);
1305
1306 ret = wsm_cmd_send(hw_priv, buf, NULL, 0x001B, WSM_CMD_TIMEOUT, if_id);
1307
1308 wsm_cmd_unlock(hw_priv);
1309 return ret;
1310
1311 nomem:
1312 wsm_cmd_unlock(hw_priv);
1313 return -ENOMEM;
1314
1315 }
1316 /* ******************************************************************** */
1317 #ifdef MCAST_FWDING
1318 /* 3.66 */
wsm_give_buffer_confirm(struct xradio_common * hw_priv,struct wsm_buf * buf)1319 static int wsm_give_buffer_confirm(struct xradio_common *hw_priv,
1320 struct wsm_buf *buf)
1321 {
1322 wsm_printk(XRADIO_DBG_MSG, "HW Buf count %d\n", hw_priv->hw_bufs_used);
1323 if (!hw_priv->hw_bufs_used)
1324 wake_up(&hw_priv->bh_evt_wq);
1325
1326 return 0;
1327 }
1328
1329 /* 3.65 */
wsm_init_release_buffer_request(struct xradio_common * hw_priv)1330 int wsm_init_release_buffer_request(struct xradio_common *hw_priv)
1331 {
1332 struct wsm_buf *buf = &hw_priv->wsm_release_buf;
1333 u16 cmd = 0x0022; /* Buffer Request */
1334 size_t buf_len = sizeof(struct wsm_hdr) + 8;
1335
1336 wsm_buf_init(buf, buf_len);
1337 WSM_PUT8(buf, 0);
1338 WSM_PUT8(buf, 0);
1339 WSM_PUT16(buf, 0);
1340
1341 buf_len = buf->data - buf->begin;
1342
1343 /* Fill HI message header */
1344 ((__le16 *)buf->begin)[0] = __cpu_to_le16(buf_len);
1345 ((__le16 *)buf->begin)[1] = __cpu_to_le16(cmd);
1346
1347 return 0;
1348 nomem:
1349 return -ENOMEM;
1350 }
1351
wsm_deinit_release_buffer(struct xradio_common * hw_priv)1352 void wsm_deinit_release_buffer(struct xradio_common *hw_priv)
1353 {
1354 wsm_buf_deinit(&hw_priv->wsm_release_buf);
1355 }
1356
1357 /* 3.68 */
wsm_request_buffer_confirm(struct xradio_vif * priv,u8 * arg,struct wsm_buf * buf)1358 static int wsm_request_buffer_confirm(struct xradio_vif *priv,
1359 u8 *arg,
1360 struct wsm_buf *buf)
1361 {
1362 u8 count;
1363 u32 sta_asleep_mask = 0;
1364 int i;
1365 u32 mask = 0;
1366 u32 change_mask = 0;
1367 struct xradio_common *hw_priv = priv->hw_priv;
1368
1369 /* There is no status field in this message */
1370 sta_asleep_mask = WSM_GET32(buf);
1371 count = WSM_GET8(buf);
1372 count -= 1; /* Current workaround for FW issue */
1373
1374 spin_lock_bh(&priv->ps_state_lock);
1375 change_mask = (priv->sta_asleep_mask ^ sta_asleep_mask);
1376 wsm_printk(XRADIO_DBG_MSG, "CM %x, HM %x, FWM %x\n",
1377 change_mask, priv->sta_asleep_mask, sta_asleep_mask);
1378 spin_unlock_bh(&priv->ps_state_lock);
1379
1380 if (change_mask) {
1381 struct ieee80211_sta *sta;
1382 int ret = 0;
1383
1384
1385 for (i = 0; i < MAX_STA_IN_AP_MODE ; ++i) {
1386
1387 if (XRADIO_LINK_HARD != priv->link_id_db[i].status)
1388 continue;
1389 mask = BIT(i + 1);
1390 /* If FW state and host state for
1391 * this link are different then notify OMAC */
1392 if (change_mask & mask) {
1393 wsm_printk(XRADIO_DBG_MSG,
1394 "PS State Changed %d for sta %pM\n",
1395 (sta_asleep_mask & mask) ? 1 : 0,
1396 priv->link_id_db[i].mac);
1397 rcu_read_lock();
1398 sta = mac80211_find_sta(priv->vif, priv->link_id_db[i].mac);
1399 if (!sta) {
1400 wsm_printk(XRADIO_DBG_MSG,
1401 "WRBC - could not find sta %pM\n",
1402 priv->link_id_db[i].mac);
1403 } else {
1404 ret = ieee80211_sta_ps_transition_ni(sta,
1405 (sta_asleep_mask & mask) ? true : false);
1406 wsm_printk(XRADIO_DBG_MSG, "PS State NOTIFIED %d\n", ret);
1407 SYS_WARN(ret);
1408 }
1409 rcu_read_unlock();
1410 }
1411 }
1412 /* Replace STA mask with one reported by FW */
1413 spin_lock_bh(&priv->ps_state_lock);
1414 priv->sta_asleep_mask = sta_asleep_mask;
1415 spin_unlock_bh(&priv->ps_state_lock);
1416 }
1417
1418 wsm_printk(XRADIO_DBG_MSG, "WRBC - HW Buf count %d SleepMask %d\n",
1419 hw_priv->hw_bufs_used, sta_asleep_mask);
1420 hw_priv->buf_released = 0;
1421 SYS_WARN(count != (hw_priv->wsm_caps.numInpChBufs - 1));
1422
1423 return 0;
1424
1425 underflow:
1426 SYS_WARN(1);
1427 return -EINVAL;
1428 }
1429
1430 /* 3.67 */
wsm_request_buffer_request(struct xradio_vif * priv,u8 * arg)1431 int wsm_request_buffer_request(struct xradio_vif *priv,
1432 u8 *arg)
1433 {
1434 int ret;
1435 struct wsm_buf *buf = &priv->hw_priv->wsm_cmd_buf;
1436
1437 wsm_cmd_lock(priv->hw_priv);
1438
1439 WSM_PUT8(buf, (*arg));
1440 WSM_PUT8(buf, 0);
1441 WSM_PUT16(buf, 0);
1442
1443 ret = wsm_cmd_send(priv->hw_priv, buf, arg, 0x0023,
1444 WSM_CMD_JOIN_TIMEOUT, priv->if_id);
1445
1446 wsm_cmd_unlock(priv->hw_priv);
1447 return ret;
1448
1449 nomem:
1450 wsm_cmd_unlock(priv->hw_priv);
1451 return -ENOMEM;
1452 }
1453 #endif
1454
wsm_set_keepalive_filter(struct xradio_vif * priv,bool enable)1455 int wsm_set_keepalive_filter(struct xradio_vif *priv, bool enable)
1456 {
1457 struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
1458
1459 priv->rx_filter.keepalive = enable;
1460 return wsm_set_rx_filter(hw_priv, &priv->rx_filter, priv->if_id);
1461 }
1462
wsm_set_probe_responder(struct xradio_vif * priv,bool enable)1463 int wsm_set_probe_responder(struct xradio_vif *priv, bool enable)
1464 {
1465 struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
1466
1467 priv->rx_filter.probeResponder = enable;
1468 return wsm_set_rx_filter(hw_priv, &priv->rx_filter, priv->if_id);
1469 }
1470 /* ******************************************************************** */
1471 /* WSM indication events implementation */
1472
wsm_startup_indication(struct xradio_common * hw_priv,struct wsm_buf * buf)1473 static int wsm_startup_indication(struct xradio_common *hw_priv,
1474 struct wsm_buf *buf)
1475 {
1476 u16 status;
1477 #ifdef CONFIG_XRADIO_DEBUG
1478 static const char * const fw_types[] = {
1479 "ETF",
1480 "WFM",
1481 "WSM",
1482 "HI test",
1483 "Platform test"
1484 };
1485 #endif
1486
1487 hw_priv->wsm_caps.numInpChBufs = WSM_GET16(buf);
1488 hw_priv->wsm_caps.sizeInpChBuf = WSM_GET16(buf);
1489 hw_priv->wsm_caps.hardwareId = WSM_GET16(buf);
1490 hw_priv->wsm_caps.hardwareSubId = WSM_GET16(buf);
1491 status = WSM_GET16(buf);
1492 hw_priv->wsm_caps.firmwareCap = WSM_GET16(buf);
1493 hw_priv->wsm_caps.firmwareType = WSM_GET16(buf);
1494 hw_priv->wsm_caps.firmwareApiVer = WSM_GET16(buf);
1495 hw_priv->wsm_caps.firmwareBuildNumber = WSM_GET16(buf);
1496 hw_priv->wsm_caps.firmwareVersion = WSM_GET16(buf);
1497 WSM_GET(buf, &hw_priv->wsm_caps.fw_label[0], WSM_FW_LABEL);
1498 /* Do not trust FW too much. */
1499 hw_priv->wsm_caps.fw_label[WSM_FW_LABEL+1] = 0;
1500
1501 hw_priv->wsm_caps.firmwareConfig[0] = WSM_GET32(buf);
1502 hw_priv->wsm_caps.firmwareConfig[1] = WSM_GET32(buf);
1503 hw_priv->wsm_caps.firmwareConfig[2] = WSM_GET32(buf);
1504
1505 if (SYS_WARN(status))
1506 return -EINVAL;
1507
1508 if (SYS_WARN(hw_priv->wsm_caps.firmwareType > 4))
1509 return -EINVAL;
1510
1511 wsm_printk(XRADIO_DBG_NIY, "%s\n"
1512 " Input buffers: %d x %d bytes\n"
1513 " Hardware: %d.%d\n"
1514 " %s firmware ver: %d, build: %d, "
1515 " api: %d, cap: 0x%.4X\n",
1516 __func__,
1517 hw_priv->wsm_caps.numInpChBufs,
1518 hw_priv->wsm_caps.sizeInpChBuf,
1519 hw_priv->wsm_caps.hardwareId,
1520 hw_priv->wsm_caps.hardwareSubId,
1521 fw_types[hw_priv->wsm_caps.firmwareType],
1522 hw_priv->wsm_caps.firmwareVersion,
1523 hw_priv->wsm_caps.firmwareBuildNumber,
1524 hw_priv->wsm_caps.firmwareApiVer,
1525 hw_priv->wsm_caps.firmwareCap);
1526
1527 wsm_printk(XRADIO_DBG_ALWY, "Firmware Label:%s\n",
1528 &hw_priv->wsm_caps.fw_label[0]);
1529
1530 hw_priv->wsm_caps.firmwareReady = 1;
1531
1532 wake_up(&hw_priv->wsm_startup_done);
1533 return 0;
1534
1535 underflow:
1536 SYS_WARN(1);
1537 return -EINVAL;
1538 }
1539
wsm_send_deauth_to_self(struct xradio_common * hw_priv,struct xradio_vif * priv)1540 void wsm_send_deauth_to_self(struct xradio_common *hw_priv,
1541 struct xradio_vif *priv)
1542 {
1543 struct sk_buff *skb = NULL;
1544 struct ieee80211_mgmt *deauth = NULL;
1545
1546 if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
1547 int i = 0;
1548 wsm_printk(XRADIO_DBG_WARN, "AP mode, send_deauth_to_self\n");
1549 for (i = 0; i < MAX_STA_IN_AP_MODE; i++) {
1550 if (priv->link_id_db[i].status == XRADIO_LINK_HARD) {
1551 skb = xr_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
1552 if (!skb)
1553 return;
1554 skb_reserve(skb, 64);
1555 deauth = (struct ieee80211_mgmt *) \
1556 skb_put(skb, sizeof(struct ieee80211_mgmt));
1557 if (!deauth) {
1558 SYS_WARN(1);
1559 return;
1560 }
1561 deauth->frame_control =
1562 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
1563 deauth->duration = 0;
1564 memcpy(deauth->da, priv->vif->addr, ETH_ALEN);
1565 memcpy(deauth->sa, priv->link_id_db[i].mac, ETH_ALEN);
1566 memcpy(deauth->bssid, priv->vif->addr, ETH_ALEN);
1567 deauth->seq_ctrl = 0;
1568 deauth->u.deauth.reason_code = WLAN_REASON_DEAUTH_LEAVING;
1569 mac80211_rx_irqsafe(priv->hw, skb);
1570 }
1571 }
1572 } else if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
1573 wsm_printk(XRADIO_DBG_WARN, "STA mode, send_deauth_to_self\n");
1574 skb = xr_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
1575 if (!skb)
1576 return;
1577 skb_reserve(skb, 64);
1578 deauth = (struct ieee80211_mgmt *) \
1579 skb_put(skb, sizeof(struct ieee80211_mgmt));
1580 if (!deauth) {
1581 SYS_WARN(1);
1582 return;
1583 }
1584 deauth->frame_control =
1585 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
1586 deauth->duration = 0;
1587 memcpy(deauth->da, priv->vif->addr, ETH_ALEN);
1588 memcpy(deauth->sa, priv->join_bssid, ETH_ALEN);
1589 memcpy(deauth->bssid, priv->join_bssid, ETH_ALEN);
1590 deauth->seq_ctrl = 0;
1591 deauth->u.deauth.reason_code = WLAN_REASON_DEAUTH_LEAVING;
1592 mac80211_rx_irqsafe(priv->hw, skb);
1593 priv->setbssparams_done = false;
1594 }
1595 }
1596
wsm_send_disassoc_to_self(struct xradio_common * hw_priv,struct xradio_vif * priv)1597 void wsm_send_disassoc_to_self(struct xradio_common *hw_priv,
1598 struct xradio_vif *priv)
1599 {
1600 struct sk_buff *skb = NULL;
1601 struct ieee80211_mgmt *disassoc = NULL;
1602 if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
1603 int i = 0;
1604 wsm_printk(XRADIO_DBG_WARN, "AP mode, wsm_send_disassoc_to_self\n");
1605 for (i = 0; i < MAX_STA_IN_AP_MODE; i++) {
1606 if (priv->link_id_db[i].status == XRADIO_LINK_HARD) {
1607 skb = xr_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
1608 if (!skb)
1609 return;
1610 skb_reserve(skb, 64);
1611 disassoc = (struct ieee80211_mgmt *) \
1612 skb_put(skb, sizeof(struct ieee80211_mgmt));
1613 if (!disassoc) {
1614 SYS_WARN(1);
1615 return;
1616 }
1617 disassoc->frame_control =
1618 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC);
1619 disassoc->duration = 0;
1620 memcpy(disassoc->da, priv->vif->addr, ETH_ALEN);
1621 memcpy(disassoc->sa, priv->link_id_db[i].mac, ETH_ALEN);
1622 memcpy(disassoc->bssid, priv->vif->addr, ETH_ALEN);
1623 disassoc->seq_ctrl = 0;
1624 disassoc->u.disassoc.reason_code =
1625 WLAN_REASON_DISASSOC_STA_HAS_LEFT;
1626 mac80211_rx_irqsafe(priv->hw, skb);
1627 }
1628 }
1629 } else if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
1630 wsm_printk(XRADIO_DBG_WARN, "STA mode, wsm_send_disassoc_to_self\n");
1631 skb = xr_alloc_skb(sizeof(struct ieee80211_mgmt) + 64);
1632 if (!skb)
1633 return;
1634 skb_reserve(skb, 64);
1635 disassoc = (struct ieee80211_mgmt *) \
1636 skb_put(skb, sizeof(struct ieee80211_mgmt));
1637 if (!disassoc) {
1638 SYS_WARN(1);
1639 return;
1640 }
1641 disassoc->frame_control =
1642 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC);
1643 disassoc->duration = 0;
1644 memcpy(disassoc->da, priv->vif->addr, ETH_ALEN);
1645 memcpy(disassoc->sa, priv->join_bssid, ETH_ALEN);
1646 memcpy(disassoc->bssid, priv->join_bssid, ETH_ALEN);
1647 disassoc->seq_ctrl = 0;
1648 disassoc->u.disassoc.reason_code =
1649 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY;
1650 mac80211_rx_irqsafe(priv->hw, skb);
1651 priv->setbssparams_done = false;
1652 }
1653 }
1654
wsm_receive_indication(struct xradio_common * hw_priv,int interface_link_id,struct wsm_buf * buf,struct sk_buff ** skb_p)1655 static int wsm_receive_indication(struct xradio_common *hw_priv,
1656 int interface_link_id,
1657 struct wsm_buf *buf,
1658 struct sk_buff **skb_p)
1659 {
1660 struct xradio_vif *priv;
1661 int if_id = interface_link_id;
1662
1663 hw_priv->rx_timestamp = jiffies;
1664 if (hw_priv->wsm_cbc.rx) {
1665 struct wsm_rx rx;
1666 struct ieee80211_hdr *hdr;
1667 size_t hdr_len;
1668 #ifdef SUPPORT_HT40
1669
1670 rx.status = WSM_GET32(buf);
1671 rx.channelNumber = WSM_GET16(buf);
1672 rx.rxedRateEntry = WSM_GET16(buf);
1673 rx.Reserved[0] = WSM_GET8(buf);
1674 rx.Reserved[1] = WSM_GET8(buf);
1675 rx.Reserved[2] = WSM_GET8(buf);
1676 rx.rcpiRssi = WSM_GET8(buf);
1677 rx.flags = WSM_GET32(buf);
1678
1679 #else
1680
1681 rx.status = WSM_GET32(buf);
1682 rx.channelNumber = WSM_GET16(buf);
1683 rx.rxedRate = WSM_GET8(buf);
1684 rx.rcpiRssi = WSM_GET8(buf);
1685 rx.flags = WSM_GET32(buf);
1686
1687 #endif
1688
1689 /* TODO:COMBO: Frames received from scanning are received
1690 * with interface ID == 2 */
1691 if (is_hardware_xradio(hw_priv)) {
1692 if (if_id == XRWL_GENERIC_IF_ID) {
1693 /* Frames received in response to SCAN
1694 * Request */
1695 if_id = get_interface_id_scanning(hw_priv);
1696 if (if_id == -1) {
1697 if_id = hw_priv->roc_if_id;
1698 }
1699 #ifdef ROAM_OFFLOAD
1700 if (hw_priv->auto_scanning) {
1701 if_id = hw_priv->scan.if_id;
1702 }
1703 #endif/*ROAM_OFFLOAD*/
1704 }
1705 /* linkid (peer sta id is encoded in bit 25-28 of
1706 flags field */
1707 #ifdef SUPPORT_HT40
1708
1709 rx.link_id = WSM_RX_LINK_ID_GET(rx.flags);
1710
1711 #else
1712
1713 rx.link_id = ((rx.flags & (0xf << 25)) >> 25);
1714
1715 #endif
1716 rx.if_id = if_id;
1717 } else {
1718 rx.link_id = if_id;
1719 rx.if_id = 0;
1720 }
1721 #ifdef MONITOR_MODE
1722 if (hw_priv->monitor_if_id != -1)
1723 priv = xrwl_hwpriv_to_vifpriv(hw_priv, hw_priv->monitor_if_id);
1724 else
1725 #endif
1726 priv = xrwl_hwpriv_to_vifpriv(hw_priv, rx.if_id);
1727 if (!priv) {
1728 wsm_printk(XRADIO_DBG_WARN,
1729 "%s: NULL priv(if=%d) drop frame, link_id=%d, "
1730 "scan_id=%d, roc_id=%d, scan_req=%p, direct_probe=%d\n",
1731 __func__, if_id, interface_link_id,
1732 hw_priv->scan.if_id, hw_priv->roc_if_id,
1733 hw_priv->scan.req, hw_priv->scan.direct_probe);
1734 return 0;
1735 }
1736 /*remove wsm hdr of skb*/
1737 hdr_len = buf->data - buf->begin;
1738 skb_pull(*skb_p, hdr_len);
1739
1740 /* FW Workaround: Drop probe resp or
1741 beacon when RSSI is 0 */
1742 hdr = (struct ieee80211_hdr *) (*skb_p)->data;
1743
1744 if (!rx.rcpiRssi &&
1745 (ieee80211_is_probe_resp(hdr->frame_control) ||
1746 ieee80211_is_beacon(hdr->frame_control))) {
1747 spin_unlock(&priv->vif_lock);
1748 skb_push(*skb_p, hdr_len);
1749 return 0;
1750 }
1751
1752 /* If no RSSI subscription has been made,
1753 * convert RCPI to RSSI here */
1754 if (!priv->cqm_use_rssi)
1755 rx.rcpiRssi = rx.rcpiRssi / 2 - 110;
1756 #ifdef USE_RSSI_OFFSET
1757 rx.rcpiRssi = (s8)rx.rcpiRssi - WSM_RSSI_OFFSET; /* rssi offset.*/
1758 #endif
1759 if ((s8)rx.rcpiRssi > 0)
1760 rx.rcpiRssi = 0;
1761
1762 if (!rx.status && unlikely(ieee80211_is_deauth(hdr->frame_control))) {
1763 if (ieee80211_has_protected(hdr->frame_control) || !priv->is_mfp_connect) {
1764 if (priv->join_status == XRADIO_JOIN_STATUS_STA) {
1765 /* Shedule unjoin work */
1766 wsm_printk(XRADIO_DBG_WARN, \
1767 "Issue unjoin command (RX).\n");
1768
1769 cancel_delayed_work(&priv->unjoin_delayed_work);
1770 wsm_lock_tx_async(hw_priv);
1771 if (queue_work(hw_priv->workqueue, &priv->unjoin_work) <= 0)
1772 wsm_unlock_tx(hw_priv);
1773 }
1774 }
1775 }
1776 hw_priv->wsm_cbc.rx(priv, &rx, skb_p);
1777 if (*skb_p)
1778 skb_push(*skb_p, hdr_len);
1779 spin_unlock(&priv->vif_lock);
1780 }
1781 return 0;
1782
1783 underflow:
1784 return -EINVAL;
1785 }
wsm_multi_receive_indication(struct xradio_common * hw_priv,int multirxlen,struct wsm_buf * buf,struct sk_buff ** skb_p)1786 static int wsm_multi_receive_indication(struct xradio_common *hw_priv,
1787 int multirxlen,
1788 struct wsm_buf *buf,
1789 struct sk_buff **skb_p)
1790 {
1791 size_t wsm_len = 0;
1792 int wsm_id;
1793 size_t len;
1794 struct wsm_hdr *wsm;
1795 u8 *data = buf->begin;
1796 size_t packet_len = 0;
1797 int interface_link_id = 0;
1798 int cloned = 0;
1799 wsm_printk(XRADIO_DBG_NIY, "%s Total=%d\n",
1800 __func__, multirxlen);
1801
1802 for (len = 0; len < multirxlen; len += packet_len) {
1803 wsm = (struct wsm_hdr *)(data + len);
1804 wsm_len = __le32_to_cpu(wsm->len);
1805 packet_len = ROUND4(wsm_len);
1806 wsm_id = __le32_to_cpu(wsm->id) & 0xFFF;
1807 interface_link_id = (wsm_id >> 6) & 0x0F;
1808 wsm_printk(XRADIO_DBG_MSG, "if%d-multi-rx 0x%.4X (%zu)\n",
1809 interface_link_id, wsm_id, wsm_len);
1810
1811 wsm_id &= ~WSM_TX_LINK_ID(WSM_TX_LINK_ID_MAX);
1812 if (wsm_id == 0x0804) {
1813 struct wsm_buf wsm_buffer;
1814 struct sk_buff *skb = NULL;
1815
1816 wsm_buffer.begin = (u8 *)&wsm[0];
1817 wsm_buffer.data = (u8 *)&wsm[1];
1818 wsm_buffer.end =
1819 &wsm_buffer.begin[__le32_to_cpu(wsm->len)];
1820
1821 if ((len + packet_len) < multirxlen) {
1822 skb = skb_clone((*skb_p), GFP_ATOMIC);
1823 if (WARN_ON(!skb))
1824 break;
1825
1826 skb_trim(skb, 0);
1827 skb_put(skb, len + wsm_len); /* set data end.*/
1828 skb_pull(skb, len); /* set data begin.*/
1829 skb_trim(skb, wsm_len); /* set data length.*/
1830
1831 wsm_receive_indication(hw_priv,
1832 interface_link_id, &wsm_buffer, &skb);
1833 if (skb) {
1834 dev_kfree_skb(skb);
1835 skb = NULL;
1836 } else {
1837 ++cloned;
1838 }
1839 } else { /*last packet*/
1840 skb_trim(*skb_p, 0);
1841 skb_put(*skb_p, len + wsm_len); /* set data end.*/
1842 skb_pull(*skb_p, len); /* set data begin.*/
1843 skb_trim(*skb_p, wsm_len); /* set data length.*/
1844 wsm_receive_indication(hw_priv,
1845 interface_link_id, &wsm_buffer, skb_p);
1846
1847 if (*skb_p) {
1848 /* the skb cannot be reclaim by xradio_put_skb or
1849 * xradio_put_resv_skb if it is cloned.
1850 */
1851 if (cloned) {
1852 dev_kfree_skb(*skb_p);
1853 *skb_p = NULL;
1854 } else {
1855 /* reset the data begin.*/
1856 skb_push(*skb_p, len);
1857 }
1858 }
1859 }
1860 }
1861 }
1862 return 0;
1863 }
1864
wsm_event_indication(struct xradio_common * hw_priv,struct wsm_buf * buf,int interface_link_id)1865 static int wsm_event_indication(struct xradio_common *hw_priv,
1866 struct wsm_buf *buf,
1867 int interface_link_id)
1868 {
1869 int first;
1870 struct xradio_wsm_event *event = NULL;
1871 struct xradio_vif *priv;
1872
1873 if (!is_hardware_xradio(hw_priv))
1874 interface_link_id = 0;
1875
1876 priv = xrwl_hwpriv_to_vifpriv(hw_priv, interface_link_id);
1877
1878 if (unlikely(!priv)) {
1879 wsm_printk(XRADIO_DBG_WARN, "Event: %d(%d) for removed "
1880 "interface, ignoring\n", __le32_to_cpu(WSM_GET32(buf)),
1881 __le32_to_cpu(WSM_GET32(buf)));
1882 return 0;
1883 }
1884
1885 if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) {
1886 /* STA is stopped. */
1887 return 0;
1888 }
1889 spin_unlock(&priv->vif_lock);
1890
1891 event = xr_kzalloc(sizeof(struct xradio_wsm_event), false);
1892 if (event == NULL) {
1893 wsm_printk(XRADIO_DBG_ERROR, "%s:xr_kzalloc failed!", __func__);
1894 return -EINVAL;
1895 }
1896
1897 event->evt.eventId = __le32_to_cpu(WSM_GET32(buf));
1898 event->evt.eventData = __le32_to_cpu(WSM_GET32(buf));
1899 event->if_id = interface_link_id;
1900
1901 wsm_printk(XRADIO_DBG_MSG, "Event: %d(%d)\n",
1902 event->evt.eventId, event->evt.eventData);
1903 if (event->evt.eventId == WSM_EVENT_ERROR) {
1904 int len = (int)(buf->end - buf->data);
1905 int i = 0;
1906 wsm_printk(XRADIO_DBG_ALWY, "FW TXERR: 0x%08x(%d)\n",
1907 event->evt.eventData, len);
1908 for (i = 0; i < (len>>2); i++)
1909 wsm_printk(XRADIO_DBG_ALWY, "0x%08x\n", __le32_to_cpu(WSM_GET32(buf)));
1910 for (len &= 0x3; len > 0; len--)
1911 wsm_printk(XRADIO_DBG_ALWY, "0x%x\n", __le32_to_cpu(WSM_GET8(buf)));
1912 wsm_printk(XRADIO_DBG_ALWY, "FW TXERR END\n");
1913 }
1914
1915 spin_lock(&hw_priv->event_queue_lock);
1916 first = list_empty(&hw_priv->event_queue);
1917 list_add_tail(&event->link, &hw_priv->event_queue);
1918 spin_unlock(&hw_priv->event_queue_lock);
1919
1920 if (first)
1921 queue_work(hw_priv->workqueue, &hw_priv->event_handler);
1922
1923 return 0;
1924
1925 underflow:
1926 kfree(event);
1927 return -EINVAL;
1928 }
1929
1930 #define PRINT_11K_MEASRURE 1
wsm_measure_cmpl_indication(struct xradio_common * hw_priv,struct wsm_buf * buf)1931 static int wsm_measure_cmpl_indication(struct xradio_common *hw_priv,
1932 struct wsm_buf *buf)
1933 {
1934 MEASUREMENT_COMPLETE measure_cmpl;
1935 u8 cca_chanload;
1936 u32 buf_len = 0;
1937 u32 *data;
1938
1939 LMAC_MEAS_CHANNEL_LOAD_RESULTS *chanload_res;
1940 LMAC_MEAS_NOISE_HISTOGRAM_RESULTS *noise_res;
1941 WSM_GET(buf, &measure_cmpl, 12);
1942
1943 switch (measure_cmpl.MeasurementType) {
1944 case ChannelLoadMeasurement:
1945 buf_len = sizeof(LMAC_MEAS_CHANNEL_LOAD_RESULTS);
1946 break;
1947 case NoiseHistrogramMeasurement:
1948 buf_len = sizeof(LMAC_MEAS_NOISE_HISTOGRAM_RESULTS);
1949 break;
1950 case BeaconReport:
1951 buf_len = sizeof(LMAC_MEAS_BEACON_RESULTS);
1952 break;
1953 case STAstatisticsReport:
1954 buf_len = sizeof(LMAC_MEAS_STA_STATS_RESULTS);
1955 break;
1956 case LinkMeasurement:
1957 buf_len = sizeof(LMAC_MEAS_LINK_MEASUREMENT_RESULTS);
1958 break;
1959 }
1960 wsm_printk(XRADIO_DBG_ERROR, "[11K]buf_len = %d\n", buf_len);
1961 WSM_GET(buf, &measure_cmpl.MeasurementReport, buf_len);
1962
1963 data = (u32 *)(&measure_cmpl);
1964 /*
1965 wsm_printk(XRADIO_DBG_ERROR, "[***11K***]data[0]=%08x\n", data[0]);
1966 wsm_printk(XRADIO_DBG_ERROR, "[***11K***]data[1]=%08x\n", data[1]);
1967 wsm_printk(XRADIO_DBG_ERROR, "[***11K***]data[2]=%08x\n", data[2]);
1968 wsm_printk(XRADIO_DBG_ERROR, "[***11K***]data[3]=%08x\n", data[3]);
1969 wsm_printk(XRADIO_DBG_ERROR, "[***11K***]data[4]=%08x\n", data[4]);
1970 wsm_printk(XRADIO_DBG_ERROR, "[***11K***]data[5]=%08x\n", data[5]);
1971 wsm_printk(XRADIO_DBG_ERROR, "[***11K***]data[6]=%08x\n", data[6]);
1972 */
1973 wsm_printk(XRADIO_DBG_ERROR, "[***11K***]MeasurementType=%0d\n",
1974 measure_cmpl.MeasurementType);
1975
1976 if (measure_cmpl.Status == WSM_STATUS_SUCCESS) {
1977 switch (measure_cmpl.MeasurementType) {
1978 case ChannelLoadMeasurement:
1979 chanload_res = &measure_cmpl.MeasurementReport.ChannelLoadResults;
1980 cca_chanload = (chanload_res->ChannelLoadCCA == MEAS_CCA) ?
1981 chanload_res->CCAbusyFraction :
1982 chanload_res->ChannelLoad;
1983 #ifdef PRINT_11K_MEASRURE
1984 wsm_printk(XRADIO_DBG_ERROR,
1985 "[11K] ChannelLoadMeasurement Result:\n"\
1986 "ChannelLoadCCA = %d\n"\
1987 "ChannelNum = %d\n"\
1988 "Duration = %d\n"\
1989 "Fraction = %d\n", \
1990 chanload_res->ChannelLoadCCA, \
1991 chanload_res->ChannelNum, \
1992 chanload_res->MeasurementDuration, \
1993 cca_chanload);
1994 #endif
1995 break;
1996 case NoiseHistrogramMeasurement:
1997 noise_res = &measure_cmpl.MeasurementReport.NoiseHistogramResults;
1998 /*
1999 IpiRpi = (noise_res->IpiRpi == MEAS_RPI) ?
2000 chanload_res->CCAbusyFraction :
2001 chanload_res->ChannelLoad;
2002 */
2003 #ifdef PRINT_11K_MEASRURE
2004 wsm_printk(XRADIO_DBG_ERROR, "[11K] NoiseHistogramResults:\n"\
2005 "IpiRpi = %d\n"\
2006 "ChannelNum = %d\n"\
2007 "PI_0__Density = %d\n"\
2008 "PI_1__Density = %d\n"\
2009 "PI_2__Density = %d\n"\
2010 "PI_3__Density = %d\n"\
2011 "PI_4__Density = %d\n"\
2012 "PI_5__Density = %d\n"\
2013 "PI_6__Density = %d\n"\
2014 "PI_7__Density = %d\n"\
2015 "PI_8__Density = %d\n"\
2016 "PI_9__Density = %d\n"\
2017 "PI_10_Density = %d\n", \
2018 noise_res->IpiRpi, \
2019 noise_res->ChannelNum, \
2020 noise_res->PI_0_Density, \
2021 noise_res->PI_1_Density, \
2022 noise_res->PI_2_Density, \
2023 noise_res->PI_3_Density, \
2024 noise_res->PI_4_Density, \
2025 noise_res->PI_5_Density, \
2026 noise_res->PI_6_Density, \
2027 noise_res->PI_7_Density, \
2028 noise_res->PI_8_Density, \
2029 noise_res->PI_9_Density, \
2030 noise_res->PI_10_Density \
2031 );
2032 #endif
2033 break;
2034 case BeaconReport:
2035 break;
2036 case STAstatisticsReport:
2037 break;
2038 case LinkMeasurement:
2039 break;
2040 }
2041 } else {
2042 wsm_printk(XRADIO_DBG_ERROR,
2043 "11K Measure(type=%d) Fail\n",
2044 measure_cmpl.MeasurementType);
2045 }
2046
2047 return 0;
2048
2049 underflow:
2050 return -EINVAL;
2051 }
2052 /* TODO:COMBO:Make this perVIFF once mac80211 support is available */
wsm_channel_switch_indication(struct xradio_common * hw_priv,struct wsm_buf * buf)2053 static int wsm_channel_switch_indication(struct xradio_common *hw_priv,
2054 struct wsm_buf *buf)
2055 {
2056 wsm_unlock_tx(hw_priv); /* Re-enable datapath */
2057 SYS_WARN(WSM_GET32(buf));
2058
2059 hw_priv->channel_switch_in_progress = 0;
2060 wake_up(&hw_priv->channel_switch_done);
2061
2062 if (hw_priv->wsm_cbc.channel_switch)
2063 hw_priv->wsm_cbc.channel_switch(hw_priv);
2064 return 0;
2065
2066 underflow:
2067 return -EINVAL;
2068 }
2069
wsm_set_pm_indication(struct xradio_common * hw_priv,struct wsm_buf * buf)2070 static int wsm_set_pm_indication(struct xradio_common *hw_priv,
2071 struct wsm_buf *buf)
2072 {
2073 wsm_oper_unlock(hw_priv);
2074 return 0;
2075 }
2076
wsm_scan_complete_indication(struct xradio_common * hw_priv,struct wsm_buf * buf)2077 static int wsm_scan_complete_indication(struct xradio_common *hw_priv,
2078 struct wsm_buf *buf)
2079 {
2080 //#ifdef ROAM_OFFLOAD
2081 // if (hw_priv->auto_scanning == 0)
2082 // wsm_oper_unlock(hw_priv);
2083 //#else
2084 // wsm_oper_unlock(hw_priv);
2085 //#endif /*ROAM_OFFLOAD*/
2086
2087 if (hw_priv->wsm_cbc.scan_complete) {
2088 struct wsm_scan_complete arg;
2089 arg.status = WSM_GET32(buf);
2090 arg.psm = WSM_GET8(buf);
2091 arg.numChannels = WSM_GET8(buf);
2092 hw_priv->wsm_cbc.scan_complete(hw_priv, &arg);
2093 }
2094 return 0;
2095
2096 underflow:
2097 return -EINVAL;
2098 }
2099
wsm_find_complete_indication(struct xradio_common * hw_priv,struct wsm_buf * buf)2100 static int wsm_find_complete_indication(struct xradio_common *hw_priv,
2101 struct wsm_buf *buf)
2102 {
2103 /* TODO: Implement me. */
2104 /*STUB();*/
2105 return 0;
2106 }
2107
wsm_suspend_resume_indication(struct xradio_common * hw_priv,int interface_link_id,struct wsm_buf * buf)2108 static int wsm_suspend_resume_indication(struct xradio_common *hw_priv,
2109 int interface_link_id,
2110 struct wsm_buf *buf)
2111 {
2112 if (hw_priv->wsm_cbc.suspend_resume) {
2113 u32 flags;
2114 struct wsm_suspend_resume arg;
2115 struct xradio_vif *priv;
2116
2117 if (is_hardware_xradio(hw_priv)) {
2118 int i;
2119 arg.if_id = interface_link_id;
2120 /* TODO:COMBO: Extract bitmap from suspend-resume
2121 * TX indication */
2122 xradio_for_each_vif(hw_priv, priv, i) {
2123 if (!priv)
2124 continue;
2125 if (priv->join_status ==
2126 XRADIO_JOIN_STATUS_AP) {
2127 arg.if_id = priv->if_id;
2128 break;
2129 }
2130 arg.link_id = 0;
2131 }
2132 } else {
2133 arg.if_id = 0;
2134 arg.link_id = interface_link_id;
2135 }
2136
2137 flags = WSM_GET32(buf);
2138 arg.stop = !(flags & 1);
2139 arg.multicast = !!(flags & 8);
2140 arg.queue = (flags >> 1) & 3;
2141
2142 priv = xrwl_hwpriv_to_vifpriv(hw_priv, arg.if_id);
2143 if (unlikely(!priv)) {
2144 wsm_printk(XRADIO_DBG_MSG, "suspend-resume indication"
2145 " for removed interface!\n");
2146 return 0;
2147 }
2148 hw_priv->wsm_cbc.suspend_resume(priv, &arg);
2149 spin_unlock(&priv->vif_lock);
2150 }
2151 return 0;
2152
2153 underflow:
2154 return -EINVAL;
2155 }
2156
2157
2158 /* ******************************************************************** */
2159 /* WSM TX */
wsm_cmd_send(struct xradio_common * hw_priv,struct wsm_buf * buf,void * arg,u16 cmd,long tmo,int if_id)2160 int wsm_cmd_send(struct xradio_common *hw_priv,
2161 struct wsm_buf *buf,
2162 void *arg, u16 cmd, long tmo, int if_id)
2163 {
2164 size_t buf_len = buf->data - buf->begin;
2165 int ret;
2166 u16 mib_id = 0;
2167 unsigned long wsm_cmd_max_tmo = 0x0;
2168
2169 if (cmd == 0x0006 || cmd == 0x0005) {/* Write/Read MIB */
2170 mib_id = __le16_to_cpu(((__le16 *)buf->begin)[2]);
2171 wsm_printk(XRADIO_DBG_MSG, ">>> 0x%.4X [MIB: 0x%.4X] (%zu)\n",
2172 cmd, mib_id, buf_len);
2173 } else {
2174 wsm_printk(XRADIO_DBG_MSG, ">>> 0x%.4X (%zu)\n", cmd, buf_len);
2175 }
2176
2177 #ifdef HW_RESTART
2178 if (hw_priv->hw_restart) {
2179 wsm_printk(XRADIO_DBG_NIY, "hw reset!>>> 0x%.4X (%zu)\n", cmd, buf_len);
2180 wsm_buf_reset(buf);
2181 return 0; /*return success, don't process cmd in power off.*/
2182 }
2183 #endif
2184
2185 if (unlikely(hw_priv->bh_error)) {
2186 wsm_buf_reset(buf);
2187 wsm_printk(XRADIO_DBG_ERROR, "bh error!>>> 0x%.4X (%zu)\n", cmd, buf_len);
2188 return -ETIMEDOUT;
2189 }
2190
2191 /* Fill HI message header */
2192 /* BH will add sequence number */
2193
2194 /* TODO:COMBO: Add if_id from to the WSM header */
2195 /* if_id == -1 indicates that command is HW specific,
2196 * eg. wsm_configuration which is called during driver initialzation
2197 * (mac80211 .start callback called when first ifce is created.)
2198 */
2199
2200 /* send hw specific commands on if 0 */
2201 if (if_id == -1)
2202 if_id = 0;
2203
2204 ((__le16 *)buf->begin)[0] = __cpu_to_le16(buf_len);
2205 ((__le16 *)buf->begin)[1] = __cpu_to_le16(cmd |
2206 ((is_hardware_xradio(hw_priv)) ? (if_id << 6) : 0));
2207
2208 spin_lock(&hw_priv->wsm_cmd.lock);
2209 SYS_BUG(hw_priv->wsm_cmd.ptr);
2210 hw_priv->wsm_cmd.done = 0;
2211 hw_priv->wsm_cmd.ptr = buf->begin;
2212 hw_priv->wsm_cmd.len = buf_len;
2213 hw_priv->wsm_cmd.arg = arg;
2214 hw_priv->wsm_cmd.cmd = cmd;
2215 spin_unlock(&hw_priv->wsm_cmd.lock);
2216
2217 xradio_bh_wakeup(hw_priv);
2218 if (unlikely(hw_priv->bh_error)) {
2219 /* Do not wait for timeout if BH is dead. Exit immediately. */
2220 ret = 0;
2221 } else {
2222 /* Give start cmd a little more time */
2223 if (unlikely(tmo == WSM_CMD_START_TIMEOUT))
2224 wsm_cmd_max_tmo = WSM_CMD_START_TIMEOUT;
2225 else
2226 wsm_cmd_max_tmo = WSM_CMD_DEFAULT_TIMEOUT;
2227
2228 /*Set max timeout.*/
2229 wsm_cmd_max_tmo = jiffies + wsm_cmd_max_tmo;
2230
2231 /* Firmware prioritizes data traffic over control confirm.
2232 * Loop below checks if data was RXed and increases timeout
2233 * accordingly. */
2234 do {
2235 /* It's safe to use unprotected access to wsm_cmd.done here */
2236 ret = wait_event_timeout(hw_priv->wsm_cmd_wq,
2237 hw_priv->wsm_cmd.done, tmo);
2238
2239 /* check time since last rxed and max timeout.*/
2240 } while (!ret &&
2241 time_before_eq(jiffies, hw_priv->rx_timestamp+tmo) &&
2242 time_before(jiffies, wsm_cmd_max_tmo));
2243
2244 }
2245
2246 if (unlikely(ret == 0 && !hw_priv->wsm_cmd.done)) {
2247 u16 raceCheck;
2248
2249 wsm_printk(XRADIO_DBG_ERROR,
2250 "***CMD timeout(%ld, %lu, %lu)!>>> 0x%.4X [0x%.4X](%zu), "
2251 "cmd_ptr=%p, buf_use=%d, bh_state=%d\n",
2252 tmo, wsm_cmd_max_tmo, jiffies,
2253 cmd | hw_priv->wsm_cmd.seq, mib_id, buf_len,
2254 hw_priv->wsm_cmd.ptr, hw_priv->hw_bufs_used,
2255 hw_priv->bh_error);
2256
2257 spin_lock(&hw_priv->wsm_cmd.lock);
2258 raceCheck = hw_priv->wsm_cmd.cmd;
2259 hw_priv->wsm_cmd.arg = NULL;
2260 hw_priv->wsm_cmd.ptr = NULL;
2261 spin_unlock(&hw_priv->wsm_cmd.lock);
2262
2263 /* Race condition check to make sure _confirm is not called
2264 * after exit of _send */
2265 if (raceCheck == 0xFFFF) {
2266 /* If wsm_handle_rx got stuck in _confirm we will hang
2267 * system there. It's better than silently currupt
2268 * stack or heap, isn't it? */
2269 SYS_BUG(wait_event_timeout(
2270 hw_priv->wsm_cmd_wq,
2271 hw_priv->wsm_cmd.done,
2272 WSM_CMD_LAST_CHANCE_TIMEOUT) <= 0);
2273 }
2274
2275 /* Kill BH thread to report the error to the top layer. */
2276 hw_priv->bh_error = 1;
2277 #ifdef BH_USE_SEMAPHORE
2278 up(&hw_priv->bh_sem);
2279 #else
2280 wake_up(&hw_priv->bh_wq);
2281 #endif
2282 ret = -ETIMEDOUT;
2283 } else {
2284 spin_lock(&hw_priv->wsm_cmd.lock);
2285 SYS_BUG(!hw_priv->wsm_cmd.done);
2286 ret = hw_priv->wsm_cmd.ret;
2287 spin_unlock(&hw_priv->wsm_cmd.lock);
2288 }
2289 wsm_buf_reset(buf);
2290 return ret;
2291 }
2292
2293 /* ******************************************************************** */
2294 /* WSM TX port control */
2295
wsm_lock_tx(struct xradio_common * hw_priv)2296 void wsm_lock_tx(struct xradio_common *hw_priv)
2297 {
2298 down(&hw_priv->tx_lock_sem);
2299 atomic_add(1, &hw_priv->tx_lock);
2300 /* always check event if wsm_vif_lock_tx.*/
2301 if (wsm_flush_tx(hw_priv))
2302 wsm_printk(XRADIO_DBG_MSG, "TX is locked.\n");
2303 up(&hw_priv->tx_lock_sem);
2304 }
2305
wsm_vif_lock_tx(struct xradio_vif * priv)2306 void wsm_vif_lock_tx(struct xradio_vif *priv)
2307 {
2308 struct xradio_common *hw_priv = priv->hw_priv;
2309 down(&hw_priv->tx_lock_sem);
2310 if (atomic_add_return(1, &hw_priv->tx_lock) == 1) {
2311 if (wsm_vif_flush_tx(priv))
2312 wsm_printk(XRADIO_DBG_MSG, "TX is locked for"
2313 " if_id %d.\n", priv->if_id);
2314 }
2315 up(&hw_priv->tx_lock_sem);
2316 }
2317
wsm_lock_tx_async(struct xradio_common * hw_priv)2318 void wsm_lock_tx_async(struct xradio_common *hw_priv)
2319 {
2320 if (atomic_add_return(1, &hw_priv->tx_lock) == 1)
2321 wsm_printk(XRADIO_DBG_MSG, "TX is locked (async).\n");
2322 }
2323
wsm_flush_tx(struct xradio_common * hw_priv)2324 bool wsm_flush_tx(struct xradio_common *hw_priv)
2325 {
2326 long timeout = WSM_CMD_LAST_CHANCE_TIMEOUT;
2327
2328 /* Flush must be called with TX lock held. */
2329 SYS_BUG(!atomic_read(&hw_priv->tx_lock));
2330
2331 /* First check if we really need to do something.
2332 * It is safe to use unprotected access, as hw_bufs_used
2333 * can only decrements. */
2334 if (!hw_priv->hw_bufs_used)
2335 return true;
2336
2337 if (hw_priv->bh_error) {
2338 /* In case of failure do not wait for magic. */
2339 wsm_printk(XRADIO_DBG_ERROR, "Fatal error occured, "
2340 "will not flush TX.\n");
2341 return false;
2342 } else {
2343 /* Get "oldest" frame, if any frames stuck in firmware,
2344 query all of them until max timeout. */
2345 int num = hw_priv->hw_bufs_used + 1;
2346 while (xradio_query_txpkt_timeout(hw_priv, XRWL_ALL_IFS,
2347 0xffffffff, &timeout)) {
2348 if (timeout < 0 || !num) {
2349 /* Hmmm... Not good. Frame had stuck in firmware. */
2350 wsm_printk(XRADIO_DBG_ERROR,
2351 "%s:timeout=%ld, hw_bufs_used=%d, num=%d\n",
2352 __func__, timeout, hw_priv->hw_bufs_used, num);
2353 hw_priv->bh_error = 1;
2354 #ifdef BH_USE_SEMAPHORE
2355 up(&hw_priv->bh_sem);
2356 #else
2357 wake_up(&hw_priv->bh_wq);
2358 #endif
2359 return false;
2360 } else if (wait_event_timeout(hw_priv->bh_evt_wq,
2361 !hw_priv->hw_bufs_used, timeout) > 0) {
2362 return true;
2363 }
2364 --num;
2365 }
2366 if (hw_priv->hw_bufs_used)
2367 wsm_printk(XRADIO_DBG_WARN,
2368 "%s:No pengding, but hw_bufs_used=%d\n",
2369 __func__, hw_priv->hw_bufs_used);
2370 /* Ok, everything is flushed. */
2371 return true;
2372 }
2373 }
2374
wsm_vif_flush_tx(struct xradio_vif * priv)2375 bool wsm_vif_flush_tx(struct xradio_vif *priv)
2376 {
2377 struct xradio_common *hw_priv = priv->hw_priv;
2378 long timeout = WSM_CMD_LAST_CHANCE_TIMEOUT;
2379 int if_id = priv->if_id;
2380
2381 /* Flush must be called with TX lock held. */
2382 SYS_BUG(!atomic_read(&hw_priv->tx_lock));
2383
2384 /* First check if we really need to do something.
2385 * It is safe to use unprotected access, as hw_bufs_used
2386 * can only decrements. */
2387 if (!hw_priv->hw_bufs_used_vif[if_id])
2388 return true;
2389
2390 if (hw_priv->bh_error) {
2391 /* In case of failure do not wait for magic. */
2392 wsm_printk(XRADIO_DBG_ERROR, "Fatal error occured, "
2393 "will not flush TX.\n");
2394 return false;
2395 } else {
2396 /* Get "oldest" frame, if any frames stuck in firmware,
2397 query all of them until max timeout. */
2398 int num = hw_priv->hw_bufs_used_vif[if_id] + 1;
2399 while (xradio_query_txpkt_timeout(hw_priv, if_id,
2400 0xffffffff, &timeout)) {
2401 if (timeout < 0 || !num) {
2402 /* Hmmm... Not good. Frame had stuck in firmware. */
2403 wsm_printk(XRADIO_DBG_ERROR,
2404 "%s: if_id=%d, hw_bufs_used_vif=%d, num=%d\n",
2405 __func__, if_id,
2406 hw_priv->hw_bufs_used_vif[priv->if_id], num);
2407 hw_priv->bh_error = 1;
2408 #ifdef BH_USE_SEMAPHORE
2409 up(&hw_priv->bh_sem);
2410 #else
2411 wake_up(&hw_priv->bh_wq);
2412 #endif
2413 return false;
2414 } else if (wait_event_timeout(hw_priv->bh_evt_wq,
2415 !hw_priv->hw_bufs_used_vif[if_id], timeout) > 0) {
2416 return true;
2417 }
2418 --num;
2419 }
2420 if (hw_priv->hw_bufs_used_vif[if_id])
2421 wsm_printk(XRADIO_DBG_WARN,
2422 "%s:No pengding, but hw_bufs_used_vif=%d\n",
2423 __func__, hw_priv->hw_bufs_used_vif[priv->if_id]);
2424 /* Ok, everything is flushed. */
2425 return true;
2426 }
2427 }
2428
2429
wsm_unlock_tx(struct xradio_common * hw_priv)2430 void wsm_unlock_tx(struct xradio_common *hw_priv)
2431 {
2432 int tx_lock;
2433 if (hw_priv->bh_error)
2434 wsm_printk(XRADIO_DBG_ERROR, "bh_error=%d, wsm_unlock_tx is unsafe\n",
2435 hw_priv->bh_error);
2436 else {
2437 tx_lock = atomic_sub_return(1, &hw_priv->tx_lock);
2438 if (tx_lock < 0) {
2439 SYS_BUG(1);
2440 } else if (tx_lock == 0) {
2441 #if BH_PROC_TX
2442 xradio_proc_wakeup(hw_priv);
2443 #endif
2444 xradio_bh_wakeup(hw_priv);
2445 wsm_printk(XRADIO_DBG_MSG, "TX is unlocked.\n");
2446 }
2447 }
2448 }
2449
2450 /* ******************************************************************** */
2451 /* WSM RX */
wsm_handle_exception(struct xradio_common * hw_priv,u8 * data,size_t len)2452 int wsm_handle_exception(struct xradio_common *hw_priv, u8 *data, size_t len)
2453 {
2454 struct wsm_buf buf;
2455 u32 reason;
2456 u32 reg[18];
2457 char fname[48];
2458 int i = 0;
2459
2460 #ifdef CONFIG_XRADIO_DEBUG
2461 static const char * const reason_str[] = {
2462 "undefined instruction",
2463 "prefetch abort",
2464 "data abort",
2465 "unknown error",
2466 };
2467 #endif
2468
2469 buf.begin = buf.data = data;
2470 buf.end = &buf.begin[len];
2471
2472 reason = WSM_GET32(&buf);
2473 for (i = 0; i < ARRAY_SIZE(reg); ++i)
2474 reg[i] = WSM_GET32(&buf);
2475 WSM_GET(&buf, fname, sizeof(fname));
2476
2477 if (reason < 4) {
2478 #ifdef SUPPORT_FW_DBG_INF
2479 xradio_fw_dbg_set_dump_flag_on_fw_exception();
2480 #endif
2481 wsm_printk(XRADIO_DBG_ERROR, "Firmware exception: %s.\n",
2482 reason_str[reason]);
2483 } else {
2484 wsm_printk(XRADIO_DBG_ERROR,
2485 "Firmware assert at %.*s, line %d, reason=0x%x\n",
2486 (int)sizeof(fname), fname, reg[1], reg[2]);
2487 }
2488
2489 for (i = 0; i < 12; i += 4) {
2490 wsm_printk(XRADIO_DBG_ERROR, "Firmware:" \
2491 "R%d: 0x%.8X, R%d: 0x%.8X, R%d: 0x%.8X, R%d: 0x%.8X, \n",
2492 i + 0, reg[i + 0], i + 1, reg[i + 1],
2493 i + 2, reg[i + 2], i + 3, reg[i + 3]);
2494 }
2495 wsm_printk(XRADIO_DBG_ERROR, "Firmware:" \
2496 "R12: 0x%.8X, SP: 0x%.8X, LR: 0x%.8X, PC: 0x%.8X, \n",
2497 reg[i + 0], reg[i + 1], reg[i + 2], reg[i + 3]);
2498 i += 4;
2499 wsm_printk(XRADIO_DBG_ERROR, "Firmware:CPSR: 0x%.8X, SPSR: 0x%.8X\n",
2500 reg[i + 0], reg[i + 1]);
2501
2502 return 0;
2503
2504 underflow:
2505 wiphy_err(hw_priv->hw->wiphy, "Firmware exception.\n");
2506 print_hex_dump_bytes("Exception: ", DUMP_PREFIX_NONE, data, len);
2507 return -EINVAL;
2508 }
2509
wsm_debug_indication(struct xradio_common * hw_priv,struct wsm_buf * buf)2510 static int wsm_debug_indication(struct xradio_common *hw_priv,
2511 struct wsm_buf *buf)
2512 {
2513 /*for only one debug item.*/
2514
2515 u32 buf_data = 0;
2516
2517 u32 dbg_id;
2518 u16 dbg_buf_len;
2519 u8 dbg_len;
2520 u8 *dbg_buf;
2521
2522 dbg_id = WSM_GET32(buf);
2523
2524 dbg_buf_len = buf->end - buf->data;
2525
2526 if (dbg_id == 5) {
2527 do {
2528 dbg_buf_len = buf->end - buf->data;
2529 dbg_len = WSM_GET8(buf);
2530 if (dbg_len > dbg_buf_len - sizeof(dbg_len)) {
2531 wsm_printk(XRADIO_DBG_ERROR,
2532 "[FW]dbg_len = %d\n", dbg_len);
2533 wsm_printk(XRADIO_DBG_ERROR,
2534 "[FW]dbg_buf_len = %d\n", dbg_buf_len);
2535 wsm_printk(XRADIO_DBG_ERROR, "[FW]debug ind err\n");
2536 break;
2537 }
2538 dbg_buf = buf->data;
2539 /*print it;*/
2540 wsm_printk(XRADIO_DBG_ALWY, "[FW-LOG] %s", dbg_buf);
2541 buf->data += dbg_len;
2542 } while (buf->data < buf->end);
2543 } else {
2544 wsm_printk(XRADIO_DBG_ERROR, "[FW-DEBUG] DbgId = %d\n", dbg_id);
2545 while (buf->end - buf->data >= 4) {
2546 buf_data = WSM_GET32(buf);
2547 wsm_printk(XRADIO_DBG_ERROR, "[FW-DEBUG] 0x%08X\n", buf_data);
2548 }
2549 }
2550
2551 return 0;
2552
2553 underflow:
2554 SYS_WARN(1);
2555 return -EINVAL;
2556 }
2557
2558 #if (DGB_XRADIO_HWT)
2559 extern u8 hwt_testing;
2560 extern u16 hwt_tx_len;
2561 extern u16 hwt_tx_num;
2562 extern int sent_num;
2563 extern struct timespec64 hwt_start_time;
2564 extern struct timespec64 hwt_end_time;
wsm_hwt_tx_confirm(struct xradio_common * hw_priv,struct wsm_buf * buf)2565 int wsm_hwt_tx_confirm(struct xradio_common *hw_priv, struct wsm_buf *buf)
2566 {
2567 u8 num = *(buf->data + 6);
2568 u16 *through_put = (u16 *)(buf->data) + 3;
2569
2570 wsm_printk(XRADIO_DBG_NIY, "%s, num=%d, hw_bufs_used=%d, confirm[7]=%d\n",
2571 __func__, num, hw_priv->hw_bufs_used, *(buf->data+7));
2572
2573 /*one release is in bh.*/
2574 wsm_release_vif_tx_buffer(hw_priv, 0, num - 1);
2575 wsm_release_tx_buffer(hw_priv, num - 1);
2576
2577 /*confirm of last packet, so report the test results.*/
2578 if (*(buf->data+7) & 0x01) { /*last packet*/
2579 u32 time_int = 0;
2580 u32 total = hwt_tx_num*hwt_tx_len*8;
2581 xr_do_gettimeofday(&hwt_end_time);
2582 time_int = (hwt_end_time.tv_sec-hwt_start_time.tv_sec)*1000000 + \
2583 (hwt_end_time.tv_usec-hwt_start_time.tv_usec);
2584 wsm_printk(XRADIO_DBG_ALWY,
2585 "%s, HIF TX: time=%dms, throughput=%d.%dMbps\n", __func__,
2586 time_int/1000, total/time_int, (total%time_int)*10/time_int);
2587 *through_put = (u16)((total*10)/time_int);
2588 hwt_tx_len = 0;
2589 hwt_tx_num = 0;
2590 sent_num = 0; /*reset the sent_num*/
2591 hwt_testing = 0;
2592 return 1;
2593 }
2594 return 0;
2595 }
2596
2597 u16 recv_num;
2598 extern u8 hwt_rx_en;
2599 extern u16 hwt_rx_len;
2600 extern u16 hwt_rx_num;
wsm_hwt_rx_frames(struct xradio_common * hw_priv,struct wsm_buf * buf)2601 int wsm_hwt_rx_frames(struct xradio_common *hw_priv, struct wsm_buf *buf)
2602 {
2603
2604 wsm_printk(XRADIO_DBG_NIY, "%s, status=%d, len=%d\n", __func__,
2605 *(u16 *)(buf->data+2), *(u16 *)(buf->data+4));
2606 recv_num++;
2607 if (recv_num >= hwt_rx_num) { /*last packet*/
2608 u32 time_int = 0;
2609 u32 total = recv_num*hwt_rx_len*8;
2610 xr_do_gettimeofday(&hwt_end_time);
2611 time_int = (hwt_end_time.tv_sec-hwt_start_time.tv_sec)*1000000 + \
2612 (hwt_end_time.tv_usec-hwt_start_time.tv_usec);
2613 // wsm_printk(XRADIO_DBG_ALWY,
2614 // "%s, HIF RX: time=%dms, throughput=%d.%dMbps\n",
2615 // __func__, time_int/1000, total/time_int,
2616 // (total%time_int)*10/time_int);
2617 hwt_rx_en = 0;
2618 hwt_rx_num = 0;
2619 recv_num = 0; /*reset the recv_num*/
2620 // hwt_testing = 0; //set to 0 when 0x404 received
2621 }
2622
2623 return 0;
2624 }
2625
wsm_hwt_enc_results(struct xradio_common * hw_priv,struct wsm_buf * buf)2626 int wsm_hwt_enc_results(struct xradio_common *hw_priv, struct wsm_buf *buf)
2627 {
2628 wsm_printk(XRADIO_DBG_ALWY,
2629 "%s, status=%d, enc throughput=%d.%02dMbps\n", __func__,
2630 *(u16 *)(buf->data+2), *(u32 *)(buf->data+8),
2631 *(u32 *)(buf->data+12));
2632 hwt_testing = 0;
2633 return 0;
2634 }
2635
wsm_hwt_mic_results(struct xradio_common * hw_priv,struct wsm_buf * buf)2636 int wsm_hwt_mic_results(struct xradio_common *hw_priv, struct wsm_buf *buf)
2637 {
2638 wsm_printk(XRADIO_DBG_ALWY,
2639 "%s, status=%d, mic throughput=%d.%02dMbps\n", __func__,
2640 *(u16 *)(buf->data+2), *(u32 *)(buf->data+8),
2641 *(u32 *)(buf->data+12));
2642 hwt_testing = 0;
2643 return 0;
2644 }
2645 #endif /*DGB_XRADIO_HWT*/
2646
2647 #if PERF_INFO_TEST
2648 struct timespec64 ind_rx_time;
2649
2650 #endif
2651
wsm_handle_rx(struct xradio_common * hw_priv,u8 flags,struct sk_buff ** skb_p)2652 int wsm_handle_rx(struct xradio_common *hw_priv, u8 flags, struct sk_buff **skb_p)
2653 {
2654 int ret = 0;
2655 struct xradio_vif *priv = NULL;
2656 int i = 0;
2657 struct wsm_buf wsm_buf;
2658 size_t total_len = (*skb_p)->len;
2659 struct wsm_hdr *wsm = (struct wsm_hdr *)((*skb_p)->data);
2660 int id = __le32_to_cpu(wsm->id) & 0xFFF;
2661 int interface_link_id = (id >> 6) & 0x0F;
2662 #ifdef ROAM_OFFLOAD
2663 #if 0
2664 struct xradio_vif *priv;
2665 priv = xrwl_hwpriv_to_vifpriv(hw_priv, interface_link_id);
2666 if (unlikely(!priv)) {
2667 SYS_WARN(1);
2668 return 0;
2669 }
2670 spin_unlock(&priv->vif_lock);
2671 #endif
2672 #endif/*ROAM_OFFLOAD*/
2673
2674 /* Strip link id. */
2675 id &= ~WSM_TX_LINK_ID(WSM_TX_LINK_ID_MAX);
2676
2677 wsm_buf.begin = (u8 *)&wsm[0];
2678 wsm_buf.data = (u8 *)&wsm[1];
2679 wsm_buf.end = &wsm_buf.begin[__le32_to_cpu(wsm->len)];
2680
2681 wsm_printk(XRADIO_DBG_MSG, "<<< 0x%.4X (%zu)\n", id,
2682 (size_t)(wsm_buf.end - wsm_buf.begin));
2683
2684 #ifdef CONFIG_XRADIO_ETF
2685 if (etf_is_connect()) {
2686 if (id == 0x0801) {
2687 /* ETF_CONTEXT_OFFSET need to consist with etf fw.*/
2688 u8 *pContext = wsm_buf.data + ETF_CONTEXT_OFFSET;
2689 xradio_etf_save_context(pContext, (int)(wsm_buf.end - pContext));
2690 wsm_startup_indication(hw_priv, &wsm_buf);
2691 }
2692 #if (DGB_XRADIO_HWT)
2693 /***************************for HWT ********************************/
2694 else if (id == 0x0404) {
2695 u16 TestID = *(u16 *)(wsm_buf.data);
2696 if (TestID == 1) { /*test frame confirm.*/
2697 if (wsm_hwt_tx_confirm(hw_priv, &wsm_buf)) {
2698 spin_lock(&hw_priv->wsm_cmd.lock);
2699 hw_priv->wsm_cmd.ret = *((u16 *)(wsm_buf.data) + 3);
2700 hw_priv->wsm_cmd.done = 1;
2701 spin_unlock(&hw_priv->wsm_cmd.lock);
2702 wake_up(&hw_priv->wsm_cmd_wq);
2703 wsm_printk(XRADIO_DBG_ALWY, "%s:HWT TestID=0x%x Confirm ret=%d\n",
2704 __func__, *(u16 *)(wsm_buf.data), hw_priv->wsm_cmd.ret);
2705 return xradio_etf_from_device(skb_p);
2706 }
2707 } else {
2708 spin_lock(&hw_priv->wsm_cmd.lock);
2709 hw_priv->wsm_cmd.ret = *((u16 *)(wsm_buf.data) + 1);
2710 hw_priv->wsm_cmd.done = 1;
2711 spin_unlock(&hw_priv->wsm_cmd.lock);
2712 wake_up(&hw_priv->wsm_cmd_wq);
2713 hwt_testing = 0;
2714 wsm_printk(XRADIO_DBG_ALWY, "%s:HWT TestID=0x%x Confirm ret=%d\n",
2715 __func__, *(u16 *)(wsm_buf.data), hw_priv->wsm_cmd.ret);
2716 return xradio_etf_from_device(skb_p);
2717 }
2718 return 0;
2719 } else if (id == 0x0804) {
2720 u16 TestID = *(u16 *)(wsm_buf.data);
2721 switch (TestID) {
2722 case 2: /*recieve a test frame.*/
2723 wsm_hwt_rx_frames(hw_priv, &wsm_buf);
2724 break;
2725 case 3: /*enc test result.*/
2726 wsm_hwt_enc_results(hw_priv, &wsm_buf);
2727 break;
2728 case 4: /*mic test result.*/
2729 wsm_hwt_mic_results(hw_priv, &wsm_buf);
2730 break;
2731 case 5:
2732 break;
2733 default:
2734 wsm_printk(XRADIO_DBG_ERROR,
2735 "HWT ERROR Indication TestID=0x%x\n", TestID);
2736 break;
2737 }
2738 return 0;
2739 }
2740 /***************************for HWT ********************************/
2741 #endif /*DGB_XRADIO_HWT*/
2742 else {
2743 spin_lock(&hw_priv->wsm_cmd.lock);
2744 hw_priv->wsm_cmd.ret = 0;
2745 hw_priv->wsm_cmd.done = 1;
2746 spin_unlock(&hw_priv->wsm_cmd.lock);
2747 wake_up(&hw_priv->wsm_cmd_wq);
2748 }
2749 return xradio_etf_from_device(skb_p);
2750 }
2751 #endif
2752
2753 #if (DGB_XRADIO_HWT)
2754 /***************************for HWT ********************************/
2755 if (id == 0x0424) {
2756 u16 TestID = *(u16 *)(wsm_buf.data);
2757 if (TestID == 1) /*test frame confirm.*/
2758 wsm_hwt_tx_confirm(hw_priv, &wsm_buf);
2759 else {
2760 spin_lock(&hw_priv->wsm_cmd.lock);
2761 hw_priv->wsm_cmd.ret = *((u16 *)(wsm_buf.data) + 1);
2762 hw_priv->wsm_cmd.done = 1;
2763 spin_unlock(&hw_priv->wsm_cmd.lock);
2764 wake_up(&hw_priv->wsm_cmd_wq);
2765 wsm_printk(XRADIO_DBG_ALWY, "HWT TestID=0x%x Confirm ret=%d\n",
2766 *(u16 *)(wsm_buf.data), hw_priv->wsm_cmd.ret);
2767 }
2768 return 0;
2769 } else if (id == 0x0824) {
2770 u16 TestID = *(u16 *)(wsm_buf.data);
2771 switch (TestID) {
2772 case 2: /*recieve a test frame.*/
2773 wsm_hwt_rx_frames(hw_priv, &wsm_buf);
2774 break;
2775 case 3: /*enc test result.*/
2776 wsm_hwt_enc_results(hw_priv, &wsm_buf);
2777 break;
2778 case 4: /*mic test result.*/
2779 wsm_hwt_mic_results(hw_priv, &wsm_buf);
2780 break;
2781 case 5:
2782 break;
2783 default:
2784 wsm_printk(XRADIO_DBG_ERROR,
2785 "HWT ERROR Indication TestID=0x%x\n", TestID);
2786 break;
2787 }
2788 return 0;
2789 }
2790 /***************************for HWT ********************************/
2791 #endif /*DGB_XRADIO_HWT*/
2792
2793 if (id == 0x404) {
2794 DBG_ARRY_ADD(dbg_txconfirm, 0);
2795 ret = wsm_tx_confirm(hw_priv, &wsm_buf, interface_link_id);
2796 #ifdef MCAST_FWDING
2797 #if 1
2798 } else if (id == 0x422) {
2799 ret = wsm_give_buffer_confirm(hw_priv, &wsm_buf);
2800 #endif
2801 #endif
2802
2803 } else if (id == 0x41E) {
2804 ret = wsm_multi_tx_confirm(hw_priv, &wsm_buf,
2805 interface_link_id);
2806 } else if (id & 0x0400) {
2807 void *wsm_arg;
2808 u16 wsm_cmd;
2809
2810 /* Do not trust FW too much. Protection against repeated
2811 * response and race condition removal (see above). */
2812 spin_lock(&hw_priv->wsm_cmd.lock);
2813 wsm_arg = hw_priv->wsm_cmd.arg;
2814 wsm_cmd = hw_priv->wsm_cmd.cmd &
2815 ~WSM_TX_LINK_ID(WSM_TX_LINK_ID_MAX);
2816 hw_priv->wsm_cmd.cmd = 0xFFFF;
2817 spin_unlock(&hw_priv->wsm_cmd.lock);
2818
2819 if (SYS_WARN((id & ~0x0400) != wsm_cmd)) {
2820 /* Note that any non-zero is a fatal retcode. */
2821 ret = -EINVAL;
2822 goto out;
2823 }
2824
2825 switch (id) {
2826 case 0x0409:
2827 /* Note that wsm_arg can be NULL in case of timeout in
2828 * wsm_cmd_send(). */
2829 if (likely(wsm_arg))
2830 ret = wsm_configuration_confirm(hw_priv,
2831 wsm_arg,
2832 &wsm_buf);
2833 break;
2834 case 0x0405:
2835 if (likely(wsm_arg))
2836 ret = wsm_read_mib_confirm(hw_priv, wsm_arg,
2837 &wsm_buf);
2838 break;
2839 case 0x0406:
2840 if (likely(wsm_arg))
2841 ret = wsm_write_mib_confirm(hw_priv, wsm_arg,
2842 &wsm_buf,
2843 interface_link_id);
2844 break;
2845 case 0x040B:
2846 if (likely(wsm_arg))
2847 ret = wsm_join_confirm(hw_priv, wsm_arg, &wsm_buf);
2848 if (ret)
2849 wsm_printk(XRADIO_DBG_WARN, "Join confirm Failed!\n");
2850 break;
2851 case 0x040E: /* 11K measure*/
2852 if (likely(wsm_arg))
2853 ret = wsm_generic_confirm(hw_priv, wsm_arg, &wsm_buf);
2854 if (ret)
2855 wsm_printk(XRADIO_DBG_ERROR, "[***11K***] Confirm Error\n");
2856
2857 break;
2858
2859 #ifdef MCAST_FWDING
2860 case 0x0423: /* req buffer cfm*/
2861 if (likely(wsm_arg)) {
2862 xradio_for_each_vif(hw_priv, priv, i) {
2863 if (priv && (priv->join_status == XRADIO_JOIN_STATUS_AP))
2864 ret = wsm_request_buffer_confirm(priv,
2865 wsm_arg, &wsm_buf);
2866 }
2867 }
2868 break;
2869 #endif
2870
2871 case 0x0425:
2872 ret = wsm_fw_dbg_confirm(hw_priv, wsm_arg, &wsm_buf);
2873
2874 if (ret)
2875 wsm_printk(XRADIO_DBG_ERROR,
2876 "[0x%04x] ret(%d): Confirm Error, msg_len:%d\n",
2877 id, ret, wsm->len);
2878 break;
2879
2880 case 0x0407: /* start-scan */
2881 #ifdef ROAM_OFFLOAD
2882 if (hw_priv->auto_scanning) {
2883 if (atomic_read(&hw_priv->scan.in_progress)) {
2884 hw_priv->auto_scanning = 0;
2885 } else {
2886 wsm_oper_unlock(hw_priv);
2887 up(&hw_priv->scan.lock);
2888 }
2889 }
2890 #endif /*ROAM_OFFLOAD*/
2891 case 0x0408: /* stop-scan */
2892 case 0x040A: /* wsm_reset */
2893 case 0x040C: /* add_key */
2894 case 0x040D: /* remove_key */
2895 case 0x0410: /* wsm_set_pm */
2896 case 0x0411: /* set_bss_params */
2897 case 0x0412: /* set_tx_queue_params */
2898 case 0x0413: /* set_edca_params */
2899 case 0x0416: /* switch_channel */
2900 case 0x0417: /* start */
2901 case 0x0418: /* beacon_transmit */
2902 case 0x0419: /* start_find */
2903 case 0x041A: /* stop_find */
2904 case 0x041B: /* update_ie */
2905 case 0x041C: /* map_link */
2906 SYS_WARN(wsm_arg != NULL);
2907 ret = wsm_generic_confirm(hw_priv, wsm_arg, &wsm_buf);
2908 if (ret)
2909 wsm_printk(XRADIO_DBG_ERROR,
2910 "wsm_generic_confirm "
2911 "failed for request 0x%.4X ret=%d.\n",
2912 id & ~0x0400, ret);
2913 break;
2914 default:
2915 SYS_BUG(1);
2916 }
2917
2918 spin_lock(&hw_priv->wsm_cmd.lock);
2919 hw_priv->wsm_cmd.ret = ret;
2920 hw_priv->wsm_cmd.done = 1;
2921 spin_unlock(&hw_priv->wsm_cmd.lock);
2922 ret = 0; /* Error response from device should ne stop BH. */
2923
2924 wake_up(&hw_priv->wsm_cmd_wq);
2925 } else if (id & 0x0800) {
2926 switch (id) {
2927 case 0x0801:
2928 ret = wsm_startup_indication(hw_priv, &wsm_buf);
2929 break;
2930 case 0x0804:
2931 if (xradio_realloc_resv_skb(hw_priv, *skb_p, flags)) {
2932 /* we reuse this skb, because fail to realloc.*/
2933 wsm_printk(XRADIO_DBG_WARN,
2934 "xradio_realloc_resv_skb drop frames, len=%d.\n",
2935 (*skb_p)->len);
2936 *skb_p = NULL;
2937 ret = 0;
2938 goto out;
2939 }
2940 /*
2941 * if packet len < total length - piggy back length
2942 * then multi receive indication.
2943 */
2944 PERF_INFO_GETTIME(&ind_rx_time);
2945 if (ROUND4(__le32_to_cpu(wsm->len)) < total_len) {
2946 ret = wsm_multi_receive_indication(hw_priv, total_len,
2947 &wsm_buf, skb_p);
2948 } else {
2949 if (__le32_to_cpu(wsm->len) != total_len)
2950 wsm_printk(XRADIO_DBG_WARN,
2951 "wsm->len=%u, total_len=%zu",
2952 __le32_to_cpu(wsm->len), total_len);
2953 ret = wsm_receive_indication(hw_priv, interface_link_id,
2954 &wsm_buf, skb_p);
2955 }
2956 PERF_INFO_STAMP(&ind_rx_time, &ind_rx, total_len);
2957 break;
2958 case 0x0805:
2959 ret = wsm_event_indication(hw_priv, &wsm_buf,
2960 interface_link_id);
2961 break;
2962 case 0x0807:
2963 wsm_printk(XRADIO_DBG_ERROR, "[11K]wsm_measure_cmpl_indication\n");
2964 ret = wsm_measure_cmpl_indication(hw_priv, &wsm_buf);
2965 break;
2966 case 0x080A:
2967 ret = wsm_channel_switch_indication(hw_priv, &wsm_buf);
2968 break;
2969 case 0x0809:
2970 ret = wsm_set_pm_indication(hw_priv, &wsm_buf);
2971 break;
2972 case 0x0806:
2973 #ifdef ROAM_OFFLOAD
2974 if (hw_priv->auto_scanning && hw_priv->frame_rcvd) {
2975 struct xradio_vif *priv;
2976 hw_priv->frame_rcvd = 0;
2977 priv = xrwl_hwpriv_to_vifpriv(hw_priv, hw_priv->scan.if_id);
2978 if (unlikely(!priv)) {
2979 SYS_WARN(1);
2980 return 0;
2981 }
2982 spin_unlock(&priv->vif_lock);
2983 if (hw_priv->beacon) {
2984 struct wsm_scan_complete *scan_cmpl = \
2985 (struct wsm_scan_complete *) \
2986 ((u8 *)wsm + sizeof(struct wsm_hdr));
2987 struct ieee80211_rx_status *rhdr = \
2988 IEEE80211_SKB_RXCB(hw_priv->beacon);
2989 rhdr->signal = (s8)scan_cmpl->reserved;
2990 if (!priv->cqm_use_rssi) {
2991 rhdr->signal = rhdr->signal / 2 - 110;
2992 }
2993 if (!hw_priv->beacon_bkp)
2994 hw_priv->beacon_bkp = \
2995 skb_copy(hw_priv->beacon, GFP_ATOMIC);
2996 mac80211_rx_irqsafe(hw_priv->hw, hw_priv->beacon);
2997 hw_priv->beacon = hw_priv->beacon_bkp;
2998
2999 hw_priv->beacon_bkp = NULL;
3000 }
3001 wsm_printk(XRADIO_DBG_MSG, \
3002 "Send Testmode Event.\n");
3003 xradio_testmode_event(priv->hw->wiphy,
3004 NL80211_CMD_NEW_SCAN_RESULTS, 0,
3005 0, GFP_KERNEL);
3006
3007 }
3008 #endif /*ROAM_OFFLOAD*/
3009 ret = wsm_scan_complete_indication(hw_priv, &wsm_buf);
3010 break;
3011 case 0x080B:
3012 ret = wsm_find_complete_indication(hw_priv, &wsm_buf);
3013 break;
3014 case 0x080C:
3015 ret = wsm_suspend_resume_indication(hw_priv,
3016 interface_link_id, &wsm_buf);
3017 break;
3018 case 0x080E:
3019 wsm_printk(XRADIO_DBG_MSG, "wsm_debug_indication");
3020 ret = wsm_debug_indication(hw_priv, &wsm_buf);
3021 break;
3022
3023 case 0x0825:
3024 ret = wsm_fw_dbg_indicate(hw_priv, &wsm_buf);
3025
3026 if (ret)
3027 wsm_printk(XRADIO_DBG_ERROR,
3028 "[0x%04x] ret(%d): indicate Error, msg_len:%d\n",
3029 id, ret, wsm->len);
3030 break;
3031
3032 default:
3033 wsm_printk(XRADIO_DBG_ERROR, "unknown Indmsg ID=0x%04x, len=%d\n",
3034 wsm->id, wsm->len);
3035 break;
3036 }
3037 } else {
3038 SYS_WARN(1);
3039 ret = -EINVAL;
3040 }
3041 out:
3042 return ret;
3043 }
3044
wsm_handle_tx_data(struct xradio_vif * priv,const struct wsm_tx * wsm,const struct ieee80211_tx_info * tx_info,struct xradio_txpriv * txpriv,struct xradio_queue * queue)3045 static bool wsm_handle_tx_data(struct xradio_vif *priv,
3046 const struct wsm_tx *wsm,
3047 const struct ieee80211_tx_info *tx_info,
3048 struct xradio_txpriv *txpriv,
3049 struct xradio_queue *queue)
3050 {
3051 struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
3052 #ifdef P2P_MULTIVIF
3053 struct xradio_vif *p2p_if_vif = NULL;
3054 #endif
3055 bool handled = false;
3056 const struct ieee80211_hdr *frame =
3057 (struct ieee80211_hdr *) &((u8 *)wsm)[txpriv->offset];
3058 __le16 fctl = frame->frame_control;
3059 enum {
3060 doProbe,
3061 doDrop,
3062 doJoin,
3063 doOffchannel,
3064 doWep,
3065 doTx,
3066 } action = doTx;
3067
3068 hw_priv = xrwl_vifpriv_to_hwpriv(priv);
3069 #ifdef P2P_MULTIVIF
3070 if (priv->if_id == XRWL_GENERIC_IF_ID)
3071 p2p_if_vif = __xrwl_hwpriv_to_vifpriv(hw_priv, 1);
3072 #endif
3073 frame = (struct ieee80211_hdr *) &((u8 *)wsm)[txpriv->offset];
3074 fctl = frame->frame_control;
3075
3076 switch (priv->mode) {
3077 case NL80211_IFTYPE_STATION:
3078 case NL80211_IFTYPE_P2P_DEVICE:
3079 if (unlikely(priv->bss_loss_status == XRADIO_BSS_LOSS_CHECKING &&
3080 priv->join_status == XRADIO_JOIN_STATUS_STA) &&
3081 ieee80211_is_data(fctl)) {
3082 spin_lock(&priv->bss_loss_lock);
3083 priv->bss_loss_confirm_id = wsm->packetID;
3084 priv->bss_loss_status = XRADIO_BSS_LOSS_CONFIRMING;
3085 spin_unlock(&priv->bss_loss_lock);
3086 } else if (unlikely((priv->join_status <= XRADIO_JOIN_STATUS_MONITOR)
3087 || memcmp(frame->addr1, priv->join_bssid,
3088 sizeof(priv->join_bssid)))) {
3089 #ifdef P2P_MULTIVIF
3090 if (p2p_if_vif &&
3091 (p2p_if_vif->join_status > XRADIO_JOIN_STATUS_MONITOR) &&
3092 (priv->join_status < XRADIO_JOIN_STATUS_MONITOR)) {
3093
3094 /* Post group formation, frame transmission on p2p0
3095 * interafce should not use offchannel/generic channel.
3096 * Instead, the frame should be transmitted on interafce
3097 * 1. This is needed by wsc fw.
3098 */
3099 action = doTx;
3100 txpriv->raw_if_id = 1;
3101 } else
3102 #endif
3103 if (ieee80211_is_auth(fctl))
3104 action = doJoin;
3105 else if ((ieee80211_is_deauth(fctl) ||
3106 ieee80211_is_disassoc(fctl)) &&
3107 priv->join_status < XRADIO_JOIN_STATUS_MONITOR)
3108 /* no need to send deauth when STA-unjoined.*/
3109 action = doDrop;
3110 else if (ieee80211_is_probe_req(fctl))
3111 action = doTx;
3112 else if (memcmp(frame->addr1, priv->join_bssid,
3113 sizeof(priv->join_bssid)) &&
3114 (priv->join_status ==
3115 XRADIO_JOIN_STATUS_STA) &&
3116 (ieee80211_is_data(fctl))) {
3117 action = doDrop;
3118 } else if (priv->join_status >=
3119 XRADIO_JOIN_STATUS_MONITOR)
3120 action = doTx;
3121 else if (get_interface_id_scanning(hw_priv) != -1) {
3122 wsm_printk(XRADIO_DBG_WARN, "Scan ONGOING dropping"
3123 " offchannel eligible frame.\n");
3124 action = doDrop;
3125 } else {
3126 action = doOffchannel;
3127 wsm_printk(XRADIO_DBG_WARN, "Offchannel fctl=0x%04x", fctl);
3128 }
3129 }
3130 break;
3131 case NL80211_IFTYPE_AP:
3132 if (unlikely(!priv->join_status))
3133 action = doDrop;
3134 else if (unlikely(!(BIT(txpriv->raw_link_id) &
3135 (BIT(0) | priv->link_id_map)))) {
3136 wsm_printk(XRADIO_DBG_WARN,
3137 "A frame with expired link id "
3138 "is dropped.\n");
3139 action = doDrop;
3140 }
3141 if (xradio_queue_get_generation(wsm->packetID) >
3142 XRADIO_MAX_REQUEUE_ATTEMPTS) {
3143 /* HACK!!! WSM324 firmware has tendency to requeue
3144 * multicast frames in a loop, causing performance
3145 * drop and high power consumption of the driver.
3146 * In this situation it is better just to drop
3147 * the problematic frame. */
3148 wsm_printk(XRADIO_DBG_WARN,
3149 "Too many attempts "
3150 "to requeue a frame. "
3151 "Frame is dropped, fctl=0x%04x.\n", fctl);
3152 action = doDrop;
3153 }
3154 break;
3155 case NL80211_IFTYPE_ADHOC:
3156 case NL80211_IFTYPE_MESH_POINT:
3157 /*STUB();*/
3158 case NL80211_IFTYPE_MONITOR:
3159 default:
3160 action = doDrop;
3161 break;
3162 }
3163
3164 if (action == doTx) {
3165 if (unlikely(ieee80211_is_probe_req(fctl))) {
3166 #ifdef CONFIG_XRADIO_TESTMODE
3167 if (hw_priv->enable_advance_scan &&
3168 (priv->join_status == XRADIO_JOIN_STATUS_STA) &&
3169 (hw_priv->advanceScanElems.scanMode ==
3170 XRADIO_SCAN_MEASUREMENT_ACTIVE))
3171 /* If Advance Scan is Requested on Active Scan
3172 * then transmit the Probe Request */
3173 action = doTx;
3174 else
3175 #endif
3176 action = doProbe;
3177 } else if ((fctl & __cpu_to_le32(IEEE80211_FCTL_PROTECTED)) &&
3178 tx_info->control.hw_key &&
3179 unlikely(tx_info->control.hw_key->keyidx !=
3180 priv->wep_default_key_id) &&
3181 (tx_info->control.hw_key->cipher ==
3182 WLAN_CIPHER_SUITE_WEP40 ||
3183 tx_info->control.hw_key->cipher ==
3184 WLAN_CIPHER_SUITE_WEP104)) {
3185 action = doWep;
3186 }
3187 }
3188
3189 switch (action) {
3190 case doProbe:
3191 {
3192 /* An interesting FW "feature". Device filters
3193 * probe responses.
3194 * The easiest way to get it back is to convert
3195 * probe request into WSM start_scan command. */
3196 wsm_printk(XRADIO_DBG_MSG, \
3197 "Convert probe request to scan.\n");
3198 wsm_lock_tx_async(hw_priv);
3199 hw_priv->pending_frame_id = __le32_to_cpu(wsm->packetID);
3200 queue_delayed_work(hw_priv->workqueue,
3201 &hw_priv->scan.probe_work, 0);
3202 handled = true;
3203 }
3204 break;
3205 case doDrop:
3206 {
3207 /* See detailed description of "join" below.
3208 * We are dropping everything except AUTH in non-joined mode. */
3209 wsm_printk(XRADIO_DBG_MSG, "Drop frame (0x%.4X).\n", fctl);
3210 #ifdef CONFIG_XRADIO_TESTMODE
3211 SYS_BUG(xradio_queue_remove(hw_priv, queue,
3212 __le32_to_cpu(wsm->packetID)));
3213 #else
3214 SYS_BUG(xradio_queue_remove(queue,
3215 __le32_to_cpu(wsm->packetID)));
3216 #endif /*CONFIG_XRADIO_TESTMODE*/
3217 handled = true;
3218 }
3219 break;
3220 case doJoin:
3221 {
3222 /* p2p should disconnect when sta try to join a different channel AP,
3223 * because no good performance in this case.
3224 */
3225 struct xradio_vif *p2p_tmp_vif = __xrwl_hwpriv_to_vifpriv(hw_priv, 1);
3226 if (priv->if_id == 0 && p2p_tmp_vif) {
3227 if (p2p_tmp_vif->join_status >= XRADIO_JOIN_STATUS_STA &&
3228 hw_priv->channel_changed) {
3229 wsm_printk(XRADIO_DBG_WARN,
3230 "combo with different channels, p2p disconnect.\n");
3231 wsm_send_disassoc_to_self(hw_priv, p2p_tmp_vif);
3232 }
3233 }
3234
3235 /* There is one more interesting "feature"
3236 * in FW: it can't do RX/TX before "join".
3237 * "Join" here is not an association,
3238 * but just a syncronization between AP and STA.
3239 * priv->join_status is used only in bh thread and does
3240 * not require protection */
3241 wsm_printk(XRADIO_DBG_NIY, "Issue join command.\n");
3242 wsm_lock_tx_async(hw_priv);
3243 hw_priv->pending_frame_id = __le32_to_cpu(wsm->packetID);
3244 if (queue_work(hw_priv->workqueue, &priv->join_work) <= 0)
3245 wsm_unlock_tx(hw_priv);
3246 handled = true;
3247 }
3248 break;
3249 case doOffchannel:
3250 {
3251 wsm_printk(XRADIO_DBG_MSG, "Offchannel TX request.\n");
3252 wsm_lock_tx_async(hw_priv);
3253 hw_priv->pending_frame_id = __le32_to_cpu(wsm->packetID);
3254 if (queue_work(hw_priv->workqueue, &priv->offchannel_work) <= 0)
3255 wsm_unlock_tx(hw_priv);
3256 handled = true;
3257 }
3258 break;
3259 case doWep:
3260 {
3261 wsm_printk(XRADIO_DBG_MSG, "Issue set_default_wep_key.\n");
3262 wsm_lock_tx_async(hw_priv);
3263 priv->wep_default_key_id = tx_info->control.hw_key->keyidx;
3264 hw_priv->pending_frame_id = __le32_to_cpu(wsm->packetID);
3265 if (queue_work(hw_priv->workqueue, &priv->wep_key_work) <= 0)
3266 wsm_unlock_tx(hw_priv);
3267 handled = true;
3268 }
3269 break;
3270 case doTx:
3271 {
3272 #if 0
3273 /* Kept for history. If you want to implement wsm->more,
3274 * make sure you are able to send a frame after that. */
3275 wsm->more = (count > 1) ? 1 : 0;
3276 if (wsm->more) {
3277 /* HACK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3278 * It's undocumented in WSM spec, but XRADIO hangs
3279 * if 'more' is set and no TX is performed due to TX
3280 * buffers limitation. */
3281 if (priv->hw_bufs_used + 1 ==
3282 priv->wsm_caps.numInpChBufs)
3283 wsm->more = 0;
3284 }
3285
3286 /* BUG!!! FIXME: we can't use 'more' at all: we don't know
3287 * future. It could be a request from upper layer with TX lock
3288 * requirements (scan, for example). If "more" is set device
3289 * will not send data and wsm_tx_lock() will fail...
3290 * It's not obvious how to fix this deadlock. Any ideas?
3291 * As a workaround more is set to 0. */
3292 wsm->more = 0;
3293 #endif /* 0 */
3294
3295 if (ieee80211_is_deauth(fctl) &&
3296 priv->mode != NL80211_IFTYPE_AP) {
3297 /* Shedule unjoin work */
3298 wsm_printk(XRADIO_DBG_WARN, "Issue unjoin command(TX).\n");
3299 #if 0
3300 wsm->more = 0;
3301 #endif /* 0 */
3302 queue_delayed_work(hw_priv->workqueue, &priv->unjoin_delayed_work, 1 * HZ);
3303 }
3304 }
3305 break;
3306 }
3307 return handled;
3308 }
3309
xradio_get_prio_queue(struct xradio_vif * priv,u32 link_id_map,int * total)3310 static int xradio_get_prio_queue(struct xradio_vif *priv,
3311 u32 link_id_map, int *total)
3312 {
3313 struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
3314 static u32 urgent;
3315 struct wsm_edca_queue_params *edca;
3316 unsigned score, best = -1;
3317 int winner = -1;
3318 int queued;
3319 int i;
3320 urgent = BIT(priv->link_id_after_dtim) | BIT(priv->link_id_uapsd);
3321
3322 /* search for a winner using edca params */
3323 for (i = 0; i < 4; ++i) {
3324 queued = xradio_queue_get_num_queued(priv,
3325 &hw_priv->tx_queue[i],
3326 link_id_map);
3327 if (!queued)
3328 continue;
3329 *total += queued;
3330 edca = &priv->edca.params[i];
3331 score = ((edca->aifns + edca->cwMin) << 16) +
3332 (edca->cwMax - edca->cwMin) *
3333 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
3334 (random32() & 0xFFFF);
3335 #else
3336 (get_random_int() & 0xFFFF);
3337 #endif
3338 if (score < best && (winner < 0 || i != 3)) {
3339 best = score;
3340 winner = i;
3341 }
3342 }
3343
3344 /* override winner if bursting */
3345 if (winner >= 0 && hw_priv->tx_burst_idx >= 0 &&
3346 winner != hw_priv->tx_burst_idx &&
3347 !xradio_queue_get_num_queued(priv,
3348 &hw_priv->tx_queue[winner],
3349 link_id_map & urgent) &&
3350 xradio_queue_get_num_queued(priv,
3351 &hw_priv->tx_queue[hw_priv->tx_burst_idx],
3352 link_id_map))
3353 winner = hw_priv->tx_burst_idx;
3354
3355 return winner;
3356 }
3357
wsm_get_tx_queue_and_mask(struct xradio_vif * priv,struct xradio_queue ** queue_p,u32 * tx_allowed_mask_p,bool * more)3358 static int wsm_get_tx_queue_and_mask(struct xradio_vif *priv,
3359 struct xradio_queue **queue_p,
3360 u32 *tx_allowed_mask_p,
3361 bool *more)
3362 {
3363 struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
3364 int idx;
3365 u32 tx_allowed_mask;
3366 int total = 0;
3367
3368 /* Search for a queue with multicast frames buffered */
3369 if (priv->tx_multicast) {
3370 tx_allowed_mask = BIT(priv->link_id_after_dtim);
3371 idx = xradio_get_prio_queue(priv,
3372 tx_allowed_mask, &total);
3373 if (idx >= 0) {
3374 *more = total > 1;
3375 goto found;
3376 }
3377 }
3378
3379 /* Search for unicast traffic */
3380 tx_allowed_mask = ~priv->sta_asleep_mask;
3381 tx_allowed_mask |= BIT(priv->link_id_uapsd);
3382 if (priv->sta_asleep_mask) {
3383 tx_allowed_mask |= priv->pspoll_mask;
3384 tx_allowed_mask &= ~BIT(priv->link_id_after_dtim);
3385 } else {
3386 tx_allowed_mask |= BIT(priv->link_id_after_dtim);
3387 }
3388 idx = xradio_get_prio_queue(priv,
3389 tx_allowed_mask, &total);
3390 if (idx < 0)
3391 return -ENOENT;
3392
3393 found:
3394 *queue_p = &hw_priv->tx_queue[idx];
3395 *tx_allowed_mask_p = tx_allowed_mask;
3396 return 0;
3397 }
3398
wsm_get_tx(struct xradio_common * hw_priv,u8 ** data,size_t * tx_len,int * burst,int * vif_selected)3399 int wsm_get_tx(struct xradio_common *hw_priv, u8 **data,
3400 size_t *tx_len, int *burst, int *vif_selected)
3401 {
3402 struct wsm_tx *wsm = NULL;
3403 struct ieee80211_tx_info *tx_info;
3404 struct xradio_queue *queue = NULL;
3405 int queue_num;
3406 u32 tx_allowed_mask = 0;
3407 struct xradio_txpriv *txpriv = NULL;
3408 #ifdef P2P_MULTIVIF
3409 int first = 1;
3410 int tmp_if_id = -1;
3411 #endif
3412 #if BH_PROC_TX
3413 u8 *tx_item = NULL;
3414 #endif
3415 /*
3416 * Count was intended as an input for wsm->more flag.
3417 * During implementation it was found that wsm->more
3418 * is not usable, see details above. It is kept just
3419 * in case you would like to try to implement it again.
3420 */
3421 int count = 0;
3422 #ifdef P2P_MULTIVIF
3423 int if_pending = XRWL_MAX_VIFS - 1;
3424 #else
3425 int if_pending = 1;
3426 #endif
3427
3428 /* More is used only for broadcasts. */
3429 bool more = false;
3430
3431 count = xradio_itp_get_tx(hw_priv, data, tx_len, burst);
3432 if (count)
3433 return count;
3434 #if !BH_PROC_TX
3435 if (hw_priv->wsm_cmd.ptr) {
3436 ++count;
3437 spin_lock(&hw_priv->wsm_cmd.lock);
3438 SYS_BUG(!hw_priv->wsm_cmd.ptr);
3439 *data = hw_priv->wsm_cmd.ptr;
3440 *tx_len = hw_priv->wsm_cmd.len;
3441 *burst = 1;
3442 *vif_selected = -1;
3443 spin_unlock(&hw_priv->wsm_cmd.lock);
3444 } else {
3445 #endif
3446 for (;;) {
3447 int ret;
3448 struct xradio_vif *priv;
3449 #if 0
3450 int num_pending_vif0, num_pending_vif1;
3451 #endif
3452 if (atomic_add_return(0, &hw_priv->tx_lock)) {
3453 wsm_printk(XRADIO_DBG_NIY, "%s:tx_lock!", __func__);
3454 break;
3455 }
3456 if (xradio_is_bt_block(hw_priv)) {
3457 wsm_printk(XRADIO_DBG_NIY,
3458 "%s:BT is busy, lock tx!", __func__);
3459 break;
3460 }
3461 /* Keep one buffer reserved for commands. Note
3462 that, hw_bufs_used has already been incremented
3463 before reaching here. */
3464 if (hw_priv->hw_bufs_used >=
3465 hw_priv->wsm_caps.numInpChBufs) {
3466 DBG_INT_ADD(tx_buf_limit);
3467 break;
3468 }
3469 #ifdef P2P_MULTIVIF
3470 if (first) {
3471 tmp_if_id = hw_priv->if_id_selected;
3472 hw_priv->if_id_selected = 2;
3473 }
3474 #endif
3475 priv = wsm_get_interface_for_tx(hw_priv);
3476 /* go to next interface ID to select next packet */
3477 #ifdef P2P_MULTIVIF
3478 if (first) {
3479 hw_priv->if_id_selected = tmp_if_id;
3480 first = 0;
3481 } else
3482 #endif
3483 hw_priv->if_id_selected ^= 1;
3484
3485 /* There might be no interface before add_interface
3486 * call */
3487 if (!priv) {
3488 if (if_pending) {
3489 #ifdef P2P_MULTIVIF
3490 if_pending--;
3491 #else
3492 if_pending = 0;
3493 #endif
3494 continue;
3495 }
3496 break;
3497 }
3498
3499 #if 0
3500 if (((priv->if_id == 0) &&
3501 (hw_priv->hw_bufs_used_vif[0] >=
3502 XRWL_FW_VIF0_THROTTLE)) ||
3503 ((priv->if_id == 1) &&
3504 (hw_priv->hw_bufs_used_vif[1] >=
3505 XRWL_FW_VIF1_THROTTLE))) {
3506 spin_unlock(&priv->vif_lock);
3507 if (if_pending) {
3508 if_pending = 0;
3509 continue;
3510 }
3511 break;
3512 }
3513 #endif
3514
3515 /* This can be removed probably: xradio_vif will not
3516 * be in hw_priv->vif_list (as returned from
3517 * wsm_get_interface_for_tx) until it's fully
3518 * enabled, so statement above will take case of that*/
3519 if (!atomic_read(&priv->enabled)) {
3520 spin_unlock(&priv->vif_lock);
3521 break;
3522 }
3523
3524 /* TODO:COMBO: Find the next interface for which
3525 * packet needs to be found */
3526 spin_lock_bh(&priv->ps_state_lock);
3527 ret = wsm_get_tx_queue_and_mask(priv, &queue,
3528 &tx_allowed_mask, &more);
3529 queue_num = queue - hw_priv->tx_queue;
3530
3531 if (priv->buffered_multicasts &&
3532 (ret || !more) &&
3533 (priv->tx_multicast ||
3534 !priv->sta_asleep_mask)) {
3535 priv->buffered_multicasts = false;
3536 if (priv->tx_multicast) {
3537 priv->tx_multicast = false;
3538 queue_work(hw_priv->workqueue,
3539 &priv->multicast_stop_work);
3540 }
3541 }
3542
3543 spin_unlock_bh(&priv->ps_state_lock);
3544
3545 if (ret) {
3546 spin_unlock(&priv->vif_lock);
3547 #ifdef P2P_MULTIVIF
3548 if (if_pending) {
3549 #else
3550 if (if_pending == 1) {
3551 #endif
3552 #ifdef P2P_MULTIVIF
3553 if_pending--;
3554 #else
3555 if_pending = 0;
3556 #endif
3557 continue;
3558 }
3559 break;
3560 }
3561 #if BH_PROC_TX
3562 if (xradio_queue_get(queue,
3563 priv->if_id,
3564 tx_allowed_mask,
3565 &wsm, &tx_info, &txpriv, &tx_item)) {
3566 spin_unlock(&priv->vif_lock);
3567 if_pending = 0;
3568 continue;
3569 }
3570 #else
3571 if (xradio_queue_get(queue,
3572 priv->if_id,
3573 tx_allowed_mask,
3574 &wsm, &tx_info, &txpriv)) {
3575 wsm_printk(XRADIO_DBG_WARN, "%s, if_id=%d(enable=%d), tx_allowed_mask=%08x, " \
3576 "queue_num=%d, queued_item=%d, pending_item=%d" \
3577 "link_id_after_dtim=%d, link_id_uapsd=%d, tx_multicast=%d, " \
3578 "pspoll_mask=%d, sta_asleep_mask=%d\n",
3579 __func__, priv->if_id, atomic_read(&priv->enabled),
3580 tx_allowed_mask, queue_num, queue->num_queued, queue->num_pending,
3581 priv->link_id_after_dtim, priv->link_id_uapsd,
3582 priv->tx_multicast, priv->pspoll_mask, priv->sta_asleep_mask);
3583 spin_unlock(&priv->vif_lock);
3584 if_pending = 0;
3585 continue;
3586 }
3587 #endif
3588
3589 #ifdef ROC_DEBUG
3590 #ifndef P2P_MULTIVIF
3591 {
3592 struct ieee80211_hdr *hdr =
3593 (struct ieee80211_hdr *)
3594 &((u8 *)wsm)[txpriv->offset];
3595
3596 wsm_printk(XRADIO_DBG_ERROR, "QGET-1 %x, off_id %d, "
3597 " if_id %d\n",
3598 hdr->frame_control,
3599 txpriv->offchannel_if_id,
3600 priv->if_id);
3601 }
3602 #else
3603 {
3604 struct ieee80211_hdr *hdr =
3605 (struct ieee80211_hdr *)
3606 &((u8 *)wsm)[txpriv->offset];
3607
3608 wsm_printk(XRADIO_DBG_ERROR, "QGET-1 %x, off_id %d, "
3609 " if_id %d\n",
3610 hdr->frame_control,
3611 txpriv->raw_if_id,
3612 priv->if_id);
3613 }
3614 #endif
3615 #endif
3616
3617 if (wsm_handle_tx_data(priv, wsm,
3618 tx_info, txpriv, queue)) {
3619 spin_unlock(&priv->vif_lock);
3620 if_pending = 0;
3621 continue; /* Handled by WSM */
3622 }
3623
3624 wsm->hdr.id &= __cpu_to_le16(
3625 ~WSM_TX_IF_ID(WSM_TX_IF_ID_MAX));
3626 #ifdef P2P_MULTIVIF
3627 if (txpriv->raw_if_id)
3628 wsm->hdr.id |= cpu_to_le16(
3629 WSM_TX_IF_ID(txpriv->raw_if_id));
3630 #else
3631 if (txpriv->offchannel_if_id)
3632 wsm->hdr.id |= cpu_to_le16(
3633 WSM_TX_IF_ID(txpriv->offchannel_if_id));
3634 #endif
3635 else
3636 wsm->hdr.id |= cpu_to_le16(
3637 WSM_TX_IF_ID(priv->if_id));
3638
3639 *vif_selected = priv->if_id;
3640 #ifdef ROC_DEBUG
3641 #ifndef P2P_MULTIVIF
3642
3643 {
3644 struct ieee80211_hdr *hdr =
3645 (struct ieee80211_hdr *)
3646 &((u8 *)wsm)[txpriv->offset];
3647
3648 wsm_printk(XRADIO_DBG_ERROR, "QGET-2 %x, off_id %d, "
3649 " if_id %d\n",
3650 hdr->frame_control,
3651 txpriv->offchannel_if_id,
3652 priv->if_id);
3653 }
3654 #else
3655 {
3656 struct ieee80211_hdr *hdr =
3657 (struct ieee80211_hdr *)
3658 &((u8 *)wsm)[txpriv->offset];
3659
3660 wsm_printk(XRADIO_DBG_ERROR, "QGET-2 %x, off_id %d, "
3661 " if_id %d\n",
3662 hdr->frame_control,
3663 txpriv->raw_if_id,
3664 priv->if_id);
3665 }
3666 #endif
3667 #endif
3668
3669 priv->pspoll_mask &= ~BIT(txpriv->raw_link_id);
3670
3671 #if BH_PROC_TX
3672 *data = tx_item;
3673 #else
3674 *data = (u8 *)wsm;
3675 #endif
3676 *tx_len = __le16_to_cpu(wsm->hdr.len);
3677
3678 /* allow bursting if txop is set */
3679 if (priv->edca.params[queue_num].txOpLimit)
3680 *burst = min(*burst,
3681 (int)xradio_queue_get_num_queued(priv,
3682 queue, tx_allowed_mask) + 1);
3683 else
3684 *burst = 1;
3685
3686 /* store index of bursting queue */
3687 if (*burst > 1)
3688 hw_priv->tx_burst_idx = queue_num;
3689 else
3690 hw_priv->tx_burst_idx = -1;
3691
3692 if (more) {
3693 struct ieee80211_hdr *hdr =
3694 (struct ieee80211_hdr *)
3695 &((u8 *)wsm)[txpriv->offset];
3696 if (strstr(&priv->ssid[0], "6.1.12")) {
3697 if (hdr->addr1[0] & 0x01) {
3698 hdr->frame_control |=
3699 cpu_to_le16(IEEE80211_FCTL_MOREDATA);
3700 }
3701 } else {
3702 /* more buffered multicast/broadcast frames
3703 * ==> set MoreData flag in IEEE 802.11 header
3704 * to inform PS STAs */
3705 hdr->frame_control |=
3706 cpu_to_le16(IEEE80211_FCTL_MOREDATA);
3707 }
3708 }
3709 wsm_printk(XRADIO_DBG_MSG, ">>> 0x%.4X (%zu) %p %c\n",
3710 0x0004, *tx_len, wsm,
3711 wsm->more ? 'M' : ' ');
3712 ++count;
3713 spin_unlock(&priv->vif_lock);
3714 break;
3715 }
3716 #if !BH_PROC_TX
3717 }
3718 #endif
3719
3720 return count;
3721 }
3722
3723 void wsm_txed(struct xradio_common *hw_priv, u8 *data)
3724 {
3725 if (data == hw_priv->wsm_cmd.ptr) {
3726 spin_lock(&hw_priv->wsm_cmd.lock);
3727 hw_priv->wsm_cmd.ptr = NULL;
3728 spin_unlock(&hw_priv->wsm_cmd.lock);
3729 }
3730 }
3731
3732 /* ******************************************************************** */
3733 /* WSM buffer */
3734
3735 void wsm_buf_init(struct wsm_buf *buf, int size)
3736 {
3737 SYS_BUG(buf->begin);
3738 buf->begin = xr_kmalloc(size, true);
3739 buf->end = buf->begin ? &buf->begin[size] : buf->begin;
3740 wsm_buf_reset(buf);
3741 }
3742
3743 void wsm_buf_deinit(struct wsm_buf *buf)
3744 {
3745 if (likely(buf->begin))
3746 kfree(buf->begin);
3747 buf->begin = buf->data = buf->end = NULL;
3748 }
3749
3750 static void wsm_buf_reset(struct wsm_buf *buf)
3751 {
3752 if (likely(buf->begin)) {
3753 buf->data = &buf->begin[4];
3754 *(u32 *)buf->begin = 0;
3755 } else
3756 buf->data = buf->begin;
3757 }
3758
3759 static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size)
3760 {
3761 size_t pos = buf->data - buf->begin;
3762 size_t size = pos + extra_size;
3763
3764 size = xr_sdio_blksize_align(size);
3765 buf->begin = xr_krealloc(buf->begin, size, true);
3766 if (buf->begin) {
3767 buf->data = &buf->begin[pos];
3768 buf->end = &buf->begin[size];
3769 return 0;
3770 } else {
3771 buf->end = buf->data = buf->begin;
3772 return -ENOMEM;
3773 }
3774 }
3775
3776 static struct xradio_vif *
3777 wsm_get_interface_for_tx(struct xradio_common *hw_priv)
3778 {
3779 struct xradio_vif *priv = NULL, *i_priv;
3780 int i = hw_priv->if_id_selected;
3781
3782 if (1) { /*TODO:COMBO*/
3783 spin_lock(&hw_priv->vif_list_lock);
3784 i_priv = hw_priv->vif_list[i] ?
3785 xrwl_get_vif_from_ieee80211(hw_priv->vif_list[i]) : NULL;
3786 if (i_priv && atomic_read(&i_priv->enabled)) {
3787 priv = i_priv;
3788 spin_lock(&priv->vif_lock);
3789 }
3790 /* TODO:COMBO:
3791 * Find next interface based on TX bitmap announced by the FW
3792 * Find next interface based on load balancing */
3793 spin_unlock(&hw_priv->vif_list_lock);
3794 } else {
3795 priv = xrwl_hwpriv_to_vifpriv(hw_priv, 0);
3796 }
3797
3798 return priv;
3799 }
3800
3801 static inline int get_interface_id_scanning(struct xradio_common *hw_priv)
3802 {
3803 if (hw_priv->scan.req || hw_priv->scan.direct_probe)
3804 return hw_priv->scan.if_id;
3805 else
3806 return -1;
3807 }
3808