blob: 097414f93ca1b242c92ab7bf732067499a54de6a [file] [log] [blame]
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001/*
2 * drivers/gpu/ion/ion.c
3 *
4 * Copyright (C) 2011 Google, Inc.
Olav Haugan0a852512012-01-09 10:20:55 -08005 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07006 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
Steve Mucklef132c6c2012-06-06 18:30:57 -070018#include <linux/module.h>
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -070019#include <linux/device.h>
20#include <linux/file.h>
21#include <linux/fs.h>
22#include <linux/anon_inodes.h>
23#include <linux/ion.h>
24#include <linux/list.h>
Laura Abbottb14ed962012-01-30 14:18:08 -080025#include <linux/memblock.h>
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -070026#include <linux/miscdevice.h>
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -070027#include <linux/mm.h>
28#include <linux/mm_types.h>
29#include <linux/rbtree.h>
30#include <linux/sched.h>
31#include <linux/slab.h>
32#include <linux/seq_file.h>
33#include <linux/uaccess.h>
34#include <linux/debugfs.h>
Laura Abbottb14ed962012-01-30 14:18:08 -080035#include <linux/dma-buf.h>
Mitchel Humpherysfd02cfb2012-09-04 17:00:29 -070036#include <linux/msm_ion.h>
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -070037
Laura Abbott8c017362011-09-22 20:59:12 -070038#include <mach/iommu_domains.h>
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -070039#include "ion_priv.h"
40#define DEBUG
41
42/**
43 * struct ion_device - the metadata of the ion device node
44 * @dev: the actual misc device
45 * @buffers: an rb tree of all the existing buffers
46 * @lock: lock protecting the buffers & heaps trees
47 * @heaps: list of all the heaps in the system
48 * @user_clients: list of all the clients created from userspace
49 */
50struct ion_device {
51 struct miscdevice dev;
52 struct rb_root buffers;
53 struct mutex lock;
54 struct rb_root heaps;
55 long (*custom_ioctl) (struct ion_client *client, unsigned int cmd,
56 unsigned long arg);
Laura Abbottb14ed962012-01-30 14:18:08 -080057 struct rb_root clients;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -070058 struct dentry *debug_root;
59};
60
61/**
62 * struct ion_client - a process/hw block local address space
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -070063 * @node: node in the tree of all clients
64 * @dev: backpointer to ion device
65 * @handles: an rb tree of all the handles in this client
66 * @lock: lock protecting the tree of handles
67 * @heap_mask: mask of all supported heaps
68 * @name: used for debugging
69 * @task: used for debugging
70 *
71 * A client represents a list of buffers this client may access.
72 * The mutex stored here is used to protect both handles tree
73 * as well as the handles themselves, and should be held while modifying either.
74 */
75struct ion_client {
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -070076 struct rb_node node;
77 struct ion_device *dev;
78 struct rb_root handles;
79 struct mutex lock;
80 unsigned int heap_mask;
Olav Haugan63e5f3b2012-01-11 16:42:37 -080081 char *name;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -070082 struct task_struct *task;
83 pid_t pid;
84 struct dentry *debug_root;
85};
86
87/**
88 * ion_handle - a client local reference to a buffer
89 * @ref: reference count
90 * @client: back pointer to the client the buffer resides in
91 * @buffer: pointer to the buffer
92 * @node: node in the client's handle rbtree
93 * @kmap_cnt: count of times this client has mapped to kernel
94 * @dmap_cnt: count of times this client has mapped for dma
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -070095 *
96 * Modifications to node, map_cnt or mapping should be protected by the
97 * lock in the client. Other fields are never changed after initialization.
98 */
99struct ion_handle {
100 struct kref ref;
101 struct ion_client *client;
102 struct ion_buffer *buffer;
103 struct rb_node node;
104 unsigned int kmap_cnt;
Laura Abbott8c017362011-09-22 20:59:12 -0700105 unsigned int iommu_map_cnt;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700106};
107
Olav Hauganb3676592012-03-02 15:02:25 -0800108static void ion_iommu_release(struct kref *kref);
109
Laura Abbott8c017362011-09-22 20:59:12 -0700110static int ion_validate_buffer_flags(struct ion_buffer *buffer,
111 unsigned long flags)
112{
113 if (buffer->kmap_cnt || buffer->dmap_cnt || buffer->umap_cnt ||
114 buffer->iommu_map_cnt) {
115 if (buffer->flags != flags) {
116 pr_err("%s: buffer was already mapped with flags %lx,"
117 " cannot map with flags %lx\n", __func__,
118 buffer->flags, flags);
119 return 1;
120 }
121
122 } else {
123 buffer->flags = flags;
124 }
125 return 0;
126}
127
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700128/* this function should only be called while dev->lock is held */
129static void ion_buffer_add(struct ion_device *dev,
130 struct ion_buffer *buffer)
131{
132 struct rb_node **p = &dev->buffers.rb_node;
133 struct rb_node *parent = NULL;
134 struct ion_buffer *entry;
135
136 while (*p) {
137 parent = *p;
138 entry = rb_entry(parent, struct ion_buffer, node);
139
140 if (buffer < entry) {
141 p = &(*p)->rb_left;
142 } else if (buffer > entry) {
143 p = &(*p)->rb_right;
144 } else {
145 pr_err("%s: buffer already found.", __func__);
146 BUG();
147 }
148 }
149
150 rb_link_node(&buffer->node, parent, p);
151 rb_insert_color(&buffer->node, &dev->buffers);
152}
153
Olav Haugan0fa9b602012-01-25 11:50:38 -0800154static void ion_iommu_add(struct ion_buffer *buffer,
Laura Abbott8c017362011-09-22 20:59:12 -0700155 struct ion_iommu_map *iommu)
156{
157 struct rb_node **p = &buffer->iommu_maps.rb_node;
158 struct rb_node *parent = NULL;
159 struct ion_iommu_map *entry;
160
161 while (*p) {
162 parent = *p;
163 entry = rb_entry(parent, struct ion_iommu_map, node);
164
165 if (iommu->key < entry->key) {
166 p = &(*p)->rb_left;
167 } else if (iommu->key > entry->key) {
168 p = &(*p)->rb_right;
169 } else {
170 pr_err("%s: buffer %p already has mapping for domain %d"
171 " and partition %d\n", __func__,
172 buffer,
173 iommu_map_domain(iommu),
174 iommu_map_partition(iommu));
175 BUG();
176 }
177 }
178
179 rb_link_node(&iommu->node, parent, p);
180 rb_insert_color(&iommu->node, &buffer->iommu_maps);
181
182}
183
184static struct ion_iommu_map *ion_iommu_lookup(struct ion_buffer *buffer,
185 unsigned int domain_no,
186 unsigned int partition_no)
187{
188 struct rb_node **p = &buffer->iommu_maps.rb_node;
189 struct rb_node *parent = NULL;
190 struct ion_iommu_map *entry;
191 uint64_t key = domain_no;
192 key = key << 32 | partition_no;
193
194 while (*p) {
195 parent = *p;
196 entry = rb_entry(parent, struct ion_iommu_map, node);
197
198 if (key < entry->key)
199 p = &(*p)->rb_left;
200 else if (key > entry->key)
201 p = &(*p)->rb_right;
202 else
203 return entry;
204 }
205
206 return NULL;
207}
208
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700209/* this function should only be called while dev->lock is held */
210static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
211 struct ion_device *dev,
212 unsigned long len,
213 unsigned long align,
214 unsigned long flags)
215{
216 struct ion_buffer *buffer;
Laura Abbottb14ed962012-01-30 14:18:08 -0800217 struct sg_table *table;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700218 int ret;
219
220 buffer = kzalloc(sizeof(struct ion_buffer), GFP_KERNEL);
221 if (!buffer)
222 return ERR_PTR(-ENOMEM);
223
224 buffer->heap = heap;
225 kref_init(&buffer->ref);
226
227 ret = heap->ops->allocate(heap, buffer, len, align, flags);
228 if (ret) {
229 kfree(buffer);
230 return ERR_PTR(ret);
231 }
Laura Abbottb14ed962012-01-30 14:18:08 -0800232
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700233 buffer->dev = dev;
234 buffer->size = len;
Laura Abbottb14ed962012-01-30 14:18:08 -0800235
236 table = buffer->heap->ops->map_dma(buffer->heap, buffer);
237 if (IS_ERR_OR_NULL(table)) {
238 heap->ops->free(buffer);
239 kfree(buffer);
240 return ERR_PTR(PTR_ERR(table));
241 }
242 buffer->sg_table = table;
243
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700244 mutex_init(&buffer->lock);
245 ion_buffer_add(dev, buffer);
246 return buffer;
247}
248
Olav Hauganb3676592012-03-02 15:02:25 -0800249/**
250 * Check for delayed IOMMU unmapping. Also unmap any outstanding
251 * mappings which would otherwise have been leaked.
252 */
253static void ion_iommu_delayed_unmap(struct ion_buffer *buffer)
254{
255 struct ion_iommu_map *iommu_map;
256 struct rb_node *node;
257 const struct rb_root *rb = &(buffer->iommu_maps);
258 unsigned long ref_count;
259 unsigned int delayed_unmap;
260
261 mutex_lock(&buffer->lock);
262
263 while ((node = rb_first(rb)) != 0) {
264 iommu_map = rb_entry(node, struct ion_iommu_map, node);
265 ref_count = atomic_read(&iommu_map->ref.refcount);
266 delayed_unmap = iommu_map->flags & ION_IOMMU_UNMAP_DELAYED;
267
268 if ((delayed_unmap && ref_count > 1) || !delayed_unmap) {
269 pr_err("%s: Virtual memory address leak in domain %u, partition %u\n",
270 __func__, iommu_map->domain_info[DI_DOMAIN_NUM],
271 iommu_map->domain_info[DI_PARTITION_NUM]);
272 }
273 /* set ref count to 1 to force release */
274 kref_init(&iommu_map->ref);
275 kref_put(&iommu_map->ref, ion_iommu_release);
276 }
277
278 mutex_unlock(&buffer->lock);
279}
280
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700281static void ion_buffer_destroy(struct kref *kref)
282{
283 struct ion_buffer *buffer = container_of(kref, struct ion_buffer, ref);
284 struct ion_device *dev = buffer->dev;
285
Laura Abbottb14ed962012-01-30 14:18:08 -0800286 if (WARN_ON(buffer->kmap_cnt > 0))
287 buffer->heap->ops->unmap_kernel(buffer->heap, buffer);
288
289 buffer->heap->ops->unmap_dma(buffer->heap, buffer);
290
Olav Hauganb3676592012-03-02 15:02:25 -0800291 ion_iommu_delayed_unmap(buffer);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700292 buffer->heap->ops->free(buffer);
293 mutex_lock(&dev->lock);
294 rb_erase(&buffer->node, &dev->buffers);
295 mutex_unlock(&dev->lock);
296 kfree(buffer);
297}
298
299static void ion_buffer_get(struct ion_buffer *buffer)
300{
301 kref_get(&buffer->ref);
302}
303
304static int ion_buffer_put(struct ion_buffer *buffer)
305{
306 return kref_put(&buffer->ref, ion_buffer_destroy);
307}
308
309static struct ion_handle *ion_handle_create(struct ion_client *client,
310 struct ion_buffer *buffer)
311{
312 struct ion_handle *handle;
313
314 handle = kzalloc(sizeof(struct ion_handle), GFP_KERNEL);
315 if (!handle)
316 return ERR_PTR(-ENOMEM);
317 kref_init(&handle->ref);
318 rb_init_node(&handle->node);
319 handle->client = client;
320 ion_buffer_get(buffer);
321 handle->buffer = buffer;
322
323 return handle;
324}
325
Laura Abbottb14ed962012-01-30 14:18:08 -0800326static void ion_handle_kmap_put(struct ion_handle *);
327
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700328static void ion_handle_destroy(struct kref *kref)
329{
330 struct ion_handle *handle = container_of(kref, struct ion_handle, ref);
Laura Abbottb14ed962012-01-30 14:18:08 -0800331 struct ion_client *client = handle->client;
332 struct ion_buffer *buffer = handle->buffer;
333
Laura Abbottb14ed962012-01-30 14:18:08 -0800334 mutex_lock(&buffer->lock);
335 while (handle->kmap_cnt)
336 ion_handle_kmap_put(handle);
337 mutex_unlock(&buffer->lock);
338
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700339 if (!RB_EMPTY_NODE(&handle->node))
Laura Abbottb14ed962012-01-30 14:18:08 -0800340 rb_erase(&handle->node, &client->handles);
Laura Abbottb14ed962012-01-30 14:18:08 -0800341
342 ion_buffer_put(buffer);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700343 kfree(handle);
344}
345
346struct ion_buffer *ion_handle_buffer(struct ion_handle *handle)
347{
348 return handle->buffer;
349}
350
351static void ion_handle_get(struct ion_handle *handle)
352{
353 kref_get(&handle->ref);
354}
355
356static int ion_handle_put(struct ion_handle *handle)
357{
358 return kref_put(&handle->ref, ion_handle_destroy);
359}
360
361static struct ion_handle *ion_handle_lookup(struct ion_client *client,
362 struct ion_buffer *buffer)
363{
364 struct rb_node *n;
365
366 for (n = rb_first(&client->handles); n; n = rb_next(n)) {
367 struct ion_handle *handle = rb_entry(n, struct ion_handle,
368 node);
369 if (handle->buffer == buffer)
370 return handle;
371 }
372 return NULL;
373}
374
375static bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle)
376{
377 struct rb_node *n = client->handles.rb_node;
378
379 while (n) {
380 struct ion_handle *handle_node = rb_entry(n, struct ion_handle,
381 node);
382 if (handle < handle_node)
383 n = n->rb_left;
384 else if (handle > handle_node)
385 n = n->rb_right;
386 else
387 return true;
388 }
389 return false;
390}
391
392static void ion_handle_add(struct ion_client *client, struct ion_handle *handle)
393{
394 struct rb_node **p = &client->handles.rb_node;
395 struct rb_node *parent = NULL;
396 struct ion_handle *entry;
397
398 while (*p) {
399 parent = *p;
400 entry = rb_entry(parent, struct ion_handle, node);
401
402 if (handle < entry)
403 p = &(*p)->rb_left;
404 else if (handle > entry)
405 p = &(*p)->rb_right;
406 else
407 WARN(1, "%s: buffer already found.", __func__);
408 }
409
410 rb_link_node(&handle->node, parent, p);
411 rb_insert_color(&handle->node, &client->handles);
412}
413
414struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
415 size_t align, unsigned int flags)
416{
417 struct rb_node *n;
418 struct ion_handle *handle;
419 struct ion_device *dev = client->dev;
420 struct ion_buffer *buffer = NULL;
Olav Haugan0a852512012-01-09 10:20:55 -0800421 unsigned long secure_allocation = flags & ION_SECURE;
Olav Haugan35e2f2f2012-01-11 17:31:47 -0800422 const unsigned int MAX_DBG_STR_LEN = 64;
423 char dbg_str[MAX_DBG_STR_LEN];
424 unsigned int dbg_str_idx = 0;
425
426 dbg_str[0] = '\0';
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700427
428 /*
429 * traverse the list of heaps available in this system in priority
430 * order. If the heap type is supported by the client, and matches the
431 * request of the caller allocate from it. Repeat until allocate has
432 * succeeded or all heaps have been tried
433 */
Laura Abbottb14ed962012-01-30 14:18:08 -0800434 if (WARN_ON(!len))
435 return ERR_PTR(-EINVAL);
436
437 len = PAGE_ALIGN(len);
438
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700439 mutex_lock(&dev->lock);
440 for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) {
441 struct ion_heap *heap = rb_entry(n, struct ion_heap, node);
442 /* if the client doesn't support this heap type */
443 if (!((1 << heap->type) & client->heap_mask))
444 continue;
445 /* if the caller didn't specify this heap type */
446 if (!((1 << heap->id) & flags))
447 continue;
Olav Haugan0a852512012-01-09 10:20:55 -0800448 /* Do not allow un-secure heap if secure is specified */
449 if (secure_allocation && (heap->type != ION_HEAP_TYPE_CP))
450 continue;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700451 buffer = ion_buffer_create(heap, dev, len, align, flags);
452 if (!IS_ERR_OR_NULL(buffer))
453 break;
Olav Haugan35e2f2f2012-01-11 17:31:47 -0800454 if (dbg_str_idx < MAX_DBG_STR_LEN) {
455 unsigned int len_left = MAX_DBG_STR_LEN-dbg_str_idx-1;
456 int ret_value = snprintf(&dbg_str[dbg_str_idx],
457 len_left, "%s ", heap->name);
458 if (ret_value >= len_left) {
459 /* overflow */
460 dbg_str[MAX_DBG_STR_LEN-1] = '\0';
461 dbg_str_idx = MAX_DBG_STR_LEN;
462 } else if (ret_value >= 0) {
463 dbg_str_idx += ret_value;
464 } else {
465 /* error */
466 dbg_str[MAX_DBG_STR_LEN-1] = '\0';
467 }
468 }
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700469 }
470 mutex_unlock(&dev->lock);
471
Laura Abbottb14ed962012-01-30 14:18:08 -0800472 if (buffer == NULL)
473 return ERR_PTR(-ENODEV);
474
475 if (IS_ERR(buffer)) {
Olav Haugan35e2f2f2012-01-11 17:31:47 -0800476 pr_debug("ION is unable to allocate 0x%x bytes (alignment: "
477 "0x%x) from heap(s) %sfor client %s with heap "
478 "mask 0x%x\n",
479 len, align, dbg_str, client->name, client->heap_mask);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700480 return ERR_PTR(PTR_ERR(buffer));
Olav Haugan35e2f2f2012-01-11 17:31:47 -0800481 }
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700482
483 handle = ion_handle_create(client, buffer);
484
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700485 /*
486 * ion_buffer_create will create a buffer with a ref_cnt of 1,
487 * and ion_handle_create will take a second reference, drop one here
488 */
489 ion_buffer_put(buffer);
490
Laura Abbottb14ed962012-01-30 14:18:08 -0800491 if (!IS_ERR(handle)) {
492 mutex_lock(&client->lock);
493 ion_handle_add(client, handle);
494 mutex_unlock(&client->lock);
495 }
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700496
Laura Abbottb14ed962012-01-30 14:18:08 -0800497
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700498 return handle;
499}
Olav Hauganbd2b6922012-01-25 09:28:55 -0800500EXPORT_SYMBOL(ion_alloc);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700501
502void ion_free(struct ion_client *client, struct ion_handle *handle)
503{
504 bool valid_handle;
505
506 BUG_ON(client != handle->client);
507
508 mutex_lock(&client->lock);
509 valid_handle = ion_handle_validate(client, handle);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700510 if (!valid_handle) {
Laura Abbottec149ff2012-01-26 13:33:11 -0800511 mutex_unlock(&client->lock);
Olav Haugan6ede5672012-04-19 10:20:22 -0700512 WARN(1, "%s: invalid handle passed to free.\n", __func__);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700513 return;
514 }
Laura Abbottb14ed962012-01-30 14:18:08 -0800515 ion_handle_put(handle);
Ajay Dudani6ca95312012-08-20 15:41:11 -0700516 mutex_unlock(&client->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700517}
Olav Hauganbd2b6922012-01-25 09:28:55 -0800518EXPORT_SYMBOL(ion_free);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700519
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700520int ion_phys(struct ion_client *client, struct ion_handle *handle,
521 ion_phys_addr_t *addr, size_t *len)
522{
523 struct ion_buffer *buffer;
524 int ret;
525
526 mutex_lock(&client->lock);
527 if (!ion_handle_validate(client, handle)) {
528 mutex_unlock(&client->lock);
529 return -EINVAL;
530 }
531
532 buffer = handle->buffer;
533
534 if (!buffer->heap->ops->phys) {
535 pr_err("%s: ion_phys is not implemented by this heap.\n",
536 __func__);
537 mutex_unlock(&client->lock);
538 return -ENODEV;
539 }
540 mutex_unlock(&client->lock);
541 ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len);
542 return ret;
543}
Olav Hauganbd2b6922012-01-25 09:28:55 -0800544EXPORT_SYMBOL(ion_phys);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700545
Laura Abbottb14ed962012-01-30 14:18:08 -0800546static void *ion_buffer_kmap_get(struct ion_buffer *buffer)
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700547{
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700548 void *vaddr;
549
Laura Abbottb14ed962012-01-30 14:18:08 -0800550 if (buffer->kmap_cnt) {
551 buffer->kmap_cnt++;
552 return buffer->vaddr;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700553 }
Laura Abbottb14ed962012-01-30 14:18:08 -0800554 vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer);
555 if (IS_ERR_OR_NULL(vaddr))
556 return vaddr;
557 buffer->vaddr = vaddr;
558 buffer->kmap_cnt++;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700559 return vaddr;
560}
Laura Abbottb14ed962012-01-30 14:18:08 -0800561
562static void *ion_handle_kmap_get(struct ion_handle *handle)
563{
564 struct ion_buffer *buffer = handle->buffer;
565 void *vaddr;
566
567 if (handle->kmap_cnt) {
568 handle->kmap_cnt++;
569 return buffer->vaddr;
570 }
571 vaddr = ion_buffer_kmap_get(buffer);
572 if (IS_ERR_OR_NULL(vaddr))
573 return vaddr;
574 handle->kmap_cnt++;
575 return vaddr;
576}
577
578static void ion_buffer_kmap_put(struct ion_buffer *buffer)
579{
580 buffer->kmap_cnt--;
581 if (!buffer->kmap_cnt) {
582 buffer->heap->ops->unmap_kernel(buffer->heap, buffer);
583 buffer->vaddr = NULL;
584 }
585}
586
587static void ion_handle_kmap_put(struct ion_handle *handle)
588{
589 struct ion_buffer *buffer = handle->buffer;
590
591 handle->kmap_cnt--;
592 if (!handle->kmap_cnt)
593 ion_buffer_kmap_put(buffer);
594}
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700595
Olav Hauganb3676592012-03-02 15:02:25 -0800596static struct ion_iommu_map *__ion_iommu_map(struct ion_buffer *buffer,
Laura Abbott8c017362011-09-22 20:59:12 -0700597 int domain_num, int partition_num, unsigned long align,
598 unsigned long iova_length, unsigned long flags,
599 unsigned long *iova)
600{
601 struct ion_iommu_map *data;
602 int ret;
603
604 data = kmalloc(sizeof(*data), GFP_ATOMIC);
605
606 if (!data)
Olav Hauganb3676592012-03-02 15:02:25 -0800607 return ERR_PTR(-ENOMEM);
Laura Abbott8c017362011-09-22 20:59:12 -0700608
609 data->buffer = buffer;
610 iommu_map_domain(data) = domain_num;
611 iommu_map_partition(data) = partition_num;
612
613 ret = buffer->heap->ops->map_iommu(buffer, data,
614 domain_num,
615 partition_num,
616 align,
617 iova_length,
618 flags);
619
620 if (ret)
621 goto out;
622
623 kref_init(&data->ref);
624 *iova = data->iova_addr;
625
626 ion_iommu_add(buffer, data);
627
Olav Hauganb3676592012-03-02 15:02:25 -0800628 return data;
Laura Abbott8c017362011-09-22 20:59:12 -0700629
630out:
Laura Abbott8c017362011-09-22 20:59:12 -0700631 kfree(data);
Olav Hauganb3676592012-03-02 15:02:25 -0800632 return ERR_PTR(ret);
Laura Abbott8c017362011-09-22 20:59:12 -0700633}
634
635int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
636 int domain_num, int partition_num, unsigned long align,
637 unsigned long iova_length, unsigned long *iova,
638 unsigned long *buffer_size,
Olav Hauganb3676592012-03-02 15:02:25 -0800639 unsigned long flags, unsigned long iommu_flags)
Laura Abbott8c017362011-09-22 20:59:12 -0700640{
641 struct ion_buffer *buffer;
642 struct ion_iommu_map *iommu_map;
643 int ret = 0;
644
Olav Haugan79e9ffa2012-02-24 13:11:10 -0800645 if (ION_IS_CACHED(flags)) {
646 pr_err("%s: Cannot map iommu as cached.\n", __func__);
647 return -EINVAL;
648 }
649
Laura Abbott8c017362011-09-22 20:59:12 -0700650 mutex_lock(&client->lock);
651 if (!ion_handle_validate(client, handle)) {
652 pr_err("%s: invalid handle passed to map_kernel.\n",
653 __func__);
654 mutex_unlock(&client->lock);
655 return -EINVAL;
656 }
657
658 buffer = handle->buffer;
659 mutex_lock(&buffer->lock);
660
661 if (!handle->buffer->heap->ops->map_iommu) {
662 pr_err("%s: map_iommu is not implemented by this heap.\n",
663 __func__);
664 ret = -ENODEV;
665 goto out;
666 }
667
Laura Abbott8c017362011-09-22 20:59:12 -0700668 /*
669 * If clients don't want a custom iova length, just use whatever
670 * the buffer size is
671 */
672 if (!iova_length)
673 iova_length = buffer->size;
674
675 if (buffer->size > iova_length) {
676 pr_debug("%s: iova length %lx is not at least buffer size"
677 " %x\n", __func__, iova_length, buffer->size);
678 ret = -EINVAL;
679 goto out;
680 }
681
682 if (buffer->size & ~PAGE_MASK) {
683 pr_debug("%s: buffer size %x is not aligned to %lx", __func__,
684 buffer->size, PAGE_SIZE);
685 ret = -EINVAL;
686 goto out;
687 }
688
689 if (iova_length & ~PAGE_MASK) {
690 pr_debug("%s: iova_length %lx is not aligned to %lx", __func__,
691 iova_length, PAGE_SIZE);
692 ret = -EINVAL;
693 goto out;
694 }
695
696 iommu_map = ion_iommu_lookup(buffer, domain_num, partition_num);
Olav Hauganb3676592012-03-02 15:02:25 -0800697 if (!iommu_map) {
698 iommu_map = __ion_iommu_map(buffer, domain_num, partition_num,
699 align, iova_length, flags, iova);
Laura Abbottb14ed962012-01-30 14:18:08 -0800700 if (!IS_ERR_OR_NULL(iommu_map)) {
Olav Hauganb3676592012-03-02 15:02:25 -0800701 iommu_map->flags = iommu_flags;
702
703 if (iommu_map->flags & ION_IOMMU_UNMAP_DELAYED)
704 kref_get(&iommu_map->ref);
705 }
Laura Abbott8c017362011-09-22 20:59:12 -0700706 } else {
Olav Hauganb3676592012-03-02 15:02:25 -0800707 if (iommu_map->flags != iommu_flags) {
708 pr_err("%s: handle %p is already mapped with iommu flags %lx, trying to map with flags %lx\n",
709 __func__, handle,
710 iommu_map->flags, iommu_flags);
Olav Hauganb3676592012-03-02 15:02:25 -0800711 ret = -EINVAL;
712 } else if (iommu_map->mapped_size != iova_length) {
Laura Abbott8c017362011-09-22 20:59:12 -0700713 pr_err("%s: handle %p is already mapped with length"
Olav Hauganb3676592012-03-02 15:02:25 -0800714 " %x, trying to map with length %lx\n",
Laura Abbott8c017362011-09-22 20:59:12 -0700715 __func__, handle, iommu_map->mapped_size,
716 iova_length);
Laura Abbott8c017362011-09-22 20:59:12 -0700717 ret = -EINVAL;
718 } else {
719 kref_get(&iommu_map->ref);
720 *iova = iommu_map->iova_addr;
721 }
722 }
Laura Abbottb14ed962012-01-30 14:18:08 -0800723 if (!ret)
724 buffer->iommu_map_cnt++;
Laura Abbott8c017362011-09-22 20:59:12 -0700725 *buffer_size = buffer->size;
726out:
727 mutex_unlock(&buffer->lock);
728 mutex_unlock(&client->lock);
729 return ret;
730}
731EXPORT_SYMBOL(ion_map_iommu);
732
733static void ion_iommu_release(struct kref *kref)
734{
735 struct ion_iommu_map *map = container_of(kref, struct ion_iommu_map,
736 ref);
737 struct ion_buffer *buffer = map->buffer;
738
739 rb_erase(&map->node, &buffer->iommu_maps);
740 buffer->heap->ops->unmap_iommu(map);
741 kfree(map);
742}
743
744void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
745 int domain_num, int partition_num)
746{
747 struct ion_iommu_map *iommu_map;
748 struct ion_buffer *buffer;
749
750 mutex_lock(&client->lock);
751 buffer = handle->buffer;
752
753 mutex_lock(&buffer->lock);
754
755 iommu_map = ion_iommu_lookup(buffer, domain_num, partition_num);
756
757 if (!iommu_map) {
758 WARN(1, "%s: (%d,%d) was never mapped for %p\n", __func__,
759 domain_num, partition_num, buffer);
760 goto out;
761 }
762
Laura Abbott8c017362011-09-22 20:59:12 -0700763 kref_put(&iommu_map->ref, ion_iommu_release);
764
Laura Abbottb14ed962012-01-30 14:18:08 -0800765 buffer->iommu_map_cnt--;
Laura Abbott8c017362011-09-22 20:59:12 -0700766out:
767 mutex_unlock(&buffer->lock);
768
769 mutex_unlock(&client->lock);
770
771}
772EXPORT_SYMBOL(ion_unmap_iommu);
773
Laura Abbottb14ed962012-01-30 14:18:08 -0800774void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle,
775 unsigned long flags)
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700776{
777 struct ion_buffer *buffer;
Laura Abbottb14ed962012-01-30 14:18:08 -0800778 void *vaddr;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700779
780 mutex_lock(&client->lock);
781 if (!ion_handle_validate(client, handle)) {
Laura Abbottb14ed962012-01-30 14:18:08 -0800782 pr_err("%s: invalid handle passed to map_kernel.\n",
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700783 __func__);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -0700784 mutex_unlock(&client->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700785 return ERR_PTR(-EINVAL);
786 }
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700787
Laura Abbottb14ed962012-01-30 14:18:08 -0800788 buffer = handle->buffer;
789
790 if (!handle->buffer->heap->ops->map_kernel) {
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700791 pr_err("%s: map_kernel is not implemented by this heap.\n",
792 __func__);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -0700793 mutex_unlock(&client->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700794 return ERR_PTR(-ENODEV);
795 }
Laura Abbott894fd582011-08-19 13:33:56 -0700796
Laura Abbott8c017362011-09-22 20:59:12 -0700797 if (ion_validate_buffer_flags(buffer, flags)) {
Laura Abbottb14ed962012-01-30 14:18:08 -0800798 mutex_unlock(&client->lock);
799 return ERR_PTR(-EEXIST);
Laura Abbott894fd582011-08-19 13:33:56 -0700800 }
801
Laura Abbottb14ed962012-01-30 14:18:08 -0800802 mutex_lock(&buffer->lock);
803 vaddr = ion_handle_kmap_get(handle);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700804 mutex_unlock(&buffer->lock);
805 mutex_unlock(&client->lock);
Laura Abbottb14ed962012-01-30 14:18:08 -0800806 return vaddr;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700807}
Olav Hauganbd453a92012-07-05 14:21:34 -0700808EXPORT_SYMBOL(ion_map_kernel);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700809
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700810void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle)
811{
812 struct ion_buffer *buffer;
813
814 mutex_lock(&client->lock);
815 buffer = handle->buffer;
816 mutex_lock(&buffer->lock);
Laura Abbottb14ed962012-01-30 14:18:08 -0800817 ion_handle_kmap_put(handle);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700818 mutex_unlock(&buffer->lock);
819 mutex_unlock(&client->lock);
820}
Olav Hauganbd453a92012-07-05 14:21:34 -0700821EXPORT_SYMBOL(ion_unmap_kernel);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700822
Olav Haugan41f85792012-02-08 15:28:05 -0800823int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
Laura Abbottabcb6f72011-10-04 16:26:49 -0700824 void *uaddr, unsigned long offset, unsigned long len,
825 unsigned int cmd)
826{
827 struct ion_buffer *buffer;
Laura Abbottabcb6f72011-10-04 16:26:49 -0700828 int ret = -EINVAL;
829
830 mutex_lock(&client->lock);
831 if (!ion_handle_validate(client, handle)) {
832 pr_err("%s: invalid handle passed to do_cache_op.\n",
833 __func__);
834 mutex_unlock(&client->lock);
835 return -EINVAL;
836 }
837 buffer = handle->buffer;
838 mutex_lock(&buffer->lock);
839
Laura Abbottcbaa6682011-10-19 12:14:14 -0700840 if (!ION_IS_CACHED(buffer->flags)) {
Laura Abbottabcb6f72011-10-04 16:26:49 -0700841 ret = 0;
842 goto out;
843 }
844
845 if (!handle->buffer->heap->ops->cache_op) {
846 pr_err("%s: cache_op is not implemented by this heap.\n",
847 __func__);
848 ret = -ENODEV;
849 goto out;
850 }
851
Laura Abbottabcb6f72011-10-04 16:26:49 -0700852
853 ret = buffer->heap->ops->cache_op(buffer->heap, buffer, uaddr,
854 offset, len, cmd);
855
856out:
857 mutex_unlock(&buffer->lock);
858 mutex_unlock(&client->lock);
859 return ret;
860
861}
Olav Hauganbd453a92012-07-05 14:21:34 -0700862EXPORT_SYMBOL(ion_do_cache_op);
Laura Abbottabcb6f72011-10-04 16:26:49 -0700863
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700864static int ion_debug_client_show(struct seq_file *s, void *unused)
865{
866 struct ion_client *client = s->private;
867 struct rb_node *n;
Olav Haugan854c9e12012-05-16 16:34:28 -0700868 struct rb_node *n2;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700869
Olav Haugan854c9e12012-05-16 16:34:28 -0700870 seq_printf(s, "%16.16s: %16.16s : %16.16s : %12.12s : %12.12s : %s\n",
871 "heap_name", "size_in_bytes", "handle refcount",
872 "buffer", "physical", "[domain,partition] - virt");
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700873
874 mutex_lock(&client->lock);
875 for (n = rb_first(&client->handles); n; n = rb_next(n)) {
876 struct ion_handle *handle = rb_entry(n, struct ion_handle,
877 node);
878 enum ion_heap_type type = handle->buffer->heap->type;
879
Olav Haugan854c9e12012-05-16 16:34:28 -0700880 seq_printf(s, "%16.16s: %16x : %16d : %12p",
Laura Abbott68c80642011-10-21 17:32:27 -0700881 handle->buffer->heap->name,
882 handle->buffer->size,
883 atomic_read(&handle->ref.refcount),
884 handle->buffer);
Olav Haugan854c9e12012-05-16 16:34:28 -0700885
886 if (type == ION_HEAP_TYPE_SYSTEM_CONTIG ||
887 type == ION_HEAP_TYPE_CARVEOUT ||
888 type == ION_HEAP_TYPE_CP)
889 seq_printf(s, " : %12lx", handle->buffer->priv_phys);
890 else
891 seq_printf(s, " : %12s", "N/A");
892
893 for (n2 = rb_first(&handle->buffer->iommu_maps); n2;
894 n2 = rb_next(n2)) {
895 struct ion_iommu_map *imap =
896 rb_entry(n2, struct ion_iommu_map, node);
897 seq_printf(s, " : [%d,%d] - %8lx",
898 imap->domain_info[DI_DOMAIN_NUM],
899 imap->domain_info[DI_PARTITION_NUM],
900 imap->iova_addr);
901 }
902 seq_printf(s, "\n");
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700903 }
904 mutex_unlock(&client->lock);
905
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700906 return 0;
907}
908
909static int ion_debug_client_open(struct inode *inode, struct file *file)
910{
911 return single_open(file, ion_debug_client_show, inode->i_private);
912}
913
914static const struct file_operations debug_client_fops = {
915 .open = ion_debug_client_open,
916 .read = seq_read,
917 .llseek = seq_lseek,
918 .release = single_release,
919};
920
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700921struct ion_client *ion_client_create(struct ion_device *dev,
922 unsigned int heap_mask,
923 const char *name)
924{
925 struct ion_client *client;
926 struct task_struct *task;
927 struct rb_node **p;
928 struct rb_node *parent = NULL;
929 struct ion_client *entry;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700930 pid_t pid;
Olav Haugane8a31972012-05-16 13:11:41 -0700931 unsigned int name_len;
932
933 if (!name) {
934 pr_err("%s: Name cannot be null\n", __func__);
935 return ERR_PTR(-EINVAL);
936 }
937 name_len = strnlen(name, 64);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700938
939 get_task_struct(current->group_leader);
940 task_lock(current->group_leader);
941 pid = task_pid_nr(current->group_leader);
942 /* don't bother to store task struct for kernel threads,
943 they can't be killed anyway */
944 if (current->group_leader->flags & PF_KTHREAD) {
945 put_task_struct(current->group_leader);
946 task = NULL;
947 } else {
948 task = current->group_leader;
949 }
950 task_unlock(current->group_leader);
951
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700952 client = kzalloc(sizeof(struct ion_client), GFP_KERNEL);
953 if (!client) {
Laura Abbottb14ed962012-01-30 14:18:08 -0800954 if (task)
955 put_task_struct(current->group_leader);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700956 return ERR_PTR(-ENOMEM);
957 }
958
959 client->dev = dev;
960 client->handles = RB_ROOT;
961 mutex_init(&client->lock);
Olav Haugan63e5f3b2012-01-11 16:42:37 -0800962
Olav Haugan6625c7d2012-01-24 13:50:43 -0800963 client->name = kzalloc(name_len+1, GFP_KERNEL);
Olav Haugan63e5f3b2012-01-11 16:42:37 -0800964 if (!client->name) {
965 put_task_struct(current->group_leader);
966 kfree(client);
967 return ERR_PTR(-ENOMEM);
968 } else {
Olav Haugan6625c7d2012-01-24 13:50:43 -0800969 strlcpy(client->name, name, name_len+1);
Olav Haugan63e5f3b2012-01-11 16:42:37 -0800970 }
971
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700972 client->heap_mask = heap_mask;
973 client->task = task;
974 client->pid = pid;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700975
976 mutex_lock(&dev->lock);
Laura Abbottb14ed962012-01-30 14:18:08 -0800977 p = &dev->clients.rb_node;
978 while (*p) {
979 parent = *p;
980 entry = rb_entry(parent, struct ion_client, node);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700981
Laura Abbottb14ed962012-01-30 14:18:08 -0800982 if (client < entry)
983 p = &(*p)->rb_left;
984 else if (client > entry)
985 p = &(*p)->rb_right;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700986 }
Laura Abbottb14ed962012-01-30 14:18:08 -0800987 rb_link_node(&client->node, parent, p);
988 rb_insert_color(&client->node, &dev->clients);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700989
Laura Abbotteed86032011-12-05 15:32:36 -0800990
991 client->debug_root = debugfs_create_file(name, 0664,
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -0700992 dev->debug_root, client,
993 &debug_client_fops);
994 mutex_unlock(&dev->lock);
995
996 return client;
997}
998
Laura Abbottb14ed962012-01-30 14:18:08 -0800999void ion_client_destroy(struct ion_client *client)
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001000{
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001001 struct ion_device *dev = client->dev;
1002 struct rb_node *n;
1003
1004 pr_debug("%s: %d\n", __func__, __LINE__);
1005 while ((n = rb_first(&client->handles))) {
1006 struct ion_handle *handle = rb_entry(n, struct ion_handle,
1007 node);
1008 ion_handle_destroy(&handle->ref);
1009 }
1010 mutex_lock(&dev->lock);
Laura Abbottb14ed962012-01-30 14:18:08 -08001011 if (client->task)
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001012 put_task_struct(client->task);
Laura Abbottb14ed962012-01-30 14:18:08 -08001013 rb_erase(&client->node, &dev->clients);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001014 debugfs_remove_recursive(client->debug_root);
1015 mutex_unlock(&dev->lock);
1016
Olav Haugan63e5f3b2012-01-11 16:42:37 -08001017 kfree(client->name);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001018 kfree(client);
1019}
Olav Hauganbd453a92012-07-05 14:21:34 -07001020EXPORT_SYMBOL(ion_client_destroy);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001021
Laura Abbott273dd8e2011-10-12 14:26:33 -07001022int ion_handle_get_flags(struct ion_client *client, struct ion_handle *handle,
1023 unsigned long *flags)
Rebecca Schultz Zavin46d71332012-05-07 16:06:32 -07001024{
1025 struct ion_buffer *buffer;
Rebecca Schultz Zavin46d71332012-05-07 16:06:32 -07001026
1027 mutex_lock(&client->lock);
1028 if (!ion_handle_validate(client, handle)) {
Laura Abbott273dd8e2011-10-12 14:26:33 -07001029 pr_err("%s: invalid handle passed to %s.\n",
1030 __func__, __func__);
Rebecca Schultz Zavin46d71332012-05-07 16:06:32 -07001031 mutex_unlock(&client->lock);
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001032 return -EINVAL;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001033 }
Laura Abbott273dd8e2011-10-12 14:26:33 -07001034 buffer = handle->buffer;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001035 mutex_lock(&buffer->lock);
Laura Abbott273dd8e2011-10-12 14:26:33 -07001036 *flags = buffer->flags;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001037 mutex_unlock(&buffer->lock);
Laura Abbott273dd8e2011-10-12 14:26:33 -07001038 mutex_unlock(&client->lock);
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001039
Laura Abbott273dd8e2011-10-12 14:26:33 -07001040 return 0;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001041}
Laura Abbott273dd8e2011-10-12 14:26:33 -07001042EXPORT_SYMBOL(ion_handle_get_flags);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001043
Laura Abbott8c017362011-09-22 20:59:12 -07001044int ion_handle_get_size(struct ion_client *client, struct ion_handle *handle,
1045 unsigned long *size)
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001046{
Laura Abbott8c017362011-09-22 20:59:12 -07001047 struct ion_buffer *buffer;
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001048
Laura Abbott8c017362011-09-22 20:59:12 -07001049 mutex_lock(&client->lock);
1050 if (!ion_handle_validate(client, handle)) {
1051 pr_err("%s: invalid handle passed to %s.\n",
1052 __func__, __func__);
1053 mutex_unlock(&client->lock);
1054 return -EINVAL;
Rebecca Schultz Zavinbe4a1ee2012-04-26 20:44:10 -07001055 }
Laura Abbott8c017362011-09-22 20:59:12 -07001056 buffer = handle->buffer;
Rebecca Schultz Zavinbe4a1ee2012-04-26 20:44:10 -07001057 mutex_lock(&buffer->lock);
Laura Abbott8c017362011-09-22 20:59:12 -07001058 *size = buffer->size;
Rebecca Schultz Zavinbe4a1ee2012-04-26 20:44:10 -07001059 mutex_unlock(&buffer->lock);
Laura Abbott8c017362011-09-22 20:59:12 -07001060 mutex_unlock(&client->lock);
1061
1062 return 0;
1063}
1064EXPORT_SYMBOL(ion_handle_get_size);
1065
Laura Abbottb14ed962012-01-30 14:18:08 -08001066struct sg_table *ion_sg_table(struct ion_client *client,
1067 struct ion_handle *handle)
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001068{
Laura Abbottb14ed962012-01-30 14:18:08 -08001069 struct ion_buffer *buffer;
1070 struct sg_table *table;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001071
Laura Abbottb14ed962012-01-30 14:18:08 -08001072 mutex_lock(&client->lock);
1073 if (!ion_handle_validate(client, handle)) {
1074 pr_err("%s: invalid handle passed to map_dma.\n",
1075 __func__);
1076 mutex_unlock(&client->lock);
1077 return ERR_PTR(-EINVAL);
1078 }
1079 buffer = handle->buffer;
1080 table = buffer->sg_table;
1081 mutex_unlock(&client->lock);
1082 return table;
1083}
Olav Hauganbd453a92012-07-05 14:21:34 -07001084EXPORT_SYMBOL(ion_sg_table);
Laura Abbottb14ed962012-01-30 14:18:08 -08001085
1086static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment,
1087 enum dma_data_direction direction)
1088{
1089 struct dma_buf *dmabuf = attachment->dmabuf;
1090 struct ion_buffer *buffer = dmabuf->priv;
1091
1092 return buffer->sg_table;
1093}
1094
1095static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment,
1096 struct sg_table *table,
1097 enum dma_data_direction direction)
1098{
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001099}
1100
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001101static void ion_vma_open(struct vm_area_struct *vma)
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001102{
Laura Abbottb14ed962012-01-30 14:18:08 -08001103 struct ion_buffer *buffer = vma->vm_private_data;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001104
1105 pr_debug("%s: %d\n", __func__, __LINE__);
Laura Abbottb14ed962012-01-30 14:18:08 -08001106
Rebecca Schultz Zavinbe4a1ee2012-04-26 20:44:10 -07001107 mutex_lock(&buffer->lock);
Laura Abbott77168502011-12-05 11:06:24 -08001108 buffer->umap_cnt++;
Rebecca Schultz Zavinbe4a1ee2012-04-26 20:44:10 -07001109 mutex_unlock(&buffer->lock);
1110}
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001111
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001112static void ion_vma_close(struct vm_area_struct *vma)
1113{
Laura Abbottb14ed962012-01-30 14:18:08 -08001114 struct ion_buffer *buffer = vma->vm_private_data;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001115
1116 pr_debug("%s: %d\n", __func__, __LINE__);
Laura Abbottb14ed962012-01-30 14:18:08 -08001117
Laura Abbott77168502011-12-05 11:06:24 -08001118 mutex_lock(&buffer->lock);
1119 buffer->umap_cnt--;
1120 mutex_unlock(&buffer->lock);
Laura Abbotta6835092011-11-14 15:27:02 -08001121
1122 if (buffer->heap->ops->unmap_user)
1123 buffer->heap->ops->unmap_user(buffer->heap, buffer);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001124}
1125
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001126static struct vm_operations_struct ion_vm_ops = {
1127 .open = ion_vma_open,
1128 .close = ion_vma_close,
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001129};
1130
Laura Abbottb14ed962012-01-30 14:18:08 -08001131static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001132{
Laura Abbottb14ed962012-01-30 14:18:08 -08001133 struct ion_buffer *buffer = dmabuf->priv;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001134 int ret;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001135
Laura Abbottb14ed962012-01-30 14:18:08 -08001136 if (!buffer->heap->ops->map_user) {
1137 pr_err("%s: this heap does not define a method for mapping "
1138 "to userspace\n", __func__);
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001139 return -EINVAL;
1140 }
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001141
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001142 mutex_lock(&buffer->lock);
1143 /* now map it to userspace */
Laura Abbottb14ed962012-01-30 14:18:08 -08001144 ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma);
Laura Abbotte8bc7aa2011-12-09 14:49:33 -08001145
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001146 if (ret) {
Laura Abbottb14ed962012-01-30 14:18:08 -08001147 mutex_unlock(&buffer->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001148 pr_err("%s: failure mapping buffer to userspace\n",
1149 __func__);
Laura Abbottb14ed962012-01-30 14:18:08 -08001150 } else {
1151 buffer->umap_cnt++;
1152 mutex_unlock(&buffer->lock);
1153
1154 vma->vm_ops = &ion_vm_ops;
1155 /*
1156 * move the buffer into the vm_private_data so we can access it
1157 * from vma_open/close
1158 */
1159 vma->vm_private_data = buffer;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001160 }
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001161 return ret;
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001162}
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001163
Laura Abbottb14ed962012-01-30 14:18:08 -08001164static void ion_dma_buf_release(struct dma_buf *dmabuf)
1165{
1166 struct ion_buffer *buffer = dmabuf->priv;
1167 ion_buffer_put(buffer);
1168}
1169
1170static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset)
1171{
1172 struct ion_buffer *buffer = dmabuf->priv;
1173 return buffer->vaddr + offset;
1174}
1175
1176static void ion_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset,
1177 void *ptr)
1178{
1179 return;
1180}
1181
1182static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start,
1183 size_t len,
1184 enum dma_data_direction direction)
1185{
1186 struct ion_buffer *buffer = dmabuf->priv;
1187 void *vaddr;
1188
1189 if (!buffer->heap->ops->map_kernel) {
1190 pr_err("%s: map kernel is not implemented by this heap.\n",
1191 __func__);
1192 return -ENODEV;
1193 }
1194
1195 mutex_lock(&buffer->lock);
1196 vaddr = ion_buffer_kmap_get(buffer);
1197 mutex_unlock(&buffer->lock);
1198 if (IS_ERR(vaddr))
1199 return PTR_ERR(vaddr);
1200 if (!vaddr)
1201 return -ENOMEM;
1202 return 0;
1203}
1204
1205static void ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, size_t start,
1206 size_t len,
1207 enum dma_data_direction direction)
1208{
1209 struct ion_buffer *buffer = dmabuf->priv;
1210
1211 mutex_lock(&buffer->lock);
1212 ion_buffer_kmap_put(buffer);
1213 mutex_unlock(&buffer->lock);
1214}
1215
1216struct dma_buf_ops dma_buf_ops = {
1217 .map_dma_buf = ion_map_dma_buf,
1218 .unmap_dma_buf = ion_unmap_dma_buf,
1219 .mmap = ion_mmap,
1220 .release = ion_dma_buf_release,
1221 .begin_cpu_access = ion_dma_buf_begin_cpu_access,
1222 .end_cpu_access = ion_dma_buf_end_cpu_access,
1223 .kmap_atomic = ion_dma_buf_kmap,
1224 .kunmap_atomic = ion_dma_buf_kunmap,
1225 .kmap = ion_dma_buf_kmap,
1226 .kunmap = ion_dma_buf_kunmap,
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001227};
1228
Laura Abbottb14ed962012-01-30 14:18:08 -08001229static int ion_share_set_flags(struct ion_client *client,
1230 struct ion_handle *handle,
1231 unsigned long flags)
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001232{
Laura Abbottb14ed962012-01-30 14:18:08 -08001233 struct ion_buffer *buffer;
1234 bool valid_handle;
1235 unsigned long ion_flags = ION_SET_CACHE(CACHED);
1236 if (flags & O_DSYNC)
1237 ion_flags = ION_SET_CACHE(UNCACHED);
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001238
Laura Abbottb14ed962012-01-30 14:18:08 -08001239 mutex_lock(&client->lock);
1240 valid_handle = ion_handle_validate(client, handle);
1241 mutex_unlock(&client->lock);
1242 if (!valid_handle) {
1243 WARN(1, "%s: invalid handle passed to set_flags.\n", __func__);
1244 return -EINVAL;
1245 }
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001246
Laura Abbottb14ed962012-01-30 14:18:08 -08001247 buffer = handle->buffer;
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001248
Laura Abbottb14ed962012-01-30 14:18:08 -08001249 mutex_lock(&buffer->lock);
1250 if (ion_validate_buffer_flags(buffer, ion_flags)) {
1251 mutex_unlock(&buffer->lock);
1252 return -EEXIST;
1253 }
1254 mutex_unlock(&buffer->lock);
1255 return 0;
1256}
Laura Abbott4b5d0482011-09-27 18:35:14 -07001257
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001258
Laura Abbottb14ed962012-01-30 14:18:08 -08001259int ion_share_dma_buf(struct ion_client *client, struct ion_handle *handle)
1260{
1261 struct ion_buffer *buffer;
1262 struct dma_buf *dmabuf;
1263 bool valid_handle;
1264 int fd;
1265
1266 mutex_lock(&client->lock);
1267 valid_handle = ion_handle_validate(client, handle);
1268 mutex_unlock(&client->lock);
1269 if (!valid_handle) {
Olav Haugan0df59942012-07-05 14:27:30 -07001270 WARN(1, "%s: invalid handle passed to share.\n", __func__);
Laura Abbottb14ed962012-01-30 14:18:08 -08001271 return -EINVAL;
1272 }
1273
1274 buffer = handle->buffer;
1275 ion_buffer_get(buffer);
1276 dmabuf = dma_buf_export(buffer, &dma_buf_ops, buffer->size, O_RDWR);
1277 if (IS_ERR(dmabuf)) {
1278 ion_buffer_put(buffer);
1279 return PTR_ERR(dmabuf);
1280 }
1281 fd = dma_buf_fd(dmabuf, O_CLOEXEC);
Ajay Dudani173f6132012-08-01 18:06:18 -07001282 if (fd < 0)
Laura Abbottb14ed962012-01-30 14:18:08 -08001283 dma_buf_put(dmabuf);
Ajay Dudani173f6132012-08-01 18:06:18 -07001284
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001285 return fd;
Laura Abbottb14ed962012-01-30 14:18:08 -08001286}
Olav Hauganbd453a92012-07-05 14:21:34 -07001287EXPORT_SYMBOL(ion_share_dma_buf);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001288
Laura Abbottb14ed962012-01-30 14:18:08 -08001289struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd)
1290{
1291 struct dma_buf *dmabuf;
1292 struct ion_buffer *buffer;
1293 struct ion_handle *handle;
1294
1295 dmabuf = dma_buf_get(fd);
1296 if (IS_ERR_OR_NULL(dmabuf))
1297 return ERR_PTR(PTR_ERR(dmabuf));
1298 /* if this memory came from ion */
1299
1300 if (dmabuf->ops != &dma_buf_ops) {
1301 pr_err("%s: can not import dmabuf from another exporter\n",
1302 __func__);
1303 dma_buf_put(dmabuf);
1304 return ERR_PTR(-EINVAL);
1305 }
1306 buffer = dmabuf->priv;
1307
1308 mutex_lock(&client->lock);
1309 /* if a handle exists for this buffer just take a reference to it */
1310 handle = ion_handle_lookup(client, buffer);
1311 if (!IS_ERR_OR_NULL(handle)) {
1312 ion_handle_get(handle);
1313 goto end;
1314 }
1315 handle = ion_handle_create(client, buffer);
1316 if (IS_ERR_OR_NULL(handle))
1317 goto end;
1318 ion_handle_add(client, handle);
1319end:
1320 mutex_unlock(&client->lock);
1321 dma_buf_put(dmabuf);
1322 return handle;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001323}
Olav Hauganbd453a92012-07-05 14:21:34 -07001324EXPORT_SYMBOL(ion_import_dma_buf);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001325
1326static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1327{
1328 struct ion_client *client = filp->private_data;
1329
1330 switch (cmd) {
1331 case ION_IOC_ALLOC:
1332 {
1333 struct ion_allocation_data data;
1334
1335 if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
1336 return -EFAULT;
1337 data.handle = ion_alloc(client, data.len, data.align,
1338 data.flags);
KyongHo Cho9ae7e012011-09-07 11:27:07 +09001339
Laura Abbottb14ed962012-01-30 14:18:08 -08001340 if (IS_ERR(data.handle))
1341 return PTR_ERR(data.handle);
KyongHo Cho9ae7e012011-09-07 11:27:07 +09001342
Laura Abbottb14ed962012-01-30 14:18:08 -08001343 if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
1344 ion_free(client, data.handle);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001345 return -EFAULT;
Laura Abbottb14ed962012-01-30 14:18:08 -08001346 }
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001347 break;
1348 }
1349 case ION_IOC_FREE:
1350 {
1351 struct ion_handle_data data;
1352 bool valid;
1353
1354 if (copy_from_user(&data, (void __user *)arg,
1355 sizeof(struct ion_handle_data)))
1356 return -EFAULT;
1357 mutex_lock(&client->lock);
1358 valid = ion_handle_validate(client, data.handle);
1359 mutex_unlock(&client->lock);
1360 if (!valid)
1361 return -EINVAL;
1362 ion_free(client, data.handle);
1363 break;
1364 }
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001365 case ION_IOC_MAP:
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001366 case ION_IOC_SHARE:
1367 {
1368 struct ion_fd_data data;
Laura Abbottb14ed962012-01-30 14:18:08 -08001369 int ret;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001370 if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
1371 return -EFAULT;
Laura Abbottb14ed962012-01-30 14:18:08 -08001372
1373 ret = ion_share_set_flags(client, data.handle, filp->f_flags);
1374 if (ret)
1375 return ret;
1376
1377 data.fd = ion_share_dma_buf(client, data.handle);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001378 if (copy_to_user((void __user *)arg, &data, sizeof(data)))
1379 return -EFAULT;
Olav Hauganc2d2cf52012-05-15 14:40:11 -07001380 if (data.fd < 0)
1381 return data.fd;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001382 break;
1383 }
1384 case ION_IOC_IMPORT:
1385 {
1386 struct ion_fd_data data;
Olav Hauganc2d2cf52012-05-15 14:40:11 -07001387 int ret = 0;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001388 if (copy_from_user(&data, (void __user *)arg,
1389 sizeof(struct ion_fd_data)))
1390 return -EFAULT;
Laura Abbottb14ed962012-01-30 14:18:08 -08001391 data.handle = ion_import_dma_buf(client, data.fd);
1392 if (IS_ERR(data.handle))
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001393 data.handle = NULL;
1394 if (copy_to_user((void __user *)arg, &data,
1395 sizeof(struct ion_fd_data)))
1396 return -EFAULT;
Olav Hauganc2d2cf52012-05-15 14:40:11 -07001397 if (ret < 0)
1398 return ret;
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001399 break;
1400 }
1401 case ION_IOC_CUSTOM:
1402 {
1403 struct ion_device *dev = client->dev;
1404 struct ion_custom_data data;
1405
1406 if (!dev->custom_ioctl)
1407 return -ENOTTY;
1408 if (copy_from_user(&data, (void __user *)arg,
1409 sizeof(struct ion_custom_data)))
1410 return -EFAULT;
1411 return dev->custom_ioctl(client, data.cmd, data.arg);
1412 }
Laura Abbottabcb6f72011-10-04 16:26:49 -07001413 case ION_IOC_CLEAN_CACHES:
Mitchel Humpherysfd02cfb2012-09-04 17:00:29 -07001414 return client->dev->custom_ioctl(client,
1415 ION_IOC_CLEAN_CACHES, arg);
Laura Abbottabcb6f72011-10-04 16:26:49 -07001416 case ION_IOC_INV_CACHES:
Mitchel Humpherysfd02cfb2012-09-04 17:00:29 -07001417 return client->dev->custom_ioctl(client,
1418 ION_IOC_INV_CACHES, arg);
Laura Abbottabcb6f72011-10-04 16:26:49 -07001419 case ION_IOC_CLEAN_INV_CACHES:
Mitchel Humpherysfd02cfb2012-09-04 17:00:29 -07001420 return client->dev->custom_ioctl(client,
1421 ION_IOC_CLEAN_INV_CACHES, arg);
Laura Abbott273dd8e2011-10-12 14:26:33 -07001422 case ION_IOC_GET_FLAGS:
Mitchel Humpherysfd02cfb2012-09-04 17:00:29 -07001423 return client->dev->custom_ioctl(client,
1424 ION_IOC_GET_FLAGS, arg);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001425 default:
1426 return -ENOTTY;
1427 }
1428 return 0;
1429}
1430
1431static int ion_release(struct inode *inode, struct file *file)
1432{
1433 struct ion_client *client = file->private_data;
1434
1435 pr_debug("%s: %d\n", __func__, __LINE__);
Laura Abbottb14ed962012-01-30 14:18:08 -08001436 ion_client_destroy(client);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001437 return 0;
1438}
1439
1440static int ion_open(struct inode *inode, struct file *file)
1441{
1442 struct miscdevice *miscdev = file->private_data;
1443 struct ion_device *dev = container_of(miscdev, struct ion_device, dev);
1444 struct ion_client *client;
Laura Abbotteed86032011-12-05 15:32:36 -08001445 char debug_name[64];
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001446
1447 pr_debug("%s: %d\n", __func__, __LINE__);
Laura Abbotteed86032011-12-05 15:32:36 -08001448 snprintf(debug_name, 64, "%u", task_pid_nr(current->group_leader));
1449 client = ion_client_create(dev, -1, debug_name);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001450 if (IS_ERR_OR_NULL(client))
1451 return PTR_ERR(client);
1452 file->private_data = client;
1453
1454 return 0;
1455}
1456
1457static const struct file_operations ion_fops = {
1458 .owner = THIS_MODULE,
1459 .open = ion_open,
1460 .release = ion_release,
1461 .unlocked_ioctl = ion_ioctl,
1462};
1463
1464static size_t ion_debug_heap_total(struct ion_client *client,
Laura Abbott3647ac32011-10-31 14:09:53 -07001465 enum ion_heap_ids id)
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001466{
1467 size_t size = 0;
1468 struct rb_node *n;
1469
1470 mutex_lock(&client->lock);
1471 for (n = rb_first(&client->handles); n; n = rb_next(n)) {
1472 struct ion_handle *handle = rb_entry(n,
1473 struct ion_handle,
1474 node);
Laura Abbott3647ac32011-10-31 14:09:53 -07001475 if (handle->buffer->heap->id == id)
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001476 size += handle->buffer->size;
1477 }
1478 mutex_unlock(&client->lock);
1479 return size;
1480}
1481
Olav Haugan0671b9a2012-05-25 11:58:56 -07001482/**
1483 * Searches through a clients handles to find if the buffer is owned
1484 * by this client. Used for debug output.
1485 * @param client pointer to candidate owner of buffer
1486 * @param buf pointer to buffer that we are trying to find the owner of
1487 * @return 1 if found, 0 otherwise
1488 */
1489static int ion_debug_find_buffer_owner(const struct ion_client *client,
1490 const struct ion_buffer *buf)
1491{
1492 struct rb_node *n;
1493
1494 for (n = rb_first(&client->handles); n; n = rb_next(n)) {
1495 const struct ion_handle *handle = rb_entry(n,
1496 const struct ion_handle,
1497 node);
1498 if (handle->buffer == buf)
1499 return 1;
1500 }
1501 return 0;
1502}
1503
1504/**
1505 * Adds mem_map_data pointer to the tree of mem_map
1506 * Used for debug output.
1507 * @param mem_map The mem_map tree
1508 * @param data The new data to add to the tree
1509 */
1510static void ion_debug_mem_map_add(struct rb_root *mem_map,
1511 struct mem_map_data *data)
1512{
1513 struct rb_node **p = &mem_map->rb_node;
1514 struct rb_node *parent = NULL;
1515 struct mem_map_data *entry;
1516
1517 while (*p) {
1518 parent = *p;
1519 entry = rb_entry(parent, struct mem_map_data, node);
1520
1521 if (data->addr < entry->addr) {
1522 p = &(*p)->rb_left;
1523 } else if (data->addr > entry->addr) {
1524 p = &(*p)->rb_right;
1525 } else {
1526 pr_err("%s: mem_map_data already found.", __func__);
1527 BUG();
1528 }
1529 }
1530 rb_link_node(&data->node, parent, p);
1531 rb_insert_color(&data->node, mem_map);
1532}
1533
1534/**
1535 * Search for an owner of a buffer by iterating over all ION clients.
1536 * @param dev ion device containing pointers to all the clients.
1537 * @param buffer pointer to buffer we are trying to find the owner of.
1538 * @return name of owner.
1539 */
1540const char *ion_debug_locate_owner(const struct ion_device *dev,
1541 const struct ion_buffer *buffer)
1542{
1543 struct rb_node *j;
1544 const char *client_name = NULL;
1545
Laura Abbottb14ed962012-01-30 14:18:08 -08001546 for (j = rb_first(&dev->clients); j && !client_name;
Olav Haugan0671b9a2012-05-25 11:58:56 -07001547 j = rb_next(j)) {
1548 struct ion_client *client = rb_entry(j, struct ion_client,
1549 node);
1550 if (ion_debug_find_buffer_owner(client, buffer))
1551 client_name = client->name;
1552 }
1553 return client_name;
1554}
1555
1556/**
1557 * Create a mem_map of the heap.
1558 * @param s seq_file to log error message to.
1559 * @param heap The heap to create mem_map for.
1560 * @param mem_map The mem map to be created.
1561 */
1562void ion_debug_mem_map_create(struct seq_file *s, struct ion_heap *heap,
1563 struct rb_root *mem_map)
1564{
1565 struct ion_device *dev = heap->dev;
1566 struct rb_node *n;
1567
1568 for (n = rb_first(&dev->buffers); n; n = rb_next(n)) {
1569 struct ion_buffer *buffer =
1570 rb_entry(n, struct ion_buffer, node);
1571 if (buffer->heap->id == heap->id) {
1572 struct mem_map_data *data =
1573 kzalloc(sizeof(*data), GFP_KERNEL);
1574 if (!data) {
1575 seq_printf(s, "ERROR: out of memory. "
1576 "Part of memory map will not be logged\n");
1577 break;
1578 }
1579 data->addr = buffer->priv_phys;
1580 data->addr_end = buffer->priv_phys + buffer->size-1;
1581 data->size = buffer->size;
1582 data->client_name = ion_debug_locate_owner(dev, buffer);
1583 ion_debug_mem_map_add(mem_map, data);
1584 }
1585 }
1586}
1587
1588/**
1589 * Free the memory allocated by ion_debug_mem_map_create
1590 * @param mem_map The mem map to free.
1591 */
1592static void ion_debug_mem_map_destroy(struct rb_root *mem_map)
1593{
1594 if (mem_map) {
1595 struct rb_node *n;
1596 while ((n = rb_first(mem_map)) != 0) {
1597 struct mem_map_data *data =
1598 rb_entry(n, struct mem_map_data, node);
1599 rb_erase(&data->node, mem_map);
1600 kfree(data);
1601 }
1602 }
1603}
1604
1605/**
1606 * Print heap debug information.
1607 * @param s seq_file to log message to.
1608 * @param heap pointer to heap that we will print debug information for.
1609 */
1610static void ion_heap_print_debug(struct seq_file *s, struct ion_heap *heap)
1611{
1612 if (heap->ops->print_debug) {
1613 struct rb_root mem_map = RB_ROOT;
1614 ion_debug_mem_map_create(s, heap, &mem_map);
1615 heap->ops->print_debug(heap, s, &mem_map);
1616 ion_debug_mem_map_destroy(&mem_map);
1617 }
1618}
1619
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001620static int ion_debug_heap_show(struct seq_file *s, void *unused)
1621{
1622 struct ion_heap *heap = s->private;
1623 struct ion_device *dev = heap->dev;
1624 struct rb_node *n;
1625
Olav Haugane4900b52012-05-25 11:58:03 -07001626 mutex_lock(&dev->lock);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001627 seq_printf(s, "%16.s %16.s %16.s\n", "client", "pid", "size");
Rebecca Schultz Zavin043a6142012-02-01 11:09:46 -08001628
Laura Abbottb14ed962012-01-30 14:18:08 -08001629 for (n = rb_first(&dev->clients); n; n = rb_next(n)) {
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001630 struct ion_client *client = rb_entry(n, struct ion_client,
1631 node);
Laura Abbott3647ac32011-10-31 14:09:53 -07001632 size_t size = ion_debug_heap_total(client, heap->id);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001633 if (!size)
1634 continue;
Laura Abbottb14ed962012-01-30 14:18:08 -08001635 if (client->task) {
1636 char task_comm[TASK_COMM_LEN];
1637
1638 get_task_comm(task_comm, client->task);
1639 seq_printf(s, "%16.s %16u %16u\n", task_comm,
1640 client->pid, size);
1641 } else {
1642 seq_printf(s, "%16.s %16u %16u\n", client->name,
1643 client->pid, size);
1644 }
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001645 }
Olav Haugan0671b9a2012-05-25 11:58:56 -07001646 ion_heap_print_debug(s, heap);
Olav Haugane4900b52012-05-25 11:58:03 -07001647 mutex_unlock(&dev->lock);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001648 return 0;
1649}
1650
1651static int ion_debug_heap_open(struct inode *inode, struct file *file)
1652{
1653 return single_open(file, ion_debug_heap_show, inode->i_private);
1654}
1655
1656static const struct file_operations debug_heap_fops = {
1657 .open = ion_debug_heap_open,
1658 .read = seq_read,
1659 .llseek = seq_lseek,
1660 .release = single_release,
1661};
1662
1663void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
1664{
1665 struct rb_node **p = &dev->heaps.rb_node;
1666 struct rb_node *parent = NULL;
1667 struct ion_heap *entry;
1668
Laura Abbottb14ed962012-01-30 14:18:08 -08001669 if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma ||
1670 !heap->ops->unmap_dma)
1671 pr_err("%s: can not add heap with invalid ops struct.\n",
1672 __func__);
1673
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001674 heap->dev = dev;
1675 mutex_lock(&dev->lock);
1676 while (*p) {
1677 parent = *p;
1678 entry = rb_entry(parent, struct ion_heap, node);
1679
1680 if (heap->id < entry->id) {
1681 p = &(*p)->rb_left;
1682 } else if (heap->id > entry->id ) {
1683 p = &(*p)->rb_right;
1684 } else {
1685 pr_err("%s: can not insert multiple heaps with "
1686 "id %d\n", __func__, heap->id);
1687 goto end;
1688 }
1689 }
1690
1691 rb_link_node(&heap->node, parent, p);
1692 rb_insert_color(&heap->node, &dev->heaps);
1693 debugfs_create_file(heap->name, 0664, dev->debug_root, heap,
1694 &debug_heap_fops);
1695end:
1696 mutex_unlock(&dev->lock);
1697}
1698
Laura Abbott7e446482012-06-13 15:59:39 -07001699int ion_secure_heap(struct ion_device *dev, int heap_id, int version,
1700 void *data)
Olav Haugan0a852512012-01-09 10:20:55 -08001701{
1702 struct rb_node *n;
1703 int ret_val = 0;
1704
1705 /*
1706 * traverse the list of heaps available in this system
1707 * and find the heap that is specified.
1708 */
1709 mutex_lock(&dev->lock);
1710 for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) {
1711 struct ion_heap *heap = rb_entry(n, struct ion_heap, node);
1712 if (heap->type != ION_HEAP_TYPE_CP)
1713 continue;
1714 if (ION_HEAP(heap->id) != heap_id)
1715 continue;
1716 if (heap->ops->secure_heap)
Laura Abbott7e446482012-06-13 15:59:39 -07001717 ret_val = heap->ops->secure_heap(heap, version, data);
Olav Haugan0a852512012-01-09 10:20:55 -08001718 else
1719 ret_val = -EINVAL;
1720 break;
1721 }
1722 mutex_unlock(&dev->lock);
1723 return ret_val;
1724}
Olav Hauganbd453a92012-07-05 14:21:34 -07001725EXPORT_SYMBOL(ion_secure_heap);
Olav Haugan0a852512012-01-09 10:20:55 -08001726
Laura Abbott7e446482012-06-13 15:59:39 -07001727int ion_unsecure_heap(struct ion_device *dev, int heap_id, int version,
1728 void *data)
Olav Haugan0a852512012-01-09 10:20:55 -08001729{
1730 struct rb_node *n;
1731 int ret_val = 0;
1732
1733 /*
1734 * traverse the list of heaps available in this system
1735 * and find the heap that is specified.
1736 */
1737 mutex_lock(&dev->lock);
1738 for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) {
1739 struct ion_heap *heap = rb_entry(n, struct ion_heap, node);
1740 if (heap->type != ION_HEAP_TYPE_CP)
1741 continue;
1742 if (ION_HEAP(heap->id) != heap_id)
1743 continue;
1744 if (heap->ops->secure_heap)
Laura Abbott7e446482012-06-13 15:59:39 -07001745 ret_val = heap->ops->unsecure_heap(heap, version, data);
Olav Haugan0a852512012-01-09 10:20:55 -08001746 else
1747 ret_val = -EINVAL;
1748 break;
1749 }
1750 mutex_unlock(&dev->lock);
1751 return ret_val;
1752}
Olav Hauganbd453a92012-07-05 14:21:34 -07001753EXPORT_SYMBOL(ion_unsecure_heap);
Olav Haugan0a852512012-01-09 10:20:55 -08001754
Laura Abbott404f8242011-10-31 14:22:53 -07001755static int ion_debug_leak_show(struct seq_file *s, void *unused)
1756{
1757 struct ion_device *dev = s->private;
1758 struct rb_node *n;
1759 struct rb_node *n2;
1760
1761 /* mark all buffers as 1 */
1762 seq_printf(s, "%16.s %16.s %16.s %16.s\n", "buffer", "heap", "size",
1763 "ref cnt");
1764 mutex_lock(&dev->lock);
1765 for (n = rb_first(&dev->buffers); n; n = rb_next(n)) {
1766 struct ion_buffer *buf = rb_entry(n, struct ion_buffer,
1767 node);
1768
1769 buf->marked = 1;
1770 }
1771
1772 /* now see which buffers we can access */
Laura Abbottb14ed962012-01-30 14:18:08 -08001773 for (n = rb_first(&dev->clients); n; n = rb_next(n)) {
Laura Abbott404f8242011-10-31 14:22:53 -07001774 struct ion_client *client = rb_entry(n, struct ion_client,
1775 node);
1776
1777 mutex_lock(&client->lock);
1778 for (n2 = rb_first(&client->handles); n2; n2 = rb_next(n2)) {
1779 struct ion_handle *handle = rb_entry(n2,
1780 struct ion_handle, node);
1781
1782 handle->buffer->marked = 0;
1783
1784 }
1785 mutex_unlock(&client->lock);
1786
1787 }
1788
Laura Abbott404f8242011-10-31 14:22:53 -07001789 /* And anyone still marked as a 1 means a leaked handle somewhere */
1790 for (n = rb_first(&dev->buffers); n; n = rb_next(n)) {
1791 struct ion_buffer *buf = rb_entry(n, struct ion_buffer,
1792 node);
1793
1794 if (buf->marked == 1)
1795 seq_printf(s, "%16.x %16.s %16.x %16.d\n",
1796 (int)buf, buf->heap->name, buf->size,
1797 atomic_read(&buf->ref.refcount));
1798 }
1799 mutex_unlock(&dev->lock);
1800 return 0;
1801}
1802
1803static int ion_debug_leak_open(struct inode *inode, struct file *file)
1804{
1805 return single_open(file, ion_debug_leak_show, inode->i_private);
1806}
1807
1808static const struct file_operations debug_leak_fops = {
1809 .open = ion_debug_leak_open,
1810 .read = seq_read,
1811 .llseek = seq_lseek,
1812 .release = single_release,
1813};
1814
1815
1816
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001817struct ion_device *ion_device_create(long (*custom_ioctl)
1818 (struct ion_client *client,
1819 unsigned int cmd,
1820 unsigned long arg))
1821{
1822 struct ion_device *idev;
1823 int ret;
1824
1825 idev = kzalloc(sizeof(struct ion_device), GFP_KERNEL);
1826 if (!idev)
1827 return ERR_PTR(-ENOMEM);
1828
1829 idev->dev.minor = MISC_DYNAMIC_MINOR;
1830 idev->dev.name = "ion";
1831 idev->dev.fops = &ion_fops;
1832 idev->dev.parent = NULL;
1833 ret = misc_register(&idev->dev);
1834 if (ret) {
1835 pr_err("ion: failed to register misc device.\n");
1836 return ERR_PTR(ret);
1837 }
1838
1839 idev->debug_root = debugfs_create_dir("ion", NULL);
1840 if (IS_ERR_OR_NULL(idev->debug_root))
1841 pr_err("ion: failed to create debug files.\n");
1842
1843 idev->custom_ioctl = custom_ioctl;
1844 idev->buffers = RB_ROOT;
1845 mutex_init(&idev->lock);
1846 idev->heaps = RB_ROOT;
Laura Abbottb14ed962012-01-30 14:18:08 -08001847 idev->clients = RB_ROOT;
Laura Abbott404f8242011-10-31 14:22:53 -07001848 debugfs_create_file("check_leaked_fds", 0664, idev->debug_root, idev,
1849 &debug_leak_fops);
Rebecca Schultz Zavin0c38bfd2011-06-29 19:44:29 -07001850 return idev;
1851}
1852
1853void ion_device_destroy(struct ion_device *dev)
1854{
1855 misc_deregister(&dev->dev);
1856 /* XXX need to free the heaps and clients ? */
1857 kfree(dev);
1858}
Laura Abbottb14ed962012-01-30 14:18:08 -08001859
1860void __init ion_reserve(struct ion_platform_data *data)
1861{
1862 int i, ret;
1863
1864 for (i = 0; i < data->nr; i++) {
1865 if (data->heaps[i].size == 0)
1866 continue;
1867 ret = memblock_reserve(data->heaps[i].base,
1868 data->heaps[i].size);
1869 if (ret)
1870 pr_err("memblock reserve of %x@%lx failed\n",
1871 data->heaps[i].size,
1872 data->heaps[i].base);
1873 }
1874}