2 * Copyright (c) 2010-2011 Imre Deak <imre.deak@nokia.com>
3 * Copyright (c) 2010-2011 Luc Verhaegen <libv@codethink.co.uk>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Debugfs interface living in pvr/ subdirectory.
25 #include <linux/kernel.h>
26 #include <linux/debugfs.h>
27 #include <linux/vmalloc.h>
28 #include <linux/mutex.h>
29 #include <linux/uaccess.h>
31 #include "img_types.h"
32 #include "servicesext.h"
34 #include "sgxinfokm.h"
35 #include "syscommon.h"
36 #include "pvr_bridge_km.h"
38 #include "pvr_debugfs.h"
40 static struct dentry *debugfs_dir;
46 static struct PVRSRV_DEVICE_NODE *get_sgx_node(void)
48 struct SYS_DATA *sysdata;
49 struct PVRSRV_DEVICE_NODE *node;
51 if (SysAcquireData(&sysdata) != PVRSRV_OK)
54 for (node = sysdata->psDeviceNodeList; node; node = node->psNext)
55 if (node->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_SGX)
61 static int pvr_debugfs_reset(void *data, u64 val)
63 struct PVRSRV_DEVICE_NODE *node;
64 enum PVRSRV_ERROR err;
72 if (pvr_is_disabled()) {
77 node = get_sgx_node();
83 err = PVRSRVSetDevicePowerStateKM(node->sDevId.ui32DeviceIndex,
84 PVRSRV_POWER_STATE_D0);
85 if (err != PVRSRV_OK) {
90 HWRecoveryResetSGX(node);
92 SGXTestActivePowerEvent(node);
99 static int pvr_debugfs_set(void *data, u64 val)
103 if (var == &pvr_reset)
104 return pvr_debugfs_reset(data, val);
109 DEFINE_SIMPLE_ATTRIBUTE(pvr_debugfs_fops, NULL, pvr_debugfs_set, "%llu\n");
114 struct edm_buf_info {
119 static int pvr_debugfs_edm_open(struct inode *inode, struct file *file)
121 struct PVRSRV_DEVICE_NODE *node;
122 struct PVRSRV_SGXDEV_INFO *sgx_info;
123 struct edm_buf_info *bi;
126 /* Take a snapshot of the EDM trace buffer */
127 size = SGXMK_TRACE_BUFFER_SIZE * SGXMK_TRACE_BUF_STR_LEN;
128 bi = vmalloc(sizeof(*bi) + size);
132 node = get_sgx_node();
133 sgx_info = node->pvDevice;
134 bi->len = snprint_edm_trace(sgx_info, bi->data, size);
135 file->private_data = bi;
140 static int pvr_debugfs_edm_release(struct inode *inode, struct file *file)
142 vfree(file->private_data);
147 static ssize_t pvr_debugfs_edm_read(struct file *file, char __user *buffer,
148 size_t count, loff_t *ppos)
150 struct edm_buf_info *bi = file->private_data;
152 return simple_read_from_buffer(buffer, count, ppos, bi->data, bi->len);
155 static const struct file_operations pvr_debugfs_edm_fops = {
156 .owner = THIS_MODULE,
157 .open = pvr_debugfs_edm_open,
158 .read = pvr_debugfs_edm_read,
159 .release = pvr_debugfs_edm_release,
165 * HW Recovery dumping support.
168 static struct mutex hwrec_mutex[1];
169 static struct timeval hwrec_time;
170 static int hwrec_open_count;
171 static DECLARE_WAIT_QUEUE_HEAD(hwrec_wait_queue);
172 static int hwrec_event;
174 /* add extra locking to keep us from overwriting things during dumping. */
175 static int hwrec_event_open_count;
176 static int hwrec_event_file_lock;
181 mutex_lock(hwrec_mutex);
183 if (hwrec_open_count || hwrec_event_file_lock) {
184 pr_err("%s: previous hwrec dump is still locked!\n", __func__);
185 mutex_unlock(hwrec_mutex);
189 do_gettimeofday(&hwrec_time);
190 pr_info("HW Recovery dump generated at %010ld%06ld\n",
191 hwrec_time.tv_sec, hwrec_time.tv_usec);
195 mutex_unlock(hwrec_mutex);
197 wake_up_interruptible(&hwrec_wait_queue);
204 hwrec_file_open(struct inode *inode, struct file *filp)
206 mutex_lock(hwrec_mutex);
210 mutex_unlock(hwrec_mutex);
215 hwrec_file_release(struct inode *inode, struct file *filp)
217 mutex_lock(hwrec_mutex);
221 mutex_unlock(hwrec_mutex);
226 * Provides a hwrec timestamp for unique dumping.
229 hwrec_time_read(struct file *filp, char __user *buf, size_t size,
234 mutex_lock(hwrec_mutex);
235 snprintf(tmp, sizeof(tmp), "%010ld%06ld",
236 hwrec_time.tv_sec, hwrec_time.tv_usec);
237 mutex_unlock(hwrec_mutex);
239 return simple_read_from_buffer(buf, size, f_pos, tmp, strlen(tmp));
242 static const struct file_operations hwrec_time_fops = {
243 .owner = THIS_MODULE,
245 .read = hwrec_time_read,
246 .open = hwrec_file_open,
247 .release = hwrec_file_release,
251 * Blocks the reader until a HWRec happens.
254 hwrec_event_open(struct inode *inode, struct file *filp)
258 mutex_lock(hwrec_mutex);
260 if (hwrec_event_open_count)
263 hwrec_event_open_count++;
267 mutex_unlock(hwrec_mutex);
273 hwrec_event_release(struct inode *inode, struct file *filp)
275 mutex_lock(hwrec_mutex);
277 hwrec_event_open_count--;
279 mutex_unlock(hwrec_mutex);
286 hwrec_event_read(struct file *filp, char __user *buf, size_t size,
291 mutex_lock(hwrec_mutex);
293 hwrec_event_file_lock = 0;
295 mutex_unlock(hwrec_mutex);
297 ret = wait_event_interruptible(hwrec_wait_queue, hwrec_event);
299 mutex_lock(hwrec_mutex);
302 hwrec_event_file_lock = 1;
304 mutex_unlock(hwrec_mutex);
310 static const struct file_operations hwrec_event_fops = {
311 .owner = THIS_MODULE,
313 .read = hwrec_event_read,
314 .open = hwrec_event_open,
315 .release = hwrec_event_release,
321 int pvr_debugfs_init(void)
323 mutex_init(hwrec_mutex);
325 debugfs_dir = debugfs_create_dir("pvr", NULL);
329 if (!debugfs_create_file("reset_sgx", S_IWUSR, debugfs_dir, &pvr_reset,
330 &pvr_debugfs_fops)) {
331 debugfs_remove(debugfs_dir);
335 if (!debugfs_create_file("edm_trace", S_IRUGO, debugfs_dir, NULL,
336 &pvr_debugfs_edm_fops)) {
337 debugfs_remove_recursive(debugfs_dir);
341 if (!debugfs_create_file("hwrec_event", S_IRUSR, debugfs_dir, NULL,
342 &hwrec_event_fops)) {
343 debugfs_remove_recursive(debugfs_dir);
347 if (!debugfs_create_file("hwrec_time", S_IRUSR, debugfs_dir, NULL,
349 debugfs_remove_recursive(debugfs_dir);
356 void pvr_debugfs_cleanup(void)
358 debugfs_remove_recursive(debugfs_dir);