1 #include <linux/init.h>
2 #include <linux/module.h>
3 #include <linux/types.h>
4 #include <linux/kernel.h>
6 #include <linux/cdev.h>
7 #include <linux/sched.h>
8 #include <asm/current.h>
9 #include <asm/uaccess.h>
10 #include <linux/fcntl.h>
11 #include <linux/poll.h>
12 #include <linux/time.h>
13 #include <linux/delay.h>
14 #include <linux/netdevice.h>
15 #include <net/net_namespace.h>
16 #include <linux/string.h>
22 MODULE_LICENSE("Dual BSD/GPL");
24 #define WIFI_DRIVER_NAME "mtk_wmt_WIFI_chrdev"
25 #define WIFI_DEV_MAJOR 153
27 #define PFX "[MTK-WIFI] "
28 #define WIFI_LOG_DBG 3
29 #define WIFI_LOG_INFO 2
30 #define WIFI_LOG_WARN 1
31 #define WIFI_LOG_ERR 0
33 UINT32 gDbgLevel
= WIFI_LOG_DBG
;
35 #define WIFI_DBG_FUNC(fmt, arg...)\
36 do {if (gDbgLevel >= WIFI_LOG_DBG) pr_warn(PFX "%s: " fmt, __func__ , ##arg); } while (0)
37 #define WIFI_INFO_FUNC(fmt, arg...)\
38 do {if (gDbgLevel >= WIFI_LOG_INFO) pr_warn(PFX "%s: " fmt, __func__ , ##arg); } while (0)
39 #define WIFI_WARN_FUNC(fmt, arg...)\
40 do {if (gDbgLevel >= WIFI_LOG_WARN) pr_warn(PFX "%s: " fmt, __func__ , ##arg); } while (0)
41 #define WIFI_ERR_FUNC(fmt, arg...)\
42 do {if (gDbgLevel >= WIFI_LOG_ERR) pr_warn(PFX "%s: " fmt, __func__ , ##arg); } while (0)
43 #define WIFI_TRC_FUNC(f)\
44 do {if (gDbgLevel >= WIFI_LOG_DBG) pr_warn(PFX "<%s> <%d>\n", __func__, __LINE__); } while (0)
49 #define WLAN_IFACE_NAME "wlan0"
57 static INT32 wlan_mode
= WLAN_MODE_HALT
;
60 typedef enum _ENUM_RESET_STATUS_T
{
63 } ENUM_RESET_STATUS_T
;
66 * enable = 1, mode = 0 => init P2P network
67 * enable = 1, mode = 1 => init Soft AP network
68 * enable = 0 => uninit P2P/AP network
70 typedef struct _PARAM_CUSTOM_P2P_SET_STRUC_T
{
73 } PARAM_CUSTOM_P2P_SET_STRUC_T
, *P_PARAM_CUSTOM_P2P_SET_STRUC_T
;
74 typedef INT32 (*set_p2p_mode
) (struct net_device
*netdev
, PARAM_CUSTOM_P2P_SET_STRUC_T p2pmode
);
76 static set_p2p_mode pf_set_p2p_mode
;
77 VOID
register_set_p2p_mode_handler(set_p2p_mode handler
) {
78 WIFI_INFO_FUNC("(pid %d) register set p2p mode handler %p\n", current
->pid
, handler
);
79 pf_set_p2p_mode
= handler
;
81 EXPORT_SYMBOL(register_set_p2p_mode_handler
);
83 /* For dynamical debug level setting */
84 /* copy of debug.h in wlan driver */
85 #define DBG_CLASS_ERROR BIT(0)
86 #define DBG_CLASS_WARN BIT(1)
87 #define DBG_CLASS_STATE BIT(2)
88 #define DBG_CLASS_EVENT BIT(3)
89 #define DBG_CLASS_TRACE BIT(4)
90 #define DBG_CLASS_INFO BIT(5)
91 #define DBG_CLASS_LOUD BIT(6)
92 #define DBG_CLASS_TEMP BIT(7)
93 #define DBG_CLASS_MASK BITS(0, 7)
95 typedef enum _ENUM_DBG_MODULE_T
{
96 DBG_INIT_IDX
= 0, /* For driver initial */
97 DBG_HAL_IDX
, /* For HAL(HW) Layer */
98 DBG_INTR_IDX
, /* For Interrupt */
102 DBG_RFTEST_IDX
, /* For RF test mode */
103 DBG_EMU_IDX
, /* Developer specific */
105 DBG_SW1_IDX
, /* Developer specific */
106 DBG_SW2_IDX
, /* Developer specific */
107 DBG_SW3_IDX
, /* Developer specific */
108 DBG_SW4_IDX
, /* Developer specific */
110 DBG_HEM_IDX
, /* HEM */
111 DBG_AIS_IDX
, /* AIS */
112 DBG_RLM_IDX
, /* RLM */
113 DBG_MEM_IDX
, /* RLM */
114 DBG_CNM_IDX
, /* CNM */
115 DBG_RSN_IDX
, /* RSN */
116 DBG_BSS_IDX
, /* BSS */
117 DBG_SCN_IDX
, /* SCN */
118 DBG_SAA_IDX
, /* SAA */
119 DBG_AAA_IDX
, /* AAA */
120 DBG_P2P_IDX
, /* P2P */
121 DBG_QM_IDX
, /* QUE_MGT */
122 DBG_SEC_IDX
, /* SEC */
123 DBG_BOW_IDX
, /* BOW */
124 DBG_WAPI_IDX
, /* WAPI */
125 DBG_ROAMING_IDX
, /* ROAMING */
127 DBG_MODULE_NUM
/* Notice the X-LOG check */
130 typedef VOID (*set_dbg_level
) (UINT8 modules
[DBG_MODULE_NUM
]);
132 UINT8 wlan_dbg_level
[DBG_MODULE_NUM
];
133 static set_dbg_level pf_set_dbg_level
;
134 VOID
register_set_dbg_level_handler(set_dbg_level handler
) {
135 pf_set_dbg_level
= handler
;
137 EXPORT_SYMBOL(register_set_dbg_level_handler
);
140 static INT32 WIFI_devs
= 1;
141 static INT32 WIFI_major
= WIFI_DEV_MAJOR
;
142 module_param(WIFI_major
, uint
, 0);
143 static struct cdev WIFI_cdev
;
144 volatile INT32 retflag
= 0;
145 static struct semaphore wr_mtx
;
148 /*******************************************************************
149 * WHOLE CHIP RESET PROCEDURE:
151 * WMTRSTMSG_RESET_START callback
153 * -> WMTRSTMSG_RESET_END callback
155 *******************************************************************
157 /*-----------------------------------------------------------------*/
159 * Receiving RESET_START message
161 /*-----------------------------------------------------------------*/
162 INT32
wifi_reset_start(VOID
)
164 struct net_device
*netdev
= NULL
;
165 PARAM_CUSTOM_P2P_SET_STRUC_T p2pmode
;
170 netdev
= dev_get_by_name(&init_net
, WLAN_IFACE_NAME
);
171 if (netdev
== NULL
) {
172 WIFI_ERR_FUNC("Fail to get wlan0 net device\n");
174 p2pmode
.u4Enable
= 0;
177 if (pf_set_p2p_mode
) {
178 if (pf_set_p2p_mode(netdev
, p2pmode
) != 0) {
179 WIFI_ERR_FUNC("Turn off p2p/ap mode fail");
181 WIFI_INFO_FUNC("Turn off p2p/ap mode");
188 /* WIFI is off before whole chip reset, do nothing */
193 EXPORT_SYMBOL(wifi_reset_start
);
195 /*-----------------------------------------------------------------*/
197 * Receiving RESET_END/RESET_END_FAIL message
199 /*-----------------------------------------------------------------*/
200 INT32
wifi_reset_end(ENUM_RESET_STATUS_T status
)
202 struct net_device
*netdev
= NULL
;
203 PARAM_CUSTOM_P2P_SET_STRUC_T p2pmode
;
207 if (status
== RESET_FAIL
) {
208 /* whole chip reset fail, donot recover WIFI */
211 } else if (status
== RESET_SUCCESS
) {
212 WIFI_WARN_FUNC("WIFI state recovering...\n");
215 /* WIFI is on before whole chip reset, reopen it now */
216 if (MTK_WCN_BOOL_FALSE
== mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI
)) {
217 WIFI_ERR_FUNC("WMT turn on WIFI fail!\n");
220 WIFI_INFO_FUNC("WMT turn on WIFI success!\n");
223 if (pf_set_p2p_mode
== NULL
) {
224 WIFI_ERR_FUNC("Set p2p mode handler is NULL\n");
228 netdev
= dev_get_by_name(&init_net
, WLAN_IFACE_NAME
);
229 while (netdev
== NULL
&& wait_cnt
< 10) {
230 WIFI_ERR_FUNC("Fail to get wlan0 net device, sleep 300ms\n");
233 netdev
= dev_get_by_name(&init_net
, WLAN_IFACE_NAME
);
235 if (wait_cnt
>= 10) {
236 WIFI_ERR_FUNC("Get wlan0 net device timeout\n");
240 if (wlan_mode
== WLAN_MODE_STA_P2P
) {
241 p2pmode
.u4Enable
= 1;
243 if (pf_set_p2p_mode(netdev
, p2pmode
) != 0) {
244 WIFI_ERR_FUNC("Set wlan mode fail\n");
246 WIFI_WARN_FUNC("Set wlan mode %d\n", WLAN_MODE_STA_P2P
);
249 } else if (wlan_mode
== WLAN_MODE_AP
) {
250 p2pmode
.u4Enable
= 1;
252 if (pf_set_p2p_mode(netdev
, p2pmode
) != 0) {
253 WIFI_ERR_FUNC("Set wlan mode fail\n");
255 WIFI_WARN_FUNC("Set wlan mode %d\n", WLAN_MODE_AP
);
260 if (netdev
!= NULL
) {
264 /* WIFI is off before whole chip reset, do nothing */
272 EXPORT_SYMBOL(wifi_reset_end
);
275 static int WIFI_open(struct inode
*inode
, struct file
*file
)
277 WIFI_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__
,
278 imajor(inode
), iminor(inode
), current
->pid
);
283 static int WIFI_close(struct inode
*inode
, struct file
*file
)
285 WIFI_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__
,
286 imajor(inode
), iminor(inode
), current
->pid
);
292 ssize_t
WIFI_write(struct file
*filp
, const char __user
*buf
, size_t count
, loff_t
*f_pos
)
295 INT8 local
[12] = { 0 };
296 struct net_device
*netdev
= NULL
;
297 PARAM_CUSTOM_P2P_SET_STRUC_T p2pmode
;
302 WIFI_ERR_FUNC("WIFI_write invalid param\n");
306 if (0 == copy_from_user(local
, buf
, (count
> sizeof(local
)) ? sizeof(local
) : count
)) {
308 WIFI_INFO_FUNC("WIFI_write %s\n", local
);
310 if (local
[0] == '0') {
312 WIFI_INFO_FUNC("WIFI is already power off!\n");
314 wlan_mode
= WLAN_MODE_HALT
;
318 netdev
= dev_get_by_name(&init_net
, WLAN_IFACE_NAME
);
319 if (netdev
== NULL
) {
320 WIFI_ERR_FUNC("Fail to get wlan0 net device\n");
322 p2pmode
.u4Enable
= 0;
325 if (pf_set_p2p_mode
) {
326 if (pf_set_p2p_mode(netdev
, p2pmode
) != 0) {
327 WIFI_ERR_FUNC("Turn off p2p/ap mode fail");
329 WIFI_INFO_FUNC("Turn off p2p/ap mode");
330 wlan_mode
= WLAN_MODE_HALT
;
337 if (MTK_WCN_BOOL_FALSE
== mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI
)) {
338 WIFI_ERR_FUNC("WMT turn off WIFI fail!\n");
340 WIFI_INFO_FUNC("WMT turn off WIFI OK!\n");
343 wlan_mode
= WLAN_MODE_HALT
;
345 } else if (local
[0] == '1') {
347 WIFI_INFO_FUNC("WIFI is already power on!\n");
352 if (MTK_WCN_BOOL_FALSE
== mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI
)) {
353 WIFI_ERR_FUNC("WMT turn on WIFI fail!\n");
357 WIFI_INFO_FUNC("WMT turn on WIFI success!\n");
358 wlan_mode
= WLAN_MODE_HALT
;
360 } else if (local
[0] == 'D') {
364 * 1: common debug output
370 for (k
= 0; k
< DBG_MODULE_NUM
; k
++) {
371 wlan_dbg_level
[k
] = 0;
373 if (pf_set_dbg_level
) {
374 pf_set_dbg_level(wlan_dbg_level
);
378 for (k
= 0; k
< DBG_MODULE_NUM
; k
++) {
379 wlan_dbg_level
[k
] = DBG_CLASS_ERROR
|
382 DBG_CLASS_EVENT
| DBG_CLASS_TRACE
| DBG_CLASS_INFO
;
384 wlan_dbg_level
[DBG_TX_IDX
] &= ~(DBG_CLASS_EVENT
|
385 DBG_CLASS_TRACE
| DBG_CLASS_INFO
);
386 wlan_dbg_level
[DBG_RX_IDX
] &= ~(DBG_CLASS_EVENT
|
387 DBG_CLASS_TRACE
| DBG_CLASS_INFO
);
388 wlan_dbg_level
[DBG_REQ_IDX
] &= ~(DBG_CLASS_EVENT
|
389 DBG_CLASS_TRACE
| DBG_CLASS_INFO
);
390 wlan_dbg_level
[DBG_INTR_IDX
] = 0;
391 wlan_dbg_level
[DBG_MEM_IDX
] = 0;
392 if (pf_set_dbg_level
) {
393 pf_set_dbg_level(wlan_dbg_level
);
397 for (k
= 0; k
< DBG_MODULE_NUM
; k
++) {
398 wlan_dbg_level
[k
] = DBG_CLASS_ERROR
|
401 DBG_CLASS_EVENT
| DBG_CLASS_TRACE
| DBG_CLASS_INFO
;
403 wlan_dbg_level
[DBG_INTR_IDX
] = 0;
404 wlan_dbg_level
[DBG_MEM_IDX
] = 0;
405 if (pf_set_dbg_level
) {
406 pf_set_dbg_level(wlan_dbg_level
);
410 for (k
= 0; k
< DBG_MODULE_NUM
; k
++) {
411 wlan_dbg_level
[k
] = DBG_CLASS_ERROR
|
415 DBG_CLASS_TRACE
| DBG_CLASS_INFO
| DBG_CLASS_LOUD
;
417 if (pf_set_dbg_level
) {
418 pf_set_dbg_level(wlan_dbg_level
);
424 } else if (local
[0] == 'S' || local
[0] == 'P' || local
[0] == 'A') {
426 /* If WIFI is off, turn on WIFI first */
427 if (MTK_WCN_BOOL_FALSE
== mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI
)) {
428 WIFI_ERR_FUNC("WMT turn on WIFI fail!\n");
432 WIFI_INFO_FUNC("WMT turn on WIFI success!\n");
433 wlan_mode
= WLAN_MODE_HALT
;
437 if (pf_set_p2p_mode
== NULL
) {
438 WIFI_ERR_FUNC("Set p2p mode handler is NULL\n");
442 netdev
= dev_get_by_name(&init_net
, WLAN_IFACE_NAME
);
443 while (netdev
== NULL
&& wait_cnt
< 10) {
444 WIFI_ERR_FUNC("Fail to get wlan0 net device, sleep 300ms\n");
447 netdev
= dev_get_by_name(&init_net
, WLAN_IFACE_NAME
);
449 if (wait_cnt
>= 10) {
450 WIFI_ERR_FUNC("Get wlan0 net device timeout\n");
454 if ((wlan_mode
== WLAN_MODE_STA_P2P
&& (local
[0] == 'S' || local
[0] == 'P')) ||
455 (wlan_mode
== WLAN_MODE_AP
&& (local
[0] == 'A'))){
456 WIFI_INFO_FUNC("WIFI is already in mode %d!\n", wlan_mode
);
461 if ((wlan_mode
== WLAN_MODE_AP
&& (local
[0] == 'S' || local
[0] == 'P')) ||
462 (wlan_mode
== WLAN_MODE_STA_P2P
&& (local
[0] == 'A'))) {
463 p2pmode
.u4Enable
= 0;
465 if (pf_set_p2p_mode(netdev
, p2pmode
) != 0) {
466 WIFI_ERR_FUNC("Turn off p2p/ap mode fail");
471 if (local
[0] == 'S' || local
[0] == 'P') {
472 p2pmode
.u4Enable
= 1;
474 if (pf_set_p2p_mode(netdev
, p2pmode
) != 0) {
475 WIFI_ERR_FUNC("Set wlan mode fail\n");
477 WIFI_INFO_FUNC("Set wlan mode %d --> %d\n", wlan_mode
,
479 wlan_mode
= WLAN_MODE_STA_P2P
;
482 } else if (local
[0] == 'A') {
483 p2pmode
.u4Enable
= 1;
485 if (pf_set_p2p_mode(netdev
, p2pmode
) != 0) {
486 WIFI_ERR_FUNC("Set wlan mode fail\n");
488 WIFI_INFO_FUNC("Set wlan mode %d --> %d\n", wlan_mode
,
490 wlan_mode
= WLAN_MODE_AP
;
499 if (netdev
!= NULL
) {
507 struct file_operations WIFI_fops
= {
509 .release
= WIFI_close
,
515 struct class *wmtWifi_class
= NULL
;
519 static int WIFI_init(void)
521 dev_t dev
= MKDEV(WIFI_major
, 0);
525 struct device
*wmtWifi_dev
= NULL
;
527 /*static allocate chrdev */
528 alloc_ret
= register_chrdev_region(dev
, 1, WIFI_DRIVER_NAME
);
530 WIFI_ERR_FUNC("Fail to register chrdev\n");
534 cdev_init(&WIFI_cdev
, &WIFI_fops
);
535 WIFI_cdev
.owner
= THIS_MODULE
;
537 cdev_err
= cdev_add(&WIFI_cdev
, dev
, WIFI_devs
);
543 wmtWifi_class
= class_create(THIS_MODULE
, "wmtWifi");
544 if (IS_ERR(wmtWifi_class
))
546 wmtWifi_dev
= device_create(wmtWifi_class
, NULL
, dev
, NULL
, "wmtWifi");
547 if (IS_ERR(wmtWifi_dev
))
551 sema_init(&wr_mtx
, 1);
553 WIFI_INFO_FUNC("%s driver(major %d) installed.\n", WIFI_DRIVER_NAME
, WIFI_major
);
555 wlan_mode
= WLAN_MODE_HALT
;
556 pf_set_p2p_mode
= NULL
;
562 if (!IS_ERR(wmtWifi_dev
))
563 device_destroy(wmtWifi_class
, dev
);
564 if (!IS_ERR(wmtWifi_class
)) {
565 class_destroy(wmtWifi_class
);
566 wmtWifi_class
= NULL
;
571 cdev_del(&WIFI_cdev
);
574 if (alloc_ret
== 0) {
575 unregister_chrdev_region(dev
, WIFI_devs
);
581 static void WIFI_exit(void)
583 dev_t dev
= MKDEV(WIFI_major
, 0);
587 device_destroy(wmtWifi_class
, dev
);
588 class_destroy(wmtWifi_class
);
589 wmtWifi_class
= NULL
;
592 cdev_del(&WIFI_cdev
);
593 unregister_chrdev_region(dev
, WIFI_devs
);
595 WIFI_INFO_FUNC("%s driver removed.\n", WIFI_DRIVER_NAME
);
599 #ifdef MTK_WCN_REMOVE_KERNEL_MODULE
600 INT32
mtk_wcn_wmt_wifi_init(VOID
)
605 VOID
mtk_wcn_wmt_wifi_exit(VOID
)
609 EXPORT_SYMBOL(mtk_wcn_wmt_wifi_init
);
610 EXPORT_SYMBOL(mtk_wcn_wmt_wifi_exit
);
612 module_init(WIFI_init
);
613 module_exit(WIFI_exit
);