blob: 3935164897f54a38a3e3dc89df6e57daa878f43b [file] [log] [blame]
Jordan Crouseef3456c2013-01-04 16:46:51 -07001/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#ifndef __KGSL_H
14#define __KGSL_H
15
16#include <linux/types.h>
17#include <linux/msm_kgsl.h>
18#include <linux/platform_device.h>
19#include <linux/clk.h>
20#include <linux/interrupt.h>
21#include <linux/mutex.h>
22#include <linux/cdev.h>
23#include <linux/regulator/consumer.h>
Harsh Vardhan Dwivedi8cb835b2012-03-29 17:23:11 -060024#include <linux/mm.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070025
Jordan Crouse914de9b2012-07-09 13:49:46 -060026#include <mach/kgsl.h>
27
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070028#define KGSL_NAME "kgsl"
29
Carter Cooper7e7f02e2012-02-15 09:36:31 -070030/* The number of memstore arrays limits the number of contexts allowed.
31 * If more contexts are needed, update multiple for MEMSTORE_SIZE
32 */
33#define KGSL_MEMSTORE_SIZE ((int)(PAGE_SIZE * 2))
34#define KGSL_MEMSTORE_GLOBAL (0)
35#define KGSL_MEMSTORE_MAX (KGSL_MEMSTORE_SIZE / \
36 sizeof(struct kgsl_devmemstore) - 1)
37
Jeff Boody23bfaa22012-04-24 14:57:45 -060038/* Timestamp window used to detect rollovers (half of integer range) */
Jeff Boody86149482012-04-17 09:30:19 -060039#define KGSL_TIMESTAMP_WINDOW 0x80000000
40
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070041/*cache coherency ops */
42#define DRM_KGSL_GEM_CACHE_OP_TO_DEV 0x0001
43#define DRM_KGSL_GEM_CACHE_OP_FROM_DEV 0x0002
44
45/* The size of each entry in a page table */
46#define KGSL_PAGETABLE_ENTRY_SIZE 4
47
48/* Pagetable Virtual Address base */
Shubhraprakash Dasf6920742012-05-01 01:48:37 -060049#define KGSL_PAGETABLE_BASE 0x10000000
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070050
51/* Extra accounting entries needed in the pagetable */
52#define KGSL_PT_EXTRA_ENTRIES 16
53
54#define KGSL_PAGETABLE_ENTRIES(_sz) (((_sz) >> PAGE_SHIFT) + \
55 KGSL_PT_EXTRA_ENTRIES)
56
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070057#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
58#define KGSL_PAGETABLE_COUNT (CONFIG_MSM_KGSL_PAGE_TABLE_COUNT)
59#else
60#define KGSL_PAGETABLE_COUNT 1
61#endif
62
63/* Casting using container_of() for structures that kgsl owns. */
64#define KGSL_CONTAINER_OF(ptr, type, member) \
65 container_of(ptr, type, member)
66
67/* A macro for memory statistics - add the new size to the stat and if
68 the statisic is greater then _max, set _max
69*/
70
71#define KGSL_STATS_ADD(_size, _stat, _max) \
72 do { _stat += (_size); if (_stat > _max) _max = _stat; } while (0)
73
74struct kgsl_device;
Jordan Crouseef3456c2013-01-04 16:46:51 -070075struct kgsl_context;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070076
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070077struct kgsl_driver {
78 struct cdev cdev;
79 dev_t major;
80 struct class *class;
81 /* Virtual device for managing the core */
82 struct device virtdev;
83 /* Kobjects for storing pagetable and process statistics */
84 struct kobject *ptkobj;
85 struct kobject *prockobj;
86 struct kgsl_device *devp[KGSL_DEVICE_MAX];
87
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070088 /* Global lilst of open processes */
89 struct list_head process_list;
90 /* Global list of pagetables */
91 struct list_head pagetable_list;
92 /* Spinlock for accessing the pagetable list */
93 spinlock_t ptlock;
94 /* Mutex for accessing the process list */
95 struct mutex process_mutex;
96
97 /* Mutex for protecting the device list */
98 struct mutex devlock;
99
Shubhraprakash Das767fdda2011-08-15 15:49:45 -0600100 void *ptpool;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700101
102 struct {
103 unsigned int vmalloc;
104 unsigned int vmalloc_max;
Harsh Vardhan Dwivedif99c2632012-03-15 14:17:11 -0600105 unsigned int page_alloc;
106 unsigned int page_alloc_max;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700107 unsigned int coherent;
108 unsigned int coherent_max;
109 unsigned int mapped;
110 unsigned int mapped_max;
111 unsigned int histogram[16];
112 } stats;
113};
114
115extern struct kgsl_driver kgsl_driver;
116
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117struct kgsl_pagetable;
Harsh Vardhan Dwivedi8cb835b2012-03-29 17:23:11 -0600118struct kgsl_memdesc;
119
120struct kgsl_memdesc_ops {
121 int (*vmflags)(struct kgsl_memdesc *);
122 int (*vmfault)(struct kgsl_memdesc *, struct vm_area_struct *,
123 struct vm_fault *);
124 void (*free)(struct kgsl_memdesc *memdesc);
125 int (*map_kernel_mem)(struct kgsl_memdesc *);
126};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700127
Jordan Crousedc67dfb2012-10-25 09:41:46 -0600128/* Internal definitions for memdesc->priv */
Jordan Crouse7d3139b2012-05-18 10:05:02 -0600129#define KGSL_MEMDESC_GUARD_PAGE BIT(0)
Jordan Crousedc67dfb2012-10-25 09:41:46 -0600130/* Set if the memdesc is mapped into all pagetables */
131#define KGSL_MEMDESC_GLOBAL BIT(1)
Jordan Crouse7d3139b2012-05-18 10:05:02 -0600132
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700133/* shared memory allocation */
134struct kgsl_memdesc {
135 struct kgsl_pagetable *pagetable;
136 void *hostptr;
137 unsigned int gpuaddr;
138 unsigned int physaddr;
139 unsigned int size;
Jordan Crousedc67dfb2012-10-25 09:41:46 -0600140 unsigned int priv; /* Internal flags and settings */
Jordan Croused17e9aa2011-10-12 16:57:48 -0600141 struct scatterlist *sg;
Rajeev Kulkarni8dfdc3362012-11-22 00:22:32 -0800142 unsigned int sglen; /* Active entries in the sglist */
143 unsigned int sglen_alloc; /* Allocated entries in the sglist */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700144 struct kgsl_memdesc_ops *ops;
Jordan Crousedc67dfb2012-10-25 09:41:46 -0600145 unsigned int flags; /* Flags set from userspace */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700146};
147
Jordan Crouse1b897cf2011-10-12 16:57:48 -0600148/* List of different memory entry types */
149
150#define KGSL_MEM_ENTRY_KERNEL 0
151#define KGSL_MEM_ENTRY_PMEM 1
152#define KGSL_MEM_ENTRY_ASHMEM 2
153#define KGSL_MEM_ENTRY_USER 3
Jordan Crouse8eab35a2011-10-12 16:57:48 -0600154#define KGSL_MEM_ENTRY_ION 4
155#define KGSL_MEM_ENTRY_MAX 5
Jordan Crouse1b897cf2011-10-12 16:57:48 -0600156
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600157/* List of flags */
158
159#define KGSL_MEM_ENTRY_FROZEN (1 << 0)
160
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700161struct kgsl_mem_entry {
162 struct kref refcount;
163 struct kgsl_memdesc memdesc;
164 int memtype;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600165 int flags;
Jordan Crouse1b897cf2011-10-12 16:57:48 -0600166 void *priv_data;
Jordan Crousec9559e42012-04-05 16:55:56 -0600167 struct rb_node node;
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700168 unsigned int context_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700169 /* back pointer to private structure under whose context this
170 * allocation is made */
171 struct kgsl_process_private *priv;
172};
173
174#ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT
175#define MMU_CONFIG 2
176#else
177#define MMU_CONFIG 1
178#endif
179
180void kgsl_mem_entry_destroy(struct kref *kref);
Harsh Vardhan Dwivedi715fb832012-05-18 00:24:18 -0600181int kgsl_postmortem_dump(struct kgsl_device *device, int manual);
Jordan Crouse0fdf3a02012-03-16 14:53:41 -0600182
Shubhraprakash Das3cf33be2012-08-16 22:42:55 -0700183struct kgsl_mem_entry *kgsl_get_mem_entry(struct kgsl_device *device,
184 unsigned int ptbase, unsigned int gpuaddr, unsigned int size);
Jordan Crouse0fdf3a02012-03-16 14:53:41 -0600185
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700186struct kgsl_mem_entry *kgsl_sharedmem_find_region(
187 struct kgsl_process_private *private, unsigned int gpuaddr,
188 size_t size);
189
Jeremy Gebben158a5c02012-09-24 14:27:25 -0600190void kgsl_get_memory_usage(char *str, size_t len, unsigned int memflags);
191
Shubhraprakash Dascb068072012-06-07 17:52:41 -0600192int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts,
193 void (*cb)(struct kgsl_device *, void *, u32, u32), void *priv,
194 void *owner);
195
196void kgsl_cancel_events(struct kgsl_device *device,
197 void *owner);
198
Jordan Crouseef3456c2013-01-04 16:46:51 -0700199void kgsl_cancel_events_ctxt(struct kgsl_device *device,
200 struct kgsl_context *context);
201
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700202extern const struct dev_pm_ops kgsl_pm_ops;
203
204struct early_suspend;
205int kgsl_suspend_driver(struct platform_device *pdev, pm_message_t state);
206int kgsl_resume_driver(struct platform_device *pdev);
207void kgsl_early_suspend_driver(struct early_suspend *h);
208void kgsl_late_resume_driver(struct early_suspend *h);
209
210#ifdef CONFIG_MSM_KGSL_DRM
211extern int kgsl_drm_init(struct platform_device *dev);
212extern void kgsl_drm_exit(void);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700213#else
214static inline int kgsl_drm_init(struct platform_device *dev)
215{
216 return 0;
217}
218
219static inline void kgsl_drm_exit(void)
220{
221}
222#endif
223
224static inline int kgsl_gpuaddr_in_memdesc(const struct kgsl_memdesc *memdesc,
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700225 unsigned int gpuaddr, unsigned int size)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700226{
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700227 if (gpuaddr >= memdesc->gpuaddr &&
228 ((gpuaddr + size) <= (memdesc->gpuaddr + memdesc->size))) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700229 return 1;
230 }
231 return 0;
232}
Jordan Crouse17d6d8b2012-04-18 09:31:09 -0600233
234static inline void *kgsl_memdesc_map(struct kgsl_memdesc *memdesc)
235{
Shubhraprakash Das80af30d2012-05-24 18:22:54 -0600236 if (memdesc->hostptr == NULL && memdesc->ops &&
237 memdesc->ops->map_kernel_mem)
Jordan Crouse17d6d8b2012-04-18 09:31:09 -0600238 memdesc->ops->map_kernel_mem(memdesc);
239
240 return memdesc->hostptr;
241}
242
Harsh Vardhan Dwivedi8cb835b2012-03-29 17:23:11 -0600243static inline uint8_t *kgsl_gpuaddr_to_vaddr(struct kgsl_memdesc *memdesc,
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700244 unsigned int gpuaddr)
245{
Jordan Crouse17d6d8b2012-04-18 09:31:09 -0600246 void *hostptr = NULL;
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700247
Jordan Crouse17d6d8b2012-04-18 09:31:09 -0600248 if ((gpuaddr >= memdesc->gpuaddr) &&
249 (gpuaddr < (memdesc->gpuaddr + memdesc->size)))
250 hostptr = kgsl_memdesc_map(memdesc);
251
252 return hostptr != NULL ? hostptr + (gpuaddr - memdesc->gpuaddr) : NULL;
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700253}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700254
Jeff Boody23bfaa22012-04-24 14:57:45 -0600255static inline int timestamp_cmp(unsigned int a, unsigned int b)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700256{
Jeff Boody23bfaa22012-04-24 14:57:45 -0600257 /* check for equal */
258 if (a == b)
Jordan Crousee6239dd2011-11-17 13:39:21 -0700259 return 0;
260
Jeff Boody23bfaa22012-04-24 14:57:45 -0600261 /* check for greater-than for non-rollover case */
262 if ((a > b) && (a - b < KGSL_TIMESTAMP_WINDOW))
263 return 1;
264
265 /* check for greater-than for rollover case
266 * note that <= is required to ensure that consistent
267 * results are returned for values whose difference is
268 * equal to the window size
269 */
270 a += KGSL_TIMESTAMP_WINDOW;
271 b += KGSL_TIMESTAMP_WINDOW;
272 return ((a > b) && (a - b <= KGSL_TIMESTAMP_WINDOW)) ? 1 : -1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700273}
274
275static inline void
276kgsl_mem_entry_get(struct kgsl_mem_entry *entry)
277{
278 kref_get(&entry->refcount);
279}
280
281static inline void
282kgsl_mem_entry_put(struct kgsl_mem_entry *entry)
283{
284 kref_put(&entry->refcount, kgsl_mem_entry_destroy);
285}
286
287#endif /* __KGSL_H */