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, ¶m);
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