blob: 275eeaf6d3e86a2cb0e1b2b721f5959075ea2dd7 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Abhishek Singh64ecee22016-01-04 15:44:04 +05302 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Jeff Johnson295189b2012-06-20 16:38:30 -070028/**=========================================================================
29
30 EDIT HISTORY FOR FILE
31
32
33 This section contains comments describing changes made to the module.
34 Notice that changes are listed in reverse chronological order.
35
36
37 $Header:$ $DateTime: $ $Author: $
38
39
40 when who what, where, why
41 -------- --- --------------------------------------------------------
42 03/29/11 tbh Created module.
43
44 ==========================================================================*/
45
46/*----------------------------------------------------------------------------
47 * Include Files
48 * -------------------------------------------------------------------------*/
49#include <wlan_hdd_dev_pwr.h>
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053050#include <vos_sched.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070051#ifdef ANI_BUS_TYPE_PLATFORM
52#include <linux/wcnss_wlan.h>
53#else
54#include <wcnss_wlan.h>
55#endif // ANI_BUS_TYP_PLATFORM
56
57/*----------------------------------------------------------------------------
58 * Preprocessor Definitions and Constants
59 * -------------------------------------------------------------------------*/
60
61/*----------------------------------------------------------------------------
62 * Type Declarations
63 * -------------------------------------------------------------------------*/
64
65
66/*-------------------------------------------------------------------------
67 * Global variables.
68 *-------------------------------------------------------------------------*/
69
70/*-------------------------------------------------------------------------
71 * Local variables.
72 *-------------------------------------------------------------------------*/
73/* Reference VoIP, 100msec delay make disconnect.
74 * So TX sleep must be less than 100msec
75 * Every 20msec TX frame will goes out.
76 * 10 frame means 2seconds TX operation */
77static const hdd_tmLevelAction_t thermalMigrationAction[WLAN_HDD_TM_LEVEL_MAX] =
78{
79 /* TM Level 0, Do nothing, just normal operaton */
80 {1, 0, 0, 0, 0xFFFFF},
81 /* Tm Level 1, disable TX AMPDU */
82 {0, 0, 0, 0, 0xFFFFF},
83 /* TM Level 2, disable AMDPU,
84 * TX sleep 100msec if TX frame count is larger than 16 during 300msec */
85 {0, 0, 100, 300, 16},
86 /* TM Level 3, disable AMDPU,
87 * TX sleep 500msec if TX frame count is larger than 11 during 500msec */
88 {0, 0, 500, 500, 11},
89 /* TM Level 4, MAX TM level, enter IMPS */
90 {0, 1, 1000, 500, 10}
91};
Sravan Kumar Kairam8a09a9f2016-08-04 13:18:25 +053092
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080093#ifdef HAVE_WCNSS_SUSPEND_RESUME_NOTIFY
94static bool suspend_notify_sent;
95#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070096
97
Abhishek Singhd987f3e2016-01-05 17:09:57 +053098#ifdef FEATURE_WLAN_DIAG_SUPPORT
99/**
100 * hdd_wlan_suspend_resume_event()- send suspend/resume state
101 *
102 * @state: suspend/resume state
103 *
104 * This Function send send suspend resume state diag event
105 *
106 * Return: void.
107 */
108void hdd_wlan_suspend_resume_event(uint8_t state)
109{
110 WLAN_VOS_DIAG_EVENT_DEF(suspend_state,
111 struct vos_event_suspend);
112 vos_mem_zero( &suspend_state,
113 sizeof(suspend_state));
114
115 suspend_state.state= state;
116 WLAN_VOS_DIAG_EVENT_REPORT(&suspend_state,
117 EVENT_WLAN_SUSPEND_RESUME);
118
119}
120#endif
121
122
Jeff Johnson295189b2012-06-20 16:38:30 -0700123/*----------------------------------------------------------------------------
124
125 @brief Function to suspend the wlan driver.
126
127 @param hdd_context_t pHddCtx
128 Global hdd context
129
130
131 @return None
132
133----------------------------------------------------------------------------*/
134static int wlan_suspend(hdd_context_t* pHddCtx)
135{
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530136 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700137
138 pVosSchedContext vosSchedContext = NULL;
139
140 /* Get the global VOSS context */
141 vosSchedContext = get_vos_sched_ctxt();
142
143 if(!vosSchedContext) {
144 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: Global VOS_SCHED context is Null",__func__);
145 return 0;
146 }
Abhishek Singh837adf22015-10-01 17:37:37 +0530147
148 if (!pHddCtx->last_suspend_success)
149 pHddCtx->last_suspend_success = vos_timer_get_system_time();
150
151 if (!vos_is_apps_power_collapse_allowed(pHddCtx))
Jeff Johnson295189b2012-06-20 16:38:30 -0700152 {
153 /* Fail this suspend */
Abhishek Singh837adf22015-10-01 17:37:37 +0530154 pHddCtx->continuous_suspend_fail_cnt++;
SaidiReddy Yenugaf62fcd12016-07-27 19:29:18 +0530155 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Abhishek Singh837adf22015-10-01 17:37:37 +0530156 FL("Fail wlan suspend: not in IMPS/BMPS, continuous Failcnt %d"),
157 pHddCtx->continuous_suspend_fail_cnt);
158
159 /* call fatal event if power collapse fails for
160 * WLAN_POWER_COLLAPSE_FAIL_THRESHOLD time.
161 */
162 if ((vos_timer_get_system_time() - pHddCtx->last_suspend_success) >=
163 WLAN_POWER_COLLAPSE_FAIL_THRESHOLD)
164 {
165 pHddCtx->last_suspend_success = 0;
166 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
167 WLAN_LOG_INDICATOR_HOST_DRIVER,
168 WLAN_LOG_REASON_POWER_COLLAPSE_FAIL,
169 FALSE, TRUE);
170 }
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800171 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -0700172 }
Abhishek Singh837adf22015-10-01 17:37:37 +0530173 pHddCtx->continuous_suspend_fail_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700174 /*
175 Suspending MC Thread, Rx Thread and Tx Thread as the platform driver is going to Suspend.
176 */
177 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Suspending Mc, Rx and Tx Threads",__func__);
178
Gopichand Nakkala05621412013-06-19 19:37:38 +0530179 INIT_COMPLETION(pHddCtx->tx_sus_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700180
181 /* Indicate Tx Thread to Suspend */
Mahesh A Saptasagard4b89fa2016-02-24 16:22:45 +0530182 set_bit(TX_SUSPEND_EVENT, &vosSchedContext->txEventFlag);
Jeff Johnson295189b2012-06-20 16:38:30 -0700183
184 wake_up_interruptible(&vosSchedContext->txWaitQueue);
185
186 /* Wait for Suspend Confirmation from Tx Thread */
187 rc = wait_for_completion_interruptible_timeout(&pHddCtx->tx_sus_event_var, msecs_to_jiffies(200));
188
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530189 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700190 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530191 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530192 "%s: TX Thread: timeout while suspending %ld"
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530193 , __func__, rc);
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530194 /* There is a race condition here, where the TX Thread can process the
195 * SUSPEND_EVENT even after the wait_for_completion has timed out.
196 * Check the SUSPEND_EVENT_MASK, if it is already cleared by the TX
197 * Thread then it means it is going to suspend, so do not return failure
198 * from here.
199 */
Mahesh A Saptasagard4b89fa2016-02-24 16:22:45 +0530200 if (!test_and_clear_bit(TX_SUSPEND_EVENT,
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530201 &vosSchedContext->txEventFlag))
202 {
203 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
204 "%s: TX Thread: will still suspend", __func__);
205 goto tx_suspend;
206 }
Abhishek Singh837adf22015-10-01 17:37:37 +0530207 /* call fatal event if suspend for
208 * WLAN_POWER_COLLAPSE_FAIL_THRESHOLD time.
209 */
210 if ((vos_timer_get_system_time() - pHddCtx->last_suspend_success) >=
211 WLAN_POWER_COLLAPSE_FAIL_THRESHOLD)
212 {
213 pHddCtx->last_suspend_success = 0;
214 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
215 WLAN_LOG_INDICATOR_HOST_DRIVER,
216 WLAN_LOG_REASON_POWER_COLLAPSE_FAIL,
217 FALSE, TRUE);
218 }
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800219 return -ETIME;
Jeff Johnson295189b2012-06-20 16:38:30 -0700220 }
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530221
222tx_suspend:
Jeff Johnson295189b2012-06-20 16:38:30 -0700223 /* Set the Tx Thread as Suspended */
224 pHddCtx->isTxThreadSuspended = TRUE;
225
Gopichand Nakkala05621412013-06-19 19:37:38 +0530226 INIT_COMPLETION(pHddCtx->rx_sus_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700227
228 /* Indicate Rx Thread to Suspend */
Mahesh A Saptasagard4b89fa2016-02-24 16:22:45 +0530229 set_bit(RX_SUSPEND_EVENT, &vosSchedContext->rxEventFlag);
Jeff Johnson295189b2012-06-20 16:38:30 -0700230
231 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
232
233 /* Wait for Suspend Confirmation from Rx Thread */
234 rc = wait_for_completion_interruptible_timeout(&pHddCtx->rx_sus_event_var, msecs_to_jiffies(200));
235
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530236 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700237 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530238 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530239 "%s: RX Thread: timeout while suspending %ld", __func__, rc);
240 /* There is a race condition here, where the RX Thread can process the
241 * SUSPEND_EVENT even after the wait_for_completion has timed out.
242 * Check the SUSPEND_EVENT_MASK, if it is already cleared by the RX
243 * Thread then it means it is going to suspend, so do not return failure
244 * from here.
245 */
Mahesh A Saptasagard4b89fa2016-02-24 16:22:45 +0530246 if (!test_and_clear_bit(RX_SUSPEND_EVENT,
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530247 &vosSchedContext->rxEventFlag))
248 {
249 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
250 "%s: RX Thread: will still suspend", __func__);
251 goto rx_suspend;
252 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700253
254 /* Indicate Tx Thread to Resume */
255 complete(&vosSchedContext->ResumeTxEvent);
256
257 /* Set the Tx Thread as Resumed */
258 pHddCtx->isTxThreadSuspended = FALSE;
Abhishek Singh837adf22015-10-01 17:37:37 +0530259 /* call fatal event if suspend for
260 * WLAN_POWER_COLLAPSE_FAIL_THRESHOLD time.
261 */
262 if ((vos_timer_get_system_time() - pHddCtx->last_suspend_success) >=
263 WLAN_POWER_COLLAPSE_FAIL_THRESHOLD)
264 {
265 pHddCtx->last_suspend_success = 0;
266 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
267 WLAN_LOG_INDICATOR_HOST_DRIVER,
268 WLAN_LOG_REASON_POWER_COLLAPSE_FAIL,
269 FALSE, TRUE);
270 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700271
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800272 return -ETIME;
Jeff Johnson295189b2012-06-20 16:38:30 -0700273 }
274
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530275rx_suspend:
Jeff Johnson295189b2012-06-20 16:38:30 -0700276 /* Set the Rx Thread as Suspended */
277 pHddCtx->isRxThreadSuspended = TRUE;
278
Gopichand Nakkala05621412013-06-19 19:37:38 +0530279 INIT_COMPLETION(pHddCtx->mc_sus_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700280
281 /* Indicate MC Thread to Suspend */
Mahesh A Saptasagard4b89fa2016-02-24 16:22:45 +0530282 set_bit(MC_SUSPEND_EVENT, &vosSchedContext->mcEventFlag);
Jeff Johnson295189b2012-06-20 16:38:30 -0700283
284 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
285
286 /* Wait for Suspend Confirmation from MC Thread */
Abhishek Singh64ecee22016-01-04 15:44:04 +0530287 rc = wait_for_completion_interruptible_timeout(&pHddCtx->mc_sus_event_var,
288 msecs_to_jiffies(200));
Jeff Johnson295189b2012-06-20 16:38:30 -0700289
Abhishek Singh64ecee22016-01-04 15:44:04 +0530290 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700291 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530293 "%s: MC Thread: timeout while suspending %ld",
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530294 __func__, rc);
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530295 /* There is a race condition here, where the MC Thread can process the
296 * SUSPEND_EVENT even after the wait_for_completion has timed out.
297 * Check the SUSPEND_EVENT_MASK, if it is already cleared by the MC
298 * Thread then it means it is going to suspend, so do not return failure
299 * from here.
300 */
Mahesh A Saptasagard4b89fa2016-02-24 16:22:45 +0530301 if (!test_and_clear_bit(MC_SUSPEND_EVENT,
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530302 &vosSchedContext->mcEventFlag))
303 {
304 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
305 "%s: MC Thread: will still suspend", __func__);
306 goto mc_suspend;
307 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700308
309 /* Indicate Rx Thread to Resume */
310 complete(&vosSchedContext->ResumeRxEvent);
311
312 /* Set the Rx Thread as Resumed */
313 pHddCtx->isRxThreadSuspended = FALSE;
314
315 /* Indicate Tx Thread to Resume */
316 complete(&vosSchedContext->ResumeTxEvent);
317
318 /* Set the Tx Thread as Resumed */
319 pHddCtx->isTxThreadSuspended = FALSE;
320
Abhishek Singh837adf22015-10-01 17:37:37 +0530321 /* call fatal event if suspend for
322 * WLAN_POWER_COLLAPSE_FAIL_THRESHOLD time.
323 */
324 if ((vos_timer_get_system_time() - pHddCtx->last_suspend_success) >=
325 WLAN_POWER_COLLAPSE_FAIL_THRESHOLD)
326 {
327 pHddCtx->last_suspend_success = 0;
328 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
329 WLAN_LOG_INDICATOR_HOST_DRIVER,
330 WLAN_LOG_REASON_POWER_COLLAPSE_FAIL,
331 FALSE, TRUE);
332 }
333
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800334 return -ETIME;
Jeff Johnson295189b2012-06-20 16:38:30 -0700335 }
336
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530337mc_suspend:
Jeff Johnson295189b2012-06-20 16:38:30 -0700338 /* Set the Mc Thread as Suspended */
339 pHddCtx->isMcThreadSuspended = TRUE;
340
341 /* Set the Station state as Suspended */
342 pHddCtx->isWlanSuspended = TRUE;
Abhishek Singh837adf22015-10-01 17:37:37 +0530343 pHddCtx->last_suspend_success = 0;
Sravan Kumar Kairam8a09a9f2016-08-04 13:18:25 +0530344 pHddCtx->rx_wow_dump = true;
Abhishek Singhd987f3e2016-01-05 17:09:57 +0530345 hdd_wlan_suspend_resume_event(HDD_WLAN_SUSPEND);
Jeff Johnson295189b2012-06-20 16:38:30 -0700346 return 0;
347}
348
349/*----------------------------------------------------------------------------
350
351 @brief Function to resume the wlan driver.
352
353 @param hdd_context_t pHddCtx
354 Global hdd context
355
356
357 @return None
358
359----------------------------------------------------------------------------*/
360static void wlan_resume(hdd_context_t* pHddCtx)
361{
362 pVosSchedContext vosSchedContext = NULL;
363
364 //Get the global VOSS context.
365 vosSchedContext = get_vos_sched_ctxt();
366
367 if(!vosSchedContext) {
368 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: Global VOS_SCHED context is Null",__func__);
369 return;
370 }
371
372 /*
373 Resuming Mc, Rx and Tx Thread as platform Driver is resuming.
374 */
375 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Resuming Mc, Rx and Tx Thread",__func__);
376
377 /* Indicate MC Thread to Resume */
378 complete(&vosSchedContext->ResumeMcEvent);
379
380 /* Set the Mc Thread as Resumed */
381 pHddCtx->isMcThreadSuspended = FALSE;
382
383 /* Indicate Rx Thread to Resume */
384 complete(&vosSchedContext->ResumeRxEvent);
385
386 /* Set the Rx Thread as Resumed */
387 pHddCtx->isRxThreadSuspended = FALSE;
388
389 /* Indicate Tx Thread to Resume */
390 complete(&vosSchedContext->ResumeTxEvent);
391
392 /* Set the Tx Thread as Resumed */
393 pHddCtx->isTxThreadSuspended = FALSE;
394
395 /* Set the Station state as Suspended */
396 pHddCtx->isWlanSuspended = FALSE;
Abhishek Singhd987f3e2016-01-05 17:09:57 +0530397 hdd_wlan_suspend_resume_event(HDD_WLAN_RESUME);
Jeff Johnson295189b2012-06-20 16:38:30 -0700398}
399
400/*----------------------------------------------------------------------------
401
402 @brief Function to suspend the wlan driver.
403 This function will get called by platform driver Suspend on System Suspend
404
405 @param dev platform_func_device
406
407
408 @return None
409
410----------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530411int __hddDevSuspendHdlr(struct device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -0700412{
413 int ret = 0;
414 hdd_context_t* pHddCtx = NULL;
415
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530416 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700417
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530418 pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700419
420 /* Get the HDD context */
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530421 ret = wlan_hdd_validate_context(pHddCtx);
422 if (0 != ret)
423 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530424 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700425 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700426 if(pHddCtx->isWlanSuspended == TRUE)
427 {
428 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: WLAN is already in suspended state",__func__);
429 return 0;
430 }
431
432 /* Suspend the wlan driver */
433 ret = wlan_suspend(pHddCtx);
434 if(ret != 0)
435 {
436 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: Not able to suspend wlan",__func__);
437 return ret;
438 }
439
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -0800440#ifdef HAVE_WCNSS_SUSPEND_RESUME_NOTIFY
441 if(hdd_is_suspend_notify_allowed(pHddCtx))
442 {
443 wcnss_suspend_notify();
444 suspend_notify_sent = true;
445 }
446#endif
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530447
448 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700449 return 0;
450}
451
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530452int hddDevSuspendHdlr(struct device *dev)
453{
454 int ret;
455 vos_ssr_protect(__func__);
456 ret = __hddDevSuspendHdlr(dev);
457 vos_ssr_unprotect(__func__);
458
459 return ret;
460}
461
Jeff Johnson295189b2012-06-20 16:38:30 -0700462/*----------------------------------------------------------------------------
463
464 @brief Function to resume the wlan driver.
465 This function will get called by platform driver Resume on System Resume
466
467 @param dev platform_func_device
468
469
470 @return None
471
472----------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530473int __hddDevResumeHdlr(struct device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -0700474{
475 hdd_context_t* pHddCtx = NULL;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530476 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700477
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530478 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700479
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530480 pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev);
481 ret = wlan_hdd_validate_context(pHddCtx);
482 if (0 != ret)
483 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530484 return ret;
485 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700486 if(pHddCtx->isWlanSuspended != TRUE)
487 {
488 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: WLAN is already in resumed state",__func__);
489 return 0;
490 }
491
492 /* Resume the wlan driver */
493 wlan_resume(pHddCtx);
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -0800494#ifdef HAVE_WCNSS_SUSPEND_RESUME_NOTIFY
495 if(suspend_notify_sent == true)
496 {
497 wcnss_resume_notify();
498 suspend_notify_sent = false;
499 }
500#endif
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530501 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700502 return 0;
503}
504
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530505int hddDevResumeHdlr(struct device *dev)
506{
507 int ret;
508
509 vos_ssr_protect(__func__);
510 ret = __hddDevResumeHdlr(dev);
511 vos_ssr_unprotect(__func__);
512
513 return ret;
514}
515
Jeff Johnson295189b2012-06-20 16:38:30 -0700516static const struct dev_pm_ops pm_ops = {
517 .suspend = hddDevSuspendHdlr,
518 .resume = hddDevResumeHdlr,
519};
520
521/*----------------------------------------------------------------------------
522 *
523
524 @brief Registration function.
525 Register suspend, resume callback functions with platform driver.
526
527 @param hdd_context_t pHddCtx
528 Global hdd context
529
530 @return General status code
531 VOS_STATUS_SUCCESS Registration Success
532 VOS_STATUS_E_FAILURE Registration Fail
533
534----------------------------------------------------------------------------*/
535VOS_STATUS hddRegisterPmOps(hdd_context_t *pHddCtx)
536{
Jeff Johnson295189b2012-06-20 16:38:30 -0700537 wcnss_wlan_register_pm_ops(pHddCtx->parent_dev, &pm_ops);
Jeff Johnson295189b2012-06-20 16:38:30 -0700538 return VOS_STATUS_SUCCESS;
539}
540
541/*----------------------------------------------------------------------------
542
543 @brief De-registration function.
544 Deregister the suspend, resume callback functions with platform driver
545
546 @param hdd_context_t pHddCtx
547 Global hdd context
548
549 @return General status code
550 VOS_STATUS_SUCCESS De-Registration Success
551 VOS_STATUS_E_FAILURE De-Registration Fail
552
553----------------------------------------------------------------------------*/
554VOS_STATUS hddDeregisterPmOps(hdd_context_t *pHddCtx)
555{
Jeff Johnson295189b2012-06-20 16:38:30 -0700556 wcnss_wlan_unregister_pm_ops(pHddCtx->parent_dev, &pm_ops);
Jeff Johnson295189b2012-06-20 16:38:30 -0700557 return VOS_STATUS_SUCCESS;
558}
559
560/*----------------------------------------------------------------------------
561
562 @brief TX frame block timeout handler
563 Resume TX, and reset TX frame count
564
565 @param hdd_context_t pHddCtx
566 Global hdd context
567
568 @return NONE
569
570----------------------------------------------------------------------------*/
571void hddDevTmTxBlockTimeoutHandler(void *usrData)
572{
573 hdd_context_t *pHddCtx = (hdd_context_t *)usrData;
574 hdd_adapter_t *staAdapater;
Mahesh A Saptasagar4534e2b2015-03-05 20:45:41 +0530575
576 ENTER();
577 if (0 != (wlan_hdd_validate_context(pHddCtx)))
Jeff Johnson295189b2012-06-20 16:38:30 -0700578 {
Mahesh A Saptasagar4534e2b2015-03-05 20:45:41 +0530579 return;
Jeff Johnson295189b2012-06-20 16:38:30 -0700580 }
581
582 staAdapater = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -0700583
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +0530584 if ((NULL == staAdapater) || (WLAN_HDD_ADAPTER_MAGIC != staAdapater->magic))
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -0700585 {
586 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +0530587 FL("invalid Adapter %p"), staAdapater);
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -0700588 VOS_ASSERT(0);
589 return;
590 }
591
Jeff Johnson295189b2012-06-20 16:38:30 -0700592 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
593 {
594 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -0800595 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700596 return;
597 }
598 pHddCtx->tmInfo.txFrameCount = 0;
599
600 /* Resume TX flow */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530601 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Leo Chang50bbd252013-04-25 14:58:01 -0700602 netif_tx_wake_all_queues(staAdapater->dev);
603 pHddCtx->tmInfo.qBlocked = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700604 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
605
Mahesh A Saptasagar4534e2b2015-03-05 20:45:41 +0530606 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700607 return;
608}
609
610/*----------------------------------------------------------------------------
611
612 @brief TM Level Change handler
613 Received Tm Level changed notification
614
615 @param dev : Device context
616 changedTmLevel : Changed new TM level
617
618 @return
619
620----------------------------------------------------------------------------*/
621void hddDevTmLevelChangedHandler(struct device *dev, int changedTmLevel)
622{
623 hdd_context_t *pHddCtx = NULL;
624 WLAN_TmLevelEnumType newTmLevel = changedTmLevel;
625 hdd_adapter_t *staAdapater;
626
627 pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev);
628
Jeff Johnson4416a782013-03-25 14:17:50 -0700629 if ((pHddCtx->tmInfo.currentTmLevel == newTmLevel) ||
630 (!pHddCtx->cfg_ini->thermalMitigationEnable))
Jeff Johnson295189b2012-06-20 16:38:30 -0700631 {
632 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_WARN,
633 "%s: TM Not enabled %d or Level does not changed %d",
634 __func__, pHddCtx->cfg_ini->thermalMitigationEnable, newTmLevel);
635 /* TM Level does not changed,
636 * Or feature does not enabled
637 * do nothing */
638 return;
639 }
640
Leo Chang6fe1f922013-06-07 19:21:24 -0700641 /* Only STA mode support TM now
642 * all other mode, TM feature should be disabled */
643 if (~VOS_STA & pHddCtx->concurrency_mode)
644 {
645 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
646 "%s: CMODE 0x%x, TM disable",
647 __func__, pHddCtx->concurrency_mode);
648 newTmLevel = WLAN_HDD_TM_LEVEL_0;
649 }
650
Jeff Johnson4416a782013-03-25 14:17:50 -0700651 if ((newTmLevel < WLAN_HDD_TM_LEVEL_0) ||
652 (newTmLevel >= WLAN_HDD_TM_LEVEL_MAX))
653 {
654 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
655 "%s: TM level %d out of range",
656 __func__, newTmLevel);
657 return;
658 }
659
Leo Changd791cee2013-06-26 09:30:55 -0700660 if (newTmLevel != WLAN_HDD_TM_LEVEL_4)
661 sme_SetTmLevel(pHddCtx->hHal, newTmLevel, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -0700662
Jeff Johnson4416a782013-03-25 14:17:50 -0700663 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
Jeff Johnson295189b2012-06-20 16:38:30 -0700664 {
665 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -0800666 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700667 return;
668 }
669
Leo Changd791cee2013-06-26 09:30:55 -0700670 pHddCtx->tmInfo.currentTmLevel = newTmLevel;
Jeff Johnson295189b2012-06-20 16:38:30 -0700671 pHddCtx->tmInfo.txFrameCount = 0;
672 vos_mem_copy(&pHddCtx->tmInfo.tmAction,
673 &thermalMigrationAction[newTmLevel],
674 sizeof(hdd_tmLevelAction_t));
675
676
Jeff Johnson4416a782013-03-25 14:17:50 -0700677 if (pHddCtx->tmInfo.tmAction.enterImps)
Jeff Johnson295189b2012-06-20 16:38:30 -0700678 {
679 staAdapater = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
Jeff Johnson4416a782013-03-25 14:17:50 -0700680 if (staAdapater)
Jeff Johnson295189b2012-06-20 16:38:30 -0700681 {
Jeff Johnson4416a782013-03-25 14:17:50 -0700682 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(staAdapater)))
Jeff Johnson295189b2012-06-20 16:38:30 -0700683 {
684 sme_RoamDisconnect(pHddCtx->hHal,
685 staAdapater->sessionId,
686 eCSR_DISCONNECT_REASON_UNSPECIFIED);
687 }
688 }
689 }
690
691 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
692
693 return;
694}
695
696/*----------------------------------------------------------------------------
697
698 @brief Register function
699 Register Thermal Mitigation Level Changed handle callback function
700
701 @param hdd_context_t pHddCtx
702 Global hdd context
703
704 @return General status code
705 VOS_STATUS_SUCCESS Registration Success
706 VOS_STATUS_E_FAILURE Registration Fail
707
708----------------------------------------------------------------------------*/
709VOS_STATUS hddDevTmRegisterNotifyCallback(hdd_context_t *pHddCtx)
710{
711 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO,
712 "%s: Register TM Handler", __func__);
713
714 wcnss_register_thermal_mitigation(pHddCtx->parent_dev ,hddDevTmLevelChangedHandler);
715
716 /* Set Default TM Level as Lowest, do nothing */
717 pHddCtx->tmInfo.currentTmLevel = WLAN_HDD_TM_LEVEL_0;
718 vos_mem_zero(&pHddCtx->tmInfo.tmAction, sizeof(hdd_tmLevelAction_t));
719 vos_timer_init(&pHddCtx->tmInfo.txSleepTimer,
720 VOS_TIMER_TYPE_SW,
721 hddDevTmTxBlockTimeoutHandler,
722 (void *)pHddCtx);
723 mutex_init(&pHddCtx->tmInfo.tmOperationLock);
724 pHddCtx->tmInfo.txFrameCount = 0;
725 pHddCtx->tmInfo.blockedQueue = NULL;
Leo Chang50bbd252013-04-25 14:58:01 -0700726 pHddCtx->tmInfo.qBlocked = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700727 return VOS_STATUS_SUCCESS;
728}
729
730/*----------------------------------------------------------------------------
731
732 @brief Un-Register function
733 Un-Register Thermal Mitigation Level Changed handle callback function
734
735 @param hdd_context_t pHddCtx
736 Global hdd context
737
738 @return General status code
739 VOS_STATUS_SUCCESS Un-Registration Success
740 VOS_STATUS_E_FAILURE Un-Registration Fail
741
742----------------------------------------------------------------------------*/
743VOS_STATUS hddDevTmUnregisterNotifyCallback(hdd_context_t *pHddCtx)
744{
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700745 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
746
Jeff Johnson295189b2012-06-20 16:38:30 -0700747 wcnss_unregister_thermal_mitigation(hddDevTmLevelChangedHandler);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700748
749 if(VOS_TIMER_STATE_RUNNING ==
750 vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
751 {
752 vosStatus = vos_timer_stop(&pHddCtx->tmInfo.txSleepTimer);
753 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
754 {
755 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
756 "%s: Timer stop fail", __func__);
757 }
758 }
759
760 // Destroy the vos timer...
761 vosStatus = vos_timer_destroy(&pHddCtx->tmInfo.txSleepTimer);
762 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
763 {
764 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
765 "%s: Fail to destroy timer", __func__);
766 }
767
Jeff Johnson295189b2012-06-20 16:38:30 -0700768 return VOS_STATUS_SUCCESS;
769}
770