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