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 / platform.c
1 /* Copyright Statement:
2  *
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.
9  */
10 /* MediaTek Inc. (C) 2010. All rights reserved.
11  *
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.
30  *
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.
34  */
35
36 /*
37 ** $Id: //Department/DaVinci/BRANCHES/MT662X_593X_WIFI_DRIVER_V2_3/os/linux/platform.c#1 $
38 */
39
40 /*! \file   "platform.c"
41     \brief  This file including the protocol layer privacy function.
42
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
46
47 */
48
49 /*******************************************************************************
50 * Copyright (c) 2007 MediaTek Inc.
51 *
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
55 * MediaTek Inc.
56 ********************************************************************************
57 */
58
59 /*******************************************************************************
60 * LEGAL DISCLAIMER
61 *
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.
75 *
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.
81 *
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
87 * (ICC).
88 ********************************************************************************
89 */
90
91 /*
92 ** $Log: platform.c $
93 ** 
94 ** 08 24 2012 cp.wu
95 ** [WCXRP00001269] [MT6620 Wi-Fi][Driver] cfg80211 porting merge back to DaVinci
96 ** .
97  *
98  * 11 14 2011 cm.chang
99  * NULL
100  * Fix compiling warning
101  *
102  * 11 10 2011 cp.wu
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.
106  *
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
110  *
111  * 06 29 2011 george.huang
112  * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
113  * .
114  *
115  * 06 28 2011 george.huang
116  * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
117  * remove un-used code
118  *
119  * 05 11 2011 jeffrey.chang
120  * NULL
121  * fix build error
122  *
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
126  *
127  * 04 08 2011 pat.lu
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
130  *
131  * 03 22 2011 pat.lu
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.
134  *
135  * 03 21 2011 cp.wu
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.
138  *
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
142  *
143  * 03 03 2011 jeffrey.chang
144  * NULL
145  * add the ARP filter callback
146  *
147  * 02 15 2011 jeffrey.chang
148  * NULL
149  * to support early suspend in android
150  *
151  * 02 01 2011 cp.wu
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/...
154  *
155  * 11 01 2010 cp.wu
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.
160  *
161  * 10 18 2010 cp.wu
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
164  *
165  * 10 05 2010 cp.wu
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
170  *
171 **
172 */
173 /*******************************************************************************
174 *                         C O M P I L E R   F L A G S
175 ********************************************************************************
176 */
177
178 /*******************************************************************************
179 *                    E X T E R N A L   R E F E R E N C E S
180 ********************************************************************************
181 */
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>
187
188 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
189     #include <linux/uaccess.h>
190 #endif
191
192 #include "gl_os.h"
193
194 #ifndef CONFIG_X86
195 #if defined(CONFIG_HAS_EARLY_SUSPEND)
196     #include <linux/earlysuspend.h>
197 #endif
198 #endif
199
200
201 extern BOOLEAN fgIsUnderEarlierSuspend;
202
203 /*******************************************************************************
204 *                              C O N S T A N T S
205 ********************************************************************************
206 */
207 #define WIFI_NVRAM_FILE_NAME   "/system/etc/firmware/WIFI_MT5931"
208 #define WIFI_NVRAM_CUSTOM_NAME "/data/nvram/APCFG/APRDEB/WIFI_CUSTOM"
209
210
211 /*******************************************************************************
212 *                             D A T A   T Y P E S
213 ********************************************************************************
214 */
215
216 /*******************************************************************************
217 *                            P U B L I C   D A T A
218 ********************************************************************************
219 */
220
221 /*******************************************************************************
222 *                           P R I V A T E   D A T A
223 ********************************************************************************
224 */
225
226 /*******************************************************************************
227 *                                 M A C R O S
228 ********************************************************************************
229 */
230
231 /*******************************************************************************
232 *                   F U N C T I O N   D E C L A R A T I O N S
233 ********************************************************************************
234 */
235
236 /*******************************************************************************
237 *                              F U N C T I O N S
238 ********************************************************************************
239 */
240
241
242
243 static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
244 {
245     UINT_8  ip[4] = { 0 };
246     UINT_32 u4NumIPv4 = 0;
247 //#ifdef  CONFIG_IPV6
248 #if 0
249     UINT_8  ip6[16] = { 0 };     // FIX ME: avoid to allocate large memory in stack
250     UINT_32 u4NumIPv6 = 0;
251 #endif
252     struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
253     struct net_device *prDev = ifa->ifa_dev->dev;
254     UINT_32 i;
255     P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr;
256     P_GLUE_INFO_T prGlueInfo = NULL;
257
258     if (prDev == NULL) {
259         DBGLOG(REQ, INFO, ("netdev_event: device is empty.\n"));
260         return NOTIFY_DONE;
261     }
262
263     if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) {
264         DBGLOG(REQ, INFO, ("netdev_event: xxx\n"));
265         return NOTIFY_DONE;
266     }
267
268     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
269
270     if (prGlueInfo == NULL) {
271         DBGLOG(REQ, INFO, ("netdev_event: prGlueInfo is empty.\n"));
272         return NOTIFY_DONE;
273     }
274     ASSERT(prGlueInfo);
275
276     if (fgIsUnderEarlierSuspend == false) {
277         DBGLOG(REQ, INFO, ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", prGlueInfo->eParamMediaStateIndicated));
278         return NOTIFY_DONE;
279     }
280
281
282
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"));
288         return NOTIFY_DONE;
289     }
290
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]));
294
295     // todo: traverse between list to find whole sets of IPv4 addresses
296     if (!((ip[0] == 0) &&
297          (ip[1] == 0) &&
298          (ip[2] == 0) &&
299          (ip[3] == 0))) {
300         u4NumIPv4++;
301     }
302
303 //#ifdef  CONFIG_IPV6
304 #if 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");
309         return NOTIFY_DONE;
310     }
311
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]
318             );
319
320     // todo: traverse between list to find whole sets of IPv6 addresses
321     if (!((ip6[0] == 0) &&
322          (ip6[1] == 0) &&
323          (ip6[2] == 0) &&
324          (ip6[3] == 0) &&
325          (ip6[4] == 0) &&
326          (ip6[5] == 0))) {
327         //u4NumIPv6++;
328     }
329 #endif
330
331     // here we can compare the dev with other network's netdev to
332     // set the proper arp filter
333     //
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
336
337     // <7> set up the ARP filter
338     {
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;
345
346 //#ifdef  CONFIG_IPV6
347 #if 0
348         prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6;
349 #else
350         prParamNetAddrList->u4AddressCount = u4NumIPv4;
351 #endif
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;;
356 #if 0
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);
360 #else
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);
365 #endif
366         }
367 //#ifdef  CONFIG_IPV6
368 #if 0
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);
375        }
376 #endif
377         ASSERT(u4Len <= sizeof(aucBuf));
378
379     DBGLOG(REQ, INFO, ("kalIoctl (0x%x, 0x%x)\n", prGlueInfo, prParamNetAddrList));
380
381         rStatus = kalIoctl(prGlueInfo,
382                 wlanoidSetNetworkAddress,
383                 (PVOID)prParamNetAddrList,
384                 u4Len,
385                 FALSE,
386                 FALSE,
387                 TRUE,
388                 FALSE,
389                 &u4SetInfoLen);
390
391         if (rStatus != WLAN_STATUS_SUCCESS) {
392             DBGLOG(REQ, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus));
393         }
394     }
395
396     return NOTIFY_DONE;
397
398 }
399
400 static struct notifier_block inetaddr_notifier = {
401     .notifier_call      =   netdev_event,
402 };
403
404 void wlanRegisterNotifier(void)
405 {
406     register_inetaddr_notifier(&inetaddr_notifier);
407 }
408
409 //EXPORT_SYMBOL(wlanRegisterNotifier);
410
411 void wlanUnregisterNotifier(void)
412 {
413     unregister_inetaddr_notifier(&inetaddr_notifier);
414 }
415
416 //EXPORT_SYMBOL(wlanUnregisterNotifier);
417
418 #ifndef CONFIG_X86
419 #if defined(CONFIG_HAS_EARLYSUSPEND)
420
421
422 /*----------------------------------------------------------------------------*/
423 /*!
424 * \brief This function will register platform driver to os
425 *
426 * \param[in] wlanSuspend    Function pointer to platform suspend function
427 * \param[in] wlanResume   Function pointer to platform resume   function
428 *
429 * \return The result of registering earlysuspend
430 */
431 /*----------------------------------------------------------------------------*/
432
433 int glRegisterEarlySuspend(
434     struct early_suspend        *prDesc,
435     early_suspend_callback      wlanSuspend,
436     late_resume_callback        wlanResume)
437 {
438     int ret = 0;
439
440     if(NULL != wlanSuspend)
441         prDesc->suspend = wlanSuspend;
442     else{
443         DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanSuspend ERROR.\n"));
444         ret = -1;
445     }
446
447     if(NULL != wlanResume)
448         prDesc->resume = wlanResume;
449     else{
450         DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanResume ERROR.\n"));
451         ret = -1;
452     }
453
454     register_early_suspend(prDesc);
455     return ret;
456 }
457
458 //EXPORT_SYMBOL(glRegisterEarlySuspend);
459
460 /*----------------------------------------------------------------------------*/
461 /*!
462 * \brief This function will un-register platform driver to os
463 *
464 * \return The result of un-registering earlysuspend
465 */
466 /*----------------------------------------------------------------------------*/
467
468 int glUnregisterEarlySuspend(struct early_suspend *prDesc)
469 {
470     int ret = 0;
471
472     unregister_early_suspend(prDesc);
473
474     prDesc->suspend = NULL;
475     prDesc->resume = NULL;
476
477     return ret;
478 }
479
480 //EXPORT_SYMBOL(glUnregisterEarlySuspend);
481 #endif
482 #endif // !CONFIG_X86
483
484 /*----------------------------------------------------------------------------*/
485 /*!
486 * \brief Utility function for reading data from files on NVRAM-FS
487 *
488 * \param[in]
489 *           filename
490 *           len
491 *           offset
492 * \param[out]
493 *           buf
494 * \return
495 *           actual length of data being read
496 */
497 /*----------------------------------------------------------------------------*/
498 static int
499 nvram_read(
500     char *filename,
501     char *buf,
502     ssize_t len,
503     int offset)
504 {
505 #if CFG_SUPPORT_NVRAM
506     struct file *fd;
507     int retLen = -1;
508
509     mm_segment_t old_fs = get_fs();
510     set_fs(KERNEL_DS);
511
512     fd = filp_open(filename, O_RDONLY, 0644);
513
514     if(IS_ERR(fd)) {
515         DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : failed to open!!\n"));
516         return -1;
517     }
518
519     do {
520         if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) {
521             DBGLOG(INIT, INFO, ("[MT6620][nvram_read] : file can not be read!!\n"));
522             break;
523         }
524
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"));
529                     break;
530                 }
531             }
532             else {
533                 fd->f_pos = offset;
534             }
535         }
536
537         retLen = fd->f_op->read(fd,
538                 buf,
539                 len,
540                 &fd->f_pos);
541
542     } while(FALSE);
543
544     filp_close(fd, NULL);
545
546     set_fs(old_fs);
547
548     return retLen;
549
550 #else // !CFG_SUPPORT_NVRAM
551
552     return -EIO;
553
554 #endif
555 }
556
557
558 /*----------------------------------------------------------------------------*/
559 /*!
560 * \brief Utility function for writing data to files on NVRAM-FS
561 *
562 * \param[in]
563 *           filename
564 *           buf
565 *           len
566 *           offset
567 * \return
568 *           actual length of data being written
569 */
570 /*----------------------------------------------------------------------------*/
571 static int
572 nvram_write (
573     char *filename,
574     char *buf,
575     ssize_t len,
576     int offset)
577 {
578 #if CFG_SUPPORT_NVRAM
579     struct file *fd;
580     int retLen = -1;
581
582     mm_segment_t old_fs = get_fs();
583     set_fs(KERNEL_DS);
584
585     fd = filp_open(filename, O_WRONLY|O_CREAT, 0644);
586
587     if(IS_ERR(fd)) {
588         DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : failed to open!!\n"));
589         return -1;
590     }
591
592     do{
593         if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) {
594             DBGLOG(INIT, INFO, ("[MT6620][nvram_write] : file can not be write!!\n"));
595             break;
596         } /* End of if */
597
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"));
602                     break;
603                 }
604             }
605             else {
606                 fd->f_pos = offset;
607             }
608         }
609
610         retLen = fd->f_op->write(fd,
611                 buf,
612                 len,
613                 &fd->f_pos);
614
615     } while(FALSE);
616
617     filp_close(fd, NULL);
618
619     set_fs(old_fs);
620
621     return retLen;
622
623 #else // !CFG_SUPPORT_NVRAMS
624
625     return -EIO;
626
627 #endif
628 }
629
630
631 /*----------------------------------------------------------------------------*/
632 /*!
633 * \brief API for reading data on NVRAM
634 *
635 * \param[in]
636 *           prGlueInfo
637 *           u4Offset
638 * \param[out]
639 *           pu2Data
640 * \return
641 *           TRUE
642 *           FALSE
643 */
644 /*----------------------------------------------------------------------------*/
645 BOOLEAN
646 kalCfgDataRead16(
647     IN P_GLUE_INFO_T    prGlueInfo,
648     IN UINT_32          u4Offset,
649     OUT PUINT_16        pu2Data
650     )
651 {
652     if(pu2Data == NULL) {
653         return FALSE;
654     }
655
656     if(nvram_read(WIFI_NVRAM_FILE_NAME,
657                 (char *)pu2Data,
658                 sizeof(unsigned short),
659                 u4Offset) != sizeof(unsigned short)) {
660         return FALSE;
661     }
662     else {
663         return TRUE;
664     }
665 }
666
667
668 /*----------------------------------------------------------------------------*/
669 /*!
670 * \brief API for writing data on NVRAM
671 *
672 * \param[in]
673 *           prGlueInfo
674 *           u4Offset
675 *           u2Data
676 * \return
677 *           TRUE
678 *           FALSE
679 */
680 /*----------------------------------------------------------------------------*/
681 BOOLEAN
682 kalCfgDataWrite16(
683     IN P_GLUE_INFO_T    prGlueInfo,
684     UINT_32             u4Offset,
685     UINT_16             u2Data
686     )
687 {
688     if(nvram_write(WIFI_NVRAM_FILE_NAME,
689                 (char *)&u2Data,
690                 sizeof(unsigned short),
691                 u4Offset) != sizeof(unsigned short)) {
692         return FALSE;
693     }
694     else {
695         return TRUE;
696     }
697 }
698
699