Commit 1c0c8461 authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Linus Torvalds

ps3fb: thread updates

ps3fb: Replace the kernel_thread and the semaphore by a proper kthread, which
is simply woken up when the screen must be updated
Signed-off-by: default avatarGeert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 254f9c5c
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/fb.h> #include <linux/fb.h>
...@@ -129,7 +131,6 @@ struct ps3fb_priv { ...@@ -129,7 +131,6 @@ struct ps3fb_priv {
u64 context_handle, memory_handle; u64 context_handle, memory_handle;
void *xdr_ea; void *xdr_ea;
struct gpu_driver_info *dinfo; struct gpu_driver_info *dinfo;
struct semaphore sem;
u32 res_index; u32 res_index;
u64 vblank_count; /* frame count */ u64 vblank_count; /* frame count */
...@@ -139,6 +140,8 @@ struct ps3fb_priv { ...@@ -139,6 +140,8 @@ struct ps3fb_priv {
atomic_t ext_flip; /* on/off flip with vsync */ atomic_t ext_flip; /* on/off flip with vsync */
atomic_t f_count; /* fb_open count */ atomic_t f_count; /* fb_open count */
int is_blanked; int is_blanked;
int is_kicked;
struct task_struct *task;
}; };
static struct ps3fb_priv ps3fb; static struct ps3fb_priv ps3fb;
...@@ -805,11 +808,14 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, ...@@ -805,11 +808,14 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
static int ps3fbd(void *arg) static int ps3fbd(void *arg)
{ {
daemonize("ps3fbd"); while (!kthread_should_stop()) {
for (;;) { try_to_freeze();
down(&ps3fb.sem); set_current_state(TASK_INTERRUPTIBLE);
if (atomic_read(&ps3fb.ext_flip) == 0) if (ps3fb.is_kicked) {
ps3fb.is_kicked = 0;
ps3fb_sync(0); /* single buffer */ ps3fb_sync(0); /* single buffer */
}
schedule();
} }
return 0; return 0;
} }
...@@ -830,8 +836,11 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr) ...@@ -830,8 +836,11 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) { if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
/* VSYNC */ /* VSYNC */
ps3fb.vblank_count = head->vblank_count; ps3fb.vblank_count = head->vblank_count;
if (!ps3fb.is_blanked) if (ps3fb.task && !ps3fb.is_blanked &&
up(&ps3fb.sem); !atomic_read(&ps3fb.ext_flip)) {
ps3fb.is_kicked = 1;
wake_up_process(ps3fb.task);
}
wake_up_interruptible(&ps3fb.wait_vsync); wake_up_interruptible(&ps3fb.wait_vsync);
} }
...@@ -968,6 +977,7 @@ static int __init ps3fb_probe(struct platform_device *dev) ...@@ -968,6 +977,7 @@ static int __init ps3fb_probe(struct platform_device *dev)
u64 xdr_lpar; u64 xdr_lpar;
int status; int status;
unsigned long offset; unsigned long offset;
struct task_struct *task;
/* get gpu context handle */ /* get gpu context handle */
status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0, status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
...@@ -1050,9 +1060,18 @@ static int __init ps3fb_probe(struct platform_device *dev) ...@@ -1050,9 +1060,18 @@ static int __init ps3fb_probe(struct platform_device *dev)
"fb%d: PS3 frame buffer device, using %ld KiB of video memory\n", "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
info->node, ps3fb_videomemory.size >> 10); info->node, ps3fb_videomemory.size >> 10);
kernel_thread(ps3fbd, info, CLONE_KERNEL); task = kthread_run(ps3fbd, info, "ps3fbd");
if (IS_ERR(task)) {
retval = PTR_ERR(task);
goto err_unregister_framebuffer;
}
ps3fb.task = task;
return 0; return 0;
err_unregister_framebuffer:
unregister_framebuffer(info);
err_fb_dealloc: err_fb_dealloc:
fb_dealloc_cmap(&info->cmap); fb_dealloc_cmap(&info->cmap);
err_framebuffer_release: err_framebuffer_release:
...@@ -1083,6 +1102,11 @@ void ps3fb_cleanup(void) ...@@ -1083,6 +1102,11 @@ void ps3fb_cleanup(void)
{ {
int status; int status;
if (ps3fb.task) {
struct task_struct *task = ps3fb.task;
ps3fb.task = NULL;
kthread_stop(task);
}
if (ps3fb.irq_no) { if (ps3fb.irq_no) {
free_irq(ps3fb.irq_no, ps3fb.dev); free_irq(ps3fb.irq_no, ps3fb.dev);
ps3_free_irq(ps3fb.irq_no); ps3_free_irq(ps3fb.irq_no);
...@@ -1195,7 +1219,6 @@ static int __init ps3fb_init(void) ...@@ -1195,7 +1219,6 @@ static int __init ps3fb_init(void)
atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */
atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */
init_MUTEX(&ps3fb.sem);
init_waitqueue_head(&ps3fb.wait_vsync); init_waitqueue_head(&ps3fb.wait_vsync);
ps3fb.num_frames = 1; ps3fb.num_frames = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment