2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/platform.c#1 $
6 \brief This file including the protocol layer privacy function.
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
21 * Fix compiling warning
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.
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
32 * 06 29 2011 george.huang
33 * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
36 * 06 28 2011 george.huang
37 * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
40 * 05 11 2011 jeffrey.chang
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
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
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.
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.
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
64 * 03 03 2011 jeffrey.chang
66 * add the ARP filter callback
68 * 02 15 2011 jeffrey.chang
70 * to support early suspend in android
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/...
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.
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
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
94 /*******************************************************************************
95 * C O M P I L E R F L A G S
96 ********************************************************************************
99 /*******************************************************************************
100 * E X T E R N A L R E F E R E N C E S
101 ********************************************************************************
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>
109 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
110 #include <linux/uaccess.h>
116 #if defined(CONFIG_HAS_EARLY_SUSPEND)
117 #include <linux/earlysuspend.h>
121 extern atomic_t fgIsUnderEarlierSuspend;
123 /*******************************************************************************
125 ********************************************************************************
127 #define WIFI_NVRAM_FILE_NAME "/data/nvram/APCFG/APRDEB/WIFI"
128 #define WIFI_NVRAM_CUSTOM_NAME "/data/nvram/APCFG/APRDEB/WIFI_CUSTOM"
131 /*******************************************************************************
133 ********************************************************************************
136 /*******************************************************************************
137 * P U B L I C D A T A
138 ********************************************************************************
141 /*******************************************************************************
142 * P R I V A T E D A T A
143 ********************************************************************************
146 /*******************************************************************************
148 ********************************************************************************
151 /*******************************************************************************
152 * F U N C T I O N D E C L A R A T I O N S
153 ********************************************************************************
156 /*******************************************************************************
158 ********************************************************************************
163 static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
165 struct in_device *in_dev;
166 UINT_8 ip[4] = { 0 };
167 UINT_32 u4NumIPv4 = 0;
170 UINT_8 ip6[16] = { 0 }; // FIX ME: avoid to allocate large memory in stack
171 UINT_32 u4NumIPv6 = 0;
173 struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
174 struct net_device *prDev = ifa->ifa_dev->dev;
176 P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr;
177 P_GLUE_INFO_T prGlueInfo = NULL;
180 DBGLOG(REQ, INFO, ("netdev_event: device is empty.\n"));
184 if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) {
185 DBGLOG(REQ, INFO, ("netdev_event: xxx\n"));
189 prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
191 if (prGlueInfo == NULL) {
192 DBGLOG(REQ, INFO, ("netdev_event: prGlueInfo is empty.\n"));
197 // <3> get the IPv4 address
198 in_dev = in_dev_get(prDev);
203 if(!in_dev->ifa_list ||!in_dev->ifa_list->ifa_local) {
206 DBGLOG(REQ, INFO, ("ip is not avaliable.\n"));
209 // <4> copy the IPv4 address
210 kalMemCopy(ip, &(in_dev->ifa_list->ifa_local), sizeof(ip));
214 DBGLOG(REQ, INFO, ("ip is %d.%d.%d.%d\n",
215 ip[0],ip[1],ip[2],ip[3]));
217 // todo: traverse between list to find whole sets of IPv4 addresses
218 if (!((ip[0] == 0) &&
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;
231 SwCtrlInfo.u4Id = 0x90110000;
232 SwCtrlInfo.u4Data = 1;
234 rStatus = kalIoctl(prGlueInfo,
235 wlanoidSetSwCtrlWrite,
244 if (rStatus != WLAN_STATUS_SUCCESS) {
245 DBGLOG(REQ, INFO, ("ARP OFFLOAD fail 0x%lx\n", rStatus));
247 DBGLOG(REQ, INFO, ("ARP OFFLOAD success\n"));
252 if(atomic_read(&fgIsUnderEarlierSuspend)==0){
254 DBGLOG(REQ, INFO, ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", prGlueInfo->eParamMediaStateIndicated));
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");
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]
275 // todo: traverse between list to find whole sets of IPv6 addresses
276 if (!((ip6[0] == 0) &&
286 // here we can compare the dev with other network's netdev to
287 // set the proper arp filter
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
292 // <7> set up the ARP filter
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;
303 prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6;
305 prParamNetAddrList->u4AddressCount = u4NumIPv4;
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;;
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);
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);
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);
332 ASSERT(u4Len <= sizeof(aucBuf));
334 DBGLOG(REQ, INFO, ("kalIoctl (0x%x, 0x%x)\n", prGlueInfo, prParamNetAddrList));
336 rStatus = kalIoctl(prGlueInfo,
337 wlanoidSetNetworkAddress,
338 (PVOID)prParamNetAddrList,
346 if (rStatus != WLAN_STATUS_SUCCESS) {
347 DBGLOG(REQ, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus));
355 static struct notifier_block inetaddr_notifier = {
356 .notifier_call = netdev_event,
359 void wlanRegisterNotifier(void)
361 register_inetaddr_notifier(&inetaddr_notifier);
364 //EXPORT_SYMBOL(wlanRegisterNotifier);
366 void wlanUnregisterNotifier(void)
368 unregister_inetaddr_notifier(&inetaddr_notifier);
371 //EXPORT_SYMBOL(wlanUnregisterNotifier);
374 #if defined(CONFIG_HAS_EARLYSUSPEND)
377 /*----------------------------------------------------------------------------*/
379 * \brief This function will register platform driver to os
381 * \param[in] wlanSuspend Function pointer to platform suspend function
382 * \param[in] wlanResume Function pointer to platform resume function
384 * \return The result of registering earlysuspend
386 /*----------------------------------------------------------------------------*/
388 int glRegisterEarlySuspend(
389 struct early_suspend *prDesc,
390 early_suspend_callback wlanSuspend,
391 late_resume_callback wlanResume)
395 if(NULL != wlanSuspend)
396 prDesc->suspend = wlanSuspend;
398 DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanSuspend ERROR.\n"));
402 if(NULL != wlanResume)
403 prDesc->resume = wlanResume;
405 DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanResume ERROR.\n"));
409 register_early_suspend(prDesc);
413 //EXPORT_SYMBOL(glRegisterEarlySuspend);
415 /*----------------------------------------------------------------------------*/
417 * \brief This function will un-register platform driver to os
419 * \return The result of un-registering earlysuspend
421 /*----------------------------------------------------------------------------*/
423 int glUnregisterEarlySuspend(struct early_suspend *prDesc)
427 unregister_early_suspend(prDesc);
429 prDesc->suspend = NULL;
430 prDesc->resume = NULL;
435 //EXPORT_SYMBOL(glUnregisterEarlySuspend);
437 #endif // !CONFIG_X86
439 /*----------------------------------------------------------------------------*/
441 * \brief Utility function for reading data from files on NVRAM-FS
450 * actual length of data being read
452 /*----------------------------------------------------------------------------*/
460 #if CFG_SUPPORT_NVRAM
464 mm_segment_t old_fs = get_fs();
467 fd = filp_open(filename, O_RDONLY, 0644);
470 DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : failed to open!!\n"));
475 if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) {
476 DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : file can not be read!!\n"));
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"));
492 retLen = fd->f_op->read(fd,
499 filp_close(fd, NULL);
505 #else // !CFG_SUPPORT_NVRAM
513 /*----------------------------------------------------------------------------*/
515 * \brief Utility function for writing data to files on NVRAM-FS
523 * actual length of data being written
525 /*----------------------------------------------------------------------------*/
533 #if CFG_SUPPORT_NVRAM
537 mm_segment_t old_fs = get_fs();
540 fd = filp_open(filename, O_WRONLY|O_CREAT, 0644);
543 DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : failed to open!!\n"));
548 if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) {
549 DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : file can not be write!!\n"));
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"));
565 retLen = fd->f_op->write(fd,
572 filp_close(fd, NULL);
578 #else // !CFG_SUPPORT_NVRAMS
586 /*----------------------------------------------------------------------------*/
588 * \brief API for reading data on NVRAM
599 /*----------------------------------------------------------------------------*/
602 IN P_GLUE_INFO_T prGlueInfo,
607 if(pu2Data == NULL) {
611 if(nvram_read(WIFI_NVRAM_FILE_NAME,
613 sizeof(unsigned short),
614 u4Offset) != sizeof(unsigned short)) {
623 /*----------------------------------------------------------------------------*/
625 * \brief API for writing data on NVRAM
635 /*----------------------------------------------------------------------------*/
638 IN P_GLUE_INFO_T prGlueInfo,
643 if(nvram_write(WIFI_NVRAM_FILE_NAME,
645 sizeof(unsigned short),
646 u4Offset) != sizeof(unsigned short)) {