blob: f0e81c5db2e90bd5996245a74091a8b9741f3b47 [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;
896 struct smem_log_inst *inst;
897
898 inst = fp->private_data;
899
900 remote_spin_lock_irqsave(inst->remote_spinlock, flags);
901
902 orig_idx = *inst->idx;
903 idx = orig_idx;
904
905 while (1) {
906 idx--;
907 if (idx < 0)
908 idx = inst->num - 1;
909 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
919 ret = copy_to_user(buf, &inst[GEN].events[idx],
920 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
931 remote_spin_unlock_irqrestore(inst->remote_spinlock, flags);
932
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{
1121 struct smem_log_inst *inst;
1122
1123 inst = fp->private_data;
1124
1125 switch (cmd) {
1126 default:
1127 return -ENOTTY;
1128
1129 case SMIOC_SETMODE:
1130 if (arg == SMIOC_TEXT) {
1131 D("%s set text mode\n", __func__);
1132 fp->f_op = &smem_log_fops;
1133 } else if (arg == SMIOC_BINARY) {
1134 D("%s set bin mode\n", __func__);
1135 fp->f_op = &smem_log_bin_fops;
1136 } else {
1137 return -EINVAL;
1138 }
1139 break;
1140 case SMIOC_SETLOG:
1141 if (arg == SMIOC_LOG)
1142 fp->private_data = &inst[GEN];
1143 else if (arg == SMIOC_STATIC_LOG)
1144 fp->private_data = &inst[STA];
1145 else
1146 return -EINVAL;
1147 break;
1148 }
1149
1150 return 0;
1151}
1152
1153static struct miscdevice smem_log_dev = {
1154 .minor = MISC_DYNAMIC_MINOR,
1155 .name = "smem_log",
1156 .fops = &smem_log_fops,
1157};
1158
1159#if defined(CONFIG_DEBUG_FS)
1160
1161#define SMEM_LOG_ITEM_PRINT_SIZE 160
1162
1163#define EVENTS_PRINT_SIZE \
1164(SMEM_LOG_ITEM_PRINT_SIZE * SMEM_LOG_NUM_ENTRIES)
1165
1166static uint32_t smem_log_timeout_ms;
1167module_param_named(timeout_ms, smem_log_timeout_ms,
1168 int, S_IRUGO | S_IWUSR | S_IWGRP);
1169
1170static int smem_log_debug_mask;
1171module_param_named(debug_mask, smem_log_debug_mask, int,
1172 S_IRUGO | S_IWUSR | S_IWGRP);
1173
1174#define DBG(x...) do {\
1175 if (smem_log_debug_mask) \
1176 printk(KERN_DEBUG x);\
1177 } while (0)
1178
1179static int update_read_avail(struct smem_log_inst *inst)
1180{
1181 int curr_read_avail;
1182 unsigned long flags = 0;
1183
1184 remote_spin_lock_irqsave(inst->remote_spinlock, flags);
1185
1186 curr_read_avail = (*inst->idx - inst->read_idx);
1187 if (curr_read_avail < 0)
1188 curr_read_avail = inst->num - inst->read_idx + *inst->idx;
1189
1190 DBG("%s: read = %d write = %d curr = %d last = %d\n", __func__,
1191 inst->read_idx, *inst->idx, curr_read_avail, inst->last_read_avail);
1192
1193 if (curr_read_avail < inst->last_read_avail) {
1194 if (inst->last_read_avail != inst->num)
1195 pr_info("smem_log: skipping %d log entries\n",
1196 inst->last_read_avail);
1197 inst->read_idx = *inst->idx + 1;
1198 inst->last_read_avail = inst->num - 1;
1199 } else
1200 inst->last_read_avail = curr_read_avail;
1201
1202 remote_spin_unlock_irqrestore(inst->remote_spinlock, flags);
1203
1204 DBG("%s: read = %d write = %d curr = %d last = %d\n", __func__,
1205 inst->read_idx, *inst->idx, curr_read_avail, inst->last_read_avail);
1206
1207 return inst->last_read_avail;
1208}
1209
1210static int _debug_dump(int log, char *buf, int max, uint32_t cont)
1211{
1212 unsigned int idx;
1213 int write_idx, read_avail = 0;
1214 unsigned long flags;
1215 int i = 0;
1216
1217 if (!inst[log].events)
1218 return 0;
1219
1220 if (cont && update_read_avail(&inst[log]) == 0)
1221 return 0;
1222
1223 remote_spin_lock_irqsave(inst[log].remote_spinlock, flags);
1224
1225 if (cont) {
1226 idx = inst[log].read_idx;
1227 write_idx = (inst[log].read_idx + inst[log].last_read_avail);
1228 if (write_idx >= inst[log].num)
1229 write_idx -= inst[log].num;
1230 } else {
1231 write_idx = *inst[log].idx;
1232 idx = (write_idx + 1);
1233 }
1234
1235 DBG("%s: read %d write %d idx %d num %d\n", __func__,
1236 inst[log].read_idx, write_idx, idx, inst[log].num - 1);
1237
1238 while ((max - i) > 50) {
1239 if ((inst[log].num - 1) < idx)
1240 idx = 0;
1241
1242 if (idx == write_idx)
1243 break;
1244
1245 if (inst[log].events[idx].identifier) {
1246
1247 i += scnprintf(buf + i, max - i,
1248 "%08x %08x %08x %08x %08x\n",
1249 inst[log].events[idx].identifier,
1250 inst[log].events[idx].timetick,
1251 inst[log].events[idx].data1,
1252 inst[log].events[idx].data2,
1253 inst[log].events[idx].data3);
1254 }
1255 idx++;
1256 }
1257 if (cont) {
1258 inst[log].read_idx = idx;
1259 read_avail = (write_idx - inst[log].read_idx);
1260 if (read_avail < 0)
1261 read_avail = inst->num - inst->read_idx + write_idx;
1262 inst[log].last_read_avail = read_avail;
1263 }
1264
1265 remote_spin_unlock_irqrestore(inst[log].remote_spinlock, flags);
1266
1267 DBG("%s: read %d write %d idx %d num %d\n", __func__,
1268 inst[log].read_idx, write_idx, idx, inst[log].num);
1269
1270 return i;
1271}
1272
1273static int _debug_dump_voters(char *buf, int max)
1274{
1275 int k, i = 0;
1276
1277 find_voters();
1278
1279 i += scnprintf(buf + i, max - i, "Voters:\n");
1280 for (k = 0; k < ARRAY_SIZE(voter_d3_syms); ++k)
1281 if (voter_d3_syms[k].str)
1282 i += scnprintf(buf + i, max - i, "%s ",
1283 voter_d3_syms[k].str);
1284 for (k = 0; k < ARRAY_SIZE(voter_d2_syms); ++k)
1285 if (voter_d2_syms[k].str)
1286 i += scnprintf(buf + i, max - i, "%s ",
1287 voter_d2_syms[k].str);
1288 i += scnprintf(buf + i, max - i, "\n");
1289
1290 return i;
1291}
1292
1293static int _debug_dump_sym(int log, char *buf, int max, uint32_t cont)
1294{
1295 unsigned int idx;
1296 int write_idx, read_avail = 0;
1297 unsigned long flags;
1298 int i = 0;
1299
1300 char *proc;
1301 char *sub;
1302 char *id;
1303 const char *sym = NULL;
1304
1305 uint32_t data[3];
1306
1307 uint32_t proc_val = 0;
1308 uint32_t sub_val = 0;
1309 uint32_t id_val = 0;
1310 uint32_t id_only_val = 0;
1311 uint32_t data1 = 0;
1312 uint32_t data2 = 0;
1313 uint32_t data3 = 0;
1314
1315 if (!inst[log].events)
1316 return 0;
1317
1318 find_voters();
1319
1320 if (cont && update_read_avail(&inst[log]) == 0)
1321 return 0;
1322
1323 remote_spin_lock_irqsave(inst[log].remote_spinlock, flags);
1324
1325 if (cont) {
1326 idx = inst[log].read_idx;
1327 write_idx = (inst[log].read_idx + inst[log].last_read_avail);
1328 if (write_idx >= inst[log].num)
1329 write_idx -= inst[log].num;
1330 } else {
1331 write_idx = *inst[log].idx;
1332 idx = (write_idx + 1);
1333 }
1334
1335 DBG("%s: read %d write %d idx %d num %d\n", __func__,
1336 inst[log].read_idx, write_idx, idx, inst[log].num - 1);
1337
1338 for (; (max - i) > SMEM_LOG_ITEM_PRINT_SIZE; idx++) {
1339 if (idx > (inst[log].num - 1))
1340 idx = 0;
1341
1342 if (idx == write_idx)
1343 break;
1344
1345 if (idx < inst[log].num) {
1346 if (!inst[log].events[idx].identifier)
1347 continue;
1348
1349 proc_val = PROC & inst[log].events[idx].identifier;
1350 sub_val = SUB & inst[log].events[idx].identifier;
1351 id_val = (SUB | ID) & inst[log].events[idx].identifier;
1352 id_only_val = ID & inst[log].events[idx].identifier;
1353 data1 = inst[log].events[idx].data1;
1354 data2 = inst[log].events[idx].data2;
1355 data3 = inst[log].events[idx].data3;
1356
1357 if (!(proc_val & SMEM_LOG_CONT)) {
1358 i += scnprintf(buf + i, max - i, "\n");
1359
1360 proc = find_sym(ID_SYM, proc_val);
1361
1362 if (proc)
1363 i += scnprintf(buf + i, max - i,
1364 "%4s: ", proc);
1365 else
1366 i += scnprintf(buf + i, max - i,
1367 "%04x: ",
1368 PROC &
1369 inst[log].events[idx].
1370 identifier);
1371
1372 i += scnprintf(buf + i, max - i, "%10u ",
1373 inst[log].events[idx].timetick);
1374
1375 sub = find_sym(BASE_SYM, sub_val);
1376
1377 if (sub)
1378 i += scnprintf(buf + i, max - i,
1379 "%9s: ", sub);
1380 else
1381 i += scnprintf(buf + i, max - i,
1382 "%08x: ", sub_val);
1383
1384 id = find_sym(EVENT_SYM, id_val);
1385
1386 if (id)
1387 i += scnprintf(buf + i, max - i,
1388 "%11s: ", id);
1389 else
1390 i += scnprintf(buf + i, max - i,
1391 "%08x: ", id_only_val);
1392 }
1393
1394 if ((proc_val & SMEM_LOG_CONT) &&
1395 (id_val == ONCRPC_LOG_EVENT_STD_CALL ||
1396 id_val == ONCRPC_LOG_EVENT_STD_REPLY)) {
1397 data[0] = data1;
1398 data[1] = data2;
1399 data[2] = data3;
1400 i += scnprintf(buf + i, max - i,
1401 " %.16s", (char *) data);
1402 } else if (proc_val & SMEM_LOG_CONT) {
1403 i += scnprintf(buf + i, max - i,
1404 " %08x %08x %08x",
1405 data1, data2, data3);
1406 } else if (id_val == ONCRPC_LOG_EVENT_STD_CALL) {
1407 sym = smd_rpc_get_sym(data2);
1408
1409 if (sym)
1410 i += scnprintf(buf + i, max - i,
1411 "xid:%4i %8s proc:%3i",
1412 data1, sym, data3);
1413 else
1414 i += scnprintf(buf + i, max - i,
1415 "xid:%4i %08x proc:%3i",
1416 data1, data2, data3);
1417#if defined(CONFIG_MSM_N_WAY_SMSM)
1418 } else if (id_val == DEM_STATE_CHANGE) {
1419 if (data1 == 1) {
1420 i += scnprintf(buf + i, max - i,
1421 "MASTER: ");
1422 sym = find_sym(DEM_STATE_MASTER_SYM,
1423 data2);
1424 } else if (data1 == 0) {
1425 i += scnprintf(buf + i, max - i,
1426 " SLAVE: ");
1427 sym = find_sym(DEM_STATE_SLAVE_SYM,
1428 data2);
1429 } else {
1430 i += scnprintf(buf + i, max - i,
1431 "%x: ", data1);
1432 sym = NULL;
1433 }
1434 if (sym)
1435 i += scnprintf(buf + i, max - i,
1436 "from:%s ", sym);
1437 else
1438 i += scnprintf(buf + i, max - i,
1439 "from:0x%x ", data2);
1440
1441 if (data1 == 1)
1442 sym = find_sym(DEM_STATE_MASTER_SYM,
1443 data3);
1444 else if (data1 == 0)
1445 sym = find_sym(DEM_STATE_SLAVE_SYM,
1446 data3);
1447 else
1448 sym = NULL;
1449 if (sym)
1450 i += scnprintf(buf + i, max - i,
1451 "to:%s ", sym);
1452 else
1453 i += scnprintf(buf + i, max - i,
1454 "to:0x%x ", data3);
1455
1456 } else if (id_val == DEM_STATE_MACHINE_ENTER) {
1457 i += scnprintf(buf + i, max - i,
1458 "swfi:%i timer:%i manexit:%i",
1459 data1, data2, data3);
1460
1461 } else if (id_val == DEM_TIME_SYNC_REQUEST ||
1462 id_val == DEM_TIME_SYNC_POLL ||
1463 id_val == DEM_TIME_SYNC_INIT) {
1464 sym = find_sym(SMSM_ENTRY_TYPE_SYM,
1465 data1);
1466 if (sym)
1467 i += scnprintf(buf + i, max - i,
1468 "hostid:%s", sym);
1469 else
1470 i += scnprintf(buf + i, max - i,
1471 "hostid:%x", data1);
1472
1473 } else if (id_val == DEM_TIME_SYNC_START ||
1474 id_val == DEM_TIME_SYNC_SEND_VALUE) {
1475 unsigned mask = 0x1;
1476 unsigned tmp = 0;
1477 if (id_val == DEM_TIME_SYNC_START)
1478 i += scnprintf(buf + i, max - i,
1479 "req:");
1480 else
1481 i += scnprintf(buf + i, max - i,
1482 "pol:");
1483 while (mask) {
1484 if (mask & data1) {
1485 sym = find_sym(
1486 SMSM_ENTRY_TYPE_SYM,
1487 tmp);
1488 if (sym)
1489 i += scnprintf(buf + i,
1490 max - i,
1491 "%s ",
1492 sym);
1493 else
1494 i += scnprintf(buf + i,
1495 max - i,
1496 "%i ",
1497 tmp);
1498 }
1499 mask <<= 1;
1500 tmp++;
1501 }
1502 if (id_val == DEM_TIME_SYNC_SEND_VALUE)
1503 i += scnprintf(buf + i, max - i,
1504 "tick:%x", data2);
1505 } else if (id_val == DEM_SMSM_ISR) {
1506 unsigned vals[] = {data2, data3};
1507 unsigned j;
1508 unsigned mask;
1509 unsigned tmp;
1510 unsigned once;
1511 sym = find_sym(SMSM_ENTRY_TYPE_SYM,
1512 data1);
1513 if (sym)
1514 i += scnprintf(buf + i, max - i,
1515 "%s ", sym);
1516 else
1517 i += scnprintf(buf + i, max - i,
1518 "%x ", data1);
1519
1520 for (j = 0; j < ARRAY_SIZE(vals); ++j) {
1521 i += scnprintf(buf + i, max - i, "[");
1522 mask = 0x80000000;
1523 once = 0;
1524 while (mask) {
1525 tmp = vals[j] & mask;
1526 mask >>= 1;
1527 if (!tmp)
1528 continue;
1529 sym = find_sym(SMSM_STATE_SYM,
1530 tmp);
1531
1532 if (once)
1533 i += scnprintf(buf + i,
1534 max - i,
1535 " ");
1536 if (sym)
1537 i += scnprintf(buf + i,
1538 max - i,
1539 "%s",
1540 sym);
1541 else
1542 i += scnprintf(buf + i,
1543 max - i,
1544 "0x%x",
1545 tmp);
1546 once = 1;
1547 }
1548 i += scnprintf(buf + i, max - i, "] ");
1549 }
1550#else
1551 } else if (id_val == DEMAPPS_WAKEUP_REASON) {
1552 unsigned mask = 0x80000000;
1553 unsigned tmp = 0;
1554 while (mask) {
1555 tmp = data1 & mask;
1556 mask >>= 1;
1557 if (!tmp)
1558 continue;
1559 sym = find_sym(WAKEUP_SYM, tmp);
1560 if (sym)
1561 i += scnprintf(buf + i,
1562 max - i,
1563 "%s ",
1564 sym);
1565 else
1566 i += scnprintf(buf + i,
1567 max - i,
1568 "%08x ",
1569 tmp);
1570 }
1571 i += scnprintf(buf + i, max - i,
1572 "%08x %08x", data2, data3);
1573 } else if (id_val == DEMMOD_APPS_WAKEUP_INT) {
1574 sym = find_sym(WAKEUP_INT_SYM, data1);
1575
1576 if (sym)
1577 i += scnprintf(buf + i, max - i,
1578 "%s %08x %08x",
1579 sym, data2, data3);
1580 else
1581 i += scnprintf(buf + i, max - i,
1582 "%08x %08x %08x",
1583 data1, data2, data3);
1584 } else if (id_val == DEM_NO_SLEEP ||
1585 id_val == NO_SLEEP_NEW) {
1586 unsigned vals[] = {data3, data2};
1587 unsigned j;
1588 unsigned mask;
1589 unsigned tmp;
1590 unsigned once;
1591 i += scnprintf(buf + i, max - i, "%08x ",
1592 data1);
1593 i += scnprintf(buf + i, max - i, "[");
1594 once = 0;
1595 for (j = 0; j < ARRAY_SIZE(vals); ++j) {
1596 mask = 0x00000001;
1597 while (mask) {
1598 tmp = vals[j] & mask;
1599 mask <<= 1;
1600 if (!tmp)
1601 continue;
1602 if (j == 0)
1603 sym = find_sym(
1604 VOTER_D3_SYM,
1605 tmp);
1606 else
1607 sym = find_sym(
1608 VOTER_D2_SYM,
1609 tmp);
1610
1611 if (once)
1612 i += scnprintf(buf + i,
1613 max - i,
1614 " ");
1615 if (sym)
1616 i += scnprintf(buf + i,
1617 max - i,
1618 "%s",
1619 sym);
1620 else
1621 i += scnprintf(buf + i,
1622 max - i,
1623 "%08x",
1624 tmp);
1625 once = 1;
1626 }
1627 }
1628 i += scnprintf(buf + i, max - i, "] ");
1629#endif
1630 } else if (id_val == SMEM_LOG_EVENT_CB) {
1631 unsigned vals[] = {data2, data3};
1632 unsigned j;
1633 unsigned mask;
1634 unsigned tmp;
1635 unsigned once;
1636 i += scnprintf(buf + i, max - i, "%08x ",
1637 data1);
1638 for (j = 0; j < ARRAY_SIZE(vals); ++j) {
1639 i += scnprintf(buf + i, max - i, "[");
1640 mask = 0x80000000;
1641 once = 0;
1642 while (mask) {
1643 tmp = vals[j] & mask;
1644 mask >>= 1;
1645 if (!tmp)
1646 continue;
1647 sym = find_sym(SMSM_SYM, tmp);
1648
1649 if (once)
1650 i += scnprintf(buf + i,
1651 max - i,
1652 " ");
1653 if (sym)
1654 i += scnprintf(buf + i,
1655 max - i,
1656 "%s",
1657 sym);
1658 else
1659 i += scnprintf(buf + i,
1660 max - i,
1661 "%08x",
1662 tmp);
1663 once = 1;
1664 }
1665 i += scnprintf(buf + i, max - i, "] ");
1666 }
1667 } else {
1668 i += scnprintf(buf + i, max - i,
1669 "%08x %08x %08x",
1670 data1, data2, data3);
1671 }
1672 }
1673 }
1674 if (cont) {
1675 inst[log].read_idx = idx;
1676 read_avail = (write_idx - inst[log].read_idx);
1677 if (read_avail < 0)
1678 read_avail = inst->num - inst->read_idx + write_idx;
1679 inst[log].last_read_avail = read_avail;
1680 }
1681
1682 remote_spin_unlock_irqrestore(inst[log].remote_spinlock, flags);
1683
1684 DBG("%s: read %d write %d idx %d num %d\n", __func__,
1685 inst[log].read_idx, write_idx, idx, inst[log].num);
1686
1687 return i;
1688}
1689
1690static int debug_dump(char *buf, int max, uint32_t cont)
1691{
1692 int r;
1693 while (cont) {
1694 update_read_avail(&inst[GEN]);
1695 r = wait_event_interruptible_timeout(inst[GEN].read_wait,
1696 inst[GEN].last_read_avail,
1697 smem_log_timeout_ms *
1698 HZ / 1000);
1699 DBG("%s: read available %d\n", __func__,
1700 inst[GEN].last_read_avail);
1701 if (r < 0)
1702 return 0;
1703 else if (inst[GEN].last_read_avail)
1704 break;
1705 }
1706
1707 return _debug_dump(GEN, buf, max, cont);
1708}
1709
1710static int debug_dump_sym(char *buf, int max, uint32_t cont)
1711{
1712 int r;
1713 while (cont) {
1714 update_read_avail(&inst[GEN]);
1715 r = wait_event_interruptible_timeout(inst[GEN].read_wait,
1716 inst[GEN].last_read_avail,
1717 smem_log_timeout_ms *
1718 HZ / 1000);
1719 DBG("%s: readavailable %d\n", __func__,
1720 inst[GEN].last_read_avail);
1721 if (r < 0)
1722 return 0;
1723 else if (inst[GEN].last_read_avail)
1724 break;
1725 }
1726
1727 return _debug_dump_sym(GEN, buf, max, cont);
1728}
1729
1730static int debug_dump_static(char *buf, int max, uint32_t cont)
1731{
1732 int r;
1733 while (cont) {
1734 update_read_avail(&inst[STA]);
1735 r = wait_event_interruptible_timeout(inst[STA].read_wait,
1736 inst[STA].last_read_avail,
1737 smem_log_timeout_ms *
1738 HZ / 1000);
1739 DBG("%s: readavailable %d\n", __func__,
1740 inst[STA].last_read_avail);
1741 if (r < 0)
1742 return 0;
1743 else if (inst[STA].last_read_avail)
1744 break;
1745 }
1746
1747 return _debug_dump(STA, buf, max, cont);
1748}
1749
1750static int debug_dump_static_sym(char *buf, int max, uint32_t cont)
1751{
1752 int r;
1753 while (cont) {
1754 update_read_avail(&inst[STA]);
1755 r = wait_event_interruptible_timeout(inst[STA].read_wait,
1756 inst[STA].last_read_avail,
1757 smem_log_timeout_ms *
1758 HZ / 1000);
1759 DBG("%s: readavailable %d\n", __func__,
1760 inst[STA].last_read_avail);
1761 if (r < 0)
1762 return 0;
1763 else if (inst[STA].last_read_avail)
1764 break;
1765 }
1766
1767 return _debug_dump_sym(STA, buf, max, cont);
1768}
1769
1770static int debug_dump_power(char *buf, int max, uint32_t cont)
1771{
1772 int r;
1773 while (cont) {
1774 update_read_avail(&inst[POW]);
1775 r = wait_event_interruptible_timeout(inst[POW].read_wait,
1776 inst[POW].last_read_avail,
1777 smem_log_timeout_ms *
1778 HZ / 1000);
1779 DBG("%s: readavailable %d\n", __func__,
1780 inst[POW].last_read_avail);
1781 if (r < 0)
1782 return 0;
1783 else if (inst[POW].last_read_avail)
1784 break;
1785 }
1786
1787 return _debug_dump(POW, buf, max, cont);
1788}
1789
1790static int debug_dump_power_sym(char *buf, int max, uint32_t cont)
1791{
1792 int r;
1793 while (cont) {
1794 update_read_avail(&inst[POW]);
1795 r = wait_event_interruptible_timeout(inst[POW].read_wait,
1796 inst[POW].last_read_avail,
1797 smem_log_timeout_ms *
1798 HZ / 1000);
1799 DBG("%s: readavailable %d\n", __func__,
1800 inst[POW].last_read_avail);
1801 if (r < 0)
1802 return 0;
1803 else if (inst[POW].last_read_avail)
1804 break;
1805 }
1806
1807 return _debug_dump_sym(POW, buf, max, cont);
1808}
1809
1810static int debug_dump_voters(char *buf, int max, uint32_t cont)
1811{
1812 return _debug_dump_voters(buf, max);
1813}
1814
1815static char debug_buffer[EVENTS_PRINT_SIZE];
1816
1817static ssize_t debug_read(struct file *file, char __user *buf,
1818 size_t count, loff_t *ppos)
1819{
1820 int r;
1821 static int bsize;
1822 int (*fill)(char *, int, uint32_t) = file->private_data;
1823 if (!(*ppos))
1824 bsize = fill(debug_buffer, EVENTS_PRINT_SIZE, 0);
1825 DBG("%s: count %d ppos %d\n", __func__, count, (unsigned int)*ppos);
1826 r = simple_read_from_buffer(buf, count, ppos, debug_buffer,
1827 bsize);
1828 return r;
1829}
1830
1831static ssize_t debug_read_cont(struct file *file, char __user *buf,
1832 size_t count, loff_t *ppos)
1833{
1834 int (*fill)(char *, int, uint32_t) = file->private_data;
1835 char *buffer = kmalloc(count, GFP_KERNEL);
1836 int bsize;
1837 if (!buffer)
1838 return -ENOMEM;
1839 bsize = fill(buffer, count, 1);
1840 DBG("%s: count %d bsize %d\n", __func__, count, bsize);
1841 if (copy_to_user(buf, buffer, bsize)) {
1842 kfree(buffer);
1843 return -EFAULT;
1844 }
1845 kfree(buffer);
1846 return bsize;
1847}
1848
1849static int debug_open(struct inode *inode, struct file *file)
1850{
1851 file->private_data = inode->i_private;
1852 return 0;
1853}
1854
1855static const struct file_operations debug_ops = {
1856 .read = debug_read,
1857 .open = debug_open,
1858};
1859
1860static const struct file_operations debug_ops_cont = {
1861 .read = debug_read_cont,
1862 .open = debug_open,
1863};
1864
1865static void debug_create(const char *name, mode_t mode,
1866 struct dentry *dent,
1867 int (*fill)(char *buf, int max, uint32_t cont),
1868 const struct file_operations *fops)
1869{
1870 debugfs_create_file(name, mode, dent, fill, fops);
1871}
1872
1873static void smem_log_debugfs_init(void)
1874{
1875 struct dentry *dent;
1876
1877 dent = debugfs_create_dir("smem_log", 0);
1878 if (IS_ERR(dent))
1879 return;
1880
1881 debug_create("dump", 0444, dent, debug_dump, &debug_ops);
1882 debug_create("dump_sym", 0444, dent, debug_dump_sym, &debug_ops);
1883 debug_create("dump_static", 0444, dent, debug_dump_static, &debug_ops);
1884 debug_create("dump_static_sym", 0444, dent,
1885 debug_dump_static_sym, &debug_ops);
1886 debug_create("dump_power", 0444, dent, debug_dump_power, &debug_ops);
1887 debug_create("dump_power_sym", 0444, dent,
1888 debug_dump_power_sym, &debug_ops);
1889 debug_create("dump_voters", 0444, dent,
1890 debug_dump_voters, &debug_ops);
1891
1892 debug_create("dump_cont", 0444, dent, debug_dump, &debug_ops_cont);
1893 debug_create("dump_sym_cont", 0444, dent,
1894 debug_dump_sym, &debug_ops_cont);
1895 debug_create("dump_static_cont", 0444, dent,
1896 debug_dump_static, &debug_ops_cont);
1897 debug_create("dump_static_sym_cont", 0444, dent,
1898 debug_dump_static_sym, &debug_ops_cont);
1899 debug_create("dump_power_cont", 0444, dent,
1900 debug_dump_power, &debug_ops_cont);
1901 debug_create("dump_power_sym_cont", 0444, dent,
1902 debug_dump_power_sym, &debug_ops_cont);
1903
1904 smem_log_timeout_ms = 500;
1905 smem_log_debug_mask = 0;
1906}
1907#else
1908static void smem_log_debugfs_init(void) {}
1909#endif
1910
1911static int smem_log_initialize(void)
1912{
1913 int ret;
1914
1915 ret = _smem_log_init();
1916 if (ret < 0) {
1917 pr_err("%s: init failed %d\n", __func__, ret);
1918 return ret;
1919 }
1920
1921 ret = misc_register(&smem_log_dev);
1922 if (ret < 0) {
1923 pr_err("%s: device register failed %d\n", __func__, ret);
1924 return ret;
1925 }
1926
1927 smem_log_enable = 1;
1928 smem_log_initialized = 1;
1929 smem_log_debugfs_init();
1930 return ret;
1931}
1932
1933static int modem_notifier(struct notifier_block *this,
1934 unsigned long code,
1935 void *_cmd)
1936{
1937 switch (code) {
1938 case MODEM_NOTIFIER_SMSM_INIT:
1939 if (!smem_log_initialized)
1940 smem_log_initialize();
1941 break;
1942 default:
1943 break;
1944 }
1945 return NOTIFY_DONE;
1946}
1947
1948static struct notifier_block nb = {
1949 .notifier_call = modem_notifier,
1950};
1951
1952static int __init smem_log_init(void)
1953{
1954 return modem_register_notifier(&nb);
1955}
1956
1957
1958module_init(smem_log_init);
1959
1960MODULE_DESCRIPTION("smem log");
1961MODULE_LICENSE("GPL v2");