import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / connectivity / combo / drv_wlan / mt6630 / wlan / os / linux / platform.c
1 /*
2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/platform.c#3 $
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 ** 09 17 2012 cm.chang
20 ** [BORA00002149] [MT6630 Wi-Fi] Initial software development
21 ** Duplicate source from MT6620 v2.3 driver branch
22 ** (Davinci label: MT6620_WIFI_Driver_V2_3_120913_1942_As_MT6630_Base)
23 **
24 ** 08 24 2012 cp.wu
25 ** [WCXRP00001269] [MT6620 Wi-Fi][Driver] cfg80211 porting merge back to DaVinci
26 ** .
27 *
28 * 11 14 2011 cm.chang
29 * NULL
30 * Fix compiling warning
31 *
32 * 11 10 2011 cp.wu
33 * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
34 * 1. eliminaite direct calls to printk in porting layer.
35 * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
36 *
37 * 09 13 2011 jeffrey.chang
38 * [WCXRP00000983] [MT6620][Wi-Fi Driver] invalid pointer casting causes kernel panic during p2p connection
39 * fix the pointer casting
40 *
41 * 06 29 2011 george.huang
42 * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
43 * .
44 *
45 * 06 28 2011 george.huang
46 * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
47 * remove un-used code
48 *
49 * 05 11 2011 jeffrey.chang
50 * NULL
51 * fix build error
52 *
53 * 05 09 2011 jeffrey.chang
54 * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change
55 * support ARP filter through kernel notifier
56 *
57 * 04 08 2011 pat.lu
58 * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver
59 * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile settting for PC Linux driver
60 *
61 * 03 22 2011 pat.lu
62 * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build
63 * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment.
64 *
65 * 03 21 2011 cp.wu
66 * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
67 * improve portability for awareness of early version of linux kernel and wireless extension.
68 *
69 * 03 18 2011 jeffrey.chang
70 * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
71 * remove early suspend functions
72 *
73 * 03 03 2011 jeffrey.chang
74 * NULL
75 * add the ARP filter callback
76 *
77 * 02 15 2011 jeffrey.chang
78 * NULL
79 * to support early suspend in android
80 *
81 * 02 01 2011 cp.wu
82 * [WCXRP00000413] [MT6620 Wi-Fi][Driver] Merge 1103 changes on NVRAM file path change to DaVinci main trunk and V1.1 branch
83 * upon Jason Zhang(NVRAM owner)'s change, ALPS has modified its NVRAM storage from /nvram/... to /data/nvram/...
84 *
85 * 11 01 2010 cp.wu
86 * [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
87 * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead
88 * 2) Remove CNM CH-RECOVER event handling
89 * 3) cfg read/write API renamed with kal prefix for unified naming rules.
90 *
91 * 10 18 2010 cp.wu
92 * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android
93 * complete implementation of Android NVRAM access
94 *
95 * 10 05 2010 cp.wu
96 * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check
97 * 1) add NVRAM access API
98 * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option)
99 * 3) add OID implementation for NVRAM read/write service
100 *
101 **
102 */
103 /*******************************************************************************
104 * C O M P I L E R F L A G S
105 ********************************************************************************
106 */
107
108 /*******************************************************************************
109 * E X T E R N A L R E F E R E N C E S
110 ********************************************************************************
111 */
112 #include <linux/version.h>
113 #include <linux/init.h>
114 #include <linux/types.h>
115 #include <linux/module.h>
116 #include <linux/fs.h>
117
118 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
119 #include <linux/uaccess.h>
120 #endif
121
122 #include "gl_os.h"
123
124 #if CFG_ENABLE_EARLY_SUSPEND
125 #include <linux/earlysuspend.h>
126 #endif
127
128 /*******************************************************************************
129 * C O N S T A N T S
130 ********************************************************************************
131 */
132 #define WIFI_NVRAM_FILE_NAME "/data/nvram/APCFG/APRDEB/WIFI"
133 #define WIFI_NVRAM_CUSTOM_NAME "/data/nvram/APCFG/APRDEB/WIFI_CUSTOM"
134
135
136 /*******************************************************************************
137 * D A T A T Y P E S
138 ********************************************************************************
139 */
140
141 /*******************************************************************************
142 * P U B L I C D A T A
143 ********************************************************************************
144 */
145
146 /*******************************************************************************
147 * P R I V A T E D A T A
148 ********************************************************************************
149 */
150
151 /*******************************************************************************
152 * M A C R O S
153 ********************************************************************************
154 */
155
156 /*******************************************************************************
157 * F U N C T I O N D E C L A R A T I O N S
158 ********************************************************************************
159 */
160
161 /*******************************************************************************
162 * F U N C T I O N S
163 ********************************************************************************
164 */
165
166 static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
167 {
168 struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
169 struct net_device *prDev = ifa->ifa_dev->dev;
170 P_GLUE_INFO_T prGlueInfo = NULL;
171
172 if (prDev == NULL) {
173 /* DBGLOG(REQ, INFO, ("netdev_event: device is empty.\n")); */
174 return NOTIFY_DONE;
175 }
176
177 if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) {
178 /* DBGLOG(REQ, INFO, ("netdev_event: xxx\n")); */
179 return NOTIFY_DONE;
180 }
181 #if 0 /* CFG_SUPPORT_PASSPOINT */
182 {
183 /* printk(KERN_INFO "[netdev_event] IPV4_DAD is unlock now!!\n"); */
184 prGlueInfo->fgIsDad = FALSE;
185 }
186 #endif /* CFG_SUPPORT_PASSPOINT */
187
188 prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
189 if (prGlueInfo == NULL) {
190 DBGLOG(REQ, INFO, ("netdev_event: prGlueInfo is empty.\n"));
191 return NOTIFY_DONE;
192 }
193
194 if (prGlueInfo->fgIsInSuspendMode == FALSE) {
195 /* DBGLOG(REQ, INFO, ("netdev_event: PARAM_MEDIA_STATE_DISCONNECTED. (%d)\n", prGlueInfo->eParamMediaStateIndicated)); */
196 return NOTIFY_DONE;
197 }
198
199 kalSetNetAddressFromInterface(prGlueInfo, prDev, TRUE);
200
201 return NOTIFY_DONE;
202
203 }
204
205
206 #if 0 /* CFG_SUPPORT_PASSPOINT */
207 static int net6dev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
208 {
209 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
210 struct net_device *prDev = ifa->idev->dev;
211 P_GLUE_INFO_T prGlueInfo = NULL;
212
213 if (prDev == NULL) {
214 DBGLOG(REQ, INFO, ("net6dev_event: device is empty.\n"));
215 return NOTIFY_DONE;
216 }
217
218 if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) {
219 DBGLOG(REQ, INFO, ("net6dev_event: xxx\n"));
220 return NOTIFY_DONE;
221 }
222
223 if (strncmp(prDev->name, "p2p", 3) == 0) {
224 /* because we store the address of prGlueInfo in p2p's private date of net device */
225 /* *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prP2PInfo->prDevHandler)) = prGlueInfo; */
226 prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
227 } else { /* wlan0 */
228 prGlueInfo = (P_GLUE_INFO_T) netdev_priv(prDev);
229 }
230
231 if (prGlueInfo == NULL) {
232 DBGLOG(REQ, INFO, ("netdev_event: prGlueInfo is empty.\n"));
233 return NOTIFY_DONE;
234 }
235 /* printk(KERN_INFO "[net6dev_event] IPV6_DAD is unlock now!!\n"); */
236 prGlueInfo->fgIs6Dad = FALSE;
237
238 return NOTIFY_DONE;
239 }
240 #endif /* CFG_SUPPORT_PASSPOINT */
241
242
243 static struct notifier_block inetaddr_notifier = {
244 .notifier_call = netdev_event,
245 };
246
247 #if 0 /* CFG_SUPPORT_PASSPOINT */
248 static struct notifier_block inet6addr_notifier = {
249 .notifier_call = net6dev_event,
250 };
251 #endif /* CFG_SUPPORT_PASSPOINT */
252
253
254 void wlanRegisterNotifier(void)
255 {
256 register_inetaddr_notifier(&inetaddr_notifier);
257 #if 0 /* CFG_SUPPORT_PASSPOINT */
258 register_inet6addr_notifier(&inet6addr_notifier);
259 #endif /* CFG_SUPPORT_PASSPOINT */
260 }
261
262 void wlanUnregisterNotifier(void)
263 {
264 unregister_inetaddr_notifier(&inetaddr_notifier);
265 #if 0 /* CFG_SUPPORT_PASSPOINT */
266 unregister_inetaddr_notifier(&inet6addr_notifier);
267 #endif /* CFG_SUPPORT_PASSPOINT */
268 }
269
270 #if CFG_ENABLE_EARLY_SUSPEND
271 /*----------------------------------------------------------------------------*/
272 /*!
273 * \brief This function will register platform driver to os
274 *
275 * \param[in] wlanSuspend Function pointer to platform suspend function
276 * \param[in] wlanResume Function pointer to platform resume function
277 *
278 * \return The result of registering earlysuspend
279 */
280 /*----------------------------------------------------------------------------*/
281
282 int glRegisterEarlySuspend(struct early_suspend *prDesc,
283 early_suspend_callback wlanSuspend, late_resume_callback wlanResume)
284 {
285 int ret = 0;
286
287 if (NULL != wlanSuspend)
288 prDesc->suspend = wlanSuspend;
289 else {
290 DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanSuspend ERROR.\n"));
291 ret = -1;
292 }
293
294 if (NULL != wlanResume)
295 prDesc->resume = wlanResume;
296 else {
297 DBGLOG(REQ, INFO, ("glRegisterEarlySuspend wlanResume ERROR.\n"));
298 ret = -1;
299 }
300
301 register_early_suspend(prDesc);
302 return ret;
303 }
304
305 /*----------------------------------------------------------------------------*/
306 /*!
307 * \brief This function will un-register platform driver to os
308 *
309 * \return The result of un-registering earlysuspend
310 */
311 /*----------------------------------------------------------------------------*/
312
313 int glUnregisterEarlySuspend(struct early_suspend *prDesc)
314 {
315 int ret = 0;
316
317 unregister_early_suspend(prDesc);
318
319 prDesc->suspend = NULL;
320 prDesc->resume = NULL;
321
322 return ret;
323 }
324 #endif
325
326 /*----------------------------------------------------------------------------*/
327 /*!
328 * \brief Utility function for reading data from files on NVRAM-FS
329 *
330 * \param[in]
331 * filename
332 * len
333 * offset
334 * \param[out]
335 * buf
336 * \return
337 * actual length of data being read
338 */
339 /*----------------------------------------------------------------------------*/
340 static int nvram_read(char *filename, char *buf, ssize_t len, int offset)
341 {
342 #if CFG_SUPPORT_NVRAM
343 struct file *fd;
344 int retLen = -1;
345
346 mm_segment_t old_fs = get_fs();
347 set_fs(KERNEL_DS);
348
349 fd = filp_open(filename, O_RDONLY, 0644);
350
351 if (IS_ERR(fd)) {
352 DBGLOG(INIT, INFO, ("[nvram_read] : failed to open!!\n"));
353 return -1;
354 }
355
356 do {
357 if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) {
358 DBGLOG(INIT, INFO, ("[nvram_read] : file can not be read!!\n"));
359 break;
360 }
361
362 if (fd->f_pos != offset) {
363 if (fd->f_op->llseek) {
364 if (fd->f_op->llseek(fd, offset, 0) != offset) {
365 DBGLOG(INIT, INFO, ("[nvram_read] : failed to seek!!\n"));
366 break;
367 }
368 } else {
369 fd->f_pos = offset;
370 }
371 }
372
373 retLen = fd->f_op->read(fd, buf, len, &fd->f_pos);
374
375 } while (FALSE);
376
377 filp_close(fd, NULL);
378
379 set_fs(old_fs);
380
381 return retLen;
382
383 #else /* !CFG_SUPPORT_NVRAM */
384
385 return -EIO;
386
387 #endif
388 }
389
390
391 /*----------------------------------------------------------------------------*/
392 /*!
393 * \brief Utility function for writing data to files on NVRAM-FS
394 *
395 * \param[in]
396 * filename
397 * buf
398 * len
399 * offset
400 * \return
401 * actual length of data being written
402 */
403 /*----------------------------------------------------------------------------*/
404 static int nvram_write(char *filename, char *buf, ssize_t len, int offset)
405 {
406 #if CFG_SUPPORT_NVRAM
407 struct file *fd;
408 int retLen = -1;
409
410 mm_segment_t old_fs = get_fs();
411 set_fs(KERNEL_DS);
412
413 fd = filp_open(filename, O_WRONLY | O_CREAT, 0644);
414
415 if (IS_ERR(fd)) {
416 DBGLOG(INIT, INFO, ("[nvram_write] : failed to open!!\n"));
417 return -1;
418 }
419
420 do {
421 if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) {
422 DBGLOG(INIT, INFO, ("[nvram_write] : file can not be write!!\n"));
423 break;
424 }
425 /* End of if */
426 if (fd->f_pos != offset) {
427 if (fd->f_op->llseek) {
428 if (fd->f_op->llseek(fd, offset, 0) != offset) {
429 DBGLOG(INIT, INFO, ("[nvram_write] : failed to seek!!\n"));
430 break;
431 }
432 } else {
433 fd->f_pos = offset;
434 }
435 }
436
437 retLen = fd->f_op->write(fd, buf, len, &fd->f_pos);
438
439 } while (FALSE);
440
441 filp_close(fd, NULL);
442
443 set_fs(old_fs);
444
445 return retLen;
446
447 #else /* !CFG_SUPPORT_NVRAMS */
448
449 return -EIO;
450
451 #endif
452 }
453
454
455 /*----------------------------------------------------------------------------*/
456 /*!
457 * \brief API for reading data on NVRAM
458 *
459 * \param[in]
460 * prGlueInfo
461 * u4Offset
462 * \param[out]
463 * pu2Data
464 * \return
465 * TRUE
466 * FALSE
467 */
468 /*----------------------------------------------------------------------------*/
469 BOOLEAN kalCfgDataRead16(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, OUT PUINT_16 pu2Data)
470 {
471 if (pu2Data == NULL) {
472 return FALSE;
473 }
474
475 if (nvram_read(WIFI_NVRAM_FILE_NAME,
476 (char *)pu2Data,
477 sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) {
478 return FALSE;
479 } else {
480 return TRUE;
481 }
482 }
483
484
485 /*----------------------------------------------------------------------------*/
486 /*!
487 * \brief API for writing data on NVRAM
488 *
489 * \param[in]
490 * prGlueInfo
491 * u4Offset
492 * u2Data
493 * \return
494 * TRUE
495 * FALSE
496 */
497 /*----------------------------------------------------------------------------*/
498 BOOLEAN kalCfgDataWrite16(IN P_GLUE_INFO_T prGlueInfo, UINT_32 u4Offset, UINT_16 u2Data)
499 {
500 if (nvram_write(WIFI_NVRAM_FILE_NAME,
501 (char *)&u2Data,
502 sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) {
503 return FALSE;
504 } else {
505 return TRUE;
506 }
507 }