blob: 92016c3f3bf6b13511e750ad4f5a03822521c4db [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
yeshwanth sriram guntuka2bdbfb72017-02-08 16:39:29 +05302 * Copyright (c) 2012-2017 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 Kairam1871d402016-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 Singh37471cd2016-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 Yenugaa8b32f92016-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 {
yeshwanth sriram guntuka2bdbfb72017-02-08 16:39:29 +0530165 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
166 FL("Current time: %lu Last suspend fail time: %lu continuous fail count: %d"),
167 vos_timer_get_system_time(), pHddCtx->last_suspend_success,
168 pHddCtx->continuous_suspend_fail_cnt);
Abhishek Singh837adf22015-10-01 17:37:37 +0530169 pHddCtx->last_suspend_success = 0;
170 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
171 WLAN_LOG_INDICATOR_HOST_DRIVER,
172 WLAN_LOG_REASON_POWER_COLLAPSE_FAIL,
173 FALSE, TRUE);
174 }
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800175 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -0700176 }
Abhishek Singh837adf22015-10-01 17:37:37 +0530177 pHddCtx->continuous_suspend_fail_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700178 /*
179 Suspending MC Thread, Rx Thread and Tx Thread as the platform driver is going to Suspend.
180 */
181 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Suspending Mc, Rx and Tx Threads",__func__);
182
Gopichand Nakkala05621412013-06-19 19:37:38 +0530183 INIT_COMPLETION(pHddCtx->tx_sus_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700184
185 /* Indicate Tx Thread to Suspend */
Mahesh A Saptasagar8b42b272016-02-24 16:22:45 +0530186 set_bit(TX_SUSPEND_EVENT, &vosSchedContext->txEventFlag);
Jeff Johnson295189b2012-06-20 16:38:30 -0700187
188 wake_up_interruptible(&vosSchedContext->txWaitQueue);
189
190 /* Wait for Suspend Confirmation from Tx Thread */
191 rc = wait_for_completion_interruptible_timeout(&pHddCtx->tx_sus_event_var, msecs_to_jiffies(200));
192
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530193 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700194 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530195 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530196 "%s: TX Thread: timeout while suspending %ld"
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530197 , __func__, rc);
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530198 /* There is a race condition here, where the TX Thread can process the
199 * SUSPEND_EVENT even after the wait_for_completion has timed out.
200 * Check the SUSPEND_EVENT_MASK, if it is already cleared by the TX
201 * Thread then it means it is going to suspend, so do not return failure
202 * from here.
203 */
Mahesh A Saptasagar8b42b272016-02-24 16:22:45 +0530204 if (!test_and_clear_bit(TX_SUSPEND_EVENT,
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530205 &vosSchedContext->txEventFlag))
206 {
207 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
208 "%s: TX Thread: will still suspend", __func__);
209 goto tx_suspend;
210 }
Abhishek Singh837adf22015-10-01 17:37:37 +0530211 /* call fatal event if suspend for
212 * WLAN_POWER_COLLAPSE_FAIL_THRESHOLD time.
213 */
214 if ((vos_timer_get_system_time() - pHddCtx->last_suspend_success) >=
215 WLAN_POWER_COLLAPSE_FAIL_THRESHOLD)
216 {
217 pHddCtx->last_suspend_success = 0;
218 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
219 WLAN_LOG_INDICATOR_HOST_DRIVER,
220 WLAN_LOG_REASON_POWER_COLLAPSE_FAIL,
221 FALSE, TRUE);
222 }
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800223 return -ETIME;
Jeff Johnson295189b2012-06-20 16:38:30 -0700224 }
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530225
226tx_suspend:
Jeff Johnson295189b2012-06-20 16:38:30 -0700227 /* Set the Tx Thread as Suspended */
228 pHddCtx->isTxThreadSuspended = TRUE;
229
Gopichand Nakkala05621412013-06-19 19:37:38 +0530230 INIT_COMPLETION(pHddCtx->rx_sus_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700231
232 /* Indicate Rx Thread to Suspend */
Mahesh A Saptasagar8b42b272016-02-24 16:22:45 +0530233 set_bit(RX_SUSPEND_EVENT, &vosSchedContext->rxEventFlag);
Jeff Johnson295189b2012-06-20 16:38:30 -0700234
235 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
236
237 /* Wait for Suspend Confirmation from Rx Thread */
238 rc = wait_for_completion_interruptible_timeout(&pHddCtx->rx_sus_event_var, msecs_to_jiffies(200));
239
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530240 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700241 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530242 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530243 "%s: RX Thread: timeout while suspending %ld", __func__, rc);
244 /* There is a race condition here, where the RX Thread can process the
245 * SUSPEND_EVENT even after the wait_for_completion has timed out.
246 * Check the SUSPEND_EVENT_MASK, if it is already cleared by the RX
247 * Thread then it means it is going to suspend, so do not return failure
248 * from here.
249 */
Mahesh A Saptasagar8b42b272016-02-24 16:22:45 +0530250 if (!test_and_clear_bit(RX_SUSPEND_EVENT,
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530251 &vosSchedContext->rxEventFlag))
252 {
253 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
254 "%s: RX Thread: will still suspend", __func__);
255 goto rx_suspend;
256 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700257
258 /* Indicate Tx Thread to Resume */
259 complete(&vosSchedContext->ResumeTxEvent);
260
261 /* Set the Tx Thread as Resumed */
262 pHddCtx->isTxThreadSuspended = FALSE;
Abhishek Singh837adf22015-10-01 17:37:37 +0530263 /* call fatal event if suspend for
264 * WLAN_POWER_COLLAPSE_FAIL_THRESHOLD time.
265 */
266 if ((vos_timer_get_system_time() - pHddCtx->last_suspend_success) >=
267 WLAN_POWER_COLLAPSE_FAIL_THRESHOLD)
268 {
269 pHddCtx->last_suspend_success = 0;
270 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
271 WLAN_LOG_INDICATOR_HOST_DRIVER,
272 WLAN_LOG_REASON_POWER_COLLAPSE_FAIL,
273 FALSE, TRUE);
274 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700275
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800276 return -ETIME;
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 }
278
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530279rx_suspend:
Jeff Johnson295189b2012-06-20 16:38:30 -0700280 /* Set the Rx Thread as Suspended */
281 pHddCtx->isRxThreadSuspended = TRUE;
282
Gopichand Nakkala05621412013-06-19 19:37:38 +0530283 INIT_COMPLETION(pHddCtx->mc_sus_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700284
285 /* Indicate MC Thread to Suspend */
Mahesh A Saptasagar8b42b272016-02-24 16:22:45 +0530286 set_bit(MC_SUSPEND_EVENT, &vosSchedContext->mcEventFlag);
Jeff Johnson295189b2012-06-20 16:38:30 -0700287
288 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
289
290 /* Wait for Suspend Confirmation from MC Thread */
Abhishek Singh58de19f2016-01-04 15:44:04 +0530291 rc = wait_for_completion_interruptible_timeout(&pHddCtx->mc_sus_event_var,
292 msecs_to_jiffies(200));
Jeff Johnson295189b2012-06-20 16:38:30 -0700293
Abhishek Singh58de19f2016-01-04 15:44:04 +0530294 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700295 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530296 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530297 "%s: MC Thread: timeout while suspending %ld",
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530298 __func__, rc);
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530299 /* There is a race condition here, where the MC Thread can process the
300 * SUSPEND_EVENT even after the wait_for_completion has timed out.
301 * Check the SUSPEND_EVENT_MASK, if it is already cleared by the MC
302 * Thread then it means it is going to suspend, so do not return failure
303 * from here.
304 */
Mahesh A Saptasagar8b42b272016-02-24 16:22:45 +0530305 if (!test_and_clear_bit(MC_SUSPEND_EVENT,
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530306 &vosSchedContext->mcEventFlag))
307 {
308 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
309 "%s: MC Thread: will still suspend", __func__);
310 goto mc_suspend;
311 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700312
313 /* Indicate Rx Thread to Resume */
314 complete(&vosSchedContext->ResumeRxEvent);
315
316 /* Set the Rx Thread as Resumed */
317 pHddCtx->isRxThreadSuspended = FALSE;
318
319 /* Indicate Tx Thread to Resume */
320 complete(&vosSchedContext->ResumeTxEvent);
321
322 /* Set the Tx Thread as Resumed */
323 pHddCtx->isTxThreadSuspended = FALSE;
324
Abhishek Singh837adf22015-10-01 17:37:37 +0530325 /* call fatal event if suspend for
326 * WLAN_POWER_COLLAPSE_FAIL_THRESHOLD time.
327 */
328 if ((vos_timer_get_system_time() - pHddCtx->last_suspend_success) >=
329 WLAN_POWER_COLLAPSE_FAIL_THRESHOLD)
330 {
331 pHddCtx->last_suspend_success = 0;
332 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
333 WLAN_LOG_INDICATOR_HOST_DRIVER,
334 WLAN_LOG_REASON_POWER_COLLAPSE_FAIL,
335 FALSE, TRUE);
336 }
337
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800338 return -ETIME;
Jeff Johnson295189b2012-06-20 16:38:30 -0700339 }
340
Mihir Shete5dfd9a52014-06-09 17:22:55 +0530341mc_suspend:
Jeff Johnson295189b2012-06-20 16:38:30 -0700342 /* Set the Mc Thread as Suspended */
343 pHddCtx->isMcThreadSuspended = TRUE;
344
345 /* Set the Station state as Suspended */
346 pHddCtx->isWlanSuspended = TRUE;
Abhishek Singh837adf22015-10-01 17:37:37 +0530347 pHddCtx->last_suspend_success = 0;
Sravan Kumar Kairam1871d402016-08-04 13:18:25 +0530348 pHddCtx->rx_wow_dump = true;
Abhishek Singh37471cd2016-01-05 17:09:57 +0530349 hdd_wlan_suspend_resume_event(HDD_WLAN_SUSPEND);
Jeff Johnson295189b2012-06-20 16:38:30 -0700350 return 0;
351}
352
353/*----------------------------------------------------------------------------
354
355 @brief Function to resume the wlan driver.
356
357 @param hdd_context_t pHddCtx
358 Global hdd context
359
360
361 @return None
362
363----------------------------------------------------------------------------*/
364static void wlan_resume(hdd_context_t* pHddCtx)
365{
366 pVosSchedContext vosSchedContext = NULL;
367
368 //Get the global VOSS context.
369 vosSchedContext = get_vos_sched_ctxt();
370
371 if(!vosSchedContext) {
372 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: Global VOS_SCHED context is Null",__func__);
373 return;
374 }
375
376 /*
377 Resuming Mc, Rx and Tx Thread as platform Driver is resuming.
378 */
379 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Resuming Mc, Rx and Tx Thread",__func__);
380
381 /* Indicate MC Thread to Resume */
382 complete(&vosSchedContext->ResumeMcEvent);
383
384 /* Set the Mc Thread as Resumed */
385 pHddCtx->isMcThreadSuspended = FALSE;
386
387 /* Indicate Rx Thread to Resume */
388 complete(&vosSchedContext->ResumeRxEvent);
389
390 /* Set the Rx Thread as Resumed */
391 pHddCtx->isRxThreadSuspended = FALSE;
392
393 /* Indicate Tx Thread to Resume */
394 complete(&vosSchedContext->ResumeTxEvent);
395
396 /* Set the Tx Thread as Resumed */
397 pHddCtx->isTxThreadSuspended = FALSE;
398
399 /* Set the Station state as Suspended */
400 pHddCtx->isWlanSuspended = FALSE;
Abhishek Singh37471cd2016-01-05 17:09:57 +0530401 hdd_wlan_suspend_resume_event(HDD_WLAN_RESUME);
Jeff Johnson295189b2012-06-20 16:38:30 -0700402}
403
404/*----------------------------------------------------------------------------
405
406 @brief Function to suspend the wlan driver.
407 This function will get called by platform driver Suspend on System Suspend
408
409 @param dev platform_func_device
410
411
412 @return None
413
414----------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530415int __hddDevSuspendHdlr(struct device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -0700416{
417 int ret = 0;
418 hdd_context_t* pHddCtx = NULL;
419
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530420 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700421
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530422 pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700423
424 /* Get the HDD context */
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530425 ret = wlan_hdd_validate_context(pHddCtx);
426 if (0 != ret)
427 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530428 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700429 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700430 if(pHddCtx->isWlanSuspended == TRUE)
431 {
432 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: WLAN is already in suspended state",__func__);
433 return 0;
434 }
435
436 /* Suspend the wlan driver */
437 ret = wlan_suspend(pHddCtx);
438 if(ret != 0)
439 {
440 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: Not able to suspend wlan",__func__);
441 return ret;
442 }
443
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -0800444#ifdef HAVE_WCNSS_SUSPEND_RESUME_NOTIFY
445 if(hdd_is_suspend_notify_allowed(pHddCtx))
446 {
447 wcnss_suspend_notify();
448 suspend_notify_sent = true;
449 }
450#endif
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530451
452 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700453 return 0;
454}
455
Alok Kumarcd688c12018-04-25 01:47:22 +0530456int __hddDevSuspendNoIrqHdlr(struct device *dev)
457{
458 int ret = 0;
459 hdd_context_t* pHddCtx = NULL;
460 pVosContextType pVosContext;
461 pVosSchedContext pSchedContext;
462
463 ENTER();
464
465 pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev);
466
467 /* Get the HDD context */
468 ret = wlan_hdd_validate_context(pHddCtx);
469 if (0 != ret)
470 {
471 return ret;
472 }
473
474 if(pHddCtx->isWlanSuspended != TRUE)
475 {
476 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,
477 "%s: WLAN is not in suspended state",__func__);
478 return -EPERM;
479 }
480 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
481 if(pVosContext == NULL)
482 {
483 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,
484 "%s: Failed vos_get_global_context",__func__);
485 return -EPERM;
486 }
487
488 pSchedContext = &pVosContext->vosSched;
489
490 if (test_bit(RX_POST_EVENT, &pSchedContext->rxEventFlag))
491 {
492 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO,
493 "%s: WLAN suspend is not honored",__func__);
494 return -EPERM;
495 }
496
497 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
498 "%s: Suspend No IRQ done successfully",__func__);
499 EXIT();
500 return 0;
501}
502
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530503int hddDevSuspendHdlr(struct device *dev)
504{
505 int ret;
506 vos_ssr_protect(__func__);
507 ret = __hddDevSuspendHdlr(dev);
508 vos_ssr_unprotect(__func__);
509
510 return ret;
511}
512
Alok Kumarcd688c12018-04-25 01:47:22 +0530513int hddDevSuspendNoIrqHdlr(struct device *dev)
514{
515 int ret;
516 vos_ssr_protect(__func__);
517 ret = __hddDevSuspendNoIrqHdlr(dev);
518 vos_ssr_unprotect(__func__);
519 return ret;
520}
521
522int hddDevResumeNoIrqHdlr(struct device *dev)
523{
524 return 0;
525}
Jeff Johnson295189b2012-06-20 16:38:30 -0700526/*----------------------------------------------------------------------------
527
528 @brief Function to resume the wlan driver.
529 This function will get called by platform driver Resume on System Resume
530
531 @param dev platform_func_device
532
533
534 @return None
535
536----------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530537int __hddDevResumeHdlr(struct device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -0700538{
539 hdd_context_t* pHddCtx = NULL;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530540 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700541
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530542 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -0700543
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530544 pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev);
545 ret = wlan_hdd_validate_context(pHddCtx);
546 if (0 != ret)
547 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530548 return ret;
549 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700550 if(pHddCtx->isWlanSuspended != TRUE)
551 {
552 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_FATAL,"%s: WLAN is already in resumed state",__func__);
553 return 0;
554 }
555
556 /* Resume the wlan driver */
557 wlan_resume(pHddCtx);
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -0800558#ifdef HAVE_WCNSS_SUSPEND_RESUME_NOTIFY
559 if(suspend_notify_sent == true)
560 {
561 wcnss_resume_notify();
562 suspend_notify_sent = false;
563 }
564#endif
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530565 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700566 return 0;
567}
568
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530569int hddDevResumeHdlr(struct device *dev)
570{
571 int ret;
572
573 vos_ssr_protect(__func__);
574 ret = __hddDevResumeHdlr(dev);
575 vos_ssr_unprotect(__func__);
576
577 return ret;
578}
579
Jeff Johnson295189b2012-06-20 16:38:30 -0700580static const struct dev_pm_ops pm_ops = {
581 .suspend = hddDevSuspendHdlr,
582 .resume = hddDevResumeHdlr,
Alok Kumarcd688c12018-04-25 01:47:22 +0530583 .suspend_noirq = hddDevSuspendNoIrqHdlr,
584 .resume_noirq = hddDevResumeNoIrqHdlr
Jeff Johnson295189b2012-06-20 16:38:30 -0700585};
586
587/*----------------------------------------------------------------------------
588 *
589
590 @brief Registration function.
591 Register suspend, resume callback functions with platform driver.
592
593 @param hdd_context_t pHddCtx
594 Global hdd context
595
596 @return General status code
597 VOS_STATUS_SUCCESS Registration Success
598 VOS_STATUS_E_FAILURE Registration Fail
599
600----------------------------------------------------------------------------*/
601VOS_STATUS hddRegisterPmOps(hdd_context_t *pHddCtx)
602{
Jeff Johnson295189b2012-06-20 16:38:30 -0700603 wcnss_wlan_register_pm_ops(pHddCtx->parent_dev, &pm_ops);
Jeff Johnson295189b2012-06-20 16:38:30 -0700604 return VOS_STATUS_SUCCESS;
605}
606
607/*----------------------------------------------------------------------------
608
609 @brief De-registration function.
610 Deregister the suspend, resume callback functions with platform driver
611
612 @param hdd_context_t pHddCtx
613 Global hdd context
614
615 @return General status code
616 VOS_STATUS_SUCCESS De-Registration Success
617 VOS_STATUS_E_FAILURE De-Registration Fail
618
619----------------------------------------------------------------------------*/
620VOS_STATUS hddDeregisterPmOps(hdd_context_t *pHddCtx)
621{
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 wcnss_wlan_unregister_pm_ops(pHddCtx->parent_dev, &pm_ops);
Jeff Johnson295189b2012-06-20 16:38:30 -0700623 return VOS_STATUS_SUCCESS;
624}
625
626/*----------------------------------------------------------------------------
627
628 @brief TX frame block timeout handler
629 Resume TX, and reset TX frame count
630
631 @param hdd_context_t pHddCtx
632 Global hdd context
633
634 @return NONE
635
636----------------------------------------------------------------------------*/
637void hddDevTmTxBlockTimeoutHandler(void *usrData)
638{
639 hdd_context_t *pHddCtx = (hdd_context_t *)usrData;
640 hdd_adapter_t *staAdapater;
Mahesh A Saptasagar4534e2b2015-03-05 20:45:41 +0530641
642 ENTER();
643 if (0 != (wlan_hdd_validate_context(pHddCtx)))
Jeff Johnson295189b2012-06-20 16:38:30 -0700644 {
Mahesh A Saptasagar4534e2b2015-03-05 20:45:41 +0530645 return;
Jeff Johnson295189b2012-06-20 16:38:30 -0700646 }
647
648 staAdapater = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -0700649
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +0530650 if ((NULL == staAdapater) || (WLAN_HDD_ADAPTER_MAGIC != staAdapater->magic))
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -0700651 {
652 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -0700653 FL("invalid Adapter %pK"), staAdapater);
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -0700654 VOS_ASSERT(0);
655 return;
656 }
657
Jeff Johnson295189b2012-06-20 16:38:30 -0700658 if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
659 {
660 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -0800661 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700662 return;
663 }
664 pHddCtx->tmInfo.txFrameCount = 0;
665
666 /* Resume TX flow */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +0530667 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Leo Chang50bbd252013-04-25 14:58:01 -0700668 netif_tx_wake_all_queues(staAdapater->dev);
669 pHddCtx->tmInfo.qBlocked = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700670 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
671
Mahesh A Saptasagar4534e2b2015-03-05 20:45:41 +0530672 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -0700673 return;
674}
675
676/*----------------------------------------------------------------------------
677
678 @brief TM Level Change handler
679 Received Tm Level changed notification
680
681 @param dev : Device context
682 changedTmLevel : Changed new TM level
683
684 @return
685
686----------------------------------------------------------------------------*/
687void hddDevTmLevelChangedHandler(struct device *dev, int changedTmLevel)
688{
689 hdd_context_t *pHddCtx = NULL;
690 WLAN_TmLevelEnumType newTmLevel = changedTmLevel;
691 hdd_adapter_t *staAdapater;
692
693 pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev);
694
Jeff Johnson4416a782013-03-25 14:17:50 -0700695 if ((pHddCtx->tmInfo.currentTmLevel == newTmLevel) ||
696 (!pHddCtx->cfg_ini->thermalMitigationEnable))
Jeff Johnson295189b2012-06-20 16:38:30 -0700697 {
698 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_WARN,
699 "%s: TM Not enabled %d or Level does not changed %d",
700 __func__, pHddCtx->cfg_ini->thermalMitigationEnable, newTmLevel);
701 /* TM Level does not changed,
702 * Or feature does not enabled
703 * do nothing */
704 return;
705 }
706
Leo Chang6fe1f922013-06-07 19:21:24 -0700707 /* Only STA mode support TM now
708 * all other mode, TM feature should be disabled */
709 if (~VOS_STA & pHddCtx->concurrency_mode)
710 {
711 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
712 "%s: CMODE 0x%x, TM disable",
713 __func__, pHddCtx->concurrency_mode);
714 newTmLevel = WLAN_HDD_TM_LEVEL_0;
715 }
716
Jeff Johnson4416a782013-03-25 14:17:50 -0700717 if ((newTmLevel < WLAN_HDD_TM_LEVEL_0) ||
718 (newTmLevel >= WLAN_HDD_TM_LEVEL_MAX))
719 {
720 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
721 "%s: TM level %d out of range",
722 __func__, newTmLevel);
723 return;
724 }
725
Leo Changd791cee2013-06-26 09:30:55 -0700726 if (newTmLevel != WLAN_HDD_TM_LEVEL_4)
727 sme_SetTmLevel(pHddCtx->hHal, newTmLevel, 0);
Jeff Johnson295189b2012-06-20 16:38:30 -0700728
Jeff Johnson4416a782013-03-25 14:17:50 -0700729 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
Jeff Johnson295189b2012-06-20 16:38:30 -0700730 {
731 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -0800732 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700733 return;
734 }
735
Leo Changd791cee2013-06-26 09:30:55 -0700736 pHddCtx->tmInfo.currentTmLevel = newTmLevel;
Jeff Johnson295189b2012-06-20 16:38:30 -0700737 pHddCtx->tmInfo.txFrameCount = 0;
738 vos_mem_copy(&pHddCtx->tmInfo.tmAction,
739 &thermalMigrationAction[newTmLevel],
740 sizeof(hdd_tmLevelAction_t));
741
742
Jeff Johnson4416a782013-03-25 14:17:50 -0700743 if (pHddCtx->tmInfo.tmAction.enterImps)
Jeff Johnson295189b2012-06-20 16:38:30 -0700744 {
745 staAdapater = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
Jeff Johnson4416a782013-03-25 14:17:50 -0700746 if (staAdapater)
Jeff Johnson295189b2012-06-20 16:38:30 -0700747 {
Jeff Johnson4416a782013-03-25 14:17:50 -0700748 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(staAdapater)))
Jeff Johnson295189b2012-06-20 16:38:30 -0700749 {
750 sme_RoamDisconnect(pHddCtx->hHal,
751 staAdapater->sessionId,
752 eCSR_DISCONNECT_REASON_UNSPECIFIED);
753 }
754 }
755 }
756
757 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
758
759 return;
760}
761
762/*----------------------------------------------------------------------------
763
764 @brief Register function
765 Register Thermal Mitigation Level Changed handle callback function
766
767 @param hdd_context_t pHddCtx
768 Global hdd context
769
770 @return General status code
771 VOS_STATUS_SUCCESS Registration Success
772 VOS_STATUS_E_FAILURE Registration Fail
773
774----------------------------------------------------------------------------*/
775VOS_STATUS hddDevTmRegisterNotifyCallback(hdd_context_t *pHddCtx)
776{
777 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO,
778 "%s: Register TM Handler", __func__);
779
780 wcnss_register_thermal_mitigation(pHddCtx->parent_dev ,hddDevTmLevelChangedHandler);
781
782 /* Set Default TM Level as Lowest, do nothing */
783 pHddCtx->tmInfo.currentTmLevel = WLAN_HDD_TM_LEVEL_0;
784 vos_mem_zero(&pHddCtx->tmInfo.tmAction, sizeof(hdd_tmLevelAction_t));
785 vos_timer_init(&pHddCtx->tmInfo.txSleepTimer,
786 VOS_TIMER_TYPE_SW,
787 hddDevTmTxBlockTimeoutHandler,
788 (void *)pHddCtx);
789 mutex_init(&pHddCtx->tmInfo.tmOperationLock);
790 pHddCtx->tmInfo.txFrameCount = 0;
791 pHddCtx->tmInfo.blockedQueue = NULL;
Leo Chang50bbd252013-04-25 14:58:01 -0700792 pHddCtx->tmInfo.qBlocked = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700793 return VOS_STATUS_SUCCESS;
794}
795
796/*----------------------------------------------------------------------------
797
798 @brief Un-Register function
799 Un-Register Thermal Mitigation Level Changed handle callback function
800
801 @param hdd_context_t pHddCtx
802 Global hdd context
803
804 @return General status code
805 VOS_STATUS_SUCCESS Un-Registration Success
806 VOS_STATUS_E_FAILURE Un-Registration Fail
807
808----------------------------------------------------------------------------*/
809VOS_STATUS hddDevTmUnregisterNotifyCallback(hdd_context_t *pHddCtx)
810{
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700811 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
812
Jeff Johnson295189b2012-06-20 16:38:30 -0700813 wcnss_unregister_thermal_mitigation(hddDevTmLevelChangedHandler);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700814
815 if(VOS_TIMER_STATE_RUNNING ==
816 vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer))
817 {
818 vosStatus = vos_timer_stop(&pHddCtx->tmInfo.txSleepTimer);
819 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
820 {
821 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
822 "%s: Timer stop fail", __func__);
823 }
824 }
825
826 // Destroy the vos timer...
827 vosStatus = vos_timer_destroy(&pHddCtx->tmInfo.txSleepTimer);
828 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
829 {
830 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
831 "%s: Fail to destroy timer", __func__);
832 }
833
Jeff Johnson295189b2012-06-20 16:38:30 -0700834 return VOS_STATUS_SUCCESS;
835}
836