add rk3288 pinctrl dts code
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / combo_mt66xx / mt6620 / wlan / os / linux / platform.c
1 /*
2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/platform.c#1 $
3 */
4
5 /*! \file   "platform.c"
6     \brief  This file including the protocol layer privacy function.
7
8     This file provided the macros and functions library support for the
9     protocol layer security setting from wlan_oid.c and for parse.c and
10     rsn.c and nic_privacy.c
11
12 */
13
14
15
16 /*
17 ** $Log: platform.c $
18  *
19  * 11 14 2011 cm.chang
20  * NULL
21  * Fix compiling warning
22  *
23  * 11 10 2011 cp.wu
24  * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
25  * 1. eliminaite direct calls to printk in porting layer.
26  * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
27  *
28  * 09 13 2011 jeffrey.chang
29  * [WCXRP00000983] [MT6620][Wi-Fi Driver] invalid pointer casting causes kernel panic during p2p connection
30  * fix the pointer casting
31  *
32  * 06 29 2011 george.huang
33  * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
34  * .
35  *
36  * 06 28 2011 george.huang
37  * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
38  * remove un-used code
39  *
40  * 05 11 2011 jeffrey.chang
41  * NULL
42  * fix build error
43  *
44  * 05 09 2011 jeffrey.chang
45  * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change
46  * support ARP filter through kernel notifier
47  *
48  * 04 08 2011 pat.lu
49  * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver
50  * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile settting for PC Linux driver
51  *
52  * 03 22 2011 pat.lu
53  * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build
54  * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment.
55  *
56  * 03 21 2011 cp.wu
57  * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
58  * improve portability for awareness of early version of linux kernel and wireless extension.
59  *
60  * 03 18 2011 jeffrey.chang
61  * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
62  * remove early suspend functions
63  *
64  * 03 03 2011 jeffrey.chang
65  * NULL
66  * add the ARP filter callback
67  *
68  * 02 15 2011 jeffrey.chang
69  * NULL
70  * to support early suspend in android
71  *
72  * 02 01 2011 cp.wu
73  * [WCXRP00000413] [MT6620 Wi-Fi][Driver] Merge 1103 changes on NVRAM file path change to DaVinci main trunk and V1.1 branch
74  * upon Jason Zhang(NVRAM owner)'s change, ALPS has modified its NVRAM storage from /nvram/... to /data/nvram/...
75  *
76  * 11 01 2010 cp.wu
77  * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module
78  * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead
79  * 2) Remove CNM CH-RECOVER event handling
80  * 3) cfg read/write API renamed with kal prefix for unified naming rules.
81  *
82  * 10 18 2010 cp.wu
83  * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android
84  * complete implementation of Android NVRAM access
85  *
86  * 10 05 2010 cp.wu
87  * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check
88  * 1) add NVRAM access API
89  * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option)
90  * 3) add OID implementation for NVRAM read/write service
91  *
92 **
93 */
94 /*******************************************************************************
95 *                         C O M P I L E R   F L A G S
96 ********************************************************************************
97 */
98
99 /*******************************************************************************
100 *                    E X T E R N A L   R E F E R E N C E S
101 ********************************************************************************
102 */
103 #include <linux/version.h>
104 #include <linux/init.h>
105 #include <linux/types.h>
106 #include <linux/module.h>
107 #include <linux/fs.h>
108
109 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
110     #include <linux/uaccess.h>
111 #endif
112
113 #include "gl_os.h"
114
115 #ifndef CONFIG_X86
116 #if defined(CONFIG_HAS_EARLY_SUSPEND)
117     #include <linux/earlysuspend.h>
118 #endif
119 #endif
120
121     extern atomic_t fgIsUnderEarlierSuspend;
122
123 /*******************************************************************************
124 *                              C O N S T A N T S
125 ********************************************************************************
126 */
127 #define WIFI_NVRAM_FILE_NAME   "/data/nvram/APCFG/APRDEB/WIFI"
128 #define WIFI_NVRAM_CUSTOM_NAME "/data/nvram/APCFG/APRDEB/WIFI_CUSTOM"
129
130
131 /*******************************************************************************
132 *                             D A T A   T Y P E S
133 ********************************************************************************
134 */
135
136 /*******************************************************************************
137 *                            P U B L I C   D A T A
138 ********************************************************************************
139 */
140
141 /*******************************************************************************
142 *                           P R I V A T E   D A T A
143 ********************************************************************************
144 */
145
146 /*******************************************************************************
147 *                                 M A C R O S
148 ********************************************************************************
149 */
150
151 /*******************************************************************************
152 *                   F U N C T I O N   D E C L A R A T I O N S
153 ********************************************************************************
154 */
155
156 /*******************************************************************************
157 *                              F U N C T I O N S
158 ********************************************************************************
159 */
160
161
162
163 static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
164 {
165    struct in_device *in_dev;
166     UINT_8  ip[4] = { 0 };
167     UINT_32 u4NumIPv4 = 0;
168 //#ifdef  CONFIG_IPV6
169 #if 0
170     UINT_8  ip6[16] = { 0 };     // FIX ME: avoid to allocate large memory in stack
171     UINT_32 u4NumIPv6 = 0;
172 #endif
173     struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
174     struct net_device *prDev = ifa->ifa_dev->dev;
175     UINT_32 i;
176     P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr;
177     P_GLUE_INFO_T prGlueInfo = NULL;
178
179     if (prDev == NULL) {
180         DBGLOG(REQ, INFO, ("netdev_event: device is empty.\n"));
181         return NOTIFY_DONE;
182     }
183
184     if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) {
185         DBGLOG(REQ, INFO, ("netdev_event: xxx\n"));
186         return NOTIFY_DONE;
187     }
188
189     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
190
191     if (prGlueInfo == NULL) {
192         DBGLOG(REQ, INFO, ("netdev_event: prGlueInfo is empty.\n"));
193         return NOTIFY_DONE;
194     }
195     ASSERT(prGlueInfo);
196
197            // <3> get the IPv4 address    
198            in_dev = in_dev_get(prDev);
199            if (!in_dev)
200               return;
201            
202            //rtnl_lock();                  
203            if(!in_dev->ifa_list ||!in_dev->ifa_list->ifa_local) {
204                   //rtnl_unlock();
205                   in_dev_put(in_dev);
206                   DBGLOG(REQ, INFO, ("ip is not avaliable.\n"));
207                   return;
208               }
209            // <4> copy the IPv4 address
210            kalMemCopy(ip, &(in_dev->ifa_list->ifa_local), sizeof(ip));
211            //rtnl_unlock();
212            in_dev_put(in_dev);
213
214     DBGLOG(REQ, INFO, ("ip is %d.%d.%d.%d\n",
215             ip[0],ip[1],ip[2],ip[3]));
216
217     // todo: traverse between list to find whole sets of IPv4 addresses
218     if (!((ip[0] == 0) &&
219          (ip[1] == 0) &&
220          (ip[2] == 0) &&
221          (ip[3] == 0))) {
222         u4NumIPv4++;
223     }
224
225 #if defined(MTK_WLAN_ARP_OFFLOAD)
226         if(NETDEV_UP == notification && PARAM_MEDIA_STATE_CONNECTED == prGlueInfo->eParamMediaStateIndicated){
227                 PARAM_CUSTOM_SW_CTRL_STRUC_T SwCtrlInfo;
228                 UINT_32 u4SetInfoLen;
229                 WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
230                 
231                 SwCtrlInfo.u4Id = 0x90110000;
232                 SwCtrlInfo.u4Data = 1;
233                 
234                 rStatus = kalIoctl(prGlueInfo,
235                 wlanoidSetSwCtrlWrite,
236                 (PVOID)&SwCtrlInfo,
237                 sizeof(SwCtrlInfo),
238                 FALSE,
239                 FALSE,
240                 TRUE,
241                 FALSE,
242                 &u4SetInfoLen);
243
244      if (rStatus != WLAN_STATUS_SUCCESS) {
245                 DBGLOG(REQ, INFO, ("ARP OFFLOAD fail 0x%lx\n", rStatus));
246      }else{
247                 DBGLOG(REQ, INFO, ("ARP OFFLOAD success\n"));                   
248     }     
249   }
250 #endif
251     
252        if(atomic_read(&fgIsUnderEarlierSuspend)==0){
253
254                                 DBGLOG(REQ, INFO, ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", prGlueInfo->eParamMediaStateIndicated));
255                                 return NOTIFY_DONE;
256     }
257
258 //#ifdef  CONFIG_IPV6
259 #if 0
260     if(!prDev || !(prDev->ip6_ptr)||\
261         !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\
262         !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){
263         printk(KERN_INFO "ipv6 is not avaliable.\n");
264         return NOTIFY_DONE;
265     }
266
267     kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6));
268     printk(KERN_INFO"ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n",
269             ip6[0],ip6[1],ip6[2],ip6[3],
270             ip6[4],ip6[5],ip6[6],ip6[7],
271             ip6[8],ip6[9],ip6[10],ip6[11],
272             ip6[12],ip6[13],ip6[14],ip6[15]
273             );
274
275     // todo: traverse between list to find whole sets of IPv6 addresses
276     if (!((ip6[0] == 0) &&
277          (ip6[1] == 0) &&
278          (ip6[2] == 0) &&
279          (ip6[3] == 0) &&
280          (ip6[4] == 0) &&
281          (ip6[5] == 0))) {
282         //u4NumIPv6++;
283     }
284 #endif
285
286     // here we can compare the dev with other network's netdev to
287     // set the proper arp filter
288     //
289     // IMPORTANT: please make sure if the context can sleep, if the context can't sleep
290     // we should schedule a kernel thread to do this for us
291
292     // <7> set up the ARP filter
293     {
294         WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
295         UINT_32 u4SetInfoLen = 0;
296         UINT_8 aucBuf[32] = {0};
297         UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress);
298         P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)aucBuf;
299         P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress;
300
301 //#ifdef  CONFIG_IPV6
302 #if 0
303         prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6;
304 #else
305         prParamNetAddrList->u4AddressCount = u4NumIPv4;
306 #endif
307         prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;
308         for (i = 0; i < u4NumIPv4; i++) {
309             prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP);//4;;
310             prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;;
311 #if 0
312             kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip));
313             prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip));
314             u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip);
315 #else
316             prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP)prParamNetAddr->aucAddress;
317             kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip));
318             prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS));
319             u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS);
320 #endif
321         }
322 //#ifdef  CONFIG_IPV6
323 #if 0
324         for (i = 0; i < u4NumIPv6; i++) {
325             prParamNetAddr->u2AddressLength = 6;;
326             prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;;
327             kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6));
328             prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6));
329             u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6);
330        }
331 #endif
332         ASSERT(u4Len <= sizeof(aucBuf));
333
334     DBGLOG(REQ, INFO, ("kalIoctl (0x%x, 0x%x)\n", prGlueInfo, prParamNetAddrList));
335
336         rStatus = kalIoctl(prGlueInfo,
337                 wlanoidSetNetworkAddress,
338                 (PVOID)prParamNetAddrList,
339                 u4Len,
340                 FALSE,
341                 FALSE,
342                 TRUE,
343                 FALSE,
344                 &u4SetInfoLen);
345
346         if (rStatus != WLAN_STATUS_SUCCESS) {
347             DBGLOG(REQ, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus));
348         }
349     }
350
351     return NOTIFY_DONE;
352
353 }
354
355 static struct notifier_block inetaddr_notifier = {
356     .notifier_call      =   netdev_event,
357 };
358
359 void wlanRegisterNotifier(void)
360 {
361     register_inetaddr_notifier(&inetaddr_notifier);
362 }
363
364 //EXPORT_SYMBOL(wlanRegisterNotifier);
365
366 void wlanUnregisterNotifier(void)
367 {
368     unregister_inetaddr_notifier(&inetaddr_notifier);
369 }
370
371 //EXPORT_SYMBOL(wlanUnregisterNotifier);
372
373 #ifndef CONFIG_X86
374 #if defined(CONFIG_HAS_EARLYSUSPEND)
375
376
377 /*----------------------------------------------------------------------------*/
378 /*!
379 * \brief This function will register platform driver to os
380 *
381 * \param[in] wlanSuspend    Function pointer to platform suspend function
382 * \param[in] wlanResume   Function pointer to platform resume   function
383 *
384 * \return The result of registering earlysuspend
385 */
386 /*----------------------------------------------------------------------------*/
387
388 int glRegisterEarlySuspend(
389     struct early_suspend        *prDesc,
390     early_suspend_callback      wlanSuspend,
391     late_resume_callback        wlanResume)
392 {
393     int ret = 0;
394
395     if(NULL != wlanSuspend)
396         prDesc->suspend = wlanSuspend;
397     else{
398         DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanSuspend ERROR.\n"));
399         ret = -1;
400     }
401
402     if(NULL != wlanResume)
403         prDesc->resume = wlanResume;
404     else{
405         DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanResume ERROR.\n"));
406         ret = -1;
407     }
408
409     register_early_suspend(prDesc);
410     return ret;
411 }
412
413 //EXPORT_SYMBOL(glRegisterEarlySuspend);
414
415 /*----------------------------------------------------------------------------*/
416 /*!
417 * \brief This function will un-register platform driver to os
418 *
419 * \return The result of un-registering earlysuspend
420 */
421 /*----------------------------------------------------------------------------*/
422
423 int glUnregisterEarlySuspend(struct early_suspend *prDesc)
424 {
425     int ret = 0;
426
427     unregister_early_suspend(prDesc);
428
429     prDesc->suspend = NULL;
430     prDesc->resume = NULL;
431
432     return ret;
433 }
434
435 //EXPORT_SYMBOL(glUnregisterEarlySuspend);
436 #endif
437 #endif // !CONFIG_X86
438
439 /*----------------------------------------------------------------------------*/
440 /*!
441 * \brief Utility function for reading data from files on NVRAM-FS
442 *
443 * \param[in]
444 *           filename
445 *           len
446 *           offset
447 * \param[out]
448 *           buf
449 * \return
450 *           actual length of data being read
451 */
452 /*----------------------------------------------------------------------------*/
453 static int
454 nvram_read(
455     char *filename,
456     char *buf,
457     ssize_t len,
458     int offset)
459 {
460 #if CFG_SUPPORT_NVRAM
461     struct file *fd;
462     int retLen = -1;
463
464     mm_segment_t old_fs = get_fs();
465     set_fs(KERNEL_DS);
466
467     fd = filp_open(filename, O_RDONLY, 0644);
468
469     if(IS_ERR(fd)) {
470         DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : failed to open!!\n"));
471         return -1;
472     }
473
474     do {
475         if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) {
476             DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : file can not be read!!\n"));
477             break;
478         }
479
480         if (fd->f_pos != offset) {
481             if (fd->f_op->llseek) {
482                 if(fd->f_op->llseek(fd, offset, 0) != offset) {
483                     DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : failed to seek!!\n"));
484                     break;
485                 }
486             }
487             else {
488                 fd->f_pos = offset;
489             }
490         }
491
492         retLen = fd->f_op->read(fd,
493                 buf,
494                 len,
495                 &fd->f_pos);
496
497     } while(FALSE);
498
499     filp_close(fd, NULL);
500
501     set_fs(old_fs);
502
503     return retLen;
504
505 #else // !CFG_SUPPORT_NVRAM
506
507     return -EIO;
508
509 #endif
510 }
511
512
513 /*----------------------------------------------------------------------------*/
514 /*!
515 * \brief Utility function for writing data to files on NVRAM-FS
516 *
517 * \param[in]
518 *           filename
519 *           buf
520 *           len
521 *           offset
522 * \return
523 *           actual length of data being written
524 */
525 /*----------------------------------------------------------------------------*/
526 static int
527 nvram_write (
528     char *filename,
529     char *buf,
530     ssize_t len,
531     int offset)
532 {
533 #if CFG_SUPPORT_NVRAM
534     struct file *fd;
535     int retLen = -1;
536
537     mm_segment_t old_fs = get_fs();
538     set_fs(KERNEL_DS);
539
540     fd = filp_open(filename, O_WRONLY|O_CREAT, 0644);
541
542     if(IS_ERR(fd)) {
543         DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : failed to open!!\n"));
544         return -1;
545     }
546
547     do{
548         if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) {
549             DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : file can not be write!!\n"));
550             break;
551         } /* End of if */
552
553         if (fd->f_pos != offset) {
554             if (fd->f_op->llseek) {
555                 if(fd->f_op->llseek(fd, offset, 0) != offset) {
556                     DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : failed to seek!!\n"));
557                     break;
558                 }
559             }
560             else {
561                 fd->f_pos = offset;
562             }
563         }
564
565         retLen = fd->f_op->write(fd,
566                 buf,
567                 len,
568                 &fd->f_pos);
569
570     } while(FALSE);
571
572     filp_close(fd, NULL);
573
574     set_fs(old_fs);
575
576     return retLen;
577
578 #else // !CFG_SUPPORT_NVRAMS
579
580     return -EIO;
581
582 #endif
583 }
584
585
586 /*----------------------------------------------------------------------------*/
587 /*!
588 * \brief API for reading data on NVRAM
589 *
590 * \param[in]
591 *           prGlueInfo
592 *           u4Offset
593 * \param[out]
594 *           pu2Data
595 * \return
596 *           TRUE
597 *           FALSE
598 */
599 /*----------------------------------------------------------------------------*/
600 BOOLEAN
601 kalCfgDataRead16(
602     IN P_GLUE_INFO_T    prGlueInfo,
603     IN UINT_32          u4Offset,
604     OUT PUINT_16        pu2Data
605     )
606 {
607     if(pu2Data == NULL) {
608         return FALSE;
609     }
610
611     if(nvram_read(WIFI_NVRAM_FILE_NAME,
612                 (char *)pu2Data,
613                 sizeof(unsigned short),
614                 u4Offset) != sizeof(unsigned short)) {
615         return FALSE;
616     }
617     else {
618         return TRUE;
619     }
620 }
621
622
623 /*----------------------------------------------------------------------------*/
624 /*!
625 * \brief API for writing data on NVRAM
626 *
627 * \param[in]
628 *           prGlueInfo
629 *           u4Offset
630 *           u2Data
631 * \return
632 *           TRUE
633 *           FALSE
634 */
635 /*----------------------------------------------------------------------------*/
636 BOOLEAN
637 kalCfgDataWrite16(
638     IN P_GLUE_INFO_T    prGlueInfo,
639     UINT_32             u4Offset,
640     UINT_16             u2Data
641     )
642 {
643     if(nvram_write(WIFI_NVRAM_FILE_NAME,
644                 (char *)&u2Data,
645                 sizeof(unsigned short),
646                 u4Offset) != sizeof(unsigned short)) {
647         return FALSE;
648     }
649     else {
650         return TRUE;
651     }
652 }
653
654