blob: 6b7573c5aa71ac88343b4fc36600f5ea8c924c96 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13/*
14 * Shared memory logging implementation.
15 */
16
17#include <linux/slab.h>
18#include <linux/uaccess.h>
19#include <linux/module.h>
20#include <linux/fs.h>
21#include <linux/miscdevice.h>
22#include <linux/kernel.h>
23#include <linux/errno.h>
24#include <linux/jiffies.h>
25#include <linux/remote_spinlock.h>
26#include <linux/debugfs.h>
27#include <linux/io.h>
28#include <linux/string.h>
29#include <linux/sched.h>
30#include <linux/wait.h>
31#include <linux/delay.h>
32
33#include <mach/msm_iomap.h>
34#include <mach/smem_log.h>
35
36#include "smd_private.h"
37#include "smd_rpc_sym.h"
38#include "modem_notifier.h"
39
40#define DEBUG
41#undef DEBUG
42
43#ifdef DEBUG
44#define D_DUMP_BUFFER(prestr, cnt, buf) \
45do { \
46 int i; \
47 printk(KERN_ERR "%s", prestr); \
48 for (i = 0; i < cnt; i++) \
49 printk(KERN_ERR "%.2x", buf[i]); \
50 printk(KERN_ERR "\n"); \
51} while (0)
52#else
53#define D_DUMP_BUFFER(prestr, cnt, buf)
54#endif
55
56#ifdef DEBUG
57#define D(x...) printk(x)
58#else
59#define D(x...) do {} while (0)
60#endif
61
62#if defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60) \
63 || defined(CONFIG_ARCH_FSM9XXX)
64#define TIMESTAMP_ADDR (MSM_TMR_BASE + 0x08)
65#else
66#define TIMESTAMP_ADDR (MSM_TMR_BASE + 0x04)
67#endif
68
69struct smem_log_item {
70 uint32_t identifier;
71 uint32_t timetick;
72 uint32_t data1;
73 uint32_t data2;
74 uint32_t data3;
75};
76
77#define SMEM_LOG_NUM_ENTRIES 2000
78#define SMEM_LOG_EVENTS_SIZE (sizeof(struct smem_log_item) * \
79 SMEM_LOG_NUM_ENTRIES)
80
81#define SMEM_LOG_NUM_STATIC_ENTRIES 150
82#define SMEM_STATIC_LOG_EVENTS_SIZE (sizeof(struct smem_log_item) * \
83 SMEM_LOG_NUM_STATIC_ENTRIES)
84
85#define SMEM_LOG_NUM_POWER_ENTRIES 2000
86#define SMEM_POWER_LOG_EVENTS_SIZE (sizeof(struct smem_log_item) * \
87 SMEM_LOG_NUM_POWER_ENTRIES)
88
89#define SMEM_SPINLOCK_SMEM_LOG "S:2"
90#define SMEM_SPINLOCK_STATIC_LOG "S:5"
91/* POWER shares with SMEM_SPINLOCK_SMEM_LOG */
92
93static remote_spinlock_t remote_spinlock;
94static remote_spinlock_t remote_spinlock_static;
95static uint32_t smem_log_enable;
96static int smem_log_initialized;
97
98module_param_named(log_enable, smem_log_enable, int,
99 S_IRUGO | S_IWUSR | S_IWGRP);
100
101
102struct smem_log_inst {
103 int which_log;
104 struct smem_log_item __iomem *events;
105 uint32_t __iomem *idx;
106 uint32_t num;
107 uint32_t read_idx;
108 uint32_t last_read_avail;
109 wait_queue_head_t read_wait;
110 remote_spinlock_t *remote_spinlock;
111};
112
113enum smem_logs {
114 GEN = 0,
115 STA,
116 POW,
117 NUM
118};
119
120static struct smem_log_inst inst[NUM];
121
122#if defined(CONFIG_DEBUG_FS)
123
124#define HSIZE 13
125
126struct sym {
127 uint32_t val;
128 char *str;
129 struct hlist_node node;
130};
131
132struct sym id_syms[] = {
133 { SMEM_LOG_PROC_ID_MODEM, "MODM" },
134 { SMEM_LOG_PROC_ID_Q6, "QDSP" },
135 { SMEM_LOG_PROC_ID_APPS, "APPS" },
136};
137
138struct sym base_syms[] = {
139 { SMEM_LOG_ONCRPC_EVENT_BASE, "ONCRPC" },
140 { SMEM_LOG_SMEM_EVENT_BASE, "SMEM" },
141 { SMEM_LOG_TMC_EVENT_BASE, "TMC" },
142 { SMEM_LOG_TIMETICK_EVENT_BASE, "TIMETICK" },
143 { SMEM_LOG_DEM_EVENT_BASE, "DEM" },
144 { SMEM_LOG_ERROR_EVENT_BASE, "ERROR" },
145 { SMEM_LOG_DCVS_EVENT_BASE, "DCVS" },
146 { SMEM_LOG_SLEEP_EVENT_BASE, "SLEEP" },
147 { SMEM_LOG_RPC_ROUTER_EVENT_BASE, "ROUTER" },
148};
149
150struct sym event_syms[] = {
151#if defined(CONFIG_MSM_N_WAY_SMSM)
152 { DEM_SMSM_ISR, "SMSM_ISR" },
153 { DEM_STATE_CHANGE, "STATE_CHANGE" },
154 { DEM_STATE_MACHINE_ENTER, "STATE_MACHINE_ENTER" },
155 { DEM_ENTER_SLEEP, "ENTER_SLEEP" },
156 { DEM_END_SLEEP, "END_SLEEP" },
157 { DEM_SETUP_SLEEP, "SETUP_SLEEP" },
158 { DEM_SETUP_POWER_COLLAPSE, "SETUP_POWER_COLLAPSE" },
159 { DEM_SETUP_SUSPEND, "SETUP_SUSPEND" },
160 { DEM_EARLY_EXIT, "EARLY_EXIT" },
161 { DEM_WAKEUP_REASON, "WAKEUP_REASON" },
162 { DEM_DETECT_WAKEUP, "DETECT_WAKEUP" },
163 { DEM_DETECT_RESET, "DETECT_RESET" },
164 { DEM_DETECT_SLEEPEXIT, "DETECT_SLEEPEXIT" },
165 { DEM_DETECT_RUN, "DETECT_RUN" },
166 { DEM_APPS_SWFI, "APPS_SWFI" },
167 { DEM_SEND_WAKEUP, "SEND_WAKEUP" },
168 { DEM_ASSERT_OKTS, "ASSERT_OKTS" },
169 { DEM_NEGATE_OKTS, "NEGATE_OKTS" },
170 { DEM_PROC_COMM_CMD, "PROC_COMM_CMD" },
171 { DEM_REMOVE_PROC_PWR, "REMOVE_PROC_PWR" },
172 { DEM_RESTORE_PROC_PWR, "RESTORE_PROC_PWR" },
173 { DEM_SMI_CLK_DISABLED, "SMI_CLK_DISABLED" },
174 { DEM_SMI_CLK_ENABLED, "SMI_CLK_ENABLED" },
175 { DEM_MAO_INTS, "MAO_INTS" },
176 { DEM_APPS_WAKEUP_INT, "APPS_WAKEUP_INT" },
177 { DEM_PROC_WAKEUP, "PROC_WAKEUP" },
178 { DEM_PROC_POWERUP, "PROC_POWERUP" },
179 { DEM_TIMER_EXPIRED, "TIMER_EXPIRED" },
180 { DEM_SEND_BATTERY_INFO, "SEND_BATTERY_INFO" },
181 { DEM_REMOTE_PWR_CB, "REMOTE_PWR_CB" },
182 { DEM_TIME_SYNC_START, "TIME_SYNC_START" },
183 { DEM_TIME_SYNC_SEND_VALUE, "TIME_SYNC_SEND_VALUE" },
184 { DEM_TIME_SYNC_DONE, "TIME_SYNC_DONE" },
185 { DEM_TIME_SYNC_REQUEST, "TIME_SYNC_REQUEST" },
186 { DEM_TIME_SYNC_POLL, "TIME_SYNC_POLL" },
187 { DEM_TIME_SYNC_INIT, "TIME_SYNC_INIT" },
188 { DEM_INIT, "INIT" },
189#else
190
191 { DEM_NO_SLEEP, "NO_SLEEP" },
192 { DEM_INSUF_TIME, "INSUF_TIME" },
193 { DEMAPPS_ENTER_SLEEP, "APPS_ENTER_SLEEP" },
194 { DEMAPPS_DETECT_WAKEUP, "APPS_DETECT_WAKEUP" },
195 { DEMAPPS_END_APPS_TCXO, "APPS_END_APPS_TCXO" },
196 { DEMAPPS_ENTER_SLEEPEXIT, "APPS_ENTER_SLEEPEXIT" },
197 { DEMAPPS_END_APPS_SLEEP, "APPS_END_APPS_SLEEP" },
198 { DEMAPPS_SETUP_APPS_PWRCLPS, "APPS_SETUP_APPS_PWRCLPS" },
199 { DEMAPPS_PWRCLPS_EARLY_EXIT, "APPS_PWRCLPS_EARLY_EXIT" },
200 { DEMMOD_SEND_WAKEUP, "MOD_SEND_WAKEUP" },
201 { DEMMOD_NO_APPS_VOTE, "MOD_NO_APPS_VOTE" },
202 { DEMMOD_NO_TCXO_SLEEP, "MOD_NO_TCXO_SLEEP" },
203 { DEMMOD_BT_CLOCK, "MOD_BT_CLOCK" },
204 { DEMMOD_UART_CLOCK, "MOD_UART_CLOCK" },
205 { DEMMOD_OKTS, "MOD_OKTS" },
206 { DEM_SLEEP_INFO, "SLEEP_INFO" },
207 { DEMMOD_TCXO_END, "MOD_TCXO_END" },
208 { DEMMOD_END_SLEEP_SIG, "MOD_END_SLEEP_SIG" },
209 { DEMMOD_SETUP_APPSSLEEP, "MOD_SETUP_APPSSLEEP" },
210 { DEMMOD_ENTER_TCXO, "MOD_ENTER_TCXO" },
211 { DEMMOD_WAKE_APPS, "MOD_WAKE_APPS" },
212 { DEMMOD_POWER_COLLAPSE_APPS, "MOD_POWER_COLLAPSE_APPS" },
213 { DEMMOD_RESTORE_APPS_PWR, "MOD_RESTORE_APPS_PWR" },
214 { DEMAPPS_ASSERT_OKTS, "APPS_ASSERT_OKTS" },
215 { DEMAPPS_RESTART_START_TIMER, "APPS_RESTART_START_TIMER" },
216 { DEMAPPS_ENTER_RUN, "APPS_ENTER_RUN" },
217 { DEMMOD_MAO_INTS, "MOD_MAO_INTS" },
218 { DEMMOD_POWERUP_APPS_CALLED, "MOD_POWERUP_APPS_CALLED" },
219 { DEMMOD_PC_TIMER_EXPIRED, "MOD_PC_TIMER_EXPIRED" },
220 { DEM_DETECT_SLEEPEXIT, "_DETECT_SLEEPEXIT" },
221 { DEM_DETECT_RUN, "DETECT_RUN" },
222 { DEM_SET_APPS_TIMER, "SET_APPS_TIMER" },
223 { DEM_NEGATE_OKTS, "NEGATE_OKTS" },
224 { DEMMOD_APPS_WAKEUP_INT, "MOD_APPS_WAKEUP_INT" },
225 { DEMMOD_APPS_SWFI, "MOD_APPS_SWFI" },
226 { DEM_SEND_BATTERY_INFO, "SEND_BATTERY_INFO" },
227 { DEM_SMI_CLK_DISABLED, "SMI_CLK_DISABLED" },
228 { DEM_SMI_CLK_ENABLED, "SMI_CLK_ENABLED" },
229 { DEMAPPS_SETUP_APPS_SUSPEND, "APPS_SETUP_APPS_SUSPEND" },
230 { DEM_RPC_EARLY_EXIT, "RPC_EARLY_EXIT" },
231 { DEMAPPS_WAKEUP_REASON, "APPS_WAKEUP_REASON" },
232 { DEM_INIT, "INIT" },
233#endif
234 { DEMMOD_UMTS_BASE, "MOD_UMTS_BASE" },
235 { DEMMOD_GL1_GO_TO_SLEEP, "GL1_GO_TO_SLEEP" },
236 { DEMMOD_GL1_SLEEP_START, "GL1_SLEEP_START" },
237 { DEMMOD_GL1_AFTER_GSM_CLK_ON, "GL1_AFTER_GSM_CLK_ON" },
238 { DEMMOD_GL1_BEFORE_RF_ON, "GL1_BEFORE_RF_ON" },
239 { DEMMOD_GL1_AFTER_RF_ON, "GL1_AFTER_RF_ON" },
240 { DEMMOD_GL1_FRAME_TICK, "GL1_FRAME_TICK" },
241 { DEMMOD_GL1_WCDMA_START, "GL1_WCDMA_START" },
242 { DEMMOD_GL1_WCDMA_ENDING, "GL1_WCDMA_ENDING" },
243 { DEMMOD_UMTS_NOT_OKTS, "UMTS_NOT_OKTS" },
244 { DEMMOD_UMTS_START_TCXO_SHUTDOWN, "UMTS_START_TCXO_SHUTDOWN" },
245 { DEMMOD_UMTS_END_TCXO_SHUTDOWN, "UMTS_END_TCXO_SHUTDOWN" },
246 { DEMMOD_UMTS_START_ARM_HALT, "UMTS_START_ARM_HALT" },
247 { DEMMOD_UMTS_END_ARM_HALT, "UMTS_END_ARM_HALT" },
248 { DEMMOD_UMTS_NEXT_WAKEUP_SCLK, "UMTS_NEXT_WAKEUP_SCLK" },
249 { TIME_REMOTE_LOG_EVENT_START, "START" },
250 { TIME_REMOTE_LOG_EVENT_GOTO_WAIT,
251 "GOTO_WAIT" },
252 { TIME_REMOTE_LOG_EVENT_GOTO_INIT,
253 "GOTO_INIT" },
254 { ERR_ERROR_FATAL, "ERR_ERROR_FATAL" },
255 { ERR_ERROR_FATAL_TASK, "ERR_ERROR_FATAL_TASK" },
256 { DCVSAPPS_LOG_IDLE, "DCVSAPPS_LOG_IDLE" },
257 { DCVSAPPS_LOG_ERR, "DCVSAPPS_LOG_ERR" },
258 { DCVSAPPS_LOG_CHG, "DCVSAPPS_LOG_CHG" },
259 { DCVSAPPS_LOG_REG, "DCVSAPPS_LOG_REG" },
260 { DCVSAPPS_LOG_DEREG, "DCVSAPPS_LOG_DEREG" },
261 { SMEM_LOG_EVENT_CB, "CB" },
262 { SMEM_LOG_EVENT_START, "START" },
263 { SMEM_LOG_EVENT_INIT, "INIT" },
264 { SMEM_LOG_EVENT_RUNNING, "RUNNING" },
265 { SMEM_LOG_EVENT_STOP, "STOP" },
266 { SMEM_LOG_EVENT_RESTART, "RESTART" },
267 { SMEM_LOG_EVENT_SS, "SS" },
268 { SMEM_LOG_EVENT_READ, "READ" },
269 { SMEM_LOG_EVENT_WRITE, "WRITE" },
270 { SMEM_LOG_EVENT_SIGS1, "SIGS1" },
271 { SMEM_LOG_EVENT_SIGS2, "SIGS2" },
272 { SMEM_LOG_EVENT_WRITE_DM, "WRITE_DM" },
273 { SMEM_LOG_EVENT_READ_DM, "READ_DM" },
274 { SMEM_LOG_EVENT_SKIP_DM, "SKIP_DM" },
275 { SMEM_LOG_EVENT_STOP_DM, "STOP_DM" },
276 { SMEM_LOG_EVENT_ISR, "ISR" },
277 { SMEM_LOG_EVENT_TASK, "TASK" },
278 { SMEM_LOG_EVENT_RS, "RS" },
279 { ONCRPC_LOG_EVENT_SMD_WAIT, "SMD_WAIT" },
280 { ONCRPC_LOG_EVENT_RPC_WAIT, "RPC_WAIT" },
281 { ONCRPC_LOG_EVENT_RPC_BOTH_WAIT, "RPC_BOTH_WAIT" },
282 { ONCRPC_LOG_EVENT_RPC_INIT, "RPC_INIT" },
283 { ONCRPC_LOG_EVENT_RUNNING, "RUNNING" },
284 { ONCRPC_LOG_EVENT_APIS_INITED, "APIS_INITED" },
285 { ONCRPC_LOG_EVENT_AMSS_RESET, "AMSS_RESET" },
286 { ONCRPC_LOG_EVENT_SMD_RESET, "SMD_RESET" },
287 { ONCRPC_LOG_EVENT_ONCRPC_RESET, "ONCRPC_RESET" },
288 { ONCRPC_LOG_EVENT_CB, "CB" },
289 { ONCRPC_LOG_EVENT_STD_CALL, "STD_CALL" },
290 { ONCRPC_LOG_EVENT_STD_REPLY, "STD_REPLY" },
291 { ONCRPC_LOG_EVENT_STD_CALL_ASYNC, "STD_CALL_ASYNC" },
292 { NO_SLEEP_OLD, "NO_SLEEP_OLD" },
293 { INSUF_TIME, "INSUF_TIME" },
294 { MOD_UART_CLOCK, "MOD_UART_CLOCK" },
295 { SLEEP_INFO, "SLEEP_INFO" },
296 { MOD_TCXO_END, "MOD_TCXO_END" },
297 { MOD_ENTER_TCXO, "MOD_ENTER_TCXO" },
298 { NO_SLEEP_NEW, "NO_SLEEP_NEW" },
299 { RPC_ROUTER_LOG_EVENT_UNKNOWN, "UNKNOWN" },
300 { RPC_ROUTER_LOG_EVENT_MSG_READ, "MSG_READ" },
301 { RPC_ROUTER_LOG_EVENT_MSG_WRITTEN, "MSG_WRITTEN" },
302 { RPC_ROUTER_LOG_EVENT_MSG_CFM_REQ, "MSG_CFM_REQ" },
303 { RPC_ROUTER_LOG_EVENT_MSG_CFM_SNT, "MSG_CFM_SNT" },
304 { RPC_ROUTER_LOG_EVENT_MID_READ, "MID_READ" },
305 { RPC_ROUTER_LOG_EVENT_MID_WRITTEN, "MID_WRITTEN" },
306 { RPC_ROUTER_LOG_EVENT_MID_CFM_REQ, "MID_CFM_REQ" },
307};
308
309struct sym wakeup_syms[] = {
310 { 0x00000040, "OTHER" },
311 { 0x00000020, "RESET" },
312 { 0x00000010, "ALARM" },
313 { 0x00000008, "TIMER" },
314 { 0x00000004, "GPIO" },
315 { 0x00000002, "INT" },
316 { 0x00000001, "RPC" },
317 { 0x00000000, "NONE" },
318};
319
320struct sym wakeup_int_syms[] = {
321 { 0, "MDDI_EXT" },
322 { 1, "MDDI_PRI" },
323 { 2, "MDDI_CLIENT"},
324 { 3, "USB_OTG" },
325 { 4, "I2CC" },
326 { 5, "SDC1_0" },
327 { 6, "SDC1_1" },
328 { 7, "SDC2_0" },
329 { 8, "SDC2_1" },
330 { 9, "ADSP_A9A11" },
331 { 10, "UART1" },
332 { 11, "UART2" },
333 { 12, "UART3" },
334 { 13, "DP_RX_DATA" },
335 { 14, "DP_RX_DATA2" },
336 { 15, "DP_RX_DATA3" },
337 { 16, "DM_UART" },
338 { 17, "DM_DP_RX_DATA" },
339 { 18, "KEYSENSE" },
340 { 19, "HSSD" },
341 { 20, "NAND_WR_ER_DONE" },
342 { 21, "NAND_OP_DONE" },
343 { 22, "TCHSCRN1" },
344 { 23, "TCHSCRN2" },
345 { 24, "TCHSCRN_SSBI" },
346 { 25, "USB_HS" },
347 { 26, "UART2_DM_RX" },
348 { 27, "UART2_DM" },
349 { 28, "SDC4_1" },
350 { 29, "SDC4_0" },
351 { 30, "SDC3_1" },
352 { 31, "SDC3_0" },
353};
354
355struct sym smsm_syms[] = {
356 { 0x80000000, "UN" },
357 { 0x7F000000, "ERR" },
358 { 0x00800000, "SMLP" },
359 { 0x00400000, "ADWN" },
360 { 0x00200000, "PWRS" },
361 { 0x00100000, "DWLD" },
362 { 0x00080000, "SRBT" },
363 { 0x00040000, "SDWN" },
364 { 0x00020000, "ARBT" },
365 { 0x00010000, "REL" },
366 { 0x00008000, "SLE" },
367 { 0x00004000, "SLP" },
368 { 0x00002000, "WFPI" },
369 { 0x00001000, "EEX" },
370 { 0x00000800, "TIN" },
371 { 0x00000400, "TWT" },
372 { 0x00000200, "PWRC" },
373 { 0x00000100, "RUN" },
374 { 0x00000080, "SA" },
375 { 0x00000040, "RES" },
376 { 0x00000020, "RIN" },
377 { 0x00000010, "RWT" },
378 { 0x00000008, "SIN" },
379 { 0x00000004, "SWT" },
380 { 0x00000002, "OE" },
381 { 0x00000001, "I" },
382};
383
384/* never reorder */
385struct sym voter_d2_syms[] = {
386 { 0x00000001, NULL },
387 { 0x00000002, NULL },
388 { 0x00000004, NULL },
389 { 0x00000008, NULL },
390 { 0x00000010, NULL },
391 { 0x00000020, NULL },
392 { 0x00000040, NULL },
393 { 0x00000080, NULL },
394 { 0x00000100, NULL },
395 { 0x00000200, NULL },
396 { 0x00000400, NULL },
397 { 0x00000800, NULL },
398 { 0x00001000, NULL },
399 { 0x00002000, NULL },
400 { 0x00004000, NULL },
401 { 0x00008000, NULL },
402 { 0x00010000, NULL },
403 { 0x00020000, NULL },
404 { 0x00040000, NULL },
405 { 0x00080000, NULL },
406 { 0x00100000, NULL },
407 { 0x00200000, NULL },
408 { 0x00400000, NULL },
409 { 0x00800000, NULL },
410 { 0x01000000, NULL },
411 { 0x02000000, NULL },
412 { 0x04000000, NULL },
413 { 0x08000000, NULL },
414 { 0x10000000, NULL },
415 { 0x20000000, NULL },
416 { 0x40000000, NULL },
417 { 0x80000000, NULL },
418};
419
420/* never reorder */
421struct sym voter_d3_syms[] = {
422 { 0x00000001, NULL },
423 { 0x00000002, NULL },
424 { 0x00000004, NULL },
425 { 0x00000008, NULL },
426 { 0x00000010, NULL },
427 { 0x00000020, NULL },
428 { 0x00000040, NULL },
429 { 0x00000080, NULL },
430 { 0x00000100, NULL },
431 { 0x00000200, NULL },
432 { 0x00000400, NULL },
433 { 0x00000800, NULL },
434 { 0x00001000, NULL },
435 { 0x00002000, NULL },
436 { 0x00004000, NULL },
437 { 0x00008000, NULL },
438 { 0x00010000, NULL },
439 { 0x00020000, NULL },
440 { 0x00040000, NULL },
441 { 0x00080000, NULL },
442 { 0x00100000, NULL },
443 { 0x00200000, NULL },
444 { 0x00400000, NULL },
445 { 0x00800000, NULL },
446 { 0x01000000, NULL },
447 { 0x02000000, NULL },
448 { 0x04000000, NULL },
449 { 0x08000000, NULL },
450 { 0x10000000, NULL },
451 { 0x20000000, NULL },
452 { 0x40000000, NULL },
453 { 0x80000000, NULL },
454};
455
456struct sym dem_state_master_syms[] = {
457 { 0, "INIT" },
458 { 1, "RUN" },
459 { 2, "SLEEP_WAIT" },
460 { 3, "SLEEP_CONFIRMED" },
461 { 4, "SLEEP_EXIT" },
462 { 5, "RSA" },
463 { 6, "EARLY_EXIT" },
464 { 7, "RSA_DELAYED" },
465 { 8, "RSA_CHECK_INTS" },
466 { 9, "RSA_CONFIRMED" },
467 { 10, "RSA_WAKING" },
468 { 11, "RSA_RESTORE" },
469 { 12, "RESET" },
470};
471
472struct sym dem_state_slave_syms[] = {
473 { 0, "INIT" },
474 { 1, "RUN" },
475 { 2, "SLEEP_WAIT" },
476 { 3, "SLEEP_EXIT" },
477 { 4, "SLEEP_RUN_PENDING" },
478 { 5, "POWER_COLLAPSE" },
479 { 6, "CHECK_INTERRUPTS" },
480 { 7, "SWFI" },
481 { 8, "WFPI" },
482 { 9, "EARLY_EXIT" },
483 { 10, "RESET_RECOVER" },
484 { 11, "RESET_ACKNOWLEDGE" },
485 { 12, "ERROR" },
486};
487
488struct sym smsm_entry_type_syms[] = {
489 { 0, "SMSM_APPS_STATE" },
490 { 1, "SMSM_MODEM_STATE" },
491 { 2, "SMSM_Q6_STATE" },
492 { 3, "SMSM_APPS_DEM" },
493 { 4, "SMSM_MODEM_DEM" },
494 { 5, "SMSM_Q6_DEM" },
495 { 6, "SMSM_POWER_MASTER_DEM" },
496 { 7, "SMSM_TIME_MASTER_DEM" },
497};
498
499struct sym smsm_state_syms[] = {
500 { 0x00000001, "INIT" },
501 { 0x00000002, "OSENTERED" },
502 { 0x00000004, "SMDWAIT" },
503 { 0x00000008, "SMDINIT" },
504 { 0x00000010, "RPCWAIT" },
505 { 0x00000020, "RPCINIT" },
506 { 0x00000040, "RESET" },
507 { 0x00000080, "RSA" },
508 { 0x00000100, "RUN" },
509 { 0x00000200, "PWRC" },
510 { 0x00000400, "TIMEWAIT" },
511 { 0x00000800, "TIMEINIT" },
512 { 0x00001000, "PWRC_EARLY_EXIT" },
513 { 0x00002000, "WFPI" },
514 { 0x00004000, "SLEEP" },
515 { 0x00008000, "SLEEPEXIT" },
516 { 0x00010000, "OEMSBL_RELEASE" },
517 { 0x00020000, "APPS_REBOOT" },
518 { 0x00040000, "SYSTEM_POWER_DOWN" },
519 { 0x00080000, "SYSTEM_REBOOT" },
520 { 0x00100000, "SYSTEM_DOWNLOAD" },
521 { 0x00200000, "PWRC_SUSPEND" },
522 { 0x00400000, "APPS_SHUTDOWN" },
523 { 0x00800000, "SMD_LOOPBACK" },
524 { 0x01000000, "RUN_QUIET" },
525 { 0x02000000, "MODEM_WAIT" },
526 { 0x04000000, "MODEM_BREAK" },
527 { 0x08000000, "MODEM_CONTINUE" },
528 { 0x80000000, "UNKNOWN" },
529};
530
531#define ID_SYM 0
532#define BASE_SYM 1
533#define EVENT_SYM 2
534#define WAKEUP_SYM 3
535#define WAKEUP_INT_SYM 4
536#define SMSM_SYM 5
537#define VOTER_D2_SYM 6
538#define VOTER_D3_SYM 7
539#define DEM_STATE_MASTER_SYM 8
540#define DEM_STATE_SLAVE_SYM 9
541#define SMSM_ENTRY_TYPE_SYM 10
542#define SMSM_STATE_SYM 11
543
544static struct sym_tbl {
545 struct sym *data;
546 int size;
547 struct hlist_head hlist[HSIZE];
548} tbl[] = {
549 { id_syms, ARRAY_SIZE(id_syms) },
550 { base_syms, ARRAY_SIZE(base_syms) },
551 { event_syms, ARRAY_SIZE(event_syms) },
552 { wakeup_syms, ARRAY_SIZE(wakeup_syms) },
553 { wakeup_int_syms, ARRAY_SIZE(wakeup_int_syms) },
554 { smsm_syms, ARRAY_SIZE(smsm_syms) },
555 { voter_d2_syms, ARRAY_SIZE(voter_d2_syms) },
556 { voter_d3_syms, ARRAY_SIZE(voter_d3_syms) },
557 { dem_state_master_syms, ARRAY_SIZE(dem_state_master_syms) },
558 { dem_state_slave_syms, ARRAY_SIZE(dem_state_slave_syms) },
559 { smsm_entry_type_syms, ARRAY_SIZE(smsm_entry_type_syms) },
560 { smsm_state_syms, ARRAY_SIZE(smsm_state_syms) },
561};
562
563static void find_voters(void)
564{
565 void *x, *next;
566 unsigned size;
567 int i = 0, j = 0;
568
569 x = smem_get_entry(SMEM_SLEEP_STATIC, &size);
570 next = x;
571 while (next && (next < (x + size)) &&
572 ((i + j) < (ARRAY_SIZE(voter_d3_syms) +
573 ARRAY_SIZE(voter_d2_syms)))) {
574
575 if (i < ARRAY_SIZE(voter_d3_syms)) {
576 voter_d3_syms[i].str = (char *) next;
577 i++;
578 } else if (i >= ARRAY_SIZE(voter_d3_syms) &&
579 j < ARRAY_SIZE(voter_d2_syms)) {
580 voter_d2_syms[j].str = (char *) next;
581 j++;
582 }
583
584 next += 9;
585 }
586}
587
588#define hash(val) (val % HSIZE)
589
590static void init_syms(void)
591{
592 int i;
593 int j;
594
595 for (i = 0; i < ARRAY_SIZE(tbl); ++i)
596 for (j = 0; j < HSIZE; ++j)
597 INIT_HLIST_HEAD(&tbl[i].hlist[j]);
598
599 for (i = 0; i < ARRAY_SIZE(tbl); ++i)
600 for (j = 0; j < tbl[i].size; ++j) {
601 INIT_HLIST_NODE(&tbl[i].data[j].node);
602 hlist_add_head(&tbl[i].data[j].node,
603 &tbl[i].hlist[hash(tbl[i].data[j].val)]);
604 }
605}
606
607static char *find_sym(uint32_t id, uint32_t val)
608{
609 struct hlist_node *n;
610 struct sym *s;
611
612 hlist_for_each(n, &tbl[id].hlist[hash(val)]) {
613 s = hlist_entry(n, struct sym, node);
614 if (s->val == val)
615 return s->str;
616 }
617
618 return 0;
619}
620
621#else
622static void init_syms(void) {}
623#endif
624
625static inline unsigned int read_timestamp(void)
626{
627 unsigned int tick = 0;
628
629 /* no barriers necessary as the read value is a dependency for the
630 * comparison operation so the processor shouldn't be able to
631 * reorder things
632 */
633 do {
634 tick = __raw_readl(TIMESTAMP_ADDR);
635 } while (tick != __raw_readl(TIMESTAMP_ADDR));
636
637 return tick;
638}
639
640static void smem_log_event_from_user(struct smem_log_inst *inst,
641 const char __user *buf, int size, int num)
642{
643 uint32_t idx;
644 uint32_t next_idx;
645 unsigned long flags;
646 uint32_t identifier = 0;
647 uint32_t timetick = 0;
648 int first = 1;
649 int ret;
650
651 remote_spin_lock_irqsave(inst->remote_spinlock, flags);
652
653 while (num--) {
654 idx = *inst->idx;
655
656 if (idx < inst->num) {
657 ret = copy_from_user(&inst->events[idx],
658 buf, size);
659 if (ret) {
660 printk("ERROR %s:%i tried to write "
661 "%i got ret %i",
662 __func__, __LINE__,
663 size, size - ret);
664 goto out;
665 }
666
667 if (first) {
668 identifier =
669 inst->events[idx].
670 identifier;
671 timetick = read_timestamp();
672 first = 0;
673 } else {
674 identifier |= SMEM_LOG_CONT;
675 }
676 inst->events[idx].identifier =
677 identifier;
678 inst->events[idx].timetick =
679 timetick;
680 }
681
682 next_idx = idx + 1;
683 if (next_idx >= inst->num)
684 next_idx = 0;
685 *inst->idx = next_idx;
686 buf += sizeof(struct smem_log_item);
687 }
688
689 out:
690 wmb();
691 remote_spin_unlock_irqrestore(inst->remote_spinlock, flags);
692}
693
694static void _smem_log_event(
695 struct smem_log_item __iomem *events,
696 uint32_t __iomem *_idx,
697 remote_spinlock_t *lock,
698 int num,
699 uint32_t id, uint32_t data1, uint32_t data2,
700 uint32_t data3)
701{
702 struct smem_log_item item;
703 uint32_t idx;
704 uint32_t next_idx;
705 unsigned long flags;
706
707 item.timetick = read_timestamp();
708 item.identifier = id;
709 item.data1 = data1;
710 item.data2 = data2;
711 item.data3 = data3;
712
713 remote_spin_lock_irqsave(lock, flags);
714
715 idx = *_idx;
716
717 if (idx < num) {
718 memcpy(&events[idx],
719 &item, sizeof(item));
720 }
721
722 next_idx = idx + 1;
723 if (next_idx >= num)
724 next_idx = 0;
725 *_idx = next_idx;
726 wmb();
727
728 remote_spin_unlock_irqrestore(lock, flags);
729}
730
731static void _smem_log_event6(
732 struct smem_log_item __iomem *events,
733 uint32_t __iomem *_idx,
734 remote_spinlock_t *lock,
735 int num,
736 uint32_t id, uint32_t data1, uint32_t data2,
737 uint32_t data3, uint32_t data4, uint32_t data5,
738 uint32_t data6)
739{
740 struct smem_log_item item[2];
741 uint32_t idx;
742 uint32_t next_idx;
743 unsigned long flags;
744
745 item[0].timetick = read_timestamp();
746 item[0].identifier = id;
747 item[0].data1 = data1;
748 item[0].data2 = data2;
749 item[0].data3 = data3;
750 item[1].identifier = item[0].identifier;
751 item[1].timetick = item[0].timetick;
752 item[1].data1 = data4;
753 item[1].data2 = data5;
754 item[1].data3 = data6;
755
756 remote_spin_lock_irqsave(lock, flags);
757
758 idx = *_idx;
759
760 /* FIXME: Wrap around */
761 if (idx < (num-1)) {
762 memcpy(&events[idx],
763 &item, sizeof(item));
764 }
765
766 next_idx = idx + 2;
767 if (next_idx >= num)
768 next_idx = 0;
769 *_idx = next_idx;
770
771 wmb();
772 remote_spin_unlock_irqrestore(lock, flags);
773}
774
775void smem_log_event(uint32_t id, uint32_t data1, uint32_t data2,
776 uint32_t data3)
777{
778 if (smem_log_enable)
779 _smem_log_event(inst[GEN].events, inst[GEN].idx,
780 inst[GEN].remote_spinlock,
781 SMEM_LOG_NUM_ENTRIES, id,
782 data1, data2, data3);
783}
784
785void smem_log_event6(uint32_t id, uint32_t data1, uint32_t data2,
786 uint32_t data3, uint32_t data4, uint32_t data5,
787 uint32_t data6)
788{
789 if (smem_log_enable)
790 _smem_log_event6(inst[GEN].events, inst[GEN].idx,
791 inst[GEN].remote_spinlock,
792 SMEM_LOG_NUM_ENTRIES, id,
793 data1, data2, data3, data4, data5, data6);
794}
795
796void smem_log_event_to_static(uint32_t id, uint32_t data1, uint32_t data2,
797 uint32_t data3)
798{
799 if (smem_log_enable)
800 _smem_log_event(inst[STA].events, inst[STA].idx,
801 inst[STA].remote_spinlock,
802 SMEM_LOG_NUM_STATIC_ENTRIES, id,
803 data1, data2, data3);
804}
805
806void smem_log_event6_to_static(uint32_t id, uint32_t data1, uint32_t data2,
807 uint32_t data3, uint32_t data4, uint32_t data5,
808 uint32_t data6)
809{
810 if (smem_log_enable)
811 _smem_log_event6(inst[STA].events, inst[STA].idx,
812 inst[STA].remote_spinlock,
813 SMEM_LOG_NUM_STATIC_ENTRIES, id,
814 data1, data2, data3, data4, data5, data6);
815}
816
817static int _smem_log_init(void)
818{
819 int ret;
820
821 inst[GEN].which_log = GEN;
822 inst[GEN].events =
823 (struct smem_log_item *)smem_alloc(SMEM_SMEM_LOG_EVENTS,
824 SMEM_LOG_EVENTS_SIZE);
825 inst[GEN].idx = (uint32_t *)smem_alloc(SMEM_SMEM_LOG_IDX,
826 sizeof(uint32_t));
827 if (!inst[GEN].events || !inst[GEN].idx)
828 pr_info("%s: no log or log_idx allocated\n", __func__);
829
830 inst[GEN].num = SMEM_LOG_NUM_ENTRIES;
831 inst[GEN].read_idx = 0;
832 inst[GEN].last_read_avail = SMEM_LOG_NUM_ENTRIES;
833 init_waitqueue_head(&inst[GEN].read_wait);
834 inst[GEN].remote_spinlock = &remote_spinlock;
835
836 inst[STA].which_log = STA;
837 inst[STA].events =
838 (struct smem_log_item *)
839 smem_alloc(SMEM_SMEM_STATIC_LOG_EVENTS,
840 SMEM_STATIC_LOG_EVENTS_SIZE);
841 inst[STA].idx = (uint32_t *)smem_alloc(SMEM_SMEM_STATIC_LOG_IDX,
842 sizeof(uint32_t));
843 if (!inst[STA].events || !inst[STA].idx)
844 pr_info("%s: no static log or log_idx allocated\n", __func__);
845
846 inst[STA].num = SMEM_LOG_NUM_STATIC_ENTRIES;
847 inst[STA].read_idx = 0;
848 inst[STA].last_read_avail = SMEM_LOG_NUM_ENTRIES;
849 init_waitqueue_head(&inst[STA].read_wait);
850 inst[STA].remote_spinlock = &remote_spinlock_static;
851
852 inst[POW].which_log = POW;
853 inst[POW].events =
854 (struct smem_log_item *)
855 smem_alloc(SMEM_SMEM_LOG_POWER_EVENTS,
856 SMEM_POWER_LOG_EVENTS_SIZE);
857 inst[POW].idx = (uint32_t *)smem_alloc(SMEM_SMEM_LOG_POWER_IDX,
858 sizeof(uint32_t));
859 if (!inst[POW].events || !inst[POW].idx)
860 pr_info("%s: no power log or log_idx allocated\n", __func__);
861
862 inst[POW].num = SMEM_LOG_NUM_POWER_ENTRIES;
863 inst[POW].read_idx = 0;
864 inst[POW].last_read_avail = SMEM_LOG_NUM_ENTRIES;
865 init_waitqueue_head(&inst[POW].read_wait);
866 inst[POW].remote_spinlock = &remote_spinlock;
867
868 ret = remote_spin_lock_init(&remote_spinlock,
869 SMEM_SPINLOCK_SMEM_LOG);
870 if (ret) {
871 mb();
872 return ret;
873 }
874
875 ret = remote_spin_lock_init(&remote_spinlock_static,
876 SMEM_SPINLOCK_STATIC_LOG);
877 if (ret) {
878 mb();
879 return ret;
880 }
881
882 init_syms();
883 mb();
884
885 return 0;
886}
887
888static ssize_t smem_log_read_bin(struct file *fp, char __user *buf,
889 size_t count, loff_t *pos)
890{
891 int idx;
892 int orig_idx;
893 unsigned long flags;
894 int ret;
895 int tot_bytes = 0;
Eric Holmbergcf065312011-09-09 14:00:40 -0600896 struct smem_log_inst *local_inst;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700897
Eric Holmbergcf065312011-09-09 14:00:40 -0600898 local_inst = fp->private_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700899
Eric Holmbergcf065312011-09-09 14:00:40 -0600900 remote_spin_lock_irqsave(local_inst->remote_spinlock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700901
Eric Holmbergcf065312011-09-09 14:00:40 -0600902 orig_idx = *local_inst->idx;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700903 idx = orig_idx;
904
905 while (1) {
906 idx--;
907 if (idx < 0)
Eric Holmbergcf065312011-09-09 14:00:40 -0600908 idx = local_inst->num - 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700909 if (idx == orig_idx) {
910 ret = tot_bytes;
911 break;
912 }
913
914 if ((tot_bytes + sizeof(struct smem_log_item)) > count) {
915 ret = tot_bytes;
916 break;
917 }
918
Eric Holmbergcf065312011-09-09 14:00:40 -0600919 ret = copy_to_user(buf, &local_inst->events[idx],
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700920 sizeof(struct smem_log_item));
921 if (ret) {
922 ret = -EIO;
923 break;
924 }
925
926 tot_bytes += sizeof(struct smem_log_item);
927
928 buf += sizeof(struct smem_log_item);
929 }
930
Eric Holmbergcf065312011-09-09 14:00:40 -0600931 remote_spin_unlock_irqrestore(local_inst->remote_spinlock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700932
933 return ret;
934}
935
936static ssize_t smem_log_read(struct file *fp, char __user *buf,
937 size_t count, loff_t *pos)
938{
939 char loc_buf[128];
940 int i;
941 int idx;
942 int orig_idx;
943 unsigned long flags;
944 int ret;
945 int tot_bytes = 0;
946 struct smem_log_inst *inst;
947
948 inst = fp->private_data;
949
950 remote_spin_lock_irqsave(inst->remote_spinlock, flags);
951
952 orig_idx = *inst->idx;
953 idx = orig_idx;
954
955 while (1) {
956 idx--;
957 if (idx < 0)
958 idx = inst->num - 1;
959 if (idx == orig_idx) {
960 ret = tot_bytes;
961 break;
962 }
963
964 i = scnprintf(loc_buf, 128,
965 "0x%x 0x%x 0x%x 0x%x 0x%x\n",
966 inst->events[idx].identifier,
967 inst->events[idx].timetick,
968 inst->events[idx].data1,
969 inst->events[idx].data2,
970 inst->events[idx].data3);
971 if (i == 0) {
972 ret = -EIO;
973 break;
974 }
975
976 if ((tot_bytes + i) > count) {
977 ret = tot_bytes;
978 break;
979 }
980
981 tot_bytes += i;
982
983 ret = copy_to_user(buf, loc_buf, i);
984 if (ret) {
985 ret = -EIO;
986 break;
987 }
988
989 buf += i;
990 }
991
992 remote_spin_unlock_irqrestore(inst->remote_spinlock, flags);
993
994 return ret;
995}
996
997static ssize_t smem_log_write_bin(struct file *fp, const char __user *buf,
998 size_t count, loff_t *pos)
999{
1000 if (count < sizeof(struct smem_log_item))
1001 return -EINVAL;
1002
1003 if (smem_log_enable)
1004 smem_log_event_from_user(fp->private_data, buf,
1005 sizeof(struct smem_log_item),
1006 count / sizeof(struct smem_log_item));
1007 return count;
1008}
1009
1010static ssize_t smem_log_write(struct file *fp, const char __user *buf,
1011 size_t count, loff_t *pos)
1012{
1013 int ret;
1014 const char delimiters[] = " ,;";
1015 char locbuf[256] = {0};
1016 uint32_t val[10] = {0};
1017 int vals = 0;
1018 char *token;
1019 char *running;
1020 struct smem_log_inst *inst;
1021 unsigned long res;
1022
1023 inst = fp->private_data;
1024
1025 count = count > 255 ? 255 : count;
1026
1027 if (!smem_log_enable)
1028 return count;
1029
1030 locbuf[count] = '\0';
1031
1032 ret = copy_from_user(locbuf, buf, count);
1033 if (ret != 0) {
1034 printk(KERN_ERR "ERROR: %s could not copy %i bytes\n",
1035 __func__, ret);
1036 return -EINVAL;
1037 }
1038
1039 D(KERN_ERR "%s: ", __func__);
1040 D_DUMP_BUFFER("We got", len, locbuf);
1041
1042 running = locbuf;
1043
1044 token = strsep(&running, delimiters);
1045 while (token && vals < ARRAY_SIZE(val)) {
1046 if (*token != '\0') {
1047 D(KERN_ERR "%s: ", __func__);
1048 D_DUMP_BUFFER("", strlen(token), token);
1049 ret = strict_strtoul(token, 0, &res);
1050 if (ret) {
1051 printk(KERN_ERR "ERROR: %s:%i got bad char "
1052 "at strict_strtoul\n",
1053 __func__, __LINE__-4);
1054 return -EINVAL;
1055 }
1056 val[vals++] = res;
1057 }
1058 token = strsep(&running, delimiters);
1059 }
1060
1061 if (vals > 5) {
1062 if (inst->which_log == GEN)
1063 smem_log_event6(val[0], val[2], val[3], val[4],
1064 val[7], val[8], val[9]);
1065 else if (inst->which_log == STA)
1066 smem_log_event6_to_static(val[0],
1067 val[2], val[3], val[4],
1068 val[7], val[8], val[9]);
1069 else
1070 return -1;
1071 } else {
1072 if (inst->which_log == GEN)
1073 smem_log_event(val[0], val[2], val[3], val[4]);
1074 else if (inst->which_log == STA)
1075 smem_log_event_to_static(val[0],
1076 val[2], val[3], val[4]);
1077 else
1078 return -1;
1079 }
1080
1081 return count;
1082}
1083
1084static int smem_log_open(struct inode *ip, struct file *fp)
1085{
1086 fp->private_data = &inst[GEN];
1087
1088 return 0;
1089}
1090
1091
1092static int smem_log_release(struct inode *ip, struct file *fp)
1093{
1094 return 0;
1095}
1096
1097static long smem_log_ioctl(struct file *fp, unsigned int cmd,
1098 unsigned long arg);
1099
1100static const struct file_operations smem_log_fops = {
1101 .owner = THIS_MODULE,
1102 .read = smem_log_read,
1103 .write = smem_log_write,
1104 .open = smem_log_open,
1105 .release = smem_log_release,
1106 .unlocked_ioctl = smem_log_ioctl,
1107};
1108
1109static const struct file_operations smem_log_bin_fops = {
1110 .owner = THIS_MODULE,
1111 .read = smem_log_read_bin,
1112 .write = smem_log_write_bin,
1113 .open = smem_log_open,
1114 .release = smem_log_release,
1115 .unlocked_ioctl = smem_log_ioctl,
1116};
1117
1118static long smem_log_ioctl(struct file *fp,
1119 unsigned int cmd, unsigned long arg)
1120{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001121 switch (cmd) {
1122 default:
1123 return -ENOTTY;
1124
1125 case SMIOC_SETMODE:
1126 if (arg == SMIOC_TEXT) {
1127 D("%s set text mode\n", __func__);
1128 fp->f_op = &smem_log_fops;
1129 } else if (arg == SMIOC_BINARY) {
1130 D("%s set bin mode\n", __func__);
1131 fp->f_op = &smem_log_bin_fops;
1132 } else {
1133 return -EINVAL;
1134 }
1135 break;
1136 case SMIOC_SETLOG:
Eric Holmberg391ec1b2011-09-09 14:02:22 -06001137 if (arg == SMIOC_LOG) {
1138 if (inst[GEN].events)
1139 fp->private_data = &inst[GEN];
1140 else
1141 return -ENODEV;
1142 } else if (arg == SMIOC_STATIC_LOG) {
1143 if (inst[STA].events)
1144 fp->private_data = &inst[STA];
1145 else
1146 return -ENODEV;
1147 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001148 return -EINVAL;
Eric Holmberg391ec1b2011-09-09 14:02:22 -06001149 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001150 break;
1151 }
1152
1153 return 0;
1154}
1155
1156static struct miscdevice smem_log_dev = {
1157 .minor = MISC_DYNAMIC_MINOR,
1158 .name = "smem_log",
1159 .fops = &smem_log_fops,
1160};
1161
1162#if defined(CONFIG_DEBUG_FS)
1163
1164#define SMEM_LOG_ITEM_PRINT_SIZE 160
1165
1166#define EVENTS_PRINT_SIZE \
1167(SMEM_LOG_ITEM_PRINT_SIZE * SMEM_LOG_NUM_ENTRIES)
1168
1169static uint32_t smem_log_timeout_ms;
1170module_param_named(timeout_ms, smem_log_timeout_ms,
1171 int, S_IRUGO | S_IWUSR | S_IWGRP);
1172
1173static int smem_log_debug_mask;
1174module_param_named(debug_mask, smem_log_debug_mask, int,
1175 S_IRUGO | S_IWUSR | S_IWGRP);
1176
1177#define DBG(x...) do {\
1178 if (smem_log_debug_mask) \
1179 printk(KERN_DEBUG x);\
1180 } while (0)
1181
1182static int update_read_avail(struct smem_log_inst *inst)
1183{
1184 int curr_read_avail;
1185 unsigned long flags = 0;
1186
1187 remote_spin_lock_irqsave(inst->remote_spinlock, flags);
1188
1189 curr_read_avail = (*inst->idx - inst->read_idx);
1190 if (curr_read_avail < 0)
1191 curr_read_avail = inst->num - inst->read_idx + *inst->idx;
1192
1193 DBG("%s: read = %d write = %d curr = %d last = %d\n", __func__,
1194 inst->read_idx, *inst->idx, curr_read_avail, inst->last_read_avail);
1195
1196 if (curr_read_avail < inst->last_read_avail) {
1197 if (inst->last_read_avail != inst->num)
1198 pr_info("smem_log: skipping %d log entries\n",
1199 inst->last_read_avail);
1200 inst->read_idx = *inst->idx + 1;
1201 inst->last_read_avail = inst->num - 1;
1202 } else
1203 inst->last_read_avail = curr_read_avail;
1204
1205 remote_spin_unlock_irqrestore(inst->remote_spinlock, flags);
1206
1207 DBG("%s: read = %d write = %d curr = %d last = %d\n", __func__,
1208 inst->read_idx, *inst->idx, curr_read_avail, inst->last_read_avail);
1209
1210 return inst->last_read_avail;
1211}
1212
1213static int _debug_dump(int log, char *buf, int max, uint32_t cont)
1214{
1215 unsigned int idx;
1216 int write_idx, read_avail = 0;
1217 unsigned long flags;
1218 int i = 0;
1219
1220 if (!inst[log].events)
1221 return 0;
1222
1223 if (cont && update_read_avail(&inst[log]) == 0)
1224 return 0;
1225
1226 remote_spin_lock_irqsave(inst[log].remote_spinlock, flags);
1227
1228 if (cont) {
1229 idx = inst[log].read_idx;
1230 write_idx = (inst[log].read_idx + inst[log].last_read_avail);
1231 if (write_idx >= inst[log].num)
1232 write_idx -= inst[log].num;
1233 } else {
1234 write_idx = *inst[log].idx;
1235 idx = (write_idx + 1);
1236 }
1237
1238 DBG("%s: read %d write %d idx %d num %d\n", __func__,
1239 inst[log].read_idx, write_idx, idx, inst[log].num - 1);
1240
1241 while ((max - i) > 50) {
1242 if ((inst[log].num - 1) < idx)
1243 idx = 0;
1244
1245 if (idx == write_idx)
1246 break;
1247
1248 if (inst[log].events[idx].identifier) {
1249
1250 i += scnprintf(buf + i, max - i,
1251 "%08x %08x %08x %08x %08x\n",
1252 inst[log].events[idx].identifier,
1253 inst[log].events[idx].timetick,
1254 inst[log].events[idx].data1,
1255 inst[log].events[idx].data2,
1256 inst[log].events[idx].data3);
1257 }
1258 idx++;
1259 }
1260 if (cont) {
1261 inst[log].read_idx = idx;
1262 read_avail = (write_idx - inst[log].read_idx);
1263 if (read_avail < 0)
1264 read_avail = inst->num - inst->read_idx + write_idx;
1265 inst[log].last_read_avail = read_avail;
1266 }
1267
1268 remote_spin_unlock_irqrestore(inst[log].remote_spinlock, flags);
1269
1270 DBG("%s: read %d write %d idx %d num %d\n", __func__,
1271 inst[log].read_idx, write_idx, idx, inst[log].num);
1272
1273 return i;
1274}
1275
1276static int _debug_dump_voters(char *buf, int max)
1277{
1278 int k, i = 0;
1279
1280 find_voters();
1281
1282 i += scnprintf(buf + i, max - i, "Voters:\n");
1283 for (k = 0; k < ARRAY_SIZE(voter_d3_syms); ++k)
1284 if (voter_d3_syms[k].str)
1285 i += scnprintf(buf + i, max - i, "%s ",
1286 voter_d3_syms[k].str);
1287 for (k = 0; k < ARRAY_SIZE(voter_d2_syms); ++k)
1288 if (voter_d2_syms[k].str)
1289 i += scnprintf(buf + i, max - i, "%s ",
1290 voter_d2_syms[k].str);
1291 i += scnprintf(buf + i, max - i, "\n");
1292
1293 return i;
1294}
1295
1296static int _debug_dump_sym(int log, char *buf, int max, uint32_t cont)
1297{
1298 unsigned int idx;
1299 int write_idx, read_avail = 0;
1300 unsigned long flags;
1301 int i = 0;
1302
1303 char *proc;
1304 char *sub;
1305 char *id;
1306 const char *sym = NULL;
1307
1308 uint32_t data[3];
1309
1310 uint32_t proc_val = 0;
1311 uint32_t sub_val = 0;
1312 uint32_t id_val = 0;
1313 uint32_t id_only_val = 0;
1314 uint32_t data1 = 0;
1315 uint32_t data2 = 0;
1316 uint32_t data3 = 0;
1317
1318 if (!inst[log].events)
1319 return 0;
1320
1321 find_voters();
1322
1323 if (cont && update_read_avail(&inst[log]) == 0)
1324 return 0;
1325
1326 remote_spin_lock_irqsave(inst[log].remote_spinlock, flags);
1327
1328 if (cont) {
1329 idx = inst[log].read_idx;
1330 write_idx = (inst[log].read_idx + inst[log].last_read_avail);
1331 if (write_idx >= inst[log].num)
1332 write_idx -= inst[log].num;
1333 } else {
1334 write_idx = *inst[log].idx;
1335 idx = (write_idx + 1);
1336 }
1337
1338 DBG("%s: read %d write %d idx %d num %d\n", __func__,
1339 inst[log].read_idx, write_idx, idx, inst[log].num - 1);
1340
1341 for (; (max - i) > SMEM_LOG_ITEM_PRINT_SIZE; idx++) {
1342 if (idx > (inst[log].num - 1))
1343 idx = 0;
1344
1345 if (idx == write_idx)
1346 break;
1347
1348 if (idx < inst[log].num) {
1349 if (!inst[log].events[idx].identifier)
1350 continue;
1351
1352 proc_val = PROC & inst[log].events[idx].identifier;
1353 sub_val = SUB & inst[log].events[idx].identifier;
1354 id_val = (SUB | ID) & inst[log].events[idx].identifier;
1355 id_only_val = ID & inst[log].events[idx].identifier;
1356 data1 = inst[log].events[idx].data1;
1357 data2 = inst[log].events[idx].data2;
1358 data3 = inst[log].events[idx].data3;
1359
1360 if (!(proc_val & SMEM_LOG_CONT)) {
1361 i += scnprintf(buf + i, max - i, "\n");
1362
1363 proc = find_sym(ID_SYM, proc_val);
1364
1365 if (proc)
1366 i += scnprintf(buf + i, max - i,
1367 "%4s: ", proc);
1368 else
1369 i += scnprintf(buf + i, max - i,
1370 "%04x: ",
1371 PROC &
1372 inst[log].events[idx].
1373 identifier);
1374
1375 i += scnprintf(buf + i, max - i, "%10u ",
1376 inst[log].events[idx].timetick);
1377
1378 sub = find_sym(BASE_SYM, sub_val);
1379
1380 if (sub)
1381 i += scnprintf(buf + i, max - i,
1382 "%9s: ", sub);
1383 else
1384 i += scnprintf(buf + i, max - i,
1385 "%08x: ", sub_val);
1386
1387 id = find_sym(EVENT_SYM, id_val);
1388
1389 if (id)
1390 i += scnprintf(buf + i, max - i,
1391 "%11s: ", id);
1392 else
1393 i += scnprintf(buf + i, max - i,
1394 "%08x: ", id_only_val);
1395 }
1396
1397 if ((proc_val & SMEM_LOG_CONT) &&
1398 (id_val == ONCRPC_LOG_EVENT_STD_CALL ||
1399 id_val == ONCRPC_LOG_EVENT_STD_REPLY)) {
1400 data[0] = data1;
1401 data[1] = data2;
1402 data[2] = data3;
1403 i += scnprintf(buf + i, max - i,
1404 " %.16s", (char *) data);
1405 } else if (proc_val & SMEM_LOG_CONT) {
1406 i += scnprintf(buf + i, max - i,
1407 " %08x %08x %08x",
1408 data1, data2, data3);
1409 } else if (id_val == ONCRPC_LOG_EVENT_STD_CALL) {
1410 sym = smd_rpc_get_sym(data2);
1411
1412 if (sym)
1413 i += scnprintf(buf + i, max - i,
1414 "xid:%4i %8s proc:%3i",
1415 data1, sym, data3);
1416 else
1417 i += scnprintf(buf + i, max - i,
1418 "xid:%4i %08x proc:%3i",
1419 data1, data2, data3);
1420#if defined(CONFIG_MSM_N_WAY_SMSM)
1421 } else if (id_val == DEM_STATE_CHANGE) {
1422 if (data1 == 1) {
1423 i += scnprintf(buf + i, max - i,
1424 "MASTER: ");
1425 sym = find_sym(DEM_STATE_MASTER_SYM,
1426 data2);
1427 } else if (data1 == 0) {
1428 i += scnprintf(buf + i, max - i,
1429 " SLAVE: ");
1430 sym = find_sym(DEM_STATE_SLAVE_SYM,
1431 data2);
1432 } else {
1433 i += scnprintf(buf + i, max - i,
1434 "%x: ", data1);
1435 sym = NULL;
1436 }
1437 if (sym)
1438 i += scnprintf(buf + i, max - i,
1439 "from:%s ", sym);
1440 else
1441 i += scnprintf(buf + i, max - i,
1442 "from:0x%x ", data2);
1443
1444 if (data1 == 1)
1445 sym = find_sym(DEM_STATE_MASTER_SYM,
1446 data3);
1447 else if (data1 == 0)
1448 sym = find_sym(DEM_STATE_SLAVE_SYM,
1449 data3);
1450 else
1451 sym = NULL;
1452 if (sym)
1453 i += scnprintf(buf + i, max - i,
1454 "to:%s ", sym);
1455 else
1456 i += scnprintf(buf + i, max - i,
1457 "to:0x%x ", data3);
1458
1459 } else if (id_val == DEM_STATE_MACHINE_ENTER) {
1460 i += scnprintf(buf + i, max - i,
1461 "swfi:%i timer:%i manexit:%i",
1462 data1, data2, data3);
1463
1464 } else if (id_val == DEM_TIME_SYNC_REQUEST ||
1465 id_val == DEM_TIME_SYNC_POLL ||
1466 id_val == DEM_TIME_SYNC_INIT) {
1467 sym = find_sym(SMSM_ENTRY_TYPE_SYM,
1468 data1);
1469 if (sym)
1470 i += scnprintf(buf + i, max - i,
1471 "hostid:%s", sym);
1472 else
1473 i += scnprintf(buf + i, max - i,
1474 "hostid:%x", data1);
1475
1476 } else if (id_val == DEM_TIME_SYNC_START ||
1477 id_val == DEM_TIME_SYNC_SEND_VALUE) {
1478 unsigned mask = 0x1;
1479 unsigned tmp = 0;
1480 if (id_val == DEM_TIME_SYNC_START)
1481 i += scnprintf(buf + i, max - i,
1482 "req:");
1483 else
1484 i += scnprintf(buf + i, max - i,
1485 "pol:");
1486 while (mask) {
1487 if (mask & data1) {
1488 sym = find_sym(
1489 SMSM_ENTRY_TYPE_SYM,
1490 tmp);
1491 if (sym)
1492 i += scnprintf(buf + i,
1493 max - i,
1494 "%s ",
1495 sym);
1496 else
1497 i += scnprintf(buf + i,
1498 max - i,
1499 "%i ",
1500 tmp);
1501 }
1502 mask <<= 1;
1503 tmp++;
1504 }
1505 if (id_val == DEM_TIME_SYNC_SEND_VALUE)
1506 i += scnprintf(buf + i, max - i,
1507 "tick:%x", data2);
1508 } else if (id_val == DEM_SMSM_ISR) {
1509 unsigned vals[] = {data2, data3};
1510 unsigned j;
1511 unsigned mask;
1512 unsigned tmp;
1513 unsigned once;
1514 sym = find_sym(SMSM_ENTRY_TYPE_SYM,
1515 data1);
1516 if (sym)
1517 i += scnprintf(buf + i, max - i,
1518 "%s ", sym);
1519 else
1520 i += scnprintf(buf + i, max - i,
1521 "%x ", data1);
1522
1523 for (j = 0; j < ARRAY_SIZE(vals); ++j) {
1524 i += scnprintf(buf + i, max - i, "[");
1525 mask = 0x80000000;
1526 once = 0;
1527 while (mask) {
1528 tmp = vals[j] & mask;
1529 mask >>= 1;
1530 if (!tmp)
1531 continue;
1532 sym = find_sym(SMSM_STATE_SYM,
1533 tmp);
1534
1535 if (once)
1536 i += scnprintf(buf + i,
1537 max - i,
1538 " ");
1539 if (sym)
1540 i += scnprintf(buf + i,
1541 max - i,
1542 "%s",
1543 sym);
1544 else
1545 i += scnprintf(buf + i,
1546 max - i,
1547 "0x%x",
1548 tmp);
1549 once = 1;
1550 }
1551 i += scnprintf(buf + i, max - i, "] ");
1552 }
1553#else
1554 } else if (id_val == DEMAPPS_WAKEUP_REASON) {
1555 unsigned mask = 0x80000000;
1556 unsigned tmp = 0;
1557 while (mask) {
1558 tmp = data1 & mask;
1559 mask >>= 1;
1560 if (!tmp)
1561 continue;
1562 sym = find_sym(WAKEUP_SYM, tmp);
1563 if (sym)
1564 i += scnprintf(buf + i,
1565 max - i,
1566 "%s ",
1567 sym);
1568 else
1569 i += scnprintf(buf + i,
1570 max - i,
1571 "%08x ",
1572 tmp);
1573 }
1574 i += scnprintf(buf + i, max - i,
1575 "%08x %08x", data2, data3);
1576 } else if (id_val == DEMMOD_APPS_WAKEUP_INT) {
1577 sym = find_sym(WAKEUP_INT_SYM, data1);
1578
1579 if (sym)
1580 i += scnprintf(buf + i, max - i,
1581 "%s %08x %08x",
1582 sym, data2, data3);
1583 else
1584 i += scnprintf(buf + i, max - i,
1585 "%08x %08x %08x",
1586 data1, data2, data3);
1587 } else if (id_val == DEM_NO_SLEEP ||
1588 id_val == NO_SLEEP_NEW) {
1589 unsigned vals[] = {data3, data2};
1590 unsigned j;
1591 unsigned mask;
1592 unsigned tmp;
1593 unsigned once;
1594 i += scnprintf(buf + i, max - i, "%08x ",
1595 data1);
1596 i += scnprintf(buf + i, max - i, "[");
1597 once = 0;
1598 for (j = 0; j < ARRAY_SIZE(vals); ++j) {
1599 mask = 0x00000001;
1600 while (mask) {
1601 tmp = vals[j] & mask;
1602 mask <<= 1;
1603 if (!tmp)
1604 continue;
1605 if (j == 0)
1606 sym = find_sym(
1607 VOTER_D3_SYM,
1608 tmp);
1609 else
1610 sym = find_sym(
1611 VOTER_D2_SYM,
1612 tmp);
1613
1614 if (once)
1615 i += scnprintf(buf + i,
1616 max - i,
1617 " ");
1618 if (sym)
1619 i += scnprintf(buf + i,
1620 max - i,
1621 "%s",
1622 sym);
1623 else
1624 i += scnprintf(buf + i,
1625 max - i,
1626 "%08x",
1627 tmp);
1628 once = 1;
1629 }
1630 }
1631 i += scnprintf(buf + i, max - i, "] ");
1632#endif
1633 } else if (id_val == SMEM_LOG_EVENT_CB) {
1634 unsigned vals[] = {data2, data3};
1635 unsigned j;
1636 unsigned mask;
1637 unsigned tmp;
1638 unsigned once;
1639 i += scnprintf(buf + i, max - i, "%08x ",
1640 data1);
1641 for (j = 0; j < ARRAY_SIZE(vals); ++j) {
1642 i += scnprintf(buf + i, max - i, "[");
1643 mask = 0x80000000;
1644 once = 0;
1645 while (mask) {
1646 tmp = vals[j] & mask;
1647 mask >>= 1;
1648 if (!tmp)
1649 continue;
1650 sym = find_sym(SMSM_SYM, tmp);
1651
1652 if (once)
1653 i += scnprintf(buf + i,
1654 max - i,
1655 " ");
1656 if (sym)
1657 i += scnprintf(buf + i,
1658 max - i,
1659 "%s",
1660 sym);
1661 else
1662 i += scnprintf(buf + i,
1663 max - i,
1664 "%08x",
1665 tmp);
1666 once = 1;
1667 }
1668 i += scnprintf(buf + i, max - i, "] ");
1669 }
1670 } else {
1671 i += scnprintf(buf + i, max - i,
1672 "%08x %08x %08x",
1673 data1, data2, data3);
1674 }
1675 }
1676 }
1677 if (cont) {
1678 inst[log].read_idx = idx;
1679 read_avail = (write_idx - inst[log].read_idx);
1680 if (read_avail < 0)
1681 read_avail = inst->num - inst->read_idx + write_idx;
1682 inst[log].last_read_avail = read_avail;
1683 }
1684
1685 remote_spin_unlock_irqrestore(inst[log].remote_spinlock, flags);
1686
1687 DBG("%s: read %d write %d idx %d num %d\n", __func__,
1688 inst[log].read_idx, write_idx, idx, inst[log].num);
1689
1690 return i;
1691}
1692
1693static int debug_dump(char *buf, int max, uint32_t cont)
1694{
1695 int r;
1696 while (cont) {
1697 update_read_avail(&inst[GEN]);
1698 r = wait_event_interruptible_timeout(inst[GEN].read_wait,
1699 inst[GEN].last_read_avail,
1700 smem_log_timeout_ms *
1701 HZ / 1000);
1702 DBG("%s: read available %d\n", __func__,
1703 inst[GEN].last_read_avail);
1704 if (r < 0)
1705 return 0;
1706 else if (inst[GEN].last_read_avail)
1707 break;
1708 }
1709
1710 return _debug_dump(GEN, buf, max, cont);
1711}
1712
1713static int debug_dump_sym(char *buf, int max, uint32_t cont)
1714{
1715 int r;
1716 while (cont) {
1717 update_read_avail(&inst[GEN]);
1718 r = wait_event_interruptible_timeout(inst[GEN].read_wait,
1719 inst[GEN].last_read_avail,
1720 smem_log_timeout_ms *
1721 HZ / 1000);
1722 DBG("%s: readavailable %d\n", __func__,
1723 inst[GEN].last_read_avail);
1724 if (r < 0)
1725 return 0;
1726 else if (inst[GEN].last_read_avail)
1727 break;
1728 }
1729
1730 return _debug_dump_sym(GEN, buf, max, cont);
1731}
1732
1733static int debug_dump_static(char *buf, int max, uint32_t cont)
1734{
1735 int r;
1736 while (cont) {
1737 update_read_avail(&inst[STA]);
1738 r = wait_event_interruptible_timeout(inst[STA].read_wait,
1739 inst[STA].last_read_avail,
1740 smem_log_timeout_ms *
1741 HZ / 1000);
1742 DBG("%s: readavailable %d\n", __func__,
1743 inst[STA].last_read_avail);
1744 if (r < 0)
1745 return 0;
1746 else if (inst[STA].last_read_avail)
1747 break;
1748 }
1749
1750 return _debug_dump(STA, buf, max, cont);
1751}
1752
1753static int debug_dump_static_sym(char *buf, int max, uint32_t cont)
1754{
1755 int r;
1756 while (cont) {
1757 update_read_avail(&inst[STA]);
1758 r = wait_event_interruptible_timeout(inst[STA].read_wait,
1759 inst[STA].last_read_avail,
1760 smem_log_timeout_ms *
1761 HZ / 1000);
1762 DBG("%s: readavailable %d\n", __func__,
1763 inst[STA].last_read_avail);
1764 if (r < 0)
1765 return 0;
1766 else if (inst[STA].last_read_avail)
1767 break;
1768 }
1769
1770 return _debug_dump_sym(STA, buf, max, cont);
1771}
1772
1773static int debug_dump_power(char *buf, int max, uint32_t cont)
1774{
1775 int r;
1776 while (cont) {
1777 update_read_avail(&inst[POW]);
1778 r = wait_event_interruptible_timeout(inst[POW].read_wait,
1779 inst[POW].last_read_avail,
1780 smem_log_timeout_ms *
1781 HZ / 1000);
1782 DBG("%s: readavailable %d\n", __func__,
1783 inst[POW].last_read_avail);
1784 if (r < 0)
1785 return 0;
1786 else if (inst[POW].last_read_avail)
1787 break;
1788 }
1789
1790 return _debug_dump(POW, buf, max, cont);
1791}
1792
1793static int debug_dump_power_sym(char *buf, int max, uint32_t cont)
1794{
1795 int r;
1796 while (cont) {
1797 update_read_avail(&inst[POW]);
1798 r = wait_event_interruptible_timeout(inst[POW].read_wait,
1799 inst[POW].last_read_avail,
1800 smem_log_timeout_ms *
1801 HZ / 1000);
1802 DBG("%s: readavailable %d\n", __func__,
1803 inst[POW].last_read_avail);
1804 if (r < 0)
1805 return 0;
1806 else if (inst[POW].last_read_avail)
1807 break;
1808 }
1809
1810 return _debug_dump_sym(POW, buf, max, cont);
1811}
1812
1813static int debug_dump_voters(char *buf, int max, uint32_t cont)
1814{
1815 return _debug_dump_voters(buf, max);
1816}
1817
1818static char debug_buffer[EVENTS_PRINT_SIZE];
1819
1820static ssize_t debug_read(struct file *file, char __user *buf,
1821 size_t count, loff_t *ppos)
1822{
1823 int r;
1824 static int bsize;
1825 int (*fill)(char *, int, uint32_t) = file->private_data;
1826 if (!(*ppos))
1827 bsize = fill(debug_buffer, EVENTS_PRINT_SIZE, 0);
1828 DBG("%s: count %d ppos %d\n", __func__, count, (unsigned int)*ppos);
1829 r = simple_read_from_buffer(buf, count, ppos, debug_buffer,
1830 bsize);
1831 return r;
1832}
1833
1834static ssize_t debug_read_cont(struct file *file, char __user *buf,
1835 size_t count, loff_t *ppos)
1836{
1837 int (*fill)(char *, int, uint32_t) = file->private_data;
1838 char *buffer = kmalloc(count, GFP_KERNEL);
1839 int bsize;
1840 if (!buffer)
1841 return -ENOMEM;
1842 bsize = fill(buffer, count, 1);
1843 DBG("%s: count %d bsize %d\n", __func__, count, bsize);
1844 if (copy_to_user(buf, buffer, bsize)) {
1845 kfree(buffer);
1846 return -EFAULT;
1847 }
1848 kfree(buffer);
1849 return bsize;
1850}
1851
1852static int debug_open(struct inode *inode, struct file *file)
1853{
1854 file->private_data = inode->i_private;
1855 return 0;
1856}
1857
1858static const struct file_operations debug_ops = {
1859 .read = debug_read,
1860 .open = debug_open,
1861};
1862
1863static const struct file_operations debug_ops_cont = {
1864 .read = debug_read_cont,
1865 .open = debug_open,
1866};
1867
1868static void debug_create(const char *name, mode_t mode,
1869 struct dentry *dent,
1870 int (*fill)(char *buf, int max, uint32_t cont),
1871 const struct file_operations *fops)
1872{
1873 debugfs_create_file(name, mode, dent, fill, fops);
1874}
1875
1876static void smem_log_debugfs_init(void)
1877{
1878 struct dentry *dent;
1879
1880 dent = debugfs_create_dir("smem_log", 0);
1881 if (IS_ERR(dent))
1882 return;
1883
1884 debug_create("dump", 0444, dent, debug_dump, &debug_ops);
1885 debug_create("dump_sym", 0444, dent, debug_dump_sym, &debug_ops);
1886 debug_create("dump_static", 0444, dent, debug_dump_static, &debug_ops);
1887 debug_create("dump_static_sym", 0444, dent,
1888 debug_dump_static_sym, &debug_ops);
1889 debug_create("dump_power", 0444, dent, debug_dump_power, &debug_ops);
1890 debug_create("dump_power_sym", 0444, dent,
1891 debug_dump_power_sym, &debug_ops);
1892 debug_create("dump_voters", 0444, dent,
1893 debug_dump_voters, &debug_ops);
1894
1895 debug_create("dump_cont", 0444, dent, debug_dump, &debug_ops_cont);
1896 debug_create("dump_sym_cont", 0444, dent,
1897 debug_dump_sym, &debug_ops_cont);
1898 debug_create("dump_static_cont", 0444, dent,
1899 debug_dump_static, &debug_ops_cont);
1900 debug_create("dump_static_sym_cont", 0444, dent,
1901 debug_dump_static_sym, &debug_ops_cont);
1902 debug_create("dump_power_cont", 0444, dent,
1903 debug_dump_power, &debug_ops_cont);
1904 debug_create("dump_power_sym_cont", 0444, dent,
1905 debug_dump_power_sym, &debug_ops_cont);
1906
1907 smem_log_timeout_ms = 500;
1908 smem_log_debug_mask = 0;
1909}
1910#else
1911static void smem_log_debugfs_init(void) {}
1912#endif
1913
1914static int smem_log_initialize(void)
1915{
1916 int ret;
1917
1918 ret = _smem_log_init();
1919 if (ret < 0) {
1920 pr_err("%s: init failed %d\n", __func__, ret);
1921 return ret;
1922 }
1923
1924 ret = misc_register(&smem_log_dev);
1925 if (ret < 0) {
1926 pr_err("%s: device register failed %d\n", __func__, ret);
1927 return ret;
1928 }
1929
1930 smem_log_enable = 1;
1931 smem_log_initialized = 1;
1932 smem_log_debugfs_init();
1933 return ret;
1934}
1935
1936static int modem_notifier(struct notifier_block *this,
1937 unsigned long code,
1938 void *_cmd)
1939{
1940 switch (code) {
1941 case MODEM_NOTIFIER_SMSM_INIT:
1942 if (!smem_log_initialized)
1943 smem_log_initialize();
1944 break;
1945 default:
1946 break;
1947 }
1948 return NOTIFY_DONE;
1949}
1950
1951static struct notifier_block nb = {
1952 .notifier_call = modem_notifier,
1953};
1954
1955static int __init smem_log_init(void)
1956{
1957 return modem_register_notifier(&nb);
1958}
1959
1960
1961module_init(smem_log_init);
1962
1963MODULE_DESCRIPTION("smem log");
1964MODULE_LICENSE("GPL v2");