2 * Copyright (c) 2010-2011 by Luc Verhaegen <libv@codethink.co.uk>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <linux/mutex.h>
20 #include <linux/uaccess.h>
21 #include <linux/debugfs.h>
24 #include "services_headers.h"
25 #include "pvr_pdump.h"
26 #include "pvr_pdumpfs.h"
28 static struct mutex pdumpfs_mutex[1];
31 PDUMPFS_MODE_DISABLED,
32 PDUMPFS_MODE_STANDARD,
36 static enum pdumpfs_mode pdumpfs_mode =
37 #if defined(CONFIG_PVR_PDUMP_MODE_STANDARD)
39 #elif defined(CONFIG_PVR_PDUMP_MODE_FULL)
46 #define FRAME_PAGE_COUNT 2040
48 struct pdumpfs_frame {
49 struct pdumpfs_frame *next;
56 unsigned long pages[FRAME_PAGE_COUNT];
59 #define MAX_FRAME_COUNT_HARD 1024
60 static u32 frame_count_max = CONFIG_PVR_PDUMP_INITIAL_MAX_FRAME_COUNT;
61 static u32 frame_count;
63 static struct pdumpfs_frame *frame_init;
64 static struct pdumpfs_frame *frame_stream;
65 static struct pdumpfs_frame *frame_current;
67 static struct pdumpfs_frame *frame_current_debugfs;
68 static int frame_current_open_count;
69 static int frame_stream_open_count;
71 static loff_t stream_start;
72 static loff_t stream_f_pos;
73 static loff_t stream_end;
75 static struct pdumpfs_frame *
78 struct pdumpfs_frame *frame =
79 kmalloc(sizeof(struct pdumpfs_frame), GFP_KERNEL);
83 memset(frame, 0, sizeof(struct pdumpfs_frame));
89 frame_destroy(struct pdumpfs_frame *frame)
96 for (i = 0; i < frame->page_count; i++)
97 free_page(frame->pages[i]);
103 frame_destroy_all(void)
105 /* detach from possible clones */
106 if (frame_current_debugfs &&
107 ((frame_current_debugfs == frame_init) ||
108 (frame_current_debugfs == frame_current) ||
109 frame_current_debugfs->next))
110 frame_current_debugfs = NULL;
112 frame_current = NULL;
114 frame_destroy(frame_init);
117 frame_destroy(frame_current_debugfs);
118 frame_current_debugfs = NULL;
120 while (frame_stream) {
121 struct pdumpfs_frame *frame = frame_stream;
123 frame_stream = frame->next;
125 frame_destroy(frame);
135 frame_cull_first(void)
137 struct pdumpfs_frame *frame = frame_stream;
139 frame_stream = frame->next;
142 if (frame_stream_open_count)
143 stream_start += frame->offset;
145 stream_end -= frame->offset;
148 * we cannot have frames vanish in the middle of reading
149 * them through debugfs
151 if (frame != frame_current_debugfs)
152 frame_destroy(frame);
161 if (!frame_stream_open_count) {
162 while (frame_count > frame_count_max)
165 while (((stream_start + frame_stream->offset) < stream_f_pos) ||
166 (frame_count > MAX_FRAME_COUNT_HARD))
172 frame_new(u32 pid, u32 number)
174 struct pdumpfs_frame *frame = frame_create();
177 pr_err("%s: Failed to create frame.\n", __func__);
182 frame->number = number;
187 if (frame_current != frame_init)
188 frame_current->next = frame;
190 frame_stream = frame;
194 frame_current = frame;
202 pdumpfs_frame_set(u32 pid, u32 frame)
204 mutex_lock(pdumpfs_mutex);
206 frame_new(pid, frame);
208 mutex_unlock(pdumpfs_mutex);
212 pdumpfs_capture_enabled(void)
216 mutex_lock(pdumpfs_mutex);
218 if ((pdumpfs_mode == PDUMPFS_MODE_FULL) &&
219 (frame_current != frame_init)) /* simulator bails otherwise */
224 mutex_unlock(pdumpfs_mutex);
230 pdumpfs_flags_check(u32 flags)
234 if (flags & PDUMP_FLAGS_NEVER)
237 mutex_lock(pdumpfs_mutex);
239 if (pdumpfs_mode == PDUMPFS_MODE_DISABLED)
241 else if ((pdumpfs_mode == PDUMPFS_MODE_FULL) &&
242 (frame_current != frame_init)) /* simulator bails otherwise */
244 else if (flags & PDUMP_FLAGS_CONTINUOUS)
249 mutex_unlock(pdumpfs_mutex);
255 pdumpfs_frame_write_low(void *buffer, size_t size, bool from_user)
257 struct pdumpfs_frame *frame = frame_current;
262 size_t offset = frame->offset & ~PAGE_MASK;
266 if (frame->page_count >= FRAME_PAGE_COUNT) {
267 pr_err("%s: Frame size overrun.\n", __func__);
271 page = __get_free_page(GFP_KERNEL);
273 pr_err("%s: failed to get free page.\n",
278 frame->pages[frame->page_count] = page;
282 frame->pages[frame->page_count - 1];
284 if (count > (PAGE_SIZE - offset))
285 count = PAGE_SIZE - offset;
288 if (copy_from_user(((u8 *) page) + offset,
289 (void __user __force *) buffer,
293 memcpy(((u8 *) page) + offset, buffer, count);
298 frame->offset += count;
304 pdumpfs_frame_write(void *buffer, size_t size, bool from_user)
308 if ((frame_current->offset + size) > (PAGE_SIZE * FRAME_PAGE_COUNT)) {
309 u32 pid = OSGetCurrentProcessIDKM();
310 struct task_struct *task;
312 pr_err("Frame overrun!!!\n");
314 ret = frame_new(pid, -1);
319 task = pid_task(find_vpid(pid), PIDTYPE_PID);
321 #define FRAME_OVERRUN_MESSAGE "-- Starting forced frame caused by "
322 pdumpfs_frame_write_low(FRAME_OVERRUN_MESSAGE,
323 sizeof(FRAME_OVERRUN_MESSAGE), false);
324 pdumpfs_frame_write_low(task->comm, strlen(task->comm), false);
325 pdumpfs_frame_write_low("\r\n", 2, false);
327 pr_err("%s: Frame size overrun, caused by %d (%s)\n",
328 __func__, pid, task->comm);
333 return pdumpfs_frame_write_low(buffer, size, from_user);
337 pdumpfs_write_data(void *buffer, size_t size, bool from_user)
339 mutex_lock(pdumpfs_mutex);
341 size = pdumpfs_frame_write(buffer, size, from_user);
342 if ((size > 0) && (frame_current != frame_init))
345 mutex_unlock(pdumpfs_mutex);
347 if ((size >= 0) || (size == -ENOMEM))
350 return PVRSRV_ERROR_GENERIC;
354 pdumpfs_write_string(char *string)
358 mutex_lock(pdumpfs_mutex);
360 size = pdumpfs_frame_write(string, strlen(string), false);
361 if ((size > 0) && (frame_current != frame_init))
364 mutex_unlock(pdumpfs_mutex);
370 static const struct {
372 enum pdumpfs_mode mode;
373 } pdumpfs_modes[] = {
374 {"disabled", PDUMPFS_MODE_DISABLED},
375 {"standard", PDUMPFS_MODE_STANDARD},
376 {"full", PDUMPFS_MODE_FULL},
377 {NULL, PDUMPFS_MODE_DISABLED}
381 pdumpfs_mode_read(struct file *filp, char __user *buf, size_t size,
389 mutex_lock(pdumpfs_mutex);
391 for (i = 0; pdumpfs_modes[i].name; i++)
392 if (pdumpfs_modes[i].mode == pdumpfs_mode)
393 snprintf(tmp, sizeof(tmp), "%s\n",
394 pdumpfs_modes[i].name);
396 mutex_unlock(pdumpfs_mutex);
398 if (strlen(tmp) < *f_pos)
401 if ((strlen(tmp) + 1) < (*f_pos + size))
402 size = strlen(tmp) + 1 - *f_pos;
404 if (copy_to_user(buf, tmp + *f_pos, size))
412 pdumpfs_mode_write(struct file *filp, const char __user *buf, size_t size,
418 if (*f_pos > sizeof(tmp))
421 if (size > (sizeof(tmp) - *f_pos))
422 size = sizeof(tmp) - *f_pos;
424 if (copy_from_user(tmp + *f_pos, buf, size))
429 mutex_lock(pdumpfs_mutex);
431 for (i = 0; pdumpfs_modes[i].name; i++)
432 if (!strnicmp(tmp, pdumpfs_modes[i].name,
433 strlen(pdumpfs_modes[i].name))) {
434 pdumpfs_mode = pdumpfs_modes[i].mode;
435 mutex_unlock(pdumpfs_mutex);
439 mutex_unlock(pdumpfs_mutex);
443 static const struct file_operations pdumpfs_mode_fops = {
444 .owner = THIS_MODULE,
446 .read = pdumpfs_mode_read,
447 .write = pdumpfs_mode_write,
451 pdumpfs_modes_possible_read(struct file *filp, char __user *buf, size_t size,
454 unsigned int i, skip = *f_pos, pos = 0;
456 for (i = 0; pdumpfs_modes[i].name; i++) {
460 else if (size > pos) {
461 if (copy_to_user(buf + pos, " ", 1))
468 int len = strlen(pdumpfs_modes[i].name);
472 } else if (size > pos) {
473 len = min(len - skip, size - pos);
475 if (copy_to_user(buf + pos,
476 pdumpfs_modes[i].name + skip,
490 static const struct file_operations pdumpfs_modes_possible_fops = {
491 .owner = THIS_MODULE,
493 .read = pdumpfs_modes_possible_read,
497 pdumpfs_frame_count_max_read(struct file *filp, char __user *buf, size_t size,
504 mutex_lock(pdumpfs_mutex);
505 snprintf(tmp, sizeof(tmp), "%d", frame_count_max);
506 mutex_unlock(pdumpfs_mutex);
508 if (strlen(tmp) < *f_pos)
511 if ((strlen(tmp) + 1) < (*f_pos + size))
512 size = strlen(tmp) + 1 - *f_pos;
514 if (copy_to_user(buf, tmp + *f_pos, size))
522 pdumpfs_frame_count_max_write(struct file *filp, const char __user *buf,
523 size_t size, loff_t *f_pos)
526 unsigned long result = 0;
528 if (*f_pos > sizeof(tmp))
531 if (size > (sizeof(tmp) - *f_pos))
532 size = sizeof(tmp) - *f_pos;
534 if (copy_from_user(tmp + *f_pos, buf, size))
539 mutex_lock(pdumpfs_mutex);
541 if (!strict_strtoul(tmp, 0, &result)) {
546 frame_count_max = result;
549 mutex_unlock(pdumpfs_mutex);
555 static const struct file_operations pdumpfs_frame_count_max_fops = {
556 .owner = THIS_MODULE,
558 .read = pdumpfs_frame_count_max_read,
559 .write = pdumpfs_frame_count_max_write,
563 pdumpfs_frame_read_single(struct pdumpfs_frame *frame, char __user *buf,
564 size_t size, loff_t f_pos)
569 if (f_pos >= frame->offset)
572 if (size > (frame->offset - f_pos))
573 size = frame->offset - f_pos;
575 page = f_pos / PAGE_SIZE;
576 offset = f_pos % PAGE_SIZE;
578 if (size > (PAGE_SIZE - offset))
579 size = PAGE_SIZE - offset;
581 if (copy_to_user(buf, ((u8 *) frame->pages[page]) + offset, size))
588 pdumpfs_llseek_helper(struct file *filp, loff_t offset, int whence, loff_t max)
594 if ((offset > max) || (offset < 0))
600 if (((filp->f_pos + offset) > max) ||
601 ((filp->f_pos + offset) < 0))
604 f_pos = filp->f_pos + offset;
611 f_pos = max + offset;
625 pdumpfs_init_llseek(struct file *filp, loff_t offset, int whence)
629 mutex_lock(pdumpfs_mutex);
631 f_pos = pdumpfs_llseek_helper(filp, offset, whence, frame_init->offset);
633 mutex_unlock(pdumpfs_mutex);
639 pdumpfs_init_read(struct file *filp, char __user *buf, size_t size,
642 mutex_lock(pdumpfs_mutex);
644 size = pdumpfs_frame_read_single(frame_init,
647 mutex_unlock(pdumpfs_mutex);
654 static const struct file_operations pdumpfs_init_fops = {
655 .owner = THIS_MODULE,
656 .llseek = pdumpfs_init_llseek,
657 .read = pdumpfs_init_read,
661 * We need to make sure that our frame doesn't vanish while we are still
662 * reading it: so reference this frame again.
665 pdumpfs_current_open(struct inode *inode, struct file *filp)
667 mutex_lock(pdumpfs_mutex);
669 if (!frame_current_open_count)
670 frame_current_debugfs = frame_current;
672 frame_current_open_count++;
674 mutex_unlock(pdumpfs_mutex);
679 pdumpfs_current_release(struct inode *inode, struct file *filp)
681 mutex_lock(pdumpfs_mutex);
683 frame_current_open_count--;
685 if (!frame_current_open_count) {
686 if ((frame_current_debugfs != frame_init) &&
687 (frame_current_debugfs != frame_current) &&
688 !frame_current_debugfs->next)
689 frame_destroy(frame_current_debugfs);
690 frame_current_debugfs = NULL;
693 mutex_unlock(pdumpfs_mutex);
698 pdumpfs_current_llseek(struct file *filp, loff_t offset, int whence)
702 mutex_lock(pdumpfs_mutex);
704 f_pos = pdumpfs_llseek_helper(filp, offset, whence,
705 frame_current_debugfs->offset);
707 mutex_unlock(pdumpfs_mutex);
713 pdumpfs_current_read(struct file *filp, char __user *buf, size_t size,
716 mutex_lock(pdumpfs_mutex);
718 if (frame_current_debugfs->offset)
719 size = pdumpfs_frame_read_single(frame_current_debugfs,
724 mutex_unlock(pdumpfs_mutex);
731 static const struct file_operations pdumpfs_current_fops = {
732 .owner = THIS_MODULE,
733 .llseek = pdumpfs_current_llseek,
734 .read = pdumpfs_current_read,
735 .open = pdumpfs_current_open,
736 .release = pdumpfs_current_release,
740 * So we can track when we can alter stream offsets.
743 pdumpfs_stream_open(struct inode *inode, struct file *filp)
747 mutex_lock(pdumpfs_mutex);
749 if (frame_stream_open_count)
752 frame_stream_open_count++;
756 mutex_unlock(pdumpfs_mutex);
761 pdumpfs_stream_release(struct inode *inode, struct file *filp)
763 mutex_lock(pdumpfs_mutex);
765 frame_stream_open_count--;
767 /* fix the damage done while it was open */
768 if (!frame_stream_open_count) {
769 stream_end -= stream_start;
774 mutex_unlock(pdumpfs_mutex);
779 pdumpfs_stream_buffer_clear(char __user *buf, size_t size)
783 memset(tmp, '.', sizeof(tmp) - 1);
784 tmp[sizeof(tmp) - 1] = '\n';
786 if (size >= sizeof(tmp)) {
789 for (i = 0; (i + sizeof(tmp)) < size; i += sizeof(tmp))
790 if (copy_to_user(buf + i, tmp, sizeof(tmp)))
794 if (copy_to_user(buf, tmp + sizeof(tmp) - size, size))
801 pdumpfs_stream_buffer_fill(struct pdumpfs_frame *frame,
802 char __user *buf, size_t offset, size_t size)
804 int page = offset / PAGE_SIZE;
806 if (size > (frame->offset - offset))
807 size = frame->offset - offset;
811 if (size > (PAGE_SIZE - offset))
812 size = PAGE_SIZE - offset;
814 if (copy_to_user(buf, ((u8 *) frame->pages[page]) + offset, size))
817 stream_f_pos += size;
823 pdumpfs_stream_llseek(struct file *filp, loff_t offset, int whence)
827 mutex_lock(pdumpfs_mutex);
831 if ((offset > stream_end) || (offset < stream_start))
837 if (((filp->f_pos + offset) > stream_end) ||
838 ((filp->f_pos + offset) < stream_start))
841 f_pos = filp->f_pos + offset;
845 (offset < (stream_start - stream_end)))
848 f_pos = stream_end + offset;
857 stream_f_pos = f_pos;
860 mutex_unlock(pdumpfs_mutex);
866 pdumpfs_stream_read(struct file *filp, char __user *buf, size_t size,
871 mutex_lock(pdumpfs_mutex);
873 if ((stream_end <= 0) || (*f_pos >= stream_end))
875 else if (*f_pos < stream_start) {
876 if (size > (stream_start - *f_pos))
877 size = stream_start - *f_pos;
878 ret = pdumpfs_stream_buffer_clear(buf, size);
880 loff_t start = stream_start;
881 struct pdumpfs_frame *frame = frame_stream;
883 /* skip frames that are before our offset */
884 while ((start + frame->offset) <= *f_pos) {
885 start += frame->offset;
889 ret = pdumpfs_stream_buffer_fill(frame, buf, *f_pos - start,
895 mutex_unlock(pdumpfs_mutex);
899 static const struct file_operations pdumpfs_stream_fops = {
900 .owner = THIS_MODULE,
901 .llseek = pdumpfs_stream_llseek,
902 .read = pdumpfs_stream_read,
903 .open = pdumpfs_stream_open,
904 .release = pdumpfs_stream_release,
907 static struct dentry *pdumpfs_dir;
910 pdumpfs_file_create(const char *name, mode_t mode,
911 const struct file_operations *fops)
913 struct dentry *tmp = NULL;
915 tmp = debugfs_create_file(name, mode, pdumpfs_dir, NULL, fops);
917 pr_err("%s: failed to create pvr/%s file.\n", __func__, name);
921 pdumpfs_fs_init(void)
923 if (!pvr_debugfs_dir) {
924 pr_err("%s: debugfs pvr/ directory does not exist.\n",
929 pdumpfs_dir = debugfs_create_dir("pdump", pvr_debugfs_dir);
931 pr_err("%s: failed to create top level directory.\n",
936 pdumpfs_file_create("mode", S_IRUSR | S_IWUSR,
938 pdumpfs_file_create("modes_possible", S_IRUSR,
939 &pdumpfs_modes_possible_fops);
941 pdumpfs_file_create("frame_count_max", S_IRUSR | S_IWUSR,
942 &pdumpfs_frame_count_max_fops);
944 pdumpfs_file_create("init_frame", S_IRUSR,
946 pdumpfs_file_create("current_frame", S_IRUSR,
947 &pdumpfs_current_fops);
948 pdumpfs_file_create("stream_frames", S_IRUSR,
949 &pdumpfs_stream_fops);
955 pdumpfs_fs_destroy(void)
958 debugfs_remove_recursive(pdumpfs_dir);
966 mutex_init(pdumpfs_mutex);
968 ret = frame_new(0, 0);
978 pdumpfs_cleanup(void)
980 pdumpfs_fs_destroy();