gpu: pvr: pdumpfs: add initial frame handling and debugfs support
authorLuc Verhaegen <libv@codethink.co.uk>
Fri, 11 Mar 2011 14:02:51 +0000 (15:02 +0100)
committerGrazvydas Ignotas <notasas@gmail.com>
Sun, 20 May 2012 18:43:04 +0000 (21:43 +0300)
This adds the separate handling of the initial frame, and adds
debugfs support for this initial frame.

The initial frame is the frame started when the driver is initialised.
Once userspace flags the first frame, the initial frame is ended, and
a new frame started, but the initial frame is not part of the stream
list. The initial frame therefor does not get culled as part of
standard frame culling and is kept around for the life of the driver.

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

index 5caca90..60cb726 100644 (file)
@@ -59,6 +59,7 @@ struct pdumpfs_frame {
 static u32 frame_count_max = CONFIG_PVR_PDUMP_INITIAL_MAX_FRAME_COUNT;
 static u32 frame_count;
 
+static struct pdumpfs_frame *frame_init;
 static struct pdumpfs_frame *frame_stream;
 static struct pdumpfs_frame *frame_current;
 
@@ -94,6 +95,9 @@ frame_destroy_all(void)
 {
        frame_current = NULL;
 
+       frame_destroy(frame_init);
+       frame_init = NULL;
+
        while (frame_stream) {
                struct pdumpfs_frame *frame = frame_stream;
 
@@ -131,10 +135,17 @@ frame_new(u32 pid, u32 number)
        frame->pid = pid;
        frame->number = number;
 
-       if (frame_current)
-               frame_current->next = frame;
+       if (!frame_init)
+               frame_init = frame;
+       else {
+               if (frame_current != frame_init)
+                       frame_current->next = frame;
+               else
+                       frame_stream = frame;
+               frame_count++;
+       }
+
        frame_current = frame;
-       frame_count++;
 
        frame_cull();
 
@@ -493,6 +504,104 @@ static const struct file_operations pdumpfs_frame_count_max_fops = {
        .write = pdumpfs_frame_count_max_write,
 };
 
+static ssize_t
+pdumpfs_frame_read_single(struct pdumpfs_frame *frame, char __user *buf,
+                         size_t size, loff_t f_pos)
+{
+       int page;
+       size_t offset;
+
+       if (f_pos >= frame->offset)
+               return 0;
+
+       if (size > (frame->offset - f_pos))
+               size = frame->offset - f_pos;
+
+       page = f_pos / PAGE_SIZE;
+       offset = f_pos % PAGE_SIZE;
+
+       if (size > (PAGE_SIZE - offset))
+               size = PAGE_SIZE - offset;
+
+       if (copy_to_user(buf, ((u8 *) frame->pages[page]) + offset, size))
+               return -EFAULT;
+
+       return size;
+}
+
+static loff_t
+pdumpfs_llseek_helper(struct file *filp, loff_t offset, int whence, loff_t max)
+{
+       loff_t f_pos;
+
+       switch (whence) {
+       case SEEK_SET:
+               if ((offset > max) || (offset < 0))
+                       f_pos = -EINVAL;
+               else
+                       f_pos = offset;
+               break;
+       case SEEK_CUR:
+               if (((filp->f_pos + offset) > max) ||
+                   ((filp->f_pos + offset) < 0))
+                       f_pos = -EINVAL;
+               else
+                       f_pos = filp->f_pos + offset;
+               break;
+       case SEEK_END:
+               if ((offset > 0) ||
+                   (offset < -max))
+                       f_pos = -EINVAL;
+               else
+                       f_pos = max + offset;
+               break;
+       default:
+               f_pos = -EINVAL;
+               break;
+       }
+
+       if (f_pos >= 0)
+               filp->f_pos = f_pos;
+
+       return f_pos;
+}
+
+static loff_t
+pdumpfs_init_llseek(struct file *filp, loff_t offset, int whence)
+{
+       loff_t f_pos;
+
+       mutex_lock(pdumpfs_mutex);
+
+       f_pos = pdumpfs_llseek_helper(filp, offset, whence, frame_init->offset);
+
+       mutex_unlock(pdumpfs_mutex);
+
+       return f_pos;
+}
+
+static ssize_t
+pdumpfs_init_read(struct file *filp, char __user *buf, size_t size,
+                 loff_t *f_pos)
+{
+       mutex_lock(pdumpfs_mutex);
+
+       size = pdumpfs_frame_read_single(frame_init,
+                                        buf, size, *f_pos);
+
+       mutex_unlock(pdumpfs_mutex);
+
+       if (size > 0)
+               *f_pos += size;
+       return size;
+}
+
+static const struct file_operations pdumpfs_init_fops = {
+       .owner = THIS_MODULE,
+       .llseek = pdumpfs_init_llseek,
+       .read = pdumpfs_init_read,
+};
+
 static struct dentry *pdumpfs_dir;
 
 static void
@@ -530,6 +639,9 @@ pdumpfs_fs_init(void)
        pdumpfs_file_create("frame_count_max", S_IRUSR | S_IWUSR,
                            &pdumpfs_frame_count_max_fops);
 
+       pdumpfs_file_create("init_frame", S_IRUSR,
+                           &pdumpfs_init_fops);
+
        return 0;
 }