blob: d436ef41a0980895e44258dbc0da60036a9ff9dd [file] [log] [blame]
Rebecca Schultz Zavinc80005a2011-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 Zavinc80005a2011-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
18#include <linux/device.h>
19#include <linux/file.h>
20#include <linux/fs.h>
21#include <linux/anon_inodes.h>
22#include <linux/ion.h>
23#include <linux/list.h>
24#include <linux/miscdevice.h>
25#include <linux/mm.h>
26#include <linux/mm_types.h>
27#include <linux/rbtree.h>
28#include <linux/sched.h>
29#include <linux/slab.h>
30#include <linux/seq_file.h>
31#include <linux/uaccess.h>
32#include <linux/debugfs.h>
33
Laura Abbott8c017362011-09-22 20:59:12 -070034#include <mach/iommu_domains.h>
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -070035#include "ion_priv.h"
36#define DEBUG
37
38/**
39 * struct ion_device - the metadata of the ion device node
40 * @dev: the actual misc device
41 * @buffers: an rb tree of all the existing buffers
42 * @lock: lock protecting the buffers & heaps trees
43 * @heaps: list of all the heaps in the system
44 * @user_clients: list of all the clients created from userspace
45 */
46struct ion_device {
47 struct miscdevice dev;
48 struct rb_root buffers;
49 struct mutex lock;
50 struct rb_root heaps;
51 long (*custom_ioctl) (struct ion_client *client, unsigned int cmd,
52 unsigned long arg);
53 struct rb_root user_clients;
54 struct rb_root kernel_clients;
55 struct dentry *debug_root;
56};
57
58/**
59 * struct ion_client - a process/hw block local address space
60 * @ref: for reference counting the client
61 * @node: node in the tree of all clients
62 * @dev: backpointer to ion device
63 * @handles: an rb tree of all the handles in this client
64 * @lock: lock protecting the tree of handles
65 * @heap_mask: mask of all supported heaps
66 * @name: used for debugging
67 * @task: used for debugging
68 *
69 * A client represents a list of buffers this client may access.
70 * The mutex stored here is used to protect both handles tree
71 * as well as the handles themselves, and should be held while modifying either.
72 */
73struct ion_client {
74 struct kref ref;
75 struct rb_node node;
76 struct ion_device *dev;
77 struct rb_root handles;
78 struct mutex lock;
79 unsigned int heap_mask;
80 const char *name;
81 struct task_struct *task;
82 pid_t pid;
83 struct dentry *debug_root;
84};
85
86/**
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -070087 * ion_handle - a client local reference to a buffer
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -070088 * @ref: reference count
89 * @client: back pointer to the client the buffer resides in
90 * @buffer: pointer to the buffer
91 * @node: node in the client's handle rbtree
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -070092 * @kmap_cnt: count of times this client has mapped to kernel
93 * @dmap_cnt: count of times this client has mapped for dma
94 * @usermap_cnt: count of times this client has mapped for userspace
Rebecca Schultz Zavinc80005a2011-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;
105 unsigned int dmap_cnt;
106 unsigned int usermap_cnt;
Laura Abbott8c017362011-09-22 20:59:12 -0700107 unsigned int iommu_map_cnt;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700108};
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 Zavinc80005a2011-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
Rebecca Schultz Zavinf9fb95e2011-06-30 18:09:05 -0700140 if (buffer < entry) {
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700141 p = &(*p)->rb_left;
Rebecca Schultz Zavinf9fb95e2011-06-30 18:09:05 -0700142 } else if (buffer > entry) {
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700143 p = &(*p)->rb_right;
Rebecca Schultz Zavinf9fb95e2011-06-30 18:09:05 -0700144 } else {
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -0700145 pr_err("%s: buffer already found.", __func__);
146 BUG();
Rebecca Schultz Zavinf9fb95e2011-06-30 18:09:05 -0700147 }
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700148 }
149
150 rb_link_node(&buffer->node, parent, p);
151 rb_insert_color(&buffer->node, &dev->buffers);
152}
153
Laura Abbott8c017362011-09-22 20:59:12 -0700154void ion_iommu_add(struct ion_buffer *buffer,
155 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 Zavinc80005a2011-06-29 19:44:29 -0700209/* this function should only be called while dev->lock is held */
Iliyan Malchev3fe24362011-08-09 14:42:08 -0700210static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700211 struct ion_device *dev,
212 unsigned long len,
213 unsigned long align,
214 unsigned long flags)
215{
216 struct ion_buffer *buffer;
217 int ret;
218
219 buffer = kzalloc(sizeof(struct ion_buffer), GFP_KERNEL);
220 if (!buffer)
221 return ERR_PTR(-ENOMEM);
222
223 buffer->heap = heap;
224 kref_init(&buffer->ref);
225
226 ret = heap->ops->allocate(heap, buffer, len, align, flags);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -0700227 if (ret) {
228 kfree(buffer);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700229 return ERR_PTR(ret);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -0700230 }
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700231 buffer->dev = dev;
232 buffer->size = len;
233 mutex_init(&buffer->lock);
234 ion_buffer_add(dev, buffer);
235 return buffer;
236}
237
238static void ion_buffer_destroy(struct kref *kref)
239{
240 struct ion_buffer *buffer = container_of(kref, struct ion_buffer, ref);
241 struct ion_device *dev = buffer->dev;
242
243 buffer->heap->ops->free(buffer);
244 mutex_lock(&dev->lock);
245 rb_erase(&buffer->node, &dev->buffers);
246 mutex_unlock(&dev->lock);
247 kfree(buffer);
248}
249
250static void ion_buffer_get(struct ion_buffer *buffer)
251{
252 kref_get(&buffer->ref);
253}
254
255static int ion_buffer_put(struct ion_buffer *buffer)
256{
257 return kref_put(&buffer->ref, ion_buffer_destroy);
258}
259
Iliyan Malchev3fe24362011-08-09 14:42:08 -0700260static struct ion_handle *ion_handle_create(struct ion_client *client,
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700261 struct ion_buffer *buffer)
262{
263 struct ion_handle *handle;
264
265 handle = kzalloc(sizeof(struct ion_handle), GFP_KERNEL);
266 if (!handle)
267 return ERR_PTR(-ENOMEM);
268 kref_init(&handle->ref);
Iliyan Malchev3fe24362011-08-09 14:42:08 -0700269 rb_init_node(&handle->node);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700270 handle->client = client;
271 ion_buffer_get(buffer);
272 handle->buffer = buffer;
273
274 return handle;
275}
276
277static void ion_handle_destroy(struct kref *kref)
278{
279 struct ion_handle *handle = container_of(kref, struct ion_handle, ref);
280 /* XXX Can a handle be destroyed while it's map count is non-zero?:
281 if (handle->map_cnt) unmap
282 */
Laura Abbottd2a87372011-10-20 17:53:49 -0700283 WARN_ON(handle->kmap_cnt || handle->dmap_cnt || handle->usermap_cnt);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700284 ion_buffer_put(handle->buffer);
285 mutex_lock(&handle->client->lock);
Iliyan Malchev3fe24362011-08-09 14:42:08 -0700286 if (!RB_EMPTY_NODE(&handle->node))
287 rb_erase(&handle->node, &handle->client->handles);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700288 mutex_unlock(&handle->client->lock);
289 kfree(handle);
290}
291
292struct ion_buffer *ion_handle_buffer(struct ion_handle *handle)
293{
294 return handle->buffer;
295}
296
297static void ion_handle_get(struct ion_handle *handle)
298{
299 kref_get(&handle->ref);
300}
301
302static int ion_handle_put(struct ion_handle *handle)
303{
304 return kref_put(&handle->ref, ion_handle_destroy);
305}
306
307static struct ion_handle *ion_handle_lookup(struct ion_client *client,
308 struct ion_buffer *buffer)
309{
310 struct rb_node *n;
311
312 for (n = rb_first(&client->handles); n; n = rb_next(n)) {
313 struct ion_handle *handle = rb_entry(n, struct ion_handle,
314 node);
315 if (handle->buffer == buffer)
316 return handle;
317 }
318 return NULL;
319}
320
Iliyan Malchev3fe24362011-08-09 14:42:08 -0700321static bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle)
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700322{
323 struct rb_node *n = client->handles.rb_node;
324
325 while (n) {
326 struct ion_handle *handle_node = rb_entry(n, struct ion_handle,
327 node);
328 if (handle < handle_node)
329 n = n->rb_left;
330 else if (handle > handle_node)
331 n = n->rb_right;
332 else
333 return true;
334 }
335 return false;
336}
337
338static void ion_handle_add(struct ion_client *client, struct ion_handle *handle)
339{
340 struct rb_node **p = &client->handles.rb_node;
341 struct rb_node *parent = NULL;
342 struct ion_handle *entry;
343
344 while (*p) {
345 parent = *p;
346 entry = rb_entry(parent, struct ion_handle, node);
347
348 if (handle < entry)
349 p = &(*p)->rb_left;
350 else if (handle > entry)
351 p = &(*p)->rb_right;
352 else
353 WARN(1, "%s: buffer already found.", __func__);
354 }
355
356 rb_link_node(&handle->node, parent, p);
357 rb_insert_color(&handle->node, &client->handles);
358}
359
360struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
361 size_t align, unsigned int flags)
362{
363 struct rb_node *n;
364 struct ion_handle *handle;
365 struct ion_device *dev = client->dev;
366 struct ion_buffer *buffer = NULL;
Olav Haugan0a852512012-01-09 10:20:55 -0800367 unsigned long secure_allocation = flags & ION_SECURE;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700368
369 /*
370 * traverse the list of heaps available in this system in priority
371 * order. If the heap type is supported by the client, and matches the
372 * request of the caller allocate from it. Repeat until allocate has
373 * succeeded or all heaps have been tried
374 */
375 mutex_lock(&dev->lock);
376 for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) {
377 struct ion_heap *heap = rb_entry(n, struct ion_heap, node);
378 /* if the client doesn't support this heap type */
379 if (!((1 << heap->type) & client->heap_mask))
380 continue;
381 /* if the caller didn't specify this heap type */
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -0700382 if (!((1 << heap->id) & flags))
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700383 continue;
Olav Haugan0a852512012-01-09 10:20:55 -0800384 /* Do not allow un-secure heap if secure is specified */
385 if (secure_allocation && (heap->type != ION_HEAP_TYPE_CP))
386 continue;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700387 buffer = ion_buffer_create(heap, dev, len, align, flags);
388 if (!IS_ERR_OR_NULL(buffer))
389 break;
390 }
391 mutex_unlock(&dev->lock);
392
393 if (IS_ERR_OR_NULL(buffer))
394 return ERR_PTR(PTR_ERR(buffer));
395
396 handle = ion_handle_create(client, buffer);
397
398 if (IS_ERR_OR_NULL(handle))
399 goto end;
400
401 /*
402 * ion_buffer_create will create a buffer with a ref_cnt of 1,
403 * and ion_handle_create will take a second reference, drop one here
404 */
405 ion_buffer_put(buffer);
406
407 mutex_lock(&client->lock);
408 ion_handle_add(client, handle);
409 mutex_unlock(&client->lock);
410 return handle;
411
412end:
413 ion_buffer_put(buffer);
414 return handle;
415}
416
417void ion_free(struct ion_client *client, struct ion_handle *handle)
418{
Rebecca Schultz Zavinc72866d2011-07-07 17:07:56 -0700419 bool valid_handle;
420
421 BUG_ON(client != handle->client);
422
423 mutex_lock(&client->lock);
424 valid_handle = ion_handle_validate(client, handle);
425 mutex_unlock(&client->lock);
426
427 if (!valid_handle) {
428 WARN("%s: invalid handle passed to free.\n", __func__);
429 return;
430 }
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700431 ion_handle_put(handle);
432}
433
434static void ion_client_get(struct ion_client *client);
435static int ion_client_put(struct ion_client *client);
436
Iliyan Malchev3fe24362011-08-09 14:42:08 -0700437static bool _ion_map(int *buffer_cnt, int *handle_cnt)
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700438{
439 bool map;
440
441 BUG_ON(*handle_cnt != 0 && *buffer_cnt == 0);
442
443 if (*buffer_cnt)
444 map = false;
445 else
446 map = true;
447 if (*handle_cnt == 0)
448 (*buffer_cnt)++;
449 (*handle_cnt)++;
450 return map;
451}
452
Iliyan Malchev3fe24362011-08-09 14:42:08 -0700453static bool _ion_unmap(int *buffer_cnt, int *handle_cnt)
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700454{
455 BUG_ON(*handle_cnt == 0);
456 (*handle_cnt)--;
457 if (*handle_cnt != 0)
458 return false;
459 BUG_ON(*buffer_cnt == 0);
460 (*buffer_cnt)--;
461 if (*buffer_cnt == 0)
462 return true;
463 return false;
464}
465
466int ion_phys(struct ion_client *client, struct ion_handle *handle,
467 ion_phys_addr_t *addr, size_t *len)
468{
469 struct ion_buffer *buffer;
470 int ret;
471
472 mutex_lock(&client->lock);
473 if (!ion_handle_validate(client, handle)) {
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -0700474 mutex_unlock(&client->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700475 return -EINVAL;
476 }
477
478 buffer = handle->buffer;
479
480 if (!buffer->heap->ops->phys) {
481 pr_err("%s: ion_phys is not implemented by this heap.\n",
482 __func__);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -0700483 mutex_unlock(&client->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700484 return -ENODEV;
485 }
486 mutex_unlock(&client->lock);
487 ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len);
488 return ret;
489}
490
Laura Abbott894fd582011-08-19 13:33:56 -0700491void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle,
492 unsigned long flags)
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700493{
494 struct ion_buffer *buffer;
495 void *vaddr;
496
497 mutex_lock(&client->lock);
498 if (!ion_handle_validate(client, handle)) {
499 pr_err("%s: invalid handle passed to map_kernel.\n",
500 __func__);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -0700501 mutex_unlock(&client->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700502 return ERR_PTR(-EINVAL);
503 }
504
505 buffer = handle->buffer;
506 mutex_lock(&buffer->lock);
507
508 if (!handle->buffer->heap->ops->map_kernel) {
509 pr_err("%s: map_kernel is not implemented by this heap.\n",
510 __func__);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -0700511 mutex_unlock(&buffer->lock);
512 mutex_unlock(&client->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700513 return ERR_PTR(-ENODEV);
514 }
515
Laura Abbott8c017362011-09-22 20:59:12 -0700516 if (ion_validate_buffer_flags(buffer, flags)) {
Laura Abbott894fd582011-08-19 13:33:56 -0700517 vaddr = ERR_PTR(-EEXIST);
518 goto out;
Laura Abbott894fd582011-08-19 13:33:56 -0700519 }
520
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700521 if (_ion_map(&buffer->kmap_cnt, &handle->kmap_cnt)) {
Laura Abbott894fd582011-08-19 13:33:56 -0700522 vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer,
523 flags);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700524 if (IS_ERR_OR_NULL(vaddr))
525 _ion_unmap(&buffer->kmap_cnt, &handle->kmap_cnt);
526 buffer->vaddr = vaddr;
527 } else {
528 vaddr = buffer->vaddr;
529 }
Laura Abbott894fd582011-08-19 13:33:56 -0700530
531out:
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700532 mutex_unlock(&buffer->lock);
533 mutex_unlock(&client->lock);
534 return vaddr;
535}
536
Laura Abbott8c017362011-09-22 20:59:12 -0700537int __ion_iommu_map(struct ion_buffer *buffer,
538 int domain_num, int partition_num, unsigned long align,
539 unsigned long iova_length, unsigned long flags,
540 unsigned long *iova)
541{
542 struct ion_iommu_map *data;
543 int ret;
544
545 data = kmalloc(sizeof(*data), GFP_ATOMIC);
546
547 if (!data)
548 return -ENOMEM;
549
550 data->buffer = buffer;
551 iommu_map_domain(data) = domain_num;
552 iommu_map_partition(data) = partition_num;
553
554 ret = buffer->heap->ops->map_iommu(buffer, data,
555 domain_num,
556 partition_num,
557 align,
558 iova_length,
559 flags);
560
561 if (ret)
562 goto out;
563
564 kref_init(&data->ref);
565 *iova = data->iova_addr;
566
567 ion_iommu_add(buffer, data);
568
569 return 0;
570
571out:
572 msm_free_iova_address(data->iova_addr, domain_num, partition_num,
573 buffer->size);
574 kfree(data);
575 return ret;
576}
577
578int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
579 int domain_num, int partition_num, unsigned long align,
580 unsigned long iova_length, unsigned long *iova,
581 unsigned long *buffer_size,
582 unsigned long flags)
583{
584 struct ion_buffer *buffer;
585 struct ion_iommu_map *iommu_map;
586 int ret = 0;
587
588 mutex_lock(&client->lock);
589 if (!ion_handle_validate(client, handle)) {
590 pr_err("%s: invalid handle passed to map_kernel.\n",
591 __func__);
592 mutex_unlock(&client->lock);
593 return -EINVAL;
594 }
595
596 buffer = handle->buffer;
597 mutex_lock(&buffer->lock);
598
599 if (!handle->buffer->heap->ops->map_iommu) {
600 pr_err("%s: map_iommu is not implemented by this heap.\n",
601 __func__);
602 ret = -ENODEV;
603 goto out;
604 }
605
606 if (ion_validate_buffer_flags(buffer, flags)) {
607 ret = -EEXIST;
608 goto out;
609 }
610
611 /*
612 * If clients don't want a custom iova length, just use whatever
613 * the buffer size is
614 */
615 if (!iova_length)
616 iova_length = buffer->size;
617
618 if (buffer->size > iova_length) {
619 pr_debug("%s: iova length %lx is not at least buffer size"
620 " %x\n", __func__, iova_length, buffer->size);
621 ret = -EINVAL;
622 goto out;
623 }
624
625 if (buffer->size & ~PAGE_MASK) {
626 pr_debug("%s: buffer size %x is not aligned to %lx", __func__,
627 buffer->size, PAGE_SIZE);
628 ret = -EINVAL;
629 goto out;
630 }
631
632 if (iova_length & ~PAGE_MASK) {
633 pr_debug("%s: iova_length %lx is not aligned to %lx", __func__,
634 iova_length, PAGE_SIZE);
635 ret = -EINVAL;
636 goto out;
637 }
638
639 iommu_map = ion_iommu_lookup(buffer, domain_num, partition_num);
640 if (_ion_map(&buffer->iommu_map_cnt, &handle->iommu_map_cnt) ||
641 !iommu_map) {
642 ret = __ion_iommu_map(buffer, domain_num, partition_num, align,
643 iova_length, flags, iova);
644 if (ret < 0)
645 _ion_unmap(&buffer->iommu_map_cnt,
646 &handle->iommu_map_cnt);
647 } else {
648 if (iommu_map->mapped_size != iova_length) {
649 pr_err("%s: handle %p is already mapped with length"
650 " %x, trying to map with length %lx\n",
651 __func__, handle, iommu_map->mapped_size,
652 iova_length);
653 _ion_unmap(&buffer->iommu_map_cnt,
654 &handle->iommu_map_cnt);
655 ret = -EINVAL;
656 } else {
657 kref_get(&iommu_map->ref);
658 *iova = iommu_map->iova_addr;
659 }
660 }
661 *buffer_size = buffer->size;
662out:
663 mutex_unlock(&buffer->lock);
664 mutex_unlock(&client->lock);
665 return ret;
666}
667EXPORT_SYMBOL(ion_map_iommu);
668
669static void ion_iommu_release(struct kref *kref)
670{
671 struct ion_iommu_map *map = container_of(kref, struct ion_iommu_map,
672 ref);
673 struct ion_buffer *buffer = map->buffer;
674
675 rb_erase(&map->node, &buffer->iommu_maps);
676 buffer->heap->ops->unmap_iommu(map);
677 kfree(map);
678}
679
680void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
681 int domain_num, int partition_num)
682{
683 struct ion_iommu_map *iommu_map;
684 struct ion_buffer *buffer;
685
686 mutex_lock(&client->lock);
687 buffer = handle->buffer;
688
689 mutex_lock(&buffer->lock);
690
691 iommu_map = ion_iommu_lookup(buffer, domain_num, partition_num);
692
693 if (!iommu_map) {
694 WARN(1, "%s: (%d,%d) was never mapped for %p\n", __func__,
695 domain_num, partition_num, buffer);
696 goto out;
697 }
698
699 _ion_unmap(&buffer->iommu_map_cnt, &handle->iommu_map_cnt);
700 kref_put(&iommu_map->ref, ion_iommu_release);
701
702out:
703 mutex_unlock(&buffer->lock);
704
705 mutex_unlock(&client->lock);
706
707}
708EXPORT_SYMBOL(ion_unmap_iommu);
709
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700710struct scatterlist *ion_map_dma(struct ion_client *client,
Laura Abbott894fd582011-08-19 13:33:56 -0700711 struct ion_handle *handle,
712 unsigned long flags)
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700713{
714 struct ion_buffer *buffer;
715 struct scatterlist *sglist;
716
717 mutex_lock(&client->lock);
718 if (!ion_handle_validate(client, handle)) {
719 pr_err("%s: invalid handle passed to map_dma.\n",
720 __func__);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -0700721 mutex_unlock(&client->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700722 return ERR_PTR(-EINVAL);
723 }
724 buffer = handle->buffer;
725 mutex_lock(&buffer->lock);
726
727 if (!handle->buffer->heap->ops->map_dma) {
728 pr_err("%s: map_kernel is not implemented by this heap.\n",
729 __func__);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -0700730 mutex_unlock(&buffer->lock);
731 mutex_unlock(&client->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700732 return ERR_PTR(-ENODEV);
733 }
Laura Abbott894fd582011-08-19 13:33:56 -0700734
Laura Abbott8c017362011-09-22 20:59:12 -0700735 if (ion_validate_buffer_flags(buffer, flags)) {
736 sglist = ERR_PTR(-EEXIST);
737 goto out;
Laura Abbott894fd582011-08-19 13:33:56 -0700738 }
739
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700740 if (_ion_map(&buffer->dmap_cnt, &handle->dmap_cnt)) {
741 sglist = buffer->heap->ops->map_dma(buffer->heap, buffer);
742 if (IS_ERR_OR_NULL(sglist))
743 _ion_unmap(&buffer->dmap_cnt, &handle->dmap_cnt);
744 buffer->sglist = sglist;
745 } else {
746 sglist = buffer->sglist;
747 }
Laura Abbott894fd582011-08-19 13:33:56 -0700748
749out:
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700750 mutex_unlock(&buffer->lock);
751 mutex_unlock(&client->lock);
752 return sglist;
753}
754
755void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle)
756{
757 struct ion_buffer *buffer;
758
759 mutex_lock(&client->lock);
760 buffer = handle->buffer;
761 mutex_lock(&buffer->lock);
762 if (_ion_unmap(&buffer->kmap_cnt, &handle->kmap_cnt)) {
763 buffer->heap->ops->unmap_kernel(buffer->heap, buffer);
764 buffer->vaddr = NULL;
765 }
766 mutex_unlock(&buffer->lock);
767 mutex_unlock(&client->lock);
768}
769
770void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle)
771{
772 struct ion_buffer *buffer;
773
774 mutex_lock(&client->lock);
775 buffer = handle->buffer;
776 mutex_lock(&buffer->lock);
777 if (_ion_unmap(&buffer->dmap_cnt, &handle->dmap_cnt)) {
778 buffer->heap->ops->unmap_dma(buffer->heap, buffer);
779 buffer->sglist = NULL;
780 }
781 mutex_unlock(&buffer->lock);
782 mutex_unlock(&client->lock);
783}
784
785
786struct ion_buffer *ion_share(struct ion_client *client,
787 struct ion_handle *handle)
788{
Rebecca Schultz Zavinc72866d2011-07-07 17:07:56 -0700789 bool valid_handle;
790
791 mutex_lock(&client->lock);
792 valid_handle = ion_handle_validate(client, handle);
793 mutex_unlock(&client->lock);
794 if (!valid_handle) {
795 WARN("%s: invalid handle passed to share.\n", __func__);
796 return ERR_PTR(-EINVAL);
797 }
798
Iliyan Malchev3fe24362011-08-09 14:42:08 -0700799 /* do not take an extra reference here, the burden is on the caller
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700800 * to make sure the buffer doesn't go away while it's passing it
801 * to another client -- ion_free should not be called on this handle
802 * until the buffer has been imported into the other client
803 */
804 return handle->buffer;
805}
806
807struct ion_handle *ion_import(struct ion_client *client,
808 struct ion_buffer *buffer)
809{
810 struct ion_handle *handle = NULL;
811
812 mutex_lock(&client->lock);
813 /* if a handle exists for this buffer just take a reference to it */
814 handle = ion_handle_lookup(client, buffer);
815 if (!IS_ERR_OR_NULL(handle)) {
816 ion_handle_get(handle);
817 goto end;
818 }
819 handle = ion_handle_create(client, buffer);
820 if (IS_ERR_OR_NULL(handle))
821 goto end;
822 ion_handle_add(client, handle);
823end:
824 mutex_unlock(&client->lock);
825 return handle;
826}
827
Laura Abbottabcb6f72011-10-04 16:26:49 -0700828static int check_vaddr_bounds(unsigned long start, unsigned long end)
829{
830 struct mm_struct *mm = current->active_mm;
831 struct vm_area_struct *vma;
832 int ret = 1;
833
834 if (end < start)
835 goto out;
836
837 down_read(&mm->mmap_sem);
838 vma = find_vma(mm, start);
839 if (vma && vma->vm_start < end) {
840 if (start < vma->vm_start)
841 goto out_up;
842 if (end > vma->vm_end)
843 goto out_up;
844 ret = 0;
845 }
846
847out_up:
848 up_read(&mm->mmap_sem);
849out:
850 return ret;
851}
852
853int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
854 void *uaddr, unsigned long offset, unsigned long len,
855 unsigned int cmd)
856{
857 struct ion_buffer *buffer;
Laura Abbottabcb6f72011-10-04 16:26:49 -0700858 int ret = -EINVAL;
859
860 mutex_lock(&client->lock);
861 if (!ion_handle_validate(client, handle)) {
862 pr_err("%s: invalid handle passed to do_cache_op.\n",
863 __func__);
864 mutex_unlock(&client->lock);
865 return -EINVAL;
866 }
867 buffer = handle->buffer;
868 mutex_lock(&buffer->lock);
869
Laura Abbottcbaa6682011-10-19 12:14:14 -0700870 if (!ION_IS_CACHED(buffer->flags)) {
Laura Abbottabcb6f72011-10-04 16:26:49 -0700871 ret = 0;
872 goto out;
873 }
874
875 if (!handle->buffer->heap->ops->cache_op) {
876 pr_err("%s: cache_op is not implemented by this heap.\n",
877 __func__);
878 ret = -ENODEV;
879 goto out;
880 }
881
Laura Abbottabcb6f72011-10-04 16:26:49 -0700882
883 ret = buffer->heap->ops->cache_op(buffer->heap, buffer, uaddr,
884 offset, len, cmd);
885
886out:
887 mutex_unlock(&buffer->lock);
888 mutex_unlock(&client->lock);
889 return ret;
890
891}
892
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700893static const struct file_operations ion_share_fops;
894
895struct ion_handle *ion_import_fd(struct ion_client *client, int fd)
896{
897 struct file *file = fget(fd);
898 struct ion_handle *handle;
899
900 if (!file) {
901 pr_err("%s: imported fd not found in file table.\n", __func__);
902 return ERR_PTR(-EINVAL);
903 }
904 if (file->f_op != &ion_share_fops) {
Laura Abbott084d6eb2011-10-24 19:09:50 -0700905 pr_err("%s: imported file %s is not a shared ion"
906 " file.", __func__, file->f_dentry->d_name.name);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700907 handle = ERR_PTR(-EINVAL);
908 goto end;
909 }
910 handle = ion_import(client, file->private_data);
911end:
912 fput(file);
913 return handle;
914}
915
916static int ion_debug_client_show(struct seq_file *s, void *unused)
917{
918 struct ion_client *client = s->private;
919 struct rb_node *n;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700920
Laura Abbott68c80642011-10-21 17:32:27 -0700921 seq_printf(s, "%16.16s: %16.16s : %16.16s : %16.16s\n", "heap_name",
922 "size_in_bytes", "handle refcount", "buffer");
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700923 mutex_lock(&client->lock);
924 for (n = rb_first(&client->handles); n; n = rb_next(n)) {
925 struct ion_handle *handle = rb_entry(n, struct ion_handle,
926 node);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700927
Laura Abbott8747bbe2011-10-31 14:18:13 -0700928 seq_printf(s, "%16.16s: %16x : %16d : %16p\n",
Laura Abbott68c80642011-10-21 17:32:27 -0700929 handle->buffer->heap->name,
930 handle->buffer->size,
931 atomic_read(&handle->ref.refcount),
932 handle->buffer);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700933 }
Laura Abbott68c80642011-10-21 17:32:27 -0700934
935 seq_printf(s, "%16.16s %d\n", "client refcount:",
936 atomic_read(&client->ref.refcount));
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700937 mutex_unlock(&client->lock);
938
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700939 return 0;
940}
941
942static int ion_debug_client_open(struct inode *inode, struct file *file)
943{
944 return single_open(file, ion_debug_client_show, inode->i_private);
945}
946
947static const struct file_operations debug_client_fops = {
948 .open = ion_debug_client_open,
949 .read = seq_read,
950 .llseek = seq_lseek,
951 .release = single_release,
952};
953
Rebecca Schultz Zavin83e3dab2011-07-01 20:41:25 -0700954static struct ion_client *ion_client_lookup(struct ion_device *dev,
955 struct task_struct *task)
956{
957 struct rb_node *n = dev->user_clients.rb_node;
958 struct ion_client *client;
959
960 mutex_lock(&dev->lock);
961 while (n) {
962 client = rb_entry(n, struct ion_client, node);
963 if (task == client->task) {
964 ion_client_get(client);
965 mutex_unlock(&dev->lock);
966 return client;
967 } else if (task < client->task) {
968 n = n->rb_left;
969 } else if (task > client->task) {
970 n = n->rb_right;
971 }
972 }
973 mutex_unlock(&dev->lock);
974 return NULL;
975}
976
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700977struct ion_client *ion_client_create(struct ion_device *dev,
978 unsigned int heap_mask,
979 const char *name)
980{
981 struct ion_client *client;
982 struct task_struct *task;
983 struct rb_node **p;
984 struct rb_node *parent = NULL;
985 struct ion_client *entry;
Rebecca Schultz Zavin83e3dab2011-07-01 20:41:25 -0700986 pid_t pid;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700987
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700988 get_task_struct(current->group_leader);
989 task_lock(current->group_leader);
Rebecca Schultz Zavin83e3dab2011-07-01 20:41:25 -0700990 pid = task_pid_nr(current->group_leader);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -0700991 /* don't bother to store task struct for kernel threads,
992 they can't be killed anyway */
993 if (current->group_leader->flags & PF_KTHREAD) {
994 put_task_struct(current->group_leader);
995 task = NULL;
996 } else {
997 task = current->group_leader;
998 }
999 task_unlock(current->group_leader);
Rebecca Schultz Zavin83e3dab2011-07-01 20:41:25 -07001000
1001 /* if this isn't a kernel thread, see if a client already
1002 exists */
1003 if (task) {
1004 client = ion_client_lookup(dev, task);
1005 if (!IS_ERR_OR_NULL(client)) {
1006 put_task_struct(current->group_leader);
1007 return client;
1008 }
1009 }
1010
1011 client = kzalloc(sizeof(struct ion_client), GFP_KERNEL);
1012 if (!client) {
1013 put_task_struct(current->group_leader);
1014 return ERR_PTR(-ENOMEM);
1015 }
1016
1017 client->dev = dev;
1018 client->handles = RB_ROOT;
1019 mutex_init(&client->lock);
1020 client->name = name;
1021 client->heap_mask = heap_mask;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001022 client->task = task;
Rebecca Schultz Zavin83e3dab2011-07-01 20:41:25 -07001023 client->pid = pid;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001024 kref_init(&client->ref);
1025
1026 mutex_lock(&dev->lock);
1027 if (task) {
1028 p = &dev->user_clients.rb_node;
1029 while (*p) {
1030 parent = *p;
1031 entry = rb_entry(parent, struct ion_client, node);
1032
1033 if (task < entry->task)
1034 p = &(*p)->rb_left;
1035 else if (task > entry->task)
1036 p = &(*p)->rb_right;
1037 }
1038 rb_link_node(&client->node, parent, p);
1039 rb_insert_color(&client->node, &dev->user_clients);
1040 } else {
1041 p = &dev->kernel_clients.rb_node;
1042 while (*p) {
1043 parent = *p;
1044 entry = rb_entry(parent, struct ion_client, node);
1045
1046 if (client < entry)
1047 p = &(*p)->rb_left;
1048 else if (client > entry)
1049 p = &(*p)->rb_right;
1050 }
1051 rb_link_node(&client->node, parent, p);
1052 rb_insert_color(&client->node, &dev->kernel_clients);
1053 }
1054
Laura Abbotteed86032011-12-05 15:32:36 -08001055
1056 client->debug_root = debugfs_create_file(name, 0664,
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001057 dev->debug_root, client,
1058 &debug_client_fops);
1059 mutex_unlock(&dev->lock);
1060
1061 return client;
1062}
1063
Rebecca Schultz Zavin0b7e8ae2011-07-06 18:07:01 -07001064static void _ion_client_destroy(struct kref *kref)
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001065{
Rebecca Schultz Zavin0b7e8ae2011-07-06 18:07:01 -07001066 struct ion_client *client = container_of(kref, struct ion_client, ref);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001067 struct ion_device *dev = client->dev;
1068 struct rb_node *n;
1069
1070 pr_debug("%s: %d\n", __func__, __LINE__);
1071 while ((n = rb_first(&client->handles))) {
1072 struct ion_handle *handle = rb_entry(n, struct ion_handle,
1073 node);
1074 ion_handle_destroy(&handle->ref);
1075 }
1076 mutex_lock(&dev->lock);
1077 if (client->task) {
1078 rb_erase(&client->node, &dev->user_clients);
1079 put_task_struct(client->task);
1080 } else {
1081 rb_erase(&client->node, &dev->kernel_clients);
1082 }
1083 debugfs_remove_recursive(client->debug_root);
1084 mutex_unlock(&dev->lock);
1085
1086 kfree(client);
1087}
1088
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001089static void ion_client_get(struct ion_client *client)
1090{
1091 kref_get(&client->ref);
1092}
1093
1094static int ion_client_put(struct ion_client *client)
1095{
1096 return kref_put(&client->ref, _ion_client_destroy);
1097}
1098
Rebecca Schultz Zavin0b7e8ae2011-07-06 18:07:01 -07001099void ion_client_destroy(struct ion_client *client)
1100{
Jordan Crousea75022c2011-10-12 16:57:47 -06001101 if (client)
1102 ion_client_put(client);
Rebecca Schultz Zavin0b7e8ae2011-07-06 18:07:01 -07001103}
1104
Laura Abbott273dd8e2011-10-12 14:26:33 -07001105int ion_handle_get_flags(struct ion_client *client, struct ion_handle *handle,
1106 unsigned long *flags)
1107{
1108 struct ion_buffer *buffer;
1109
1110 mutex_lock(&client->lock);
1111 if (!ion_handle_validate(client, handle)) {
1112 pr_err("%s: invalid handle passed to %s.\n",
1113 __func__, __func__);
1114 mutex_unlock(&client->lock);
1115 return -EINVAL;
1116 }
1117 buffer = handle->buffer;
1118 mutex_lock(&buffer->lock);
1119 *flags = buffer->flags;
1120 mutex_unlock(&buffer->lock);
1121 mutex_unlock(&client->lock);
1122
1123 return 0;
1124}
1125EXPORT_SYMBOL(ion_handle_get_flags);
1126
Laura Abbott8c017362011-09-22 20:59:12 -07001127int ion_handle_get_size(struct ion_client *client, struct ion_handle *handle,
1128 unsigned long *size)
1129{
1130 struct ion_buffer *buffer;
1131
1132 mutex_lock(&client->lock);
1133 if (!ion_handle_validate(client, handle)) {
1134 pr_err("%s: invalid handle passed to %s.\n",
1135 __func__, __func__);
1136 mutex_unlock(&client->lock);
1137 return -EINVAL;
1138 }
1139 buffer = handle->buffer;
1140 mutex_lock(&buffer->lock);
1141 *size = buffer->size;
1142 mutex_unlock(&buffer->lock);
1143 mutex_unlock(&client->lock);
1144
1145 return 0;
1146}
1147EXPORT_SYMBOL(ion_handle_get_size);
1148
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001149static int ion_share_release(struct inode *inode, struct file* file)
1150{
1151 struct ion_buffer *buffer = file->private_data;
1152
1153 pr_debug("%s: %d\n", __func__, __LINE__);
1154 /* drop the reference to the buffer -- this prevents the
1155 buffer from going away because the client holding it exited
1156 while it was being passed */
1157 ion_buffer_put(buffer);
1158 return 0;
1159}
1160
1161static void ion_vma_open(struct vm_area_struct *vma)
1162{
1163
1164 struct ion_buffer *buffer = vma->vm_file->private_data;
1165 struct ion_handle *handle = vma->vm_private_data;
1166 struct ion_client *client;
1167
1168 pr_debug("%s: %d\n", __func__, __LINE__);
1169 /* check that the client still exists and take a reference so
1170 it can't go away until this vma is closed */
1171 client = ion_client_lookup(buffer->dev, current->group_leader);
1172 if (IS_ERR_OR_NULL(client)) {
1173 vma->vm_private_data = NULL;
1174 return;
1175 }
Laura Abbott0f2175b2011-12-09 14:26:07 -08001176 ion_handle_get(handle);
Laura Abbott77168502011-12-05 11:06:24 -08001177 mutex_lock(&buffer->lock);
1178 buffer->umap_cnt++;
1179 mutex_unlock(&buffer->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001180 pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
1181 __func__, __LINE__,
1182 atomic_read(&client->ref.refcount),
1183 atomic_read(&handle->ref.refcount),
1184 atomic_read(&buffer->ref.refcount));
1185}
1186
1187static void ion_vma_close(struct vm_area_struct *vma)
1188{
1189 struct ion_handle *handle = vma->vm_private_data;
1190 struct ion_buffer *buffer = vma->vm_file->private_data;
1191 struct ion_client *client;
1192
1193 pr_debug("%s: %d\n", __func__, __LINE__);
1194 /* this indicates the client is gone, nothing to do here */
1195 if (!handle)
1196 return;
1197 client = handle->client;
Laura Abbott77168502011-12-05 11:06:24 -08001198 mutex_lock(&buffer->lock);
1199 buffer->umap_cnt--;
1200 mutex_unlock(&buffer->lock);
Laura Abbotta6835092011-11-14 15:27:02 -08001201
1202 if (buffer->heap->ops->unmap_user)
1203 buffer->heap->ops->unmap_user(buffer->heap, buffer);
1204
1205
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001206 pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
1207 __func__, __LINE__,
1208 atomic_read(&client->ref.refcount),
1209 atomic_read(&handle->ref.refcount),
1210 atomic_read(&buffer->ref.refcount));
1211 ion_handle_put(handle);
1212 ion_client_put(client);
1213 pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
1214 __func__, __LINE__,
1215 atomic_read(&client->ref.refcount),
1216 atomic_read(&handle->ref.refcount),
1217 atomic_read(&buffer->ref.refcount));
1218}
1219
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001220static struct vm_operations_struct ion_vm_ops = {
1221 .open = ion_vma_open,
1222 .close = ion_vma_close,
1223};
1224
1225static int ion_share_mmap(struct file *file, struct vm_area_struct *vma)
1226{
1227 struct ion_buffer *buffer = file->private_data;
1228 unsigned long size = vma->vm_end - vma->vm_start;
1229 struct ion_client *client;
1230 struct ion_handle *handle;
1231 int ret;
Laura Abbott894fd582011-08-19 13:33:56 -07001232 unsigned long flags = file->f_flags & O_DSYNC ?
1233 ION_SET_CACHE(UNCACHED) :
1234 ION_SET_CACHE(CACHED);
1235
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001236
1237 pr_debug("%s: %d\n", __func__, __LINE__);
1238 /* make sure the client still exists, it's possible for the client to
1239 have gone away but the map/share fd still to be around, take
1240 a reference to it so it can't go away while this mapping exists */
1241 client = ion_client_lookup(buffer->dev, current->group_leader);
1242 if (IS_ERR_OR_NULL(client)) {
1243 pr_err("%s: trying to mmap an ion handle in a process with no "
1244 "ion client\n", __func__);
1245 return -EINVAL;
1246 }
1247
1248 if ((size > buffer->size) || (size + (vma->vm_pgoff << PAGE_SHIFT) >
1249 buffer->size)) {
1250 pr_err("%s: trying to map larger area than handle has available"
1251 "\n", __func__);
1252 ret = -EINVAL;
1253 goto err;
1254 }
1255
1256 /* find the handle and take a reference to it */
1257 handle = ion_import(client, buffer);
1258 if (IS_ERR_OR_NULL(handle)) {
1259 ret = -EINVAL;
1260 goto err;
1261 }
1262
1263 if (!handle->buffer->heap->ops->map_user) {
1264 pr_err("%s: this heap does not define a method for mapping "
1265 "to userspace\n", __func__);
1266 ret = -EINVAL;
1267 goto err1;
1268 }
1269
1270 mutex_lock(&buffer->lock);
Laura Abbott894fd582011-08-19 13:33:56 -07001271
Laura Abbott8c017362011-09-22 20:59:12 -07001272 if (ion_validate_buffer_flags(buffer, flags)) {
1273 ret = -EEXIST;
1274 mutex_unlock(&buffer->lock);
1275 goto err1;
Laura Abbott894fd582011-08-19 13:33:56 -07001276 }
Laura Abbott8c017362011-09-22 20:59:12 -07001277
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001278 /* now map it to userspace */
Laura Abbott894fd582011-08-19 13:33:56 -07001279 ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma,
1280 flags);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -07001281 mutex_unlock(&buffer->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001282 if (ret) {
1283 pr_err("%s: failure mapping buffer to userspace\n",
1284 __func__);
Laura Abbott894fd582011-08-19 13:33:56 -07001285 goto err2;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001286 }
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001287
1288 vma->vm_ops = &ion_vm_ops;
1289 /* move the handle into the vm_private_data so we can access it from
1290 vma_open/close */
1291 vma->vm_private_data = handle;
1292 pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
1293 __func__, __LINE__,
1294 atomic_read(&client->ref.refcount),
1295 atomic_read(&handle->ref.refcount),
1296 atomic_read(&buffer->ref.refcount));
1297 return 0;
1298
Laura Abbott894fd582011-08-19 13:33:56 -07001299err2:
1300 buffer->umap_cnt--;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001301 /* drop the reference to the handle */
Laura Abbott894fd582011-08-19 13:33:56 -07001302err1:
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001303 ion_handle_put(handle);
1304err:
Iliyan Malchev3fe24362011-08-09 14:42:08 -07001305 /* drop the reference to the client */
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001306 ion_client_put(client);
1307 return ret;
1308}
1309
1310static const struct file_operations ion_share_fops = {
1311 .owner = THIS_MODULE,
1312 .release = ion_share_release,
1313 .mmap = ion_share_mmap,
1314};
1315
1316static int ion_ioctl_share(struct file *parent, struct ion_client *client,
1317 struct ion_handle *handle)
1318{
1319 int fd = get_unused_fd();
1320 struct file *file;
1321
1322 if (fd < 0)
1323 return -ENFILE;
1324
1325 file = anon_inode_getfile("ion_share_fd", &ion_share_fops,
1326 handle->buffer, O_RDWR);
1327 if (IS_ERR_OR_NULL(file))
1328 goto err;
Laura Abbott4b5d0482011-09-27 18:35:14 -07001329
1330 if (parent->f_flags & O_DSYNC)
1331 file->f_flags |= O_DSYNC;
1332
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001333 ion_buffer_get(handle->buffer);
1334 fd_install(fd, file);
1335
1336 return fd;
1337
1338err:
1339 put_unused_fd(fd);
1340 return -ENFILE;
1341}
1342
1343static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1344{
1345 struct ion_client *client = filp->private_data;
1346
1347 switch (cmd) {
1348 case ION_IOC_ALLOC:
1349 {
1350 struct ion_allocation_data data;
1351
1352 if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
1353 return -EFAULT;
1354 data.handle = ion_alloc(client, data.len, data.align,
1355 data.flags);
Laura Abbotte1b9ce52011-11-11 18:31:39 -08001356
1357 if (IS_ERR_OR_NULL(data.handle))
Olav Hauganb06ee072011-12-13 15:31:41 -08001358 return -ENOMEM;
Laura Abbotte1b9ce52011-11-11 18:31:39 -08001359
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001360 if (copy_to_user((void __user *)arg, &data, sizeof(data)))
1361 return -EFAULT;
1362 break;
1363 }
1364 case ION_IOC_FREE:
1365 {
1366 struct ion_handle_data data;
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -07001367 bool valid;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001368
1369 if (copy_from_user(&data, (void __user *)arg,
1370 sizeof(struct ion_handle_data)))
1371 return -EFAULT;
1372 mutex_lock(&client->lock);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -07001373 valid = ion_handle_validate(client, data.handle);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001374 mutex_unlock(&client->lock);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -07001375 if (!valid)
1376 return -EINVAL;
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001377 ion_free(client, data.handle);
1378 break;
1379 }
1380 case ION_IOC_MAP:
1381 case ION_IOC_SHARE:
1382 {
1383 struct ion_fd_data data;
1384
1385 if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
1386 return -EFAULT;
1387 mutex_lock(&client->lock);
1388 if (!ion_handle_validate(client, data.handle)) {
1389 pr_err("%s: invalid handle passed to share ioctl.\n",
1390 __func__);
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -07001391 mutex_unlock(&client->lock);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001392 return -EINVAL;
1393 }
1394 data.fd = ion_ioctl_share(filp, client, data.handle);
1395 mutex_unlock(&client->lock);
1396 if (copy_to_user((void __user *)arg, &data, sizeof(data)))
1397 return -EFAULT;
1398 break;
1399 }
1400 case ION_IOC_IMPORT:
1401 {
1402 struct ion_fd_data data;
1403 if (copy_from_user(&data, (void __user *)arg,
1404 sizeof(struct ion_fd_data)))
1405 return -EFAULT;
1406
1407 data.handle = ion_import_fd(client, data.fd);
1408 if (IS_ERR(data.handle))
1409 data.handle = NULL;
1410 if (copy_to_user((void __user *)arg, &data,
1411 sizeof(struct ion_fd_data)))
1412 return -EFAULT;
1413 break;
1414 }
1415 case ION_IOC_CUSTOM:
1416 {
1417 struct ion_device *dev = client->dev;
1418 struct ion_custom_data data;
1419
1420 if (!dev->custom_ioctl)
1421 return -ENOTTY;
1422 if (copy_from_user(&data, (void __user *)arg,
1423 sizeof(struct ion_custom_data)))
1424 return -EFAULT;
1425 return dev->custom_ioctl(client, data.cmd, data.arg);
1426 }
Laura Abbottabcb6f72011-10-04 16:26:49 -07001427 case ION_IOC_CLEAN_CACHES:
1428 case ION_IOC_INV_CACHES:
1429 case ION_IOC_CLEAN_INV_CACHES:
1430 {
1431 struct ion_flush_data data;
Laura Abbott9fa29e82011-11-14 09:42:53 -08001432 unsigned long start, end;
Laura Abbotte80ea012011-11-18 18:36:47 -08001433 struct ion_handle *handle = NULL;
1434 int ret;
Laura Abbottabcb6f72011-10-04 16:26:49 -07001435
1436 if (copy_from_user(&data, (void __user *)arg,
1437 sizeof(struct ion_flush_data)))
1438 return -EFAULT;
1439
Laura Abbott9fa29e82011-11-14 09:42:53 -08001440 start = (unsigned long) data.vaddr;
1441 end = (unsigned long) data.vaddr + data.length;
1442
1443 if (check_vaddr_bounds(start, end)) {
1444 pr_err("%s: virtual address %p is out of bounds\n",
1445 __func__, data.vaddr);
1446 return -EINVAL;
1447 }
1448
Laura Abbotte80ea012011-11-18 18:36:47 -08001449 if (!data.handle) {
1450 handle = ion_import_fd(client, data.fd);
1451 if (IS_ERR_OR_NULL(handle)) {
1452 pr_info("%s: Could not import handle: %d\n",
1453 __func__, (int)handle);
1454 return -EINVAL;
1455 }
1456 }
1457
1458 ret = ion_do_cache_op(client,
1459 data.handle ? data.handle : handle,
1460 data.vaddr, data.offset, data.length,
1461 cmd);
1462
1463 if (!data.handle)
1464 ion_free(client, handle);
1465
1466 break;
Laura Abbottabcb6f72011-10-04 16:26:49 -07001467
1468 }
Laura Abbott273dd8e2011-10-12 14:26:33 -07001469 case ION_IOC_GET_FLAGS:
1470 {
1471 struct ion_flag_data data;
1472 int ret;
1473 if (copy_from_user(&data, (void __user *)arg,
1474 sizeof(struct ion_flag_data)))
1475 return -EFAULT;
1476
1477 ret = ion_handle_get_flags(client, data.handle, &data.flags);
1478 if (ret < 0)
1479 return ret;
1480 if (copy_to_user((void __user *)arg, &data,
1481 sizeof(struct ion_flag_data)))
1482 return -EFAULT;
1483 break;
1484 }
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001485 default:
1486 return -ENOTTY;
1487 }
1488 return 0;
1489}
1490
1491static int ion_release(struct inode *inode, struct file *file)
1492{
1493 struct ion_client *client = file->private_data;
1494
1495 pr_debug("%s: %d\n", __func__, __LINE__);
1496 ion_client_put(client);
1497 return 0;
1498}
1499
1500static int ion_open(struct inode *inode, struct file *file)
1501{
1502 struct miscdevice *miscdev = file->private_data;
1503 struct ion_device *dev = container_of(miscdev, struct ion_device, dev);
1504 struct ion_client *client;
Laura Abbotteed86032011-12-05 15:32:36 -08001505 char debug_name[64];
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001506
1507 pr_debug("%s: %d\n", __func__, __LINE__);
Laura Abbotteed86032011-12-05 15:32:36 -08001508 snprintf(debug_name, 64, "%u", task_pid_nr(current->group_leader));
1509 client = ion_client_create(dev, -1, debug_name);
Rebecca Schultz Zavin6d3b9582011-07-06 18:07:24 -07001510 if (IS_ERR_OR_NULL(client))
1511 return PTR_ERR(client);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001512 file->private_data = client;
1513
1514 return 0;
1515}
1516
1517static const struct file_operations ion_fops = {
1518 .owner = THIS_MODULE,
1519 .open = ion_open,
1520 .release = ion_release,
1521 .unlocked_ioctl = ion_ioctl,
1522};
1523
1524static size_t ion_debug_heap_total(struct ion_client *client,
Laura Abbott3647ac32011-10-31 14:09:53 -07001525 enum ion_heap_ids id)
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001526{
1527 size_t size = 0;
1528 struct rb_node *n;
1529
1530 mutex_lock(&client->lock);
1531 for (n = rb_first(&client->handles); n; n = rb_next(n)) {
1532 struct ion_handle *handle = rb_entry(n,
1533 struct ion_handle,
1534 node);
Laura Abbott3647ac32011-10-31 14:09:53 -07001535 if (handle->buffer->heap->id == id)
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001536 size += handle->buffer->size;
1537 }
1538 mutex_unlock(&client->lock);
1539 return size;
1540}
1541
1542static int ion_debug_heap_show(struct seq_file *s, void *unused)
1543{
1544 struct ion_heap *heap = s->private;
1545 struct ion_device *dev = heap->dev;
1546 struct rb_node *n;
1547
1548 seq_printf(s, "%16.s %16.s %16.s\n", "client", "pid", "size");
1549 for (n = rb_first(&dev->user_clients); n; n = rb_next(n)) {
1550 struct ion_client *client = rb_entry(n, struct ion_client,
1551 node);
1552 char task_comm[TASK_COMM_LEN];
Laura Abbott3647ac32011-10-31 14:09:53 -07001553 size_t size = ion_debug_heap_total(client, heap->id);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001554 if (!size)
1555 continue;
1556
1557 get_task_comm(task_comm, client->task);
Laura Abbott8747bbe2011-10-31 14:18:13 -07001558 seq_printf(s, "%16.s %16u %16x\n", task_comm, client->pid,
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001559 size);
1560 }
1561
1562 for (n = rb_first(&dev->kernel_clients); n; n = rb_next(n)) {
1563 struct ion_client *client = rb_entry(n, struct ion_client,
1564 node);
Laura Abbott3647ac32011-10-31 14:09:53 -07001565 size_t size = ion_debug_heap_total(client, heap->id);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001566 if (!size)
1567 continue;
Laura Abbott8747bbe2011-10-31 14:18:13 -07001568 seq_printf(s, "%16.s %16u %16x\n", client->name, client->pid,
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001569 size);
1570 }
Laura Abbott68c80642011-10-21 17:32:27 -07001571 if (heap->ops->get_allocated) {
1572 seq_printf(s, "total bytes currently allocated: %lx\n",
1573 heap->ops->get_allocated(heap));
1574 }
1575 if (heap->ops->get_total) {
1576 seq_printf(s, "total heap size: %lx\n",
1577 heap->ops->get_total(heap));
1578 }
Olav Haugane1f5d832011-12-13 15:16:28 -08001579 if (heap->ops->get_alloc_cnt) {
1580 seq_printf(s, "allocation count: %lx\n",
1581 heap->ops->get_alloc_cnt(heap));
1582 }
1583 if (heap->ops->get_umap_cnt) {
1584 seq_printf(s, "umapping count: %lx\n",
1585 heap->ops->get_umap_cnt(heap));
1586 }
1587 if (heap->ops->get_kmap_cnt) {
1588 seq_printf(s, "kmapping count: %lx\n",
1589 heap->ops->get_kmap_cnt(heap));
1590 }
1591 if (heap->ops->get_secured) {
1592 seq_printf(s, "secured heap: %s\n",
1593 heap->ops->get_secured(heap) ? "Yes" : "No");
1594 }
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001595 return 0;
1596}
1597
1598static int ion_debug_heap_open(struct inode *inode, struct file *file)
1599{
1600 return single_open(file, ion_debug_heap_show, inode->i_private);
1601}
1602
1603static const struct file_operations debug_heap_fops = {
1604 .open = ion_debug_heap_open,
1605 .read = seq_read,
1606 .llseek = seq_lseek,
1607 .release = single_release,
1608};
1609
1610void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
1611{
1612 struct rb_node **p = &dev->heaps.rb_node;
1613 struct rb_node *parent = NULL;
1614 struct ion_heap *entry;
1615
1616 heap->dev = dev;
1617 mutex_lock(&dev->lock);
1618 while (*p) {
1619 parent = *p;
1620 entry = rb_entry(parent, struct ion_heap, node);
1621
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -07001622 if (heap->id < entry->id) {
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001623 p = &(*p)->rb_left;
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -07001624 } else if (heap->id > entry->id ) {
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001625 p = &(*p)->rb_right;
1626 } else {
1627 pr_err("%s: can not insert multiple heaps with "
Rebecca Schultz Zavine6ee1242011-06-30 12:19:55 -07001628 "id %d\n", __func__, heap->id);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001629 goto end;
1630 }
1631 }
1632
1633 rb_link_node(&heap->node, parent, p);
1634 rb_insert_color(&heap->node, &dev->heaps);
1635 debugfs_create_file(heap->name, 0664, dev->debug_root, heap,
1636 &debug_heap_fops);
1637end:
1638 mutex_unlock(&dev->lock);
1639}
1640
Olav Haugan0a852512012-01-09 10:20:55 -08001641int ion_secure_heap(struct ion_device *dev, int heap_id)
1642{
1643 struct rb_node *n;
1644 int ret_val = 0;
1645
1646 /*
1647 * traverse the list of heaps available in this system
1648 * and find the heap that is specified.
1649 */
1650 mutex_lock(&dev->lock);
1651 for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) {
1652 struct ion_heap *heap = rb_entry(n, struct ion_heap, node);
1653 if (heap->type != ION_HEAP_TYPE_CP)
1654 continue;
1655 if (ION_HEAP(heap->id) != heap_id)
1656 continue;
1657 if (heap->ops->secure_heap)
1658 ret_val = heap->ops->secure_heap(heap);
1659 else
1660 ret_val = -EINVAL;
1661 break;
1662 }
1663 mutex_unlock(&dev->lock);
1664 return ret_val;
1665}
1666EXPORT_SYMBOL(ion_secure_heap);
1667
1668int ion_unsecure_heap(struct ion_device *dev, int heap_id)
1669{
1670 struct rb_node *n;
1671 int ret_val = 0;
1672
1673 /*
1674 * traverse the list of heaps available in this system
1675 * and find the heap that is specified.
1676 */
1677 mutex_lock(&dev->lock);
1678 for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) {
1679 struct ion_heap *heap = rb_entry(n, struct ion_heap, node);
1680 if (heap->type != ION_HEAP_TYPE_CP)
1681 continue;
1682 if (ION_HEAP(heap->id) != heap_id)
1683 continue;
1684 if (heap->ops->secure_heap)
1685 ret_val = heap->ops->unsecure_heap(heap);
1686 else
1687 ret_val = -EINVAL;
1688 break;
1689 }
1690 mutex_unlock(&dev->lock);
1691 return ret_val;
1692}
1693EXPORT_SYMBOL(ion_unsecure_heap);
1694
Laura Abbott404f8242011-10-31 14:22:53 -07001695static int ion_debug_leak_show(struct seq_file *s, void *unused)
1696{
1697 struct ion_device *dev = s->private;
1698 struct rb_node *n;
1699 struct rb_node *n2;
1700
1701 /* mark all buffers as 1 */
1702 seq_printf(s, "%16.s %16.s %16.s %16.s\n", "buffer", "heap", "size",
1703 "ref cnt");
1704 mutex_lock(&dev->lock);
1705 for (n = rb_first(&dev->buffers); n; n = rb_next(n)) {
1706 struct ion_buffer *buf = rb_entry(n, struct ion_buffer,
1707 node);
1708
1709 buf->marked = 1;
1710 }
1711
1712 /* now see which buffers we can access */
1713 for (n = rb_first(&dev->kernel_clients); n; n = rb_next(n)) {
1714 struct ion_client *client = rb_entry(n, struct ion_client,
1715 node);
1716
1717 mutex_lock(&client->lock);
1718 for (n2 = rb_first(&client->handles); n2; n2 = rb_next(n2)) {
1719 struct ion_handle *handle = rb_entry(n2,
1720 struct ion_handle, node);
1721
1722 handle->buffer->marked = 0;
1723
1724 }
1725 mutex_unlock(&client->lock);
1726
1727 }
1728
1729 for (n = rb_first(&dev->user_clients); n; n = rb_next(n)) {
1730 struct ion_client *client = rb_entry(n, struct ion_client,
1731 node);
1732
1733 mutex_lock(&client->lock);
1734 for (n2 = rb_first(&client->handles); n2; n2 = rb_next(n2)) {
1735 struct ion_handle *handle = rb_entry(n2,
1736 struct ion_handle, node);
1737
1738 handle->buffer->marked = 0;
1739
1740 }
1741 mutex_unlock(&client->lock);
1742
1743 }
1744 /* And anyone still marked as a 1 means a leaked handle somewhere */
1745 for (n = rb_first(&dev->buffers); n; n = rb_next(n)) {
1746 struct ion_buffer *buf = rb_entry(n, struct ion_buffer,
1747 node);
1748
1749 if (buf->marked == 1)
1750 seq_printf(s, "%16.x %16.s %16.x %16.d\n",
1751 (int)buf, buf->heap->name, buf->size,
1752 atomic_read(&buf->ref.refcount));
1753 }
1754 mutex_unlock(&dev->lock);
1755 return 0;
1756}
1757
1758static int ion_debug_leak_open(struct inode *inode, struct file *file)
1759{
1760 return single_open(file, ion_debug_leak_show, inode->i_private);
1761}
1762
1763static const struct file_operations debug_leak_fops = {
1764 .open = ion_debug_leak_open,
1765 .read = seq_read,
1766 .llseek = seq_lseek,
1767 .release = single_release,
1768};
1769
1770
1771
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001772struct ion_device *ion_device_create(long (*custom_ioctl)
1773 (struct ion_client *client,
1774 unsigned int cmd,
1775 unsigned long arg))
1776{
1777 struct ion_device *idev;
1778 int ret;
1779
1780 idev = kzalloc(sizeof(struct ion_device), GFP_KERNEL);
1781 if (!idev)
1782 return ERR_PTR(-ENOMEM);
1783
1784 idev->dev.minor = MISC_DYNAMIC_MINOR;
1785 idev->dev.name = "ion";
1786 idev->dev.fops = &ion_fops;
1787 idev->dev.parent = NULL;
1788 ret = misc_register(&idev->dev);
1789 if (ret) {
1790 pr_err("ion: failed to register misc device.\n");
1791 return ERR_PTR(ret);
1792 }
1793
1794 idev->debug_root = debugfs_create_dir("ion", NULL);
1795 if (IS_ERR_OR_NULL(idev->debug_root))
1796 pr_err("ion: failed to create debug files.\n");
1797
1798 idev->custom_ioctl = custom_ioctl;
1799 idev->buffers = RB_ROOT;
1800 mutex_init(&idev->lock);
1801 idev->heaps = RB_ROOT;
1802 idev->user_clients = RB_ROOT;
1803 idev->kernel_clients = RB_ROOT;
Laura Abbott404f8242011-10-31 14:22:53 -07001804 debugfs_create_file("check_leaked_fds", 0664, idev->debug_root, idev,
1805 &debug_leak_fops);
Rebecca Schultz Zavinc80005a2011-06-29 19:44:29 -07001806 return idev;
1807}
1808
1809void ion_device_destroy(struct ion_device *dev)
1810{
1811 misc_deregister(&dev->dev);
1812 /* XXX need to free the heaps and clients ? */
1813 kfree(dev);
1814}