aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/ion
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/gpu/ion
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/gpu/ion')
-rw-r--r--drivers/gpu/ion/Kconfig17
-rw-r--r--drivers/gpu/ion/Makefile3
-rw-r--r--drivers/gpu/ion/ion.c1152
-rw-r--r--drivers/gpu/ion/ion_carveout_heap.c162
-rw-r--r--drivers/gpu/ion/ion_heap.c78
-rw-r--r--drivers/gpu/ion/ion_iommu_heap.c382
-rw-r--r--drivers/gpu/ion/ion_priv.h293
-rw-r--r--drivers/gpu/ion/ion_system_heap.c198
-rw-r--r--drivers/gpu/ion/ion_system_mapper.c114
-rw-r--r--drivers/gpu/ion/tegra/Makefile1
-rw-r--r--drivers/gpu/ion/tegra/tegra_ion.c599
11 files changed, 2999 insertions, 0 deletions
diff --git a/drivers/gpu/ion/Kconfig b/drivers/gpu/ion/Kconfig
new file mode 100644
index 00000000000..9a8cbdd9836
--- /dev/null
+++ b/drivers/gpu/ion/Kconfig
@@ -0,0 +1,17 @@
1menuconfig ION
2 tristate "Ion Memory Manager"
3 select GENERIC_ALLOCATOR
4 help
5 Chose this option to enable the ION Memory Manager.
6
7config ION_IOMMU
8 bool
9
10config ION_TEGRA
11 tristate "Ion for Tegra"
12 depends on ARCH_TEGRA && ION
13 select TEGRA_IOMMU_SMMU if !ARCH_TEGRA_2x_SOC
14 select ION_IOMMU if TEGRA_IOMMU_SMMU
15 help
16 Choose this option if you wish to use ion on an nVidia Tegra.
17
diff --git a/drivers/gpu/ion/Makefile b/drivers/gpu/ion/Makefile
new file mode 100644
index 00000000000..4ddc78e9d41
--- /dev/null
+++ b/drivers/gpu/ion/Makefile
@@ -0,0 +1,3 @@
1obj-$(CONFIG_ION) += ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o
2obj-$(CONFIG_ION_IOMMU) += ion_iommu_heap.o
3obj-$(CONFIG_ION_TEGRA) += tegra/
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
new file mode 100644
index 00000000000..512ebc5cc8e
--- /dev/null
+++ b/drivers/gpu/ion/ion.c
@@ -0,0 +1,1152 @@
1/*
2 * drivers/gpu/ion/ion.c
3 *
4 * Copyright (C) 2011 Google, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#define pr_fmt(fmt) "%s():%d: " fmt, __func__, __LINE__
18
19#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>
25#include <linux/miscdevice.h>
26#include <linux/mm.h>
27#include <linux/mm_types.h>
28#include <linux/rbtree.h>
29#include <linux/sched.h>
30#include <linux/slab.h>
31#include <linux/seq_file.h>
32#include <linux/uaccess.h>
33#include <linux/debugfs.h>
34
35#include "ion_priv.h"
36#define DEBUG
37
38/* this function should only be called while dev->lock is held */
39static void ion_buffer_add(struct ion_device *dev,
40 struct ion_buffer *buffer)
41{
42 struct rb_node **p = &dev->buffers.rb_node;
43 struct rb_node *parent = NULL;
44 struct ion_buffer *entry;
45
46 while (*p) {
47 parent = *p;
48 entry = rb_entry(parent, struct ion_buffer, node);
49
50 if (buffer < entry) {
51 p = &(*p)->rb_left;
52 } else if (buffer > entry) {
53 p = &(*p)->rb_right;
54 } else {
55 pr_err("buffer already found.");
56 BUG();
57 }
58 }
59
60 rb_link_node(&buffer->node, parent, p);
61 rb_insert_color(&buffer->node, &dev->buffers);
62}
63
64/* this function should only be called while dev->lock is held */
65static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
66 struct ion_device *dev,
67 unsigned long len,
68 unsigned long align,
69 unsigned long flags)
70{
71 struct ion_buffer *buffer;
72 int ret;
73
74 buffer = kzalloc(sizeof(struct ion_buffer), GFP_KERNEL);
75 if (!buffer)
76 return ERR_PTR(-ENOMEM);
77
78 buffer->heap = heap;
79 kref_init(&buffer->ref);
80
81 ret = heap->ops->allocate(heap, buffer, len, align, flags);
82 if (ret) {
83 kfree(buffer);
84 return ERR_PTR(ret);
85 }
86 buffer->dev = dev;
87 buffer->size = len;
88 mutex_init(&buffer->lock);
89 ion_buffer_add(dev, buffer);
90 return buffer;
91}
92
93static void ion_buffer_destroy(struct kref *kref)
94{
95 struct ion_buffer *buffer = container_of(kref, struct ion_buffer, ref);
96 struct ion_device *dev = buffer->dev;
97
98 buffer->heap->ops->free(buffer);
99 mutex_lock(&dev->lock);
100 rb_erase(&buffer->node, &dev->buffers);
101 mutex_unlock(&dev->lock);
102 kfree(buffer);
103}
104
105void ion_buffer_get(struct ion_buffer *buffer)
106{
107 kref_get(&buffer->ref);
108}
109
110static int ion_buffer_put(struct ion_buffer *buffer)
111{
112 return kref_put(&buffer->ref, ion_buffer_destroy);
113}
114
115struct ion_handle *ion_handle_create(struct ion_client *client,
116 struct ion_buffer *buffer)
117{
118 struct ion_handle *handle;
119
120 handle = kzalloc(sizeof(struct ion_handle), GFP_KERNEL);
121 if (!handle)
122 return ERR_PTR(-ENOMEM);
123 kref_init(&handle->ref);
124 rb_init_node(&handle->node);
125 handle->client = client;
126 ion_buffer_get(buffer);
127 handle->buffer = buffer;
128
129 return handle;
130}
131
132static void ion_handle_destroy(struct kref *kref)
133{
134 struct ion_handle *handle = container_of(kref, struct ion_handle, ref);
135 /* XXX Can a handle be destroyed while it's map count is non-zero?:
136 if (handle->map_cnt) unmap
137 */
138 ion_buffer_put(handle->buffer);
139 mutex_lock(&handle->client->lock);
140 if (!RB_EMPTY_NODE(&handle->node))
141 rb_erase(&handle->node, &handle->client->handles);
142 mutex_unlock(&handle->client->lock);
143 kfree(handle);
144}
145
146struct ion_buffer *ion_handle_buffer(struct ion_handle *handle)
147{
148 return handle->buffer;
149}
150
151void ion_handle_get(struct ion_handle *handle)
152{
153 kref_get(&handle->ref);
154}
155
156int ion_handle_put(struct ion_handle *handle)
157{
158 return kref_put(&handle->ref, ion_handle_destroy);
159}
160
161static struct ion_handle *ion_handle_lookup(struct ion_client *client,
162 struct ion_buffer *buffer)
163{
164 struct rb_node *n;
165
166 for (n = rb_first(&client->handles); n; n = rb_next(n)) {
167 struct ion_handle *handle = rb_entry(n, struct ion_handle,
168 node);
169 if (handle->buffer == buffer)
170 return handle;
171 }
172 return NULL;
173}
174
175bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle)
176{
177 struct rb_node *n = client->handles.rb_node;
178
179 while (n) {
180 struct ion_handle *handle_node = rb_entry(n, struct ion_handle,
181 node);
182 if (handle < handle_node)
183 n = n->rb_left;
184 else if (handle > handle_node)
185 n = n->rb_right;
186 else
187 return true;
188 }
189 WARN(1, "invalid handle passed h=0x%x,comm=%d\n", handle,
190 current->group_leader->comm);
191 return false;
192}
193
194void ion_handle_add(struct ion_client *client, struct ion_handle *handle)
195{
196 struct rb_node **p = &client->handles.rb_node;
197 struct rb_node *parent = NULL;
198 struct ion_handle *entry;
199
200 while (*p) {
201 parent = *p;
202 entry = rb_entry(parent, struct ion_handle, node);
203
204 if (handle < entry)
205 p = &(*p)->rb_left;
206 else if (handle > entry)
207 p = &(*p)->rb_right;
208 else
209 WARN(1, "%s: buffer already found.", __func__);
210 }
211
212 rb_link_node(&handle->node, parent, p);
213 rb_insert_color(&handle->node, &client->handles);
214}
215
216struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
217 size_t align, unsigned int flags)
218{
219 struct rb_node *n;
220 struct ion_handle *handle;
221 struct ion_device *dev = client->dev;
222 struct ion_buffer *buffer = NULL;
223
224 /*
225 * traverse the list of heaps available in this system in priority
226 * order. If the heap type is supported by the client, and matches the
227 * request of the caller allocate from it. Repeat until allocate has
228 * succeeded or all heaps have been tried
229 */
230 mutex_lock(&dev->lock);
231 for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) {
232 struct ion_heap *heap = rb_entry(n, struct ion_heap, node);
233 /* if the client doesn't support this heap type */
234 if (!((1 << heap->type) & client->heap_mask))
235 continue;
236 /* if the caller didn't specify this heap type */
237 if (!((1 << heap->id) & flags))
238 continue;
239 buffer = ion_buffer_create(heap, dev, len, align, flags);
240 if (!IS_ERR_OR_NULL(buffer))
241 break;
242 }
243 mutex_unlock(&dev->lock);
244
245 if (IS_ERR_OR_NULL(buffer))
246 return ERR_PTR(PTR_ERR(buffer));
247
248 handle = ion_handle_create(client, buffer);
249
250 if (IS_ERR_OR_NULL(handle))
251 goto end;
252
253 /*
254 * ion_buffer_create will create a buffer with a ref_cnt of 1,
255 * and ion_handle_create will take a second reference, drop one here
256 */
257 ion_buffer_put(buffer);
258
259 mutex_lock(&client->lock);
260 ion_handle_add(client, handle);
261 mutex_unlock(&client->lock);
262 return handle;
263
264end:
265 ion_buffer_put(buffer);
266 return handle;
267}
268
269void ion_free(struct ion_client *client, struct ion_handle *handle)
270{
271 bool valid_handle;
272
273 BUG_ON(client != handle->client);
274
275 mutex_lock(&client->lock);
276 valid_handle = ion_handle_validate(client, handle);
277 mutex_unlock(&client->lock);
278
279 if (!valid_handle) {
280 WARN(1, "%s: invalid handle passed to free.\n", __func__);
281 return;
282 }
283 ion_handle_put(handle);
284}
285
286static bool _ion_map(int *buffer_cnt, int *handle_cnt)
287{
288 bool map;
289
290 BUG_ON(*handle_cnt != 0 && *buffer_cnt == 0);
291
292 if (*buffer_cnt)
293 map = false;
294 else
295 map = true;
296 if (*handle_cnt == 0)
297 (*buffer_cnt)++;
298 (*handle_cnt)++;
299 return map;
300}
301
302static bool _ion_unmap(int *buffer_cnt, int *handle_cnt)
303{
304 BUG_ON(*handle_cnt == 0);
305 (*handle_cnt)--;
306 if (*handle_cnt != 0)
307 return false;
308 BUG_ON(*buffer_cnt == 0);
309 (*buffer_cnt)--;
310 if (*buffer_cnt == 0)
311 return true;
312 return false;
313}
314
315int ion_phys(struct ion_client *client, struct ion_handle *handle,
316 ion_phys_addr_t *addr, size_t *len)
317{
318 struct ion_buffer *buffer;
319 int ret;
320
321 mutex_lock(&client->lock);
322 if (!ion_handle_validate(client, handle)) {
323 mutex_unlock(&client->lock);
324 return -EINVAL;
325 }
326
327 buffer = handle->buffer;
328
329 if (!buffer->heap->ops->phys) {
330 pr_err("ion_phys is not implemented by this heap.\n");
331 mutex_unlock(&client->lock);
332 return -ENODEV;
333 }
334 mutex_unlock(&client->lock);
335 ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len);
336 return ret;
337}
338
339void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle)
340{
341 struct ion_buffer *buffer;
342 void *vaddr;
343
344 mutex_lock(&client->lock);
345 if (!ion_handle_validate(client, handle)) {
346 WARN(1, "invalid handle passed to map_kernel.\n");
347 mutex_unlock(&client->lock);
348 return ERR_PTR(-EINVAL);
349 }
350
351 buffer = handle->buffer;
352 mutex_lock(&buffer->lock);
353
354 if (!handle->buffer->heap->ops->map_kernel) {
355 pr_err("map_kernel is not implemented by this heap.\n");
356 mutex_unlock(&buffer->lock);
357 mutex_unlock(&client->lock);
358 return ERR_PTR(-ENODEV);
359 }
360
361 if (_ion_map(&buffer->kmap_cnt, &handle->kmap_cnt)) {
362 vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer);
363 if (IS_ERR_OR_NULL(vaddr))
364 _ion_unmap(&buffer->kmap_cnt, &handle->kmap_cnt);
365 buffer->vaddr = vaddr;
366 } else {
367 vaddr = buffer->vaddr;
368 }
369 mutex_unlock(&buffer->lock);
370 mutex_unlock(&client->lock);
371 return vaddr;
372}
373
374struct scatterlist *ion_map_dma(struct ion_client *client,
375 struct ion_handle *handle)
376{
377 struct ion_buffer *buffer;
378 struct scatterlist *sglist;
379
380 mutex_lock(&client->lock);
381 if (!ion_handle_validate(client, handle)) {
382 WARN(1, "invalid handle passed to map_dma.\n");
383 mutex_unlock(&client->lock);
384 return ERR_PTR(-EINVAL);
385 }
386 buffer = handle->buffer;
387 mutex_lock(&buffer->lock);
388
389 if (!handle->buffer->heap->ops->map_dma) {
390 pr_err("map_kernel is not implemented by this heap.\n");
391 mutex_unlock(&buffer->lock);
392 mutex_unlock(&client->lock);
393 return ERR_PTR(-ENODEV);
394 }
395 if (_ion_map(&buffer->dmap_cnt, &handle->dmap_cnt)) {
396 sglist = buffer->heap->ops->map_dma(buffer->heap, buffer);
397 if (IS_ERR_OR_NULL(sglist))
398 _ion_unmap(&buffer->dmap_cnt, &handle->dmap_cnt);
399 buffer->sglist = sglist;
400 } else {
401 sglist = buffer->sglist;
402 }
403 mutex_unlock(&buffer->lock);
404 mutex_unlock(&client->lock);
405 return sglist;
406}
407
408struct scatterlist *iommu_heap_remap_dma(struct ion_heap *heap,
409 struct ion_buffer *buf,
410 unsigned long addr);
411int ion_remap_dma(struct ion_client *client,
412 struct ion_handle *handle,
413 unsigned long addr)
414{
415 struct ion_buffer *buffer;
416 int ret;
417
418 mutex_lock(&client->lock);
419 if (!ion_handle_validate(client, handle)) {
420 pr_err("invalid handle passed to map_dma.\n");
421 mutex_unlock(&client->lock);
422 return -EINVAL;
423 }
424 buffer = handle->buffer;
425 mutex_lock(&buffer->lock);
426
427 ret = iommu_heap_remap_dma(buffer->heap, buffer, addr);
428
429 mutex_unlock(&buffer->lock);
430 mutex_unlock(&client->lock);
431 return ret;
432}
433
434void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle)
435{
436 struct ion_buffer *buffer;
437
438 mutex_lock(&client->lock);
439 buffer = handle->buffer;
440 mutex_lock(&buffer->lock);
441 if (_ion_unmap(&buffer->kmap_cnt, &handle->kmap_cnt)) {
442 buffer->heap->ops->unmap_kernel(buffer->heap, buffer);
443 buffer->vaddr = NULL;
444 }
445 mutex_unlock(&buffer->lock);
446 mutex_unlock(&client->lock);
447}
448
449void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle)
450{
451 struct ion_buffer *buffer;
452
453 mutex_lock(&client->lock);
454 buffer = handle->buffer;
455 mutex_lock(&buffer->lock);
456 if (_ion_unmap(&buffer->dmap_cnt, &handle->dmap_cnt)) {
457 buffer->heap->ops->unmap_dma(buffer->heap, buffer);
458 buffer->sglist = NULL;
459 }
460 mutex_unlock(&buffer->lock);
461 mutex_unlock(&client->lock);
462}
463
464
465struct ion_buffer *ion_share(struct ion_client *client,
466 struct ion_handle *handle)
467{
468 bool valid_handle;
469
470 mutex_lock(&client->lock);
471 valid_handle = ion_handle_validate(client, handle);
472 mutex_unlock(&client->lock);
473 if (!valid_handle) {
474 WARN(1, "%s: invalid handle passed to share.\n", __func__);
475 return ERR_PTR(-EINVAL);
476 }
477
478 /* do not take an extra reference here, the burden is on the caller
479 * to make sure the buffer doesn't go away while it's passing it
480 * to another client -- ion_free should not be called on this handle
481 * until the buffer has been imported into the other client
482 */
483 return handle->buffer;
484}
485
486struct ion_handle *ion_import(struct ion_client *client,
487 struct ion_buffer *buffer)
488{
489 struct ion_handle *handle = NULL;
490
491 mutex_lock(&client->lock);
492 /* if a handle exists for this buffer just take a reference to it */
493 handle = ion_handle_lookup(client, buffer);
494 if (!IS_ERR_OR_NULL(handle)) {
495 ion_handle_get(handle);
496 goto end;
497 }
498 handle = ion_handle_create(client, buffer);
499 if (IS_ERR_OR_NULL(handle)) {
500 pr_err("error during handle create\n");
501 goto end;
502 }
503 ion_handle_add(client, handle);
504end:
505 mutex_unlock(&client->lock);
506 return handle;
507}
508
509static const struct file_operations ion_share_fops;
510
511struct ion_handle *ion_import_fd(struct ion_client *client, int fd)
512{
513 struct file *file = fget(fd);
514 struct ion_handle *handle;
515
516 if (!file) {
517 pr_err("imported fd not found in file table.\n");
518 return ERR_PTR(-EINVAL);
519 }
520 if (file->f_op != &ion_share_fops) {
521 pr_err("imported file is not a shared ion file.\n");
522 handle = ERR_PTR(-EINVAL);
523 goto end;
524 }
525 handle = ion_import(client, file->private_data);
526end:
527 fput(file);
528 return handle;
529}
530
531static int ion_debug_client_show(struct seq_file *s, void *unused)
532{
533 struct ion_client *client = s->private;
534 struct rb_node *n;
535 size_t sizes[ION_NUM_HEAPS] = {0};
536 const char *names[ION_NUM_HEAPS] = {0};
537 int i;
538
539 mutex_lock(&client->lock);
540 for (n = rb_first(&client->handles); n; n = rb_next(n)) {
541 struct ion_handle *handle = rb_entry(n, struct ion_handle,
542 node);
543 enum ion_heap_type type = handle->buffer->heap->type;
544
545 if (!names[type])
546 names[type] = handle->buffer->heap->name;
547 sizes[type] += handle->buffer->size;
548 }
549 mutex_unlock(&client->lock);
550
551 seq_printf(s, "%16.16s: %16.16s\n", "heap_name", "size_in_bytes");
552 for (i = 0; i < ION_NUM_HEAPS; i++) {
553 if (!names[i])
554 continue;
555 seq_printf(s, "%16.16s: %16u %d\n", names[i], sizes[i],
556 atomic_read(&client->ref.refcount));
557 }
558 return 0;
559}
560
561static int ion_debug_client_open(struct inode *inode, struct file *file)
562{
563 return single_open(file, ion_debug_client_show, inode->i_private);
564}
565
566static const struct file_operations debug_client_fops = {
567 .open = ion_debug_client_open,
568 .read = seq_read,
569 .llseek = seq_lseek,
570 .release = single_release,
571};
572
573static struct ion_client *ion_client_lookup(struct ion_device *dev,
574 struct task_struct *task)
575{
576 struct rb_node *n = dev->user_clients.rb_node;
577 struct ion_client *client;
578
579 mutex_lock(&dev->lock);
580 while (n) {
581 client = rb_entry(n, struct ion_client, node);
582 if (task == client->task) {
583 ion_client_get(client);
584 mutex_unlock(&dev->lock);
585 return client;
586 } else if (task < client->task) {
587 n = n->rb_left;
588 } else if (task > client->task) {
589 n = n->rb_right;
590 }
591 }
592 mutex_unlock(&dev->lock);
593 return NULL;
594}
595
596struct ion_client *ion_client_create(struct ion_device *dev,
597 unsigned int heap_mask,
598 const char *name)
599{
600 struct ion_client *client;
601 struct task_struct *task;
602 struct rb_node **p;
603 struct rb_node *parent = NULL;
604 struct ion_client *entry;
605 char debug_name[64];
606 pid_t pid;
607
608 get_task_struct(current->group_leader);
609 task_lock(current->group_leader);
610 pid = task_pid_nr(current->group_leader);
611 /* don't bother to store task struct for kernel threads,
612 they can't be killed anyway */
613 if (current->group_leader->flags & PF_KTHREAD) {
614 put_task_struct(current->group_leader);
615 task = NULL;
616 } else {
617 task = current->group_leader;
618 }
619 task_unlock(current->group_leader);
620
621 /* if this isn't a kernel thread, see if a client already
622 exists */
623 if (task) {
624 client = ion_client_lookup(dev, task);
625 if (!IS_ERR_OR_NULL(client)) {
626 put_task_struct(current->group_leader);
627 return client;
628 }
629 }
630
631 client = kzalloc(sizeof(struct ion_client), GFP_KERNEL);
632 if (!client) {
633 put_task_struct(current->group_leader);
634 return ERR_PTR(-ENOMEM);
635 }
636
637 client->dev = dev;
638 client->handles = RB_ROOT;
639 mutex_init(&client->lock);
640 client->name = name;
641 client->heap_mask = heap_mask;
642 client->task = task;
643 client->pid = pid;
644 kref_init(&client->ref);
645
646 mutex_lock(&dev->lock);
647 if (task) {
648 p = &dev->user_clients.rb_node;
649 while (*p) {
650 parent = *p;
651 entry = rb_entry(parent, struct ion_client, node);
652
653 if (task < entry->task)
654 p = &(*p)->rb_left;
655 else if (task > entry->task)
656 p = &(*p)->rb_right;
657 }
658 rb_link_node(&client->node, parent, p);
659 rb_insert_color(&client->node, &dev->user_clients);
660 } else {
661 p = &dev->kernel_clients.rb_node;
662 while (*p) {
663 parent = *p;
664 entry = rb_entry(parent, struct ion_client, node);
665
666 if (client < entry)
667 p = &(*p)->rb_left;
668 else if (client > entry)
669 p = &(*p)->rb_right;
670 }
671 rb_link_node(&client->node, parent, p);
672 rb_insert_color(&client->node, &dev->kernel_clients);
673 }
674
675 snprintf(debug_name, 64, "%u", client->pid);
676 client->debug_root = debugfs_create_file(debug_name, 0664,
677 dev->debug_root, client,
678 &debug_client_fops);
679 mutex_unlock(&dev->lock);
680
681 return client;
682}
683
684static void _ion_client_destroy(struct kref *kref)
685{
686 struct ion_client *client = container_of(kref, struct ion_client, ref);
687 struct ion_device *dev = client->dev;
688 struct rb_node *n;
689
690 pr_debug("\n");
691 while ((n = rb_first(&client->handles))) {
692 struct ion_handle *handle = rb_entry(n, struct ion_handle,
693 node);
694 ion_handle_destroy(&handle->ref);
695 }
696 mutex_lock(&dev->lock);
697 if (client->task) {
698 rb_erase(&client->node, &dev->user_clients);
699 put_task_struct(client->task);
700 } else {
701 rb_erase(&client->node, &dev->kernel_clients);
702 }
703 debugfs_remove_recursive(client->debug_root);
704 mutex_unlock(&dev->lock);
705
706 kfree(client);
707}
708
709void ion_client_get(struct ion_client *client)
710{
711 kref_get(&client->ref);
712}
713
714int ion_client_put(struct ion_client *client)
715{
716 return kref_put(&client->ref, _ion_client_destroy);
717}
718
719void ion_client_destroy(struct ion_client *client)
720{
721 ion_client_put(client);
722}
723
724static int ion_share_release(struct inode *inode, struct file* file)
725{
726 struct ion_buffer *buffer = file->private_data;
727
728 pr_debug("\n");
729 /* drop the reference to the buffer -- this prevents the
730 buffer from going away because the client holding it exited
731 while it was being passed */
732 ion_buffer_put(buffer);
733 return 0;
734}
735
736static void ion_vma_open(struct vm_area_struct *vma)
737{
738
739 struct ion_buffer *buffer = vma->vm_file->private_data;
740 struct ion_handle *handle = vma->vm_private_data;
741 struct ion_client *client;
742
743 pr_debug("\n");
744 /* check that the client still exists and take a reference so
745 it can't go away until this vma is closed */
746 client = ion_client_lookup(buffer->dev, current->group_leader);
747 if (IS_ERR_OR_NULL(client)) {
748 vma->vm_private_data = NULL;
749 return;
750 }
751 ion_buffer_get(buffer);
752 ion_handle_get(handle);
753 pr_debug("client_cnt %d handle_cnt %d alloc_cnt %d\n",
754 atomic_read(&client->ref.refcount),
755 atomic_read(&handle->ref.refcount),
756 atomic_read(&buffer->ref.refcount));
757}
758
759static void ion_vma_close(struct vm_area_struct *vma)
760{
761 struct ion_handle *handle = vma->vm_private_data;
762 struct ion_buffer *buffer = vma->vm_file->private_data;
763 struct ion_client *client;
764
765 pr_debug("\n");
766 /* this indicates the client is gone, nothing to do here */
767 if (!handle)
768 return;
769 client = handle->client;
770 pr_debug("client_cnt %d handle_cnt %d alloc_cnt %d\n",
771 atomic_read(&client->ref.refcount),
772 atomic_read(&handle->ref.refcount),
773 atomic_read(&buffer->ref.refcount));
774 ion_handle_put(handle);
775 ion_client_put(client);
776 ion_buffer_put(buffer);
777 pr_debug("client_cnt %d handle_cnt %d alloc_cnt %d\n",
778 atomic_read(&client->ref.refcount),
779 atomic_read(&handle->ref.refcount),
780 atomic_read(&buffer->ref.refcount));
781}
782
783static struct vm_operations_struct ion_vm_ops = {
784 .open = ion_vma_open,
785 .close = ion_vma_close,
786};
787
788static int ion_share_mmap(struct file *file, struct vm_area_struct *vma)
789{
790 struct ion_buffer *buffer = file->private_data;
791 unsigned long size = vma->vm_end - vma->vm_start;
792 struct ion_client *client;
793 struct ion_handle *handle;
794 int ret;
795
796 pr_debug("\n");
797 /* make sure the client still exists, it's possible for the client to
798 have gone away but the map/share fd still to be around, take
799 a reference to it so it can't go away while this mapping exists */
800 client = ion_client_lookup(buffer->dev, current->group_leader);
801 if (IS_ERR_OR_NULL(client)) {
802 WARN(1, "trying to mmap an ion handle in a process with no "
803 "ion client\n");
804 return -EINVAL;
805 }
806
807 if ((size > buffer->size) || (size + (vma->vm_pgoff << PAGE_SHIFT) >
808 buffer->size)) {
809 WARN(1, "trying to map larger area than handle has available"
810 "\n");
811 ret = -EINVAL;
812 goto err;
813 }
814
815 /* find the handle and take a reference to it */
816 handle = ion_import(client, buffer);
817 if (IS_ERR_OR_NULL(handle)) {
818 ret = -EINVAL;
819 goto err;
820 }
821 ion_buffer_get(buffer);
822
823 if (!handle->buffer->heap->ops->map_user) {
824 pr_err("this heap does not define a method for mapping "
825 "to userspace\n");
826 ret = -EINVAL;
827 goto err1;
828 }
829
830 mutex_lock(&buffer->lock);
831 /* now map it to userspace */
832 ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma);
833 mutex_unlock(&buffer->lock);
834 if (ret) {
835 pr_err("failure mapping buffer to userspace\n");
836 goto err1;
837 }
838
839 vma->vm_ops = &ion_vm_ops;
840 /* move the handle into the vm_private_data so we can access it from
841 vma_open/close */
842 vma->vm_private_data = handle;
843 pr_debug("client_cnt %d handle_cnt %d alloc_cnt %d\n",
844 atomic_read(&client->ref.refcount),
845 atomic_read(&handle->ref.refcount),
846 atomic_read(&buffer->ref.refcount));
847 return 0;
848
849err1:
850 /* drop the reference to the handle */
851 ion_handle_put(handle);
852err:
853 /* drop the reference to the client */
854 ion_client_put(client);
855 return ret;
856}
857
858static const struct file_operations ion_share_fops = {
859 .owner = THIS_MODULE,
860 .release = ion_share_release,
861 .mmap = ion_share_mmap,
862};
863
864static int ion_ioctl_share(struct file *parent, struct ion_client *client,
865 struct ion_handle *handle)
866{
867 int fd = get_unused_fd();
868 struct file *file;
869
870 if (fd < 0)
871 return -ENFILE;
872
873 file = anon_inode_getfile("ion_share_fd", &ion_share_fops,
874 handle->buffer, O_RDWR);
875 if (IS_ERR_OR_NULL(file))
876 goto err;
877 ion_buffer_get(handle->buffer);
878 fd_install(fd, file);
879
880 return fd;
881
882err:
883 put_unused_fd(fd);
884 return -ENFILE;
885}
886
887static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
888{
889 struct ion_client *client = filp->private_data;
890
891 switch (cmd) {
892 case ION_IOC_ALLOC:
893 {
894 struct ion_allocation_data data;
895
896 if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
897 return -EFAULT;
898 data.handle = ion_alloc(client, data.len, data.align,
899 data.flags);
900 if (copy_to_user((void __user *)arg, &data, sizeof(data)))
901 return -EFAULT;
902 break;
903 }
904 case ION_IOC_FREE:
905 {
906 struct ion_handle_data data;
907 bool valid;
908
909 if (copy_from_user(&data, (void __user *)arg,
910 sizeof(struct ion_handle_data)))
911 return -EFAULT;
912 mutex_lock(&client->lock);
913 valid = ion_handle_validate(client, data.handle);
914 mutex_unlock(&client->lock);
915 if (!valid)
916 return -EINVAL;
917 ion_free(client, data.handle);
918 break;
919 }
920 case ION_IOC_MAP:
921 case ION_IOC_SHARE:
922 {
923 struct ion_fd_data data;
924
925 if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
926 return -EFAULT;
927 mutex_lock(&client->lock);
928 if (!ion_handle_validate(client, data.handle)) {
929 WARN(1, "invalid handle passed to share ioctl.\n");
930 mutex_unlock(&client->lock);
931 return -EINVAL;
932 }
933 data.fd = ion_ioctl_share(filp, client, data.handle);
934 mutex_unlock(&client->lock);
935 if (copy_to_user((void __user *)arg, &data, sizeof(data)))
936 return -EFAULT;
937 break;
938 }
939 case ION_IOC_IMPORT:
940 {
941 struct ion_fd_data data;
942 if (copy_from_user(&data, (void __user *)arg,
943 sizeof(struct ion_fd_data)))
944 return -EFAULT;
945
946 data.handle = ion_import_fd(client, data.fd);
947 if (IS_ERR(data.handle))
948 data.handle = NULL;
949 if (copy_to_user((void __user *)arg, &data,
950 sizeof(struct ion_fd_data)))
951 return -EFAULT;
952 break;
953 }
954 case ION_IOC_CUSTOM:
955 {
956 struct ion_device *dev = client->dev;
957 struct ion_custom_data data;
958
959 if (!dev->custom_ioctl)
960 return -ENOTTY;
961 if (copy_from_user(&data, (void __user *)arg,
962 sizeof(struct ion_custom_data)))
963 return -EFAULT;
964 return dev->custom_ioctl(client, data.cmd, data.arg);
965 }
966 default:
967 return -ENOTTY;
968 }
969 return 0;
970}
971
972static int ion_release(struct inode *inode, struct file *file)
973{
974 struct ion_client *client = file->private_data;
975
976 pr_debug("\n");
977 ion_client_put(client);
978 return 0;
979}
980
981static int ion_open(struct inode *inode, struct file *file)
982{
983 struct miscdevice *miscdev = file->private_data;
984 struct ion_device *dev = container_of(miscdev, struct ion_device, dev);
985 struct ion_client *client;
986
987 pr_debug("\n");
988 client = ion_client_create(dev, -1, "user");
989 if (IS_ERR_OR_NULL(client))
990 return PTR_ERR(client);
991 file->private_data = client;
992
993 return 0;
994}
995
996static const struct file_operations ion_fops = {
997 .owner = THIS_MODULE,
998 .open = ion_open,
999 .release = ion_release,
1000 .unlocked_ioctl = ion_ioctl,
1001};
1002
1003static size_t ion_debug_heap_total(struct ion_client *client,
1004 enum ion_heap_type type)
1005{
1006 size_t size = 0;
1007 struct rb_node *n;
1008
1009 mutex_lock(&client->lock);
1010 for (n = rb_first(&client->handles); n; n = rb_next(n)) {
1011 struct ion_handle *handle = rb_entry(n,
1012 struct ion_handle,
1013 node);
1014 if (handle->buffer->heap->type == type)
1015 size += handle->buffer->size;
1016 }
1017 mutex_unlock(&client->lock);
1018 return size;
1019}
1020
1021static int ion_debug_heap_show(struct seq_file *s, void *unused)
1022{
1023 struct ion_heap *heap = s->private;
1024 struct ion_device *dev = heap->dev;
1025 struct rb_node *n;
1026
1027 seq_printf(s, "%16.s %16.s %16.s\n", "client", "pid", "size");
1028 for (n = rb_first(&dev->user_clients); n; n = rb_next(n)) {
1029 struct ion_client *client = rb_entry(n, struct ion_client,
1030 node);
1031 char task_comm[TASK_COMM_LEN];
1032 size_t size = ion_debug_heap_total(client, heap->type);
1033 if (!size)
1034 continue;
1035
1036 get_task_comm(task_comm, client->task);
1037 seq_printf(s, "%16.s %16u %16u\n", task_comm, client->pid,
1038 size);
1039 }
1040
1041 for (n = rb_first(&dev->kernel_clients); n; n = rb_next(n)) {
1042 struct ion_client *client = rb_entry(n, struct ion_client,
1043 node);
1044 size_t size = ion_debug_heap_total(client, heap->type);
1045 if (!size)
1046 continue;
1047 seq_printf(s, "%16.s %16u %16u\n", client->name, client->pid,
1048 size);
1049 }
1050 return 0;
1051}
1052
1053static int ion_debug_heap_open(struct inode *inode, struct file *file)
1054{
1055 return single_open(file, ion_debug_heap_show, inode->i_private);
1056}
1057
1058static const struct file_operations debug_heap_fops = {
1059 .open = ion_debug_heap_open,
1060 .read = seq_read,
1061 .llseek = seq_lseek,
1062 .release = single_release,
1063};
1064
1065void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
1066{
1067 struct rb_node **p = &dev->heaps.rb_node;
1068 struct rb_node *parent = NULL;
1069 struct ion_heap *entry;
1070
1071 heap->dev = dev;
1072 mutex_lock(&dev->lock);
1073 while (*p) {
1074 parent = *p;
1075 entry = rb_entry(parent, struct ion_heap, node);
1076
1077 if (heap->id < entry->id) {
1078 p = &(*p)->rb_left;
1079 } else if (heap->id > entry->id ) {
1080 p = &(*p)->rb_right;
1081 } else {
1082 pr_err("can not insert multiple heaps with "
1083 "id %d\n", heap->id);
1084 goto end;
1085 }
1086 }
1087
1088 rb_link_node(&heap->node, parent, p);
1089 rb_insert_color(&heap->node, &dev->heaps);
1090 debugfs_create_file(heap->name, 0664, dev->debug_root, heap,
1091 &debug_heap_fops);
1092end:
1093 mutex_unlock(&dev->lock);
1094}
1095
1096struct ion_device *ion_device_create(long (*custom_ioctl)
1097 (struct ion_client *client,
1098 unsigned int cmd,
1099 unsigned long arg))
1100{
1101 struct ion_device *idev;
1102 int ret;
1103
1104 idev = kzalloc(sizeof(struct ion_device), GFP_KERNEL);
1105 if (!idev)
1106 return ERR_PTR(-ENOMEM);
1107
1108 idev->dev.minor = MISC_DYNAMIC_MINOR;
1109 idev->dev.name = "ion";
1110 idev->dev.fops = &ion_fops;
1111 idev->dev.parent = NULL;
1112 ret = misc_register(&idev->dev);
1113 if (ret) {
1114 pr_err("ion: failed to register misc device.\n");
1115 return ERR_PTR(ret);
1116 }
1117
1118 idev->debug_root = debugfs_create_dir("ion", NULL);
1119 if (IS_ERR_OR_NULL(idev->debug_root))
1120 pr_err("ion: failed to create debug files.\n");
1121
1122 idev->custom_ioctl = custom_ioctl;
1123 idev->buffers = RB_ROOT;
1124 mutex_init(&idev->lock);
1125 idev->heaps = RB_ROOT;
1126 idev->user_clients = RB_ROOT;
1127 idev->kernel_clients = RB_ROOT;
1128 return idev;
1129}
1130
1131void ion_device_destroy(struct ion_device *dev)
1132{
1133 misc_deregister(&dev->dev);
1134 /* XXX need to free the heaps and clients ? */
1135 kfree(dev);
1136}
1137
1138struct ion_client *ion_client_get_file(int fd)
1139{
1140 struct ion_client *client = ERR_PTR(-EFAULT);
1141 struct file *f = fget(fd);
1142 if (!f)
1143 return ERR_PTR(-EINVAL);
1144
1145 if (f->f_op == &ion_fops) {
1146 client = f->private_data;
1147 ion_client_get(client);
1148 }
1149
1150 fput(f);
1151 return client;
1152}
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
new file mode 100644
index 00000000000..606adae13f4
--- /dev/null
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -0,0 +1,162 @@
1/*
2 * drivers/gpu/ion/ion_carveout_heap.c
3 *
4 * Copyright (C) 2011 Google, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16#include <linux/spinlock.h>
17
18#include <linux/err.h>
19#include <linux/genalloc.h>
20#include <linux/io.h>
21#include <linux/ion.h>
22#include <linux/mm.h>
23#include <linux/scatterlist.h>
24#include <linux/slab.h>
25#include <linux/vmalloc.h>
26#include "ion_priv.h"
27
28#include <asm/mach/map.h>
29
30struct ion_carveout_heap {
31 struct ion_heap heap;
32 struct gen_pool *pool;
33 ion_phys_addr_t base;
34};
35
36ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap,
37 unsigned long size,
38 unsigned long align)
39{
40 struct ion_carveout_heap *carveout_heap =
41 container_of(heap, struct ion_carveout_heap, heap);
42 unsigned long offset = gen_pool_alloc(carveout_heap->pool, size);
43
44 if (!offset)
45 return ION_CARVEOUT_ALLOCATE_FAIL;
46
47 return offset;
48}
49
50void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
51 unsigned long size)
52{
53 struct ion_carveout_heap *carveout_heap =
54 container_of(heap, struct ion_carveout_heap, heap);
55
56 if (addr == ION_CARVEOUT_ALLOCATE_FAIL)
57 return;
58 gen_pool_free(carveout_heap->pool, addr, size);
59}
60
61static int ion_carveout_heap_phys(struct ion_heap *heap,
62 struct ion_buffer *buffer,
63 ion_phys_addr_t *addr, size_t *len)
64{
65 *addr = buffer->priv_phys;
66 *len = buffer->size;
67 return 0;
68}
69
70static int ion_carveout_heap_allocate(struct ion_heap *heap,
71 struct ion_buffer *buffer,
72 unsigned long size, unsigned long align,
73 unsigned long flags)
74{
75 buffer->priv_phys = ion_carveout_allocate(heap, size, align);
76 return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0;
77}
78
79static void ion_carveout_heap_free(struct ion_buffer *buffer)
80{
81 struct ion_heap *heap = buffer->heap;
82
83 ion_carveout_free(heap, buffer->priv_phys, buffer->size);
84 buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL;
85}
86
87struct scatterlist *ion_carveout_heap_map_dma(struct ion_heap *heap,
88 struct ion_buffer *buffer)
89{
90 return ERR_PTR(-EINVAL);
91}
92
93void ion_carveout_heap_unmap_dma(struct ion_heap *heap,
94 struct ion_buffer *buffer)
95{
96 return;
97}
98
99void *ion_carveout_heap_map_kernel(struct ion_heap *heap,
100 struct ion_buffer *buffer)
101{
102 return __arch_ioremap(buffer->priv_phys, buffer->size,
103 MT_MEMORY_NONCACHED);
104}
105
106void ion_carveout_heap_unmap_kernel(struct ion_heap *heap,
107 struct ion_buffer *buffer)
108{
109 __arch_iounmap(buffer->vaddr);
110 buffer->vaddr = NULL;
111 return;
112}
113
114int ion_carveout_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
115 struct vm_area_struct *vma)
116{
117 return remap_pfn_range(vma, vma->vm_start,
118 __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
119 buffer->size,
120 pgprot_noncached(vma->vm_page_prot));
121}
122
123static struct ion_heap_ops carveout_heap_ops = {
124 .allocate = ion_carveout_heap_allocate,
125 .free = ion_carveout_heap_free,
126 .phys = ion_carveout_heap_phys,
127 .map_user = ion_carveout_heap_map_user,
128 .map_kernel = ion_carveout_heap_map_kernel,
129 .unmap_kernel = ion_carveout_heap_unmap_kernel,
130};
131
132struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
133{
134 struct ion_carveout_heap *carveout_heap;
135
136 carveout_heap = kzalloc(sizeof(struct ion_carveout_heap), GFP_KERNEL);
137 if (!carveout_heap)
138 return ERR_PTR(-ENOMEM);
139
140 carveout_heap->pool = gen_pool_create(12, -1);
141 if (!carveout_heap->pool) {
142 kfree(carveout_heap);
143 return ERR_PTR(-ENOMEM);
144 }
145 carveout_heap->base = heap_data->base;
146 gen_pool_add(carveout_heap->pool, carveout_heap->base, heap_data->size,
147 -1);
148 carveout_heap->heap.ops = &carveout_heap_ops;
149 carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT;
150
151 return &carveout_heap->heap;
152}
153
154void ion_carveout_heap_destroy(struct ion_heap *heap)
155{
156 struct ion_carveout_heap *carveout_heap =
157 container_of(heap, struct ion_carveout_heap, heap);
158
159 gen_pool_destroy(carveout_heap->pool);
160 kfree(carveout_heap);
161 carveout_heap = NULL;
162}
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
new file mode 100644
index 00000000000..6d09778745c
--- /dev/null
+++ b/drivers/gpu/ion/ion_heap.c
@@ -0,0 +1,78 @@
1/*
2 * drivers/gpu/ion/ion_heap.c
3 *
4 * Copyright (C) 2011 Google, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/err.h>
18#include <linux/ion.h>
19#include "ion_priv.h"
20
21struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
22{
23 struct ion_heap *heap = NULL;
24
25 switch (heap_data->type) {
26 case ION_HEAP_TYPE_SYSTEM_CONTIG:
27 heap = ion_system_contig_heap_create(heap_data);
28 break;
29 case ION_HEAP_TYPE_SYSTEM:
30 heap = ion_system_heap_create(heap_data);
31 break;
32 case ION_HEAP_TYPE_CARVEOUT:
33 heap = ion_carveout_heap_create(heap_data);
34 break;
35 case ION_HEAP_TYPE_IOMMU:
36 heap = ion_iommu_heap_create(heap_data);
37 break;
38 default:
39 pr_err("%s: Invalid heap type %d\n", __func__,
40 heap_data->type);
41 return ERR_PTR(-EINVAL);
42 }
43
44 if (IS_ERR_OR_NULL(heap)) {
45 pr_err("%s: error creating heap %s type %d base %lu size %u\n",
46 __func__, heap_data->name, heap_data->type,
47 heap_data->base, heap_data->size);
48 return ERR_PTR(-EINVAL);
49 }
50
51 heap->name = heap_data->name;
52 heap->id = heap_data->id;
53 return heap;
54}
55
56void ion_heap_destroy(struct ion_heap *heap)
57{
58 if (!heap)
59 return;
60
61 switch (heap->type) {
62 case ION_HEAP_TYPE_SYSTEM_CONTIG:
63 ion_system_contig_heap_destroy(heap);
64 break;
65 case ION_HEAP_TYPE_SYSTEM:
66 ion_system_heap_destroy(heap);
67 break;
68 case ION_HEAP_TYPE_CARVEOUT:
69 ion_carveout_heap_destroy(heap);
70 break;
71 case ION_HEAP_TYPE_IOMMU:
72 ion_iommu_heap_destroy(heap);
73 break;
74 default:
75 pr_err("%s: Invalid heap type %d\n", __func__,
76 heap->type);
77 }
78}
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
new file mode 100644
index 00000000000..a3d2d726bda
--- /dev/null
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -0,0 +1,382 @@
1/*
2 * drivers/gpu/ion/ion_iommu_heap.c
3 *
4 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#define pr_fmt(fmt) "%s(): " fmt, __func__
21
22#include <linux/spinlock.h>
23#include <linux/kernel.h>
24#include <linux/genalloc.h>
25#include <linux/io.h>
26#include <linux/ion.h>
27#include <linux/mm.h>
28#include <linux/scatterlist.h>
29#include <linux/slab.h>
30#include <linux/vmalloc.h>
31#include <linux/iommu.h>
32#include <linux/highmem.h>
33#include <linux/platform_device.h>
34
35#include <asm/cacheflush.h>
36
37#include "ion_priv.h"
38
39#define NUM_PAGES(buf) (PAGE_ALIGN((buf)->size) >> PAGE_SHIFT)
40
41#define GFP_ION (GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN)
42
43struct ion_iommu_heap {
44 struct ion_heap heap;
45 struct gen_pool *pool;
46 struct iommu_domain *domain;
47 struct device *dev;
48};
49
50static struct scatterlist *iommu_heap_map_dma(struct ion_heap *heap,
51 struct ion_buffer *buf)
52{
53 struct ion_iommu_heap *h =
54 container_of(heap, struct ion_iommu_heap, heap);
55 int err, npages = NUM_PAGES(buf);
56 unsigned int i;
57 struct scatterlist *sg;
58 unsigned long da = (unsigned long)buf->priv_virt;
59
60 for_each_sg(buf->sglist, sg, npages, i) {
61 phys_addr_t pa;
62
63 pa = sg_phys(sg);
64 BUG_ON(!IS_ALIGNED(sg->length, PAGE_SIZE));
65 err = iommu_map(h->domain, da, pa, PAGE_SIZE, 0);
66 if (err)
67 goto err_out;
68
69 sg->dma_address = da;
70 da += PAGE_SIZE;
71 }
72
73 pr_debug("da:%p pa:%08x va:%p\n",
74 buf->priv_virt, sg_phys(buf->sglist), buf->vaddr);
75
76 return buf->sglist;
77
78err_out:
79 if (i-- > 0) {
80 unsigned int j;
81 for_each_sg(buf->sglist, sg, i, j)
82 iommu_unmap(h->domain, sg_dma_address(sg), 0);
83 }
84 return ERR_PTR(err);
85}
86
87static void iommu_heap_unmap_dma(struct ion_heap *heap, struct ion_buffer *buf)
88{
89 struct ion_iommu_heap *h =
90 container_of(heap, struct ion_iommu_heap, heap);
91 unsigned int i;
92 struct scatterlist *sg;
93 int npages = NUM_PAGES(buf);
94
95 for_each_sg(buf->sglist, sg, npages, i)
96 iommu_unmap(h->domain, sg_dma_address(sg), 0);
97
98 pr_debug("da:%p\n", buf->priv_virt);
99}
100
101struct scatterlist *iommu_heap_remap_dma(struct ion_heap *heap,
102 struct ion_buffer *buf,
103 unsigned long addr)
104{
105 struct ion_iommu_heap *h =
106 container_of(heap, struct ion_iommu_heap, heap);
107 int err;
108 unsigned int i;
109 unsigned long da, da_to_free = (unsigned long)buf->priv_virt;
110 int npages = NUM_PAGES(buf);
111
112 BUG_ON(!buf->priv_virt);
113
114 da = gen_pool_alloc_addr(h->pool, buf->size, addr);
115 if (da == 0) {
116 pr_err("dma address alloc failed, addr=0x%lx", addr);
117 return ERR_PTR(-ENOMEM);
118 } else {
119 pr_err("iommu_heap_remap_dma passed, addr=0x%lx",
120 addr);
121 iommu_heap_unmap_dma(heap, buf);
122 gen_pool_free(h->pool, da_to_free, buf->size);
123 buf->priv_virt = (void *)da;
124 }
125 for (i = 0; i < npages; i++) {
126 phys_addr_t pa;
127
128 pa = page_to_phys(buf->pages[i]);
129 err = iommu_map(h->domain, da, pa, 0, 0);
130 if (err)
131 goto err_out;
132 da += PAGE_SIZE;
133 }
134
135 pr_debug("da:%p pa:%08x va:%p\n",
136 buf->priv_virt, page_to_phys(buf->pages[0]), buf->vaddr);
137
138 return (struct scatterlist *)buf->pages;
139
140err_out:
141 if (i-- > 0) {
142 da = (unsigned long)buf->priv_virt;
143 iommu_unmap(h->domain, da + (i << PAGE_SHIFT), 0);
144 }
145 return ERR_PTR(err);
146}
147
148static int ion_buffer_allocate(struct ion_buffer *buf)
149{
150 int i, npages = NUM_PAGES(buf);
151
152 buf->pages = kmalloc(npages * sizeof(*buf->pages), GFP_KERNEL);
153 if (!buf->pages)
154 goto err_pages;
155
156 buf->sglist = vzalloc(npages * sizeof(*buf->sglist));
157 if (!buf->sglist)
158 goto err_sgl;
159
160 sg_init_table(buf->sglist, npages);
161
162 for (i = 0; i < npages; i++) {
163 struct page *page;
164 phys_addr_t pa;
165
166 page = alloc_page(GFP_ION);
167 if (!page)
168 goto err_pgalloc;
169 pa = page_to_phys(page);
170
171 sg_set_page(&buf->sglist[i], page, PAGE_SIZE, 0);
172
173 flush_dcache_page(page);
174 outer_flush_range(pa, pa + PAGE_SIZE);
175
176 buf->pages[i] = page;
177
178 pr_debug_once("pa:%08x\n", pa);
179 }
180 return 0;
181
182err_pgalloc:
183 while (i-- > 0)
184 __free_page(buf->pages[i]);
185 vfree(buf->sglist);
186err_sgl:
187 kfree(buf->pages);
188err_pages:
189 return -ENOMEM;
190}
191
192static void ion_buffer_free(struct ion_buffer *buf)
193{
194 int i, npages = NUM_PAGES(buf);
195
196 for (i = 0; i < npages; i++)
197 __free_page(buf->pages[i]);
198 vfree(buf->sglist);
199 kfree(buf->pages);
200}
201
202static int iommu_heap_allocate(struct ion_heap *heap, struct ion_buffer *buf,
203 unsigned long len, unsigned long align,
204 unsigned long flags)
205{
206 int err;
207 struct ion_iommu_heap *h =
208 container_of(heap, struct ion_iommu_heap, heap);
209 unsigned long da;
210 struct scatterlist *sgl;
211
212 len = round_up(len, PAGE_SIZE);
213
214 da = gen_pool_alloc(h->pool, len);
215 if (!da)
216 return -ENOMEM;
217
218 buf->priv_virt = (void *)da;
219 buf->size = len;
220
221 WARN_ON(!IS_ALIGNED(da, PAGE_SIZE));
222
223 err = ion_buffer_allocate(buf);
224 if (err)
225 goto err_alloc_buf;
226
227 sgl = iommu_heap_map_dma(heap, buf);
228 if (IS_ERR_OR_NULL(sgl))
229 goto err_heap_map_dma;
230 buf->vaddr = 0;
231 return 0;
232
233err_heap_map_dma:
234 ion_buffer_free(buf);
235err_alloc_buf:
236 gen_pool_free(h->pool, da, len);
237 buf->size = 0;
238 buf->pages = NULL;
239 buf->priv_virt = NULL;
240 return err;
241}
242
243static void iommu_heap_free(struct ion_buffer *buf)
244{
245 struct ion_heap *heap = buf->heap;
246 struct ion_iommu_heap *h =
247 container_of(heap, struct ion_iommu_heap, heap);
248 void *da = buf->priv_virt;
249
250 iommu_heap_unmap_dma(heap, buf);
251 ion_buffer_free(buf);
252 gen_pool_free(h->pool, (unsigned long)da, buf->size);
253
254 buf->pages = NULL;
255 buf->priv_virt = NULL;
256 pr_debug("da:%p\n", da);
257}
258
259static int iommu_heap_phys(struct ion_heap *heap, struct ion_buffer *buf,
260 ion_phys_addr_t *addr, size_t *len)
261{
262 *addr = (unsigned long)buf->priv_virt;
263 *len = buf->size;
264 pr_debug("da:%08lx(%x)\n", *addr, *len);
265 return 0;
266}
267
268static void *iommu_heap_map_kernel(struct ion_heap *heap,
269 struct ion_buffer *buf)
270{
271 int npages = NUM_PAGES(buf);
272
273 BUG_ON(!buf->pages);
274 buf->vaddr = vm_map_ram(buf->pages, npages, -1,
275 pgprot_noncached(pgprot_kernel));
276 pr_debug("va:%p\n", buf->vaddr);
277 WARN_ON(!buf->vaddr);
278 return buf->vaddr;
279}
280
281static void iommu_heap_unmap_kernel(struct ion_heap *heap,
282 struct ion_buffer *buf)
283{
284 int npages = NUM_PAGES(buf);
285
286 BUG_ON(!buf->pages);
287 WARN_ON(!buf->vaddr);
288 vm_unmap_ram(buf->vaddr, npages);
289 buf->vaddr = NULL;
290 pr_debug("va:%p\n", buf->vaddr);
291}
292
293static int iommu_heap_map_user(struct ion_heap *mapper,
294 struct ion_buffer *buf,
295 struct vm_area_struct *vma)
296{
297 int i = vma->vm_pgoff >> PAGE_SHIFT;
298 unsigned long uaddr = vma->vm_start;
299 unsigned long usize = vma->vm_end - vma->vm_start;
300
301 pr_debug("vma:%08lx-%08lx\n", vma->vm_start, vma->vm_end);
302 BUG_ON(!buf->pages);
303
304 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
305 do {
306 int ret;
307 struct page *page = buf->pages[i++];
308
309 ret = vm_insert_page(vma, uaddr, page);
310 if (ret)
311 return ret;
312
313 uaddr += PAGE_SIZE;
314 usize -= PAGE_SIZE;
315 } while (usize > 0);
316
317 return 0;
318}
319
320static struct ion_heap_ops iommu_heap_ops = {
321 .allocate = iommu_heap_allocate,
322 .free = iommu_heap_free,
323 .phys = iommu_heap_phys,
324 .map_dma = iommu_heap_map_dma,
325 .unmap_dma = iommu_heap_unmap_dma,
326 .map_kernel = iommu_heap_map_kernel,
327 .unmap_kernel = iommu_heap_unmap_kernel,
328 .map_user = iommu_heap_map_user,
329};
330
331struct ion_heap *ion_iommu_heap_create(struct ion_platform_heap *data)
332{
333 struct ion_iommu_heap *h;
334 int err;
335
336 h = kzalloc(sizeof(*h), GFP_KERNEL);
337 if (!h) {
338 err = -ENOMEM;
339 goto err_heap;
340 }
341
342 h->pool = gen_pool_create(12, -1);
343 if (!h->pool) {
344 err = -ENOMEM;
345 goto err_genpool;
346 }
347 gen_pool_add(h->pool, data->base, data->size, -1);
348
349 h->heap.ops = &iommu_heap_ops;
350 h->domain = iommu_domain_alloc(&platform_bus_type);
351 h->dev = data->priv;
352 if (!h->domain) {
353 err = -ENOMEM;
354 goto err_iommu_alloc;
355 }
356
357 err = iommu_attach_device(h->domain, h->dev);
358 if (err)
359 goto err_iommu_attach;
360
361 return &h->heap;
362
363err_iommu_attach:
364 iommu_domain_free(h->domain);
365err_iommu_alloc:
366 gen_pool_destroy(h->pool);
367err_genpool:
368 kfree(h);
369err_heap:
370 return ERR_PTR(err);
371}
372
373void ion_iommu_heap_destroy(struct ion_heap *heap)
374{
375 struct ion_iommu_heap *h =
376 container_of(heap, struct ion_iommu_heap, heap);
377
378 iommu_detach_device(h->domain, h->dev);
379 gen_pool_destroy(h->pool);
380 iommu_domain_free(h->domain);
381 kfree(h);
382}
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
new file mode 100644
index 00000000000..bfe26da9c04
--- /dev/null
+++ b/drivers/gpu/ion/ion_priv.h
@@ -0,0 +1,293 @@
1/*
2 * drivers/gpu/ion/ion_priv.h
3 *
4 * Copyright (C) 2011 Google, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef _ION_PRIV_H
18#define _ION_PRIV_H
19
20#include <linux/kref.h>
21#include <linux/mm_types.h>
22#include <linux/mutex.h>
23#include <linux/rbtree.h>
24#include <linux/ion.h>
25#include <linux/miscdevice.h>
26
27struct ion_mapping;
28
29struct ion_dma_mapping {
30 struct kref ref;
31 struct scatterlist *sglist;
32};
33
34struct ion_kernel_mapping {
35 struct kref ref;
36 void *vaddr;
37};
38
39/**
40 * struct ion_device - the metadata of the ion device node
41 * @dev: the actual misc device
42 * @buffers: an rb tree of all the existing buffers
43 * @lock: lock protecting the buffers & heaps trees
44 * @heaps: list of all the heaps in the system
45 * @user_clients: list of all the clients created from userspace
46 */
47struct ion_device {
48 struct miscdevice dev;
49 struct rb_root buffers;
50 struct mutex lock;
51 struct rb_root heaps;
52 long (*custom_ioctl) (struct ion_client *client, unsigned int cmd,
53 unsigned long arg);
54 struct rb_root user_clients;
55 struct rb_root kernel_clients;
56 struct dentry *debug_root;
57};
58
59/**
60 * struct ion_client - a process/hw block local address space
61 * @ref: for reference counting the client
62 * @node: node in the tree of all clients
63 * @dev: backpointer to ion device
64 * @handles: an rb tree of all the handles in this client
65 * @lock: lock protecting the tree of handles
66 * @heap_mask: mask of all supported heaps
67 * @name: used for debugging
68 * @task: used for debugging
69 *
70 * A client represents a list of buffers this client may access.
71 * The mutex stored here is used to protect both handles tree
72 * as well as the handles themselves, and should be held while modifying either.
73 */
74struct ion_client {
75 struct kref ref;
76 struct rb_node node;
77 struct ion_device *dev;
78 struct rb_root handles;
79 struct mutex lock;
80 unsigned int heap_mask;
81 const char *name;
82 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
95 * @usermap_cnt: count of times this client has mapped for userspace
96 *
97 * Modifications to node, map_cnt or mapping should be protected by the
98 * lock in the client. Other fields are never changed after initialization.
99 */
100struct ion_handle {
101 struct kref ref;
102 struct ion_client *client;
103 struct ion_buffer *buffer;
104 struct rb_node node;
105 unsigned int kmap_cnt;
106 unsigned int dmap_cnt;
107 unsigned int usermap_cnt;
108};
109
110bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle);
111
112void ion_buffer_get(struct ion_buffer *buffer);
113
114struct ion_buffer *ion_handle_buffer(struct ion_handle *handle);
115
116struct ion_client *ion_client_get_file(int fd);
117
118void ion_client_get(struct ion_client *client);
119
120int ion_client_put(struct ion_client *client);
121
122void ion_handle_get(struct ion_handle *handle);
123
124int ion_handle_put(struct ion_handle *handle);
125
126struct ion_handle *ion_handle_create(struct ion_client *client,
127 struct ion_buffer *buffer);
128
129void ion_handle_add(struct ion_client *client, struct ion_handle *handle);
130
131int ion_remap_dma(struct ion_client *client,
132 struct ion_handle *handle,
133 unsigned long addr);
134/**
135 * struct ion_buffer - metadata for a particular buffer
136 * @ref: refernce count
137 * @node: node in the ion_device buffers tree
138 * @dev: back pointer to the ion_device
139 * @heap: back pointer to the heap the buffer came from
140 * @flags: buffer specific flags
141 * @size: size of the buffer
142 * @priv_virt: private data to the buffer representable as
143 * a void *
144 * @priv_phys: private data to the buffer representable as
145 * an ion_phys_addr_t (and someday a phys_addr_t)
146 * @lock: protects the buffers cnt fields
147 * @kmap_cnt: number of times the buffer is mapped to the kernel
148 * @vaddr: the kenrel mapping if kmap_cnt is not zero
149 * @dmap_cnt: number of times the buffer is mapped for dma
150 * @sglist: the scatterlist for the buffer is dmap_cnt is not zero
151 * @pages: list for allocated pages for the buffer
152 */
153struct ion_buffer {
154 struct kref ref;
155 struct rb_node node;
156 struct ion_device *dev;
157 struct ion_heap *heap;
158 unsigned long flags;
159 size_t size;
160 union {
161 void *priv_virt;
162 ion_phys_addr_t priv_phys;
163 };
164 struct mutex lock;
165 int kmap_cnt;
166 void *vaddr;
167 int dmap_cnt;
168 struct scatterlist *sglist;
169 struct page **pages;
170};
171
172/**
173 * struct ion_heap_ops - ops to operate on a given heap
174 * @allocate: allocate memory
175 * @free: free memory
176 * @phys get physical address of a buffer (only define on
177 * physically contiguous heaps)
178 * @map_dma map the memory for dma to a scatterlist
179 * @unmap_dma unmap the memory for dma
180 * @map_kernel map memory to the kernel
181 * @unmap_kernel unmap memory to the kernel
182 * @map_user map memory to userspace
183 */
184struct ion_heap_ops {
185 int (*allocate) (struct ion_heap *heap,
186 struct ion_buffer *buffer, unsigned long len,
187 unsigned long align, unsigned long flags);
188 void (*free) (struct ion_buffer *buffer);
189 int (*phys) (struct ion_heap *heap, struct ion_buffer *buffer,
190 ion_phys_addr_t *addr, size_t *len);
191 struct scatterlist *(*map_dma) (struct ion_heap *heap,
192 struct ion_buffer *buffer);
193 void (*unmap_dma) (struct ion_heap *heap, struct ion_buffer *buffer);
194 void * (*map_kernel) (struct ion_heap *heap, struct ion_buffer *buffer);
195 void (*unmap_kernel) (struct ion_heap *heap, struct ion_buffer *buffer);
196 int (*map_user) (struct ion_heap *mapper, struct ion_buffer *buffer,
197 struct vm_area_struct *vma);
198};
199
200/**
201 * struct ion_heap - represents a heap in the system
202 * @node: rb node to put the heap on the device's tree of heaps
203 * @dev: back pointer to the ion_device
204 * @type: type of heap
205 * @ops: ops struct as above
206 * @id: id of heap, also indicates priority of this heap when
207 * allocating. These are specified by platform data and
208 * MUST be unique
209 * @name: used for debugging
210 *
211 * Represents a pool of memory from which buffers can be made. In some
212 * systems the only heap is regular system memory allocated via vmalloc.
213 * On others, some blocks might require large physically contiguous buffers
214 * that are allocated from a specially reserved heap.
215 */
216struct ion_heap {
217 struct rb_node node;
218 struct ion_device *dev;
219 enum ion_heap_type type;
220 struct ion_heap_ops *ops;
221 int id;
222 const char *name;
223};
224
225/**
226 * ion_device_create - allocates and returns an ion device
227 * @custom_ioctl: arch specific ioctl function if applicable
228 *
229 * returns a valid device or -PTR_ERR
230 */
231struct ion_device *ion_device_create(long (*custom_ioctl)
232 (struct ion_client *client,
233 unsigned int cmd,
234 unsigned long arg));
235
236/**
237 * ion_device_destroy - free and device and it's resource
238 * @dev: the device
239 */
240void ion_device_destroy(struct ion_device *dev);
241
242/**
243 * ion_device_add_heap - adds a heap to the ion device
244 * @dev: the device
245 * @heap: the heap to add
246 */
247void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap);
248
249/**
250 * functions for creating and destroying the built in ion heaps.
251 * architectures can add their own custom architecture specific
252 * heaps as appropriate.
253 */
254
255struct ion_heap *ion_heap_create(struct ion_platform_heap *);
256void ion_heap_destroy(struct ion_heap *);
257
258struct ion_heap *ion_system_heap_create(struct ion_platform_heap *);
259void ion_system_heap_destroy(struct ion_heap *);
260
261struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *);
262void ion_system_contig_heap_destroy(struct ion_heap *);
263
264struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *);
265void ion_carveout_heap_destroy(struct ion_heap *);
266/**
267 * kernel api to allocate/free from carveout -- used when carveout is
268 * used to back an architecture specific custom heap
269 */
270ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, unsigned long size,
271 unsigned long align);
272void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
273 unsigned long size);
274
275#ifdef CONFIG_ION_IOMMU
276struct ion_heap *ion_iommu_heap_create(struct ion_platform_heap *);
277void ion_iommu_heap_destroy(struct ion_heap *);
278#else
279static inline struct ion_heap *ion_iommu_heap_create(struct ion_platform_heap *)
280{
281 return NULL;
282}
283static inline void ion_iommu_heap_destroy(struct ion_heap *)
284{
285}
286#endif
287/**
288 * The carveout heap returns physical addresses, since 0 may be a valid
289 * physical address, this is used to indicate allocation failed
290 */
291#define ION_CARVEOUT_ALLOCATE_FAIL -1
292
293#endif /* _ION_PRIV_H */
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
new file mode 100644
index 00000000000..c046cf1a321
--- /dev/null
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -0,0 +1,198 @@
1/*
2 * drivers/gpu/ion/ion_system_heap.c
3 *
4 * Copyright (C) 2011 Google, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/err.h>
18#include <linux/ion.h>
19#include <linux/mm.h>
20#include <linux/scatterlist.h>
21#include <linux/slab.h>
22#include <linux/vmalloc.h>
23#include "ion_priv.h"
24
25static int ion_system_heap_allocate(struct ion_heap *heap,
26 struct ion_buffer *buffer,
27 unsigned long size, unsigned long align,
28 unsigned long flags)
29{
30 buffer->priv_virt = vmalloc_user(size);
31 if (!buffer->priv_virt)
32 return -ENOMEM;
33 return 0;
34}
35
36void ion_system_heap_free(struct ion_buffer *buffer)
37{
38 vfree(buffer->priv_virt);
39}
40
41struct scatterlist *ion_system_heap_map_dma(struct ion_heap *heap,
42 struct ion_buffer *buffer)
43{
44 struct scatterlist *sglist;
45 struct page *page;
46 int i;
47 int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE;
48 void *vaddr = buffer->priv_virt;
49
50 sglist = vmalloc(npages * sizeof(struct scatterlist));
51 if (!sglist)
52 return ERR_PTR(-ENOMEM);
53 memset(sglist, 0, npages * sizeof(struct scatterlist));
54 sg_init_table(sglist, npages);
55 for (i = 0; i < npages; i++) {
56 page = vmalloc_to_page(vaddr);
57 if (!page)
58 goto end;
59 sg_set_page(&sglist[i], page, PAGE_SIZE, 0);
60 vaddr += PAGE_SIZE;
61 }
62 /* XXX do cache maintenance for dma? */
63 return sglist;
64end:
65 vfree(sglist);
66 return NULL;
67}
68
69void ion_system_heap_unmap_dma(struct ion_heap *heap,
70 struct ion_buffer *buffer)
71{
72 /* XXX undo cache maintenance for dma? */
73 if (buffer->sglist)
74 vfree(buffer->sglist);
75}
76
77void *ion_system_heap_map_kernel(struct ion_heap *heap,
78 struct ion_buffer *buffer)
79{
80 return buffer->priv_virt;
81}
82
83void ion_system_heap_unmap_kernel(struct ion_heap *heap,
84 struct ion_buffer *buffer)
85{
86}
87
88int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
89 struct vm_area_struct *vma)
90{
91 return remap_vmalloc_range(vma, buffer->priv_virt, vma->vm_pgoff);
92}
93
94static struct ion_heap_ops vmalloc_ops = {
95 .allocate = ion_system_heap_allocate,
96 .free = ion_system_heap_free,
97 .map_dma = ion_system_heap_map_dma,
98 .unmap_dma = ion_system_heap_unmap_dma,
99 .map_kernel = ion_system_heap_map_kernel,
100 .unmap_kernel = ion_system_heap_unmap_kernel,
101 .map_user = ion_system_heap_map_user,
102};
103
104struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused)
105{
106 struct ion_heap *heap;
107
108 heap = kzalloc(sizeof(struct ion_heap), GFP_KERNEL);
109 if (!heap)
110 return ERR_PTR(-ENOMEM);
111 heap->ops = &vmalloc_ops;
112 heap->type = ION_HEAP_TYPE_SYSTEM;
113 return heap;
114}
115
116void ion_system_heap_destroy(struct ion_heap *heap)
117{
118 kfree(heap);
119}
120
121static int ion_system_contig_heap_allocate(struct ion_heap *heap,
122 struct ion_buffer *buffer,
123 unsigned long len,
124 unsigned long align,
125 unsigned long flags)
126{
127 buffer->priv_virt = kzalloc(len, GFP_KERNEL);
128 if (!buffer->priv_virt)
129 return -ENOMEM;
130 return 0;
131}
132
133void ion_system_contig_heap_free(struct ion_buffer *buffer)
134{
135 kfree(buffer->priv_virt);
136}
137
138static int ion_system_contig_heap_phys(struct ion_heap *heap,
139 struct ion_buffer *buffer,
140 ion_phys_addr_t *addr, size_t *len)
141{
142 *addr = virt_to_phys(buffer->priv_virt);
143 *len = buffer->size;
144 return 0;
145}
146
147struct scatterlist *ion_system_contig_heap_map_dma(struct ion_heap *heap,
148 struct ion_buffer *buffer)
149{
150 struct scatterlist *sglist;
151
152 sglist = vmalloc(sizeof(struct scatterlist));
153 if (!sglist)
154 return ERR_PTR(-ENOMEM);
155 sg_init_table(sglist, 1);
156 sg_set_page(sglist, virt_to_page(buffer->priv_virt), buffer->size, 0);
157 return sglist;
158}
159
160int ion_system_contig_heap_map_user(struct ion_heap *heap,
161 struct ion_buffer *buffer,
162 struct vm_area_struct *vma)
163{
164 unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv_virt));
165 return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
166 vma->vm_end - vma->vm_start,
167 vma->vm_page_prot);
168
169}
170
171static struct ion_heap_ops kmalloc_ops = {
172 .allocate = ion_system_contig_heap_allocate,
173 .free = ion_system_contig_heap_free,
174 .phys = ion_system_contig_heap_phys,
175 .map_dma = ion_system_contig_heap_map_dma,
176 .unmap_dma = ion_system_heap_unmap_dma,
177 .map_kernel = ion_system_heap_map_kernel,
178 .unmap_kernel = ion_system_heap_unmap_kernel,
179 .map_user = ion_system_contig_heap_map_user,
180};
181
182struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused)
183{
184 struct ion_heap *heap;
185
186 heap = kzalloc(sizeof(struct ion_heap), GFP_KERNEL);
187 if (!heap)
188 return ERR_PTR(-ENOMEM);
189 heap->ops = &kmalloc_ops;
190 heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG;
191 return heap;
192}
193
194void ion_system_contig_heap_destroy(struct ion_heap *heap)
195{
196 kfree(heap);
197}
198
diff --git a/drivers/gpu/ion/ion_system_mapper.c b/drivers/gpu/ion/ion_system_mapper.c
new file mode 100644
index 00000000000..692458e07b5
--- /dev/null
+++ b/drivers/gpu/ion/ion_system_mapper.c
@@ -0,0 +1,114 @@
1/*
2 * drivers/gpu/ion/ion_system_mapper.c
3 *
4 * Copyright (C) 2011 Google, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/err.h>
18#include <linux/ion.h>
19#include <linux/memory.h>
20#include <linux/mm.h>
21#include <linux/slab.h>
22#include <linux/vmalloc.h>
23#include "ion_priv.h"
24/*
25 * This mapper is valid for any heap that allocates memory that already has
26 * a kernel mapping, this includes vmalloc'd memory, kmalloc'd memory,
27 * pages obtained via io_remap, etc.
28 */
29static void *ion_kernel_mapper_map(struct ion_mapper *mapper,
30 struct ion_buffer *buffer,
31 struct ion_mapping **mapping)
32{
33 if (!((1 << buffer->heap->type) & mapper->heap_mask)) {
34 pr_err("%s: attempting to map an unsupported heap\n", __func__);
35 return ERR_PTR(-EINVAL);
36 }
37 /* XXX REVISIT ME!!! */
38 *((unsigned long *)mapping) = (unsigned long)buffer->priv;
39 return buffer->priv;
40}
41
42static void ion_kernel_mapper_unmap(struct ion_mapper *mapper,
43 struct ion_buffer *buffer,
44 struct ion_mapping *mapping)
45{
46 if (!((1 << buffer->heap->type) & mapper->heap_mask))
47 pr_err("%s: attempting to unmap an unsupported heap\n",
48 __func__);
49}
50
51static void *ion_kernel_mapper_map_kernel(struct ion_mapper *mapper,
52 struct ion_buffer *buffer,
53 struct ion_mapping *mapping)
54{
55 if (!((1 << buffer->heap->type) & mapper->heap_mask)) {
56 pr_err("%s: attempting to unmap an unsupported heap\n",
57 __func__);
58 return ERR_PTR(-EINVAL);
59 }
60 return buffer->priv;
61}
62
63static int ion_kernel_mapper_map_user(struct ion_mapper *mapper,
64 struct ion_buffer *buffer,
65 struct vm_area_struct *vma,
66 struct ion_mapping *mapping)
67{
68 int ret;
69
70 switch (buffer->heap->type) {
71 case ION_HEAP_KMALLOC:
72 {
73 unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv));
74 ret = remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
75 vma->vm_end - vma->vm_start,
76 vma->vm_page_prot);
77 break;
78 }
79 case ION_HEAP_VMALLOC:
80 ret = remap_vmalloc_range(vma, buffer->priv, vma->vm_pgoff);
81 break;
82 default:
83 pr_err("%s: attempting to map unsupported heap to userspace\n",
84 __func__);
85 return -EINVAL;
86 }
87
88 return ret;
89}
90
91static struct ion_mapper_ops ops = {
92 .map = ion_kernel_mapper_map,
93 .map_kernel = ion_kernel_mapper_map_kernel,
94 .map_user = ion_kernel_mapper_map_user,
95 .unmap = ion_kernel_mapper_unmap,
96};
97
98struct ion_mapper *ion_system_mapper_create(void)
99{
100 struct ion_mapper *mapper;
101 mapper = kzalloc(sizeof(struct ion_mapper), GFP_KERNEL);
102 if (!mapper)
103 return ERR_PTR(-ENOMEM);
104 mapper->type = ION_SYSTEM_MAPPER;
105 mapper->ops = &ops;
106 mapper->heap_mask = (1 << ION_HEAP_VMALLOC) | (1 << ION_HEAP_KMALLOC);
107 return mapper;
108}
109
110void ion_system_mapper_destroy(struct ion_mapper *mapper)
111{
112 kfree(mapper);
113}
114
diff --git a/drivers/gpu/ion/tegra/Makefile b/drivers/gpu/ion/tegra/Makefile
new file mode 100644
index 00000000000..11cd003fb08
--- /dev/null
+++ b/drivers/gpu/ion/tegra/Makefile
@@ -0,0 +1 @@
obj-y += tegra_ion.o
diff --git a/drivers/gpu/ion/tegra/tegra_ion.c b/drivers/gpu/ion/tegra/tegra_ion.c
new file mode 100644
index 00000000000..2252079279e
--- /dev/null
+++ b/drivers/gpu/ion/tegra/tegra_ion.c
@@ -0,0 +1,599 @@
1/*
2 * drivers/gpu/tegra/tegra_ion.c
3 *
4 * Copyright (C) 2011 Google, Inc.
5 * Copyright (C) 2011, NVIDIA Corporation.
6 *
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#define pr_fmt(fmt) "%s():%d: " fmt, __func__, __LINE__
19
20#include <linux/err.h>
21#include <linux/ion.h>
22#include <linux/tegra_ion.h>
23#include <linux/platform_device.h>
24#include <linux/slab.h>
25#include <linux/uaccess.h>
26#include <linux/syscalls.h>
27#include <linux/io.h>
28#include "../ion_priv.h"
29
30#define CLIENT_HEAP_MASK 0xFFFFFFFF
31#define HEAP_FLAGS 0xFF
32
33#if !defined(CONFIG_TEGRA_NVMAP)
34#include "mach/nvmap.h"
35struct nvmap_device *nvmap_dev;
36#endif
37
38static struct ion_device *idev;
39static int num_heaps;
40static struct ion_heap **heaps;
41
42static int tegra_ion_pin(struct ion_client *client,
43 unsigned int cmd,
44 unsigned long arg)
45{
46 struct tegra_ion_pin_data data;
47 int ret;
48 struct ion_handle *on_stack[16];
49 struct ion_handle **refs = on_stack;
50 int i;
51 bool valid_handle;
52
53 if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
54 return -EFAULT;
55 if (data.count) {
56 size_t bytes = data.count * sizeof(struct ion_handle *);
57
58 if (data.count > ARRAY_SIZE(on_stack))
59 refs = kmalloc(data.count * sizeof(*refs), GFP_KERNEL);
60 else
61 refs = on_stack;
62 if (!refs)
63 return -ENOMEM;
64 if (copy_from_user(refs, (void *)data.handles, bytes)) {
65 ret = -EFAULT;
66 goto err;
67 }
68 } else
69 return -EINVAL;
70
71 mutex_lock(&client->lock);
72 for (i = 0; i < data.count; i++) {
73 /* Ignore NULL pointers during unpin operation. */
74 if (!refs[i] && cmd == TEGRA_ION_UNPIN)
75 continue;
76 valid_handle = ion_handle_validate(client, refs[i]);
77 if (!valid_handle) {
78 WARN(1, "invalid handle passed h=0x%x", (u32)refs[i]);
79 mutex_unlock(&client->lock);
80 ret = -EINVAL;
81 goto err;
82 }
83 }
84 mutex_unlock(&client->lock);
85
86 if (cmd == TEGRA_ION_PIN) {
87 ion_phys_addr_t addr;
88 size_t len;
89
90 for (i = 0; i < data.count; i++) {
91 ret = ion_phys(client, refs[i], &addr, &len);
92 if (ret)
93 goto err;
94 ion_handle_get(refs[i]);
95 ret = put_user(addr, &data.addr[i]);
96 if (ret)
97 return ret;
98 }
99 } else if (cmd == TEGRA_ION_UNPIN) {
100 for (i = 0; i < data.count; i++) {
101 if (refs[i])
102 ion_handle_put(refs[i]);
103 }
104 }
105
106err:
107 if (ret) {
108 pr_err("error, ret=0x%x", ret);
109 /* FIXME: undo pinning. */
110 }
111 if (refs != on_stack)
112 kfree(refs);
113 return ret;
114}
115
116static int tegra_ion_alloc_from_id(struct ion_client *client,
117 unsigned int cmd,
118 unsigned long arg)
119{
120 struct tegra_ion_id_data data;
121 struct ion_buffer *buffer;
122 struct tegra_ion_id_data *user_data = (struct tegra_ion_id_data *)arg;
123
124 if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
125 return -EFAULT;
126 buffer = (struct ion_buffer *)data.id;
127 data.handle = ion_import(client, buffer);
128 data.size = buffer->size;
129 if (put_user(data.handle, &user_data->handle))
130 return -EFAULT;
131 if (put_user(data.size, &user_data->size))
132 return -EFAULT;
133 return 0;
134}
135
136static int tegra_ion_get_id(struct ion_client *client,
137 unsigned int cmd,
138 unsigned long arg)
139{
140 bool valid_handle;
141 struct tegra_ion_id_data data;
142 struct tegra_ion_id_data *user_data = (struct tegra_ion_id_data *)arg;
143
144 if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
145 return -EFAULT;
146
147 mutex_lock(&client->lock);
148 valid_handle = ion_handle_validate(client, data.handle);
149 mutex_unlock(&client->lock);
150
151 if (!valid_handle) {
152 WARN(1, "invalid handle passed\n");
153 return -EINVAL;
154 }
155
156 pr_debug("h=0x%x, b=0x%x, bref=%d",
157 (u32)data.handle, (u32)data.handle->buffer,
158 atomic_read(&data.handle->buffer->ref.refcount));
159 if (put_user((unsigned long)ion_handle_buffer(data.handle),
160 &user_data->id))
161 return -EFAULT;
162 return 0;
163}
164
165static int tegra_ion_cache_maint(struct ion_client *client,
166 unsigned int cmd,
167 unsigned long arg)
168{
169 wmb();
170 return 0;
171}
172
173static int tegra_ion_rw(struct ion_client *client,
174 unsigned int cmd,
175 unsigned long arg)
176{
177 bool valid_handle;
178 struct tegra_ion_rw_data data;
179 char *kern_addr, *src;
180 int ret = 0;
181 size_t copied = 0;
182
183 if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
184 return -EFAULT;
185
186 if (!data.handle || !data.addr || !data.count || !data.elem_size)
187 return -EINVAL;
188
189 mutex_lock(&client->lock);
190 valid_handle = ion_handle_validate(client, data.handle);
191 mutex_unlock(&client->lock);
192
193 if (!valid_handle) {
194 WARN(1, "%s: invalid handle passed to get id.\n", __func__);
195 return -EINVAL;
196 }
197
198 if (data.elem_size == data.mem_stride &&
199 data.elem_size == data.user_stride) {
200 data.elem_size *= data.count;
201 data.mem_stride = data.elem_size;
202 data.user_stride = data.elem_size;
203 data.count = 1;
204 }
205
206 kern_addr = ion_map_kernel(client, data.handle);
207
208 while (data.count--) {
209 if (data.offset + data.elem_size > data.handle->buffer->size) {
210 WARN(1, "read/write outside of handle\n");
211 ret = -EFAULT;
212 break;
213 }
214
215 src = kern_addr + data.offset;
216 if (cmd == TEGRA_ION_READ)
217 ret = copy_to_user((void *)data.addr,
218 src, data.elem_size);
219 else
220 ret = copy_from_user(src,
221 (void *)data.addr, data.elem_size);
222
223 if (ret)
224 break;
225
226 copied += data.elem_size;
227 data.addr += data.user_stride;
228 data.offset += data.mem_stride;
229 }
230
231 ion_unmap_kernel(client, data.handle);
232 return ret;
233}
234
235static int tegra_ion_get_param(struct ion_client *client,
236 unsigned int cmd,
237 unsigned long arg)
238{
239 bool valid_handle;
240 struct tegra_ion_get_params_data data;
241 struct tegra_ion_get_params_data *user_data =
242 (struct tegra_ion_get_params_data *)arg;
243 struct ion_buffer *buffer;
244
245 if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
246 return -EFAULT;
247
248 mutex_lock(&client->lock);
249 valid_handle = ion_handle_validate(client, data.handle);
250 mutex_unlock(&client->lock);
251
252 if (!valid_handle) {
253 WARN(1, "%s: invalid handle passed to get id.\n", __func__);
254 return -EINVAL;
255 }
256
257 buffer = ion_handle_buffer(data.handle);
258 data.align = 4096;
259 data.heap = 1;
260 ion_phys(client, data.handle, &data.addr, &data.size);
261
262 if (copy_to_user(user_data, &data, sizeof(data)))
263 return -EFAULT;
264
265 return 0;
266}
267
268static long tegra_ion_ioctl(struct ion_client *client,
269 unsigned int cmd,
270 unsigned long arg)
271{
272 int ret = -ENOTTY;
273
274 switch (cmd) {
275 case TEGRA_ION_ALLOC_FROM_ID:
276 ret = tegra_ion_alloc_from_id(client, cmd, arg);
277 break;
278 case TEGRA_ION_GET_ID:
279 ret = tegra_ion_get_id(client, cmd, arg);
280 break;
281 case TEGRA_ION_PIN:
282 case TEGRA_ION_UNPIN:
283 ret = tegra_ion_pin(client, cmd, arg);
284 break;
285 case TEGRA_ION_CACHE_MAINT:
286 ret = tegra_ion_cache_maint(client, cmd, arg);
287 break;
288 case TEGRA_ION_READ:
289 case TEGRA_ION_WRITE:
290 ret = tegra_ion_rw(client, cmd, arg);
291 break;
292 case TEGRA_ION_GET_PARAM:
293 ret = tegra_ion_get_param(client, cmd, arg);
294 break;
295 default:
296 WARN(1, "Unknown custom ioctl\n");
297 return -ENOTTY;
298 }
299 return ret;
300}
301
302int tegra_ion_probe(struct platform_device *pdev)
303{
304 struct ion_platform_data *pdata = pdev->dev.platform_data;
305 int i;
306
307 num_heaps = pdata->nr;
308
309 heaps = kzalloc(sizeof(struct ion_heap *) * pdata->nr, GFP_KERNEL);
310
311 idev = ion_device_create(tegra_ion_ioctl);
312 if (IS_ERR_OR_NULL(idev)) {
313 kfree(heaps);
314 return PTR_ERR(idev);
315 }
316
317 /* create the heaps as specified in the board file */
318 for (i = 0; i < num_heaps; i++) {
319 struct ion_platform_heap *heap_data = &pdata->heaps[i];
320
321 heaps[i] = ion_heap_create(heap_data);
322 if (IS_ERR_OR_NULL(heaps[i])) {
323 pr_warn("%s(type:%d id:%d) isn't supported\n",
324 heap_data->name,
325 heap_data->type, heap_data->id);
326 continue;
327 }
328 ion_device_add_heap(idev, heaps[i]);
329 }
330 platform_set_drvdata(pdev, idev);
331#if !defined(CONFIG_TEGRA_NVMAP)
332 nvmap_dev = (struct nvmap_device *)idev;
333#endif
334 return 0;
335}
336
337int tegra_ion_remove(struct platform_device *pdev)
338{
339 struct ion_device *idev = platform_get_drvdata(pdev);
340 int i;
341
342 ion_device_destroy(idev);
343 for (i = 0; i < num_heaps; i++)
344 ion_heap_destroy(heaps[i]);
345 kfree(heaps);
346 return 0;
347}
348
349static struct platform_driver ion_driver = {
350 .probe = tegra_ion_probe,
351 .remove = tegra_ion_remove,
352 .driver = { .name = "ion-tegra" }
353};
354
355static int __init ion_init(void)
356{
357 return platform_driver_register(&ion_driver);
358}
359
360static void __exit ion_exit(void)
361{
362 platform_driver_unregister(&ion_driver);
363}
364
365fs_initcall(ion_init);
366module_exit(ion_exit);
367
368#if !defined(CONFIG_TEGRA_NVMAP)
369struct nvmap_client *nvmap_create_client(struct nvmap_device *dev,
370 const char *name)
371{
372 return ion_client_create(dev, CLIENT_HEAP_MASK, name);
373}
374
375struct nvmap_handle_ref *nvmap_alloc(struct nvmap_client *client, size_t size,
376 size_t align, unsigned int flags,
377 unsigned int heap_mask)
378{
379 return ion_alloc(client, size, align, HEAP_FLAGS);
380}
381
382void nvmap_free(struct nvmap_client *client, struct nvmap_handle_ref *r)
383{
384 ion_free(client, r);
385}
386
387void *nvmap_mmap(struct nvmap_handle_ref *r)
388{
389 return ion_map_kernel(r->client, r);
390}
391
392void nvmap_munmap(struct nvmap_handle_ref *r, void *addr)
393{
394 ion_unmap_kernel(r->client, r);
395}
396
397struct nvmap_client *nvmap_client_get_file(int fd)
398{
399 return ion_client_get_file(fd);
400}
401
402struct nvmap_client *nvmap_client_get(struct nvmap_client *client)
403{
404 ion_client_get(client);
405 return client;
406}
407
408void nvmap_client_put(struct nvmap_client *c)
409{
410 ion_client_put(c);
411}
412
413phys_addr_t nvmap_pin(struct nvmap_client *c, struct nvmap_handle_ref *r)
414{
415 ion_phys_addr_t addr;
416 size_t len;
417
418 ion_handle_get(r);
419 ion_phys(c, r, &addr, &len);
420 wmb();
421 return addr;
422}
423
424phys_addr_t nvmap_handle_address(struct nvmap_client *c, unsigned long id)
425{
426 struct ion_handle *handle;
427 ion_phys_addr_t addr;
428 size_t len;
429
430 handle = nvmap_convert_handle_u2k(id);
431 ion_phys(c, handle, &addr, &len);
432 return addr;
433}
434
435void nvmap_unpin(struct nvmap_client *client, struct nvmap_handle_ref *r)
436{
437 if (r)
438 ion_handle_put(r);
439}
440
441static int nvmap_reloc_pin_array(struct ion_client *client,
442 const struct nvmap_pinarray_elem *arr,
443 int nr, struct ion_handle *gather)
444{
445 struct ion_handle *last_patch = NULL;
446 void *patch_addr;
447 ion_phys_addr_t pin_addr;
448 size_t len;
449 int i;
450
451 for (i = 0; i < nr; i++) {
452 struct ion_handle *patch;
453 struct ion_handle *pin;
454 ion_phys_addr_t reloc_addr;
455
456 /* all of the handles are validated and get'ted prior to
457 * calling this function, so casting is safe here */
458 pin = (struct ion_handle *)arr[i].pin_mem;
459
460 if (arr[i].patch_mem == (unsigned long)last_patch) {
461 patch = last_patch;
462 } else if (arr[i].patch_mem == (unsigned long)gather) {
463 patch = gather;
464 } else {
465 if (last_patch)
466 ion_handle_put(last_patch);
467
468 ion_handle_get((struct ion_handle *)arr[i].patch_mem);
469 patch = (struct ion_handle *)arr[i].patch_mem;
470 if (!patch)
471 return -EPERM;
472 last_patch = patch;
473 }
474
475 patch_addr = ion_map_kernel(client, patch);
476 patch_addr = patch_addr + arr[i].patch_offset;
477
478 ion_phys(client, pin, &pin_addr, &len);
479 reloc_addr = pin_addr + arr[i].pin_offset;
480 __raw_writel(reloc_addr, patch_addr);
481 ion_unmap_kernel(client, patch);
482 }
483
484 if (last_patch)
485 ion_handle_put(last_patch);
486
487 wmb();
488 return 0;
489}
490
491int nvmap_pin_array(struct nvmap_client *client, struct nvmap_handle *gather,
492 const struct nvmap_pinarray_elem *arr, int nr,
493 struct nvmap_handle **unique)
494{
495 int i;
496 int count = 0;
497
498 /* FIXME: take care of duplicate ones & validation. */
499 for (i = 0; i < nr; i++) {
500 unique[i] = (struct nvmap_handle *)arr[i].pin_mem;
501 nvmap_pin(client, (struct nvmap_handle_ref *)unique[i]);
502 count++;
503 }
504 nvmap_reloc_pin_array((struct ion_client *)client,
505 arr, nr, (struct ion_handle *)gather);
506 return nr;
507}
508
509void nvmap_unpin_handles(struct nvmap_client *client,
510 struct nvmap_handle **h, int nr)
511{
512 int i;
513
514 for (i = 0; i < nr; i++)
515 nvmap_unpin(client, h[i]);
516}
517
518int nvmap_patch_word(struct nvmap_client *client,
519 struct nvmap_handle *patch,
520 u32 patch_offset, u32 patch_value)
521{
522 void *vaddr;
523 u32 *patch_addr;
524
525 vaddr = ion_map_kernel(client, patch);
526 patch_addr = vaddr + patch_offset;
527 __raw_writel(patch_value, patch_addr);
528 wmb();
529 ion_unmap_kernel(client, patch);
530 return 0;
531}
532
533struct nvmap_handle *nvmap_handle_get(struct nvmap_handle *h);
534struct nvmap_handle *nvmap_get_handle_id(struct nvmap_client *client,
535 unsigned long id)
536{
537 struct ion_handle *handle;
538
539 handle = (struct ion_handle *)nvmap_convert_handle_u2k(id);
540 pr_debug("id=0x%x, h=0x%x,c=0x%x",
541 (u32)id, (u32)handle, (u32)client);
542 nvmap_handle_get(handle);
543 return handle;
544}
545
546struct nvmap_handle_ref *nvmap_duplicate_handle_id(struct nvmap_client *client,
547 unsigned long id)
548{
549 struct ion_buffer *buffer;
550 struct ion_handle *handle;
551 struct ion_client *ion_client = client;
552
553 handle = (struct ion_handle *)nvmap_convert_handle_u2k(id);
554 pr_debug("id=0x%x, h=0x%x,c=0x%x",
555 (u32)id, (u32)handle, (u32)client);
556 buffer = handle->buffer;
557
558 handle = ion_handle_create(client, buffer);
559
560 mutex_lock(&ion_client->lock);
561 ion_handle_add(ion_client, handle);
562 mutex_unlock(&ion_client->lock);
563
564 pr_debug("dup id=0x%x, h=0x%x", (u32)id, (u32)handle);
565 return handle;
566}
567
568void _nvmap_handle_free(struct nvmap_handle *h)
569{
570 ion_handle_put(h);
571}
572
573struct nvmap_handle_ref *nvmap_alloc_iovm(struct nvmap_client *client,
574 size_t size, size_t align, unsigned int flags, unsigned int iova_start)
575{
576 struct ion_handle *h;
577
578 h = ion_alloc(client, size, align, 0xFF);
579 ion_remap_dma(client, h, iova_start);
580 return h;
581}
582
583void nvmap_free_iovm(struct nvmap_client *client, struct nvmap_handle_ref *r)
584{
585 ion_free(client, r);
586}
587
588struct nvmap_handle *nvmap_handle_get(struct nvmap_handle *h)
589{
590 ion_handle_get(h);
591 return h;
592}
593
594void nvmap_handle_put(struct nvmap_handle *h)
595{
596 ion_handle_put(h);
597}
598
599#endif