wifi: renew patch drivers/net/wireless
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / mt5931 / 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
122 extern BOOLEAN fgIsUnderEarlierSuspend;
123
124 /*******************************************************************************
125 *                              C O N S T A N T S
126 ********************************************************************************
127 */
128 #define WIFI_NVRAM_FILE_NAME   "/data/nvram/APCFG/APRDEB/WIFI"
129 #define WIFI_NVRAM_CUSTOM_NAME "/data/nvram/APCFG/APRDEB/WIFI_CUSTOM"
130
131
132 /*******************************************************************************
133 *                             D A T A   T Y P E S
134 ********************************************************************************
135 */
136
137 /*******************************************************************************
138 *                            P U B L I C   D A T A
139 ********************************************************************************
140 */
141
142 /*******************************************************************************
143 *                           P R I V A T E   D A T A
144 ********************************************************************************
145 */
146
147 /*******************************************************************************
148 *                                 M A C R O S
149 ********************************************************************************
150 */
151
152 /*******************************************************************************
153 *                   F U N C T I O N   D E C L A R A T I O N S
154 ********************************************************************************
155 */
156
157 /*******************************************************************************
158 *                              F U N C T I O N S
159 ********************************************************************************
160 */
161
162
163
164 static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
165 {
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     if (fgIsUnderEarlierSuspend == false) {
198         DBGLOG(REQ, INFO, ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", prGlueInfo->eParamMediaStateIndicated));
199         return NOTIFY_DONE;
200     }
201
202
203
204     // <3> get the IPv4 address
205     if(!prDev || !(prDev->ip_ptr)||\
206             !((struct in_device *)(prDev->ip_ptr))->ifa_list||\
207             !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){
208         DBGLOG(REQ, INFO, ("ip is not avaliable.\n"));
209         return NOTIFY_DONE;
210     }
211
212     kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip));
213     DBGLOG(REQ, INFO, ("ip is %d.%d.%d.%d\n",
214             ip[0],ip[1],ip[2],ip[3]));
215
216     // todo: traverse between list to find whole sets of IPv4 addresses
217     if (!((ip[0] == 0) &&
218          (ip[1] == 0) &&
219          (ip[2] == 0) &&
220          (ip[3] == 0))) {
221         u4NumIPv4++;
222     }
223
224 //#ifdef  CONFIG_IPV6
225 #if 0
226     if(!prDev || !(prDev->ip6_ptr)||\
227         !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\
228         !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){
229         printk(KERN_INFO "ipv6 is not avaliable.\n");
230         return NOTIFY_DONE;
231     }
232
233     kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6));
234     printk(KERN_INFO"ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n",
235             ip6[0],ip6[1],ip6[2],ip6[3],
236             ip6[4],ip6[5],ip6[6],ip6[7],
237             ip6[8],ip6[9],ip6[10],ip6[11],
238             ip6[12],ip6[13],ip6[14],ip6[15]
239             );
240
241     // todo: traverse between list to find whole sets of IPv6 addresses
242     if (!((ip6[0] == 0) &&
243          (ip6[1] == 0) &&
244          (ip6[2] == 0) &&
245          (ip6[3] == 0) &&
246          (ip6[4] == 0) &&
247          (ip6[5] == 0))) {
248         //u4NumIPv6++;
249     }
250 #endif
251
252     // here we can compare the dev with other network's netdev to
253     // set the proper arp filter
254     //
255     // IMPORTANT: please make sure if the context can sleep, if the context can't sleep
256     // we should schedule a kernel thread to do this for us
257
258     // <7> set up the ARP filter
259     {
260         WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
261         UINT_32 u4SetInfoLen = 0;
262         UINT_8 aucBuf[32] = {0};
263         UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress);
264         P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)aucBuf;
265         P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress;
266
267 //#ifdef  CONFIG_IPV6
268 #if 0
269         prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6;
270 #else
271         prParamNetAddrList->u4AddressCount = u4NumIPv4;
272 #endif
273         prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;
274         for (i = 0; i < u4NumIPv4; i++) {
275             prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP);//4;;
276             prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;;
277 #if 0
278             kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip));
279             prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip));
280             u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip);
281 #else
282             prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP)prParamNetAddr->aucAddress;
283             kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip));
284             prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS));
285             u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS);
286 #endif
287         }
288 //#ifdef  CONFIG_IPV6
289 #if 0
290         for (i = 0; i < u4NumIPv6; i++) {
291             prParamNetAddr->u2AddressLength = 6;;
292             prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;;
293             kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6));
294             prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6));
295             u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6);
296        }
297 #endif
298         ASSERT(u4Len <= sizeof(aucBuf));
299
300     DBGLOG(REQ, INFO, ("kalIoctl (0x%x, 0x%x)\n", prGlueInfo, prParamNetAddrList));
301
302         rStatus = kalIoctl(prGlueInfo,
303                 wlanoidSetNetworkAddress,
304                 (PVOID)prParamNetAddrList,
305                 u4Len,
306                 FALSE,
307                 FALSE,
308                 TRUE,
309                 FALSE,
310                 &u4SetInfoLen);
311
312         if (rStatus != WLAN_STATUS_SUCCESS) {
313             DBGLOG(REQ, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus));
314         }
315     }
316
317     return NOTIFY_DONE;
318
319 }
320
321 static struct notifier_block inetaddr_notifier = {
322     .notifier_call      =   netdev_event,
323 };
324
325 void wlanRegisterNotifier(void)
326 {
327     register_inetaddr_notifier(&inetaddr_notifier);
328 }
329
330 //EXPORT_SYMBOL(wlanRegisterNotifier);
331
332 void wlanUnregisterNotifier(void)
333 {
334     unregister_inetaddr_notifier(&inetaddr_notifier);
335 }
336
337 //EXPORT_SYMBOL(wlanUnregisterNotifier);
338
339 #ifndef CONFIG_X86
340 #if defined(CONFIG_HAS_EARLYSUSPEND)
341
342
343 /*----------------------------------------------------------------------------*/
344 /*!
345 * \brief This function will register platform driver to os
346 *
347 * \param[in] wlanSuspend    Function pointer to platform suspend function
348 * \param[in] wlanResume   Function pointer to platform resume   function
349 *
350 * \return The result of registering earlysuspend
351 */
352 /*----------------------------------------------------------------------------*/
353
354 int glRegisterEarlySuspend(
355     struct early_suspend        *prDesc,
356     early_suspend_callback      wlanSuspend,
357     late_resume_callback        wlanResume)
358 {
359     int ret = 0;
360
361     if(NULL != wlanSuspend)
362         prDesc->suspend = wlanSuspend;
363     else{
364         DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanSuspend ERROR.\n"));
365         ret = -1;
366     }
367
368     if(NULL != wlanResume)
369         prDesc->resume = wlanResume;
370     else{
371         DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanResume ERROR.\n"));
372         ret = -1;
373     }
374
375     register_early_suspend(prDesc);
376     return ret;
377 }
378
379 //EXPORT_SYMBOL(glRegisterEarlySuspend);
380
381 /*----------------------------------------------------------------------------*/
382 /*!
383 * \brief This function will un-register platform driver to os
384 *
385 * \return The result of un-registering earlysuspend
386 */
387 /*----------------------------------------------------------------------------*/
388
389 int glUnregisterEarlySuspend(struct early_suspend *prDesc)
390 {
391     int ret = 0;
392
393     unregister_early_suspend(prDesc);
394
395     prDesc->suspend = NULL;
396     prDesc->resume = NULL;
397
398     return ret;
399 }
400
401 //EXPORT_SYMBOL(glUnregisterEarlySuspend);
402 #endif
403 #endif // !CONFIG_X86
404
405 /*----------------------------------------------------------------------------*/
406 /*!
407 * \brief Utility function for reading data from files on NVRAM-FS
408 *
409 * \param[in]
410 *           filename
411 *           len
412 *           offset
413 * \param[out]
414 *           buf
415 * \return
416 *           actual length of data being read
417 */
418 /*----------------------------------------------------------------------------*/
419 static int
420 nvram_read(
421     char *filename,
422     char *buf,
423     ssize_t len,
424     int offset)
425 {
426 #if CFG_SUPPORT_NVRAM
427     struct file *fd;
428     int retLen = -1;
429
430     mm_segment_t old_fs = get_fs();
431     set_fs(KERNEL_DS);
432
433     fd = filp_open(filename, O_RDONLY, 0644);
434
435     if(IS_ERR(fd)) {
436         DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : failed to open!!\n"));
437         return -1;
438     }
439
440     do {
441         if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) {
442             DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : file can not be read!!\n"));
443             break;
444         }
445
446         if (fd->f_pos != offset) {
447             if (fd->f_op->llseek) {
448                 if(fd->f_op->llseek(fd, offset, 0) != offset) {
449                     DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : failed to seek!!\n"));
450                     break;
451                 }
452             }
453             else {
454                 fd->f_pos = offset;
455             }
456         }
457
458         retLen = fd->f_op->read(fd,
459                 buf,
460                 len,
461                 &fd->f_pos);
462
463     } while(FALSE);
464
465     filp_close(fd, NULL);
466
467     set_fs(old_fs);
468
469     return retLen;
470
471 #else // !CFG_SUPPORT_NVRAM
472
473     return -EIO;
474
475 #endif
476 }
477
478
479 /*----------------------------------------------------------------------------*/
480 /*!
481 * \brief Utility function for writing data to files on NVRAM-FS
482 *
483 * \param[in]
484 *           filename
485 *           buf
486 *           len
487 *           offset
488 * \return
489 *           actual length of data being written
490 */
491 /*----------------------------------------------------------------------------*/
492 static int
493 nvram_write (
494     char *filename,
495     char *buf,
496     ssize_t len,
497     int offset)
498 {
499 #if CFG_SUPPORT_NVRAM
500     struct file *fd;
501     int retLen = -1;
502
503     mm_segment_t old_fs = get_fs();
504     set_fs(KERNEL_DS);
505
506     fd = filp_open(filename, O_WRONLY|O_CREAT, 0644);
507
508     if(IS_ERR(fd)) {
509         DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : failed to open!!\n"));
510         return -1;
511     }
512
513     do{
514         if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) {
515             DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : file can not be write!!\n"));
516             break;
517         } /* End of if */
518
519         if (fd->f_pos != offset) {
520             if (fd->f_op->llseek) {
521                 if(fd->f_op->llseek(fd, offset, 0) != offset) {
522                     DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : failed to seek!!\n"));
523                     break;
524                 }
525             }
526             else {
527                 fd->f_pos = offset;
528             }
529         }
530
531         retLen = fd->f_op->write(fd,
532                 buf,
533                 len,
534                 &fd->f_pos);
535
536     } while(FALSE);
537
538     filp_close(fd, NULL);
539
540     set_fs(old_fs);
541
542     return retLen;
543
544 #else // !CFG_SUPPORT_NVRAMS
545
546     return -EIO;
547
548 #endif
549 }
550
551
552 /*----------------------------------------------------------------------------*/
553 /*!
554 * \brief API for reading data on NVRAM
555 *
556 * \param[in]
557 *           prGlueInfo
558 *           u4Offset
559 * \param[out]
560 *           pu2Data
561 * \return
562 *           TRUE
563 *           FALSE
564 */
565 /*----------------------------------------------------------------------------*/
566 BOOLEAN
567 kalCfgDataRead16(
568     IN P_GLUE_INFO_T    prGlueInfo,
569     IN UINT_32          u4Offset,
570     OUT PUINT_16        pu2Data
571     )
572 {
573     if(pu2Data == NULL) {
574         return FALSE;
575     }
576
577     if(nvram_read(WIFI_NVRAM_FILE_NAME,
578                 (char *)pu2Data,
579                 sizeof(unsigned short),
580                 u4Offset) != sizeof(unsigned short)) {
581         return FALSE;
582     }
583     else {
584         return TRUE;
585     }
586 }
587
588
589 /*----------------------------------------------------------------------------*/
590 /*!
591 * \brief API for writing data on NVRAM
592 *
593 * \param[in]
594 *           prGlueInfo
595 *           u4Offset
596 *           u2Data
597 * \return
598 *           TRUE
599 *           FALSE
600 */
601 /*----------------------------------------------------------------------------*/
602 BOOLEAN
603 kalCfgDataWrite16(
604     IN P_GLUE_INFO_T    prGlueInfo,
605     UINT_32             u4Offset,
606     UINT_16             u2Data
607     )
608 {
609     if(nvram_write(WIFI_NVRAM_FILE_NAME,
610                 (char *)&u2Data,
611                 sizeof(unsigned short),
612                 u4Offset) != sizeof(unsigned short)) {
613         return FALSE;
614     }
615     else {
616         return TRUE;
617     }
618 }
619
620