support different wifi bt chip auto compatible
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / mt5931_kk / drv_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  * 1. add code to put whole-chip resetting trigger when abnormal firmware assertion is detected
69  * 2. add dummy function for both Win32 and Linux part.
70  *
71  * 03 30 2011 cp.wu
72  * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events
73  * use netlink unicast instead of broadcast
74  *
75 **
76 */
77
78 /*******************************************************************************
79 *                         C O M P I L E R   F L A G S
80 ********************************************************************************
81 */
82
83 /*******************************************************************************
84 *                    E X T E R N A L   R E F E R E N C E S
85 ********************************************************************************
86 */
87 #include "gl_os.h"
88 #include "debug.h"
89 #include "wlan_lib.h"
90 #include "gl_wext.h"
91 #include "precomp.h"
92 #include <linux/poll.h>
93 #include <net/netlink.h>
94 #include <net/genetlink.h>
95
96 #if CFG_CHIP_RESET_SUPPORT
97
98 /*******************************************************************************
99 *                              C O N S T A N T S
100 ********************************************************************************
101 */
102 #define MAX_BIND_PROCESS    (4)
103
104 #define MTK_WIFI_FAMILY_NAME        "MTK_WIFI"
105 #define MTK_WIFI_RESET_START_NAME   "RESET_START"
106 #define MTK_WIFI_RESET_END_NAME     "RESET_END"
107 #define MTK_WIFI_RESET_TEST_NAME    "GENETLINK_START"
108
109
110 /*******************************************************************************
111 *                             D A T A   T Y P E S
112 ********************************************************************************
113 */
114 enum {
115     __MTK_WIFI_ATTR_INVALID,
116     MTK_WIFI_ATTR_MSG,
117     __MTK_WIFI_ATTR_MAX,
118 };
119 #define MTK_WIFI_ATTR_MAX       (__MTK_WIFI_ATTR_MAX - 1)
120
121
122 enum {
123     __MTK_WIFI_COMMAND_INVALID,
124     MTK_WIFI_COMMAND_BIND,
125     MTK_WIFI_COMMAND_RESET,
126     __MTK_WIFI_COMMAND_MAX,
127 };
128 #define MTK_WIFI_COMMAND_MAX    (__MTK_WIFI_COMMAND_MAX - 1)
129
130 /*******************************************************************************
131 *                            P U B L I C   D A T A
132 ********************************************************************************
133 */
134 BOOLEAN fgIsResetting = FALSE;
135
136 /*******************************************************************************
137 *                           P R I V A T E   D A T A
138 ********************************************************************************
139 */
140 static UINT_32 mtk_wifi_seqnum = 0;
141 static int num_bind_process = 0;
142 static pid_t bind_pid[MAX_BIND_PROCESS];
143
144
145 /* attribute policy */
146 static struct nla_policy mtk_wifi_genl_policy[MTK_WIFI_ATTR_MAX + 1] = {
147     [MTK_WIFI_ATTR_MSG] = { .type = NLA_NUL_STRING },
148 };
149
150 /* family definition */
151 static struct genl_family mtk_wifi_gnl_family = {
152     .id         = GENL_ID_GENERATE,
153     .hdrsize    = 0,
154     .name       = MTK_WIFI_FAMILY_NAME,
155     .version    = 1,
156     .maxattr    = MTK_WIFI_ATTR_MAX,
157 };
158
159 /* forward declaration */
160 static int mtk_wifi_bind(
161     struct sk_buff *skb,
162     struct genl_info *info
163     );
164
165 static int mtk_wifi_reset(
166     struct sk_buff *skb,
167     struct genl_info *info
168     );
169
170 /* operation definition */
171 static struct genl_ops mtk_wifi_gnl_ops_bind = {
172     .cmd = MTK_WIFI_COMMAND_BIND,
173     .flags  = 0,
174     .policy = mtk_wifi_genl_policy,
175     .doit   = mtk_wifi_bind,
176     .dumpit = NULL,
177 };
178
179 static struct genl_ops mtk_wifi_gnl_ops_reset = {
180     .cmd = MTK_WIFI_COMMAND_RESET,
181     .flags  = 0,
182     .policy = mtk_wifi_genl_policy,
183     .doit   = mtk_wifi_reset,
184     .dumpit = NULL,
185 };
186
187
188 /*******************************************************************************
189 *                                 M A C R O S
190 ********************************************************************************
191 */
192
193 /*******************************************************************************
194 *                   F U N C T I O N   D E C L A R A T I O N S
195 ********************************************************************************
196 */
197 extern int
198 mtk_wcn_wmt_msgcb_reg(
199     ENUM_WMTDRV_TYPE_T eType,
200     PF_WMT_CB pCb);
201
202 extern int
203 mtk_wcn_wmt_msgcb_unreg(
204     ENUM_WMTDRV_TYPE_T eType
205     );
206
207 static void *
208 glResetCallback (
209     ENUM_WMTDRV_TYPE_T  eSrcType,
210     ENUM_WMTDRV_TYPE_T  eDstType,
211     ENUM_WMTMSG_TYPE_T  eMsgType,
212     void *              prMsgBody,
213     unsigned int        u4MsgLength
214     );
215
216 static BOOLEAN
217 glResetSendMessage (
218     char    *aucMsg,
219     u8      cmd
220     );
221
222
223 /*******************************************************************************
224 *                              F U N C T I O N S
225 ********************************************************************************
226 */
227 /*----------------------------------------------------------------------------*/
228 /*!
229  * @brief This routine is responsible for 
230  *        1. registering for reset callbacks
231  *        2. initialize netlink socket 
232  *
233  * @param none
234  *
235  * @retval none
236  */
237 /*----------------------------------------------------------------------------*/
238 VOID
239 glResetInit(
240     VOID
241     )
242 {
243     /* 1. register for reset callback */
244     mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_WIFI, (PF_WMT_CB)glResetCallback);
245
246     /* 2.1 registration for NETLINK_GENERIC family */
247     if(genl_register_family(&mtk_wifi_gnl_family) != 0) {
248         DBGLOG(INIT, WARN, ("%s(): GE_NELINK family registration fail\n", __func__));
249     }
250     else {
251         /* 2.2 operation registration */
252         if(genl_register_ops(&mtk_wifi_gnl_family, &mtk_wifi_gnl_ops_bind) != 0) {
253             DBGLOG(INIT, WARN, ("%s(): BIND operation registration fail\n", __func__));
254         }
255
256         if(genl_register_ops(&mtk_wifi_gnl_family, &mtk_wifi_gnl_ops_reset) != 0) {
257             DBGLOG(INIT, WARN, ("%s(): RESET operation registration fail\n", __func__));
258         }
259     }
260
261     return;
262 }
263
264
265 /*----------------------------------------------------------------------------*/
266 /*!
267  * @brief This routine is responsible for 
268  *        1. uninitialize netlink socket 
269  *        2. deregistering for reset callbacks
270  *
271  * @param none
272  *
273  * @retval none
274  */
275 /*----------------------------------------------------------------------------*/
276 VOID
277 glResetUninit(
278     VOID
279     )
280 {
281     /* 1. release NETLINK_GENERIC family */
282     genl_unregister_family(&mtk_wifi_gnl_family);
283
284     /* 2. deregister for reset callback */
285     mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_WIFI);
286
287     return;
288 }
289
290
291 /*----------------------------------------------------------------------------*/
292 /*!
293  * @brief This routine is invoked when there is reset messages indicated
294  *
295  * @param   eSrcType
296  *          eDstType
297  *          eMsgType
298  *          prMsgBody
299  *          u4MsgLength
300  *
301  * @retval 
302  */
303 /*----------------------------------------------------------------------------*/
304 static void *
305 glResetCallback (
306     ENUM_WMTDRV_TYPE_T  eSrcType,
307     ENUM_WMTDRV_TYPE_T  eDstType,
308     ENUM_WMTMSG_TYPE_T  eMsgType,
309     void *              prMsgBody,
310     unsigned int        u4MsgLength
311     )
312 {
313     switch(eMsgType) {
314     case WMTMSG_TYPE_RESET:
315         if(u4MsgLength == sizeof(ENUM_WMTRSTMSG_TYPE_T)) {
316             P_ENUM_WMTRSTMSG_TYPE_T prRstMsg = (P_ENUM_WMTRSTMSG_TYPE_T) prMsgBody;
317
318             switch(*prRstMsg) {
319             case WMTRSTMSG_RESET_START:
320                 fgIsResetting = TRUE;
321                 glResetSendMessage(MTK_WIFI_RESET_START_NAME, MTK_WIFI_COMMAND_RESET);
322                 break;
323
324             case WMTRSTMSG_RESET_END:
325                 glResetSendMessage(MTK_WIFI_RESET_END_NAME, MTK_WIFI_COMMAND_RESET);
326                 fgIsResetting = FALSE;
327                 break;
328
329             default:
330                 break;
331             }
332         }
333
334         break;
335
336     default:
337         break;
338     }
339
340     return NULL;
341 }
342
343
344 /*----------------------------------------------------------------------------*/
345 /*!
346  * @brief This routine send out message via netlink socket
347  *
348  * @param   aucMsg
349  *          u4MsgLength
350  *
351  * @retval  TRUE
352  *          FALSE
353  */
354 /*----------------------------------------------------------------------------*/
355 static BOOLEAN
356 glResetSendMessage(
357     char *  aucMsg,
358     u8      cmd
359     )
360 {
361     struct sk_buff *skb = NULL;
362     void *msg_head = NULL;
363     int rc = -1;
364     int i;
365
366     if(num_bind_process == 0) {
367         /* no listening process */
368         return FALSE;
369     }
370
371     for(i = 0 ; i < num_bind_process ; i++) {
372         skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
373
374         if(skb) {
375             msg_head = genlmsg_put(skb, 0, mtk_wifi_seqnum++, &mtk_wifi_gnl_family, 0, cmd);
376
377             if(msg_head == NULL) {
378                 nlmsg_free(skb);
379                 return FALSE;
380             }
381
382             rc = nla_put_string(skb, MTK_WIFI_ATTR_MSG, aucMsg);
383             if(rc != 0) {
384                 nlmsg_free(skb);
385                 return FALSE;
386             }
387         
388             /* finalize the message */
389             genlmsg_end(skb, msg_head);
390         
391             /* sending message */
392             rc = genlmsg_unicast(&init_net, skb, bind_pid[i]);
393             if(rc != 0) {
394                 return FALSE;
395             }
396         }
397         else {
398             return FALSE;
399         }
400     }
401
402     return TRUE;
403 }
404
405
406 /*----------------------------------------------------------------------------*/
407 /*!
408  * @brief This routine is called to identify PID for process binding
409  *
410  * @param   skb
411  *          info
412  *
413  * @retval  0
414  *          nonzero
415  */
416 /*----------------------------------------------------------------------------*/
417 int mtk_wifi_bind(
418     struct sk_buff *skb,
419     struct genl_info *info
420     )
421 {
422     struct nlattr *na;
423     char * mydata;
424
425     if (info == NULL) {
426         goto out;
427     }
428
429     /*for each attribute there is an index in info->attrs which points to a nlattr structure
430      *in this structure the data is given
431      */
432     
433     na = info->attrs[MTK_WIFI_ATTR_MSG];
434     if (na) {
435         mydata = (char *)nla_data(na);
436
437         /* no need to parse mydata */
438     }
439
440     /* collect PID */
441     if(num_bind_process < MAX_BIND_PROCESS) {
442         bind_pid[num_bind_process] = info->snd_pid;
443         num_bind_process++;
444         }
445     else {
446         DBGLOG(INIT, WARN, ("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS));
447     }
448
449 out:
450     return 0;
451 }
452
453
454 /*----------------------------------------------------------------------------*/
455 /*!
456  * @brief This routine is called for reset, shout not happen
457  *
458  * @param   skb
459  *          info
460  *
461  * @retval  0
462  *          nonzero
463  */
464 /*----------------------------------------------------------------------------*/
465 int mtk_wifi_reset(
466     struct sk_buff *skb,
467     struct genl_info *info
468     )
469 {
470     DBGLOG(INIT, WARN, ("%s(): should not be invoked\n", __func__));
471
472     return 0;
473 }
474
475
476 /*----------------------------------------------------------------------------*/
477 /*!
478  * @brief This routine is called for generating reset request to WMT
479  *
480  * @param   None
481  *
482  * @retval  None
483  */
484 /*----------------------------------------------------------------------------*/
485 VOID
486 glSendResetRequest(
487     VOID
488     )
489 {
490     // WMT thread would trigger whole chip resetting itself
491     return;
492 }
493
494
495 /*----------------------------------------------------------------------------*/
496 /*!
497  * @brief This routine is called for checking if MT6620 is resetting
498  *
499  * @param   None
500  *
501  * @retval  TRUE
502  *          FALSE
503  */
504 /*----------------------------------------------------------------------------*/
505 BOOLEAN
506 kalIsResetting(
507     VOID
508     )
509 {
510     return fgIsResetting;
511 }
512
513
514 #endif // CFG_CHIP_RESET_SUPPORT