blob: 7ffa83b663fe5c0d29044a0dad5251b01c3bbd4e [file] [log] [blame]
Jordan Crouse0fdf3a02012-03-16 14:53:41 -06001/* Copyright (c) 2008-2012, Code Aurora Forum. 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
26#define KGSL_NAME "kgsl"
27
Carter Cooper7e7f02e2012-02-15 09:36:31 -070028/* The number of memstore arrays limits the number of contexts allowed.
29 * If more contexts are needed, update multiple for MEMSTORE_SIZE
30 */
31#define KGSL_MEMSTORE_SIZE ((int)(PAGE_SIZE * 2))
32#define KGSL_MEMSTORE_GLOBAL (0)
33#define KGSL_MEMSTORE_MAX (KGSL_MEMSTORE_SIZE / \
34 sizeof(struct kgsl_devmemstore) - 1)
35
Jeff Boody23bfaa22012-04-24 14:57:45 -060036/* Timestamp window used to detect rollovers (half of integer range) */
Jeff Boody86149482012-04-17 09:30:19 -060037#define KGSL_TIMESTAMP_WINDOW 0x80000000
38
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070039/*cache coherency ops */
40#define DRM_KGSL_GEM_CACHE_OP_TO_DEV 0x0001
41#define DRM_KGSL_GEM_CACHE_OP_FROM_DEV 0x0002
42
43/* The size of each entry in a page table */
44#define KGSL_PAGETABLE_ENTRY_SIZE 4
45
46/* Pagetable Virtual Address base */
Shubhraprakash Dasf6920742012-05-01 01:48:37 -060047#define KGSL_PAGETABLE_BASE 0x10000000
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070048
49/* Extra accounting entries needed in the pagetable */
50#define KGSL_PT_EXTRA_ENTRIES 16
51
52#define KGSL_PAGETABLE_ENTRIES(_sz) (((_sz) >> PAGE_SHIFT) + \
53 KGSL_PT_EXTRA_ENTRIES)
54
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070055#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
56#define KGSL_PAGETABLE_COUNT (CONFIG_MSM_KGSL_PAGE_TABLE_COUNT)
57#else
58#define KGSL_PAGETABLE_COUNT 1
59#endif
60
61/* Casting using container_of() for structures that kgsl owns. */
62#define KGSL_CONTAINER_OF(ptr, type, member) \
63 container_of(ptr, type, member)
64
65/* A macro for memory statistics - add the new size to the stat and if
66 the statisic is greater then _max, set _max
67*/
68
69#define KGSL_STATS_ADD(_size, _stat, _max) \
70 do { _stat += (_size); if (_stat > _max) _max = _stat; } while (0)
71
72struct kgsl_device;
73
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070074struct kgsl_driver {
75 struct cdev cdev;
76 dev_t major;
77 struct class *class;
78 /* Virtual device for managing the core */
79 struct device virtdev;
80 /* Kobjects for storing pagetable and process statistics */
81 struct kobject *ptkobj;
82 struct kobject *prockobj;
83 struct kgsl_device *devp[KGSL_DEVICE_MAX];
84
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070085 /* Global lilst of open processes */
86 struct list_head process_list;
87 /* Global list of pagetables */
88 struct list_head pagetable_list;
89 /* Spinlock for accessing the pagetable list */
90 spinlock_t ptlock;
91 /* Mutex for accessing the process list */
92 struct mutex process_mutex;
93
94 /* Mutex for protecting the device list */
95 struct mutex devlock;
96
Shubhraprakash Das767fdda2011-08-15 15:49:45 -060097 void *ptpool;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070098
99 struct {
100 unsigned int vmalloc;
101 unsigned int vmalloc_max;
Harsh Vardhan Dwivedif99c2632012-03-15 14:17:11 -0600102 unsigned int page_alloc;
103 unsigned int page_alloc_max;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700104 unsigned int coherent;
105 unsigned int coherent_max;
106 unsigned int mapped;
107 unsigned int mapped_max;
108 unsigned int histogram[16];
109 } stats;
110};
111
112extern struct kgsl_driver kgsl_driver;
113
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700114struct kgsl_pagetable;
Harsh Vardhan Dwivedi8cb835b2012-03-29 17:23:11 -0600115struct kgsl_memdesc;
116
117struct kgsl_memdesc_ops {
118 int (*vmflags)(struct kgsl_memdesc *);
119 int (*vmfault)(struct kgsl_memdesc *, struct vm_area_struct *,
120 struct vm_fault *);
121 void (*free)(struct kgsl_memdesc *memdesc);
122 int (*map_kernel_mem)(struct kgsl_memdesc *);
123};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700124
Jordan Crouse7d3139b2012-05-18 10:05:02 -0600125#define KGSL_MEMDESC_GUARD_PAGE BIT(0)
126
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700127/* shared memory allocation */
128struct kgsl_memdesc {
129 struct kgsl_pagetable *pagetable;
130 void *hostptr;
131 unsigned int gpuaddr;
132 unsigned int physaddr;
133 unsigned int size;
134 unsigned int priv;
Jordan Croused17e9aa2011-10-12 16:57:48 -0600135 struct scatterlist *sg;
136 unsigned int sglen;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700137 struct kgsl_memdesc_ops *ops;
Jordan Crouse7d3139b2012-05-18 10:05:02 -0600138 int flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700139};
140
Jordan Crouse1b897cf2011-10-12 16:57:48 -0600141/* List of different memory entry types */
142
143#define KGSL_MEM_ENTRY_KERNEL 0
144#define KGSL_MEM_ENTRY_PMEM 1
145#define KGSL_MEM_ENTRY_ASHMEM 2
146#define KGSL_MEM_ENTRY_USER 3
Jordan Crouse8eab35a2011-10-12 16:57:48 -0600147#define KGSL_MEM_ENTRY_ION 4
148#define KGSL_MEM_ENTRY_MAX 5
Jordan Crouse1b897cf2011-10-12 16:57:48 -0600149
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600150/* List of flags */
151
152#define KGSL_MEM_ENTRY_FROZEN (1 << 0)
153
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700154struct kgsl_mem_entry {
155 struct kref refcount;
156 struct kgsl_memdesc memdesc;
157 int memtype;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600158 int flags;
Jordan Crouse1b897cf2011-10-12 16:57:48 -0600159 void *priv_data;
Jordan Crousec9559e42012-04-05 16:55:56 -0600160 struct rb_node node;
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700161 unsigned int context_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700162 /* back pointer to private structure under whose context this
163 * allocation is made */
164 struct kgsl_process_private *priv;
165};
166
167#ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT
168#define MMU_CONFIG 2
169#else
170#define MMU_CONFIG 1
171#endif
172
173void kgsl_mem_entry_destroy(struct kref *kref);
Jordan Crouse0fdf3a02012-03-16 14:53:41 -0600174
175struct kgsl_mem_entry *kgsl_get_mem_entry(unsigned int ptbase,
176 unsigned int gpuaddr, unsigned int size);
177
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700178struct kgsl_mem_entry *kgsl_sharedmem_find_region(
179 struct kgsl_process_private *private, unsigned int gpuaddr,
180 size_t size);
181
Shubhraprakash Dascb068072012-06-07 17:52:41 -0600182int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts,
183 void (*cb)(struct kgsl_device *, void *, u32, u32), void *priv,
184 void *owner);
185
186void kgsl_cancel_events(struct kgsl_device *device,
187 void *owner);
188
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700189extern const struct dev_pm_ops kgsl_pm_ops;
190
191struct early_suspend;
192int kgsl_suspend_driver(struct platform_device *pdev, pm_message_t state);
193int kgsl_resume_driver(struct platform_device *pdev);
194void kgsl_early_suspend_driver(struct early_suspend *h);
195void kgsl_late_resume_driver(struct early_suspend *h);
196
197#ifdef CONFIG_MSM_KGSL_DRM
198extern int kgsl_drm_init(struct platform_device *dev);
199extern void kgsl_drm_exit(void);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700200#else
201static inline int kgsl_drm_init(struct platform_device *dev)
202{
203 return 0;
204}
205
206static inline void kgsl_drm_exit(void)
207{
208}
209#endif
210
211static inline int kgsl_gpuaddr_in_memdesc(const struct kgsl_memdesc *memdesc,
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700212 unsigned int gpuaddr, unsigned int size)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700213{
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700214 if (gpuaddr >= memdesc->gpuaddr &&
215 ((gpuaddr + size) <= (memdesc->gpuaddr + memdesc->size))) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700216 return 1;
217 }
218 return 0;
219}
Jordan Crouse17d6d8b2012-04-18 09:31:09 -0600220
221static inline void *kgsl_memdesc_map(struct kgsl_memdesc *memdesc)
222{
Shubhraprakash Das80af30d2012-05-24 18:22:54 -0600223 if (memdesc->hostptr == NULL && memdesc->ops &&
224 memdesc->ops->map_kernel_mem)
Jordan Crouse17d6d8b2012-04-18 09:31:09 -0600225 memdesc->ops->map_kernel_mem(memdesc);
226
227 return memdesc->hostptr;
228}
229
Harsh Vardhan Dwivedi8cb835b2012-03-29 17:23:11 -0600230static inline uint8_t *kgsl_gpuaddr_to_vaddr(struct kgsl_memdesc *memdesc,
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700231 unsigned int gpuaddr)
232{
Jordan Crouse17d6d8b2012-04-18 09:31:09 -0600233 void *hostptr = NULL;
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700234
Jordan Crouse17d6d8b2012-04-18 09:31:09 -0600235 if ((gpuaddr >= memdesc->gpuaddr) &&
236 (gpuaddr < (memdesc->gpuaddr + memdesc->size)))
237 hostptr = kgsl_memdesc_map(memdesc);
238
239 return hostptr != NULL ? hostptr + (gpuaddr - memdesc->gpuaddr) : NULL;
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700240}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700241
Jeff Boody23bfaa22012-04-24 14:57:45 -0600242static inline int timestamp_cmp(unsigned int a, unsigned int b)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700243{
Jeff Boody23bfaa22012-04-24 14:57:45 -0600244 /* check for equal */
245 if (a == b)
Jordan Crousee6239dd2011-11-17 13:39:21 -0700246 return 0;
247
Jeff Boody23bfaa22012-04-24 14:57:45 -0600248 /* check for greater-than for non-rollover case */
249 if ((a > b) && (a - b < KGSL_TIMESTAMP_WINDOW))
250 return 1;
251
252 /* check for greater-than for rollover case
253 * note that <= is required to ensure that consistent
254 * results are returned for values whose difference is
255 * equal to the window size
256 */
257 a += KGSL_TIMESTAMP_WINDOW;
258 b += KGSL_TIMESTAMP_WINDOW;
259 return ((a > b) && (a - b <= KGSL_TIMESTAMP_WINDOW)) ? 1 : -1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700260}
261
262static inline void
263kgsl_mem_entry_get(struct kgsl_mem_entry *entry)
264{
265 kref_get(&entry->refcount);
266}
267
268static inline void
269kgsl_mem_entry_put(struct kgsl_mem_entry *entry)
270{
271 kref_put(&entry->refcount, kgsl_mem_entry_destroy);
272}
273
274#endif /* __KGSL_H */