fixes for bc_cat
[sgx.git] / pvr / pvr_debug.c
1 /**********************************************************************
2  *
3  * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful but, except
10  * as otherwise stated in writing, without any warranty; without even the
11  * implied warranty of merchantability or fitness for a particular purpose.
12  * See the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * The full GNU General Public License is included in this distribution in
19  * the file called "COPYING".
20  *
21  * Contact Information:
22  * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23  * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
24  *
25  ******************************************************************************/
26
27 #include <linux/uaccess.h>
28 #include <linux/kernel.h>
29 #include <linux/hardirq.h>
30 #include <linux/module.h>
31 #include <linux/spinlock.h>
32
33 #include "img_types.h"
34 #include "servicesext.h"
35 #include "pvr_debug.h"
36 #include "proc.h"
37
38 #ifdef CONFIG_PVR_DEBUG
39
40 u32 gPVRDebugLevel = DBGPRIV_WARNING;
41
42 #define PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
43
44 static char gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
45
46 static char gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
47 static struct mutex gsDebugMutexNonIRQ;
48 static DEFINE_SPINLOCK(gsDebugLockIRQ);
49 #define USE_SPIN_LOCK (in_interrupt() || !preemptible())
50 static inline void GetBufferLock(unsigned long *pulLockFlags)
51 {
52         if (USE_SPIN_LOCK)
53                 spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
54         else
55                 mutex_lock(&gsDebugMutexNonIRQ);
56 }
57
58 static inline void ReleaseBufferLock(unsigned long ulLockFlags)
59 {
60         if (USE_SPIN_LOCK)
61                 spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
62         else
63                 mutex_unlock(&gsDebugMutexNonIRQ);
64 }
65
66 static inline void SelectBuffer(char **ppszBuf, u32 *pui32BufSiz)
67 {
68         if (USE_SPIN_LOCK) {
69                 *ppszBuf = gszBufferIRQ;
70                 *pui32BufSiz = sizeof(gszBufferIRQ);
71         } else {
72                 *ppszBuf = gszBufferNonIRQ;
73                 *pui32BufSiz = sizeof(gszBufferNonIRQ);
74         }
75 }
76
77 static IMG_BOOL VBAppend(char *pszBuf, u32 ui32BufSiz, const char *pszFormat,
78                          va_list VArgs)
79 {
80         u32 ui32Used;
81         u32 ui32Space;
82         s32 i32Len;
83         ui32Used = strlen(pszBuf);
84         BUG_ON(ui32Used >= ui32BufSiz);
85         ui32Space = ui32BufSiz - ui32Used;
86         i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
87         pszBuf[ui32BufSiz - 1] = 0;
88         return i32Len < 0 || i32Len >= ui32Space;
89 }
90
91 static IMG_BOOL BAppend(char *pszBuf, u32 ui32BufSiz, const char *pszFormat,
92                         ...)
93 {
94         va_list VArgs;
95         IMG_BOOL bTrunc;
96
97         va_start(VArgs, pszFormat);
98
99         bTrunc = VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs);
100
101         va_end(VArgs);
102
103         return bTrunc;
104 }
105
106 void PVRSRVDebugPrintf(u32 ui32DebugLevel,
107                        const char *pszFileName,
108                        u32 ui32Line, const char *pszFormat, ...)
109 {
110         IMG_BOOL bTrace, bDebug;
111         char *pszLeafName;
112
113         pszLeafName = (char *)strrchr(pszFileName, '\\');
114
115         if (pszLeafName)
116                 pszFileName = pszLeafName;
117
118         bTrace = gPVRDebugLevel & ui32DebugLevel & DBGPRIV_CALLTRACE;
119         bDebug = ((gPVRDebugLevel & DBGPRIV_ALLLEVELS) >= ui32DebugLevel);
120
121         if (bTrace || bDebug) {
122                 va_list vaArgs;
123                 unsigned long ulLockFlags = 0;  /* suppress gc warning */
124                 char *pszBuf;
125                 u32 ui32BufSiz;
126
127                 SelectBuffer(&pszBuf, &ui32BufSiz);
128                 va_start(vaArgs, pszFormat);
129
130                 GetBufferLock(&ulLockFlags);
131
132                 if (bDebug) {
133                         switch (ui32DebugLevel) {
134                         case DBGPRIV_FATAL:
135                                 strncpy(pszBuf, "PVR_K:(Fatal): ",
136                                         (ui32BufSiz - 1));
137                                 break;
138                         case DBGPRIV_ERROR:
139                                 strncpy(pszBuf, "PVR_K:(Error): ",
140                                                 (ui32BufSiz - 1));
141                                 break;
142                         case DBGPRIV_WARNING:
143                                 strncpy(pszBuf, "PVR_K:(Warning): ",
144                                                 (ui32BufSiz - 1));
145                                 break;
146                         case DBGPRIV_MESSAGE:
147                                 strncpy(pszBuf, "PVR_K:(Message): ",
148                                                 (ui32BufSiz - 1));
149                                 break;
150                         case DBGPRIV_VERBOSE:
151                                 strncpy(pszBuf, "PVR_K:(Verbose): ",
152                                                 (ui32BufSiz - 1));
153                                 break;
154                         default:
155                                 strncpy(pszBuf,
156                                                 "PVR_K:(Unknown message level)",
157                                                 (ui32BufSiz - 1));
158                                 break;
159                         }
160                 } else {
161                         strncpy(pszBuf, "PVR_K: ", (ui32BufSiz - 1));
162                 }
163
164                 if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs)) {
165                         printk(KERN_INFO "PVR_K:(Message Truncated): %s\n",
166                                pszBuf);
167                 } else {
168                         if (!bTrace) {
169                                 if (BAppend
170                                     (pszBuf, ui32BufSiz, " [%lu, %s]", ui32Line,
171                                      pszFileName))
172                                         printk(KERN_INFO
173                                               "PVR_K:(Message Truncated): %s\n",
174                                                pszBuf);
175                                 else
176                                         printk(KERN_INFO "%s\n", pszBuf);
177                         }
178                 }
179
180                 ReleaseBufferLock(ulLockFlags);
181                 va_end(vaArgs);
182         }
183 }
184
185 void PVRSRVDebugAssertFail(const char *pszFile, u32 uLine)
186 {
187         PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine,
188                           "Debug assertion failed!");
189         BUG();
190 }
191
192 void PVRSRVTrace(const char *pszFormat, ...)
193 {
194         va_list VArgs;
195         unsigned long ulLockFlags = 0;          /* suppress gcc warning */
196         char *pszBuf;
197         u32 ui32BufSiz;
198
199         SelectBuffer(&pszBuf, &ui32BufSiz);
200
201         va_start(VArgs, pszFormat);
202         GetBufferLock(&ulLockFlags);
203         strncpy(pszBuf, "PVR: ", (ui32BufSiz - 1));
204         if (VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs))
205                 printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
206         else
207                 printk(KERN_INFO "%s\n", pszBuf);
208         ReleaseBufferLock(ulLockFlags);
209         va_end(VArgs);
210 }
211
212 void PVRDebugSetLevel(u32 uDebugLevel)
213 {
214         printk(KERN_INFO "PVR: Setting Debug Level = 0x%x\n",
215                (unsigned)uDebugLevel);
216
217         gPVRDebugLevel = uDebugLevel;
218 }
219
220 int PVRDebugProcSetLevel(struct file *file, const char __user *buffer,
221                          unsigned long count, void *data)
222 {
223 #define _PROC_SET_BUFFER_SZ             2
224         char data_buffer[_PROC_SET_BUFFER_SZ];
225
226         if (count != _PROC_SET_BUFFER_SZ) {
227                 return -EINVAL;
228         } else {
229                 if (copy_from_user(data_buffer, buffer, count))
230                         return -EINVAL;
231                 if (data_buffer[count - 1] != '\n')
232                         return -EINVAL;
233                 PVRDebugSetLevel(data_buffer[0] - '0');
234         }
235         return count;
236 }
237
238 int PVRDebugProcGetLevel(char *page, char **start, off_t off, int count,
239                          int *eof, void *data)
240 {
241         if (off == 0) {
242                 *start = (char *)1;
243                 return printAppend(page, count, 0, "%u\n", gPVRDebugLevel);
244         }
245         *eof = 1;
246         return 0;
247 }
248
249 #endif
250
251 void pvr_dbg_init(void)
252 {
253 #if defined(CONFIG_PVR_DEBUG) || defined(TIMING)
254         mutex_init(&gsDebugMutexNonIRQ);
255 #endif
256 }
257
258 void pvr_dbg_cleanup(void)
259 {
260
261 }
262