adsp_sleepmon.c 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. /*
  7. * This driver exposes API for aDSP service layers to intimate session
  8. * start and stop. Based on the aDSP sessions and activity information
  9. * derived from SMEM statistics, the driver detects and acts on
  10. * possible aDSP sleep (voting related) issues.
  11. */
  12. #define pr_fmt(fmt) "adsp_sleepmon: " fmt
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/completion.h>
  16. #include <linux/string.h>
  17. #include <linux/err.h>
  18. #include <linux/limits.h>
  19. #include <linux/types.h>
  20. #include <linux/platform_device.h>
  21. #include <linux/cdev.h>
  22. #include <linux/device.h>
  23. #include <linux/of.h>
  24. #include <linux/of_device.h>
  25. #include <linux/of_platform.h>
  26. #include <linux/kthread.h>
  27. #include <linux/workqueue.h>
  28. #include <linux/delay.h>
  29. #include <linux/list.h>
  30. #include <linux/time.h>
  31. #include <linux/spinlock.h>
  32. #include <linux/rpmsg.h>
  33. #include <linux/debugfs.h>
  34. #include <linux/soc/qcom/smem.h>
  35. #include <linux/soc/qcom/adsp_sleepmon_stats.h>
  36. #include <asm/arch_timer.h>
  37. #include <linux/jiffies.h>
  38. #include <linux/suspend.h>
  39. #include <../../remoteproc/qcom_common.h>
  40. #include <uapi/misc/adsp_sleepmon.h>
  41. #if IS_ENABLED(CONFIG_SEC_SENSORS_SSC) && !IS_ENABLED(CONFIG_SEC_FACTORY)
  42. #include <linux/time.h>
  43. #include <linux/ktime.h>
  44. #include <linux/time64.h>
  45. #endif
  46. #if IS_ENABLED(CONFIG_SND_SOC_SAMSUNG_AUDIO)
  47. #include <sound/samsung/snd_debug_proc.h>
  48. #endif
  49. #define ADSPSLEEPMON_SMEM_ADSP_PID 2
  50. #define ADSPSLEEPMON_SLEEPSTATS_ADSP_SMEM_ID 606
  51. #define ADSPSLEEPMON_SLEEPSTATS_ADSP_LPI_SMEM_ID 613
  52. #define ADSPSLEEPMON_DSPPMSTATS_SMEM_ID 624
  53. #define ADSPSLEEPMON_DSPPMSTATS_NUMPD 5
  54. #define ADSPSLEEPMON_DSPPMSTATS_PID_FILTER 0x7F
  55. #define ADSPSLEEPMON_DSPPMSTATS_AUDIO_PID 2
  56. #define ADSPSLEEPMON_SYSMONSTATS_SMEM_ID 634
  57. #define ADSPSLEEPMON_SYSMONSTATS_EVENTS_FEATURE_ID 2
  58. #define ADSPSLEEPMON_SYS_CLK_TICKS_PER_SEC 19200000
  59. #define ADSPSLEEPMON_SYS_CLK_TICKS_PER_MILLISEC 19200
  60. #define ADSPSLEEPMON_LPI_WAIT_TIME 15
  61. #define ADSPSLEEPMON_LPM_WAIT_TIME 5
  62. #define ADSPSLEEPMON_LPM_WAIT_TIME_OVERALL 60
  63. #define ADSPSLEEPMON_MIN_REQUIRED_RESUMES 5
  64. #define QDSPPM_CLIENT_NAME_SIZE_SLEEPMON 24
  65. #define QDSPPM_NUM_OF_CLIENTS_SLEEPMON 16
  66. #define SLEEPMON_ADSP_FEATURE_INFO 1
  67. #define SLEEPMON_DSPPM_FEATURE_INFO 2
  68. #define SLEEPMON_LPI_ISSUE_FEATURE_INFO 3
  69. #define SLEEPMON_SEND_SSR_COMMAND 4
  70. #define SLEEPMON_RECEIVE_PANIC_COMMAND 5
  71. #define SLEEPMON_RECEIVE_USLEEP_CLIENTS 6
  72. #define SLEEPMON_ADSP_GLINK_VERSION 0x2
  73. #define SLEEPMON_PROCESS_NAME_SIZE 20
  74. #define ADSPSLEEPMON_AUDIO_CLIENT 1
  75. #define ADSPSLEEPMON_DEVICE_NAME_LOCAL "msm_adsp_sleepmon"
  76. #define WAIT_FOR_DSPPM_CLIENTDATA_TIMEOUT msecs_to_jiffies(100)
  77. struct sleep_stats {
  78. u32 stat_type;
  79. u32 count;
  80. u64 last_entered_at;
  81. u64 last_exited_at;
  82. u64 accumulated;
  83. };
  84. struct pd_clients {
  85. int pid;
  86. u32 num_active;
  87. };
  88. struct dsppm_stats {
  89. u32 version;
  90. u32 latency_us;
  91. u32 timestamp;
  92. struct pd_clients pd[ADSPSLEEPMON_DSPPMSTATS_NUMPD];
  93. };
  94. struct sysmon_event_stats {
  95. u32 core_clk;
  96. u32 ab_vote_lsb;
  97. u32 ab_vote_msb;
  98. u32 ib_vote_lsb;
  99. u32 ib_vote_msb;
  100. u32 sleep_latency;
  101. u32 timestamp_lsb;
  102. u32 timestamp_msb;
  103. };
  104. struct adspsleepmon_file {
  105. struct hlist_node hn;
  106. spinlock_t hlock;
  107. u32 b_connected;
  108. u32 num_sessions;
  109. u32 num_lpi_sessions;
  110. };
  111. struct adspsleepmon_audio {
  112. u32 num_sessions;
  113. u32 num_lpi_sessions;
  114. };
  115. struct sleepmon_mmpmmipsreqtype {
  116. u32 total;
  117. u32 per_thread;
  118. };
  119. struct sleepmon_mmpmbusbwdatausagetype {
  120. u64 bytes_persec;
  121. u32 usage_percentage;
  122. };
  123. struct sleepmon_mmpmmppsreqtype {
  124. u32 total;
  125. u32 floor_clock;
  126. };
  127. enum islandparticipationoptionstype {
  128. MMPM_ISLAND_PARTICIPATION_NONE = 0x0,
  129. MMPM_ISLAND_PARTICIPATION_LPI = 0x1,
  130. MMPM_ISLAND_PARTICIPATION_DISALLOW_LPI = 0x2,
  131. MMPM_ISLAND_PARTICIPATION_UIMAGE = 0x4,
  132. MMPM_ISLAND_PARTICIPATION_DISALLOW_UIMAGE = 0x8,
  133. };
  134. enum dsppm_client_data_fetch_status {
  135. DSPPM_CLIENT_DATA_FETCH_SUCCESS = 0x1,
  136. DSPPM_CLIENT_DATA_FAILED_ONGOING_COHERENT = 0x2,
  137. DSPPM_CLIENT_DATA_FAILED_DSPPM_RETURNED_NULL = 0x3,
  138. };
  139. struct islandparticipationtype {
  140. u32 islandopt; //islandparticipationoptionstype
  141. };
  142. struct sleepmon_qdsppmrequest {
  143. char clientname[QDSPPM_CLIENT_NAME_SIZE_SLEEPMON];
  144. u32 clientid;
  145. u64 timestamp;
  146. u8 b_valid;
  147. u32 poweron;
  148. struct sleepmon_mmpmmipsreqtype mips;
  149. struct sleepmon_mmpmmppsreqtype mpps;
  150. struct sleepmon_mmpmbusbwdatausagetype bw;
  151. u32 sleeplatency;
  152. char process[SLEEPMON_PROCESS_NAME_SIZE];
  153. struct islandparticipationtype islandparticipation;
  154. u32 reserved_1;
  155. u32 reserved_2;
  156. u32 reserved_3;
  157. u32 reserved_4;
  158. u32 reserved_5;
  159. u32 reserved_6;
  160. };
  161. struct sleepmon_mmpmaggregatedmipsdata {
  162. u32 mips;
  163. u32 mpps;
  164. u32 clock;
  165. u32 kfactor;
  166. };
  167. struct sleepmon_mmpmaggregatedbwtype {
  168. u64 adsp_ddr_ab;
  169. u64 adsp_ddr_ib;
  170. u64 snoc_ddr_ab;
  171. u64 snoc_ddr_ib;
  172. u32 ddr_latency;
  173. u32 snoc_latency;
  174. };
  175. struct sleepmon_mmpmaggregatedahbtype {
  176. u32 ahbe_hz;
  177. u32 ahbi_hz;
  178. };
  179. struct sleepmon_qdsppm_aggdata {
  180. struct sleepmon_mmpmaggregatedmipsdata agg_mips;
  181. struct sleepmon_mmpmaggregatedbwtype agg_bw;
  182. struct sleepmon_mmpmaggregatedahbtype agg_ahb;
  183. u32 agg_latency;
  184. u32 reserved_3;
  185. u32 reserved_4;
  186. u32 reserved_5;
  187. u32 reserved_6;
  188. u32 reserved_7;
  189. u32 reserved_8;
  190. };
  191. struct sleepmon_qdsppm_clients {
  192. u8 update_flag;
  193. u64 timestamp;
  194. struct sleepmon_qdsppmrequest clients[QDSPPM_NUM_OF_CLIENTS_SLEEPMON];
  195. struct sleepmon_qdsppm_aggdata agg_data;
  196. u8 result;
  197. u32 num_clients;
  198. u32 sysmon_qdsppm_version;
  199. u32 reserved_1;
  200. u32 reserved_2;
  201. u32 reserved_3;
  202. u32 reserved_4;
  203. u32 reserved_5;
  204. u32 reserved_6;
  205. u32 reserved_7;
  206. u32 reserved_8;
  207. };
  208. struct sleepmon_usleep_npa_clients {
  209. char clientname[67];
  210. u32 request;
  211. };
  212. struct sleepmon_rx_msg_t {
  213. u32 size;
  214. u32 ver_info;
  215. u32 feature_id;
  216. union {
  217. struct sleepmon_qdsppm_clients dsppm_clients;
  218. int lpi_panic;
  219. struct sleepmon_usleep_npa_clients sleepmon_usleep_npa;
  220. } featureStruct;
  221. };
  222. struct sleepmon_lpi_issue {
  223. u8 lpi_issue_detect;
  224. u8 panic_enable;
  225. u8 ssr_enable;
  226. };
  227. struct sleepmon_tx_msg_t {
  228. u32 size;
  229. u32 adsp_ver_info;
  230. u32 feature_id;
  231. union {
  232. u32 dsppm_client_signal;
  233. struct sleepmon_lpi_issue sleepmon_lpi_detect;
  234. u32 send_ssr_command;
  235. } fs;
  236. };
  237. struct sleepmon_request {
  238. struct list_head node;
  239. struct sleepmon_rx_msg_t msg;
  240. bool busy;
  241. };
  242. #if IS_ENABLED(CONFIG_SEC_SENSORS_SSC) && !IS_ENABLED(CONFIG_SEC_FACTORY)
  243. struct sleepmon_ap_sleep_check {
  244. struct timespec64 suspend_ts;
  245. struct timespec64 resume_ts;
  246. u32 no_sleep_count;
  247. u32 frequent_wakeup_count;
  248. };
  249. #endif
  250. struct adspsleepmon {
  251. bool b_enable;
  252. bool timer_event;
  253. bool timer_pending;
  254. bool suspend_event;
  255. bool smem_init_done;
  256. bool suspend_init_done;
  257. bool b_panic_lpm;
  258. bool b_panic_lpi;
  259. bool b_config_panic_lpm;
  260. bool b_config_panic_lpi;
  261. bool b_config_adsp_panic_lpm;
  262. bool b_config_adsp_panic_lpi;
  263. bool b_config_adsp_panic_lpm_overall;
  264. bool b_config_adsp_ssr_enable;
  265. bool b_rpmsg_register;
  266. #if IS_ENABLED(CONFIG_SEC_SENSORS_SSC) && !IS_ENABLED(CONFIG_SEC_FACTORY)
  267. bool b_config_enable_adsp_sleep_checker_ss;
  268. u32 adsp_crash_ssr;
  269. #endif
  270. u32 lpm_wait_time;
  271. u32 lpi_wait_time;
  272. u32 lpm_wait_time_overall;
  273. u32 min_required_resumes;
  274. u32 accumulated_resumes;
  275. u64 accumulated_duration;
  276. struct completion sem;
  277. u32 adsp_version;
  278. struct rpmsg_device *rpmsgdev;
  279. struct mutex lock;
  280. struct cdev cdev;
  281. struct class *class;
  282. dev_t devno;
  283. struct device *dev;
  284. struct task_struct *worker_task;
  285. struct adspsleepmon_audio audio_stats;
  286. struct hlist_head audio_clients;
  287. struct sleep_stats backup_lpm_stats;
  288. unsigned long long backup_lpm_timestamp;
  289. struct sleep_stats backup_lpi_stats;
  290. unsigned long long backup_lpi_timestamp;
  291. struct sleep_stats *lpm_stats;
  292. struct sleep_stats *lpi_stats;
  293. struct dsppm_stats *dsppm_stats;
  294. struct sysmon_event_stats *sysmon_event_stats;
  295. struct sleepmon_qdsppm_clients dsppm_clients;
  296. struct dentry *debugfs_dir;
  297. struct dentry *debugfs_panic_file;
  298. struct dentry *debugfs_master_stats;
  299. struct dentry *debugfs_read_panic_state;
  300. struct dentry *debugfs_adsp_panic_file;
  301. struct dentry *debugfs_read_adsp_panic_state;
  302. phandle adsp_rproc_phandle;
  303. struct rproc *adsp_rproc;
  304. #if IS_ENABLED(CONFIG_SEC_SENSORS_SSC) && !IS_ENABLED(CONFIG_SEC_FACTORY)
  305. struct sleepmon_ap_sleep_check ap_sleep_checker;
  306. struct sleep_stats suspend_prepare_stats;
  307. #endif
  308. };
  309. static struct adspsleepmon g_adspsleepmon;
  310. static void adspsleepmon_timer_cb(struct timer_list *unused);
  311. static DEFINE_TIMER(adspsleep_timer, adspsleepmon_timer_cb);
  312. static DECLARE_WAIT_QUEUE_HEAD(adspsleepmon_wq);
  313. static int sleepmon_get_dsppm_client_stats(void)
  314. {
  315. int result = -EINVAL;
  316. struct sleepmon_tx_msg_t rpmsg;
  317. if (g_adspsleepmon.rpmsgdev && g_adspsleepmon.adsp_version > 0) {
  318. rpmsg.adsp_ver_info = SLEEPMON_ADSP_GLINK_VERSION;
  319. rpmsg.feature_id = SLEEPMON_DSPPM_FEATURE_INFO;
  320. rpmsg.fs.dsppm_client_signal = true;
  321. rpmsg.size = sizeof(rpmsg);
  322. result = rpmsg_send(g_adspsleepmon.rpmsgdev->ept,
  323. &rpmsg,
  324. sizeof(rpmsg));
  325. if (result)
  326. pr_err("DSPPM client signal send failed :%u\n", result);
  327. }
  328. return result;
  329. }
  330. static int sleepmon_send_ssr_command(void)
  331. {
  332. int result = -EINVAL;
  333. struct sleepmon_tx_msg_t rpmsg;
  334. if (g_adspsleepmon.rpmsgdev && g_adspsleepmon.adsp_version > 1) {
  335. if (g_adspsleepmon.b_config_adsp_ssr_enable) {
  336. if (g_adspsleepmon.adsp_rproc) {
  337. pr_info("Setting recovery flag for ADSP SSR\n");
  338. qcom_rproc_update_recovery_status(g_adspsleepmon.adsp_rproc, true);
  339. } else {
  340. pr_info("Couldn't find rproc handle for ADSP\n");
  341. }
  342. }
  343. rpmsg.adsp_ver_info = SLEEPMON_ADSP_GLINK_VERSION;
  344. rpmsg.feature_id = SLEEPMON_SEND_SSR_COMMAND;
  345. rpmsg.fs.send_ssr_command = 1;
  346. rpmsg.size = sizeof(rpmsg);
  347. result = rpmsg_send(g_adspsleepmon.rpmsgdev->ept,
  348. &rpmsg,
  349. sizeof(rpmsg));
  350. if (result) {
  351. pr_err("Send SSR command failed\n");
  352. if (g_adspsleepmon.b_config_adsp_ssr_enable) {
  353. if (g_adspsleepmon.adsp_rproc) {
  354. pr_info("Resetting recovery flag for ADSP SSR\n");
  355. qcom_rproc_update_recovery_status(
  356. g_adspsleepmon.adsp_rproc, false);
  357. }
  358. }
  359. }
  360. } else {
  361. pr_err("ADSP version doesn't support panic\n");
  362. }
  363. return result;
  364. }
  365. static int sleepmon_send_lpi_issue_command(void)
  366. {
  367. int result = -EINVAL;
  368. struct sleepmon_tx_msg_t rpmsg;
  369. if (g_adspsleepmon.rpmsgdev && g_adspsleepmon.adsp_version > 1) {
  370. rpmsg.adsp_ver_info = SLEEPMON_ADSP_GLINK_VERSION;
  371. rpmsg.feature_id = SLEEPMON_LPI_ISSUE_FEATURE_INFO;
  372. rpmsg.fs.sleepmon_lpi_detect.lpi_issue_detect = 1;
  373. if (g_adspsleepmon.b_panic_lpi ||
  374. g_adspsleepmon.b_config_adsp_panic_lpi)
  375. rpmsg.fs.sleepmon_lpi_detect.panic_enable = 1;
  376. else
  377. rpmsg.fs.sleepmon_lpi_detect.panic_enable = 0;
  378. rpmsg.fs.sleepmon_lpi_detect.ssr_enable = 0;
  379. rpmsg.size = sizeof(rpmsg);
  380. result = rpmsg_send(g_adspsleepmon.rpmsgdev->ept,
  381. &rpmsg,
  382. sizeof(rpmsg));
  383. if (result)
  384. pr_err("Send LPI issue command failed\n");
  385. } else {
  386. pr_err("Send LPI issue command failed, ADSP version unsupported\n");
  387. }
  388. return result;
  389. }
  390. static int adspsleepmon_suspend_notify(struct notifier_block *nb,
  391. unsigned long mode, void *_unused)
  392. {
  393. switch (mode) {
  394. case PM_POST_SUSPEND:
  395. {
  396. /*
  397. * Resume notification (previously in suspend)
  398. * TODO
  399. * Not acquiring mutex here, see if it is needed!
  400. */
  401. pr_info("PM_POST_SUSPEND\n");
  402. #if IS_ENABLED(CONFIG_SEC_SENSORS_SSC) && !IS_ENABLED(CONFIG_SEC_FACTORY)
  403. g_adspsleepmon.ap_sleep_checker.resume_ts =
  404. ktime_to_timespec64(ktime_get_boottime());
  405. #endif
  406. if (!g_adspsleepmon.audio_stats.num_sessions ||
  407. (g_adspsleepmon.audio_stats.num_sessions ==
  408. g_adspsleepmon.audio_stats.num_lpi_sessions)) {
  409. g_adspsleepmon.suspend_event = true;
  410. wake_up_interruptible(&adspsleepmon_wq);
  411. }
  412. break;
  413. }
  414. #if IS_ENABLED(CONFIG_SEC_SENSORS_SSC) && !IS_ENABLED(CONFIG_SEC_FACTORY)
  415. case PM_SUSPEND_PREPARE:
  416. {
  417. memcpy(&g_adspsleepmon.suspend_prepare_stats,
  418. g_adspsleepmon.lpm_stats,
  419. sizeof(struct sleep_stats));
  420. g_adspsleepmon.ap_sleep_checker.suspend_ts =
  421. ktime_to_timespec64(ktime_get_boottime());
  422. break;
  423. }
  424. #endif
  425. default:
  426. /*
  427. * Not handling other PM states, just return
  428. */
  429. break;
  430. }
  431. return 0;
  432. }
  433. static struct notifier_block adsp_sleepmon_pm_nb = {
  434. .notifier_call = adspsleepmon_suspend_notify,
  435. };
  436. static void update_sysmon_event_stats_ptr(void *stats, size_t size)
  437. {
  438. u32 feature_size, feature_id, version;
  439. g_adspsleepmon.sysmon_event_stats = NULL;
  440. feature_id = *(u32 *)stats;
  441. version = feature_id & 0xFFFF;
  442. feature_size = (feature_id >> 16) & 0xFFF;
  443. feature_id = feature_id >> 28;
  444. while (size >= feature_size) {
  445. switch (feature_id) {
  446. case ADSPSLEEPMON_SYSMONSTATS_EVENTS_FEATURE_ID:
  447. g_adspsleepmon.sysmon_event_stats =
  448. (struct sysmon_event_stats *)(stats + sizeof(u32));
  449. size = 0;
  450. break;
  451. default:
  452. /*
  453. * Unrecognized, feature, jump through to the next
  454. */
  455. stats = stats + feature_size;
  456. if (size >= feature_size)
  457. size = size - feature_size;
  458. feature_id = *(u32 *)stats;
  459. feature_size = (feature_id >> 16) & 0xFFF;
  460. feature_id = feature_id >> 28;
  461. version = feature_id & 0xFFFF;
  462. break;
  463. }
  464. }
  465. }
  466. static int adspsleepmon_smem_init(void)
  467. {
  468. size_t size;
  469. void *stats = NULL;
  470. g_adspsleepmon.lpm_stats = qcom_smem_get(
  471. ADSPSLEEPMON_SMEM_ADSP_PID,
  472. ADSPSLEEPMON_SLEEPSTATS_ADSP_SMEM_ID,
  473. &size);
  474. if (IS_ERR_OR_NULL(g_adspsleepmon.lpm_stats) ||
  475. (sizeof(struct sleep_stats) > size)) {
  476. pr_err("Failed to get sleep stats from SMEM for ADSP: %d, size: %d\n",
  477. PTR_ERR(g_adspsleepmon.lpm_stats), size);
  478. return -ENOMEM;
  479. }
  480. g_adspsleepmon.lpi_stats = qcom_smem_get(
  481. ADSPSLEEPMON_SMEM_ADSP_PID,
  482. ADSPSLEEPMON_SLEEPSTATS_ADSP_LPI_SMEM_ID,
  483. &size);
  484. if (IS_ERR_OR_NULL(g_adspsleepmon.lpi_stats) ||
  485. (sizeof(struct sleep_stats) > size)) {
  486. pr_err("Failed to get LPI sleep stats from SMEM for ADSP: %d, size: %d\n",
  487. PTR_ERR(g_adspsleepmon.lpi_stats), size);
  488. return -ENOMEM;
  489. }
  490. g_adspsleepmon.dsppm_stats = qcom_smem_get(
  491. ADSPSLEEPMON_SMEM_ADSP_PID,
  492. ADSPSLEEPMON_DSPPMSTATS_SMEM_ID,
  493. &size);
  494. if (IS_ERR_OR_NULL(g_adspsleepmon.dsppm_stats) ||
  495. (sizeof(struct dsppm_stats) > size)) {
  496. pr_err("Failed to get DSPPM stats from SMEM for ADSP: %d, size: %d\n",
  497. PTR_ERR(g_adspsleepmon.dsppm_stats), size);
  498. return -ENOMEM;
  499. }
  500. stats = qcom_smem_get(ADSPSLEEPMON_SMEM_ADSP_PID,
  501. ADSPSLEEPMON_SYSMONSTATS_SMEM_ID,
  502. &size);
  503. if (IS_ERR_OR_NULL(stats) || !size) {
  504. pr_err("Failed to get SysMon stats from SMEM for ADSP: %d, size: %d\n",
  505. PTR_ERR(stats), size);
  506. return -ENOMEM;
  507. }
  508. update_sysmon_event_stats_ptr(stats, size);
  509. if (IS_ERR_OR_NULL(g_adspsleepmon.sysmon_event_stats)) {
  510. pr_err("Failed to get SysMon event stats from SMEM for ADSP\n");
  511. return -ENOMEM;
  512. }
  513. /*
  514. * Register for Resume notifications
  515. */
  516. if (!g_adspsleepmon.suspend_init_done) {
  517. register_pm_notifier(&adsp_sleepmon_pm_nb);
  518. g_adspsleepmon.suspend_init_done = true;
  519. }
  520. g_adspsleepmon.smem_init_done = true;
  521. return 0;
  522. }
  523. static int sleepmon_rpmsg_callback(struct rpmsg_device *dev, void *data,
  524. int len, void *priv, u32 addr)
  525. {
  526. struct sleepmon_rx_msg_t *msg = (struct sleepmon_rx_msg_t *)data;
  527. if (!data || (len < sizeof(*msg))) {
  528. dev_err(&dev->dev,
  529. "Invalid message in rpmsg callback, length: %d, expected: %lu\n",
  530. len, sizeof(*msg));
  531. return -EINVAL;
  532. }
  533. if (msg->feature_id == SLEEPMON_ADSP_FEATURE_INFO) {
  534. g_adspsleepmon.adsp_version = msg->ver_info;
  535. pr_info("Received ADSP version 0x%x\n",
  536. g_adspsleepmon.adsp_version);
  537. /*
  538. * ADSP is booting up, time to initialize
  539. * number of sessions params and delete
  540. * any pending timer. Also backup LPM
  541. * stats.
  542. */
  543. if (!g_adspsleepmon.smem_init_done)
  544. return 0;
  545. g_adspsleepmon.audio_stats.num_sessions = 0;
  546. g_adspsleepmon.audio_stats.num_lpi_sessions = 0;
  547. del_timer(&adspsleep_timer);
  548. g_adspsleepmon.timer_pending = false;
  549. g_adspsleepmon.accumulated_duration = 0;
  550. g_adspsleepmon.accumulated_resumes = 0;
  551. memcpy(&g_adspsleepmon.backup_lpm_stats,
  552. g_adspsleepmon.lpm_stats,
  553. sizeof(struct sleep_stats));
  554. g_adspsleepmon.backup_lpm_timestamp = __arch_counter_get_cntvct();
  555. }
  556. if (msg->feature_id == SLEEPMON_DSPPM_FEATURE_INFO) {
  557. g_adspsleepmon.dsppm_clients.result = 0;
  558. g_adspsleepmon.dsppm_clients = msg->featureStruct.dsppm_clients;
  559. complete(&g_adspsleepmon.sem);
  560. pr_debug("Received DSPPM data version: 0x%x\n",
  561. msg->ver_info);
  562. }
  563. if (msg->feature_id == SLEEPMON_RECEIVE_PANIC_COMMAND) {
  564. if (g_adspsleepmon.b_panic_lpi) {
  565. pr_err("ADSP LPI issue detected: Triggering panic\n");
  566. panic("ADSP_SLEEPMON: ADSP LPI issue detected");
  567. } else if (g_adspsleepmon.b_config_adsp_panic_lpi) {
  568. sleepmon_send_ssr_command();
  569. }
  570. }
  571. if (msg->feature_id == SLEEPMON_RECEIVE_USLEEP_CLIENTS) {
  572. pr_info("USleep_NPA_Client :%s, Client_request :%x\n",
  573. msg->featureStruct.sleepmon_usleep_npa.clientname,
  574. msg->featureStruct.sleepmon_usleep_npa.request);
  575. }
  576. return 0;
  577. }
  578. static int debugfs_panic_state_read(void *data, u64 *val)
  579. {
  580. *val = g_adspsleepmon.b_panic_lpm | (g_adspsleepmon.b_panic_lpi << 1);
  581. return 0;
  582. }
  583. static int debugfs_panic_state_write(void *data, u64 val)
  584. {
  585. if (!(val & 0x1))
  586. g_adspsleepmon.b_panic_lpm = false;
  587. else
  588. g_adspsleepmon.b_panic_lpm =
  589. g_adspsleepmon.b_config_panic_lpm;
  590. if (!(val & 0x2))
  591. g_adspsleepmon.b_panic_lpi = false;
  592. else
  593. g_adspsleepmon.b_panic_lpi =
  594. g_adspsleepmon.b_config_panic_lpi;
  595. return 0;
  596. }
  597. DEFINE_DEBUGFS_ATTRIBUTE(panic_state_fops,
  598. debugfs_panic_state_read,
  599. debugfs_panic_state_write,
  600. "%u\n");
  601. static int read_panic_state_show(struct seq_file *s, void *d)
  602. {
  603. int val = g_adspsleepmon.b_panic_lpm | (g_adspsleepmon.b_panic_lpi << 1);
  604. if (val == 0)
  605. seq_puts(s, "\nPanic State: LPM and LPI panics Disabled\n");
  606. if (val == 1)
  607. seq_puts(s, "\nPanic State: LPM Panic enabled\n");
  608. if (val == 2)
  609. seq_puts(s, "\nPanic State: LPI Panic enabled\n");
  610. if (val == 3)
  611. seq_puts(s, "\nPanic State: LPI and LPM Panics enabled\n");
  612. return 0;
  613. }
  614. DEFINE_SHOW_ATTRIBUTE(read_panic_state);
  615. static int debugfs_adsp_panic_state_read(void *data, u64 *val)
  616. {
  617. *val = g_adspsleepmon.b_config_adsp_panic_lpm |
  618. (g_adspsleepmon.b_config_adsp_panic_lpi << 1) |
  619. (g_adspsleepmon.b_config_adsp_panic_lpm_overall << 2) |
  620. (g_adspsleepmon.b_config_adsp_ssr_enable << 3);
  621. return 0;
  622. }
  623. static int debugfs_adsp_panic_state_write(void *data, u64 val)
  624. {
  625. if (!g_adspsleepmon.rpmsgdev ||
  626. g_adspsleepmon.adsp_version <= 1) {
  627. pr_err("ADSP version doesn't support panic\n");
  628. return -EINVAL;
  629. }
  630. if (!(val & 0x1))
  631. g_adspsleepmon.b_config_adsp_panic_lpm = false;
  632. else
  633. g_adspsleepmon.b_config_adsp_panic_lpm = true;
  634. if (!(val & 0x2))
  635. g_adspsleepmon.b_config_adsp_panic_lpi = false;
  636. else
  637. g_adspsleepmon.b_config_adsp_panic_lpi = true;
  638. if (!(val & 0x4))
  639. g_adspsleepmon.b_config_adsp_panic_lpm_overall = false;
  640. else
  641. g_adspsleepmon.b_config_adsp_panic_lpm_overall = true;
  642. if (!(val & 0x8))
  643. g_adspsleepmon.b_config_adsp_ssr_enable = false;
  644. else {
  645. if (g_adspsleepmon.adsp_rproc) {
  646. if (g_adspsleepmon.b_config_adsp_panic_lpm ||
  647. g_adspsleepmon.b_config_adsp_panic_lpi ||
  648. g_adspsleepmon.b_config_adsp_panic_lpm_overall)
  649. g_adspsleepmon.b_config_adsp_ssr_enable = true;
  650. else {
  651. pr_err("ADSP panics are not enabled and discarded ADSP SSR enable request\n");
  652. return -EINVAL;
  653. }
  654. } else {
  655. pr_err("Couldn't find rproc handle for ADSP and discarded ADSP SSR enable request\n");
  656. return -EINVAL;
  657. }
  658. }
  659. return 0;
  660. }
  661. DEFINE_DEBUGFS_ATTRIBUTE(adsp_panic_state_fops,
  662. debugfs_adsp_panic_state_read,
  663. debugfs_adsp_panic_state_write,
  664. "%u\n");
  665. static int read_adsp_panic_state_show(struct seq_file *s, void *d)
  666. {
  667. int val = g_adspsleepmon.b_config_adsp_panic_lpm |
  668. (g_adspsleepmon.b_config_adsp_panic_lpi << 1) |
  669. (g_adspsleepmon.b_config_adsp_panic_lpm_overall << 2) |
  670. (g_adspsleepmon.b_config_adsp_ssr_enable << 3);
  671. if (!g_adspsleepmon.rpmsgdev ||
  672. g_adspsleepmon.adsp_version <= 1) {
  673. seq_puts(s, "\nADSP version doesn't support panic\n");
  674. return 0;
  675. }
  676. if (val & 1)
  677. seq_puts(s, "\nADSP panic on LPM violation enabled\n");
  678. else
  679. seq_puts(s, "\nADSP panic on LPM violation is disabled\n");
  680. if (val & 2)
  681. seq_puts(s, "\nADSP panic on LPI violation enabled\n");
  682. else
  683. seq_puts(s, "\nADSP panic on LPI violation is disabled\n");
  684. if (val & 4)
  685. seq_puts(s, "\nADSP panic for LPM overall violation enabled\n");
  686. else
  687. seq_puts(s, "\nADSP panic for LPM overall violation is disabled\n");
  688. if (val & 8)
  689. seq_puts(s, "\nADSP SSR config enabled\n");
  690. else
  691. seq_puts(s, "\nADSP SSR config disabled\n");
  692. return 0;
  693. }
  694. DEFINE_SHOW_ATTRIBUTE(read_adsp_panic_state);
  695. static void print_complete_dsppm_info(void)
  696. {
  697. int i;
  698. if (g_adspsleepmon.dsppm_clients.result ==
  699. DSPPM_CLIENT_DATA_FETCH_SUCCESS) {
  700. pr_err("TS:0x%llX,AC:%u,TMIPS:%u,TMPPS:%u,QCLK:%u,KF:%u,DDRAB:%u,DDRIB:%u,SNOCAB:%u,SNOCIB:%u,AL:%u,SL:%u,AHBE:%u,AHBI:%u,ASL:%u\n",
  701. g_adspsleepmon.dsppm_clients.timestamp, g_adspsleepmon.dsppm_clients.num_clients,
  702. g_adspsleepmon.dsppm_clients.agg_data.agg_mips.mips,
  703. g_adspsleepmon.dsppm_clients.agg_data.agg_mips.mpps,
  704. g_adspsleepmon.dsppm_clients.agg_data.agg_mips.clock,
  705. g_adspsleepmon.dsppm_clients.agg_data.agg_mips.kfactor,
  706. g_adspsleepmon.dsppm_clients.agg_data.agg_bw.adsp_ddr_ab,
  707. g_adspsleepmon.dsppm_clients.agg_data.agg_bw.adsp_ddr_ib,
  708. g_adspsleepmon.dsppm_clients.agg_data.agg_bw.snoc_ddr_ab,
  709. g_adspsleepmon.dsppm_clients.agg_data.agg_bw.snoc_ddr_ib,
  710. g_adspsleepmon.dsppm_clients.agg_data.agg_bw.ddr_latency,
  711. g_adspsleepmon.dsppm_clients.agg_data.agg_bw.snoc_latency,
  712. g_adspsleepmon.dsppm_clients.agg_data.agg_ahb.ahbe_hz,
  713. g_adspsleepmon.dsppm_clients.agg_data.agg_ahb.ahbi_hz,
  714. g_adspsleepmon.dsppm_clients.agg_data.agg_latency);
  715. for (i = 0; i < g_adspsleepmon.dsppm_clients.num_clients; i++) {
  716. pr_err("%u:N:%s,ID:%u,RTS:%u,TMIPS:%u,MIPSPT:%u,TMPPS:%u,ADSPFCLK:%u,BPS:%u,UP:%u,SL:%u,POW:%u,PD:%s,ISP:%u\n",
  717. i, g_adspsleepmon.dsppm_clients.clients[i].clientname,
  718. g_adspsleepmon.dsppm_clients.clients[i].clientid,
  719. g_adspsleepmon.dsppm_clients.clients[i].timestamp,
  720. g_adspsleepmon.dsppm_clients.clients[i].mips.total,
  721. g_adspsleepmon.dsppm_clients.clients[i].mips.per_thread,
  722. g_adspsleepmon.dsppm_clients.clients[i].mpps.total,
  723. g_adspsleepmon.dsppm_clients.clients[i].mpps.floor_clock,
  724. g_adspsleepmon.dsppm_clients.clients[i].bw.bytes_persec,
  725. g_adspsleepmon.dsppm_clients.clients[i].bw.usage_percentage,
  726. g_adspsleepmon.dsppm_clients.clients[i].sleeplatency,
  727. g_adspsleepmon.dsppm_clients.clients[i].poweron,
  728. g_adspsleepmon.dsppm_clients.clients[i].process,
  729. g_adspsleepmon.dsppm_clients.clients[i].islandparticipation.islandopt);
  730. }
  731. } else if (g_adspsleepmon.dsppm_clients.result ==
  732. DSPPM_CLIENT_DATA_FAILED_ONGOING_COHERENT)
  733. pr_err("DSPPM fetch from DSP failed: Ongoing coherent DSPPM data read\n");
  734. else if (g_adspsleepmon.dsppm_clients.result ==
  735. DSPPM_CLIENT_DATA_FAILED_DSPPM_RETURNED_NULL)
  736. pr_err("DSPPM fetch from DSP failed: QDSPPM returned NULL\n");
  737. else
  738. pr_err("DSPPM fetch from DSP failed: result = %d\n",
  739. g_adspsleepmon.dsppm_clients.result);
  740. }
  741. int adsp_sleepmon_log_master_stats(u32 mask)
  742. {
  743. u64 accumulated;
  744. int result;
  745. mask = mask & 0x7;
  746. if (!mask) {
  747. pr_err("\nadsp_sleepmon_log_master_stats: Invalid Input Parameter\n");
  748. return -EINVAL;
  749. }
  750. if (mask & 0x1) {
  751. if (g_adspsleepmon.sysmon_event_stats) {
  752. pr_info("\nsysMon stats:\n\n");
  753. pr_info("Core clock(KHz): %d\n",
  754. g_adspsleepmon.sysmon_event_stats->core_clk);
  755. pr_info("Ab vote(Bytes): %llu\n",
  756. (((u64)g_adspsleepmon.sysmon_event_stats->ab_vote_msb << 32) |
  757. g_adspsleepmon.sysmon_event_stats->ab_vote_lsb));
  758. pr_info("Ib vote(Bytes): %llu\n",
  759. (((u64)g_adspsleepmon.sysmon_event_stats->ib_vote_msb << 32) |
  760. g_adspsleepmon.sysmon_event_stats->ib_vote_lsb));
  761. pr_info("Sleep latency(usec): %u\n",
  762. g_adspsleepmon.sysmon_event_stats->sleep_latency > 0 ?
  763. g_adspsleepmon.sysmon_event_stats->sleep_latency : U32_MAX);
  764. pr_info("Timestamp: %llu\n",
  765. (((u64)g_adspsleepmon.sysmon_event_stats->timestamp_msb << 32) |
  766. g_adspsleepmon.sysmon_event_stats->timestamp_lsb));
  767. } else {
  768. pr_err("Sysmon Event Stats are not available\n");
  769. }
  770. }
  771. if (mask & 0x2) {
  772. if (g_adspsleepmon.dsppm_stats) {
  773. pr_info("\nDSPPM stats:\n\n");
  774. pr_info("Version: %u\n", g_adspsleepmon.dsppm_stats->version);
  775. pr_info("Sleep latency(usec): %u\n",
  776. g_adspsleepmon.dsppm_stats->latency_us ?
  777. g_adspsleepmon.dsppm_stats->latency_us : U32_MAX);
  778. pr_info("Timestamp: %llu\n", g_adspsleepmon.dsppm_stats->timestamp);
  779. for (int i = 0; i < ADSPSLEEPMON_DSPPMSTATS_NUMPD; i++) {
  780. pr_info("Pid: %d, Num active clients: %d\n",
  781. g_adspsleepmon.dsppm_stats->pd[i].pid,
  782. g_adspsleepmon.dsppm_stats->pd[i].num_active);
  783. }
  784. if (g_adspsleepmon.adsp_version) {
  785. result = sleepmon_get_dsppm_client_stats();
  786. if (!result) {
  787. wait_for_completion(&g_adspsleepmon.sem);
  788. print_complete_dsppm_info();
  789. }
  790. }
  791. } else {
  792. pr_err("Dsppm Stats are not available\n");
  793. }
  794. }
  795. if (mask & 0x4) {
  796. if (g_adspsleepmon.lpm_stats) {
  797. accumulated = g_adspsleepmon.lpm_stats->accumulated;
  798. if (g_adspsleepmon.lpm_stats->last_entered_at >
  799. g_adspsleepmon.lpm_stats->last_exited_at)
  800. accumulated += arch_timer_read_counter() -
  801. g_adspsleepmon.lpm_stats->last_entered_at;
  802. pr_info("\nLPM stats:\n\n");
  803. pr_info("Count = %u\n", g_adspsleepmon.lpm_stats->count);
  804. pr_info("Last Entered At = %llu\n",
  805. g_adspsleepmon.lpm_stats->last_entered_at);
  806. pr_info("Last Exited At = %llu\n",
  807. g_adspsleepmon.lpm_stats->last_exited_at);
  808. pr_info("Accumulated Duration = %llu\n", accumulated);
  809. } else {
  810. pr_err("LPM Stats are not available\n");
  811. }
  812. if (g_adspsleepmon.lpi_stats) {
  813. accumulated = g_adspsleepmon.lpi_stats->accumulated;
  814. if (g_adspsleepmon.lpi_stats->last_entered_at >
  815. g_adspsleepmon.lpi_stats->last_exited_at)
  816. accumulated += arch_timer_read_counter() -
  817. g_adspsleepmon.lpi_stats->last_entered_at;
  818. pr_info("\nLPI stats:\n\n");
  819. pr_info("Count = %u\n", g_adspsleepmon.lpi_stats->count);
  820. pr_info("Last Entered At = %llu\n",
  821. g_adspsleepmon.lpi_stats->last_entered_at);
  822. pr_info("Last Exited At = %llu\n",
  823. g_adspsleepmon.lpi_stats->last_exited_at);
  824. pr_info("Accumulated Duration = %llu\n",
  825. accumulated);
  826. } else {
  827. pr_err("LPI Stats are not available\n");
  828. }
  829. }
  830. return 0;
  831. }
  832. EXPORT_SYMBOL(adsp_sleepmon_log_master_stats);
  833. static int master_stats_show(struct seq_file *s, void *d)
  834. {
  835. int i = 0;
  836. u64 accumulated;
  837. int result;
  838. if (g_adspsleepmon.adsp_version) {
  839. result = sleepmon_get_dsppm_client_stats();
  840. if (!result) {
  841. wait_for_completion(&g_adspsleepmon.sem);
  842. print_complete_dsppm_info();
  843. }
  844. }
  845. if (g_adspsleepmon.sysmon_event_stats) {
  846. seq_puts(s, "\nsysMon stats:\n\n");
  847. seq_printf(s, "Core clock(KHz): %d\n",
  848. g_adspsleepmon.sysmon_event_stats->core_clk);
  849. seq_printf(s, "Ab vote(Bytes): %llu\n",
  850. (((u64)g_adspsleepmon.sysmon_event_stats->ab_vote_msb << 32) |
  851. g_adspsleepmon.sysmon_event_stats->ab_vote_lsb));
  852. seq_printf(s, "Ib vote(Bytes): %llu\n",
  853. (((u64)g_adspsleepmon.sysmon_event_stats->ib_vote_msb << 32) |
  854. g_adspsleepmon.sysmon_event_stats->ib_vote_lsb));
  855. seq_printf(s, "Sleep latency(usec): %u\n",
  856. g_adspsleepmon.sysmon_event_stats->sleep_latency > 0 ?
  857. g_adspsleepmon.sysmon_event_stats->sleep_latency : U32_MAX);
  858. seq_printf(s, "Timestamp: %llu\n",
  859. (((u64)g_adspsleepmon.sysmon_event_stats->timestamp_msb << 32) |
  860. g_adspsleepmon.sysmon_event_stats->timestamp_lsb));
  861. }
  862. if (g_adspsleepmon.dsppm_stats) {
  863. seq_puts(s, "\nDSPPM stats:\n\n");
  864. seq_printf(s, "Version: %u\n", g_adspsleepmon.dsppm_stats->version);
  865. seq_printf(s, "Sleep latency(usec): %u\n",
  866. g_adspsleepmon.dsppm_stats->latency_us ?
  867. g_adspsleepmon.dsppm_stats->latency_us : U32_MAX);
  868. seq_printf(s, "Timestamp: %llu\n", g_adspsleepmon.dsppm_stats->timestamp);
  869. for (; i < ADSPSLEEPMON_DSPPMSTATS_NUMPD; i++) {
  870. seq_printf(s, "Pid: %d, Num active clients: %d\n",
  871. g_adspsleepmon.dsppm_stats->pd[i].pid,
  872. g_adspsleepmon.dsppm_stats->pd[i].num_active);
  873. }
  874. }
  875. if (g_adspsleepmon.lpm_stats) {
  876. accumulated = g_adspsleepmon.lpm_stats->accumulated;
  877. if (g_adspsleepmon.lpm_stats->last_entered_at >
  878. g_adspsleepmon.lpm_stats->last_exited_at)
  879. accumulated += arch_timer_read_counter() -
  880. g_adspsleepmon.lpm_stats->last_entered_at;
  881. seq_puts(s, "\nLPM stats:\n\n");
  882. seq_printf(s, "Count = %u\n", g_adspsleepmon.lpm_stats->count);
  883. seq_printf(s, "Last Entered At = %llu\n",
  884. g_adspsleepmon.lpm_stats->last_entered_at);
  885. seq_printf(s, "Last Exited At = %llu\n",
  886. g_adspsleepmon.lpm_stats->last_exited_at);
  887. seq_printf(s, "Accumulated Duration = %llu\n", accumulated);
  888. }
  889. if (g_adspsleepmon.lpi_stats) {
  890. accumulated = g_adspsleepmon.lpi_stats->accumulated;
  891. if (g_adspsleepmon.lpi_stats->last_entered_at >
  892. g_adspsleepmon.lpi_stats->last_exited_at)
  893. accumulated += arch_timer_read_counter() -
  894. g_adspsleepmon.lpi_stats->last_entered_at;
  895. seq_puts(s, "\nLPI stats:\n\n");
  896. seq_printf(s, "Count = %u\n", g_adspsleepmon.lpi_stats->count);
  897. seq_printf(s, "Last Entered At = %llu\n",
  898. g_adspsleepmon.lpi_stats->last_entered_at);
  899. seq_printf(s, "Last Exited At = %llu\n",
  900. g_adspsleepmon.lpi_stats->last_exited_at);
  901. seq_printf(s, "Accumulated Duration = %llu\n",
  902. accumulated);
  903. }
  904. return 0;
  905. }
  906. DEFINE_SHOW_ATTRIBUTE(master_stats);
  907. static void adspsleepmon_timer_cb(struct timer_list *unused)
  908. {
  909. /*
  910. * Configured timer has fired, wakeup the kernel thread
  911. */
  912. g_adspsleepmon.timer_event = true;
  913. wake_up_interruptible(&adspsleepmon_wq);
  914. }
  915. static void sleepmon_get_dsppm_clients(void)
  916. {
  917. int result = 0;
  918. if (g_adspsleepmon.adsp_version) {
  919. result = sleepmon_get_dsppm_client_stats();
  920. if (!result) {
  921. if (!wait_for_completion_timeout(&g_adspsleepmon.sem,
  922. WAIT_FOR_DSPPM_CLIENTDATA_TIMEOUT)) {
  923. pr_err("timeout waiting for completion\n");
  924. }
  925. print_complete_dsppm_info();
  926. } else
  927. pr_err("sleepmon_get_dsppm_client_stats failed with result: %u\n", result);
  928. }
  929. }
  930. static bool sleepmon_is_audio_active(struct dsppm_stats *curr_dsppm_stats)
  931. {
  932. int i;
  933. bool is_audio_active = false;
  934. bool is_pid_audio = false;
  935. for (i = 0; i < ADSPSLEEPMON_DSPPMSTATS_NUMPD; i++) {
  936. if (curr_dsppm_stats->pd[i].pid &&
  937. (curr_dsppm_stats->pd[i].num_active > 0)) {
  938. if ((curr_dsppm_stats->pd[i].pid &
  939. ADSPSLEEPMON_DSPPMSTATS_PID_FILTER) ==
  940. ADSPSLEEPMON_DSPPMSTATS_AUDIO_PID) {
  941. is_pid_audio = true;
  942. is_audio_active = true;
  943. } else {
  944. is_pid_audio = false;
  945. }
  946. pr_err("ADSP PID: %d (isAudio? %d), active clients: %d\n",
  947. curr_dsppm_stats->pd[i].pid,
  948. is_pid_audio,
  949. curr_dsppm_stats->pd[i].num_active);
  950. }
  951. }
  952. return is_audio_active;
  953. }
  954. static void adspsleepmon_lpm_adsp_panic(void)
  955. {
  956. if (g_adspsleepmon.b_config_adsp_panic_lpm) {
  957. pr_err("Sending panic command to ADSP for LPM violation\n");
  958. sleepmon_send_ssr_command();
  959. } else if (g_adspsleepmon.b_panic_lpm) {
  960. panic("ADSP sleep issue detected");
  961. }
  962. }
  963. static void adspsleepmon_lpm_adsp_panic_overall(void)
  964. {
  965. if (g_adspsleepmon.b_config_adsp_panic_lpm_overall) {
  966. pr_err("Sending panic command to ADSP for LPM violation, monitored duration (msec): %u, num resumes: %u\n",
  967. (g_adspsleepmon.accumulated_duration /
  968. ADSPSLEEPMON_SYS_CLK_TICKS_PER_MILLISEC),
  969. g_adspsleepmon.accumulated_resumes);
  970. sleepmon_send_ssr_command();
  971. }
  972. }
  973. #if IS_ENABLED(CONFIG_SEC_SENSORS_SSC) && !IS_ENABLED(CONFIG_SEC_FACTORY)
  974. extern void send_ssc_recovery_command(int type);
  975. static void adspsleepmon_adsp_sleep_check_panic(void)
  976. {
  977. pr_err("adsp_crash_ssr:%u \n", g_adspsleepmon.adsp_crash_ssr);
  978. if (g_adspsleepmon.adsp_crash_ssr == 1) { // panic
  979. panic("ADSP sleep issue detected, panic");
  980. } else if (g_adspsleepmon.adsp_crash_ssr == 2) { // ssr_dump
  981. send_ssc_recovery_command(1);
  982. } else if (g_adspsleepmon.adsp_crash_ssr == 3) { // ssr
  983. send_ssc_recovery_command(0);
  984. } else { //nothing
  985. pr_err("ADSP sleep issue detected, But ignore\n");
  986. }
  987. }
  988. static void sleepmon_lpm_dsp_sleep_check(struct sleep_stats* curr_lpm_stats)
  989. {
  990. time64_t diff_kts = -1;
  991. if (g_adspsleepmon.ap_sleep_checker.resume_ts.tv_sec >
  992. g_adspsleepmon.ap_sleep_checker.suspend_ts.tv_sec)
  993. diff_kts = g_adspsleepmon.ap_sleep_checker.resume_ts.tv_sec -
  994. g_adspsleepmon.ap_sleep_checker.suspend_ts.tv_sec;
  995. // check when ap sleep more than 10s
  996. if (diff_kts > 10) {
  997. struct dsppm_stats curr_dsppm_stats;
  998. struct sysmon_event_stats sysmon_event_stats;
  999. bool is_audio_active = false;
  1000. memcpy(&curr_dsppm_stats,g_adspsleepmon.dsppm_stats,
  1001. sizeof(struct dsppm_stats));
  1002. is_audio_active = sleepmon_is_audio_active(&curr_dsppm_stats);
  1003. memcpy(&sysmon_event_stats,
  1004. g_adspsleepmon.sysmon_event_stats,
  1005. sizeof(struct sysmon_event_stats));
  1006. pr_info("suspend ts:%d, resume ts:%d, diff_kts:%d, a:%d, l:%d\n",
  1007. (int)g_adspsleepmon.ap_sleep_checker.suspend_ts.tv_sec,
  1008. (int)g_adspsleepmon.ap_sleep_checker.resume_ts.tv_sec,
  1009. (int)diff_kts, (int)is_audio_active,
  1010. (int)sysmon_event_stats.sleep_latency);
  1011. if (!is_audio_active && sysmon_event_stats.sleep_latency == 0) {
  1012. int wakeup_rate = 0;
  1013. u32 diff_count = 0;
  1014. u64 accumulated;
  1015. pr_info("count:%d:%d, no_sleep_count:%d \n",
  1016. (int)curr_lpm_stats->count,
  1017. (int)g_adspsleepmon.suspend_prepare_stats.count,
  1018. (int)g_adspsleepmon.ap_sleep_checker.no_sleep_count);
  1019. // no adsp island
  1020. accumulated = curr_lpm_stats->accumulated;
  1021. if (curr_lpm_stats->last_entered_at >
  1022. curr_lpm_stats->last_exited_at) {
  1023. accumulated += arch_timer_read_counter() -
  1024. curr_lpm_stats->last_entered_at;
  1025. }
  1026. pr_info("accumulated:%u:%u, %u:%u \n",
  1027. (uint32_t)(g_adspsleepmon.suspend_prepare_stats.accumulated >> 32),
  1028. (uint32_t)(g_adspsleepmon.suspend_prepare_stats.accumulated & 0xFFFFFFFF),
  1029. (uint32_t)(accumulated >> 32),
  1030. (uint32_t)(accumulated & 0xFFFFFFFF));
  1031. if (curr_lpm_stats->count != 0 &&
  1032. (g_adspsleepmon.suspend_prepare_stats.count ==
  1033. curr_lpm_stats->count) &&
  1034. (g_adspsleepmon.suspend_prepare_stats.accumulated ==
  1035. accumulated)) {
  1036. g_adspsleepmon.ap_sleep_checker.no_sleep_count++;
  1037. if (g_adspsleepmon.ap_sleep_checker.no_sleep_count > 2) {
  1038. panic("ADSP sleep issue detected, no adsp island\n");
  1039. adspsleepmon_adsp_sleep_check_panic();
  1040. }
  1041. } else {
  1042. g_adspsleepmon.ap_sleep_checker.no_sleep_count = 0;
  1043. }
  1044. // frequent adsp wakeup
  1045. if (curr_lpm_stats->count > g_adspsleepmon.suspend_prepare_stats.count)
  1046. diff_count = curr_lpm_stats->count -
  1047. g_adspsleepmon.suspend_prepare_stats.count;
  1048. if (diff_count > 0)
  1049. wakeup_rate = (int)(diff_count/diff_kts);
  1050. pr_info("diff_count:%d, wakeup_rate:%d \n",
  1051. (int)diff_count, wakeup_rate);
  1052. // panic if adsp wakeup more than 50hz from island.
  1053. if (wakeup_rate > 50) {
  1054. panic("ADSP sleep issue detected, frequent adsp wakeup\n");
  1055. adspsleepmon_adsp_sleep_check_panic();
  1056. }
  1057. } else {
  1058. g_adspsleepmon.ap_sleep_checker.no_sleep_count = 0;
  1059. }
  1060. }
  1061. }
  1062. #endif
  1063. static void sleepmon_lpm_exception_check(u64 curr_timestamp, u64 elapsed_time)
  1064. {
  1065. struct sleep_stats curr_lpm_stats;
  1066. struct dsppm_stats curr_dsppm_stats;
  1067. struct sysmon_event_stats sysmon_event_stats;
  1068. bool is_audio_active = false;
  1069. /*
  1070. * Read ADSP sleep statistics and
  1071. * see if ADSP has entered sleep.
  1072. */
  1073. memcpy(&curr_lpm_stats,
  1074. g_adspsleepmon.lpm_stats,
  1075. sizeof(struct sleep_stats));
  1076. /*
  1077. * Check if ADSP didn't power collapse post
  1078. * no active client.
  1079. */
  1080. if ((!curr_lpm_stats.count) ||
  1081. (curr_lpm_stats.last_exited_at >
  1082. curr_lpm_stats.last_entered_at) ||
  1083. ((curr_lpm_stats.last_exited_at <
  1084. curr_lpm_stats.last_entered_at) &&
  1085. (curr_lpm_stats.last_entered_at >= curr_timestamp))) {
  1086. memcpy(&curr_dsppm_stats,
  1087. g_adspsleepmon.dsppm_stats,
  1088. sizeof(struct dsppm_stats));
  1089. memcpy(&sysmon_event_stats,
  1090. g_adspsleepmon.sysmon_event_stats,
  1091. sizeof(struct sysmon_event_stats));
  1092. if (curr_lpm_stats.accumulated ==
  1093. g_adspsleepmon.backup_lpm_stats.accumulated) {
  1094. pr_err("Detected ADSP sleep issue:\n");
  1095. pr_err("ADSP clock: %u, sleep latency: %u\n",
  1096. sysmon_event_stats.core_clk,
  1097. sysmon_event_stats.sleep_latency);
  1098. pr_err("Monitored duration (msec):%u,Sleep duration(msec): %u\n",
  1099. (elapsed_time /
  1100. ADSPSLEEPMON_SYS_CLK_TICKS_PER_MILLISEC),
  1101. ((curr_lpm_stats.accumulated -
  1102. g_adspsleepmon.backup_lpm_stats.accumulated) /
  1103. ADSPSLEEPMON_SYS_CLK_TICKS_PER_MILLISEC));
  1104. #if IS_ENABLED(CONFIG_SEC_FACTORY)
  1105. if (sysmon_event_stats.sleep_latency == 5000)
  1106. panic("Detected ADSP sleep issue");
  1107. #endif
  1108. is_audio_active = sleepmon_is_audio_active(&curr_dsppm_stats);
  1109. sleepmon_get_dsppm_clients();
  1110. #if IS_ENABLED(CONFIG_SND_SOC_SAMSUNG_AUDIO)
  1111. sdp_info_print("Detected ADSP sleep issue:\n");
  1112. sdp_info_print("ADSP clock: %u, sleep latency: %u, is_audio_active: %d\n",
  1113. sysmon_event_stats.core_clk,
  1114. sysmon_event_stats.sleep_latency,
  1115. is_audio_active);
  1116. #endif
  1117. if ((g_adspsleepmon.b_panic_lpm ||
  1118. g_adspsleepmon.b_config_adsp_panic_lpm) &&
  1119. is_audio_active)
  1120. adspsleepmon_lpm_adsp_panic();
  1121. else {
  1122. g_adspsleepmon.accumulated_duration += elapsed_time;
  1123. if (g_adspsleepmon.suspend_event)
  1124. g_adspsleepmon.accumulated_resumes++;
  1125. if ((g_adspsleepmon.accumulated_duration >=
  1126. ((u64)g_adspsleepmon.lpm_wait_time_overall *
  1127. ADSPSLEEPMON_SYS_CLK_TICKS_PER_SEC)) &&
  1128. (g_adspsleepmon.accumulated_resumes >=
  1129. g_adspsleepmon.min_required_resumes)) {
  1130. adspsleepmon_lpm_adsp_panic_overall();
  1131. g_adspsleepmon.accumulated_duration = 0;
  1132. g_adspsleepmon.accumulated_resumes = 0;
  1133. }
  1134. }
  1135. } else {
  1136. g_adspsleepmon.accumulated_duration = 0;
  1137. g_adspsleepmon.accumulated_resumes = 0;
  1138. }
  1139. }
  1140. memcpy(&g_adspsleepmon.backup_lpm_stats,
  1141. &curr_lpm_stats,
  1142. sizeof(struct sleep_stats));
  1143. g_adspsleepmon.backup_lpm_timestamp = __arch_counter_get_cntvct();
  1144. #if IS_ENABLED(CONFIG_SEC_SENSORS_SSC) && !IS_ENABLED(CONFIG_SEC_FACTORY)
  1145. if (g_adspsleepmon.b_config_enable_adsp_sleep_checker_ss)
  1146. if (!g_adspsleepmon.timer_event && g_adspsleepmon.suspend_event)
  1147. sleepmon_lpm_dsp_sleep_check(&curr_lpm_stats);
  1148. #endif
  1149. }
  1150. static void sleepmon_lpi_exception_check(u64 curr_timestamp, u64 elapsed_time)
  1151. {
  1152. struct sleep_stats curr_lpi_stats;
  1153. struct dsppm_stats curr_dsppm_stats;
  1154. struct sysmon_event_stats sysmon_event_stats;
  1155. bool is_audio_active = false;
  1156. /*
  1157. * Read ADSP LPI statistics and see
  1158. * if ADSP is in LPI state.
  1159. */
  1160. memcpy(&curr_lpi_stats,
  1161. g_adspsleepmon.lpi_stats,
  1162. sizeof(struct sleep_stats));
  1163. /*
  1164. * Check if ADSP is not in LPI
  1165. */
  1166. if ((!curr_lpi_stats.count) ||
  1167. (curr_lpi_stats.last_exited_at >
  1168. curr_lpi_stats.last_entered_at) ||
  1169. ((curr_lpi_stats.last_exited_at <
  1170. curr_lpi_stats.last_entered_at) &&
  1171. (curr_lpi_stats.last_entered_at >= curr_timestamp))) {
  1172. memcpy(&curr_dsppm_stats,
  1173. g_adspsleepmon.dsppm_stats,
  1174. sizeof(struct dsppm_stats));
  1175. memcpy(&sysmon_event_stats,
  1176. g_adspsleepmon.sysmon_event_stats,
  1177. sizeof(struct sysmon_event_stats));
  1178. if (curr_lpi_stats.accumulated ==
  1179. g_adspsleepmon.backup_lpi_stats.accumulated) {
  1180. pr_err("Detected ADSP LPI issue:\n");
  1181. pr_err("ADSP clock: %u, sleep latency: %u\n",
  1182. sysmon_event_stats.core_clk,
  1183. sysmon_event_stats.sleep_latency);
  1184. pr_err("Monitored duration (msec):%u,LPI duration(msec): %u\n",
  1185. (elapsed_time /
  1186. ADSPSLEEPMON_SYS_CLK_TICKS_PER_MILLISEC),
  1187. ((curr_lpi_stats.accumulated -
  1188. g_adspsleepmon.backup_lpi_stats.accumulated) /
  1189. ADSPSLEEPMON_SYS_CLK_TICKS_PER_MILLISEC));
  1190. is_audio_active = sleepmon_is_audio_active(&curr_dsppm_stats);
  1191. sleepmon_get_dsppm_clients();
  1192. #if IS_ENABLED(CONFIG_SND_SOC_SAMSUNG_AUDIO)
  1193. sdp_info_print("Detected ADSP LPI issue:\n");
  1194. sdp_info_print("ADSP clock: %u, sleep latency: %u, is_audio_active: %d\n",
  1195. sysmon_event_stats.core_clk,
  1196. sysmon_event_stats.sleep_latency,
  1197. is_audio_active);
  1198. #endif
  1199. sleepmon_send_lpi_issue_command();
  1200. }
  1201. }
  1202. memcpy(&g_adspsleepmon.backup_lpi_stats,
  1203. &curr_lpi_stats,
  1204. sizeof(struct sleep_stats));
  1205. g_adspsleepmon.backup_lpi_timestamp = __arch_counter_get_cntvct();
  1206. }
  1207. static int adspsleepmon_worker(void *data)
  1208. {
  1209. u64 curr_timestamp, elapsed_time;
  1210. int result = 0;
  1211. while (!kthread_should_stop()) {
  1212. result = wait_event_interruptible(adspsleepmon_wq,
  1213. (kthread_should_stop() ||
  1214. g_adspsleepmon.timer_event ||
  1215. g_adspsleepmon.suspend_event));
  1216. if (kthread_should_stop())
  1217. break;
  1218. if (result)
  1219. continue;
  1220. pr_info("timer_event = %d,suspend_event = %d\n",
  1221. g_adspsleepmon.timer_event,
  1222. g_adspsleepmon.suspend_event);
  1223. /*
  1224. * Handle timer event.
  1225. * 2 cases:
  1226. * - There is no active use case on ADSP, we
  1227. * are expecting it to be in power collapse
  1228. * - There is an active LPI use case on ADSP,
  1229. * we are expecting it to be in LPI.
  1230. *
  1231. * Critical section start
  1232. */
  1233. mutex_lock(&g_adspsleepmon.lock);
  1234. if (!g_adspsleepmon.audio_stats.num_sessions) {
  1235. curr_timestamp = __arch_counter_get_cntvct();
  1236. if (curr_timestamp >= g_adspsleepmon.backup_lpm_timestamp)
  1237. elapsed_time = (curr_timestamp -
  1238. g_adspsleepmon.backup_lpm_timestamp);
  1239. else
  1240. elapsed_time = U64_MAX -
  1241. g_adspsleepmon.backup_lpm_timestamp +
  1242. curr_timestamp;
  1243. /* Check elapsed time for both suspend and timer events */
  1244. if (elapsed_time <
  1245. (g_adspsleepmon.lpm_wait_time *
  1246. ADSPSLEEPMON_SYS_CLK_TICKS_PER_SEC)) {
  1247. goto TIME_NOT_ELAPSED;
  1248. }
  1249. sleepmon_lpm_exception_check(curr_timestamp, elapsed_time);
  1250. } else if (g_adspsleepmon.audio_stats.num_sessions ==
  1251. g_adspsleepmon.audio_stats.num_lpi_sessions) {
  1252. curr_timestamp = __arch_counter_get_cntvct();
  1253. if (curr_timestamp >=
  1254. g_adspsleepmon.backup_lpi_timestamp)
  1255. elapsed_time = (curr_timestamp -
  1256. g_adspsleepmon.backup_lpi_timestamp);
  1257. else
  1258. elapsed_time = U64_MAX -
  1259. g_adspsleepmon.backup_lpi_timestamp +
  1260. curr_timestamp;
  1261. /* Check elapsed time for both suspend and timer events */
  1262. if (elapsed_time <
  1263. (g_adspsleepmon.lpi_wait_time *
  1264. ADSPSLEEPMON_SYS_CLK_TICKS_PER_SEC)) {
  1265. goto TIME_NOT_ELAPSED;
  1266. }
  1267. sleepmon_lpi_exception_check(curr_timestamp, elapsed_time);
  1268. }
  1269. TIME_NOT_ELAPSED:
  1270. if (g_adspsleepmon.timer_event) {
  1271. g_adspsleepmon.timer_event = false;
  1272. g_adspsleepmon.timer_pending = false;
  1273. }
  1274. g_adspsleepmon.suspend_event = false;
  1275. mutex_unlock(&g_adspsleepmon.lock);
  1276. }
  1277. return 0;
  1278. }
  1279. static int adspsleepmon_device_open(struct inode *inode, struct file *fp)
  1280. {
  1281. struct adspsleepmon_file *fl = NULL;
  1282. /*
  1283. * Check if SMEM side needs initialization
  1284. */
  1285. if (!g_adspsleepmon.smem_init_done)
  1286. adspsleepmon_smem_init();
  1287. if (!g_adspsleepmon.smem_init_done)
  1288. return -ENODEV;
  1289. /*
  1290. * Check for device minor and return error if not matching
  1291. * May need to allocate (kzalloc) based on requirement and update
  1292. * fp->private_data.
  1293. */
  1294. fl = kzalloc(sizeof(*fl), GFP_KERNEL);
  1295. if (IS_ERR_OR_NULL(fl))
  1296. return -ENOMEM;
  1297. INIT_HLIST_NODE(&fl->hn);
  1298. fl->num_sessions = 0;
  1299. fl->num_lpi_sessions = 0;
  1300. fl->b_connected = 0;
  1301. spin_lock_init(&fl->hlock);
  1302. fp->private_data = fl;
  1303. return 0;
  1304. }
  1305. static int adspsleepmon_device_release(struct inode *inode, struct file *fp)
  1306. {
  1307. struct adspsleepmon_file *fl = (struct adspsleepmon_file *)fp->private_data;
  1308. u32 num_sessions = 0, num_lpi_sessions = 0, delay = 0;
  1309. struct adspsleepmon_file *client = NULL;
  1310. struct hlist_node *n;
  1311. /*
  1312. * do tear down
  1313. */
  1314. if (fl) {
  1315. /*
  1316. * Critical section start
  1317. */
  1318. mutex_lock(&g_adspsleepmon.lock);
  1319. spin_lock(&fl->hlock);
  1320. hlist_del_init(&fl->hn);
  1321. /*
  1322. * Reaggregate num sessions
  1323. */
  1324. hlist_for_each_entry_safe(client, n,
  1325. &g_adspsleepmon.audio_clients, hn) {
  1326. if (client->b_connected) {
  1327. num_sessions += client->num_sessions;
  1328. num_lpi_sessions += client->num_lpi_sessions;
  1329. }
  1330. }
  1331. spin_unlock(&fl->hlock);
  1332. kfree(fl);
  1333. /*
  1334. * Start/stop the timer based on
  1335. * Start -> No active session (from previous
  1336. * active session)
  1337. * Stop -> An active session
  1338. */
  1339. if (num_sessions != g_adspsleepmon.audio_stats.num_sessions) {
  1340. if (!num_sessions ||
  1341. (num_sessions == num_lpi_sessions)) {
  1342. if (!num_sessions) {
  1343. memcpy(&g_adspsleepmon.backup_lpm_stats,
  1344. g_adspsleepmon.lpm_stats,
  1345. sizeof(struct sleep_stats));
  1346. g_adspsleepmon.backup_lpm_timestamp =
  1347. __arch_counter_get_cntvct();
  1348. delay = g_adspsleepmon.lpm_wait_time;
  1349. } else {
  1350. memcpy(&g_adspsleepmon.backup_lpi_stats,
  1351. g_adspsleepmon.lpi_stats,
  1352. sizeof(struct sleep_stats));
  1353. g_adspsleepmon.backup_lpi_timestamp =
  1354. __arch_counter_get_cntvct();
  1355. delay = g_adspsleepmon.lpi_wait_time;
  1356. g_adspsleepmon.accumulated_duration = 0;
  1357. g_adspsleepmon.accumulated_resumes = 0;
  1358. }
  1359. mod_timer(&adspsleep_timer, jiffies + delay * HZ);
  1360. g_adspsleepmon.timer_pending = true;
  1361. } else if (g_adspsleepmon.timer_pending) {
  1362. del_timer(&adspsleep_timer);
  1363. g_adspsleepmon.timer_pending = false;
  1364. g_adspsleepmon.accumulated_duration = 0;
  1365. g_adspsleepmon.accumulated_resumes = 0;
  1366. }
  1367. g_adspsleepmon.audio_stats.num_sessions = num_sessions;
  1368. g_adspsleepmon.audio_stats.num_lpi_sessions = num_lpi_sessions;
  1369. }
  1370. mutex_unlock(&g_adspsleepmon.lock);
  1371. pr_info("Release: num_sessions=%d,num_lpi_sessions=%d,timer_pending=%d\n",
  1372. g_adspsleepmon.audio_stats.num_sessions,
  1373. g_adspsleepmon.audio_stats.num_lpi_sessions,
  1374. g_adspsleepmon.timer_pending);
  1375. /*
  1376. * Critical section Done
  1377. */
  1378. } else {
  1379. return -ENODATA;
  1380. }
  1381. return 0;
  1382. }
  1383. static long adspsleepmon_device_ioctl(struct file *file,
  1384. unsigned int ioctl_num,
  1385. unsigned long ioctl_param)
  1386. {
  1387. int ret = 0;
  1388. struct adspsleepmon_file *fl = (struct adspsleepmon_file *)file->private_data;
  1389. switch (ioctl_num) {
  1390. case ADSPSLEEPMON_IOCTL_CONFIGURE_PANIC:
  1391. {
  1392. struct adspsleepmon_ioctl_panic panic_param;
  1393. if (copy_from_user(&panic_param, (void const __user *)ioctl_param,
  1394. sizeof(struct adspsleepmon_ioctl_panic))) {
  1395. ret = -ENOTTY;
  1396. pr_err("IOCTL copy from user failed\n");
  1397. goto bail;
  1398. }
  1399. if (panic_param.version <
  1400. ADSPSLEEPMON_IOCTL_CONFIG_PANIC_VER_1) {
  1401. ret = -ENOTTY;
  1402. pr_err("Bad version (%d) in IOCTL (%d)\n",
  1403. panic_param.version, ioctl_num);
  1404. goto bail;
  1405. }
  1406. if (panic_param.command >= ADSPSLEEPMON_RESET_PANIC_MAX) {
  1407. ret = -EINVAL;
  1408. pr_err("Invalid command (%d) passed in IOCTL (%d)\n",
  1409. panic_param.command, ioctl_num);
  1410. goto bail;
  1411. }
  1412. switch (panic_param.command) {
  1413. case ADSPSLEEPMON_DISABLE_PANIC_LPM:
  1414. g_adspsleepmon.b_panic_lpm = false;
  1415. break;
  1416. case ADSPSLEEPMON_DISABLE_PANIC_LPI:
  1417. g_adspsleepmon.b_panic_lpi = false;
  1418. break;
  1419. case ADSPSLEEPMON_RESET_PANIC_LPM:
  1420. g_adspsleepmon.b_panic_lpm =
  1421. g_adspsleepmon.b_config_panic_lpm;
  1422. break;
  1423. case ADSPSLEEPMON_RESET_PANIC_LPI:
  1424. g_adspsleepmon.b_panic_lpi =
  1425. g_adspsleepmon.b_config_panic_lpi;
  1426. break;
  1427. }
  1428. }
  1429. break;
  1430. case ADSPSLEEPMON_IOCTL_AUDIO_ACTIVITY:
  1431. {
  1432. struct adspsleepmon_ioctl_audio audio_param;
  1433. u32 num_sessions = 0, num_lpi_sessions = 0, delay = 0;
  1434. struct adspsleepmon_file *client = NULL;
  1435. struct hlist_node *n;
  1436. if (copy_from_user(&audio_param, (void const __user *)ioctl_param,
  1437. sizeof(struct adspsleepmon_ioctl_audio))) {
  1438. ret = -ENOTTY;
  1439. pr_err("IOCTL copy from user failed\n");
  1440. goto bail;
  1441. }
  1442. if (!fl) {
  1443. pr_err("bad pointer to private data in ioctl\n");
  1444. ret = -ENOMEM;
  1445. goto bail;
  1446. }
  1447. if (fl->b_connected &&
  1448. (fl->b_connected != ADSPSLEEPMON_AUDIO_CLIENT)) {
  1449. pr_err("Restricted IOCTL (%d) called from %d client\n",
  1450. ioctl_num, fl->b_connected);
  1451. ret = -ENOMSG;
  1452. goto bail;
  1453. }
  1454. /*
  1455. * Check version
  1456. */
  1457. if (audio_param.version <
  1458. ADSPSLEEPMON_IOCTL_AUDIO_VER_1) {
  1459. ret = -ENOTTY;
  1460. pr_err("Bad version (%d) in IOCTL (%d)\n",
  1461. audio_param.version, ioctl_num);
  1462. goto bail;
  1463. }
  1464. if (audio_param.command >= ADSPSLEEPMON_AUDIO_ACTIVITY_MAX) {
  1465. ret = -EINVAL;
  1466. pr_err("Invalid command (%d) passed in IOCTL (%d)\n",
  1467. audio_param.command, ioctl_num);
  1468. goto bail;
  1469. }
  1470. /*
  1471. * Critical section start
  1472. */
  1473. mutex_lock(&g_adspsleepmon.lock);
  1474. if (!fl->b_connected) {
  1475. hlist_add_head(&fl->hn, &g_adspsleepmon.audio_clients);
  1476. fl->b_connected = ADSPSLEEPMON_AUDIO_CLIENT;
  1477. }
  1478. switch (audio_param.command) {
  1479. case ADSPSLEEPMON_AUDIO_ACTIVITY_LPI_START:
  1480. fl->num_lpi_sessions++;
  1481. __attribute__((__fallthrough__));
  1482. case ADSPSLEEPMON_AUDIO_ACTIVITY_START:
  1483. fl->num_sessions++;
  1484. break;
  1485. case ADSPSLEEPMON_AUDIO_ACTIVITY_LPI_STOP:
  1486. if (fl->num_lpi_sessions)
  1487. fl->num_lpi_sessions--;
  1488. else
  1489. pr_info("Received AUDIO LPI activity stop when none active!\n");
  1490. __attribute__((__fallthrough__));
  1491. case ADSPSLEEPMON_AUDIO_ACTIVITY_STOP:
  1492. if (fl->num_sessions)
  1493. fl->num_sessions--;
  1494. else
  1495. pr_info("Received AUDIO activity stop when none active!\n");
  1496. break;
  1497. case ADSPSLEEPMON_AUDIO_ACTIVITY_RESET:
  1498. fl->num_sessions = 0;
  1499. fl->num_lpi_sessions = 0;
  1500. break;
  1501. }
  1502. /*
  1503. * Iterate over the registered audio IOCTL clients and
  1504. * calculate total number of active sessions and LPI sessions
  1505. */
  1506. spin_lock(&fl->hlock);
  1507. hlist_for_each_entry_safe(client, n,
  1508. &g_adspsleepmon.audio_clients, hn) {
  1509. if (client->b_connected) {
  1510. num_sessions += client->num_sessions;
  1511. num_lpi_sessions += client->num_lpi_sessions;
  1512. }
  1513. }
  1514. spin_unlock(&fl->hlock);
  1515. /*
  1516. * Start/stop the timer based on
  1517. * Start -> No active session (from previous
  1518. * active session)
  1519. * Stop -> An active session
  1520. */
  1521. if (!num_sessions ||
  1522. (num_sessions == num_lpi_sessions)) {
  1523. if (!num_sessions) {
  1524. memcpy(&g_adspsleepmon.backup_lpm_stats,
  1525. g_adspsleepmon.lpm_stats,
  1526. sizeof(struct sleep_stats));
  1527. g_adspsleepmon.backup_lpm_timestamp =
  1528. __arch_counter_get_cntvct();
  1529. delay = g_adspsleepmon.lpm_wait_time;
  1530. } else {
  1531. memcpy(&g_adspsleepmon.backup_lpi_stats,
  1532. g_adspsleepmon.lpi_stats,
  1533. sizeof(struct sleep_stats));
  1534. g_adspsleepmon.backup_lpi_timestamp =
  1535. __arch_counter_get_cntvct();
  1536. delay = g_adspsleepmon.lpi_wait_time;
  1537. g_adspsleepmon.accumulated_duration = 0;
  1538. g_adspsleepmon.accumulated_resumes = 0;
  1539. }
  1540. mod_timer(&adspsleep_timer, jiffies + delay * HZ);
  1541. g_adspsleepmon.timer_pending = true;
  1542. } else if (g_adspsleepmon.timer_pending) {
  1543. del_timer(&adspsleep_timer);
  1544. g_adspsleepmon.timer_pending = false;
  1545. g_adspsleepmon.accumulated_duration = 0;
  1546. g_adspsleepmon.accumulated_resumes = 0;
  1547. }
  1548. g_adspsleepmon.audio_stats.num_sessions = num_sessions;
  1549. g_adspsleepmon.audio_stats.num_lpi_sessions = num_lpi_sessions;
  1550. pr_info("Audio: num_sessions=%d,num_lpi_sessions=%d,timer_pending=%d\n",
  1551. g_adspsleepmon.audio_stats.num_sessions,
  1552. g_adspsleepmon.audio_stats.num_lpi_sessions,
  1553. g_adspsleepmon.timer_pending);
  1554. mutex_unlock(&g_adspsleepmon.lock);
  1555. /*
  1556. * Critical section end
  1557. */
  1558. }
  1559. break;
  1560. default:
  1561. ret = -ENOTTY;
  1562. pr_info("Unidentified ioctl %d!\n", ioctl_num);
  1563. break;
  1564. }
  1565. bail:
  1566. return ret;
  1567. }
  1568. static const struct file_operations fops = {
  1569. .open = adspsleepmon_device_open,
  1570. .release = adspsleepmon_device_release,
  1571. .unlocked_ioctl = adspsleepmon_device_ioctl,
  1572. .compat_ioctl = adspsleepmon_device_ioctl,
  1573. };
  1574. static const struct of_device_id sleepmon_rpmsg_of_match[] = {
  1575. { .compatible = "qcom,msm-adspsleepmon-rpmsg" },
  1576. { },
  1577. };
  1578. MODULE_DEVICE_TABLE(of, sleepmon_rpmsg_of_match);
  1579. static const struct rpmsg_device_id sleepmon_rpmsg_match[] = {
  1580. { "sleepmonglink-apps-adsp" },
  1581. { },
  1582. };
  1583. static int sleepmon_rpmsg_probe(struct rpmsg_device *dev)
  1584. {
  1585. /* Populate child nodes as platform devices */
  1586. of_platform_populate(dev->dev.of_node, NULL, NULL, &dev->dev);
  1587. g_adspsleepmon.rpmsgdev = dev;
  1588. if (!g_adspsleepmon.adsp_rproc &&
  1589. g_adspsleepmon.adsp_rproc_phandle) {
  1590. g_adspsleepmon.adsp_rproc = rproc_get_by_phandle(
  1591. g_adspsleepmon.adsp_rproc_phandle);
  1592. }
  1593. if (g_adspsleepmon.adsp_rproc) {
  1594. pr_info("Resetting recovery flag for ADSP SSR\n");
  1595. qcom_rproc_update_recovery_status(
  1596. g_adspsleepmon.adsp_rproc, false);
  1597. }
  1598. return adspsleepmon_smem_init();
  1599. }
  1600. static void sleepmon_rpmsg_remove(struct rpmsg_device *dev)
  1601. {
  1602. g_adspsleepmon.rpmsgdev = NULL;
  1603. g_adspsleepmon.adsp_version = 0;
  1604. }
  1605. static struct rpmsg_driver sleepmon_rpmsg_client = {
  1606. .id_table = sleepmon_rpmsg_match,
  1607. .probe = sleepmon_rpmsg_probe,
  1608. .remove = sleepmon_rpmsg_remove,
  1609. .callback = sleepmon_rpmsg_callback,
  1610. .drv = {
  1611. .name = "qcom,msm_adspsleepmon_rpmsg",
  1612. .of_match_table = sleepmon_rpmsg_of_match,
  1613. },
  1614. };
  1615. static int adspsleepmon_driver_probe(struct platform_device *pdev)
  1616. {
  1617. struct device *dev = &pdev->dev;
  1618. int ret = 0;
  1619. struct adspsleepmon *me = &g_adspsleepmon;
  1620. mutex_init(&g_adspsleepmon.lock);
  1621. /*
  1622. * Initialize dtsi config
  1623. */
  1624. g_adspsleepmon.lpm_wait_time = ADSPSLEEPMON_LPM_WAIT_TIME;
  1625. g_adspsleepmon.lpi_wait_time = ADSPSLEEPMON_LPI_WAIT_TIME;
  1626. g_adspsleepmon.lpm_wait_time_overall = ADSPSLEEPMON_LPM_WAIT_TIME_OVERALL;
  1627. g_adspsleepmon.min_required_resumes = ADSPSLEEPMON_MIN_REQUIRED_RESUMES;
  1628. g_adspsleepmon.b_config_panic_lpm = false;
  1629. g_adspsleepmon.b_config_panic_lpi = false;
  1630. g_adspsleepmon.worker_task = kthread_run(adspsleepmon_worker,
  1631. NULL, "adspsleepmon-worker");
  1632. if (!g_adspsleepmon.worker_task) {
  1633. dev_err(dev, "Failed to create kernel thread\n");
  1634. return -ENOMEM;
  1635. }
  1636. INIT_HLIST_HEAD(&g_adspsleepmon.audio_clients);
  1637. ret = alloc_chrdev_region(&me->devno, 0, 1, ADSPSLEEPMON_DEVICE_NAME_LOCAL);
  1638. if (ret != 0) {
  1639. dev_err(dev, "Failed to allocate char device region\n");
  1640. goto rpmsg_bail;
  1641. }
  1642. cdev_init(&me->cdev, &fops);
  1643. me->cdev.owner = THIS_MODULE;
  1644. ret = cdev_add(&me->cdev, MKDEV(MAJOR(me->devno), 0), 1);
  1645. if (ret != 0) {
  1646. dev_err(dev, "Failed to add cdev\n");
  1647. goto cdev_bail;
  1648. }
  1649. me->class = class_create(THIS_MODULE, "adspsleepmon");
  1650. if (IS_ERR(me->class)) {
  1651. dev_err(dev, "Failed to create a class\n");
  1652. goto class_bail;
  1653. }
  1654. me->dev = device_create(me->class, NULL,
  1655. MKDEV(MAJOR(me->devno), 0), NULL, ADSPSLEEPMON_DEVICE_NAME_LOCAL);
  1656. if (IS_ERR_OR_NULL(me->dev)) {
  1657. dev_err(dev, "Failed to create a device\n");
  1658. goto device_bail;
  1659. }
  1660. g_adspsleepmon.debugfs_dir = debugfs_create_dir("adspsleepmon", NULL);
  1661. if (!g_adspsleepmon.debugfs_dir) {
  1662. dev_err(dev, "Failed to create debugfs directory for adspsleepmon\n");
  1663. goto debugfs_bail;
  1664. }
  1665. g_adspsleepmon.b_config_panic_lpm = of_property_read_bool(dev->of_node,
  1666. "qcom,enable_panic_lpm");
  1667. g_adspsleepmon.b_config_panic_lpi = of_property_read_bool(dev->of_node,
  1668. "qcom,enable_panic_lpi");
  1669. g_adspsleepmon.b_config_adsp_panic_lpm = of_property_read_bool(dev->of_node,
  1670. "qcom,enable_adsp_panic_lpm");
  1671. g_adspsleepmon.b_config_adsp_panic_lpi = of_property_read_bool(dev->of_node,
  1672. "qcom,enable_adsp_panic_lpi");
  1673. g_adspsleepmon.b_config_adsp_panic_lpm_overall = of_property_read_bool(dev->of_node,
  1674. "qcom,enable_adsp_panic_lpm_overall");
  1675. #if IS_ENABLED(CONFIG_SEC_SENSORS_SSC) && !IS_ENABLED(CONFIG_SEC_FACTORY)
  1676. g_adspsleepmon.b_config_enable_adsp_sleep_checker_ss = of_property_read_bool(dev->of_node,
  1677. "qcom,enable_adsp_sleep_checker_ss");
  1678. of_property_read_u32(dev->of_node, "qcom,adsp_crash_ssr_ss",
  1679. &g_adspsleepmon.adsp_crash_ssr);
  1680. #endif
  1681. of_property_read_u32(dev->of_node, "qcom,wait_time_lpm",
  1682. &g_adspsleepmon.lpm_wait_time);
  1683. of_property_read_u32(dev->of_node, "qcom,wait_time_lpi",
  1684. &g_adspsleepmon.lpi_wait_time);
  1685. of_property_read_u32(dev->of_node, "qcom,wait_time_lpm_overall",
  1686. &g_adspsleepmon.lpm_wait_time_overall);
  1687. of_property_read_u32(dev->of_node, "qcom,min_required_resumes",
  1688. &g_adspsleepmon.min_required_resumes);
  1689. of_property_read_u32(dev->of_node, "qcom,rproc-handle",
  1690. &g_adspsleepmon.adsp_rproc_phandle);
  1691. if (g_adspsleepmon.adsp_rproc_phandle &&
  1692. (g_adspsleepmon.b_config_adsp_panic_lpm ||
  1693. g_adspsleepmon.b_config_adsp_panic_lpi ||
  1694. g_adspsleepmon.b_config_adsp_panic_lpm_overall)) {
  1695. g_adspsleepmon.b_config_adsp_ssr_enable = true;
  1696. dev_info(dev, "ADSP SSR config enabled\n");
  1697. }
  1698. g_adspsleepmon.b_panic_lpm = g_adspsleepmon.b_config_panic_lpm;
  1699. g_adspsleepmon.b_panic_lpi = g_adspsleepmon.b_config_panic_lpi;
  1700. if (g_adspsleepmon.b_config_panic_lpm ||
  1701. g_adspsleepmon.b_config_panic_lpi) {
  1702. g_adspsleepmon.debugfs_panic_file =
  1703. debugfs_create_file("panic-state",
  1704. 0644, g_adspsleepmon.debugfs_dir, NULL, &panic_state_fops);
  1705. if (!g_adspsleepmon.debugfs_panic_file)
  1706. dev_err(dev, "Unable to create file in debugfs\n");
  1707. }
  1708. g_adspsleepmon.debugfs_read_panic_state =
  1709. debugfs_create_file("read_panic_state",
  1710. 0444, g_adspsleepmon.debugfs_dir, NULL, &read_panic_state_fops);
  1711. if (!g_adspsleepmon.debugfs_read_panic_state)
  1712. dev_err(dev, "Unable to create read panic state file in debugfs\n");
  1713. g_adspsleepmon.debugfs_master_stats =
  1714. debugfs_create_file("master_stats",
  1715. 0444, g_adspsleepmon.debugfs_dir, NULL, &master_stats_fops);
  1716. if (!g_adspsleepmon.debugfs_master_stats)
  1717. dev_err(dev, "Failed to create debugfs file for master stats\n");
  1718. g_adspsleepmon.debugfs_adsp_panic_file =
  1719. debugfs_create_file("adsp_panic_state",
  1720. 0644, g_adspsleepmon.debugfs_dir, NULL, &adsp_panic_state_fops);
  1721. if (!g_adspsleepmon.debugfs_adsp_panic_file)
  1722. dev_err(dev, "Unable to create ADSP panic state file in debugfs\n");
  1723. g_adspsleepmon.debugfs_read_adsp_panic_state =
  1724. debugfs_create_file("read_adsp_panic_state",
  1725. 0444, g_adspsleepmon.debugfs_dir, NULL, &read_adsp_panic_state_fops);
  1726. if (!g_adspsleepmon.debugfs_read_adsp_panic_state)
  1727. dev_err(dev, "Unable to create ADSP panic state read file in debugfs\n");
  1728. ret = register_rpmsg_driver(&sleepmon_rpmsg_client);
  1729. if (ret) {
  1730. dev_err(dev, "Failed registering rpmsg driver with return %d\n",
  1731. ret);
  1732. goto rpmsg_bail;
  1733. }
  1734. g_adspsleepmon.b_rpmsg_register = true;
  1735. init_completion(&g_adspsleepmon.sem);
  1736. dev_info(dev, "ADSP sleep monitor probe called\n");
  1737. return 0;
  1738. debugfs_bail:
  1739. device_destroy(g_adspsleepmon.class, g_adspsleepmon.cdev.dev);
  1740. device_bail:
  1741. class_destroy(me->class);
  1742. class_bail:
  1743. cdev_del(&me->cdev);
  1744. cdev_bail:
  1745. unregister_chrdev_region(me->devno, 1);
  1746. rpmsg_bail:
  1747. return ret;
  1748. }
  1749. static int adspsleepmon_driver_remove(struct platform_device *pdev)
  1750. {
  1751. struct device *dev = &pdev->dev;
  1752. device_destroy(g_adspsleepmon.class, g_adspsleepmon.cdev.dev);
  1753. class_destroy(g_adspsleepmon.class);
  1754. cdev_del(&g_adspsleepmon.cdev);
  1755. unregister_chrdev_region(g_adspsleepmon.devno, 1);
  1756. debugfs_remove_recursive(g_adspsleepmon.debugfs_dir);
  1757. unregister_pm_notifier(&adsp_sleepmon_pm_nb);
  1758. if (g_adspsleepmon.b_rpmsg_register) {
  1759. unregister_rpmsg_driver(&sleepmon_rpmsg_client);
  1760. g_adspsleepmon.rpmsgdev = NULL;
  1761. g_adspsleepmon.adsp_version = 0;
  1762. }
  1763. dev_info(dev, "ADSP sleep monitor remove called\n");
  1764. return 0;
  1765. }
  1766. static const struct of_device_id adspsleepmon_match_table[] = {
  1767. { .compatible = "qcom,adsp-sleepmon" },
  1768. { },
  1769. };
  1770. static struct platform_driver adspsleepmon = {
  1771. .probe = adspsleepmon_driver_probe,
  1772. .remove = adspsleepmon_driver_remove,
  1773. .driver = {
  1774. .name = "adsp_sleepmon",
  1775. .of_match_table = adspsleepmon_match_table,
  1776. },
  1777. };
  1778. module_platform_driver(adspsleepmon);
  1779. MODULE_LICENSE("GPL");