add MTK-combo-module,continue with commit 17f39ed917874e77e80411f33faba1b7ee8138c8
[firefly-linux-kernel-4.4.55.git] / drivers / mtk_wcn_combo / drv_wlan / wlan / os / linux / gl_rst.c
1 /*
2 ** $Id: @(#) gl_rst.c@@
3 */
4
5 /*! \file   gl_rst.c
6     \brief  Main routines for supporintg MT6620 whole-chip reset mechanism
7
8     This file contains the support routines of Linux driver for MediaTek Inc. 802.11
9     Wireless LAN Adapters.
10 */
11
12 /*******************************************************************************
13 * Copyright (c) 2007 MediaTek Inc.
14 *
15 * All rights reserved. Copying, compilation, modification, distribution
16 * or any other use whatsoever of this material is strictly prohibited
17 * except in accordance with a Software License Agreement with
18 * MediaTek Inc.
19 ********************************************************************************
20 */
21
22 /*******************************************************************************
23 * LEGAL DISCLAIMER
24 *
25 * BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND
26 * AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK
27 * SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE
28 * PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY
29 * DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
30 * LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
31 * PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE
32 * ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
33 * WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK
34 * SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY
35 * WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE
36 * FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO
37 * CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
38 *
39 * BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
40 * LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL
41 * BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT
42 * ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY
43 * BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
44 *
45 * THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
46 * WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT
47 * OF LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING
48 * THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN
49 * FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE
50 * (ICC).
51 ********************************************************************************
52 */
53
54 /*
55 ** $Log: gl_rst.c $
56  *
57  * 11 10 2011 cp.wu
58  * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
59  * 1. eliminaite direct calls to printk in porting layer.
60  * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
61  *
62  * 04 22 2011 cp.wu
63  * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events
64  * skip power-off handshaking when RESET indication is received.
65  *
66  * 04 14 2011 cp.wu
67  * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events
68  * sync. whole-chip resetting mechanism to V2.0 branch.
69  *
70  * 04 14 2011 cp.wu
71  * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events
72  * 1. add code to put whole-chip resetting trigger when abnormal firmware assertion is detected
73  * 2. add dummy function for both Win32 and Linux part.
74  *
75  * 03 30 2011 cp.wu
76  * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events
77  * use netlink unicast instead of broadcast
78  *
79 **
80 */
81
82 /*******************************************************************************
83 *                         C O M P I L E R   F L A G S
84 ********************************************************************************
85 */
86
87 /*******************************************************************************
88 *                    E X T E R N A L   R E F E R E N C E S
89 ********************************************************************************
90 */
91 #include "gl_os.h"
92 #include "debug.h"
93 #include "wlan_lib.h"
94 #include "gl_wext.h"
95 #include "precomp.h"
96 #include <linux/poll.h>
97 #include <net/netlink.h>
98 #include <net/genetlink.h>
99
100 #if CFG_CHIP_RESET_SUPPORT
101
102 /*******************************************************************************
103 *                              C O N S T A N T S
104 ********************************************************************************
105 */
106 #define MAX_BIND_PROCESS    (4)
107
108 #define MTK_WIFI_FAMILY_NAME        "MTK_WIFI"
109 #define MTK_WIFI_RESET_START_NAME   "RESET_START"
110 #define MTK_WIFI_RESET_END_NAME     "RESET_END"
111 #define MTK_WIFI_RESET_TEST_NAME    "GENETLINK_START"
112
113
114 /*******************************************************************************
115 *                             D A T A   T Y P E S
116 ********************************************************************************
117 */
118 enum {
119     __MTK_WIFI_ATTR_INVALID,
120     MTK_WIFI_ATTR_MSG,
121     __MTK_WIFI_ATTR_MAX,
122 };
123 #define MTK_WIFI_ATTR_MAX       (__MTK_WIFI_ATTR_MAX - 1)
124
125
126 enum {
127     __MTK_WIFI_COMMAND_INVALID,
128     MTK_WIFI_COMMAND_BIND,
129     MTK_WIFI_COMMAND_RESET,
130     __MTK_WIFI_COMMAND_MAX,
131 };
132 #define MTK_WIFI_COMMAND_MAX    (__MTK_WIFI_COMMAND_MAX - 1)
133
134 /*******************************************************************************
135 *                            P U B L I C   D A T A
136 ********************************************************************************
137 */
138
139 /*******************************************************************************
140 *                           P R I V A T E   D A T A
141 ********************************************************************************
142 */
143 static UINT_32 mtk_wifi_seqnum = 0;
144 static int num_bind_process = 0;
145 static pid_t bind_pid[MAX_BIND_PROCESS];
146 static BOOLEAN fgIsResetting = FALSE;
147
148 /* attribute policy */
149 static struct nla_policy mtk_wifi_genl_policy[MTK_WIFI_ATTR_MAX + 1] = {
150     [MTK_WIFI_ATTR_MSG] = { .type = NLA_NUL_STRING },
151 };
152
153 /* family definition */
154 static struct genl_family mtk_wifi_gnl_family = {
155     .id         = GENL_ID_GENERATE,
156     .hdrsize    = 0,
157     .name       = MTK_WIFI_FAMILY_NAME,
158     .version    = 1,
159     .maxattr    = MTK_WIFI_ATTR_MAX,
160 };
161
162 /* forward declaration */
163 static int mtk_wifi_bind(
164     struct sk_buff *skb,
165     struct genl_info *info
166     );
167
168 static int mtk_wifi_reset(
169     struct sk_buff *skb,
170     struct genl_info *info
171     );
172
173 /* operation definition */
174 static struct genl_ops mtk_wifi_gnl_ops_bind = {
175     .cmd = MTK_WIFI_COMMAND_BIND,
176     .flags  = 0,
177     .policy = mtk_wifi_genl_policy,
178     .doit   = mtk_wifi_bind,
179     .dumpit = NULL,
180 };
181
182 static struct genl_ops mtk_wifi_gnl_ops_reset = {
183     .cmd = MTK_WIFI_COMMAND_RESET,
184     .flags  = 0,
185     .policy = mtk_wifi_genl_policy,
186     .doit   = mtk_wifi_reset,
187     .dumpit = NULL,
188 };
189
190
191 /*******************************************************************************
192 *                                 M A C R O S
193 ********************************************************************************
194 */
195
196 /*******************************************************************************
197 *                   F U N C T I O N   D E C L A R A T I O N S
198 ********************************************************************************
199 */
200 extern int
201 mtk_wcn_wmt_msgcb_reg(
202     ENUM_WMTDRV_TYPE_T eType,
203     PF_WMT_CB pCb);
204
205 extern int
206 mtk_wcn_wmt_msgcb_unreg(
207     ENUM_WMTDRV_TYPE_T eType
208     );
209
210 static void *
211 glResetCallback (
212     ENUM_WMTDRV_TYPE_T  eSrcType,
213     ENUM_WMTDRV_TYPE_T  eDstType,
214     ENUM_WMTMSG_TYPE_T  eMsgType,
215     void *              prMsgBody,
216     unsigned int        u4MsgLength
217     );
218
219 static BOOLEAN
220 glResetSendMessage (
221     char    *aucMsg,
222     u8      cmd
223     );
224
225
226 /*******************************************************************************
227 *                              F U N C T I O N S
228 ********************************************************************************
229 */
230 /*----------------------------------------------------------------------------*/
231 /*!
232  * @brief This routine is responsible for 
233  *        1. registering for reset callbacks
234  *        2. initialize netlink socket 
235  *
236  * @param none
237  *
238  * @retval none
239  */
240 /*----------------------------------------------------------------------------*/
241 VOID
242 glResetInit(
243     VOID
244     )
245 {
246     /* 1. register for reset callback */
247     mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_WIFI, (PF_WMT_CB)glResetCallback);
248
249     /* 2.1 registration for NETLINK_GENERIC family */
250     if(genl_register_family(&mtk_wifi_gnl_family) != 0) {
251         DBGLOG(INIT, WARN, ("%s(): GE_NELINK family registration fail\n", __func__));
252     }
253     else {
254         /* 2.2 operation registration */
255         if(genl_register_ops(&mtk_wifi_gnl_family, &mtk_wifi_gnl_ops_bind) != 0) {
256             DBGLOG(INIT, WARN, ("%s(): BIND operation registration fail\n", __func__));
257         }
258
259         if(genl_register_ops(&mtk_wifi_gnl_family, &mtk_wifi_gnl_ops_reset) != 0) {
260             DBGLOG(INIT, WARN, ("%s(): RESET operation registration fail\n", __func__));
261         }
262     }
263
264     return;
265 }
266
267
268 /*----------------------------------------------------------------------------*/
269 /*!
270  * @brief This routine is responsible for 
271  *        1. uninitialize netlink socket 
272  *        2. deregistering for reset callbacks
273  *
274  * @param none
275  *
276  * @retval none
277  */
278 /*----------------------------------------------------------------------------*/
279 VOID
280 glResetUninit(
281     VOID
282     )
283 {
284     /* 1. release NETLINK_GENERIC family */
285     genl_unregister_family(&mtk_wifi_gnl_family);
286
287     /* 2. deregister for reset callback */
288     mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_WIFI);
289
290     return;
291 }
292
293
294 /*----------------------------------------------------------------------------*/
295 /*!
296  * @brief This routine is invoked when there is reset messages indicated
297  *
298  * @param   eSrcType
299  *          eDstType
300  *          eMsgType
301  *          prMsgBody
302  *          u4MsgLength
303  *
304  * @retval 
305  */
306 /*----------------------------------------------------------------------------*/
307 static void *
308 glResetCallback (
309     ENUM_WMTDRV_TYPE_T  eSrcType,
310     ENUM_WMTDRV_TYPE_T  eDstType,
311     ENUM_WMTMSG_TYPE_T  eMsgType,
312     void *              prMsgBody,
313     unsigned int        u4MsgLength
314     )
315 {
316     switch(eMsgType) {
317     case WMTMSG_TYPE_RESET:
318         if(u4MsgLength == sizeof(ENUM_WMTRSTMSG_TYPE_T)) {
319             P_ENUM_WMTRSTMSG_TYPE_T prRstMsg = (P_ENUM_WMTRSTMSG_TYPE_T) prMsgBody;
320
321             switch(*prRstMsg) {
322             case WMTRSTMSG_RESET_START:
323                 fgIsResetting = TRUE;
324                 glResetSendMessage(MTK_WIFI_RESET_START_NAME, MTK_WIFI_COMMAND_RESET);
325                 break;
326
327             case WMTRSTMSG_RESET_END:
328                 glResetSendMessage(MTK_WIFI_RESET_END_NAME, MTK_WIFI_COMMAND_RESET);
329                 fgIsResetting = FALSE;
330                 break;
331
332             default:
333                 break;
334             }
335         }
336
337         break;
338
339     default:
340         break;
341     }
342
343     return NULL;
344 }
345
346
347 /*----------------------------------------------------------------------------*/
348 /*!
349  * @brief This routine send out message via netlink socket
350  *
351  * @param   aucMsg
352  *          u4MsgLength
353  *
354  * @retval  TRUE
355  *          FALSE
356  */
357 /*----------------------------------------------------------------------------*/
358 static BOOLEAN
359 glResetSendMessage(
360     char *  aucMsg,
361     u8      cmd
362     )
363 {
364     struct sk_buff *skb = NULL;
365     void *msg_head = NULL;
366     int rc = -1;
367     int i;
368
369     if(num_bind_process == 0) {
370         /* no listening process */
371         return FALSE;
372     }
373
374     for(i = 0 ; i < num_bind_process ; i++) {
375         skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
376
377         if(skb) {
378             msg_head = genlmsg_put(skb, 0, mtk_wifi_seqnum++, &mtk_wifi_gnl_family, 0, cmd);
379
380             if(msg_head == NULL) {
381                 nlmsg_free(skb);
382                 return FALSE;
383             }
384
385             rc = nla_put_string(skb, MTK_WIFI_ATTR_MSG, aucMsg);
386             if(rc != 0) {
387                 nlmsg_free(skb);
388                 return FALSE;
389             }
390         
391             /* finalize the message */
392             genlmsg_end(skb, msg_head);
393         
394             /* sending message */
395             rc = genlmsg_unicast(&init_net, skb, bind_pid[i]);
396             if(rc != 0) {
397                 return FALSE;
398             }
399         }
400         else {
401             return FALSE;
402         }
403     }
404
405     return TRUE;
406 }
407
408
409 /*----------------------------------------------------------------------------*/
410 /*!
411  * @brief This routine is called to identify PID for process binding
412  *
413  * @param   skb
414  *          info
415  *
416  * @retval  0
417  *          nonzero
418  */
419 /*----------------------------------------------------------------------------*/
420 int mtk_wifi_bind(
421     struct sk_buff *skb,
422     struct genl_info *info
423     )
424 {
425     struct nlattr *na;
426     char * mydata;
427
428     if (info == NULL) {
429         goto out;
430     }
431
432     /*for each attribute there is an index in info->attrs which points to a nlattr structure
433      *in this structure the data is given
434      */
435     
436     na = info->attrs[MTK_WIFI_ATTR_MSG];
437     if (na) {
438         mydata = (char *)nla_data(na);
439
440         /* no need to parse mydata */
441     }
442
443     /* collect PID */
444     if(num_bind_process < MAX_BIND_PROCESS) {
445         bind_pid[num_bind_process] = info->snd_pid;
446         num_bind_process++;
447         }
448     else {
449         DBGLOG(INIT, WARN, ("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS));
450     }
451
452 out:
453     return 0;
454 }
455
456
457 /*----------------------------------------------------------------------------*/
458 /*!
459  * @brief This routine is called for reset, shout not happen
460  *
461  * @param   skb
462  *          info
463  *
464  * @retval  0
465  *          nonzero
466  */
467 /*----------------------------------------------------------------------------*/
468 int mtk_wifi_reset(
469     struct sk_buff *skb,
470     struct genl_info *info
471     )
472 {
473     DBGLOG(INIT, WARN, ("%s(): should not be invoked\n", __func__));
474
475     return 0;
476 }
477
478
479 /*----------------------------------------------------------------------------*/
480 /*!
481  * @brief This routine is called for generating reset request to WMT
482  *
483  * @param   None
484  *
485  * @retval  None
486  */
487 /*----------------------------------------------------------------------------*/
488 VOID
489 glSendResetRequest(
490     VOID
491     )
492 {
493     // WMT thread would trigger whole chip resetting itself
494     return;
495 }
496
497
498 /*----------------------------------------------------------------------------*/
499 /*!
500  * @brief This routine is called for checking if MT6620 is resetting
501  *
502  * @param   None
503  *
504  * @retval  TRUE
505  *          FALSE
506  */
507 /*----------------------------------------------------------------------------*/
508 BOOLEAN
509 kalIsResetting(
510     VOID
511     )
512 {
513     return fgIsResetting;
514 }
515
516
517 #endif // CFG_CHIP_RESET_SUPPORT