import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / connectivity / conn_soc / common / core / psm_core.c
CommitLineData
6fa3eb70
S
1/*
2* Copyright (C) 2011-2014 MediaTek Inc.
3*
4* This program is free software: you can redistribute it and/or modify it under the terms of the
5* GNU General Public License version 2 as published by the Free Software Foundation.
6*
7* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
8* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9* See the GNU General Public License for more details.
10*
11* You should have received a copy of the GNU General Public License along with this program.
12* If not, see <http://www.gnu.org/licenses/>.
13*/
14#include "osal_typedef.h"
15#include "osal.h"
16#include "psm_core.h"
17#include "stp_core.h"
18#include <mach/mtk_wcn_cmb_stub.h>
19
20INT32 gPsmDbgLevel = STP_PSM_LOG_INFO;
21MTKSTP_PSM_T stp_psm_i;
22MTKSTP_PSM_T *stp_psm = &stp_psm_i;
23
24STP_PSM_RECORD_T * g_stp_psm_dbg = NULL;
25static UINT32 g_record_num = 0;
26
27P_STP_PSM_OPID_RECORD g_stp_psm_opid_dbg = NULL;
28static UINT32 g_opid_record_num = 0;
29
30
31#define STP_PSM_LOUD_FUNC(fmt, arg...) if(gPsmDbgLevel >= STP_PSM_LOG_LOUD){ printk(KERN_DEBUG PFX_PSM "%s: " fmt, __FUNCTION__ ,##arg);}
32#define STP_PSM_DBG_FUNC(fmt, arg...) if(gPsmDbgLevel >= STP_PSM_LOG_DBG){ printk(KERN_DEBUG PFX_PSM "%s: " fmt, __FUNCTION__ ,##arg);}
33#define STP_PSM_INFO_FUNC(fmt, arg...) if(gPsmDbgLevel >= STP_PSM_LOG_INFO){ printk(PFX_PSM "[I]%s: " fmt, __FUNCTION__ ,##arg);}
34#define STP_PSM_WARN_FUNC(fmt, arg...) if(gPsmDbgLevel >= STP_PSM_LOG_WARN){ printk(PFX_PSM "[W]%s: " fmt, __FUNCTION__ ,##arg);}
35#define STP_PSM_ERR_FUNC(fmt, arg...) if(gPsmDbgLevel >= STP_PSM_LOG_ERR){ printk(PFX_PSM "[E]%s(%d):ERROR! " fmt, __FUNCTION__ , __LINE__, ##arg);}
36#define STP_PSM_TRC_FUNC(f) if(gPsmDbgLevel >= STP_PSM_LOG_DBG){ printk(KERN_DEBUG PFX_PSM "<%s> <%d>\n", __FUNCTION__, __LINE__);}
37
38static inline INT32 _stp_psm_notify_wmt(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action);
39static INT32 _stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm);
40static INT32 _stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm);
41static INT32 _stp_psm_dbg_dmp_in(STP_PSM_RECORD_T *stp_psm_dbg, UINT32 flag, UINT32 line_num);
42static INT32 _stp_psm_dbg_out_printk(STP_PSM_RECORD_T *stp_psm_dbg);
43
44static INT32 _stp_psm_opid_dbg_dmp_in(P_STP_PSM_OPID_RECORD p_opid_dbg, UINT32 opid, UINT32 line_num);
45static INT32 _stp_psm_opid_dbg_out_printk(P_STP_PSM_OPID_RECORD p_opid_dbg);
46
47
48static const char *g_psm_state[STP_PSM_MAX_STATE] = {
49 "ACT",
50 "ACT_INACT",
51 "INACT",
52 "INACT_ACT"
53};
54
55static const char *g_psm_action[STP_PSM_MAX_ACTION] = {
56 "SLEEP" ,
57 "HOST_AWAKE",
58 "WAKEUP",
59 "EIRQ",
60 "ROLL_BACK"
61};
62
63static const char *g_psm_op_name[STP_OPID_PSM_NUM] = {
64 "STP_OPID_PSM_SLEEP",
65 "STP_OPID_PSM_WAKEUP",
66 "STP_OPID_PSM_HOST_AWAKE",
67 "STP_OPID_PSM_EXIT"
68};
69
70int _stp_psm_release_data(MTKSTP_PSM_T *stp_psm);
71
72static inline int _stp_psm_get_state(MTKSTP_PSM_T *stp_psm);
73
74static int _stp_psm_is_redundant_active_op(
75 P_OSAL_OP pOp,
76 P_OSAL_OP_Q pOpQ
77);
78
79static int _stp_psm_clean_up_redundant_active_op(
80 P_OSAL_OP_Q pOpQ
81 );
82static MTK_WCN_BOOL _stp_psm_is_quick_ps_support (VOID);
83
84MTK_WCN_BOOL mtk_wcn_stp_psm_dbg_level(UINT32 dbglevel)
85{
86 if (0 <= dbglevel && dbglevel <= 4)
87 {
88 gPsmDbgLevel = dbglevel;
89 STP_PSM_INFO_FUNC("gPsmDbgLevel = %d\n", gPsmDbgLevel);
90 return true;
91 }
92 else
93 {
94 STP_PSM_INFO_FUNC("invalid psm debug level. gPsmDbgLevel = %d\n", gPsmDbgLevel);
95 }
96 return false;
97}
98
99
100static INT32 _stp_psm_handler(MTKSTP_PSM_T *stp_psm, P_STP_OP pStpOp)
101{
102 INT32 ret = -1;
103
104 //if (NULL == pStpOp)
105 //{
106 // return -1;
107 //}
108 ret = _stp_psm_thread_lock_aquire(stp_psm);
109 if (ret) {
110 STP_PSM_ERR_FUNC("--->lock psm_thread_lock failed ret=%d\n", ret);
111 return ret;
112 }
113
114 switch(pStpOp->opId)
115 {
116 case STP_OPID_PSM_EXIT:
117 // TODO: clean all up?
118 ret = 0;
119 break;
120
121 case STP_OPID_PSM_SLEEP:
122 if (stp_psm_check_sleep_enable(stp_psm) > 0) {
123 ret =_stp_psm_notify_wmt(stp_psm, SLEEP);
124 } else {
125 STP_PSM_INFO_FUNC("cancel sleep request\n");
126 }
127 break;
128
129 case STP_OPID_PSM_WAKEUP:
130 ret = _stp_psm_notify_wmt(stp_psm, WAKEUP);
131 break;
132
133 case STP_OPID_PSM_HOST_AWAKE:
134 ret = _stp_psm_notify_wmt(stp_psm, HOST_AWAKE);
135 break;
136
137 default:
138 STP_PSM_ERR_FUNC("invalid operation id (%d)\n", pStpOp->opId);
139 ret = -1;
140 break;
141 }
142 _stp_psm_thread_lock_release(stp_psm);
143 return ret;
144}
145
146static P_OSAL_OP _stp_psm_get_op (
147 MTKSTP_PSM_T *stp_psm,
148 P_OSAL_OP_Q pOpQ
149 )
150{
151 P_OSAL_OP pOp;
152
153 if (!pOpQ)
154 {
155 STP_PSM_WARN_FUNC("pOpQ == NULL\n");
156 return NULL;
157 }
158
159 osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock));
160 /* acquire lock success */
161 RB_GET(pOpQ, pOp);
162
163 if((pOpQ == &stp_psm->rActiveOpQ) && (NULL != pOp))
164 {
165 //stp_psm->current_active_op = pOp;//*(pOp);
166 stp_psm->last_active_opId = pOp->op.opId;
167 }
168 osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock));
169
170 if((pOpQ == &stp_psm->rActiveOpQ) && (NULL != pOp))
171 {
172 STP_PSM_INFO_FUNC("last_active_opId(%d)\n", stp_psm->last_active_opId);
173 }
174
175 if (!pOp)
176 {
177 STP_PSM_WARN_FUNC("RB_GET fail\n");
178 }
179
180 return pOp;
181}
182
183static INT32 _stp_psm_dump_active_q(
184 P_OSAL_OP_Q pOpQ
185)
186{
187 UINT32 read_idx;
188 UINT32 write_idx;
189 UINT32 opId;
190
191 if(pOpQ == &stp_psm->rActiveOpQ)
192 {
193 read_idx = stp_psm->rActiveOpQ.read;
194 write_idx = stp_psm->rActiveOpQ.write;
195
196 STP_PSM_DBG_FUNC("Active op list:++\n");
197 while ((read_idx & RB_MASK(pOpQ)) != (write_idx & RB_MASK(pOpQ)))
198 {
199 opId = pOpQ->queue[read_idx & RB_MASK(pOpQ)]->op.opId;
200 if(opId < STP_OPID_PSM_NUM)
201 {
202 STP_PSM_DBG_FUNC("%s\n", g_psm_op_name[opId] );
203 }
204 else
205 {
206 STP_PSM_WARN_FUNC("Unkown OP Id\n");
207 }
208 ++read_idx;
209 }
210 STP_PSM_DBG_FUNC("Active op list:--\n");
211 }
212 else
213 {
214 STP_PSM_DBG_FUNC("%s: not active queue, dont dump\n", __func__);
215 }
216
217 return 0;
218}
219
220static int _stp_psm_is_redundant_active_op(
221 P_OSAL_OP pOp,
222 P_OSAL_OP_Q pOpQ
223)
224{
225 unsigned int opId = 0;
226 unsigned int prev_opId = 0;
227
228 //if((pOpQ == &stp_psm->rActiveOpQ) && (NULL != stp_psm->current_active_op))
229 if((pOpQ == &stp_psm->rActiveOpQ) && (STP_OPID_PSM_INALID != stp_psm->last_active_opId))
230
231 {
232 opId = pOp->op.opId;
233
234 if(opId == STP_OPID_PSM_SLEEP)
235 {
236 if(RB_EMPTY(pOpQ))
237 {
238 //prev_opId = stp_psm->current_active_op->op.opId;
239 prev_opId = stp_psm->last_active_opId;
240 }
241 else
242 {
243 prev_opId = pOpQ->queue[(pOpQ->write - 1) & RB_MASK(pOpQ)]->op.opId;
244 }
245
246 if(prev_opId == STP_OPID_PSM_SLEEP)
247 {
248 STP_PSM_DBG_FUNC("redundant sleep opId found\n");
249 return 1;
250 }
251 else
252 {
253 return 0;
254 }
255 }
256 else
257 {
258 if(RB_EMPTY(pOpQ))
259 {
260 //prev_opId = stp_psm->current_active_op->op.opId;
261 prev_opId = stp_psm->last_active_opId;
262 }
263 else
264 {
265 prev_opId = pOpQ->queue[(pOpQ->write - 1) & RB_MASK(pOpQ)]->op.opId;
266 }
267
268 if(((opId== STP_OPID_PSM_WAKEUP) && ( prev_opId == STP_OPID_PSM_WAKEUP)) ||
269 ((opId == STP_OPID_PSM_HOST_AWAKE) && ( prev_opId == STP_OPID_PSM_WAKEUP)) ||
270 ((opId == STP_OPID_PSM_HOST_AWAKE) && ( prev_opId == STP_OPID_PSM_HOST_AWAKE)) ||
271 ((opId == STP_OPID_PSM_WAKEUP) && ( prev_opId == STP_OPID_PSM_HOST_AWAKE))
272 )
273 {
274 STP_PSM_DBG_FUNC("redundant opId found, opId(%d), preOpid(%d)\n", opId, prev_opId);
275 return 1;
276 }
277 else
278 {
279 return 0;
280 }
281 }
282 }
283 else
284 {
285 return 0;
286 }
287
288}
289
290static int _stp_psm_clean_up_redundant_active_op(
291 P_OSAL_OP_Q pOpQ
292 )
293{
294 unsigned int prev_opId = 0;
295 unsigned int prev_prev_opId = 0;
296
297 P_OSAL_OP pOp;
298 P_OSAL_OP_Q pFreeOpQ= &stp_psm->rFreeOpQ;
299
300 if(pOpQ == &stp_psm->rActiveOpQ)
301 {
302 // sleep , wakeup | sleep, --> null | sleep (x)
303 // wakeup , sleep , wakeup | sleep --> wakeup | sleep (v)
304 // sleep , wakeup , sleep | wakeup --> sleep | wakeup (v)
305 // xxx, sleep | sleep --> xxx, sleep (v)
306 // xxx, wakeup | wakeup --> xxx, wakeup (v)
307 // xxx, awake | awake --> xxx, awake (v) --> should never happen
308 while(RB_COUNT(pOpQ) > 2)
309 {
310 prev_opId = pOpQ->queue[(pOpQ->write - 1) & RB_MASK(pOpQ)]->op.opId;
311 prev_prev_opId = pOpQ->queue[(pOpQ->write - 2) & RB_MASK(pOpQ)]->op.opId;
312
313 if((prev_opId == STP_OPID_PSM_SLEEP && prev_prev_opId == STP_OPID_PSM_WAKEUP)||
314 (prev_opId == STP_OPID_PSM_SLEEP && prev_prev_opId == STP_OPID_PSM_HOST_AWAKE) ||
315 (prev_opId == STP_OPID_PSM_WAKEUP&& prev_prev_opId == STP_OPID_PSM_SLEEP) ||
316 (prev_opId == STP_OPID_PSM_HOST_AWAKE&& prev_prev_opId == STP_OPID_PSM_SLEEP)
317 )
318 {
319 RB_GET(pOpQ, pOp);
320 RB_PUT(pFreeOpQ, pOp);
321 RB_GET(pOpQ, pOp);
322 RB_PUT(pFreeOpQ, pOp);
323 }
324 else if (prev_opId == prev_prev_opId)
325 {
326 RB_GET(pOpQ, pOp);
327 STP_PSM_DBG_FUNC("redundant opId(%d) found, remove it\n", pOp->op.opId);
328 RB_PUT(pFreeOpQ, pOp);
329 }
330 }
331 }
332
333 return 0;
334}
335
336static INT32 _stp_psm_put_op (
337 MTKSTP_PSM_T *stp_psm,
338 P_OSAL_OP_Q pOpQ,
339 P_OSAL_OP pOp
340 )
341{
342 INT32 ret;
343
344 // if (!pOpQ || !pOp)
345 // {
346 // STP_PSM_WARN_FUNC("pOpQ = 0x%p, pLxOp = 0x%p \n", pOpQ, pOp);
347 // return 0;
348 // }
349 ret = 0;
350
351 osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock));
352 /* acquire lock success */
353 if(pOpQ == &stp_psm->rActiveOpQ)
354 {
355 if(!_stp_psm_is_redundant_active_op(pOp, pOpQ))
356 {
357 /* acquire lock success */
358 if (!RB_FULL(pOpQ))
359 {
360 RB_PUT(pOpQ, pOp);
361 STP_PSM_INFO_FUNC("opId(%d) enqueue\n", pOp->op.opId);
362 }
363 else
364 {
365 STP_PSM_INFO_FUNC("************ Active Queue Full ************\n");
366 ret = -1;
367 }
368
369 _stp_psm_clean_up_redundant_active_op(pOpQ);
370 }
371 else
372 {
373 /*redundant opId, mark ret as success*/
374 P_OSAL_OP_Q pFreeOpQ = &stp_psm->rFreeOpQ;
375 if (!RB_FULL(pFreeOpQ))
376 {
377 RB_PUT(pFreeOpQ, pOp);
378 }
379 else
380 {
381 osal_assert(!RB_FULL(pFreeOpQ));
382 }
383 ret = 0;
384 }
385 }
386 else
387 {
388 if (!RB_FULL(pOpQ))
389 {
390 RB_PUT(pOpQ, pOp);
391 }
392 else
393 {
394 ret = -1;
395 }
396 }
397
398 if(pOpQ == &stp_psm->rActiveOpQ)
399 {
400 _stp_psm_dump_active_q(&stp_psm->rActiveOpQ);
401 }
402
403 osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock));
404 STP_PSM_DBG_FUNC("stp_psm do unlock,active queue? (%s)\n",(pOpQ == &stp_psm->rActiveOpQ)? "y" : "n");
405
406 if (ret)
407 {
408 STP_PSM_WARN_FUNC("RB_FULL, RB_COUNT=%d , RB_SIZE=%d\n",RB_COUNT(pOpQ), RB_SIZE(pOpQ));
409 return 0;
410 }
411 else
412 {
413 return 1;
414 }
415}
416
417P_OSAL_OP _stp_psm_get_free_op (
418 MTKSTP_PSM_T *stp_psm
419 )
420{
421 P_OSAL_OP pOp;
422
423 if (stp_psm)
424 {
425 pOp = _stp_psm_get_op(stp_psm, &stp_psm->rFreeOpQ);
426 if (pOp)
427 {
428 osal_memset(&pOp->op, 0, sizeof(pOp->op));
429 }
430 return pOp;
431 }
432 else
433 {
434 return NULL;
435 }
436}
437
438INT32 _stp_psm_put_act_op (
439 MTKSTP_PSM_T *stp_psm,
440 P_OSAL_OP pOp
441 )
442{
443 INT32 bRet = 0;//MTK_WCN_BOOL_FALSE;
444 INT32 bCleanup = 0;//MTK_WCN_BOOL_FALSE;
445 INT32 wait_ret = -1;
446 P_OSAL_SIGNAL pSignal = NULL;
447
448 do
449 {
450 if (!stp_psm || !pOp)
451 {
452 STP_PSM_ERR_FUNC("stp_psm = %p, pOp = %p\n", stp_psm, pOp);
453 break;
454 }
455
456 pSignal = &pOp->signal;
457
458 if (pSignal->timeoutValue)
459 {
460 pOp->result = -9;
461 osal_signal_init(&pOp->signal);
462 }
463
464 /* put to active Q */
465 bRet = _stp_psm_put_op(stp_psm, &stp_psm->rActiveOpQ, pOp);
466
467 if(0 == bRet)
468 {
469 STP_PSM_WARN_FUNC("+++++++++++ Put op Active queue Fail\n");
470 bCleanup = 1;//MTK_WCN_BOOL_TRUE;
471 break;
472 }
473 _stp_psm_opid_dbg_dmp_in(g_stp_psm_opid_dbg, pOp->op.opId, __LINE__);
474
475 /* wake up wmtd */
476 osal_trigger_event(&stp_psm->STPd_event);
477
478 if (pSignal->timeoutValue == 0)
479 {
480 bRet = 1;//MTK_WCN_BOOL_TRUE;
481 /* clean it in wmtd */
482 break;
483 }
484
485 /* wait result, clean it here */
486 bCleanup = 1;//MTK_WCN_BOOL_TRUE;
487
488 /* check result */
489 wait_ret = osal_wait_for_signal_timeout(&pOp->signal);
490 STP_PSM_DBG_FUNC("wait completion:%d\n", wait_ret);
491 if (!wait_ret)
492 {
493 STP_PSM_ERR_FUNC("wait completion timeout \n");
494 // TODO: how to handle it? retry?
495 }
496 else
497 {
498 if (pOp->result)
499 {
500 STP_PSM_WARN_FUNC("op(%d) result:%d\n", pOp->op.opId, pOp->result);
501 }
502 /* op completes, check result */
503 bRet = (pOp->result) ? 0 : 1;
504 }
505 } while(0);
506
507 if (bCleanup) {
508 /* put Op back to freeQ */
509 bRet = _stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, pOp);
510 if(bRet == 0)
511 {
512 STP_PSM_WARN_FUNC("+++++++++++ Put op active free fail, maybe disable/enable psm\n");
513 }
514 }
515
516 return bRet;
517}
518
519static INT32 _stp_psm_wait_for_msg(void *pvData)
520{
521 MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *)pvData;
522 STP_PSM_DBG_FUNC("%s: stp_psm->rActiveOpQ = %d\n", __func__, RB_COUNT(&stp_psm->rActiveOpQ));
523
524 return ((!RB_EMPTY(&stp_psm->rActiveOpQ)) || osal_thread_should_stop(&stp_psm->PSMd));
525}
526
527static INT32 _stp_psm_proc (void *pvData)
528{
529 MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *)pvData;
530 P_OSAL_OP pOp;
531 UINT32 id;
532 INT32 result;
533
534 if (!stp_psm) {
535 STP_PSM_WARN_FUNC("!stp_psm \n");
536 return -1;
537 }
538
539// STP_PSM_INFO_FUNC("wmtd starts running: pWmtDev(0x%p) [pol, rt_pri, n_pri, pri]=[%d, %d, %d, %d] \n",
540// stp_psm, current->policy, current->rt_priority, current->normal_prio, current->prio);
541
542 for (;;) {
543
544 pOp = NULL;
545
546 osal_wait_for_event(&stp_psm->STPd_event,
547 _stp_psm_wait_for_msg,
548 (void *)stp_psm);
549
550 //we set reset flag when calling stp_reset after cleanup all op.
551 if(osal_test_bit(STP_PSM_RESET_EN,&stp_psm->flag))
552 {
553 osal_clear_bit(STP_PSM_RESET_EN,&stp_psm->flag);
554 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
555 }
556 if (osal_thread_should_stop(&stp_psm->PSMd))
557 {
558 STP_PSM_INFO_FUNC("should stop now... \n");
559 // TODO: clean up active opQ
560 break;
561 }
562
563 /* get Op from activeQ */
564 pOp = _stp_psm_get_op(stp_psm, &stp_psm->rActiveOpQ);
565 if (!pOp)
566 {
567 STP_PSM_WARN_FUNC("+++++++++++ Get op from activeQ fail, maybe disable/enable psm\n");
568 continue;
569 }
570
571 id = osal_op_get_id(pOp);
572
573 if (id >= STP_OPID_PSM_NUM)
574 {
575 STP_PSM_WARN_FUNC("abnormal opid id: 0x%x \n", id);
576 result = -1;
577 goto handler_done;
578 }
579
580 result = _stp_psm_handler(stp_psm, &pOp->op);
581
582handler_done:
583
584 if (result)
585 {
586 STP_PSM_WARN_FUNC("opid id(0x%x)(%s) error(%d)\n", id, (id >= 4)?("???"):(g_psm_op_name[id]), result);
587 }
588
589 if (osal_op_is_wait_for_signal(pOp))
590 {
591 osal_op_raise_signal(pOp, result);
592 }
593 else
594 {
595 /* put Op back to freeQ */
596 if(_stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, pOp) == 0)
597 {
598 STP_PSM_WARN_FUNC("+++++++++++ Put op to FreeOpQ fail, maybe disable/enable psm\n");
599 }
600 }
601
602 if (STP_OPID_PSM_EXIT == id)
603 {
604 break;
605 }
606 }
607 STP_PSM_INFO_FUNC("exits \n");
608
609 return 0;
610};
611
612static inline INT32 _stp_psm_get_time(void)
613{
614 if(gPsmDbgLevel >= STP_PSM_LOG_LOUD)
615 {
616 osal_printtimeofday("<psm time>>>>");
617 }
618
619 return 0;
620}
621
622static inline INT32 _stp_psm_get_state(MTKSTP_PSM_T *stp_psm)
623{
624
625 if(stp_psm == NULL)
626 {
627 return STP_PSM_OPERATION_FAIL;
628 }
629 else
630 {
631 if(stp_psm->work_state < STP_PSM_MAX_STATE)
632 {
633 return stp_psm->work_state;
634 }
635 else
636 {
637 STP_PSM_ERR_FUNC("work_state = %d, invalid\n", stp_psm->work_state);
638
639 return -STP_PSM_OPERATION_FAIL;
640 }
641 }
642}
643
644static inline INT32 _stp_psm_set_state(MTKSTP_PSM_T *stp_psm,const MTKSTP_PSM_STATE_T state)
645{
646 if(stp_psm == NULL)
647 {
648 return STP_PSM_OPERATION_FAIL;
649 }
650 else
651 {
652 if(stp_psm->work_state < STP_PSM_MAX_STATE)
653 {
654 _stp_psm_get_time();
655 //STP_PSM_INFO_FUNC("work_state = %s --> %s\n", g_psm_state[stp_psm->work_state], g_psm_state[state]);
656
657 stp_psm->work_state = state;
658 if(stp_psm->work_state != ACT)
659 {
660// osal_lock_unsleepable_lock(&stp_psm->flagSpinlock);
661 osal_set_bit(STP_PSM_BLOCK_DATA_EN,&stp_psm->flag);
662 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
663// osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock);
664 }
665 }
666 else
667 {
668 STP_PSM_ERR_FUNC("work_state = %d, invalid\n", stp_psm->work_state);
669 }
670 }
671
672 return STP_PSM_OPERATION_SUCCESS;
673}
674
675static inline INT32 _stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm)
676{
677
678 if(!stp_psm)
679 {
680 return STP_PSM_OPERATION_FAIL;
681 }
682
683 if(osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR,&stp_psm->flag))
684 {
685 STP_PSM_DBG_FUNC("STP-PSM DISABLE, DONT restart monitor!\n\r");
686 return STP_PSM_OPERATION_SUCCESS;
687 }
688
689
690 STP_PSM_LOUD_FUNC("start monitor\n");
691 osal_timer_modify(&stp_psm->psm_timer, stp_psm->idle_time_to_sleep);
692
693 return STP_PSM_OPERATION_SUCCESS;
694}
695
696static inline INT32 _stp_psm_stop_monitor(MTKSTP_PSM_T *stp_psm)
697{
698
699 if(!stp_psm)
700 {
701 return STP_PSM_OPERATION_FAIL;
702 }
703 else
704 {
705 STP_PSM_DBG_FUNC("stop monitor\n");
706 osal_timer_stop_sync(&stp_psm->psm_timer);
707 }
708
709 return STP_PSM_OPERATION_SUCCESS;
710}
711
712INT32
713_stp_psm_hold_data (
714 MTKSTP_PSM_T *stp_psm,
715 const UINT8 *buffer,
716 const UINT32 len,
717 const UINT8 type
718 )
719{
720 INT32 available_space = 0;
721 INT32 needed_space = 0;
722 UINT8 delimiter [] = {0xbb, 0xbb};
723
724 if(!stp_psm)
725 {
726 return STP_PSM_OPERATION_FAIL;
727 }
728 else
729 {
730 osal_lock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global);
731
732 available_space = STP_PSM_FIFO_SIZE- osal_fifo_len(&stp_psm->hold_fifo);
733 needed_space = len + sizeof(UINT8) + sizeof(UINT32) + 2;
734
735 //STP_PSM_INFO_FUNC("*******FIFO Available(%d), Need(%d)\n", available_space, needed_space);
736
737 if( available_space < needed_space )
738 {
739 STP_PSM_ERR_FUNC("FIFO Available!! Reset FIFO\n");
740 osal_fifo_reset(&stp_psm->hold_fifo);
741 }
742 //type
743 osal_fifo_in(&stp_psm->hold_fifo,(PUINT8) &type , sizeof(UINT8));
744 //lenght
745 osal_fifo_in(&stp_psm->hold_fifo,(PUINT8) &len , sizeof(UINT32));
746 //buffer
747 osal_fifo_in(&stp_psm->hold_fifo,(PUINT8) buffer, len);
748 //delimiter
749 osal_fifo_in(&stp_psm->hold_fifo,(PUINT8) delimiter, 2);
750
751 osal_unlock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global);
752
753 return len;
754 }
755}
756
757INT32 _stp_psm_has_pending_data(MTKSTP_PSM_T *stp_psm)
758{
759 return osal_fifo_len(&stp_psm->hold_fifo);
760}
761
762INT32 _stp_psm_release_data(MTKSTP_PSM_T *stp_psm)
763{
764
765 INT32 i = 20; /*Max buffered packet number*/
766 INT32 ret = 0;
767 UINT8 type = 0;
768 UINT32 len = 0;
769 UINT8 delimiter[2];
770
771 //STP_PSM_ERR_FUNC("++++++++++release data++len=%d\n", osal_fifo_len(&stp_psm->hold_fifo));
772 while(osal_fifo_len(&stp_psm->hold_fifo) && i > 0)
773 {
774 //acquire spinlock
775 osal_lock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global);
776
777 ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8)&type, sizeof(UINT8));
778 ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8)&len, sizeof(UINT32));
779
780 if(len > STP_PSM_PACKET_SIZE_MAX)
781 {
782 STP_PSM_ERR_FUNC("***psm packet's length too Long!****\n");
783 STP_PSM_INFO_FUNC("***reset psm's fifo***\n");
784 }
785 else
786 {
787 osal_memset(stp_psm->out_buf, 0, STP_PSM_TX_SIZE);
788 ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8)stp_psm->out_buf, len);
789 }
790
791 ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8)delimiter, 2);
792
793 if(delimiter[0]==0xbb && delimiter[1]==0xbb)
794 {
795 //osal_buffer_dump(stp_psm->out_buf, "psm->out_buf", len, 32);
796 stp_send_data_no_ps(stp_psm->out_buf, len, type);
797 }
798 else
799 {
800 STP_PSM_ERR_FUNC("***psm packet fifo parsing fail****\n");
801 STP_PSM_INFO_FUNC("***reset psm's fifo***\n");
802
803 osal_fifo_reset(&stp_psm->hold_fifo);
804 }
805 i--;
806 osal_unlock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global);
807 }
808 return STP_PSM_OPERATION_SUCCESS;
809}
810
811static inline INT32 _stp_psm_notify_wmt_host_awake_wq(MTKSTP_PSM_T *stp_psm)
812{
813
814 P_OSAL_OP pOp;
815 INT32 bRet;
816 INT32 retval;
817
818 if(stp_psm == NULL)
819 {
820 return STP_PSM_OPERATION_FAIL;
821 }
822 else
823 {
824 pOp = _stp_psm_get_free_op(stp_psm);
825 if (!pOp)
826 {
827 STP_PSM_WARN_FUNC("get_free_lxop fail \n");
828 return -1;//break;
829 }
830
831 pOp->op.opId = STP_OPID_PSM_HOST_AWAKE;
832 pOp->signal.timeoutValue = 0;
833 bRet = _stp_psm_put_act_op(stp_psm, pOp);
834
835 STP_PSM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d) \n\n",
836 pOp->op.opId,
837 pOp->op.au4OpData[0],
838 bRet);
839
840 retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : 0;
841 }
842 return retval;
843}
844
845static inline INT32 _stp_psm_notify_wmt_wakeup_wq(MTKSTP_PSM_T *stp_psm)
846{
847 P_OSAL_OP pOp;
848 INT32 bRet;
849 INT32 retval;
850
851 if(stp_psm == NULL)
852 {
853 return (STP_PSM_OPERATION_FAIL);
854 }
855 else
856 {
857 pOp = _stp_psm_get_free_op(stp_psm);
858 if (!pOp)
859 {
860 STP_PSM_WARN_FUNC("get_free_lxop fail \n");
861 return -1;//break;
862 }
863
864 pOp->op.opId = STP_OPID_PSM_WAKEUP;
865 pOp->signal.timeoutValue = 0;
866 bRet = _stp_psm_put_act_op(stp_psm, pOp);
867 if (0 == bRet)
868 {
869 STP_PSM_WARN_FUNC("OPID(%d) type(%zd) bRet(%s)\n\n",
870 pOp->op.opId,
871 pOp->op.au4OpData[0],
872 "fail");
873 }
874 retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : (STP_PSM_OPERATION_SUCCESS);
875 }
876 return retval;
877}
878
879static inline INT32 _stp_psm_notify_wmt_sleep_wq(MTKSTP_PSM_T *stp_psm)
880{
881 P_OSAL_OP pOp;
882 INT32 bRet;
883 INT32 retval;
884
885 if(stp_psm == NULL)
886 {
887 return STP_PSM_OPERATION_FAIL;
888 }
889 else
890 {
891 if(osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY,&stp_psm->flag))
892 {
893 return 0;
894 }
895
896#if PSM_USE_COUNT_PACKAGE
897 if(osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY,&stp_psm->flag))
898 {
899 return 0;
900 }
901#endif
902 if(osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR,&stp_psm->flag))
903 {
904 return 0;
905 }
906
907 pOp = _stp_psm_get_free_op(stp_psm);
908 if (!pOp) {
909 STP_PSM_WARN_FUNC("get_free_lxop fail \n");
910 return -1;//break;
911 }
912
913 pOp->op.opId = STP_OPID_PSM_SLEEP;
914 pOp->signal.timeoutValue = 0;
915 bRet = _stp_psm_put_act_op(stp_psm, pOp);
916
917 STP_PSM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d) \n\n",
918 pOp->op.opId,
919 pOp->op.au4OpData[0],
920 bRet);
921
922 retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : 0;
923 }
924 return retval;
925}
926
927/*internal function*/
928
929static inline INT32 _stp_psm_reset(MTKSTP_PSM_T *stp_psm)
930{
931 INT32 i = 0;
932 P_OSAL_OP_Q pOpQ;
933 P_OSAL_OP pOp;
934
935 STP_PSM_DBG_FUNC("PSM MODE RESET=============================>\n\r");
936
937 STP_PSM_INFO_FUNC("_stp_psm_reset\n");
938 STP_PSM_INFO_FUNC("reset-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock));
939 osal_wake_unlock(&stp_psm->wake_lock);
940 STP_PSM_INFO_FUNC("reset-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock));
941
942 //--> disable psm <--//
943 stp_psm->flag.data = 0;
944 osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR,&stp_psm->flag);
945 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
946 _stp_psm_stop_monitor(stp_psm);
947
948 //--> prepare the op list <--//
949 osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock));
950 RB_INIT(&stp_psm->rFreeOpQ, STP_OP_BUF_SIZE);
951 RB_INIT(&stp_psm->rActiveOpQ, STP_OP_BUF_SIZE);
952
953 //stp_psm->current_active_op = NULL;
954 stp_psm->last_active_opId = STP_OPID_PSM_INALID;
955
956 pOpQ = &stp_psm->rFreeOpQ;
957 for (i = 0; i < STP_OP_BUF_SIZE; i++)
958 {
959 if (!RB_FULL(pOpQ))
960 {
961 pOp = &stp_psm->arQue[i];
962 RB_PUT(pOpQ, pOp);
963 }
964 }
965 osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock));
966
967 //--> clean up interal data structure<--//
968 _stp_psm_set_state(stp_psm, ACT);
969
970 osal_lock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global);
971 osal_fifo_reset(&stp_psm->hold_fifo);
972 osal_unlock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global);
973
974 //--> stop psm thread wait <--//
975 osal_set_bit(STP_PSM_RESET_EN,&stp_psm->flag);
976 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
977 osal_trigger_event(&stp_psm->wait_wmt_q);
978
979
980 STP_PSM_DBG_FUNC("PSM MODE RESET<============================\n\r");
981
982 return STP_PSM_OPERATION_SUCCESS;
983}
984
985static INT32 _stp_psm_wait_wmt_event(void *pvData)
986{
987 MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *)pvData;
988
989 STP_PSM_DBG_FUNC("%s, stp_psm->flag= %ld\n", __func__, stp_psm->flag.data);
990
991 return ((osal_test_bit(STP_PSM_WMT_EVENT_SLEEP_EN,&stp_psm->flag)) ||
992 (osal_test_bit(STP_PSM_WMT_EVENT_WAKEUP_EN,&stp_psm->flag)) ||
993 (osal_test_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN,&stp_psm->flag)) ||
994 (osal_test_bit(STP_PSM_RESET_EN,&stp_psm->flag)));
995}
996
997
998static inline INT32 _stp_psm_wait_wmt_event_wq(MTKSTP_PSM_T *stp_psm){
999
1000 INT32 retval = 0;
1001
1002 if(stp_psm == NULL)
1003 {
1004 return STP_PSM_OPERATION_FAIL;
1005 }
1006 else
1007 {
1008 osal_wait_for_event_timeout(&stp_psm->wait_wmt_q,
1009 _stp_psm_wait_wmt_event,
1010 (void *)stp_psm);
1011
1012 if(osal_test_bit(STP_PSM_WMT_EVENT_WAKEUP_EN,&stp_psm->flag))
1013 {
1014 osal_clear_bit(STP_PSM_WMT_EVENT_WAKEUP_EN,&stp_psm->flag);
1015 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1016// osal_lock_unsleepable_lock(&stp_psm->flagSpinlock);
1017 //STP send data here: STP enqueue data to psm buffer.
1018 _stp_psm_release_data(stp_psm);
1019 //STP send data here: STP enqueue data to psm buffer. We release packet by the next one.
1020 osal_clear_bit(STP_PSM_BLOCK_DATA_EN,&stp_psm->flag);
1021 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1022 //STP send data here: STP sends data directly without PSM.
1023 _stp_psm_set_state(stp_psm, ACT);
1024// osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock);
1025
1026 if (stp_psm_is_quick_ps_support())
1027 stp_psm_notify_wmt_sleep(stp_psm);
1028 else
1029 _stp_psm_start_monitor(stp_psm);
1030 }
1031 else if (osal_test_bit(STP_PSM_WMT_EVENT_SLEEP_EN,&stp_psm->flag))
1032 {
1033 osal_clear_bit(STP_PSM_WMT_EVENT_SLEEP_EN,&stp_psm->flag);
1034 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1035 _stp_psm_set_state(stp_psm, INACT);
1036
1037 STP_PSM_DBG_FUNC("mt_combo_plt_enter_deep_idle++\n");
1038 mt_combo_plt_enter_deep_idle(COMBO_IF_BTIF);
1039 STP_PSM_DBG_FUNC("mt_combo_plt_enter_deep_idle--\n");
1040
1041 STP_PSM_DBG_FUNC("sleep-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock));
1042 osal_wake_unlock(&stp_psm->wake_lock);
1043 STP_PSM_DBG_FUNC("sleep-wake_lock#(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock));
1044 }
1045 else if (osal_test_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN,&stp_psm->flag))
1046 {
1047 osal_clear_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN,&stp_psm->flag);
1048 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1049 if(_stp_psm_get_state(stp_psm) == ACT_INACT){
1050// osal_lock_unsleepable_lock(&stp_psm->flagSpinlock);
1051 _stp_psm_release_data(stp_psm);
1052 osal_clear_bit(STP_PSM_BLOCK_DATA_EN,&stp_psm->flag);
1053 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1054 _stp_psm_set_state(stp_psm, ACT);
1055// osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock);
1056 } else if(_stp_psm_get_state(stp_psm) == INACT_ACT) {
1057 _stp_psm_set_state(stp_psm, INACT);
1058 STP_PSM_INFO_FUNC("[WARNING]PSM state rollback due too wakeup fail\n");
1059 }
1060 }
1061 else if (osal_test_bit(STP_PSM_RESET_EN,&stp_psm->flag))
1062 {
1063 osal_clear_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN,&stp_psm->flag);
1064 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1065 }
1066 else
1067 {
1068 STP_PSM_ERR_FUNC("flag = %ld<== Abnormal flag be set!!\n\r", stp_psm->flag.data);
1069 STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data);
1070 _stp_psm_dbg_out_printk(g_stp_psm_dbg);
1071 }
1072 retval = STP_PSM_OPERATION_SUCCESS;
1073 }
1074 return retval;
1075}
1076
1077static inline INT32 _stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action){
1078
1079 INT32 retval = 0;
1080
1081 if(action == EIRQ)
1082 {
1083 STP_PSM_DBG_FUNC("Call _stp_psm_notify_wmt_host_awake_wq\n\r");
1084
1085 _stp_psm_notify_wmt_host_awake_wq(stp_psm);
1086
1087 return STP_PSM_OPERATION_FAIL;
1088 }
1089
1090 if((_stp_psm_get_state(stp_psm) < STP_PSM_MAX_STATE) && (_stp_psm_get_state(stp_psm) >= 0))
1091 {
1092 STP_PSM_DBG_FUNC("state = %s, action=%s \n\r", g_psm_state[_stp_psm_get_state(stp_psm)], g_psm_action[action]);
1093 }
1094
1095 // If STP trigger WAKEUP and SLEEP, to do the job below
1096 switch(_stp_psm_get_state(stp_psm))
1097 {
1098 //stp trigger
1099 case ACT_INACT:
1100
1101 if(action == SLEEP)
1102 {
1103 STP_PSM_LOUD_FUNC("Action = %s, ACT_INACT state, ready to INACT\n\r", g_psm_action[action]);
1104 osal_clear_bit(STP_PSM_WMT_EVENT_WAKEUP_EN,&stp_psm->flag);
1105 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1106 osal_set_bit(STP_PSM_WMT_EVENT_SLEEP_EN,&stp_psm->flag);
1107 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1108 //wake_up(&stp_psm->wait_wmt_q);
1109 osal_trigger_event(&stp_psm->wait_wmt_q);
1110 }
1111 else if(action == ROLL_BACK)
1112 {
1113 STP_PSM_LOUD_FUNC("Action = %s, ACT_INACT state, back to ACT\n\r", g_psm_action[action]);
1114 //stp_psm->flag &= ~STP_PSM_WMT_EVENT_ROLL_BACK_EN;
1115 osal_set_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN,&stp_psm->flag);
1116 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1117 //wake_up(&stp_psm->wait_wmt_q);
1118 osal_trigger_event(&stp_psm->wait_wmt_q);
1119 }
1120 else
1121 {
1122 if(action < STP_PSM_MAX_ACTION)
1123 {
1124 STP_PSM_ERR_FUNC("Action = %s, ACT_INACT state, the case should not happens\n\r", g_psm_action[action]);
1125 STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data);
1126 }
1127 else
1128 {
1129 STP_PSM_ERR_FUNC("Invalid Action!!\n\r");
1130 }
1131 _stp_psm_dbg_out_printk(g_stp_psm_dbg);
1132 retval = STP_PSM_OPERATION_FAIL;
1133 }
1134 break;
1135 //stp trigger
1136
1137 case INACT_ACT:
1138
1139 if(action == WAKEUP)
1140 {
1141 STP_PSM_LOUD_FUNC("Action = %s, INACT_ACT state, ready to ACT\n\r", g_psm_action[action]);
1142 osal_clear_bit(STP_PSM_WMT_EVENT_SLEEP_EN,&stp_psm->flag);
1143 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1144 osal_set_bit(STP_PSM_WMT_EVENT_WAKEUP_EN,&stp_psm->flag);
1145 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1146 //wake_up(&stp_psm->wait_wmt_q);
1147 osal_trigger_event(&stp_psm->wait_wmt_q);
1148 }
1149 else if(action == HOST_AWAKE)
1150 {
1151 STP_PSM_LOUD_FUNC("Action = %s, INACT_ACT state, ready to ACT\n\r", g_psm_action[action]);
1152 osal_clear_bit(STP_PSM_WMT_EVENT_SLEEP_EN,&stp_psm->flag);
1153 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1154 osal_set_bit(STP_PSM_WMT_EVENT_WAKEUP_EN,&stp_psm->flag);
1155 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1156 //wake_up(&stp_psm->wait_wmt_q);
1157 osal_trigger_event(&stp_psm->wait_wmt_q);
1158 }
1159 else if(action == ROLL_BACK)
1160 {
1161 STP_PSM_LOUD_FUNC("Action = %s, INACT_ACT state, back to INACT\n\r", g_psm_action[action]);
1162 osal_set_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN,&stp_psm->flag);
1163 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1164 //wake_up(&stp_psm->wait_wmt_q);
1165 osal_trigger_event(&stp_psm->wait_wmt_q);
1166 }
1167 else
1168 {
1169 if(action < STP_PSM_MAX_ACTION)
1170 {
1171 STP_PSM_ERR_FUNC("Action = %s, INACT_ACT state, the case should not happens\n\r", g_psm_action[action]);
1172 STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data);
1173 }
1174 else
1175 {
1176 STP_PSM_ERR_FUNC("Invalid Action!!\n\r");
1177 }
1178 _stp_psm_dbg_out_printk(g_stp_psm_dbg);
1179 retval = STP_PSM_OPERATION_FAIL;
1180 }
1181 break;
1182
1183 case INACT:
1184
1185 if(action < STP_PSM_MAX_ACTION)
1186 {
1187 STP_PSM_ERR_FUNC("Action = %s, INACT state, the case should not happens\n\r", g_psm_action[action]);
1188 STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data);
1189 }
1190 else
1191 {
1192 STP_PSM_ERR_FUNC("Invalid Action!!\n\r");
1193 }
1194 _stp_psm_dbg_out_printk(g_stp_psm_dbg);
1195 retval = -1;
1196
1197 break;
1198
1199 case ACT:
1200
1201 if(action < STP_PSM_MAX_ACTION)
1202 {
1203 STP_PSM_ERR_FUNC("Action = %s, ACT state, the case should not happens\n\r", g_psm_action[action]);
1204 STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data);
1205 }
1206 else
1207 {
1208 STP_PSM_ERR_FUNC("Invalid Action!!\n\r");
1209 }
1210 _stp_psm_dbg_out_printk(g_stp_psm_dbg);
1211 retval = STP_PSM_OPERATION_FAIL;
1212
1213 break;
1214
1215 default:
1216
1217 /*invalid*/
1218 if(action < STP_PSM_MAX_ACTION)
1219 {
1220 STP_PSM_ERR_FUNC("Action = %s, Invalid state, the case should not happens\n\r", g_psm_action[action]);
1221 STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data);
1222 }
1223 else
1224 {
1225 STP_PSM_ERR_FUNC("Invalid Action!!\n\r");
1226 }
1227 _stp_psm_dbg_out_printk(g_stp_psm_dbg);
1228 retval = STP_PSM_OPERATION_FAIL;
1229
1230 break;
1231 }
1232
1233 return retval;
1234
1235}
1236
1237static inline INT32 _stp_psm_notify_wmt(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action)
1238{
1239 INT32 ret = 0;
1240
1241 if (stp_psm == NULL)
1242 {
1243 return STP_PSM_OPERATION_FAIL;
1244 }
1245
1246 switch(_stp_psm_get_state(stp_psm))
1247 {
1248 case ACT:
1249
1250 if(action == SLEEP)
1251 {
1252 if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR,&stp_psm->flag)) {
1253 STP_PSM_ERR_FUNC("psm monitor disabled, can't do sleep op\n");
1254 return STP_PSM_OPERATION_FAIL;
1255 }
1256
1257 _stp_psm_set_state(stp_psm, ACT_INACT);
1258
1259 _stp_psm_release_data(stp_psm);
1260
1261 if(stp_psm->wmt_notify)
1262 {
1263 stp_psm->wmt_notify(SLEEP);
1264 _stp_psm_wait_wmt_event_wq(stp_psm);
1265 }
1266 else
1267 {
1268 STP_PSM_ERR_FUNC("stp_psm->wmt_notify = NULL\n");
1269 ret = STP_PSM_OPERATION_FAIL;
1270 }
1271 }
1272 else if(action == WAKEUP || action == HOST_AWAKE)
1273 {
1274 STP_PSM_INFO_FUNC("In ACT state, dont do WAKEUP/HOST_AWAKE again\n");
1275 _stp_psm_release_data(stp_psm);
1276 }
1277 else
1278 {
1279 STP_PSM_ERR_FUNC("invalid operation, the case should not happen\n");
1280 STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data);
1281 _stp_psm_dbg_out_printk(g_stp_psm_dbg);
1282 ret = STP_PSM_OPERATION_FAIL;
1283
1284 }
1285
1286 break;
1287
1288 case INACT:
1289
1290 if(action == WAKEUP)
1291 {
1292 _stp_psm_set_state(stp_psm, INACT_ACT);
1293
1294 if(stp_psm->wmt_notify)
1295 {
1296 STP_PSM_DBG_FUNC("wakeup +wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock));
1297 osal_wake_lock(&stp_psm->wake_lock);
1298 STP_PSM_DBG_FUNC("wakeup +wake_lock(%d)#\n", osal_wake_lock_count(&stp_psm->wake_lock));
1299
1300 STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle++\n");
1301 mt_combo_plt_exit_deep_idle(COMBO_IF_BTIF);
1302 STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle--\n");
1303
1304 stp_psm->wmt_notify(WAKEUP);
1305 _stp_psm_wait_wmt_event_wq(stp_psm);
1306 }
1307 else
1308 {
1309 STP_PSM_ERR_FUNC("stp_psm->wmt_notify = NULL\n");
1310 ret = STP_PSM_OPERATION_FAIL;
1311 }
1312 }
1313 else if(action == HOST_AWAKE)
1314 {
1315 _stp_psm_set_state(stp_psm, INACT_ACT);
1316
1317 if(stp_psm->wmt_notify)
1318 {
1319 STP_PSM_DBG_FUNC("host awake +wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock));
1320 osal_wake_lock(&stp_psm->wake_lock);
1321 STP_PSM_DBG_FUNC("host awake +wake_lock(%d)#\n", osal_wake_lock_count(&stp_psm->wake_lock));
1322
1323 STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle++\n");
1324 mt_combo_plt_exit_deep_idle(COMBO_IF_BTIF);
1325 STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle--\n");
1326
1327 stp_psm->wmt_notify(HOST_AWAKE);
1328 _stp_psm_wait_wmt_event_wq(stp_psm);
1329 }
1330 else
1331 {
1332 STP_PSM_ERR_FUNC("stp_psm->wmt_notify = NULL\n");
1333 ret = STP_PSM_OPERATION_FAIL;
1334 }
1335 }
1336 else if(action == SLEEP)
1337 {
1338 STP_PSM_INFO_FUNC("In INACT state, dont do SLEEP again\n");
1339 }
1340 else
1341 {
1342 STP_PSM_ERR_FUNC("invalid operation, the case should not happen\n");
1343 STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data);
1344 _stp_psm_dbg_out_printk(g_stp_psm_dbg);
1345 ret = STP_PSM_OPERATION_FAIL;
1346 }
1347
1348 break;
1349
1350 default:
1351
1352 /*invalid*/
1353 STP_PSM_ERR_FUNC("invalid state, the case should not happen\n");
1354 STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data);
1355 _stp_psm_dbg_out_printk(g_stp_psm_dbg);
1356 ret = STP_PSM_OPERATION_FAIL;
1357
1358 break;
1359 }
1360 return ret;
1361}
1362
1363static inline void _stp_psm_stp_is_idle(unsigned long data)
1364{
1365 MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *)data;
1366
1367 osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY,&stp_psm->flag);
1368 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1369 osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY,&stp_psm->flag);
1370 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1371 if(osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR,&stp_psm->flag))
1372 {
1373 STP_PSM_DBG_FUNC("STP-PSM DISABLE!\n");
1374 return ;
1375 }
1376
1377 STP_PSM_INFO_FUNC("**IDLE is over %d msec, go to sleep!!!**\n", stp_psm->idle_time_to_sleep);
1378 _stp_psm_notify_wmt_sleep_wq(stp_psm);
1379}
1380
1381static inline INT32 _stp_psm_init_monitor(MTKSTP_PSM_T *stp_psm)
1382{
1383 if(!stp_psm)
1384 {
1385 return STP_PSM_OPERATION_FAIL;
1386 }
1387
1388 STP_PSM_INFO_FUNC("init monitor\n");
1389
1390 stp_psm->psm_timer.timeoutHandler = _stp_psm_stp_is_idle;
1391 stp_psm->psm_timer.timeroutHandlerData = (unsigned long)stp_psm;
1392 osal_timer_create(&stp_psm->psm_timer);
1393
1394 return STP_PSM_OPERATION_SUCCESS;
1395}
1396
1397static inline INT32 _stp_psm_deinit_monitor(MTKSTP_PSM_T *stp_psm)
1398{
1399
1400 if(!stp_psm)
1401 {
1402 return STP_PSM_OPERATION_FAIL;
1403 }
1404 else
1405 {
1406 STP_PSM_INFO_FUNC("deinit monitor\n");
1407
1408 osal_timer_stop_sync(&stp_psm->psm_timer);
1409 }
1410
1411 return 0;
1412}
1413
1414static inline INT32 _stp_psm_is_to_block_traffic(MTKSTP_PSM_T *stp_psm)
1415{
1416 INT32 iRet = -1;
1417
1418// osal_lock_unsleepable_lock(&stp_psm->flagSpinlock);
1419
1420 if(osal_test_bit(STP_PSM_BLOCK_DATA_EN,&stp_psm->flag))
1421 {
1422 iRet = 1;
1423 }
1424 else
1425 {
1426 iRet = 0;
1427 }
1428// osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock);
1429 return iRet;
1430}
1431
1432static inline INT32 _stp_psm_is_disable(MTKSTP_PSM_T *stp_psm)
1433{
1434 if(osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR,&stp_psm->flag))
1435 {
1436 return 1;
1437 }
1438 else
1439 {
1440 return 0;
1441 }
1442}
1443
1444static inline INT32 _stp_psm_do_wait(MTKSTP_PSM_T *stp_psm, MTKSTP_PSM_STATE_T state){
1445
1446 #define POLL_WAIT 20//200
1447 #define POLL_WAIT_TIME 2000
1448
1449 INT32 i = 0;
1450 INT32 limit = POLL_WAIT_TIME/POLL_WAIT;
1451
1452 while(_stp_psm_get_state(stp_psm)!=state && i < limit)
1453 {
1454 osal_sleep_ms(POLL_WAIT);
1455 i++;
1456 STP_PSM_INFO_FUNC("STP is waiting state for %s, i=%d, state = %d\n", g_psm_state[state],i , _stp_psm_get_state(stp_psm));
1457 }
1458
1459 if(i == limit)
1460 {
1461 STP_PSM_WARN_FUNC("-Wait for %s takes %d msec\n", g_psm_state[state], i*POLL_WAIT);
1462 _stp_psm_opid_dbg_out_printk(g_stp_psm_opid_dbg);
1463 return STP_PSM_OPERATION_FAIL;
1464 }
1465 else
1466 {
1467 STP_PSM_DBG_FUNC("+Total waits for %s takes %d msec\n", g_psm_state[state], i*POLL_WAIT);
1468 //_stp_psm_dbg_out_printk(g_stp_psm_opid_dbg);
1469 return STP_PSM_OPERATION_SUCCESS;
1470 }
1471}
1472
1473static inline INT32 _stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm)
1474{
1475
1476 INT32 ret = 0;
1477 INT32 retry = 10;
1478 P_OSAL_OP_Q pOpQ;
1479 P_OSAL_OP pOp;
1480
1481 STP_PSM_LOUD_FUNC("*** Do Force Wakeup!***\n\r");
1482
1483 //<1>If timer is active, we will stop it.
1484 _stp_psm_stop_monitor(stp_psm);
1485
1486 osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock));
1487
1488 pOpQ = &stp_psm->rFreeOpQ;
1489
1490 while (!RB_EMPTY(&stp_psm->rActiveOpQ))
1491 {
1492 RB_GET(&stp_psm->rActiveOpQ, pOp);
1493 if (NULL != pOp && !RB_FULL(pOpQ))
1494 {
1495 STP_PSM_DBG_FUNC("opid = %d\n", pOp->op.opId);
1496 RB_PUT(pOpQ, pOp);
1497 }
1498 else
1499 {
1500 STP_PSM_ERR_FUNC("clear up active queue fail, freeQ full\n");
1501 }
1502 }
1503 osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock));
1504 //<5>We issue wakeup request into op queue. and wait for active.
1505 do{
1506 ret = _stp_psm_notify_wmt_wakeup_wq(stp_psm);
1507
1508 if(ret == STP_PSM_OPERATION_SUCCESS)
1509 {
1510 ret = _stp_psm_do_wait(stp_psm, ACT);
1511
1512 //STP_PSM_INFO_FUNC("<< wait ret = %d, num of activeQ = %d\n", ret, RB_COUNT(&stp_psm->rActiveOpQ));
1513 if(ret == STP_PSM_OPERATION_SUCCESS)
1514 {
1515 break;
1516 }
1517 }
1518 else
1519 {
1520 STP_PSM_ERR_FUNC("_stp_psm_notify_wmt_wakeup_wq fail!!\n");
1521 }
1522
1523 //STP_PSM_INFO_FUNC("retry = %d\n", retry);
1524 retry--;
1525
1526 if(retry == 0)
1527 {
1528 break;
1529 }
1530 }
1531 while(1);
1532
1533 if(retry == 0)
1534 {
1535 return STP_PSM_OPERATION_FAIL;
1536 }
1537 else
1538 {
1539 return STP_PSM_OPERATION_SUCCESS;
1540 }
1541}
1542
1543static inline INT32 _stp_psm_disable(MTKSTP_PSM_T *stp_psm)
1544{
1545 INT32 ret = STP_PSM_OPERATION_FAIL;
1546
1547 STP_PSM_DBG_FUNC("PSM Disable start\n\r");
1548
1549 osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR,&stp_psm->flag);
1550 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1551 ret = _stp_psm_do_wakeup(stp_psm);
1552 if (ret == STP_PSM_OPERATION_SUCCESS)
1553 {
1554 STP_PSM_DBG_FUNC("PSM Disable Success\n");
1555 }
1556 else
1557 {
1558 STP_PSM_ERR_FUNC("***PSM Disable Fail***\n");
1559 }
1560
1561 return ret;
1562}
1563
1564static inline INT32 _stp_psm_enable(MTKSTP_PSM_T *stp_psm, INT32 idle_time_to_sleep)
1565{
1566 INT32 ret = STP_PSM_OPERATION_FAIL;
1567 STP_PSM_LOUD_FUNC("PSM Enable start\n\r");
1568
1569 osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR,&stp_psm->flag);
1570 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1571
1572 ret = _stp_psm_do_wakeup(stp_psm);
1573 if(ret == STP_PSM_OPERATION_SUCCESS)
1574 {
1575 osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR,&stp_psm->flag);
1576 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1577 stp_psm->idle_time_to_sleep = idle_time_to_sleep;
1578
1579 if(osal_wake_lock_count(&stp_psm->wake_lock) == 0)
1580 {
1581 STP_PSM_DBG_FUNC("psm_en+wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock));
1582 osal_wake_lock(&stp_psm->wake_lock);
1583 STP_PSM_DBG_FUNC("psm_en+wake_lock(%d)#\n", osal_wake_lock_count(&stp_psm->wake_lock));
1584 }
1585
1586 _stp_psm_start_monitor(stp_psm);
1587
1588 STP_PSM_DBG_FUNC("PSM Enable succeed\n\r");
1589 }
1590 else
1591 {
1592 STP_PSM_ERR_FUNC("***PSM Enable Fail***\n");
1593 }
1594
1595 return ret;
1596}
1597
1598INT32 _stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm)
1599{
1600 return osal_lock_sleepable_lock(&stp_psm->stp_psm_lock);
1601}
1602
1603INT32 _stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm)
1604{
1605 osal_unlock_sleepable_lock(&stp_psm->stp_psm_lock);
1606 return 0;
1607}
1608
1609MTK_WCN_BOOL _stp_psm_is_quick_ps_support (VOID)
1610{
1611 if (stp_psm->is_wmt_quick_ps_support)
1612 {
1613 return (*(stp_psm->is_wmt_quick_ps_support))();
1614 }
1615 STP_PSM_DBG_FUNC("stp_psm->is_wmt_quick_ps_support is NULL, return false\n\r");
1616 return MTK_WCN_BOOL_FALSE;
1617}
1618
1619
1620MTK_WCN_BOOL stp_psm_is_quick_ps_support (VOID)
1621{
1622 return _stp_psm_is_quick_ps_support();
1623}
1624
1625#if PSM_USE_COUNT_PACKAGE
1626int stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, int dir){
1627
1628 //easy the variable maintain beween stp tx, rx thread.
1629 //so we create variable for tx, rx respectively.
1630
1631 static int tx_cnt = 0;
1632 static int rx_cnt = 0;
1633 static int is_tx_first = 1;
1634 static int is_rx_first = 1;
1635 static unsigned long tx_end_time = 0;
1636 static unsigned long rx_end_time = 0;
1637
1638 //
1639 //BT A2DP TX CNT = 220, RX CNT = 843
1640 //BT FTP Transferring TX CNT = 574, RX CNT = 2233 (1228~1588)
1641 //BT FTP Receiving TX CNT = 204, RX CNT = 3301 (2072~2515)
1642 //BT OPP Tx TX_CNT= 330, RX CNT = 1300~1800
1643 //BT OPP Rx TX_CNT= (109~157), RX CNT = 1681~2436
1644 if(dir == 0)//tx
1645 {
1646 tx_cnt++;
1647
1648 if(((long)jiffies - (long)tx_end_time >= 0) || (is_tx_first))
1649 {
1650 tx_end_time = jiffies + (3*HZ);
1651 STP_PSM_INFO_FUNC("tx cnt = %d in the previous 3 sec\n", tx_cnt);
1652 //if(tx_cnt > 400)//for high traffic , not to do sleep.
1653 if (tx_cnt > 300)
1654 {
1655 osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY,&stp_psm->flag);
1656 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1657 stp_psm_start_monitor(stp_psm);
1658 }
1659 else
1660 {
1661 osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY,&stp_psm->flag);
1662 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1663 }
1664 tx_cnt = 0;
1665 if(is_tx_first)
1666 is_tx_first = 0;
1667 }
1668 }
1669 else
1670 {
1671 rx_cnt++;
1672
1673 if(((long)jiffies - (long)rx_end_time >= 0) || (is_rx_first))
1674 {
1675 rx_end_time = jiffies + (3*HZ);
1676 STP_PSM_INFO_FUNC("rx cnt = %d in the previous 3 sec\n", rx_cnt);
1677
1678 //if(rx_cnt > 2000)//for high traffic , not to do sleep.
1679 if(rx_cnt > 1200)//for high traffic , not to do sleep.
1680 {
1681 osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY,&stp_psm->flag);
1682 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1683 stp_psm_start_monitor(stp_psm);
1684 }
1685 else
1686 {
1687 osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY,&stp_psm->flag);
1688 _stp_psm_dbg_dmp_in(g_stp_psm_dbg,stp_psm->flag.data,__LINE__);
1689 }
1690 rx_cnt = 0;
1691 if(is_rx_first)
1692 is_rx_first = 0;
1693 }
1694 }
1695
1696 return 0;
1697}
1698
1699#else
1700static struct timeval tv_now, tv_end;
1701static INT32 sample_start = 0;
1702static INT32 tx_sum_len = 0;
1703static INT32 rx_sum_len = 0;
1704
1705INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir,INT32 length)
1706{
1707 if (sample_start) {
1708 if (dir) {
1709 rx_sum_len += length;
1710 } else {
1711 tx_sum_len += length;
1712 }
1713 do_gettimeofday(&tv_now);
1714 //STP_PSM_INFO_FUNC("tv_now:%d.%d tv_end:%d.%d\n",tv_now.tv_sec,tv_now.tv_usec,tv_end.tv_sec,tv_end.tv_usec);
1715 if (((tv_now.tv_sec == tv_end.tv_sec) && (tv_now.tv_usec > tv_end.tv_usec))||
1716 (tv_now.tv_sec > tv_end.tv_sec)) {
1717 STP_PSM_INFO_FUNC("STP speed rx:%d tx:%d\n",rx_sum_len,tx_sum_len);
1718 if((rx_sum_len + tx_sum_len) > RTX_SPEED_THRESHOLD ){
1719 //STP_PSM_INFO_FUNC("High speed,Disable monitor\n");
1720 osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY,&stp_psm->flag);
1721 stp_psm_start_monitor(stp_psm);
1722 }else{
1723 //STP_PSM_INFO_FUNC("Low speed,Enable monitor\n");
1724 osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY,&stp_psm->flag);
1725 }
1726 sample_start = 0;
1727 rx_sum_len = 0;
1728 tx_sum_len = 0;
1729 }
1730 }else{
1731 sample_start = 1;
1732 do_gettimeofday(&tv_now);
1733 tv_end = tv_now;
1734 tv_end.tv_sec += SAMPLE_DURATION;
1735 }
1736
1737 return 0;
1738}
1739#endif
1740
1741/*external function for WMT module to do sleep/wakeup*/
1742INT32 stp_psm_set_state(MTKSTP_PSM_T *stp_psm, MTKSTP_PSM_STATE_T state)
1743{
1744 return _stp_psm_set_state(stp_psm, state);
1745}
1746
1747
1748INT32 stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm)
1749{
1750 return _stp_psm_thread_lock_aquire(stp_psm);
1751}
1752
1753
1754INT32 stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm)
1755{
1756 return _stp_psm_thread_lock_release(stp_psm);
1757}
1758
1759
1760
1761INT32 stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm)
1762{
1763 return _stp_psm_do_wakeup(stp_psm);
1764}
1765
1766INT32 stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action)
1767{
1768
1769 return _stp_psm_notify_stp(stp_psm, action);
1770}
1771
1772INT32 stp_psm_notify_wmt_wakeup(MTKSTP_PSM_T *stp_psm)
1773{
1774 return _stp_psm_notify_wmt_wakeup_wq(stp_psm);
1775}
1776
1777int stp_psm_notify_wmt_sleep(MTKSTP_PSM_T *stp_psm){
1778
1779 return _stp_psm_notify_wmt_sleep_wq(stp_psm);
1780}
1781
1782INT32 stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm)
1783{
1784 return _stp_psm_start_monitor(stp_psm);
1785}
1786
1787INT32 stp_psm_is_to_block_traffic(MTKSTP_PSM_T *stp_psm)
1788{
1789 return _stp_psm_is_to_block_traffic(stp_psm);
1790}
1791
1792INT32 stp_psm_is_disable(MTKSTP_PSM_T *stp_psm)
1793{
1794 return _stp_psm_is_disable(stp_psm);
1795}
1796
1797INT32 stp_psm_has_pending_data(MTKSTP_PSM_T *stp_psm)
1798{
1799 return _stp_psm_has_pending_data(stp_psm);
1800}
1801
1802INT32 stp_psm_release_data(MTKSTP_PSM_T *stp_psm)
1803{
1804 return _stp_psm_release_data(stp_psm);
1805}
1806
1807INT32
1808stp_psm_hold_data (
1809 MTKSTP_PSM_T *stp_psm,
1810 const UINT8 *buffer,
1811 const UINT32 len,
1812 const UINT8 type
1813 )
1814{
1815 return _stp_psm_hold_data(stp_psm, buffer, len, type);
1816}
1817
1818INT32 stp_psm_disable(MTKSTP_PSM_T *stp_psm)
1819{
1820 return _stp_psm_disable(stp_psm);
1821}
1822
1823INT32 stp_psm_enable(MTKSTP_PSM_T *stp_psm, INT32 idle_time_to_sleep)
1824{
1825 return _stp_psm_enable(stp_psm, idle_time_to_sleep);
1826}
1827
1828INT32 stp_psm_reset(MTKSTP_PSM_T *stp_psm)
1829{
1830 stp_psm_set_sleep_enable(stp_psm);
1831
1832 return _stp_psm_reset(stp_psm);
1833}
1834
1835INT32 stp_psm_sleep_for_thermal(MTKSTP_PSM_T *stp_psm)
1836{
1837 return _stp_psm_notify_wmt_sleep_wq(stp_psm);
1838}
1839
1840
1841INT32 stp_psm_set_sleep_enable(MTKSTP_PSM_T *stp_psm)
1842{
1843 INT32 ret = 0;
1844
1845 if (stp_psm) {
1846 stp_psm->sleep_en = 1;
1847 STP_PSM_DBG_FUNC("\n");
1848 ret = 0;
1849 } else {
1850 STP_PSM_INFO_FUNC("Null pointer\n");
1851 ret = -1;
1852 }
1853
1854 return ret;
1855}
1856
1857
1858INT32 stp_psm_set_sleep_disable(MTKSTP_PSM_T *stp_psm)
1859{
1860 INT32 ret = 0;
1861
1862 if (stp_psm) {
1863 stp_psm->sleep_en = 0;
1864 STP_PSM_DBG_FUNC("\n");
1865 ret = 0;
1866 } else {
1867 STP_PSM_INFO_FUNC("Null pointer\n");
1868 ret = -1;
1869 }
1870
1871 return ret;
1872}
1873
1874
1875/* stp_psm_check_sleep_enable - to check if sleep cmd is enabled or not
1876 * @ stp_psm - pointer of psm
1877 *
1878 * return 1 if sleep is enabled; else return 0 if disabled; else error code
1879 */
1880INT32 stp_psm_check_sleep_enable(MTKSTP_PSM_T *stp_psm)
1881{
1882 INT32 ret = 0;
1883
1884 if (stp_psm) {
1885 ret = stp_psm->sleep_en;
1886 STP_PSM_DBG_FUNC("%s \n", ret? "enabled" : "disabled");
1887 } else {
1888 STP_PSM_INFO_FUNC("Null pointer\n");
1889 ret = -1;
1890 }
1891
1892 return ret;
1893}
1894
1895static INT32 _stp_psm_dbg_dmp_in(STP_PSM_RECORD_T *stp_psm_dbg, UINT32 flag, UINT32 line_num)
1896{
1897 INT32 index = 0;
1898 struct timeval now;
1899 if(stp_psm_dbg)
1900 {
1901 osal_lock_unsleepable_lock(&stp_psm_dbg->lock);
1902 do_gettimeofday(&now);
1903 index = stp_psm_dbg->in - 1;
1904 index = (index + STP_PSM_DBG_SIZE) % STP_PSM_DBG_SIZE;
1905 STP_PSM_DBG_FUNC("index(%d)\n",index);
1906 stp_psm_dbg->queue[stp_psm_dbg->in].prev_flag = stp_psm_dbg->queue[index].cur_flag;
1907 stp_psm_dbg->queue[stp_psm_dbg->in].cur_flag = flag;
1908 stp_psm_dbg->queue[stp_psm_dbg->in].line_num = line_num;
1909 stp_psm_dbg->queue[stp_psm_dbg->in].package_no = g_record_num++;
1910 stp_psm_dbg->queue[stp_psm_dbg->in].sec= now.tv_sec;
1911 stp_psm_dbg->queue[stp_psm_dbg->in].usec = now.tv_usec;
1912 stp_psm_dbg->size++;
1913 STP_PSM_DBG_FUNC("pre_Flag = %d, cur_flag = %d\n", stp_psm_dbg->queue[stp_psm_dbg->in].prev_flag, stp_psm_dbg->queue[stp_psm_dbg->in].cur_flag);
1914 stp_psm_dbg->size = (stp_psm_dbg->size > STP_PSM_DBG_SIZE) ? STP_PSM_DBG_SIZE : stp_psm_dbg->size;
1915 stp_psm_dbg->in = (stp_psm_dbg->in >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (stp_psm_dbg->in + 1);
1916 STP_PSM_DBG_FUNC("record size = %d, in = %d num = %d\n", stp_psm_dbg->size, stp_psm_dbg->in,line_num);
1917
1918 osal_unlock_unsleepable_lock(&stp_psm_dbg->lock);
1919 }
1920 return 0;
1921}
1922
1923static INT32 _stp_psm_dbg_out_printk(STP_PSM_RECORD_T *stp_psm_dbg)
1924{
1925
1926 UINT32 dumpSize = 0;
1927 UINT32 inIndex = 0;
1928 UINT32 outIndex = 0;
1929
1930 if(!stp_psm_dbg)
1931 {
1932 STP_PSM_ERR_FUNC("NULL g_stp_psm_dbg reference\n");
1933 return -1;
1934 }
1935 osal_lock_unsleepable_lock(&stp_psm_dbg->lock);
1936
1937 inIndex = stp_psm_dbg->in;
1938 dumpSize = stp_psm_dbg->size;
1939 if (STP_PSM_DBG_SIZE == dumpSize)
1940 {
1941 outIndex = inIndex;
1942 }
1943 else
1944 {
1945 outIndex = ((inIndex + STP_PSM_DBG_SIZE) - dumpSize) % STP_PSM_DBG_SIZE;
1946 }
1947
1948 STP_PSM_INFO_FUNC("loged record size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex);
1949 while(dumpSize > 0){
1950
1951 printk("STP-PSM:%d.%ds, n(%d)pre_flag(%d)cur_flag(%d)line_no(%d)\n", \
1952 stp_psm_dbg->queue[outIndex].sec,
1953 stp_psm_dbg->queue[outIndex].usec,
1954 stp_psm_dbg->queue[outIndex].package_no,
1955 stp_psm_dbg->queue[outIndex].prev_flag,
1956 stp_psm_dbg->queue[outIndex].cur_flag,
1957 stp_psm_dbg->queue[outIndex].line_num
1958 );
1959
1960
1961 outIndex = (outIndex >= (STP_PSM_DBG_SIZE - 1))?(0):(outIndex + 1);
1962 dumpSize--;
1963
1964 }
1965
1966
1967 osal_unlock_unsleepable_lock(&stp_psm_dbg->lock);
1968
1969 return 0;
1970}
1971
1972static INT32 _stp_psm_opid_dbg_dmp_in(P_STP_PSM_OPID_RECORD p_opid_dbg, UINT32 opid, UINT32 line_num)
1973{
1974 INT32 index = 0;
1975 struct timeval now;
1976 if(p_opid_dbg)
1977 {
1978 osal_lock_unsleepable_lock(&p_opid_dbg->lock);
1979 do_gettimeofday(&now);
1980 index = p_opid_dbg->in - 1;
1981 index = (index + STP_PSM_DBG_SIZE) % STP_PSM_DBG_SIZE;
1982 STP_PSM_DBG_FUNC("index(%d)\n",index);
1983 p_opid_dbg->queue[p_opid_dbg->in].prev_flag = p_opid_dbg->queue[index].cur_flag;
1984 p_opid_dbg->queue[p_opid_dbg->in].cur_flag = opid;
1985 p_opid_dbg->queue[p_opid_dbg->in].line_num = line_num;
1986 p_opid_dbg->queue[p_opid_dbg->in].package_no = g_opid_record_num++;
1987 p_opid_dbg->queue[p_opid_dbg->in].sec= now.tv_sec;
1988 p_opid_dbg->queue[p_opid_dbg->in].usec = now.tv_usec;
1989 p_opid_dbg->queue[p_opid_dbg->in].pid = current->pid;
1990 p_opid_dbg->size++;
1991 STP_PSM_DBG_FUNC("pre_opid = %d, cur_opid = %d\n", p_opid_dbg->queue[p_opid_dbg->in].prev_flag, p_opid_dbg->queue[p_opid_dbg->in].cur_flag);
1992 p_opid_dbg->size = (p_opid_dbg->size > STP_PSM_DBG_SIZE) ? STP_PSM_DBG_SIZE : p_opid_dbg->size;
1993 p_opid_dbg->in = (p_opid_dbg->in >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (p_opid_dbg->in + 1);
1994 STP_PSM_DBG_FUNC("opid record size = %d, in = %d num = %d\n", p_opid_dbg->size, p_opid_dbg->in,line_num);
1995
1996 osal_unlock_unsleepable_lock(&p_opid_dbg->lock);
1997 }
1998 return 0;
1999
2000}
2001
2002static INT32 _stp_psm_opid_dbg_out_printk(P_STP_PSM_OPID_RECORD p_opid_dbg)
2003{
2004 UINT32 dumpSize = 0;
2005 UINT32 inIndex = 0;
2006 UINT32 outIndex = 0;
2007
2008 if(!p_opid_dbg)
2009 {
2010 STP_PSM_ERR_FUNC("NULL p_opid_dbg reference\n");
2011 return -1;
2012 }
2013 osal_lock_unsleepable_lock(&p_opid_dbg->lock);
2014
2015 inIndex = p_opid_dbg->in;
2016 dumpSize = p_opid_dbg->size;
2017 if (STP_PSM_DBG_SIZE == dumpSize)
2018 {
2019 outIndex = inIndex;
2020 }
2021 else
2022 {
2023 outIndex = ((inIndex + STP_PSM_DBG_SIZE) - dumpSize) % STP_PSM_DBG_SIZE;
2024 }
2025
2026 STP_PSM_INFO_FUNC("loged record size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex);
2027 while(dumpSize > 0){
2028
2029 printk("STP-PSM:%d.%ds, n(%d)pre_flag(%d)cur_flag(%d)line_no(%d) pid(%d)\n", \
2030 p_opid_dbg->queue[outIndex].sec,
2031 p_opid_dbg->queue[outIndex].usec,
2032 p_opid_dbg->queue[outIndex].package_no,
2033 p_opid_dbg->queue[outIndex].prev_flag,
2034 p_opid_dbg->queue[outIndex].cur_flag,
2035 p_opid_dbg->queue[outIndex].line_num,
2036 p_opid_dbg->queue[outIndex].pid
2037 );
2038
2039
2040 outIndex = (outIndex >= (STP_PSM_DBG_SIZE - 1))?(0):(outIndex + 1);
2041 dumpSize--;
2042
2043 }
2044
2045
2046 osal_unlock_unsleepable_lock(&p_opid_dbg->lock);
2047
2048 return 0;
2049
2050}
2051
2052MTKSTP_PSM_T *stp_psm_init(void)
2053{
2054 INT32 err = 0;
2055 INT32 i = 0;
2056 INT32 ret = -1;
2057
2058 STP_PSM_INFO_FUNC("psm init\n");
2059
2060 stp_psm->work_state = ACT;
2061 stp_psm->wmt_notify = wmt_lib_ps_stp_cb;
2062 stp_psm->is_wmt_quick_ps_support = wmt_lib_is_quick_ps_support;
2063 stp_psm->idle_time_to_sleep = STP_PSM_IDLE_TIME_SLEEP;
2064 stp_psm->flag.data = 0;
2065 stp_psm->stp_tx_cb = NULL;
2066 stp_psm_set_sleep_enable(stp_psm);
2067
2068 ret = osal_fifo_init(&stp_psm->hold_fifo, NULL, STP_PSM_FIFO_SIZE);
2069 if(ret < 0)
2070 {
2071 STP_PSM_ERR_FUNC("FIFO INIT FAILS\n");
2072 goto ERR_EXIT4;
2073 }
2074
2075 osal_fifo_reset(&stp_psm->hold_fifo);
2076 osal_sleepable_lock_init(&stp_psm->hold_fifo_spinlock_global);
2077 osal_unsleepable_lock_init(&stp_psm->wq_spinlock);
2078 osal_sleepable_lock_init(&stp_psm->stp_psm_lock);
2079
2080// osal_unsleepable_lock_init(&stp_psm->flagSpinlock);
2081
2082 osal_memcpy(stp_psm->wake_lock.name, "MT662x", 6);
2083 osal_wake_lock_init(&stp_psm->wake_lock);
2084
2085 osal_event_init(&stp_psm->STPd_event);
2086 RB_INIT(&stp_psm->rFreeOpQ, STP_OP_BUF_SIZE);
2087 RB_INIT(&stp_psm->rActiveOpQ, STP_OP_BUF_SIZE);
2088 /* Put all to free Q */
2089 for (i = 0; i < STP_OP_BUF_SIZE; i++)
2090 {
2091 osal_signal_init(&(stp_psm->arQue[i].signal));
2092 _stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, &(stp_psm->arQue[i]));
2093 }
2094 //stp_psm->current_active_op = NULL;
2095 stp_psm->last_active_opId = STP_OPID_PSM_INALID;
2096 /*Generate BTM thread, to servie STP-CORE and WMT-CORE for sleeping, waking up and host awake*/
2097 stp_psm->PSMd.pThreadData = (VOID *)stp_psm;
2098 stp_psm->PSMd.pThreadFunc = (VOID *)_stp_psm_proc;
2099 osal_memcpy(stp_psm->PSMd.threadName, PSM_THREAD_NAME, osal_strlen(PSM_THREAD_NAME));
2100
2101 ret = osal_thread_create(&stp_psm->PSMd);
2102 if (ret < 0)
2103 {
2104 STP_PSM_ERR_FUNC("osal_thread_create fail...\n");
2105 goto ERR_EXIT5;
2106 }
2107
2108 //init_waitqueue_head(&stp_psm->wait_wmt_q);
2109 stp_psm->wait_wmt_q.timeoutValue = STP_PSM_WAIT_EVENT_TIMEOUT;
2110 osal_event_init(&stp_psm->wait_wmt_q);
2111
2112 err = _stp_psm_init_monitor(stp_psm);
2113 if(err)
2114 {
2115 STP_PSM_ERR_FUNC("__stp_psm_init ERROR\n");
2116 goto ERR_EXIT6;
2117 }
2118
2119 //Start STPd thread
2120 ret = osal_thread_run(&stp_psm->PSMd);
2121 if(ret < 0)
2122 {
2123 STP_PSM_ERR_FUNC("osal_thread_run FAILS\n");
2124 goto ERR_EXIT6;
2125 }
2126
2127 //psm disable in default
2128 _stp_psm_disable(stp_psm);
2129
2130 g_stp_psm_dbg = (STP_PSM_RECORD_T *)osal_malloc(osal_sizeof(STP_PSM_RECORD_T));
2131 if(!g_stp_psm_dbg){
2132 STP_PSM_ERR_FUNC("stp psm dbg allocate memory fail!\n");
2133 return NULL;
2134 }
2135 osal_memset(g_stp_psm_dbg,0,osal_sizeof(STP_PSM_RECORD_T));
2136 osal_unsleepable_lock_init(&g_stp_psm_dbg->lock);
2137
2138 g_stp_psm_opid_dbg = (STP_PSM_OPID_RECORD *)osal_malloc(osal_sizeof(STP_PSM_OPID_RECORD));
2139 if(!g_stp_psm_opid_dbg){
2140 STP_PSM_ERR_FUNC("stp psm dbg allocate memory fail!\n");
2141 return NULL;
2142 }
2143 osal_memset(g_stp_psm_opid_dbg,0,osal_sizeof(STP_PSM_OPID_RECORD));
2144 osal_unsleepable_lock_init(&g_stp_psm_opid_dbg->lock);
2145
2146
2147 return stp_psm;
2148
2149ERR_EXIT6:
2150
2151 ret = osal_thread_destroy(&stp_psm->PSMd);
2152 if(ret < 0)
2153 {
2154 STP_PSM_ERR_FUNC("osal_thread_destroy FAILS\n");
2155 goto ERR_EXIT5;
2156 }
2157ERR_EXIT5:
2158 osal_fifo_deinit(&stp_psm->hold_fifo);
2159ERR_EXIT4:
2160
2161 return NULL;
2162}
2163
2164INT32 stp_psm_deinit(MTKSTP_PSM_T *stp_psm)
2165{
2166 INT32 ret = -1;
2167
2168 STP_PSM_INFO_FUNC("psm deinit\n");
2169
2170 if(g_stp_psm_dbg)
2171 {
2172 osal_unsleepable_lock_deinit(&g_stp_psm_dbg->lock);
2173 osal_free(g_stp_psm_dbg);
2174 g_stp_psm_dbg = NULL;
2175 }
2176
2177 if(!stp_psm)
2178 {
2179 return STP_PSM_OPERATION_FAIL;
2180 }
2181
2182 ret = osal_thread_destroy(&stp_psm->PSMd);
2183 if(ret < 0)
2184 {
2185 STP_PSM_ERR_FUNC("osal_thread_destroy FAILS\n");
2186 }
2187
2188 ret = _stp_psm_deinit_monitor(stp_psm);
2189 if(ret < 0)
2190 {
2191 STP_PSM_ERR_FUNC("_stp_psm_deinit_monitor ERROR\n");
2192 }
2193
2194 osal_fifo_deinit(&stp_psm->hold_fifo);
2195 osal_sleepable_lock_deinit(&stp_psm->hold_fifo_spinlock_global);
2196 osal_unsleepable_lock_deinit(&stp_psm->wq_spinlock);
2197 osal_sleepable_lock_deinit(&stp_psm->stp_psm_lock);
2198// osal_unsleepable_lock_deinit(&stp_psm->flagSpinlock);
2199
2200 return STP_PSM_OPERATION_SUCCESS;
2201}
2202