2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2008-2013 ARM Limited
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
13 * Implementation of the OS abstraction layer for the kernel device driver
16 #include <linux/slab.h> /* For memory allocation */
17 #include <linux/workqueue.h>
18 #include <linux/version.h>
19 #include <linux/sched.h>
22 #include "mali_kernel_common.h"
23 #include "mali_kernel_license.h"
24 #include "mali_kernel_linux.h"
26 typedef struct _mali_osk_wq_work_s
{
27 _mali_osk_wq_work_handler_t handler
;
30 struct work_struct work_handle
;
31 } mali_osk_wq_work_object_t
;
33 typedef struct _mali_osk_wq_delayed_work_s
{
34 _mali_osk_wq_work_handler_t handler
;
36 struct delayed_work work
;
37 } mali_osk_wq_delayed_work_object_t
;
39 #if MALI_LICENSE_IS_GPL
40 struct workqueue_struct
*mali_wq_normal
= NULL
;
41 struct workqueue_struct
*mali_wq_high
= NULL
;
44 static void _mali_osk_wq_work_func(struct work_struct
*work
);
46 _mali_osk_errcode_t
_mali_osk_wq_init(void)
48 #if MALI_LICENSE_IS_GPL
49 MALI_DEBUG_ASSERT(NULL
== mali_wq_normal
);
50 MALI_DEBUG_ASSERT(NULL
== mali_wq_high
);
52 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
53 mali_wq_normal
= alloc_workqueue("mali", WQ_UNBOUND
, 0);
54 mali_wq_high
= alloc_workqueue("mali_high_pri", WQ_HIGHPRI
| WQ_UNBOUND
, 0);
56 mali_wq_normal
= create_workqueue("mali");
57 mali_wq_high
= create_workqueue("mali_high_pri");
59 if (NULL
== mali_wq_normal
|| NULL
== mali_wq_high
) {
60 MALI_PRINT_ERROR(("Unable to create Mali workqueues\n"));
62 if (mali_wq_normal
) destroy_workqueue(mali_wq_normal
);
63 if (mali_wq_high
) destroy_workqueue(mali_wq_high
);
65 mali_wq_normal
= NULL
;
68 return _MALI_OSK_ERR_FAULT
;
70 #endif /* MALI_LICENSE_IS_GPL */
72 return _MALI_OSK_ERR_OK
;
75 void _mali_osk_wq_flush(void)
77 #if MALI_LICENSE_IS_GPL
78 flush_workqueue(mali_wq_high
);
79 flush_workqueue(mali_wq_normal
);
81 flush_scheduled_work();
85 void _mali_osk_wq_term(void)
87 #if MALI_LICENSE_IS_GPL
88 MALI_DEBUG_ASSERT(NULL
!= mali_wq_normal
);
89 MALI_DEBUG_ASSERT(NULL
!= mali_wq_high
);
91 flush_workqueue(mali_wq_normal
);
92 destroy_workqueue(mali_wq_normal
);
94 flush_workqueue(mali_wq_high
);
95 destroy_workqueue(mali_wq_high
);
97 mali_wq_normal
= NULL
;
100 flush_scheduled_work();
104 _mali_osk_wq_work_t
*_mali_osk_wq_create_work( _mali_osk_wq_work_handler_t handler
, void *data
)
106 mali_osk_wq_work_object_t
*work
= kmalloc(sizeof(mali_osk_wq_work_object_t
), GFP_KERNEL
);
108 if (NULL
== work
) return NULL
;
110 work
->handler
= handler
;
112 work
->high_pri
= MALI_FALSE
;
114 INIT_WORK( &work
->work_handle
, _mali_osk_wq_work_func
);
119 _mali_osk_wq_work_t
*_mali_osk_wq_create_work_high_pri( _mali_osk_wq_work_handler_t handler
, void *data
)
121 mali_osk_wq_work_object_t
*work
= kmalloc(sizeof(mali_osk_wq_work_object_t
), GFP_KERNEL
);
123 if (NULL
== work
) return NULL
;
125 work
->handler
= handler
;
127 work
->high_pri
= MALI_TRUE
;
129 INIT_WORK( &work
->work_handle
, _mali_osk_wq_work_func
);
134 void _mali_osk_wq_delete_work( _mali_osk_wq_work_t
*work
)
136 mali_osk_wq_work_object_t
*work_object
= (mali_osk_wq_work_object_t
*)work
;
137 _mali_osk_wq_flush();
141 void _mali_osk_wq_delete_work_nonflush( _mali_osk_wq_work_t
*work
)
143 mali_osk_wq_work_object_t
*work_object
= (mali_osk_wq_work_object_t
*)work
;
147 void _mali_osk_wq_schedule_work( _mali_osk_wq_work_t
*work
)
149 mali_osk_wq_work_object_t
*work_object
= (mali_osk_wq_work_object_t
*)work
;
150 #if MALI_LICENSE_IS_GPL
151 queue_work(mali_wq_normal
, &work_object
->work_handle
);
153 schedule_work(&work_object
->work_handle
);
157 void _mali_osk_wq_schedule_work_high_pri( _mali_osk_wq_work_t
*work
)
159 mali_osk_wq_work_object_t
*work_object
= (mali_osk_wq_work_object_t
*)work
;
160 #if MALI_LICENSE_IS_GPL
161 queue_work(mali_wq_high
, &work_object
->work_handle
);
163 schedule_work(&work_object
->work_handle
);
167 static void _mali_osk_wq_work_func( struct work_struct
*work
)
169 mali_osk_wq_work_object_t
*work_object
;
171 work_object
= _MALI_OSK_CONTAINER_OF(work
, mali_osk_wq_work_object_t
, work_handle
);
173 #if MALI_LICENSE_IS_GPL
174 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
175 /* We want higher priority than the Dynamic Priority, setting it to the lowest of the RT priorities */
176 if (MALI_TRUE
== work_object
->high_pri
) {
177 set_user_nice(current
, -19);
180 #endif /* MALI_LICENSE_IS_GPL */
182 work_object
->handler(work_object
->data
);
185 static void _mali_osk_wq_delayed_work_func( struct work_struct
*work
)
187 mali_osk_wq_delayed_work_object_t
*work_object
;
189 work_object
= _MALI_OSK_CONTAINER_OF(work
, mali_osk_wq_delayed_work_object_t
, work
.work
);
190 work_object
->handler(work_object
->data
);
193 mali_osk_wq_delayed_work_object_t
*_mali_osk_wq_delayed_create_work( _mali_osk_wq_work_handler_t handler
, void *data
)
195 mali_osk_wq_delayed_work_object_t
*work
= kmalloc(sizeof(mali_osk_wq_delayed_work_object_t
), GFP_KERNEL
);
197 if (NULL
== work
) return NULL
;
199 work
->handler
= handler
;
202 INIT_DELAYED_WORK(&work
->work
, _mali_osk_wq_delayed_work_func
);
207 void _mali_osk_wq_delayed_delete_work_nonflush( _mali_osk_wq_delayed_work_t
*work
)
209 mali_osk_wq_delayed_work_object_t
*work_object
= (mali_osk_wq_delayed_work_object_t
*)work
;
213 void _mali_osk_wq_delayed_cancel_work_async( _mali_osk_wq_delayed_work_t
*work
)
215 mali_osk_wq_delayed_work_object_t
*work_object
= (mali_osk_wq_delayed_work_object_t
*)work
;
216 cancel_delayed_work(&work_object
->work
);
219 void _mali_osk_wq_delayed_cancel_work_sync( _mali_osk_wq_delayed_work_t
*work
)
221 mali_osk_wq_delayed_work_object_t
*work_object
= (mali_osk_wq_delayed_work_object_t
*)work
;
222 cancel_delayed_work_sync(&work_object
->work
);
225 void _mali_osk_wq_delayed_schedule_work( _mali_osk_wq_delayed_work_t
*work
, u32 delay
)
227 mali_osk_wq_delayed_work_object_t
*work_object
= (mali_osk_wq_delayed_work_object_t
*)work
;
229 #if MALI_LICENSE_IS_GPL
230 queue_delayed_work(mali_wq_normal
, &work_object
->work
, delay
);
232 schedule_delayed_work(&work_object
->work
, delay
);