1 /* Copyright Statement:
3 * This software/firmware and related documentation ("MediaTek Software") are
4 * protected under relevant copyright laws. The information contained herein
5 * is confidential and proprietary to MediaTek Inc. and/or its licensors.
6 * Without the prior written permission of MediaTek inc. and/or its licensors,
7 * any reproduction, modification, use or disclosure of MediaTek Software,
8 * and information contained herein, in whole or in part, shall be strictly prohibited.
10 /* MediaTek Inc. (C) 2010. All rights reserved.
12 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
13 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
14 * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
15 * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
18 * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
19 * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
20 * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
21 * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
22 * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
23 * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
24 * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
25 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
26 * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
27 * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
28 * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
29 * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
31 * The following software/firmware and/or related documentation ("MediaTek Software")
32 * have been modified by MediaTek Inc. All revisions are subject to any receiver's
33 * applicable license agreements with MediaTek Inc.
37 ** $Id: //Department/DaVinci/BRANCHES/MT662X_593X_WIFI_DRIVER_V2_3/os/linux/platform.c#1 $
40 /*! \file "platform.c"
41 \brief This file including the protocol layer privacy function.
43 This file provided the macros and functions library support for the
44 protocol layer security setting from wlan_oid.c and for parse.c and
45 rsn.c and nic_privacy.c
49 /*******************************************************************************
50 * Copyright (c) 2007 MediaTek Inc.
52 * All rights reserved. Copying, compilation, modification, distribution
53 * or any other use whatsoever of this material is strictly prohibited
54 * except in accordance with a Software License Agreement with
56 ********************************************************************************
59 /*******************************************************************************
62 * BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND
63 * AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK
64 * SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE
65 * PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY
66 * DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
67 * LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
68 * PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE
69 * ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
70 * WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK
71 * SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY
72 * WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE
73 * FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO
74 * CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
76 * BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
77 * LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL
78 * BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT
79 * ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY
80 * BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
82 * THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
83 * WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT
84 * OF LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING
85 * THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN
86 * FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE
88 ********************************************************************************
95 ** [WCXRP00001269] [MT6620 Wi-Fi][Driver] cfg80211 porting merge back to DaVinci
100 * Fix compiling warning
103 * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
104 * 1. eliminaite direct calls to printk in porting layer.
105 * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
107 * 09 13 2011 jeffrey.chang
108 * [WCXRP00000983] [MT6620][Wi-Fi Driver] invalid pointer casting causes kernel panic during p2p connection
109 * fix the pointer casting
111 * 06 29 2011 george.huang
112 * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
115 * 06 28 2011 george.huang
116 * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
117 * remove un-used code
119 * 05 11 2011 jeffrey.chang
123 * 05 09 2011 jeffrey.chang
124 * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change
125 * support ARP filter through kernel notifier
128 * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver
129 * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile settting for PC Linux driver
132 * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build
133 * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment.
136 * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
137 * improve portability for awareness of early version of linux kernel and wireless extension.
139 * 03 18 2011 jeffrey.chang
140 * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
141 * remove early suspend functions
143 * 03 03 2011 jeffrey.chang
145 * add the ARP filter callback
147 * 02 15 2011 jeffrey.chang
149 * to support early suspend in android
152 * [WCXRP00000413] [MT6620 Wi-Fi][Driver] Merge 1103 changes on NVRAM file path change to DaVinci main trunk and V1.1 branch
153 * upon Jason Zhang(NVRAM owner)'s change, ALPS has modified its NVRAM storage from /nvram/... to /data/nvram/...
156 * [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
157 * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead
158 * 2) Remove CNM CH-RECOVER event handling
159 * 3) cfg read/write API renamed with kal prefix for unified naming rules.
162 * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android
163 * complete implementation of Android NVRAM access
166 * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check
167 * 1) add NVRAM access API
168 * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option)
169 * 3) add OID implementation for NVRAM read/write service
173 /*******************************************************************************
174 * C O M P I L E R F L A G S
175 ********************************************************************************
178 /*******************************************************************************
179 * E X T E R N A L R E F E R E N C E S
180 ********************************************************************************
182 #include <linux/version.h>
183 #include <linux/init.h>
184 #include <linux/types.h>
185 #include <linux/module.h>
186 #include <linux/fs.h>
188 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
189 #include <linux/uaccess.h>
195 #if defined(CONFIG_HAS_EARLY_SUSPEND)
196 #include <linux/earlysuspend.h>
201 extern BOOLEAN fgIsUnderEarlierSuspend;
203 /*******************************************************************************
205 ********************************************************************************
207 #define WIFI_NVRAM_FILE_NAME "/system/etc/firmware/WIFI_MT5931"
208 #define WIFI_NVRAM_CUSTOM_NAME "/data/nvram/APCFG/APRDEB/WIFI_CUSTOM"
211 /*******************************************************************************
213 ********************************************************************************
216 /*******************************************************************************
217 * P U B L I C D A T A
218 ********************************************************************************
221 /*******************************************************************************
222 * P R I V A T E D A T A
223 ********************************************************************************
226 /*******************************************************************************
228 ********************************************************************************
231 /*******************************************************************************
232 * F U N C T I O N D E C L A R A T I O N S
233 ********************************************************************************
236 /*******************************************************************************
238 ********************************************************************************
243 static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
245 UINT_8 ip[4] = { 0 };
246 UINT_32 u4NumIPv4 = 0;
249 UINT_8 ip6[16] = { 0 }; // FIX ME: avoid to allocate large memory in stack
250 UINT_32 u4NumIPv6 = 0;
252 struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
253 struct net_device *prDev = ifa->ifa_dev->dev;
255 P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr;
256 P_GLUE_INFO_T prGlueInfo = NULL;
259 DBGLOG(REQ, INFO, ("netdev_event: device is empty.\n"));
263 if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) {
264 DBGLOG(REQ, INFO, ("netdev_event: xxx\n"));
268 prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
270 if (prGlueInfo == NULL) {
271 DBGLOG(REQ, INFO, ("netdev_event: prGlueInfo is empty.\n"));
276 if (fgIsUnderEarlierSuspend == false) {
277 DBGLOG(REQ, INFO, ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", prGlueInfo->eParamMediaStateIndicated));
283 // <3> get the IPv4 address
284 if(!prDev || !(prDev->ip_ptr)||\
285 !((struct in_device *)(prDev->ip_ptr))->ifa_list||\
286 !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){
287 DBGLOG(REQ, INFO, ("ip is not avaliable.\n"));
291 kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip));
292 DBGLOG(REQ, INFO, ("ip is %d.%d.%d.%d\n",
293 ip[0],ip[1],ip[2],ip[3]));
295 // todo: traverse between list to find whole sets of IPv4 addresses
296 if (!((ip[0] == 0) &&
305 if(!prDev || !(prDev->ip6_ptr)||\
306 !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\
307 !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){
308 printk(KERN_INFO "ipv6 is not avaliable.\n");
312 kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6));
313 printk(KERN_INFO"ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n",
314 ip6[0],ip6[1],ip6[2],ip6[3],
315 ip6[4],ip6[5],ip6[6],ip6[7],
316 ip6[8],ip6[9],ip6[10],ip6[11],
317 ip6[12],ip6[13],ip6[14],ip6[15]
320 // todo: traverse between list to find whole sets of IPv6 addresses
321 if (!((ip6[0] == 0) &&
331 // here we can compare the dev with other network's netdev to
332 // set the proper arp filter
334 // IMPORTANT: please make sure if the context can sleep, if the context can't sleep
335 // we should schedule a kernel thread to do this for us
337 // <7> set up the ARP filter
339 WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
340 UINT_32 u4SetInfoLen = 0;
341 UINT_8 aucBuf[32] = {0};
342 UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress);
343 P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)aucBuf;
344 P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress;
348 prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6;
350 prParamNetAddrList->u4AddressCount = u4NumIPv4;
352 prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;
353 for (i = 0; i < u4NumIPv4; i++) {
354 prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP);//4;;
355 prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;;
357 kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip));
358 prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip));
359 u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip);
361 prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP)prParamNetAddr->aucAddress;
362 kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip));
363 prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS));
364 u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS);
369 for (i = 0; i < u4NumIPv6; i++) {
370 prParamNetAddr->u2AddressLength = 6;;
371 prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;;
372 kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6));
373 prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6));
374 u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6);
377 ASSERT(u4Len <= sizeof(aucBuf));
379 DBGLOG(REQ, INFO, ("kalIoctl (0x%x, 0x%x)\n", prGlueInfo, prParamNetAddrList));
381 rStatus = kalIoctl(prGlueInfo,
382 wlanoidSetNetworkAddress,
383 (PVOID)prParamNetAddrList,
391 if (rStatus != WLAN_STATUS_SUCCESS) {
392 DBGLOG(REQ, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus));
400 static struct notifier_block inetaddr_notifier = {
401 .notifier_call = netdev_event,
404 void wlanRegisterNotifier(void)
406 register_inetaddr_notifier(&inetaddr_notifier);
409 //EXPORT_SYMBOL(wlanRegisterNotifier);
411 void wlanUnregisterNotifier(void)
413 unregister_inetaddr_notifier(&inetaddr_notifier);
416 //EXPORT_SYMBOL(wlanUnregisterNotifier);
419 #if defined(CONFIG_HAS_EARLYSUSPEND)
422 /*----------------------------------------------------------------------------*/
424 * \brief This function will register platform driver to os
426 * \param[in] wlanSuspend Function pointer to platform suspend function
427 * \param[in] wlanResume Function pointer to platform resume function
429 * \return The result of registering earlysuspend
431 /*----------------------------------------------------------------------------*/
433 int glRegisterEarlySuspend(
434 struct early_suspend *prDesc,
435 early_suspend_callback wlanSuspend,
436 late_resume_callback wlanResume)
440 if(NULL != wlanSuspend)
441 prDesc->suspend = wlanSuspend;
443 DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanSuspend ERROR.\n"));
447 if(NULL != wlanResume)
448 prDesc->resume = wlanResume;
450 DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanResume ERROR.\n"));
454 register_early_suspend(prDesc);
458 //EXPORT_SYMBOL(glRegisterEarlySuspend);
460 /*----------------------------------------------------------------------------*/
462 * \brief This function will un-register platform driver to os
464 * \return The result of un-registering earlysuspend
466 /*----------------------------------------------------------------------------*/
468 int glUnregisterEarlySuspend(struct early_suspend *prDesc)
472 unregister_early_suspend(prDesc);
474 prDesc->suspend = NULL;
475 prDesc->resume = NULL;
480 //EXPORT_SYMBOL(glUnregisterEarlySuspend);
482 #endif // !CONFIG_X86
484 /*----------------------------------------------------------------------------*/
486 * \brief Utility function for reading data from files on NVRAM-FS
495 * actual length of data being read
497 /*----------------------------------------------------------------------------*/
505 #if CFG_SUPPORT_NVRAM
509 mm_segment_t old_fs = get_fs();
512 fd = filp_open(filename, O_RDONLY, 0644);
515 DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : failed to open!!\n"));
520 if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) {
521 DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : file can not be read!!\n"));
525 if (fd->f_pos != offset) {
526 if (fd->f_op->llseek) {
527 if(fd->f_op->llseek(fd, offset, 0) != offset) {
528 DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : failed to seek!!\n"));
537 retLen = fd->f_op->read(fd,
544 filp_close(fd, NULL);
550 #else // !CFG_SUPPORT_NVRAM
558 /*----------------------------------------------------------------------------*/
560 * \brief Utility function for writing data to files on NVRAM-FS
568 * actual length of data being written
570 /*----------------------------------------------------------------------------*/
578 #if CFG_SUPPORT_NVRAM
582 mm_segment_t old_fs = get_fs();
585 fd = filp_open(filename, O_WRONLY|O_CREAT, 0644);
588 DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : failed to open!!\n"));
593 if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) {
594 DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : file can not be write!!\n"));
598 if (fd->f_pos != offset) {
599 if (fd->f_op->llseek) {
600 if(fd->f_op->llseek(fd, offset, 0) != offset) {
601 DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : failed to seek!!\n"));
610 retLen = fd->f_op->write(fd,
617 filp_close(fd, NULL);
623 #else // !CFG_SUPPORT_NVRAMS
631 /*----------------------------------------------------------------------------*/
633 * \brief API for reading data on NVRAM
644 /*----------------------------------------------------------------------------*/
647 IN P_GLUE_INFO_T prGlueInfo,
652 if(pu2Data == NULL) {
656 if(nvram_read(WIFI_NVRAM_FILE_NAME,
658 sizeof(unsigned short),
659 u4Offset) != sizeof(unsigned short)) {
668 /*----------------------------------------------------------------------------*/
670 * \brief API for writing data on NVRAM
680 /*----------------------------------------------------------------------------*/
683 IN P_GLUE_INFO_T prGlueInfo,
688 if(nvram_write(WIFI_NVRAM_FILE_NAME,
690 sizeof(unsigned short),
691 u4Offset) != sizeof(unsigned short)) {