|
@@ -32,6 +32,8 @@
|
|
|
#include <linux/ioctl.h>
|
|
|
#include <linux/notifier.h>
|
|
|
#include <linux/reboot.h>
|
|
|
+#include <linux/kthread.h>
|
|
|
+#include <linux/freezer.h>
|
|
|
|
|
|
#include <asm/uaccess.h>
|
|
|
#include <linux/fb.h>
|
|
@@ -129,7 +131,6 @@ struct ps3fb_priv {
|
|
|
u64 context_handle, memory_handle;
|
|
|
void *xdr_ea;
|
|
|
struct gpu_driver_info *dinfo;
|
|
|
- struct semaphore sem;
|
|
|
u32 res_index;
|
|
|
|
|
|
u64 vblank_count; /* frame count */
|
|
@@ -139,6 +140,8 @@ struct ps3fb_priv {
|
|
|
atomic_t ext_flip; /* on/off flip with vsync */
|
|
|
atomic_t f_count; /* fb_open count */
|
|
|
int is_blanked;
|
|
|
+ int is_kicked;
|
|
|
+ struct task_struct *task;
|
|
|
};
|
|
|
static struct ps3fb_priv ps3fb;
|
|
|
|
|
@@ -805,11 +808,14 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
|
|
|
|
|
|
static int ps3fbd(void *arg)
|
|
|
{
|
|
|
- daemonize("ps3fbd");
|
|
|
- for (;;) {
|
|
|
- down(&ps3fb.sem);
|
|
|
- if (atomic_read(&ps3fb.ext_flip) == 0)
|
|
|
+ while (!kthread_should_stop()) {
|
|
|
+ try_to_freeze();
|
|
|
+ set_current_state(TASK_INTERRUPTIBLE);
|
|
|
+ if (ps3fb.is_kicked) {
|
|
|
+ ps3fb.is_kicked = 0;
|
|
|
ps3fb_sync(0); /* single buffer */
|
|
|
+ }
|
|
|
+ schedule();
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
@@ -830,8 +836,11 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
|
|
|
if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
|
|
|
/* VSYNC */
|
|
|
ps3fb.vblank_count = head->vblank_count;
|
|
|
- if (!ps3fb.is_blanked)
|
|
|
- up(&ps3fb.sem);
|
|
|
+ if (ps3fb.task && !ps3fb.is_blanked &&
|
|
|
+ !atomic_read(&ps3fb.ext_flip)) {
|
|
|
+ ps3fb.is_kicked = 1;
|
|
|
+ wake_up_process(ps3fb.task);
|
|
|
+ }
|
|
|
wake_up_interruptible(&ps3fb.wait_vsync);
|
|
|
}
|
|
|
|
|
@@ -968,6 +977,7 @@ static int __init ps3fb_probe(struct platform_device *dev)
|
|
|
u64 xdr_lpar;
|
|
|
int status;
|
|
|
unsigned long offset;
|
|
|
+ struct task_struct *task;
|
|
|
|
|
|
/* get gpu context handle */
|
|
|
status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
|
|
@@ -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",
|
|
|
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;
|
|
|
|
|
|
+err_unregister_framebuffer:
|
|
|
+ unregister_framebuffer(info);
|
|
|
err_fb_dealloc:
|
|
|
fb_dealloc_cmap(&info->cmap);
|
|
|
err_framebuffer_release:
|
|
@@ -1083,6 +1102,11 @@ void ps3fb_cleanup(void)
|
|
|
{
|
|
|
int status;
|
|
|
|
|
|
+ if (ps3fb.task) {
|
|
|
+ struct task_struct *task = ps3fb.task;
|
|
|
+ ps3fb.task = NULL;
|
|
|
+ kthread_stop(task);
|
|
|
+ }
|
|
|
if (ps3fb.irq_no) {
|
|
|
free_irq(ps3fb.irq_no, ps3fb.dev);
|
|
|
ps3_free_irq(ps3fb.irq_no);
|
|
@@ -1195,7 +1219,6 @@ static int __init ps3fb_init(void)
|
|
|
|
|
|
atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */
|
|
|
atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */
|
|
|
- init_MUTEX(&ps3fb.sem);
|
|
|
init_waitqueue_head(&ps3fb.wait_vsync);
|
|
|
ps3fb.num_frames = 1;
|
|
|
|