Guest User

Untitled

a guest
Mar 30th, 2012
788
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.57 KB | None | 0 0
  1. diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
  2. index c26496e..8926d16 100644
  3. --- a/drivers/gpu/msm/kgsl.c
  4. +++ b/drivers/gpu/msm/kgsl.c
  5. @@ -33,7 +33,7 @@
  6. #include <linux/notifier.h>
  7. #include <linux/pm_runtime.h>
  8. #include <asm/atomic.h>
  9. -
  10. +#include <linux/genlock.h>
  11. #include <linux/ashmem.h>
  12.  
  13. #include "kgsl.h"
  14. @@ -56,7 +56,64 @@ int kgsl_pagetable_count = KGSL_PAGETABLE_COUNT;
  15. module_param_named(ptcount, kgsl_pagetable_count, int, 0);
  16. MODULE_PARM_DESC(kgsl_pagetable_count,
  17. "Minimum number of pagetables for KGSL to allocate at initialization time");
  18. +#ifdef CONFIG_GENLOCK
  19. +
  20. +/**
  21. + * kgsl_add_event - Add a new timstamp event for the KGSL device
  22. + * @device - KGSL device for the new event
  23. + * @ts - the timestamp to trigger the event on
  24. + * @cb - callback function to call when the timestamp expires
  25. + * @priv - private data for the specific event type
  26. + *
  27. + * @returns - 0 on success or error code on failure
  28. + */
  29. +
  30. +static int kgsl_add_event(struct kgsl_device *device, u32 ts,
  31. + void (*cb)(struct kgsl_device *, void *, u32), void *priv)
  32. +{
  33. + struct kgsl_event *event;
  34. + struct list_head *n;
  35. +/* FIXME
  36. + unsigned int cur = device->ftbl->readtimestamp(device,
  37. +*/
  38. + unsigned int cur = device->ftbl.device_cmdstream_readtimestamp(device,
  39. + KGSL_TIMESTAMP_RETIRED);
  40. +
  41. + if (cb == NULL)
  42. + return -EINVAL;
  43. +
  44. + /* Check to see if the requested timestamp has already fired */
  45. +
  46. + if (timestamp_cmp(cur, ts) >= 0) {
  47. + cb(device, priv, cur);
  48. + return 0;
  49. + }
  50. +
  51. + event = kzalloc(sizeof(*event), GFP_KERNEL);
  52. + if (event == NULL)
  53. + return -ENOMEM;
  54. +
  55. + event->timestamp = ts;
  56. + event->priv = priv;
  57. + event->func = cb;
  58. +
  59. + /* Add the event in order to the list */
  60. +
  61. + for (n = device->events.next ; n != &device->events; n = n->next) {
  62. + struct kgsl_event *e =
  63. + list_entry(n, struct kgsl_event, list);
  64. +
  65. + if (timestamp_cmp(e->timestamp, ts) > 0) {
  66. + list_add(&event->list, n->prev);
  67. + break;
  68. + } }
  69. +
  70. + if (n == &device->events)
  71. + list_add_tail(&event->list, &device->events);
  72.  
  73. + return 0;
  74. +}
  75. +#endif
  76. static void kgsl_put_phys_file(struct file *file);
  77.  
  78. /* Allocate a new context id */
  79. @@ -1649,6 +1706,114 @@ done:
  80. return result;
  81. }
  82.  
  83. +#ifdef CONFIG_GENLOCK
  84. +struct kgsl_genlock_event_priv {
  85. + struct genlock_handle *handle;
  86. + struct genlock *lock;
  87. +};
  88. +
  89. +/**
  90. + * kgsl_genlock_event_cb - Event callback for a genlock timestamp event
  91. + * @device - The KGSL device that expired the timestamp
  92. + * @priv - private data for the event
  93. + * @timestamp - the timestamp that triggered the event
  94. + *
  95. + * Release a genlock lock following the expiration of a timestamp
  96. + */
  97. +
  98. +static void kgsl_genlock_event_cb(struct kgsl_device *device,
  99. + void *priv, u32 timestamp)
  100. +{
  101. + struct kgsl_genlock_event_priv *ev = priv;
  102. + int ret;
  103. +
  104. + ret = genlock_lock(ev->handle, GENLOCK_UNLOCK, 0, 0);
  105. + if (ret)
  106. + KGSL_CORE_ERR("Error while unlocking genlock: %d\n", ret);
  107. +
  108. + genlock_put_handle(ev->handle);
  109. +
  110. + kfree(ev);
  111. +}
  112. +
  113. +/**
  114. + * kgsl_add_genlock-event - Create a new genlock event
  115. + * @device - KGSL device to create the event on
  116. + * @timestamp - Timestamp to trigger the event
  117. + * @data - User space buffer containing struct kgsl_genlock_event_priv
  118. + * @len - length of the userspace buffer
  119. + * @returns 0 on success or error code on error
  120. + *
  121. + * Attack to a genlock handle and register an event to release the
  122. + * genlock lock when the timestamp expires
  123. + */
  124. +
  125. +static int kgsl_add_genlock_event(struct kgsl_device *device,
  126. + u32 timestamp, void __user *data, int len)
  127. +{
  128. + struct kgsl_genlock_event_priv *event;
  129. + struct kgsl_timestamp_event_genlock priv;
  130. + int ret;
  131. +
  132. + if (len != sizeof(priv))
  133. + return -EINVAL;
  134. +
  135. + if (copy_from_user(&priv, data, sizeof(priv)))
  136. + return -EFAULT;
  137. +
  138. + event = kzalloc(sizeof(*event), GFP_KERNEL);
  139. +
  140. + if (event == NULL)
  141. + return -ENOMEM;
  142. +
  143. + event->handle = genlock_get_handle_fd(priv.handle);
  144. +
  145. + if (IS_ERR(event->handle)) {
  146. + int ret = PTR_ERR(event->handle);
  147. + kfree(event);
  148. + return ret;
  149. + }
  150. +
  151. + ret = kgsl_add_event(device, timestamp, kgsl_genlock_event_cb, event);
  152. + if (ret)
  153. + kfree(event);
  154. +
  155. + return ret;
  156. +}
  157. +#else
  158. +
  159. +static long kgsl_add_genlock_event(struct kgsl_device *device,
  160. + u32 timestamp, void __user *data, int len)
  161. +{
  162. + return -EINVAL;
  163. +}
  164. +#endif
  165. +/**
  166. + * kgsl_ioctl_timestamp_event - Register a new timestamp event from userspace
  167. + * @dev_priv - pointer to the private device structure
  168. + * @cmd - the ioctl cmd passed from kgsl_ioctl
  169. + * @data - the user data buffer from kgsl_ioctl
  170. + * @returns 0 on success or error code on failure
  171. + */
  172. +
  173. +static long kgsl_ioctl_timestamp_event(struct kgsl_device_private *dev_priv,
  174. + unsigned int cmd, void *data)
  175. +{
  176. + struct kgsl_timestamp_event *param = data;
  177. + int ret;
  178. +
  179. + switch (param->type) {
  180. + case KGSL_TIMESTAMP_EVENT_GENLOCK:
  181. + ret = kgsl_add_genlock_event(dev_priv->device,
  182. + param->timestamp, param->priv, param->len);
  183. + break;
  184. + default:
  185. + ret = -EINVAL;
  186. + }
  187. +
  188. + return ret;
  189. +}
  190. +
  191. typedef long (*kgsl_ioctl_func_t)(struct kgsl_device_private *,
  192. unsigned int, void *);
  193.  
  194. @@ -1662,8 +1827,6 @@ static const struct {
  195. } kgsl_ioctl_funcs[] = {
  196. KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_GETPROPERTY,
  197. kgsl_ioctl_device_getproperty, 1),
  198. - KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_REGREAD,
  199. - kgsl_ioctl_device_regread, 1),
  200. KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP,
  201. kgsl_ioctl_device_waittimestamp, 1),
  202. KGSL_IOCTL_FUNC(IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS,
  203. @@ -1686,6 +1849,10 @@ static const struct {
  204. kgsl_ioctl_sharedmem_from_vmalloc, 0),
  205. KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FLUSH_CACHE,
  206. kgsl_ioctl_sharedmem_flush_cache, 0),
  207. + KGSL_IOCTL_FUNC(IOCTL_KGSL_TIMESTAMP_EVENT,
  208. + kgsl_ioctl_timestamp_event, 1),
  209. + KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_REGREAD,
  210. + kgsl_ioctl_device_regread, 1),
  211. };
  212.  
  213. static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
  214. diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
  215. index b349c42..62b5a6a 100644
  216. --- a/drivers/gpu/msm/kgsl_device.h
  217. +++ b/drivers/gpu/msm/kgsl_device.h
  218. @@ -141,6 +141,13 @@ struct kgsl_memregion {
  219. unsigned int sizebytes;
  220. };
  221.  
  222. +struct kgsl_event {
  223. + uint32_t timestamp;
  224. + void (*func)(struct kgsl_device *, void *, u32);
  225. + void *priv;
  226. + struct list_head list;
  227. +};
  228. +
  229. struct kgsl_device {
  230. struct device *dev;
  231. const char *name;
  232. @@ -185,6 +192,8 @@ struct kgsl_device {
  233. int mem_log;
  234. int pwr_log;
  235. struct wake_lock idle_wakelock;
  236. +
  237. + struct list_head events;
  238. };
  239.  
  240. struct kgsl_context {
  241. diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
  242. index 2fc6c00..890f123 100644
  243. --- a/include/linux/msm_kgsl.h
  244. +++ b/include/linux/msm_kgsl.h
  245. @@ -417,6 +417,30 @@ struct kgsl_cmdwindow_write {
  246. #define IOCTL_KGSL_CMDWINDOW_WRITE \
  247. _IOW(KGSL_IOC_TYPE, 0x2e, struct kgsl_cmdwindow_write)
  248.  
  249. +/*
  250. + * A timestamp event allows the user space to register an action following an
  251. + * expired timestamp.
  252. + */
  253. +
  254. +struct kgsl_timestamp_event {
  255. + int type; /* Type of event (see list below) */
  256. + unsigned int timestamp; /* Timestamp to trigger event on */
  257. + unsigned int context_id; /* Context for the timestamp */
  258. + void *priv; /* Pointer to the event specific blob */
  259. + size_t len; /* Size of the event specific blob */
  260. +};
  261. +
  262. +#define IOCTL_KGSL_TIMESTAMP_EVENT \
  263. + _IOW(KGSL_IOC_TYPE, 0x31, struct kgsl_timestamp_event)
  264. +
  265. +/* A genlock timestamp event releases an existing lock on timestamp expire */
  266. +
  267. +#define KGSL_TIMESTAMP_EVENT_GENLOCK 1
  268. +
  269. +struct kgsl_timestamp_event_genlock {
  270. + int handle; /* Handle of the genlock lock to release */
  271. +};
  272. +
  273. #ifdef __KERNEL__
  274. #ifdef CONFIG_MSM_KGSL_DRM
  275. int kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start,
Advertisement
Add Comment
Please, Sign In to add comment