]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/dsp/mblog.c
ARM: OMAP: DSPGW: mailbox log cleanup
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / dsp / mblog.c
1 /*
2  * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
3  *
4  * Copyright (C) 2003-2006 Nokia Corporation. All rights reserved.
5  *
6  * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23
24 #include <linux/platform_device.h>
25 #include <linux/init.h>
26 #include <asm/arch/mailbox.h>
27 #include "dsp_mbcmd.h"
28 #include "dsp.h"
29
30 char *subcmd_name(struct mbcmd *mb)
31 {
32         u8 cmd_h = mb->cmd_h;
33         u8 cmd_l = mb->cmd_l;
34         char *s;
35
36         switch (cmd_h) {
37         case MBOX_CMD_DSP_RUNLEVEL:
38                 s = (cmd_l == RUNLEVEL_USER)     ? "USER":
39                     (cmd_l == RUNLEVEL_SUPER)    ? "SUPER":
40                     (cmd_l == RUNLEVEL_RECOVERY) ? "RECOVERY":
41                     NULL;
42                 break;
43         case MBOX_CMD_DSP_PM:
44                 s = (cmd_l == PM_DISABLE) ? "DISABLE":
45                     (cmd_l == PM_ENABLE)  ? "ENABLE":
46                     NULL;
47                 break;
48         case MBOX_CMD_DSP_KFUNC:
49                 s = (cmd_l == KFUNC_FBCTL) ? "FBCTL":
50                     NULL;
51                 break;
52         case MBOX_CMD_DSP_DSPCFG:
53                 {
54                         u8 cfgc = cmd_l & 0x7f;
55                         s = (cfgc == DSPCFG_REQ)     ? "REQ":
56                             (cfgc == DSPCFG_SYSADRH) ? "SYSADRH":
57                             (cfgc == DSPCFG_SYSADRL) ? "SYSADRL":
58                             (cfgc == DSPCFG_ABORT)   ? "ABORT":
59                             (cfgc == DSPCFG_PROTREV) ? "PROTREV":
60                             NULL;
61                         break;
62                 }
63         case MBOX_CMD_DSP_REGRW:
64                 s = (cmd_l == REGRW_MEMR) ? "MEMR":
65                     (cmd_l == REGRW_MEMW) ? "MEMW":
66                     (cmd_l == REGRW_IOR)  ? "IOR":
67                     (cmd_l == REGRW_IOW)  ? "IOW":
68                     (cmd_l == REGRW_DATA) ? "DATA":
69                     NULL;
70                 break;
71         case MBOX_CMD_DSP_GETVAR:
72         case MBOX_CMD_DSP_SETVAR:
73                 s = (cmd_l == VARID_ICRMASK)  ? "ICRMASK":
74                     (cmd_l == VARID_LOADINFO) ? "LOADINFO":
75                     NULL;
76                 break;
77         case MBOX_CMD_DSP_ERR:
78                 s = (cmd_l == EID_BADTID)     ? "BADTID":
79                     (cmd_l == EID_BADTCN)     ? "BADTCN":
80                     (cmd_l == EID_BADBID)     ? "BADBID":
81                     (cmd_l == EID_BADCNT)     ? "BADCNT":
82                     (cmd_l == EID_NOTLOCKED)  ? "NOTLOCKED":
83                     (cmd_l == EID_STVBUF)     ? "STVBUF":
84                     (cmd_l == EID_BADADR)     ? "BADADR":
85                     (cmd_l == EID_BADTCTL)    ? "BADTCTL":
86                     (cmd_l == EID_BADPARAM)   ? "BADPARAM":
87                     (cmd_l == EID_FATAL)      ? "FATAL":
88                     (cmd_l == EID_WDT)        ? "WDT":
89                     (cmd_l == EID_NOMEM)      ? "NOMEM":
90                     (cmd_l == EID_NORES)      ? "NORES":
91                     (cmd_l == EID_IPBFULL)    ? "IPBFULL":
92                     (cmd_l == EID_TASKNOTRDY) ? "TASKNOTRDY":
93                     (cmd_l == EID_TASKBSY)    ? "TASKBSY":
94                     (cmd_l == EID_TASKERR)    ? "TASKERR":
95                     (cmd_l == EID_BADCFGTYP)  ? "BADCFGTYP":
96                     (cmd_l == EID_DEBUG)      ? "DEBUG":
97                     (cmd_l == EID_BADSEQ)     ? "BADSEQ":
98                     (cmd_l == EID_BADCMD)     ? "BADCMD":
99                     NULL;
100                 break;
101         default:
102                 s = NULL;
103         }
104
105         return s;
106 }
107
108 /* output of show() method should fit to PAGE_SIZE */
109 #define MBLOG_DEPTH     64
110
111 struct mblogent {
112         unsigned long jiffies;
113         mbox_msg_t msg;
114         arm_dsp_dir_t dir;
115 };
116
117 static struct {
118         spinlock_t lock;
119         int wp;
120         unsigned long cnt, cnt_ad, cnt_da;
121         struct mblogent ent[MBLOG_DEPTH];
122 } mblog = {
123         .lock = SPIN_LOCK_UNLOCKED,
124 };
125
126 #ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE
127 static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir)
128 {
129         const struct cmdinfo *ci = cmdinfo[mb->cmd_h];
130         char *dir_str;
131         char *subname;
132
133         dir_str = (dir == DIR_A2D) ? "sending  " : "receiving";
134         switch (ci->cmd_l_type) {
135         case CMD_L_TYPE_SUBCMD:
136                 subname = subcmd_name(mb);
137                 if (unlikely(!subname))
138                         subname = "Unknown";
139                 printk(KERN_DEBUG
140                        "mbox: %s seq=%d, cmd=%02x:%02x(%s:%s), data=%04x\n",
141                        dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
142                        ci->name, subname, mb->data);
143                 break;
144         case CMD_L_TYPE_TID:
145                 printk(KERN_DEBUG
146                        "mbox: %s seq=%d, cmd=%02x:%02x(%s:task %d), data=%04x\n",
147                        dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
148                        ci->name, mb->cmd_l, mb->data);
149                 break;
150         case CMD_L_TYPE_NULL:
151                 printk(KERN_DEBUG
152                        "mbox: %s seq=%d, cmd=%02x:%02x(%s), data=%04x\n",
153                        dir_str, mb->seq, mb->cmd_h, mb->cmd_l,
154                        ci->name, mb->data);
155                 break;
156         }
157 }
158 #else
159 static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir) { }
160 #endif
161
162 void mblog_add(struct mbcmd *mb, arm_dsp_dir_t dir)
163 {
164         struct mblogent *ent;
165
166         spin_lock(&mblog.lock);
167         ent = &mblog.ent[mblog.wp];
168         ent->jiffies = jiffies;
169         ent->msg = *(mbox_msg_t *)mb;
170         ent->dir = dir;
171         if (mblog.cnt < 0xffffffff)
172                 mblog.cnt++;
173         switch (dir) {
174         case DIR_A2D:
175                 if (mblog.cnt_ad < 0xffffffff)
176                         mblog.cnt_ad++;
177                 break;
178         case DIR_D2A:
179                 if (mblog.cnt_da < 0xffffffff)
180                         mblog.cnt_da++;
181                 break;
182         }
183         if (++mblog.wp == MBLOG_DEPTH)
184                 mblog.wp = 0;
185         spin_unlock(&mblog.lock);
186
187         mblog_print_cmd(mb, dir);
188 }
189
190 /*
191  * sysfs file
192  */
193 static ssize_t mblog_show(struct device *dev, struct device_attribute *attr,
194                           char *buf)
195 {
196         int len = 0;
197         int wp;
198         int i;
199
200         spin_lock(&mblog.lock);
201
202         wp = mblog.wp;
203         len += sprintf(buf + len,
204                        "log count:%ld / ARM->DSP:%ld, DSP->ARM:%ld\n",
205                        mblog.cnt, mblog.cnt_ad, mblog.cnt_da);
206         if (mblog.cnt == 0)
207                 goto done;
208
209         len += sprintf(buf + len, "           ARM->DSP   ARM<-DSP\n");
210         len += sprintf(buf + len, " jiffies  cmd  data  cmd  data\n");
211         i = (mblog.cnt >= MBLOG_DEPTH) ? wp : 0;
212         do {
213                 struct mblogent *ent = &mblog.ent[i];
214                 struct mbcmd *mb = (struct mbcmd *)&ent->msg;
215                 char *subname;
216                 struct cmdinfo ci_null = {
217                         .name = "Unknown",
218                         .cmd_l_type = CMD_L_TYPE_NULL,
219                 };
220                 const struct cmdinfo *ci;
221
222                 len += sprintf(buf + len,
223                                (ent->dir == DIR_A2D) ?
224                                 "%08lx  %04x %04x            ":
225                                 "%08lx             %04x %04x ",
226                                ent->jiffies,
227                                (ent->msg >> 16) & 0x7fff, ent->msg & 0xffff);
228
229                 if ((ci = cmdinfo[mb->cmd_h]) == NULL)
230                         ci = &ci_null;
231
232                 switch (ci->cmd_l_type) {
233                 case CMD_L_TYPE_SUBCMD:
234                         if ((subname = subcmd_name(mb)) == NULL)
235                                 subname = "Unknown";
236                         len += sprintf(buf + len, "%s:%s\n",
237                                        ci->name, subname);
238                         break;
239                 case CMD_L_TYPE_TID:
240                         len += sprintf(buf + len, "%s:task %d\n",
241                                        ci->name, mb->cmd_l);
242                         break;
243                 case CMD_L_TYPE_NULL:
244                         len += sprintf(buf + len, "%s\n", ci->name);
245                         break;
246                 }
247
248                 if (++i == MBLOG_DEPTH)
249                         i = 0;
250         } while (i != wp);
251
252 done:
253         spin_unlock(&mblog.lock);
254
255         return len;
256 }
257
258 static struct device_attribute dev_attr_mblog = __ATTR_RO(mblog);
259
260 void __init mblog_init(void)
261 {
262         device_create_file(&dsp_device.dev, &dev_attr_mblog);
263 }
264
265 void mblog_exit(void)
266 {
267         device_remove_file(&dsp_device.dev, &dev_attr_mblog);
268 }