1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
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.
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.
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.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
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>
33 #include "img_types.h"
34 #include "servicesext.h"
35 #include "pvr_debug.h"
38 #ifdef CONFIG_PVR_DEBUG
40 u32 gPVRDebugLevel = DBGPRIV_WARNING;
42 #define PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
44 static char gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
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)
53 spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
55 mutex_lock(&gsDebugMutexNonIRQ);
58 static inline void ReleaseBufferLock(unsigned long ulLockFlags)
61 spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
63 mutex_unlock(&gsDebugMutexNonIRQ);
66 static inline void SelectBuffer(char **ppszBuf, u32 *pui32BufSiz)
69 *ppszBuf = gszBufferIRQ;
70 *pui32BufSiz = sizeof(gszBufferIRQ);
72 *ppszBuf = gszBufferNonIRQ;
73 *pui32BufSiz = sizeof(gszBufferNonIRQ);
77 static IMG_BOOL VBAppend(char *pszBuf, u32 ui32BufSiz, const char *pszFormat,
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;
91 static IMG_BOOL BAppend(char *pszBuf, u32 ui32BufSiz, const char *pszFormat,
97 va_start(VArgs, pszFormat);
99 bTrunc = VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs);
106 void PVRSRVDebugPrintf(u32 ui32DebugLevel,
107 const char *pszFileName,
108 u32 ui32Line, const char *pszFormat, ...)
110 IMG_BOOL bTrace, bDebug;
113 pszLeafName = (char *)strrchr(pszFileName, '\\');
116 pszFileName = pszLeafName;
118 bTrace = gPVRDebugLevel & ui32DebugLevel & DBGPRIV_CALLTRACE;
119 bDebug = ((gPVRDebugLevel & DBGPRIV_ALLLEVELS) >= ui32DebugLevel);
121 if (bTrace || bDebug) {
123 unsigned long ulLockFlags = 0; /* suppress gc warning */
127 SelectBuffer(&pszBuf, &ui32BufSiz);
128 va_start(vaArgs, pszFormat);
130 GetBufferLock(&ulLockFlags);
133 switch (ui32DebugLevel) {
135 strncpy(pszBuf, "PVR_K:(Fatal): ",
139 strncpy(pszBuf, "PVR_K:(Error): ",
142 case DBGPRIV_WARNING:
143 strncpy(pszBuf, "PVR_K:(Warning): ",
146 case DBGPRIV_MESSAGE:
147 strncpy(pszBuf, "PVR_K:(Message): ",
150 case DBGPRIV_VERBOSE:
151 strncpy(pszBuf, "PVR_K:(Verbose): ",
156 "PVR_K:(Unknown message level)",
161 strncpy(pszBuf, "PVR_K: ", (ui32BufSiz - 1));
164 if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs)) {
165 printk(KERN_INFO "PVR_K:(Message Truncated): %s\n",
170 (pszBuf, ui32BufSiz, " [%lu, %s]", ui32Line,
173 "PVR_K:(Message Truncated): %s\n",
176 printk(KERN_INFO "%s\n", pszBuf);
180 ReleaseBufferLock(ulLockFlags);
185 void PVRSRVDebugAssertFail(const char *pszFile, u32 uLine)
187 PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine,
188 "Debug assertion failed!");
192 void PVRSRVTrace(const char *pszFormat, ...)
195 unsigned long ulLockFlags = 0; /* suppress gcc warning */
199 SelectBuffer(&pszBuf, &ui32BufSiz);
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);
207 printk(KERN_INFO "%s\n", pszBuf);
208 ReleaseBufferLock(ulLockFlags);
212 void PVRDebugSetLevel(u32 uDebugLevel)
214 printk(KERN_INFO "PVR: Setting Debug Level = 0x%x\n",
215 (unsigned)uDebugLevel);
217 gPVRDebugLevel = uDebugLevel;
220 int PVRDebugProcSetLevel(struct file *file, const char __user *buffer,
221 unsigned long count, void *data)
223 #define _PROC_SET_BUFFER_SZ 2
224 char data_buffer[_PROC_SET_BUFFER_SZ];
226 if (count != _PROC_SET_BUFFER_SZ) {
229 if (copy_from_user(data_buffer, buffer, count))
231 if (data_buffer[count - 1] != '\n')
233 PVRDebugSetLevel(data_buffer[0] - '0');
238 int PVRDebugProcGetLevel(char *page, char **start, off_t off, int count,
239 int *eof, void *data)
243 return printAppend(page, count, 0, "%u\n", gPVRDebugLevel);
251 void pvr_dbg_init(void)
253 #if defined(CONFIG_PVR_DEBUG) || defined(TIMING)
254 mutex_init(&gsDebugMutexNonIRQ);
258 void pvr_dbg_cleanup(void)