gpu: pvr: debugfs: add initial hwrec dumping infrastructure
authorLuc Verhaegen <libv@codethink.co.uk>
Tue, 22 Mar 2011 11:38:34 +0000 (12:38 +0100)
committerGrazvydas Ignotas <notasas@gmail.com>
Sun, 20 May 2012 18:43:03 +0000 (21:43 +0300)
Currently contains hwrec_event and hwrec_time.

hwrec_event blocks the reader until a hwrec event happens. This allows
a simple shell application to sleep until a hwrec happens.

hwrec_time contains a timestamp to enable a simple shell application
to create unique dumps.

Signed-off-by: Luc Verhaegen <libv@codethink.co.uk>
Signed-off-by: Imre Deak <imre.deak@nokia.com>
pvr/pvr_debugfs.c
pvr/pvr_debugfs.h
pvr/sgxinit.c

index 1dfebca..d549133 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2010-2011 Imre Deak <imre.deak@nokia.com>
+ * Copyright (c) 2010-2011 Luc Verhaegen <libv@codethink.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -24,6 +25,8 @@
 #include <linux/kernel.h>
 #include <linux/debugfs.h>
 #include <linux/vmalloc.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
 
 #include "img_types.h"
 #include "servicesext.h"
@@ -157,11 +160,168 @@ static const struct file_operations pvr_debugfs_edm_fops = {
 };
 
 
+/*
+ *
+ * HW Recovery dumping support.
+ *
+ */
+static struct mutex hwrec_mutex[1];
+static struct timeval hwrec_time;
+static int hwrec_open_count;
+static DECLARE_WAIT_QUEUE_HEAD(hwrec_wait_queue);
+static int hwrec_event;
+
+/* add extra locking to keep us from overwriting things during dumping. */
+static int hwrec_event_open_count;
+static int hwrec_event_file_lock;
+
+void
+pvr_hwrec_dump(void)
+{
+       mutex_lock(hwrec_mutex);
+
+       if (hwrec_open_count || hwrec_event_file_lock) {
+               pr_err("%s: previous hwrec dump is still locked!\n", __func__);
+               mutex_unlock(hwrec_mutex);
+               return;
+       }
+
+       do_gettimeofday(&hwrec_time);
+       pr_info("HW Recovery dump generated at %010ld%06ld\n",
+               hwrec_time.tv_sec, hwrec_time.tv_usec);
+
+       hwrec_event = 1;
+
+       mutex_unlock(hwrec_mutex);
+
+       wake_up_interruptible(&hwrec_wait_queue);
+}
+
+/*
+ * helpers.
+ */
+static int
+hwrec_file_open(struct inode *inode, struct file *filp)
+{
+       mutex_lock(hwrec_mutex);
+
+       hwrec_open_count++;
+
+       mutex_unlock(hwrec_mutex);
+       return 0;
+}
+
+static int
+hwrec_file_release(struct inode *inode, struct file *filp)
+{
+       mutex_lock(hwrec_mutex);
+
+       hwrec_open_count--;
+
+       mutex_unlock(hwrec_mutex);
+       return 0;
+}
+
+/*
+ * Provides a hwrec timestamp for unique dumping.
+ */
+static ssize_t
+hwrec_time_read(struct file *filp, char __user *buf, size_t size,
+               loff_t *f_pos)
+{
+       char tmp[20];
+
+       mutex_lock(hwrec_mutex);
+       snprintf(tmp, sizeof(tmp), "%010ld%06ld",
+                hwrec_time.tv_sec, hwrec_time.tv_usec);
+       mutex_unlock(hwrec_mutex);
+
+       return simple_read_from_buffer(buf, size, f_pos, tmp, strlen(tmp));
+}
+
+static const struct file_operations hwrec_time_fops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .read = hwrec_time_read,
+       .open = hwrec_file_open,
+       .release = hwrec_file_release,
+};
+
+/*
+ * Blocks the reader until a HWRec happens.
+ */
+static int
+hwrec_event_open(struct inode *inode, struct file *filp)
+{
+       int ret;
+
+       mutex_lock(hwrec_mutex);
+
+       if (hwrec_event_open_count)
+               ret = -EUSERS;
+       else {
+               hwrec_event_open_count++;
+               ret = 0;
+       }
+
+       mutex_unlock(hwrec_mutex);
+
+       return ret;
+}
+
+static int
+hwrec_event_release(struct inode *inode, struct file *filp)
+{
+       mutex_lock(hwrec_mutex);
+
+       hwrec_event_open_count--;
+
+       mutex_unlock(hwrec_mutex);
+
+       return 0;
+}
+
+
+static ssize_t
+hwrec_event_read(struct file *filp, char __user *buf, size_t size,
+                loff_t *f_pos)
+{
+       int ret = 0;
+
+       mutex_lock(hwrec_mutex);
+
+       hwrec_event_file_lock = 0;
+
+       mutex_unlock(hwrec_mutex);
+
+       ret = wait_event_interruptible(hwrec_wait_queue, hwrec_event);
+       if (!ret) {
+               mutex_lock(hwrec_mutex);
+
+               hwrec_event = 0;
+               hwrec_event_file_lock = 1;
+
+               mutex_unlock(hwrec_mutex);
+       }
+
+       return ret;
+}
+
+static const struct file_operations hwrec_event_fops = {
+       .owner = THIS_MODULE,
+       .llseek = no_llseek,
+       .read = hwrec_event_read,
+       .open = hwrec_event_open,
+       .release = hwrec_event_release,
+};
+
 /*
  *
  */
 int pvr_debugfs_init(void)
 {
+       mutex_init(hwrec_mutex);
+
        debugfs_dir = debugfs_create_dir("pvr", NULL);
        if (!debugfs_dir)
                return -ENODEV;
@@ -178,6 +338,18 @@ int pvr_debugfs_init(void)
                return -ENODEV;
        }
 
+       if (!debugfs_create_file("hwrec_event", S_IRUSR, debugfs_dir, NULL,
+                                &hwrec_event_fops)) {
+               debugfs_remove_recursive(debugfs_dir);
+               return -ENODEV;
+       }
+
+       if (!debugfs_create_file("hwrec_time", S_IRUSR, debugfs_dir, NULL,
+                                &hwrec_time_fops)) {
+               debugfs_remove_recursive(debugfs_dir);
+               return -ENODEV;
+       }
+
        return 0;
 }
 
index 6adc51b..6ec216e 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2010-2011 Imre Deak <imre.deak@nokia.com>
+ * Copyright (c) 2010-2011 Luc Verhaegen <libv@codethink.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -26,4 +27,6 @@
 int pvr_debugfs_init(void);
 void pvr_debugfs_cleanup(void);
 
+void pvr_hwrec_dump(void);
+
 #endif /* _PVR_DEBUGFS_H_ */
index 8f88052..8518d22 100644 (file)
 #include "pvrversion.h"
 #include "sgx_options.h"
 
+#ifdef CONFIG_DEBUG_FS
+#include "pvr_debugfs.h"
+#endif
+
 static IMG_BOOL SGX_ISRHandler(void *pvData);
 
 static u32 gui32EventStatusServicesByISR;
@@ -987,6 +991,10 @@ void HWRecoveryResetSGX(struct PVRSRV_DEVICE_NODE *psDeviceNode)
        dump_edm(psDevInfo);
        dump_sgx_state_bufs(psDeviceNode);
 
+#ifdef CONFIG_DEBUG_FS
+       pvr_hwrec_dump();
+#endif
+
        PDUMPSUSPEND();
 
        do {