• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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