• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ETF 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 #ifndef XRADIO_ETF_C
13 #define XRADIO_ETF_C
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/vmalloc.h>
17 #include <linux/netlink.h>
18 #include <net/sock.h>
19 #include <linux/kthread.h>
20 #include <linux/wait.h>
21 #include <linux/firmware.h>
22 #include <uapi/linux/sched/types.h>
23 
24 
25 #include "etf.h"
26 #include "xradio.h"
27 #include "sbus.h"
28 #include "debug.h"
29 
30 /********************* interfaces of adapter layer **********************/
31 static struct xradio_adapter adapter_priv;
32 
33 #if (ETF_QUEUEMODE)
adapter_rec_handler(struct sk_buff * __skb)34 static void adapter_rec_handler(struct sk_buff *__skb)
35 {
36 	int i = 0;
37 	struct adapter_item *item;
38 	etf_printk(XRADIO_DBG_TRC, "%s\n", __func__);
39 
40 	do {
41 		spin_lock_bh(&adapter_priv.recv_lock);
42 		if (likely(!list_empty(&adapter_priv.rx_pool))) {
43 			item = list_first_entry(&adapter_priv.rx_pool, struct adapter_item, head);
44 			item->skb = (void *)skb_get(__skb);
45 			list_move_tail(&item->head, &adapter_priv.rx_queue);
46 			spin_unlock_bh(&adapter_priv.recv_lock);
47 			etf_printk(XRADIO_DBG_NIY, "%s recv msg to rx_queue!\n", __func__);
48 			break;
49 		} else if (++i > ETF_QUEUE_TIMEOUT) { /* about 2s.*/
50 			spin_unlock_bh(&adapter_priv.recv_lock);
51 			etf_printk(XRADIO_DBG_ERROR,
52 				"%s driver is process timeout, drop msg!\n", __func__);
53 			return;
54 		} else {
55 			etf_printk(XRADIO_DBG_NIY,
56 				"%s rx_pool is empty, wait %d!ms\n", __func__, i);
57 		}
58 		spin_unlock_bh(&adapter_priv.recv_lock);
59 		msleep(i);
60 	} while (1);
61 
62 	if (atomic_add_return(1, &adapter_priv.rx_cnt) == 1)
63 		up(&adapter_priv.proc_sem);
64 	return;
65 }
66 #else
adapter_rec_handler(struct sk_buff * skb)67 static void adapter_rec_handler(struct sk_buff *skb)
68 {
69 	struct nlmsghdr *nlhdr = (struct nlmsghdr *)skb->data;
70 	etf_printk(XRADIO_DBG_TRC, "%s\n", __func__);
71 
72 	if (nlhdr->nlmsg_len < sizeof(struct nlmsghdr)) {
73 		etf_printk(XRADIO_DBG_ERROR, "Corrupt netlink msg!\n");
74 	} else {
75 		int len = nlhdr->nlmsg_len - NLMSG_LENGTH(0);
76 		adapter_priv.send_pid = nlhdr->nlmsg_pid;
77 		adapter_priv.msg_len  = min(ADAPTER_RX_BUF_LEN, len);
78 		memcpy(adapter_priv.msg_buf, NLMSG_DATA(nlhdr), adapter_priv.msg_len);
79 		if (len != adapter_priv.msg_len)
80 			etf_printk(XRADIO_DBG_WARN, "%s recv len(%d), proc len=%d!\n",
81 					__func__, len, adapter_priv.msg_len);
82 		else
83 			etf_printk(XRADIO_DBG_NIY, "%s recv msg len(%d)!\n",
84 					__func__, adapter_priv.msg_len);
85 		if (adapter_priv.handler)
86 			adapter_priv.handler(adapter_priv.msg_buf, adapter_priv.msg_len);
87 
88 	}
89 }
90 #endif
91 
adapter_init_msgbuf(void)92 static int adapter_init_msgbuf(void)
93 {
94 #if (ETF_QUEUEMODE)
95 	int i = 0;
96 #endif
97 	etf_printk(XRADIO_DBG_NIY, "%s\n", __func__);
98 	if (adapter_priv.msg_buf) {
99 		etf_printk(XRADIO_DBG_ERROR, "%s msgbuf already init!\n", __func__);
100 		return -1;
101 	}
102 
103 #if (ETF_QUEUEMODE)
104 	atomic_set(&adapter_priv.rx_cnt, 0);
105 	INIT_LIST_HEAD(&adapter_priv.rx_queue);
106 	INIT_LIST_HEAD(&adapter_priv.rx_pool);
107 	for (i = 0; i < ADAPTER_ITEM_MAX; i++)
108 		list_add_tail(&adapter_priv.rx_items[i].head, &adapter_priv.rx_pool);
109 #endif
110 
111 	adapter_priv.msg_buf  = xr_kzalloc(ADAPTER_RX_BUF_LEN, false);
112 	if (!adapter_priv.msg_buf)
113 		return -ENOMEM;
114 	return 0;
115 }
116 
adapter_deinit_msgbuf(void)117 static void adapter_deinit_msgbuf(void)
118 {
119 #if (ETF_QUEUEMODE)
120 	struct  adapter_item *item;
121 #endif
122 	etf_printk(XRADIO_DBG_NIY, "%s\n", __func__);
123 	if (adapter_priv.msg_buf) {
124 		kfree(adapter_priv.msg_buf);
125 		adapter_priv.msg_buf = NULL;
126 	}
127 #if (ETF_QUEUEMODE)
128 	spin_lock_bh(&adapter_priv.recv_lock);
129 	list_for_each_entry(item, &adapter_priv.rx_queue, head) {
130 		if (item->skb) {
131 			dev_kfree_skb((struct sk_buff *)item->skb);
132 			item->skb = NULL;
133 		}
134 	}
135 	spin_unlock_bh(&adapter_priv.recv_lock);
136 #endif
137 }
138 
139 #if (ETF_QUEUEMODE)
adapter_handle_rx_queue(void)140 static int adapter_handle_rx_queue(void)
141 {
142 	int len = 0;
143 	struct nlmsghdr *nlhdr = NULL;
144 	struct adapter_item *item;
145 	bool bHandler = false;
146 	while (1) {
147 		spin_lock_bh(&adapter_priv.recv_lock);
148 		if (!list_empty(&adapter_priv.rx_queue)) {
149 			item = list_first_entry(&adapter_priv.rx_queue, struct adapter_item, head);
150 			if (item->skb) {
151 				struct sk_buff *skb = (struct sk_buff *)(item->skb);
152 				nlhdr = (struct nlmsghdr *)skb->data;
153 				if (nlhdr->nlmsg_len < sizeof(struct nlmsghdr)) {
154 					etf_printk(XRADIO_DBG_ERROR, "Corrupt netlink msg!\n");
155 				} else {
156 					len = nlhdr->nlmsg_len - NLMSG_LENGTH(0);
157 					adapter_priv.send_pid = nlhdr->nlmsg_pid;
158 					adapter_priv.msg_len  = min(ADAPTER_RX_BUF_LEN, len);
159 					memcpy(adapter_priv.msg_buf, NLMSG_DATA(nlhdr), len);
160 					bHandler = true;
161 					if (len != adapter_priv.msg_len)
162 						etf_printk(XRADIO_DBG_WARN, "%s recv len(%d), proc len=%d!\n",
163 								__func__, len, adapter_priv.msg_len);
164 					else
165 						etf_printk(XRADIO_DBG_NIY, "%s recv msg len(%d)!\n",
166 								__func__, adapter_priv.msg_len);
167 				}
168 				dev_kfree_skb(skb);
169 				item->skb = NULL;
170 				list_move_tail(&item->head, &adapter_priv.rx_pool);
171 			} else {
172 				etf_printk(XRADIO_DBG_ERROR, "%s skb is NULL!\n", __func__);
173 			}
174 		} else {
175 			spin_unlock_bh(&adapter_priv.recv_lock);
176 			break;
177 		}
178 		spin_unlock_bh(&adapter_priv.recv_lock);
179 		if (bHandler && adapter_priv.handler) {
180 			adapter_priv.handler(adapter_priv.msg_buf, adapter_priv.msg_len);
181 			bHandler = false;
182 		}
183 	}
184 	return 0;
185 }
186 
adapter_proc(void * param)187 static int adapter_proc(void *param)
188 {
189 	int ret  = 0;
190 	int term = 0;
191 	int recv = 0;
192 	etf_printk(XRADIO_DBG_NIY, "%s\n", __func__);
193 	for (;;) {
194 		ret = down_interruptible(&adapter_priv.proc_sem);
195 		recv = atomic_xchg(&adapter_priv.rx_cnt, 0);
196 		term = kthread_should_stop();
197 		etf_printk(XRADIO_DBG_NIY, "%s term=%d!\n", __func__, term);
198 		if (term || adapter_priv.exit || ret < 0) {
199 			break;
200 		}
201 		if (recv) {
202 			adapter_handle_rx_queue();
203 		}
204 	}
205 	etf_printk(XRADIO_DBG_NIY, "%s: exit!\n", __func__);
206 	return 0;
207 }
adapter_start_thread(void)208 static int adapter_start_thread(void)
209 {
210 	int ret = 0;
211 	struct sched_param param = {.sched_priority = 100 };
212 	etf_printk(XRADIO_DBG_NIY, "%s\n", __func__);
213 	adapter_priv.thread_tsk = NULL;
214 	adapter_priv.exit = 0;
215 	adapter_priv.thread_tsk = kthread_create(&adapter_proc, NULL, XRADIO_ADAPTER);
216 	if (IS_ERR(adapter_priv.thread_tsk)) {
217 		ret = PTR_ERR(adapter_priv.thread_tsk);
218 		adapter_priv.thread_tsk = NULL;
219 	} else {
220 		sched_setscheduler(adapter_priv.thread_tsk, SCHED_NORMAL, &param);
221 		wake_up_process(adapter_priv.thread_tsk);
222 	}
223 	return ret;
224 }
adapter_stop_thread(void)225 static void adapter_stop_thread(void)
226 {
227 	etf_printk(XRADIO_DBG_NIY, "%s\n", __func__);
228 	if (adapter_priv.thread_tsk != NULL) {
229 		adapter_priv.exit = 1;
230 		up(&adapter_priv.proc_sem);
231 		kthread_stop(adapter_priv.thread_tsk);
232 		adapter_priv.thread_tsk = NULL;
233 	} else {
234 		etf_printk(XRADIO_DBG_WARN, "%s: thread_tsk is NULL!\n", __func__);
235 	}
236 }
237 #endif /* ETF_QUEUEMODE */
238 
xradio_adapter_send(void * data,int len)239 static int xradio_adapter_send(void *data, int len)
240 {
241 	int ret = 0;
242 	struct sk_buff  *skb = NULL;
243 	struct nlmsghdr *nlhdr = NULL;
244 	u8  *payload  = NULL;
245 	if (0 == len || NULL == data)
246 		return -EINVAL;
247 
248 	skb = xr_alloc_skb(NLMSG_SPACE(len + 1));
249 	if (!skb) {
250 		etf_printk(XRADIO_DBG_WARN, "%s:xr_alloc_skb failed!\n", __func__);
251 		return -ENOMEM;
252 	}
253 	/* '\0' safe for strcpy, compat for old etf apk, may be removed in furture.*/
254 	nlhdr = nlmsg_put(skb, 0, 0, 0, len + 1, 0); /* (len+1) is payload */
255 	payload = (u8 *)NLMSG_DATA(nlhdr);
256 	memcpy(payload, data, len);
257 	payload[len] = '\0';
258 
259 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
260 	NETLINK_CB(skb).pid = 0;
261 #else
262 	NETLINK_CB(skb).portid = 0;
263 #endif
264 	NETLINK_CB(skb).dst_group = 0;
265 
266 	down(&adapter_priv.send_lock);
267 	ret = netlink_unicast(adapter_priv.sock, skb, adapter_priv.send_pid, 0);
268 	if (ret < 0)
269 		etf_printk(XRADIO_DBG_ERROR, "%s:netlink_unicast failed(%d), pid=%d!\n",
270 					__func__, ret, adapter_priv.send_pid);
271 	else
272 		etf_printk(XRADIO_DBG_NIY, "%s:netlink_unicast len(%d), pid=%d!\n",
273 					__func__, ret, adapter_priv.send_pid);
274 	up(&adapter_priv.send_lock);
275 
276 	return ret;
277 }
278 
xradio_adapter_send_pkg(void * data1,int len1,void * data2,int len2)279 static int xradio_adapter_send_pkg(void *data1, int len1, void *data2, int len2)
280 {
281 	int ret = 0;
282 	struct sk_buff  *skb = NULL;
283 	struct nlmsghdr *nlhdr = NULL;
284 	u8  *payload  = NULL;
285 	int total_len = len1 + len2;
286 	if (len1 <= 0 || len2 < 0 || NULL == data1)
287 		return -EINVAL;
288 
289 	skb = xr_alloc_skb(NLMSG_SPACE(total_len + 1));
290 	if (!skb) {
291 		etf_printk(XRADIO_DBG_WARN, "%s:xr_alloc_skb failed!\n", __func__);
292 		return -ENOMEM;
293 	}
294 	/* '\0' safe for strcpy, compat for old etf apk, may be removed in furture.*/
295 	nlhdr = nlmsg_put(skb, 0, 0, 0, total_len + 1, 0);
296 	payload = (u8 *)NLMSG_DATA(nlhdr);
297 	memcpy(payload, data1, len1);
298 	if (data2 && len2)
299 		memcpy((payload + len1), data2, len2);
300 	payload[total_len] = '\0';
301 
302 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
303 	NETLINK_CB(skb).pid = 0;
304 #else
305 	NETLINK_CB(skb).portid = 0;
306 #endif
307 	NETLINK_CB(skb).dst_group = 0;
308 
309 	down(&adapter_priv.send_lock);
310 	ret = netlink_unicast(adapter_priv.sock, skb, adapter_priv.send_pid, 0);
311 	if (ret < 0)
312 		etf_printk(XRADIO_DBG_ERROR, "%s:netlink_unicast failed(%d), pid=%d!\n",
313 					__func__, ret, adapter_priv.send_pid);
314 	else
315 		etf_printk(XRADIO_DBG_NIY, "%s:netlink_unicast len(%d), pid=%d!\n",
316 					__func__, ret, adapter_priv.send_pid);
317 	up(&adapter_priv.send_lock);
318 
319 	return ret;
320 }
321 
xradio_adapter_init(msg_proc func)322 struct xradio_adapter *xradio_adapter_init(msg_proc func)
323 {
324 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
325 	struct netlink_kernel_cfg cfg = {
326 		.input	= adapter_rec_handler,
327 	};
328 #endif
329 	if (func == NULL) {
330 		etf_printk(XRADIO_DBG_ERROR, "%s msg_proc is NULL\n", __func__);
331 		return NULL;
332 	}
333 	adapter_priv.handler = func;
334 	sema_init(&adapter_priv.send_lock, 1);
335 	if (adapter_init_msgbuf()) {
336 		etf_printk(XRADIO_DBG_ERROR, "%s adapter_init_msgbuf failed\n", __func__);
337 		return NULL;
338 	}
339 
340 #if (ETF_QUEUEMODE)
341 	sema_init(&adapter_priv.proc_sem, 0);
342 	if (adapter_start_thread()) {
343 		adapter_deinit_msgbuf();
344 		etf_printk(XRADIO_DBG_ERROR, "%s adapter_start_thread failed\n", __func__);
345 		return NULL;
346 	}
347 #endif
348 
349 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
350 	adapter_priv.sock = netlink_kernel_create(&init_net, NL_FOR_XRADIO, 0,
351 			adapter_rec_handler, NULL, THIS_MODULE);
352 #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
353 	adapter_priv.sock = netlink_kernel_create(&init_net, NL_FOR_XRADIO,
354 			THIS_MODULE, &cfg);
355 #else
356 	adapter_priv.sock = netlink_kernel_create(&init_net, NL_FOR_XRADIO, &cfg);
357 #endif
358 
359 	if (adapter_priv.sock == NULL) {
360 #if (ETF_QUEUEMODE)
361 		adapter_stop_thread();
362 #endif
363 		adapter_deinit_msgbuf();
364 		etf_printk(XRADIO_DBG_ERROR, "%s netlink_kernel_create failed\n", __func__);
365 		return NULL;
366 	}
367 
368 	return &adapter_priv;
369 }
370 
xradio_adapter_deinit(void)371 void xradio_adapter_deinit(void)
372 {
373 	if (adapter_priv.sock != NULL) {
374 		netlink_kernel_release(adapter_priv.sock);
375 		adapter_priv.sock = NULL;
376 	}
377 #if (ETF_QUEUEMODE)
378 	adapter_stop_thread();
379 #endif
380 	adapter_deinit_msgbuf();
381 }
382 
383 
384 /********************* interfaces of etf core **********************/
385 static struct xradio_etf etf_priv;
386 static struct etf_api_context context_save;
387 
388 int wsm_etf_cmd(struct xradio_common *hw_priv, struct wsm_hdr *arg);
389 int xradio_bh_suspend(struct xradio_common *hw_priv);
390 int xradio_bh_resume(struct xradio_common *hw_priv);
391 
etf_is_connect(void)392 bool etf_is_connect(void)
393 {
394 	return (bool)(etf_priv.etf_state != ETF_STAT_NULL);
395 }
396 
etf_set_core(void * core_priv)397 void etf_set_core(void *core_priv)
398 {
399 	etf_priv.core_priv = core_priv;
400 }
401 
etf_get_fwpath(void)402 const char *etf_get_fwpath(void)
403 {
404 	return (const char *)etf_priv.fw_path;
405 }
406 
etf_get_sddpath(void)407 const char *etf_get_sddpath(void)
408 {
409 	return (const char *)etf_priv.sdd_path;
410 }
411 
etf_get_sdd_param(u8 * sdd,int sdd_len,u8 ies,void ** data)412 static int etf_get_sdd_param(u8 *sdd, int sdd_len, u8 ies, void **data)
413 {
414 	int ie_len = 0;
415 	int parsedLength = 0;
416 	struct xradio_sdd *pElement = NULL;
417 	etf_printk(XRADIO_DBG_TRC, "%s\n", __func__);
418 
419 	/*parse SDD config.*/
420 	pElement = (struct xradio_sdd *)sdd;
421 	parsedLength += (FIELD_OFFSET(struct xradio_sdd, data) + \
422 					 pElement->length);
423 	pElement = FIND_NEXT_ELT(pElement);
424 
425 	while (parsedLength < sdd_len) {
426 		if (pElement->id == ies) {
427 			*data = (void *)pElement->data;
428 			ie_len = pElement->length;
429 		}
430 		parsedLength += (FIELD_OFFSET(struct xradio_sdd, data) + \
431 						pElement->length);
432 		pElement = FIND_NEXT_ELT(pElement);
433 	}
434 
435 	xradio_dbg(XRADIO_DBG_MSG, "parse len=%d, ie_len=%d.\n",
436 				parsedLength, ie_len);
437 	return ie_len;
438 }
439 
etf_driver_resp(int state,int result)440 static int etf_driver_resp(int state, int result)
441 {
442 	struct drv_resp drv_ret;
443 	drv_ret.len    = sizeof(drv_ret);
444 	drv_ret.id     = ETF_DRIVER_IND_ID;
445 	drv_ret.state  = state;
446 	drv_ret.result = result;
447 	return xradio_adapter_send(&drv_ret, drv_ret.len);
448 }
449 
xradio_etf_connect(void)450 static int xradio_etf_connect(void)
451 {
452 	int ret = BOOT_SUCCESS;
453 	etf_printk(XRADIO_DBG_TRC, "%s\n", __func__);
454 
455 	if (etf_priv.etf_state == ETF_STAT_NULL) {
456 		etf_priv.etf_state = ETF_STAT_CONNECTING;
457 		ret = xradio_core_init();
458 		if (ret) {
459 			etf_printk(XRADIO_DBG_ERROR, "%s:xradio_core_init failed(%d).\n",
460 						__func__, ret);
461 			goto err;
462 		}
463 		etf_priv.etf_state = ETF_STAT_CONNECTED;
464 	} else {
465 		etf_printk(XRADIO_DBG_WARN, "%s etf is already connect.\n", __func__);
466 		return ETF_ERR_CONNECTED;
467 	}
468 	etf_printk(XRADIO_DBG_ALWY, "%s:ETF connect success.\n", __func__);
469 	return 0;
470 
471 err:
472 	etf_priv.etf_state = ETF_STAT_NULL;
473 	return ret;
474 }
475 
xradio_etf_disconnect(void)476 static void xradio_etf_disconnect(void)
477 {
478 	etf_printk(XRADIO_DBG_TRC, "%s\n", __func__);
479 	if (etf_priv.etf_state != ETF_STAT_NULL) {
480 		xradio_core_deinit();
481 		etf_priv.etf_state = ETF_STAT_NULL;
482 	}
483 	etf_printk(XRADIO_DBG_ALWY, "%s end.\n", __func__);
484 }
485 
486 ETFCLI_PAR_T g_etfcli_par;
487 
xradio_etfcli_data_init(void)488 int xradio_etfcli_data_init(void)
489 {
490 	g_etfcli_par.bandwidth = ETF_CHANNEL_BANDWIDTH_20MHz;
491 	g_etfcli_par.channel = 7;
492 	g_etfcli_par.g_iGnModeForce = 0;
493 	g_etfcli_par.g_iRateIndex = 16;
494 	g_etfcli_par.mode = 0;
495 	g_etfcli_par.reat = 0;
496 	g_etfcli_par.subchannel = ETF_SUB_CHANNEL_UPPER;
497 	return 0;
498 }
499 
xradio_set_etfcli_data(int value,int index)500 int xradio_set_etfcli_data(int value, int index)
501 {
502 	xradio_dbg(XRADIO_DBG_MSG, "value = %d, index = %d\n", value, index);
503 
504 	switch (index) {
505 	case 0:
506 		g_etfcli_par.g_iRateIndex = value;
507 		break;
508 
509 	case 1:
510 		g_etfcli_par.g_iGnModeForce = value;
511 		break;
512 
513 	case 3:
514 		g_etfcli_par.channel = value;
515 		break;
516 
517 	case 4:
518 		g_etfcli_par.mode = value;
519 		break;
520 
521 	case 5:
522 		g_etfcli_par.reat = value;
523 		break;
524 
525 	case 6:
526 		g_etfcli_par.bandwidth = value;
527 		break;
528 
529 	case 7:
530 		g_etfcli_par.subchannel = value;
531 		break;
532 
533 	default:
534 		{
535 			etf_printk(XRADIO_DBG_ERROR,
536 				"%s This setting is not supported.\n", __func__);
537 			return -1;
538 		}
539 		break;
540 	}
541 
542 	return 0;
543 }
544 
545 #if DGB_XRADIO_HWT
546 //HWT
547 extern u8  hwt_testing;
548 extern u8 hwt_tx_en;
549 extern u8 hwt_tx_cfm;	/*confirm interval*/
550 extern u16 hwt_tx_len;
551 extern u16 hwt_tx_num;
552 
553 extern u8 hwt_rx_en;
554 extern u16 hwt_rx_len;
555 extern u16 hwt_rx_num;
556 extern struct timespec64 hwt_start_time;
557 
558 typedef struct HWT_PARAM_ENC_S {
559 	u16 Msglen;
560 	u16 MsgID;
561 	u16 TestID;
562 	u16 Params;
563 	u16 Datalen;
564 	u16 Data[2];
565 } HWT_PARAMENC;
566 
567 int wsm_hwt_cmd(struct xradio_common *hw_priv, void *arg,	size_t arg_size);
HWT_Tx_handle(HWT_PARAMETERS * cmd)568 int HWT_Tx_handle(HWT_PARAMETERS *cmd)
569 {
570 	etf_printk(XRADIO_DBG_TRC, "%s: MsgID=0x%04X, MsgLen=%d, TestID=%d, params=%d, datalen=%d\n", __func__,
571 			cmd->MsgID, cmd->Msglen, cmd->TestID, cmd->Params, cmd->Data);
572 	if (hwt_testing) {
573 		xradio_dbg(XRADIO_DBG_ALWY, "cmd refuse, hwt is testing!\n");
574 		return 0;
575 	}
576 	if (cmd->TestID == 0x1) {
577 		hwt_tx_len = cmd->Data;
578 		hwt_tx_num = cmd->Params;
579 		hwt_tx_cfm = 1;//16;   Be sure about the firmware has been using 16 buf when this value is set to 16
580 		hwt_tx_en = 1;
581 		hwt_testing = 1;
582 
583 		xradio_dbg(XRADIO_DBG_ALWY,
584 			   "hwt_tx_en=%d, hwt_tx_len=%d, hwt_tx_num=%d, hwt_tx_cfm=%d\n",
585 			   hwt_tx_en, hwt_tx_len, hwt_tx_num, hwt_tx_cfm);
586 
587 		if (!((struct xradio_common *)etf_priv.core_priv)->bh_error &&
588 			  atomic_add_return(1, &((struct xradio_common *)etf_priv.core_priv)->bh_tx) == 1)
589 			wake_up(&((struct xradio_common *)etf_priv.core_priv)->bh_wq);
590 	} else if (cmd->TestID == 0x2) {
591 		hwt_rx_len = cmd->Data;
592 		hwt_rx_num = cmd->Params;
593 		hwt_rx_en = 1;
594 		hwt_testing = 1;
595 
596 		xradio_dbg(XRADIO_DBG_ALWY,
597 			   "hwt_rx_en=%d, hwt_rx_len=%d, hwt_rx_num=%d\n", hwt_rx_en,
598 			   hwt_rx_len, hwt_rx_num);
599 
600 		wsm_hwt_cmd((struct xradio_common *)etf_priv.core_priv, (void *)&cmd->TestID, sizeof(HWT_PARAMETERS));
601 		xr_do_gettimeofday(&hwt_start_time);
602 
603 	} else if (cmd->TestID == 0x3) {
604 		xradio_dbg(XRADIO_DBG_ALWY, "pkt_num=%d, pkt_len=%d, enc_data=0x%04X\n",
605 			   cmd->Params, ((HWT_PARAMENC *)cmd)->Data[0], ((HWT_PARAMENC *)cmd)->Data[1]);
606 		hwt_testing = 1;
607 		wsm_hwt_cmd((struct xradio_common *)etf_priv.core_priv, (void *)&cmd->TestID, sizeof(HWT_PARAMETERS)+2);
608 	} else if (cmd->TestID == 0x4) {
609 		hwt_testing = 1;
610 		wsm_hwt_cmd((struct xradio_common *)etf_priv.core_priv, (void *)&cmd->TestID, sizeof(HWT_PARAMETERS));
611 	} else {
612 	}
613 	return 0;
614 }
615 #endif
xradio_etf_proc(void * data,int len)616 static int xradio_etf_proc(void *data, int len)
617 {
618 	int ret = BOOT_SUCCESS;
619 	struct wsm_hdr *hdr_rev = (struct wsm_hdr *)data;
620 	struct drv_download *download;
621 	int    datalen;
622 	etf_printk(XRADIO_DBG_TRC, "%s\n", __func__);
623 
624 	down(&etf_priv.etf_lock);
625 	/* Don't process ETF cmd in wlan mode */
626 	if (etf_priv.is_wlan) {
627 		etf_printk(XRADIO_DBG_WARN, "%s is in wlan mode.\n", __func__);
628 		ret = ETF_ERR_WLAN_MODE;
629 		etf_driver_resp(BOOT_STATE_NULL, ret);
630 		goto out;
631 	}
632 
633 	/* Process msg from ETF API */
634 	switch (MSG_ID(hdr_rev->id)) {
635 	case ETF_SOFT_RESET_REQ_ID:
636 		etf_printk(XRADIO_DBG_ALWY, "SOFT_RESET\n");
637 		xradio_etf_disconnect();
638 		etf_priv.fw_path   = XR829_ETF_FIRMWARE;
639 		etf_priv.sdd_path  = XR829_SDD_FILE;
640 		etf_priv.seq_send  = 0;
641 		etf_priv.seq_recv  = 0;
642 		memset(&context_save, 0, sizeof(context_save));
643 		etf_driver_resp(BOOT_STATE_NULL, BOOT_SUCCESS);
644 		break;
645 	case ETF_GET_API_CONTEXT_ID: /* for ETF tools which cannot save context*/
646 		{
647 			struct etf_api_context_result *ctxt_ret = NULL;
648 			struct xradio_common *hw_priv = etf_priv.core_priv;
649 			ctxt_ret = (struct etf_api_context_result *)hdr_rev;
650 			if (hw_priv) {
651 				ctxt_ret->is_etf_fw_run = hw_priv->wsm_caps.firmwareReady;
652 				memcpy(ctxt_ret->fw_label, hw_priv->wsm_caps.fw_label,
653 					min(HI_SW_LABEL_MAX, WSM_FW_LABEL));
654 				ctxt_ret->fw_api_ver = hw_priv->wsm_caps.firmwareApiVer;
655 				ctxt_ret->mib_baseaddr = context_save.config[1];
656 			} else {
657 				ctxt_ret->is_etf_fw_run = 0;
658 				memset(ctxt_ret->fw_label, 0, HI_SW_LABEL_MAX);
659 			}
660 			ctxt_ret->len = sizeof(*ctxt_ret);
661 			ctxt_ret->id |= ETF_CNF_BASE;
662 			ctxt_ret->result = 0;
663 			xradio_adapter_send(ctxt_ret, sizeof(*ctxt_ret));
664 		}
665 		break;
666 	case ETF_DOWNLOAD_ID:
667 		etf_printk(XRADIO_DBG_NIY, "DOWNLOAD_FW, size=%d\n", hdr_rev->len);
668 		download = (struct drv_download *)(hdr_rev + 1);
669 		datalen = hdr_rev->len - sizeof(*download) - sizeof(*hdr_rev);
670 		if (datalen <= 0) {
671 			/*it means old version APK, TODO:remove it in future */
672 			if (hdr_rev->len <= sizeof(*hdr_rev)) {
673 				etf_driver_resp(BOOT_COMPLETE, BOOT_SUCCESS);
674 				ret = xradio_etf_connect();
675 				if (ret)
676 					etf_driver_resp(BOOT_STATE_NULL, ret);
677 			}
678 			break;
679 		}
680 		if (download->flags & DOWNLOAD_F_PATH_ONLY) {
681 			etf_printk(XRADIO_DBG_WARN, "fw path=%s\n", (char *)(download+1));
682 			/*TODO: set etf_priv.fw_path*/
683 
684 		} else if (download->flags & DOWNLOAD_F_START) {
685 			etf_printk(XRADIO_DBG_NIY, "fw first block\n");
686 			/*TODO: open a tmp file to save firmware */
687 		}
688 
689 		/*TODO: put data into a tmp file */
690 
691 		/*TODO: put data into a tmp file */
692 		if ((download->flags & DOWNLOAD_F_END)) {
693 			etf_printk(XRADIO_DBG_NIY, "fw last block\n");
694 			etf_driver_resp(BOOT_COMPLETE, BOOT_SUCCESS);
695 			/*TODO: save data tmp file and update etf_priv.fw_path*/
696 			ret = xradio_etf_connect();
697 			if (ret)
698 				etf_driver_resp(BOOT_STATE_NULL, ret);
699 		}
700 		break;
701 	case ETF_DOWNLOAD_SDD_ID:
702 		etf_printk(XRADIO_DBG_NIY, "DOWNLOAD_SDD, size=%d\n", hdr_rev->len);
703 		download = (struct drv_download *)(hdr_rev + 1);
704 		datalen = hdr_rev->len - sizeof(*download) - sizeof(*hdr_rev);
705 		if (datalen <= 0) {
706 			/*it means old version APK, TODO:remove it in future */
707 			if (hdr_rev->len <= sizeof(*hdr_rev)) {
708 				etf_driver_resp(BOOT_SDD_COMPLETE, BOOT_SUCCESS);
709 			}
710 			break;
711 		}
712 
713 		if (download->flags & DOWNLOAD_F_PATH_ONLY) {
714 			etf_printk(XRADIO_DBG_WARN, "sdd path=%s\n", (char *)(download+1));
715 			/*TODO: set etf_priv.fw_path*/
716 
717 		} else if ((download->flags & DOWNLOAD_F_START)) {
718 			etf_printk(XRADIO_DBG_NIY, "sdd first block\n");
719 			/*TODO: open a tmp file to save firmware */
720 		}
721 
722 		/*TODO: put data into a tmp file */
723 
724 		if ((download->flags & DOWNLOAD_F_END)) {
725 			etf_printk(XRADIO_DBG_NIY, "sdd last block\n");
726 			etf_driver_resp(BOOT_SDD_COMPLETE, BOOT_SUCCESS);
727 			/*TODO: save data tmp file and update etf_priv.sdd_path*/
728 		}
729 		break;
730 	case ETF_CONNECT_ID:
731 		etf_printk(XRADIO_DBG_ALWY, "ETF_CONNECT_ID!\n");
732 		etf_driver_resp(BOOT_COMPLETE, BOOT_SUCCESS);
733 		ret = xradio_etf_connect();
734 		if (ret)
735 			etf_driver_resp(BOOT_STATE_NULL, ret);
736 		break;
737 	case ETF_DISCONNECT_ID:
738 		etf_printk(XRADIO_DBG_ALWY, "ETF_DISCONNECT_ID!\n");
739 		xradio_etf_disconnect();
740 		etf_driver_resp(BOOT_STATE_NULL, BOOT_SUCCESS);
741 		break;
742 	case ETF_RECONNECT_ID:
743 		etf_printk(XRADIO_DBG_ALWY, "ETF_RECONNECT_ID!\n");
744 		if (1/*TODO: is update files*/) {
745 			xradio_etf_disconnect();
746 			etf_driver_resp(BOOT_COMPLETE, BOOT_SUCCESS);
747 			ret = xradio_etf_connect();
748 			if (ret)
749 				etf_driver_resp(BOOT_STATE_NULL, ret);
750 		} else {
751 			ret = BOOT_ERR_BAD_OP;
752 			etf_driver_resp(BOOT_STATE_NULL, ret);
753 			etf_printk(XRADIO_DBG_ERROR, "No download files before!\n");
754 		}
755 		break;
756 	case ETF_GET_SDD_POWER_DEFT:  /* get default tx power */
757 		{
758 			const struct firmware *sdd = NULL;
759 			etf_printk(XRADIO_DBG_NIY, "%s ETF_GET_SDD_POWER_DEFT!\n", __func__);
760 
761 			ret = request_firmware(&sdd, etf_get_sddpath(), NULL);
762 			/* get sdd data */
763 			if (likely(sdd) && likely(sdd->data)) {
764 				int i;
765 				u16  *outpower = (u16 *)(hdr_rev + 1);
766 				void *ie_data = NULL;
767 				int ie_len = etf_get_sdd_param((u8 *)sdd->data, sdd->size,
768 								SDD_MAX_OUTPUT_POWER_2G4_ELT_ID, &ie_data);
769 				if (ie_len > 0 && ie_data &&
770 				   ie_len < (ADAPTER_RX_BUF_LEN - sizeof(*hdr_rev))) {
771 					memcpy(outpower, ie_data, ie_len);
772 					for (i = 0; i < (ie_len>>1); i++)
773 						outpower[i] -= 48; /*default pwr = max power - 48*/
774 				}
775 				hdr_rev->len = sizeof(*hdr_rev) + ie_len;
776 				xradio_adapter_send(hdr_rev, hdr_rev->len);
777 				release_firmware(sdd);
778 			} else {
779 				etf_printk(XRADIO_DBG_ERROR, "%s: can't load sdd file %s.\n",
780 							__func__, etf_get_sddpath());
781 				ret = -ENOENT;
782 				hdr_rev->len = sizeof(*hdr_rev);
783 				xradio_adapter_send(hdr_rev, sizeof(*hdr_rev));
784 			}
785 		}
786 		break;
787 	case ETF_GET_SDD_PARAM_ID:
788 		{
789 			struct xradio_common *hw_priv = etf_priv.core_priv;
790 			struct get_sdd_param_req *sddreq = (struct get_sdd_param_req *)hdr_rev;
791 			struct get_sdd_result *sddret = (struct get_sdd_result *)sddreq;
792 			void *ie_data = NULL;
793 			int ie_len = 0;
794 			const struct firmware *sdd = NULL;
795 			etf_printk(XRADIO_DBG_NIY, "%s ETF_GET_SDD_PARAM_ID!\n", __func__);
796 
797 			if (hw_priv && hw_priv->sdd) {
798 				etf_printk(XRADIO_DBG_NIY, "%s use xradio_common sdd!\n", __func__);
799 				sdd = hw_priv->sdd;
800 			} else {
801 				ret = request_firmware(&sdd, etf_get_sddpath(), NULL);
802 			}
803 
804 			hdr_rev->id  = hdr_rev->id + ETF_CNF_BASE;
805 			if (likely(sdd) && likely(sdd->data)) {
806 				if (sddreq->flags & FLAG_GET_SDD_ALL) {
807 					sddret->result  = 0;
808 					sddret->length  = sdd->size;
809 					xradio_adapter_send_pkg(sddret, sizeof(*sddret), (u8 *)sdd->data,
810 							sddret->length);
811 				} else {
812 					ie_len = etf_get_sdd_param((u8 *)sdd->data, sdd->size,
813 								sddreq->ies, &ie_data);
814 					if (ie_data && ie_len > 0) {
815 						sddret->result  = 0;
816 						sddret->length  = ie_len;
817 						hdr_rev->len = sizeof(*sddret) + sddret->length;
818 						xradio_adapter_send_pkg(sddret, sizeof(*sddret), ie_data,
819 								sddret->length);
820 					} else {
821 						sddret->result = -ENOMSG;
822 						sddret->length = 0;
823 						hdr_rev->len = sizeof(*sddret) + sddret->length;
824 						xradio_adapter_send(sddret, sizeof(*sddret));
825 					}
826 				}
827 				if (hw_priv && hw_priv->sdd) {
828 					sdd = NULL;
829 				} else {
830 					release_firmware(sdd);
831 				}
832 			} else {
833 				etf_printk(XRADIO_DBG_ERROR, "%s: can't load sdd file %s.\n",
834 							__func__, etf_get_sddpath());
835 				sddret->result = -ENOENT;
836 				sddret->length = 0;
837 				hdr_rev->len = sizeof(*sddret) + sddret->length;
838 				xradio_adapter_send(sddret, sizeof(*sddret));
839 			}
840 		}
841 		break;
842 	case ETF_SET_CLI_PAR_DEFT:
843 		{
844 			CLI_PARAM_SAVE_T *hdr_data = (CLI_PARAM_SAVE_T *)hdr_rev;
845 
846 			etf_printk(XRADIO_DBG_MSG, "%s ETF_GET_CLI_PAR_DEFT!\n", __func__);
847 			hdr_rev->id  = hdr_rev->id + ETF_CNF_BASE;
848 			if (hdr_data)
849 				ret = xradio_set_etfcli_data(hdr_data->value, hdr_data->index);
850 			hdr_data->result = ret;
851 			xradio_adapter_send(hdr_data, sizeof(*hdr_data));
852 		}
853 		break;
854 	case ETF_GET_CLI_PAR_DEFT:
855 		{
856 			struct get_cli_data_req *param_req;
857 			struct get_cli_data_result *param_ret;
858 
859 			param_req = (struct get_cli_data_req *)hdr_rev;
860 			param_ret = (struct get_cli_data_result *)param_req;
861 			etf_printk(XRADIO_DBG_MSG, "%s ETF_GET_CLI_PAR_DEFT!\n", __func__);
862 
863 			hdr_rev->id  = hdr_rev->id + ETF_CNF_BASE;
864 			param_ret->result	= 0;
865 			param_ret->length	= sizeof(g_etfcli_par);
866 			hdr_rev->len = sizeof(*param_ret) + param_ret->length;
867 			xradio_adapter_send_pkg(param_ret, sizeof(*param_ret),
868 					(void *)&g_etfcli_par, param_ret->length);
869 		}
870 		break;
871 	default:
872 		etf_printk(XRADIO_DBG_NIY, "%s: passed cmd=0x%04x, len=%d",
873 					__func__, MSG_ID(hdr_rev->id), hdr_rev->len);
874 		if (etf_priv.etf_state != ETF_STAT_CONNECTED) {
875 			etf_printk(XRADIO_DBG_WARN, "%s etf Not connect.\n", __func__);
876 			ret = ETF_ERR_NOT_CONNECT;
877 			etf_driver_resp(BOOT_STATE_NULL, ret);
878 			goto out;
879 		}
880 		if (SEQ_MASK(etf_priv.seq_send) != MSG_SEQ(hdr_rev->id)) {
881 			etf_printk(XRADIO_DBG_NIY, "%s:seq err, drv_seq=%d, seq=%d\n",
882 						__func__, etf_priv.seq_send, MSG_SEQ(hdr_rev->id));
883 			etf_priv.seq_send = MSG_SEQ(hdr_rev->id);
884 		}
885 		etf_priv.seq_send++;
886 		if (ETF_HWT_REQ == MSG_ID(hdr_rev->id)) {
887 			/*TODO: HW test*/
888 #if DGB_XRADIO_HWT
889 			HWT_Tx_handle((HWT_PARAMETERS *)data);
890 #else
891 			etf_printk(XRADIO_DBG_ERROR, "%s HW test unsupport\n", __func__);
892 #endif
893 		} else if (etf_priv.core_priv) {
894 			if (ETF_DOWNLOAD_SDD == MSG_ID(hdr_rev->id) &&
895 			    hdr_rev->len <= sizeof(struct etf_sdd_req)) {
896 				struct xradio_common *hw_priv = etf_priv.core_priv;
897 				struct etf_sdd_req *sdd_req = (struct etf_sdd_req *)hdr_rev;
898 				u32 sdd_cmd = sdd_req->sdd_cmd;
899 				etf_printk(XRADIO_DBG_WARN, "%s add sdd data, cmd=0x%08x!\n",
900 							__func__, sdd_cmd);
901 				if (hw_priv->sdd) {
902 					u8 *sdd_data = (u8 *)(hdr_rev + 1);
903 					int sdd_len  = hw_priv->sdd->size;
904 					if (sdd_len + sizeof(*hdr_rev) + 4 < ADAPTER_RX_BUF_LEN) {
905 						memcpy(sdd_data, hw_priv->sdd->data, sdd_len);
906 						memcpy(sdd_data + sdd_len, &sdd_cmd, 4);
907 						hdr_rev->len += sdd_len;
908 					} else {
909 						etf_printk(XRADIO_DBG_ERROR,
910 									"ADAPTER_RX_BUF_LEN=%d, sdd_len=%d\n",
911 									 ADAPTER_RX_BUF_LEN, sdd_len);
912 					}
913 				} else
914 					etf_printk(XRADIO_DBG_ERROR, "%s core_priv sdd is NULL\n",
915 							__func__);
916 			}
917 			/* send to device*/
918 			ret = wsm_etf_cmd(etf_priv.core_priv, (struct wsm_hdr *)data);
919 			if (ret < 0) {
920 				etf_driver_resp(BOOT_STATE_NULL, ret);
921 				etf_printk(XRADIO_DBG_ERROR, "%s wsm_etf_cmd failed(%d)\n",
922 							__func__, ret);
923 			}
924 		} else {
925 			etf_printk(XRADIO_DBG_ERROR, "%s core_priv is NULL\n",
926 						__func__);
927 		}
928 		break;
929 	}
930 	up(&etf_priv.etf_lock);
931 	etf_printk(XRADIO_DBG_NIY, "%s success\n", __func__);
932 	return 0;
933 
934 out:
935 	up(&etf_priv.etf_lock);
936 	if (ret)
937 		etf_printk(XRADIO_DBG_ERROR, "%s proc failed(%d)\n", __func__, ret);
938 	return ret;
939 }
940 
xradio_etf_from_device(struct sk_buff ** skb)941 int xradio_etf_from_device(struct sk_buff **skb)
942 {
943 	int ret = 0;
944 	struct wsm_hdr *wsm = (struct wsm_hdr *)((*skb)->data);
945 	etf_printk(XRADIO_DBG_NIY, "%s MsgId=0x%04x, len=%d\n", __func__,
946 			   wsm->id, wsm->len);
947 	ret = xradio_adapter_send((void *)wsm, wsm->len);
948 	if (ret < 0) {
949 		etf_printk(XRADIO_DBG_ERROR, "%s xradio_adapter_send failed(%d).\n",
950 					__func__, ret);
951 	} else {
952 		etf_priv.seq_recv++;
953 	}
954 	return 0;
955 }
956 
xradio_etf_save_context(void * buf,int len)957 void xradio_etf_save_context(void *buf, int len)
958 {
959 	etf_printk(XRADIO_DBG_TRC, "%s\n", __func__);
960 	if (len == sizeof(context_save)) {
961 		etf_printk(XRADIO_DBG_NIY, "%s, len=%d\n", __func__, len);
962 		memcpy(&context_save, buf, sizeof(context_save));
963 	} else if (len > sizeof(context_save)) {
964 		etf_printk(XRADIO_DBG_WARN, "%s, len=%d\n", __func__, len);
965 		memcpy(&context_save, buf, sizeof(context_save));
966 	} else {
967 		etf_printk(XRADIO_DBG_ERROR, "%s, len too short=%d\n", __func__, len);
968 	}
969 }
970 
xradio_etf_to_wlan(u32 change)971 void xradio_etf_to_wlan(u32 change)
972 {
973 	down(&etf_priv.etf_lock);
974 	etf_priv.is_wlan = change;
975 	if (change && etf_is_connect()) {
976 		etf_printk(XRADIO_DBG_NIY, "%s change to wlan.\n", __func__);
977 		xradio_etf_disconnect();
978 	}
979 	up(&etf_priv.etf_lock);
980 }
981 
xradio_etf_suspend(void)982 int xradio_etf_suspend(void)
983 {
984 	etf_printk(XRADIO_DBG_NIY, "%s\n", __func__);
985 	if (down_trylock(&etf_priv.etf_lock)) {
986 		etf_printk(XRADIO_DBG_WARN,
987 			"%s etf_lock is locked\n", __func__);
988 		return -EBUSY; /*etf is locked.*/
989 	}
990 	if (etf_is_connect()) {
991 		etf_printk(XRADIO_DBG_WARN,
992 			"%s etf is running, don't suspend!\n", __func__);
993 		up(&etf_priv.etf_lock);
994 		return -EBUSY; /*etf is running*/
995 	}
996 	up(&etf_priv.etf_lock);
997 	return 0;
998 }
999 
xradio_etf_resume(void)1000 int xradio_etf_resume(void)
1001 {
1002 	etf_printk(XRADIO_DBG_NIY, "%s\n", __func__);
1003 	return 0;
1004 }
1005 
xradio_etf_init(void)1006 int xradio_etf_init(void)
1007 {
1008 	int ret = 0;
1009 	etf_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1010 	sema_init(&etf_priv.etf_lock, 1);
1011 	etf_priv.etf_state = ETF_STAT_NULL;
1012 	etf_priv.fw_path  = XR829_ETF_FIRMWARE;
1013 	etf_priv.sdd_path = XR829_SDD_FILE;
1014 	xradio_etfcli_data_init();
1015 	etf_priv.adapter = xradio_adapter_init(&xradio_etf_proc);
1016 	return ret;
1017 }
1018 
xradio_etf_deinit(void)1019 void xradio_etf_deinit(void)
1020 {
1021 	etf_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1022 	/*ensure in disconnect state when etf deinit*/
1023 	xradio_etf_to_wlan(1);
1024 	xradio_adapter_deinit();
1025 	memset(&etf_priv, 0, sizeof(etf_priv));
1026 }
1027 
1028 #endif /*XRADIO_ETF_C*/
1029