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