Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(496)

Side by Side Diff: chromeos/drivers/ath6kl/os/linux/ar6000_android.c

Issue 3579004: ath6kl: Bringing in the upstream version (Closed) Base URL: http://git.chromium.org/git/kernel.git
Patch Set: Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 //------------------------------------------------------------------------------
2 * 2 // Copyright (c) 2004-2010 Atheros Communications Inc.
3 * Copyright (c) 2004-2010 Atheros Communications Inc. 3 // All rights reserved.
4 * All rights reserved.
5 *
6 *
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2 as
9 // published by the Free Software Foundation;
10 // 4 //
11 // Software distributed under the License is distributed on an "AS 5 //
12 // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 6 //
13 // implied. See the License for the specific language governing 7 // Permission to use, copy, modify, and/or distribute this software for any
14 // rights and limitations under the License. 8 // purpose with or without fee is hereby granted, provided that the above
9 // copyright notice and this permission notice appear in all copies.
10 //
11 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 // 18 //
16 // 19 //
17 * 20 //
18 */ 21 // Author(s): ="Atheros"
22 //------------------------------------------------------------------------------
19 #include "ar6000_drv.h" 23 #include "ar6000_drv.h"
20 #undef ATH_MODULE_NAME
21 #define ATH_MODULE_NAME android
22 #include "htc.h" 24 #include "htc.h"
23 #include <linux/vmalloc.h> 25 #include <linux/vmalloc.h>
24 #include <linux/fs.h> 26 #include <linux/fs.h>
25 #include <linux/platform_device.h>
26 #include <linux/inetdevice.h>
27 27
28 #ifdef CONFIG_HAS_WAKELOCK 28 #ifdef CONFIG_HAS_WAKELOCK
29 #include <linux/wakelock.h> 29 #include <linux/wakelock.h>
30 #endif 30 #endif
31 #ifdef CONFIG_HAS_EARLYSUSPEND
31 #include <linux/earlysuspend.h> 32 #include <linux/earlysuspend.h>
32
33 enum {
34 WLAN_PWR_CTRL_UP = 0,
35 WLAN_PWR_CTRL_CUT_PWR,
36 WLAN_PWR_CTRL_DEEP_SLEEP,
37 WLAN_PWR_CTRL_WOW,
38 WLAN_PWR_CTRL_DEEP_SLEEP_DISABLED
39 };
40
41 enum {
42 WOW_STATE_NONE = 0,
43 WOW_STATE_SUSPENDED,
44 WOW_STATE_SUSPENDING,
45 };
46
47 #define WOW_ENABLE_MAX_INTERVAL 0
48 #define WOW_SET_SCAN_PARAMS 0
49
50 #define IS_MAC_NULL(mac) (mac[0]==0 && mac[1]==0 && mac[2]==0 && mac[3]==0 && ma c[4]==0 && mac[5]==0)
51 #define MAX_BUF (8*1024)
52
53 #define ATH_DEBUG_SUSPEND ATH_DEBUG_MAKE_MODULE_MASK(0)
54
55 #ifdef DEBUG
56
57 static ATH_DEBUG_MASK_DESCRIPTION android_debug_desc[] = {
58 { ATH_DEBUG_SUSPEND , "Android Debug Logs"},
59 };
60
61 ATH_DEBUG_INSTANTIATE_MODULE_VAR(android,
62 "android",
63 "Android Driver Interface",
64 ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_SUSPEND,
65 ATH_DEBUG_DESCRIPTION_COUNT(android_debug_desc) ,
66 android_debug_desc);
67
68 #endif 33 #endif
69 34
70 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 35 A_BOOL enable_mmc_host_detect_change = 0;
36 static void ar6000_enable_mmchost_detect_change(int enable);
37
38
71 char fwpath[256] = "/system/wifi"; 39 char fwpath[256] = "/system/wifi";
72 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
73 int buspm = WLAN_PWR_CTRL_WOW;
74 int wow2mode = WLAN_PWR_CTRL_DEEP_SLEEP;
75 int wowledon; 40 int wowledon;
76 unsigned int enablelogcat; 41 unsigned int enablelogcat;
77 42
78 extern int bmienable; 43 extern int bmienable;
79 extern int wlaninitmode;
80 extern unsigned int wmitimeout;
81 extern wait_queue_head_t arEvent;
82 extern struct net_device *ar6000_devices[]; 44 extern struct net_device *ar6000_devices[];
83 #ifdef CONFIG_HOST_TCMD_SUPPORT 45 extern char ifname[];
84 extern unsigned int testmode; 46
47 #ifdef CONFIG_HAS_WAKELOCK
48 extern struct wake_lock ar6k_wow_wake_lock;
49 struct wake_lock ar6k_init_wake_lock;
85 #endif 50 #endif
86 extern char ifname[];
87 extern unsigned int bypasswmi;
88 51
89 const char def_ifname[] = "wlan0"; 52 const char def_ifname[] = "wlan0";
90 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
91 module_param_string(fwpath, fwpath, sizeof(fwpath), 0644); 53 module_param_string(fwpath, fwpath, sizeof(fwpath), 0644);
92 module_param(buspm, int, 0644);
93 module_param(enablelogcat, uint, 0644); 54 module_param(enablelogcat, uint, 0644);
94 module_param(wowledon, int, 0644); 55 module_param(wowledon, int, 0644);
95 #else
96 #define __user
97 /* for linux 2.4 and lower */
98 MODULE_PARM(buspm,"i");
99 MODULE_PARAM(wowledon,"i");
100 #endif
101 56
102 struct wake_lock ar6k_init_wake_lock; 57 #ifdef CONFIG_HAS_EARLYSUSPEND
103 struct wake_lock ar6k_wow_wake_lock;
104 static int screen_is_off; 58 static int screen_is_off;
105 static struct early_suspend ar6k_early_suspend; 59 static struct early_suspend ar6k_early_suspend;
60 #endif
61
106 static A_STATUS (*ar6000_avail_ev_p)(void *, void *); 62 static A_STATUS (*ar6000_avail_ev_p)(void *, void *);
107 63
108 extern int ar6000_init(struct net_device *dev); 64 #if defined(CONFIG_ANDROID_LOGGER) && (!defined(CONFIG_MMC_MSM))
109 extern A_STATUS ar6000_configure_target(AR_SOFTC_T *ar);
110 extern void ar6000_stop_endpoint(struct net_device *dev, A_BOOL keepprofile);
111 extern A_STATUS ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode);
112 extern void ar6000_destroy(struct net_device *dev, unsigned int unregister);
113
114 static void ar6000_enable_mmchost_detect_change(int enable);
115 static void ar6000_restart_endpoint(struct net_device *dev);
116
117 #if defined(CONFIG_PM)
118 static A_STATUS ar6000_suspend_ev(void *context);
119
120 static A_STATUS ar6000_resume_ev(void *context);
121 #endif
122
123 #ifndef CONFIG_MMC_MSM
124 int logger_write(const enum logidx index, 65 int logger_write(const enum logidx index,
125 const unsigned char prio, 66 const unsigned char prio,
126 const char __kernel * const tag, 67 const char __kernel * const tag,
127 const char __kernel * const fmt, 68 const char __kernel * const fmt,
128 ...) 69 ...)
129 { 70 {
130 int ret = 0; 71 int ret = 0;
131 va_list vargs; 72 va_list vargs;
132 struct file *filp = (struct file *)-ENOENT; 73 struct file *filp = (struct file *)-ENOENT;
133 mm_segment_t oldfs; 74 mm_segment_t oldfs;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 filp = filp_open(filename, mode, S_IRUSR); 175 filp = filp_open(filename, mode, S_IRUSR);
235 if (IS_ERR(filp) || !filp->f_op) { 176 if (IS_ERR(filp) || !filp->f_op) {
236 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: file %s filp_open error\n", __F UNCTION__, filename)); 177 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: file %s filp_open error\n", __F UNCTION__, filename));
237 ret = -ENOENT; 178 ret = -ENOENT;
238 break; 179 break;
239 } 180 }
240 181
241 if (length==0) { 182 if (length==0) {
242 /* Read the length of the file only */ 183 /* Read the length of the file only */
243 struct inode *inode; 184 struct inode *inode;
244 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) 185
245 inode = filp->f_path.dentry->d_inode; 186 inode = GET_INODE_FROM_FILEP(filp);
246 #else 187 if (!inode) {
247 inode = filp->f_dentry->d_inode;
248 #endif
249 » » if (!inode) {
250 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Get inode from %s failed\n" , __FUNCTION__, filename)); 188 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Get inode from %s failed\n" , __FUNCTION__, filename));
251 ret = -ENOENT; 189 ret = -ENOENT;
252 break; 190 break;
253 } 191 }
254 ret = i_size_read(inode->i_mapping->host); 192 ret = i_size_read(inode->i_mapping->host);
255 break; 193 break;
256 } 194 }
257 195
258 if (wbuf) { 196 if (wbuf) {
259 if ( (ret=filp->f_op->write(filp, wbuf, length, &filp->f_pos)) < 0) { 197 if ( (ret=filp->f_op->write(filp, wbuf, length, &filp->f_pos)) < 0) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 if ( (ret=android_readwrite_file(filename, NULL, NULL, 0)) < 0) { 233 if ( (ret=android_readwrite_file(filename, NULL, NULL, 0)) < 0) {
296 break; 234 break;
297 } else { 235 } else {
298 length = ret; 236 length = ret;
299 } 237 }
300 238
301 bufsize = ALIGN(length, PAGE_SIZE); 239 bufsize = ALIGN(length, PAGE_SIZE);
302 bmisize = A_ROUND_UP(length, 4); 240 bmisize = A_ROUND_UP(length, 4);
303 bufsize = max(bmisize, bufsize); 241 bufsize = max(bmisize, bufsize);
304 firmware->data = vmalloc(bufsize); 242 firmware->data = vmalloc(bufsize);
305 firmware->size = bmisize; 243 firmware->size = length;
306 if (!firmware->data) { 244 if (!firmware->data) {
307 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: Cannot allocate buffer for firmw are\n", __FUNCTION__)); 245 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: Cannot allocate buffer for firmw are\n", __FUNCTION__));
308 ret = -ENOMEM; 246 ret = -ENOMEM;
309 break; 247 break;
310 } 248 }
311 249
312 if ( (ret=android_readwrite_file(filename, (char*)firmware->data, NULL, length)) != length) { 250 if ( (ret=android_readwrite_file(filename, (char*)firmware->data, NULL, length)) != length) {
313 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: file read error, ret %d request %d\n", __FUNCTION__, ret, length)); 251 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: file read error, ret %d request %d\n", __FUNCTION__, ret, length));
314 ret = -1; 252 ret = -1;
315 break; 253 break;
(...skipping 16 matching lines...) Expand all
332 270
333 void android_release_firmware(const struct firmware *firmware) 271 void android_release_firmware(const struct firmware *firmware)
334 { 272 {
335 if (firmware) { 273 if (firmware) {
336 if (firmware->data) 274 if (firmware->data)
337 vfree(firmware->data); 275 vfree(firmware->data);
338 kfree(firmware); 276 kfree(firmware);
339 } 277 }
340 } 278 }
341 279
342 #if defined(CONFIG_PM)
343 static void ar6k_send_asleep_event_to_app(AR_SOFTC_T *ar, A_BOOL asleep)
344 {
345 char buf[128];
346 union iwreq_data wrqu;
347
348 snprintf(buf, sizeof(buf), "HOST_ASLEEP=%s", asleep ? "asleep" : "awake");
349 A_MEMZERO(&wrqu, sizeof(wrqu));
350 wrqu.data.length = strlen(buf);
351 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
352 }
353
354 static void ar6000_wow_resume(AR_SOFTC_T *ar)
355 {
356 if (ar->arWowState!=WOW_STATE_NONE) {
357 A_UINT16 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->s cParams.fg_start_period;
358 A_UINT16 bg_period = (ar->scParams.bg_period==0) ? 60 : ar->scParams.bg_ period;
359 WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {TRUE, FALSE};
360 ar->arWowState = WOW_STATE_NONE;
361 wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ);
362 if (wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)!=A_OK) {
363 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup restore host awake\n") );
364 }
365 #if WOW_SET_SCAN_PARAMS
366 wmi_scanparams_cmd(ar->arWmi, fg_start_period,
367 ar->scParams.fg_end_period,
368 bg_period,
369 ar->scParams.minact_chdwell_time,
370 ar->scParams.maxact_chdwell_time,
371 ar->scParams.pas_chdwell_time,
372 ar->scParams.shortScanRatio,
373 ar->scParams.scanCtrlFlags,
374 ar->scParams.max_dfsch_act_time,
375 ar->scParams.maxact_scan_per_ssid);
376 #else
377 (void)fg_start_period;
378 (void)bg_period;
379 #endif
380
381
382 #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is alread y good enough. */
383 if (wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListe nIntervalB) == A_OK) {
384 }
385 #endif
386 ar6k_send_asleep_event_to_app(ar, FALSE);
387 AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND, ("Resume WoW successfully\n"));
388 } else {
389 AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND, ("WoW does not invoked. skip resume") );
390 }
391 }
392
393 static void ar6000_wow_suspend(AR_SOFTC_T *ar)
394 {
395 #define ANDROID_WOW_LIST_ID 1
396 if (ar->arNetworkType != AP_NETWORK) {
397 /* Setup WoW for unicast & Arp request for our own IP
398 disable background scan. Set listen interval into 1000 TUs
399 Enable keepliave for 110 seconds
400 */
401 struct in_ifaddr **ifap = NULL;
402 struct in_ifaddr *ifa = NULL;
403 struct in_device *in_dev;
404 A_UINT8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
405 A_STATUS status;
406 WMI_ADD_WOW_PATTERN_CMD addWowCmd = { .filter = { 0 } };
407 WMI_DEL_WOW_PATTERN_CMD delWowCmd;
408 WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {FALSE, TRUE};
409 WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = TRUE,
410 .hostReqDelay = 500 };/*500 ms delay */
411
412 if (ar->arWowState!=WOW_STATE_NONE) {
413 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("System already go into wow mode!\n") );
414 return;
415 }
416
417 ar6000_TxDataCleanup(ar); /* IMPORTANT, otherwise there will be 11mA aft er listen interval as 1000*/
418
419 #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is alread y good enough. */
420 if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == A _OK) {
421 }
422 #endif
423
424 #if WOW_SET_SCAN_PARAMS
425 status = wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0);
426 #endif
427 /* clear up our WoW pattern first */
428 delWowCmd.filter_list_id = ANDROID_WOW_LIST_ID;
429 delWowCmd.filter_id = 0;
430 wmi_del_wow_pattern_cmd(ar->arWmi, &delWowCmd);
431
432 /* setup unicast packet pattern for WoW */
433 if (ar->arNetDev->dev_addr[1]) {
434 addWowCmd.filter_list_id = ANDROID_WOW_LIST_ID;
435 addWowCmd.filter_size = 6; /* MAC address */
436 addWowCmd.filter_offset = 0;
437 status = wmi_add_wow_pattern_cmd(ar->arWmi, &addWowCmd, ar->arNetDev ->dev_addr, macMask, addWowCmd.filter_size);
438 if (status != A_OK) {
439 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to add WoW pattern\n"));
440 }
441 }
442 /* setup ARP request for our own IP */
443 if ((in_dev = __in_dev_get_rtnl(ar->arNetDev)) != NULL) {
444 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->i fa_next) {
445 if (!strcmp(ar->arNetDev->name, ifa->ifa_label)) {
446 break; /* found */
447 }
448 }
449 }
450 if (ifa && ifa->ifa_local) {
451 WMI_SET_IP_CMD ipCmd;
452 memset(&ipCmd, 0, sizeof(ipCmd));
453 ipCmd.ips[0] = ifa->ifa_local;
454 status = wmi_set_ip_cmd(ar->arWmi, &ipCmd);
455 if (status != A_OK) {
456 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup IP for ARP agent\n "));
457 }
458 }
459
460 #ifndef ATH6K_CONFIG_OTA_MODE
461 wmi_powermode_cmd(ar->arWmi, REC_POWER);
462 #endif
463
464 status = wmi_set_wow_mode_cmd(ar->arWmi, &wowMode);
465 if (status != A_OK) {
466 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enable wow mode\n"));
467 }
468 ar6k_send_asleep_event_to_app(ar, TRUE);
469
470 status = wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode);
471 if (status != A_OK) {
472 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to set host asleep\n"));
473 }
474
475 ar->arWowState = WOW_STATE_SUSPENDING;
476 if (ar->arTxPending[ar->arControlEp]) {
477 long timeleft = wait_event_interruptible_timeout(arEvent,
478 ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ);
479 if (!timeleft || signal_pending(current)) {
480 /* what can I do? wow resume at once */
481 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WoW. Pending wmi c ontrol data %d\n", ar->arTxPending[ar->arControlEp]));
482 }
483 }
484 } else {
485 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Not allowed to go to WOW at this moment. \n"));
486 }
487 }
488
489 static void ar6000_pwr_on(AR_SOFTC_T *ar)
490 {
491 if (ar == NULL) {
492 /* turn on for all cards */
493 }
494 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s --enter\n", __FUNCTION__));
495
496 }
497
498 static void ar6000_pwr_down(AR_SOFTC_T *ar)
499 {
500 if (ar == NULL) {
501 /* shutdown for all cards */
502 }
503 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s --enter\n", __FUNCTION__));
504
505 }
506
507 static A_STATUS ar6000_suspend_ev(void *context)
508 {
509 A_STATUS status = A_OK;
510 int pmmode = buspm;
511 AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
512 wow_not_connected:
513
514 switch (pmmode) {
515 case WLAN_PWR_CTRL_DEEP_SLEEP:
516 if (ar->arWlanState == WLAN_DISABLED) {
517 ar->arOsPowerCtrl = WLAN_PWR_CTRL_DEEP_SLEEP_DISABLED;
518 AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND,("%s:Suspend for deep sleep disabl ed mode %d\n", __func__, ar->arOsPowerCtrl));
519 } else {
520 ar6000_set_wlan_state(ar, WLAN_DISABLED);
521 ar->arOsPowerCtrl = WLAN_PWR_CTRL_DEEP_SLEEP;
522 AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND,("%s:Suspend for deep sleep mode % d\n", __func__, ar->arOsPowerCtrl));
523 }
524 status = A_EBUSY;
525 break;
526 case WLAN_PWR_CTRL_WOW:
527 if (ar->arWmiReady && ar->arWlanState==WLAN_ENABLED && ar->arConnected) {
528 ar->arOsPowerCtrl = WLAN_PWR_CTRL_WOW;
529 AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND,("%s:Suspend for wow mode %d\n", _ _func__, ar->arOsPowerCtrl));
530 ar6000_wow_suspend(ar);
531 /* leave for pm_device to setup wow */
532 status = A_EBUSY;
533 } else {
534 pmmode = wow2mode;
535 goto wow_not_connected;
536 }
537 break;
538 case WLAN_PWR_CTRL_CUT_PWR:
539 /* fall through */
540 default:
541 ar->arOsPowerCtrl = WLAN_PWR_CTRL_CUT_PWR;
542 AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND,("%s: Suspend for cut off mode %d\n", __func__, ar->arOsPowerCtrl));
543 ar6000_stop_endpoint(ar->arNetDev, TRUE);
544 status = A_OK;
545 break;
546 }
547
548 ar->scan_triggered = 0;
549 return status;
550 }
551
552 static A_STATUS ar6000_resume_ev(void *context)
553 {
554 AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
555 A_UINT16 powerCtrl = ar->arOsPowerCtrl;
556 wake_lock(&ar6k_init_wake_lock);
557 AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND, ("%s: enter previous state %d wowState %d \n", __func__, powerCtrl, ar->arWowState));
558 ar->arOsPowerCtrl = WLAN_PWR_CTRL_UP;
559 switch (powerCtrl) {
560 case WLAN_PWR_CTRL_WOW:
561 ar6000_wow_resume(ar);
562 break;
563 case WLAN_PWR_CTRL_CUT_PWR:
564 ar6000_restart_endpoint(ar->arNetDev);
565 break;
566 case WLAN_PWR_CTRL_DEEP_SLEEP:
567 ar6000_set_wlan_state(ar, WLAN_ENABLED);
568 break;
569 case WLAN_PWR_CTRL_DEEP_SLEEP_DISABLED:
570 break;
571 case WLAN_PWR_CTRL_UP:
572 break;
573 default:
574 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange SDIO bus power mode!!\n"));
575 break;
576 }
577 wake_unlock(&ar6k_init_wake_lock);
578 return A_OK;
579 }
580
581 static A_STATUS ar6000_android_avail_ev(void *context, void *hif_handle) 280 static A_STATUS ar6000_android_avail_ev(void *context, void *hif_handle)
582 { 281 {
583 A_STATUS ret; 282 A_STATUS ret;
283 #ifdef CONFIG_HAS_WAKELOCK
584 wake_lock(&ar6k_init_wake_lock); 284 wake_lock(&ar6k_init_wake_lock);
285 #endif
585 ar6000_enable_mmchost_detect_change(0); 286 ar6000_enable_mmchost_detect_change(0);
586 ret = ar6000_avail_ev_p(context, hif_handle); 287 ret = ar6000_avail_ev_p(context, hif_handle);
288 #ifdef CONFIG_HAS_WAKELOCK
587 wake_unlock(&ar6k_init_wake_lock); 289 wake_unlock(&ar6k_init_wake_lock);
290 #endif
588 return ret; 291 return ret;
589 } 292 }
590 293
591
592 static int ar6000_pm_suspend(struct platform_device *dev, pm_message_t state)
593 {
594 int i;
595 for (i = 0; i < MAX_AR6000; i++) {
596 AR_SOFTC_T *ar;
597
598 if (ar6000_devices[i] == NULL)
599 continue;
600 ar = (AR_SOFTC_T*)netdev_priv(ar6000_devices[i]);
601 AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND,("%s: enter status %d\n", __func__, ar ->arOsPowerCtrl));
602 switch (ar->arOsPowerCtrl) {
603 case WLAN_PWR_CTRL_CUT_PWR:
604 ar6000_pwr_down(ar);
605 break;
606 case WLAN_PWR_CTRL_WOW:
607 if (ar->arTxPending[ar->arControlEp]) {
608 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WoW. Pending wmi c ontrol data %d\n", ar->arTxPending[ar->arControlEp]));
609 ar->arWowState = WOW_STATE_NONE;
610 } else {
611 ar->arWowState = WOW_STATE_SUSPENDED;
612 AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND,("Setup WoW successfully\n"));
613 }
614 break;
615 case WLAN_PWR_CTRL_DEEP_SLEEP:
616 /* fall through */
617 case WLAN_PWR_CTRL_DEEP_SLEEP_DISABLED:
618 /* nothing to do. keep the power on */
619 break;
620 default:
621 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Something is strange for ar6000_pm_s uspend %d\n", ar->arOsPowerCtrl));
622 break;
623 }
624 }
625 return 0;
626 }
627
628 static int ar6000_pm_resume(struct platform_device *dev)
629 {
630 int i;
631 for (i = 0; i < MAX_AR6000; i++) {
632 AR_SOFTC_T *ar;
633
634 if (ar6000_devices[i] == NULL)
635 continue;
636 ar = (AR_SOFTC_T*)netdev_priv(ar6000_devices[i]);
637 AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND,("%s: enter status %d\n", __func__, ar ->arOsPowerCtrl));
638 switch (ar->arOsPowerCtrl) {
639 case WLAN_PWR_CTRL_CUT_PWR:
640 ar6000_pwr_on(ar);
641 break;
642 case WLAN_PWR_CTRL_WOW:
643 /* nothing to do. keep the power on */
644 break;
645 case WLAN_PWR_CTRL_DEEP_SLEEP:
646 /* fall through */
647 case WLAN_PWR_CTRL_DEEP_SLEEP_DISABLED:
648 /* nothing to do. keep the power on */
649 break;
650 default:
651 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Something is strange for ar6000_pm_r esume %d\n", ar->arOsPowerCtrl));
652 break;
653 }
654 }
655 return 0;
656 }
657
658 static int ar6000_pm_probe(struct platform_device *pdev)
659 {
660 ar6000_pwr_on(NULL);
661 return 0;
662 }
663
664 static int ar6000_pm_remove(struct platform_device *pdev)
665 {
666 ar6000_pwr_down(NULL);
667 return 0;
668 }
669
670 static struct platform_driver ar6000_pm_device = {
671 .probe = ar6000_pm_probe,
672 .remove = ar6000_pm_remove,
673 .suspend = ar6000_pm_suspend,
674 .resume = ar6000_pm_resume,
675 .driver = {
676 .name = "wlan_ar6000_pm_dev",
677 },
678 };
679 #endif /* CONFIG_PM */
680
681 /* Useful for qualcom platform to detect our wlan card for mmc stack */ 294 /* Useful for qualcom platform to detect our wlan card for mmc stack */
682 static void ar6000_enable_mmchost_detect_change(int enable) 295 static void ar6000_enable_mmchost_detect_change(int enable)
683 { 296 {
684 #ifdef CONFIG_MMC_MSM 297 #ifdef CONFIG_MMC_MSM
685 #define MMC_MSM_DEV "msm_sdcc.1" 298 #define MMC_MSM_DEV "msm_sdcc.1"
686 char buf[3]; 299 char buf[3];
687 int length; 300 int length;
301
302 if (!enable_mmc_host_detect_change) {
303 return;
304 }
688 length = snprintf(buf, sizeof(buf), "%d\n", enable ? 1 : 0); 305 length = snprintf(buf, sizeof(buf), "%d\n", enable ? 1 : 0);
689 if (android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV "/detect_cha nge", 306 if (android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV "/detect_cha nge",
690 NULL, buf, length) < 0) { 307 NULL, buf, length) < 0) {
691 /* fall back to polling */ 308 /* fall back to polling */
692 android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV "/polling", NULL, buf, length); 309 android_readwrite_file("/sys/devices/platform/" MMC_MSM_DEV "/polling", NULL, buf, length);
693 } 310 }
694 #endif 311 #endif
695 } 312 }
696 313
697 static void
698 ar6000_restart_endpoint(struct net_device *dev)
699 {
700 A_STATUS status = A_OK;
701 AR_SOFTC_T *ar = (AR_SOFTC_T*)netdev_priv(dev);
702 if (down_interruptible(&ar->arSem)) {
703 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s(): down_interruptible failed \n", __ func__));
704 return ;
705 }
706 if (ar->bIsDestroyProgress) {
707 up(&ar->arSem);
708 return;
709 }
710 BMIInit();
711 do {
712 if ( (status=ar6000_configure_target(ar))!=A_OK)
713 break;
714 if ( (status=ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != A _OK)
715 {
716 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_sys fs_bmi_get_config failed\n"));
717 break;
718 }
719 rtnl_lock();
720 status = (ar6000_init(dev)==0) ? A_OK : A_ERROR;
721 rtnl_unlock();
722
723 if (status!=A_OK) {
724 break;
725 }
726 if (ar->arWlanState==WLAN_ENABLED) {
727 if (ar->arSsidLen) {
728 ar6000_connect_to_ap(ar);
729 }
730 } else {
731 WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = FALSE };
732 WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = { .awake = FALSE, .aslee p = TRUE };
733 WMI_REPORT_SLEEP_STATE_EVENT wmiSleepEvent = {
734 .sleepState = WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP
735 };
736
737 wmi_set_wow_mode_cmd(ar->arWmi, &wowMode);
738 ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (A_UINT 8*)&wmiSleepEvent,
739 sizeof(WMI_REPORT_SLEEP_STATE_EVENTID));
740 wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode);
741 }
742 } while (0);
743
744 up(&ar->arSem);
745 if (status==A_OK) {
746 return;
747 }
748
749 ar6000_devices[ar->arDeviceIndex] = NULL;
750 ar6000_destroy(ar->arNetDev, 1);
751 }
752
753 #ifdef CONFIG_HAS_EARLYSUSPEND 314 #ifdef CONFIG_HAS_EARLYSUSPEND
754 static void android_early_suspend(struct early_suspend *h) 315 static void android_early_suspend(struct early_suspend *h)
755 { 316 {
756 screen_is_off = 1; 317 screen_is_off = 1;
757 } 318 }
758 319
759 static void android_late_resume(struct early_suspend *h) 320 static void android_late_resume(struct early_suspend *h)
760 { 321 {
761 screen_is_off = 0; 322 screen_is_off = 0;
762 } 323 }
763 #endif 324 #endif
764 325
765 void android_module_init(OSDRV_CALLBACKS *osdrvCallbacks) 326 void android_module_init(OSDRV_CALLBACKS *osdrvCallbacks)
766 { 327 {
767 bmienable = 1; 328 bmienable = 1;
768 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
769 if (ifname[0] == '\0') 329 if (ifname[0] == '\0')
770 strcpy(ifname, def_ifname); 330 strcpy(ifname, def_ifname);
771 #endif 331 #ifdef CONFIG_HAS_WAKELOCK
772 if (wow2mode!=WLAN_PWR_CTRL_CUT_PWR && wow2mode!=WLAN_PWR_CTRL_DEEP_SLEEP) {
773 wow2mode=WLAN_PWR_CTRL_CUT_PWR;
774 }
775
776 wake_lock_init(&ar6k_init_wake_lock, WAKE_LOCK_SUSPEND, "ar6k_init"); 332 wake_lock_init(&ar6k_init_wake_lock, WAKE_LOCK_SUSPEND, "ar6k_init");
777 wake_lock_init(&ar6k_wow_wake_lock, WAKE_LOCK_SUSPEND, "ar6k_wow"); 333 #endif
778
779 #ifdef CONFIG_HAS_EARLYSUSPEND 334 #ifdef CONFIG_HAS_EARLYSUSPEND
780 ar6k_early_suspend.suspend = android_early_suspend; 335 ar6k_early_suspend.suspend = android_early_suspend;
781 ar6k_early_suspend.resume = android_late_resume; 336 ar6k_early_suspend.resume = android_late_resume;
782 ar6k_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; 337 ar6k_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
783 register_early_suspend(&ar6k_early_suspend); 338 register_early_suspend(&ar6k_early_suspend);
784 #endif 339 #endif
785 340
786 #if defined(CONFIG_PM)
787 osdrvCallbacks->deviceSuspendHandler = ar6000_suspend_ev;
788 osdrvCallbacks->deviceResumeHandler = ar6000_resume_ev;
789 #endif
790 ar6000_avail_ev_p = osdrvCallbacks->deviceInsertedHandler; 341 ar6000_avail_ev_p = osdrvCallbacks->deviceInsertedHandler;
791 osdrvCallbacks->deviceInsertedHandler = ar6000_android_avail_ev; 342 osdrvCallbacks->deviceInsertedHandler = ar6000_android_avail_ev;
792 343
793 #if defined(CONFIG_PM)
794 /* Register ar6000_pm_device into system.
795 * We should also add platform_device into the first item of array devices[] in
796 * file arch/xxx/mach-xxx/board-xxxx.c
797 * Otherwise, WoW may not work properly since we may trigger WoW GPIO before system suspend
798 */
799 if (platform_driver_register(&ar6000_pm_device))
800 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000: fail to register the power contr ol driver.\n"));
801 #endif
802
803 ar6000_enable_mmchost_detect_change(1); 344 ar6000_enable_mmchost_detect_change(1);
804 } 345 }
805 346
806 void android_module_exit(void) 347 void android_module_exit(void)
807 { 348 {
808 #ifdef CONFIG_HAS_EARLYSUSPEND 349 #ifdef CONFIG_HAS_EARLYSUSPEND
809 unregister_early_suspend(&ar6k_early_suspend); 350 unregister_early_suspend(&ar6k_early_suspend);
810 #endif 351 #endif
811 wake_lock_destroy(&ar6k_wow_wake_lock); 352 #ifdef CONFIG_HAS_WAKELOCK
812 wake_lock_destroy(&ar6k_init_wake_lock); 353 wake_lock_destroy(&ar6k_init_wake_lock);
813
814 #ifdef CONFIG_PM
815 platform_driver_unregister(&ar6000_pm_device);
816 #endif 354 #endif
817 ar6000_enable_mmchost_detect_change(1); 355 ar6000_enable_mmchost_detect_change(1);
818 } 356 }
819 357
820 A_BOOL android_ar6k_endpoint_is_stop(AR_SOFTC_T *ar)
821 {
822 #ifdef CONFIG_PM 358 #ifdef CONFIG_PM
823 return ar->arOsPowerCtrl == WLAN_PWR_CTRL_CUT_PWR;
824 #else
825 return FALSE;
826 #endif
827 }
828
829 void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL i sEvent) 359 void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL i sEvent)
830 { 360 {
831 #ifdef CONFIG_PM 361 if (
832 if (ar->arWowState!=WOW_STATE_NONE) { 362 #ifdef CONFIG_HAS_EARLYSUSPEND
833 if (ar->arWowState==WOW_STATE_SUSPENDING) { 363 screen_is_off &&
834 AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND,("%s: Received IRQ while we are wo w suspending!!!\n", __func__)); 364 #endif
835 return; 365 skb && ar->arConnected) {
836 }
837 /* Wow resume from irq interrupt */
838 AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND, ("%s: WoW resume from irq thread stat us %d\n",
839 __func__, ar->arOsPowerCtrl));
840 ar6000_wow_resume(ar);
841 ar->arOsPowerCtrl = WLAN_PWR_CTRL_UP;
842 } else if (screen_is_off && skb && ar->arConnected) {
843 A_BOOL needWake = FALSE; 366 A_BOOL needWake = FALSE;
844 if (isEvent) { 367 if (isEvent) {
845 if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) { 368 if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) {
846 A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb); 369 A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb);
847 switch (cmd) { 370 switch (cmd) {
848 case WMI_CONNECT_EVENTID: 371 case WMI_CONNECT_EVENTID:
849 case WMI_DISCONNECT_EVENTID: 372 case WMI_DISCONNECT_EVENTID:
850 needWake = TRUE; 373 needWake = TRUE;
851 break; 374 break;
852 default: 375 default:
(...skipping 12 matching lines...) Expand all
865 needWake = TRUE; 388 needWake = TRUE;
866 break; 389 break;
867 case 0x0806: /* ARP is not important to hold wake lock */ 390 case 0x0806: /* ARP is not important to hold wake lock */
868 default: 391 default:
869 break; 392 break;
870 } 393 }
871 } 394 }
872 } 395 }
873 if (needWake) { 396 if (needWake) {
874 /* keep host wake up if there is any event and packate comming in*/ 397 /* keep host wake up if there is any event and packate comming in*/
398 #ifdef CONFIG_HAS_WAKELOCK
875 wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ); 399 wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ);
400 #endif
876 if (wowledon) { 401 if (wowledon) {
877 char buf[32]; 402 char buf[32];
878 int len = sprintf(buf, "on"); 403 int len = sprintf(buf, "on");
879 android_readwrite_file("/sys/power/state", NULL, buf, len); 404 android_readwrite_file("/sys/power/state", NULL, buf, len);
880 405
881 len = sprintf(buf, "%d", 127); 406 len = sprintf(buf, "%d", 127);
882 android_readwrite_file("/sys/class/leds/lcd-backlight/brightness ", 407 android_readwrite_file("/sys/class/leds/lcd-backlight/brightness ",
883 NULL, buf,len); 408 NULL, buf,len);
884 } 409 }
885 } 410 }
886 } 411 }
412 }
887 #endif /* CONFIG_PM */ 413 #endif /* CONFIG_PM */
888 }
889
890 A_STATUS android_ar6k_start(AR_SOFTC_T *ar)
891 {
892 if (!bypasswmi) {
893 #ifdef ATH6K_CONFIG_OTA_MODE
894 wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER);
895 #endif
896 wmi_disctimeout_cmd(ar->arWmi, 3);
897
898 }
899 return A_OK;
900 }
OLDNEW
« no previous file with comments | « chromeos/drivers/ath6kl/miscdrv/miscdrv.h ('k') | chromeos/drivers/ath6kl/os/linux/ar6000_drv.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698