aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-05 20:18:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-05 20:18:44 -0400
commit1062ae4982cabbf60f89b4e069fbb7def7edc8f7 (patch)
tree01f6944b55d5b69615234f8c1f52b4e721f3d8e6
parent1a5fb64fee203f9f5a9274c67ddbb821a29f723f (diff)
parent644b4930bf7e2adeffbe842e1097f7933c6a9158 (diff)
Merge tag 'drm-forgot-about-tegra-for-v4.12-rc1' of git://people.freedesktop.org/~airlied/linux
Pull drm tegra updates from Dave Airlie: "I missed a pull request from Thierry, this stuff has been in linux-next for a while anyways. It does contain a branch from the iommu tree, but Thierry said it should be fine" * tag 'drm-forgot-about-tegra-for-v4.12-rc1' of git://people.freedesktop.org/~airlied/linux: gpu: host1x: Fix host1x driver shutdown gpu: host1x: Support module reset gpu: host1x: Sort includes alphabetically drm/tegra: Add VIC support dt-bindings: Add bindings for the Tegra VIC drm/tegra: Add falcon helper library drm/tegra: Add Tegra DRM allocation API drm/tegra: Add tiling FB modifiers drm/tegra: Don't leak kernel pointer to userspace drm/tegra: Protect IOMMU operations by mutex drm/tegra: Enable IOVA API when IOMMU support is enabled gpu: host1x: Add IOMMU support gpu: host1x: Fix potential out-of-bounds access iommu/iova: Fix compile error with CONFIG_IOMMU_IOVA=m iommu: Add dummy implementations for !IOMMU_IOVA MAINTAINERS: Add related headers to IOMMU section iommu/iova: Consolidate code for adding new node to iovad domain rbtree
-rw-r--r--Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt13
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/gpu/drm/tegra/Kconfig1
-rw-r--r--drivers/gpu/drm/tegra/Makefile4
-rw-r--r--drivers/gpu/drm/tegra/drm.c283
-rw-r--r--drivers/gpu/drm/tegra/drm.h15
-rw-r--r--drivers/gpu/drm/tegra/falcon.c259
-rw-r--r--drivers/gpu/drm/tegra/falcon.h127
-rw-r--r--drivers/gpu/drm/tegra/fb.c23
-rw-r--r--drivers/gpu/drm/tegra/gem.c12
-rw-r--r--drivers/gpu/drm/tegra/vic.c396
-rw-r--r--drivers/gpu/drm/tegra/vic.h31
-rw-r--r--drivers/gpu/host1x/bus.c68
-rw-r--r--drivers/gpu/host1x/cdma.c74
-rw-r--r--drivers/gpu/host1x/cdma.h6
-rw-r--r--drivers/gpu/host1x/dev.c76
-rw-r--r--drivers/gpu/host1x/dev.h14
-rw-r--r--drivers/gpu/host1x/hw/cdma_hw.c16
-rw-r--r--drivers/gpu/host1x/job.c72
-rw-r--r--drivers/gpu/host1x/job.h1
-rw-r--r--drivers/gpu/host1x/syncpt.c2
-rw-r--r--drivers/iommu/iova.c87
-rw-r--r--include/linux/host1x.h1
-rw-r--r--include/linux/iova.h91
-rw-r--r--include/uapi/drm/drm_fourcc.h45
25 files changed, 1517 insertions, 202 deletions
diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
index 0fad7ed2ea19..74e1e8add5a1 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
@@ -249,6 +249,19 @@ of the following host1x client modules:
249 See ../pinctrl/nvidia,tegra124-dpaux-padctl.txt for information 249 See ../pinctrl/nvidia,tegra124-dpaux-padctl.txt for information
250 regarding the DPAUX pad controller bindings. 250 regarding the DPAUX pad controller bindings.
251 251
252- vic: Video Image Compositor
253 - compatible : "nvidia,tegra<chip>-vic"
254 - reg: Physical base address and length of the controller's registers.
255 - interrupts: The interrupt outputs from the controller.
256 - clocks: Must contain an entry for each entry in clock-names.
257 See ../clocks/clock-bindings.txt for details.
258 - clock-names: Must include the following entries:
259 - vic: clock input for the VIC hardware
260 - resets: Must contain an entry for each entry in reset-names.
261 See ../reset/reset.txt for details.
262 - reset-names: Must include the following entries:
263 - vic
264
252Example: 265Example:
253 266
254/ { 267/ {
diff --git a/MAINTAINERS b/MAINTAINERS
index ac0ce262150c..8944b472b90f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6843,6 +6843,8 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
6843S: Maintained 6843S: Maintained
6844F: Documentation/devicetree/bindings/iommu/ 6844F: Documentation/devicetree/bindings/iommu/
6845F: drivers/iommu/ 6845F: drivers/iommu/
6846F: include/linux/iommu.h
6847F: include/linux/iova.h
6846 6848
6847IP MASQUERADING 6849IP MASQUERADING
6848M: Juanjo Ciarlante <jjciarla@raiz.uncu.edu.ar> 6850M: Juanjo Ciarlante <jjciarla@raiz.uncu.edu.ar>
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
index bbf5a4b7e0b6..2db29d67193d 100644
--- a/drivers/gpu/drm/tegra/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -7,6 +7,7 @@ config DRM_TEGRA
7 select DRM_MIPI_DSI 7 select DRM_MIPI_DSI
8 select DRM_PANEL 8 select DRM_PANEL
9 select TEGRA_HOST1X 9 select TEGRA_HOST1X
10 select IOMMU_IOVA if IOMMU_SUPPORT
10 help 11 help
11 Choose this option if you have an NVIDIA Tegra SoC. 12 Choose this option if you have an NVIDIA Tegra SoC.
12 13
diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
index 2c66a8db9da4..6af3a9ad6565 100644
--- a/drivers/gpu/drm/tegra/Makefile
+++ b/drivers/gpu/drm/tegra/Makefile
@@ -13,6 +13,8 @@ tegra-drm-y := \
13 sor.o \ 13 sor.o \
14 dpaux.o \ 14 dpaux.o \
15 gr2d.o \ 15 gr2d.o \
16 gr3d.o 16 gr3d.o \
17 falcon.o \
18 vic.o
17 19
18obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o 20obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index dba4e090d3df..9a1e34e48f64 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1,13 +1,15 @@
1/* 1/*
2 * Copyright (C) 2012 Avionic Design GmbH 2 * Copyright (C) 2012 Avionic Design GmbH
3 * Copyright (C) 2012-2013 NVIDIA CORPORATION. All rights reserved. 3 * Copyright (C) 2012-2016 NVIDIA CORPORATION. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 */ 8 */
9 9
10#include <linux/bitops.h>
10#include <linux/host1x.h> 11#include <linux/host1x.h>
12#include <linux/idr.h>
11#include <linux/iommu.h> 13#include <linux/iommu.h>
12 14
13#include <drm/drm_atomic.h> 15#include <drm/drm_atomic.h>
@@ -23,8 +25,11 @@
23#define DRIVER_MINOR 0 25#define DRIVER_MINOR 0
24#define DRIVER_PATCHLEVEL 0 26#define DRIVER_PATCHLEVEL 0
25 27
28#define CARVEOUT_SZ SZ_64M
29
26struct tegra_drm_file { 30struct tegra_drm_file {
27 struct list_head contexts; 31 struct idr contexts;
32 struct mutex lock;
28}; 33};
29 34
30static void tegra_atomic_schedule(struct tegra_drm *tegra, 35static void tegra_atomic_schedule(struct tegra_drm *tegra,
@@ -126,8 +131,9 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
126 return -ENOMEM; 131 return -ENOMEM;
127 132
128 if (iommu_present(&platform_bus_type)) { 133 if (iommu_present(&platform_bus_type)) {
134 u64 carveout_start, carveout_end, gem_start, gem_end;
129 struct iommu_domain_geometry *geometry; 135 struct iommu_domain_geometry *geometry;
130 u64 start, end; 136 unsigned long order;
131 137
132 tegra->domain = iommu_domain_alloc(&platform_bus_type); 138 tegra->domain = iommu_domain_alloc(&platform_bus_type);
133 if (!tegra->domain) { 139 if (!tegra->domain) {
@@ -136,12 +142,26 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
136 } 142 }
137 143
138 geometry = &tegra->domain->geometry; 144 geometry = &tegra->domain->geometry;
139 start = geometry->aperture_start; 145 gem_start = geometry->aperture_start;
140 end = geometry->aperture_end; 146 gem_end = geometry->aperture_end - CARVEOUT_SZ;
141 147 carveout_start = gem_end + 1;
142 DRM_DEBUG_DRIVER("IOMMU aperture initialized (%#llx-%#llx)\n", 148 carveout_end = geometry->aperture_end;
143 start, end); 149
144 drm_mm_init(&tegra->mm, start, end - start + 1); 150 order = __ffs(tegra->domain->pgsize_bitmap);
151 init_iova_domain(&tegra->carveout.domain, 1UL << order,
152 carveout_start >> order,
153 carveout_end >> order);
154
155 tegra->carveout.shift = iova_shift(&tegra->carveout.domain);
156 tegra->carveout.limit = carveout_end >> tegra->carveout.shift;
157
158 drm_mm_init(&tegra->mm, gem_start, gem_end - gem_start + 1);
159 mutex_init(&tegra->mm_lock);
160
161 DRM_DEBUG("IOMMU apertures:\n");
162 DRM_DEBUG(" GEM: %#llx-%#llx\n", gem_start, gem_end);
163 DRM_DEBUG(" Carveout: %#llx-%#llx\n", carveout_start,
164 carveout_end);
145 } 165 }
146 166
147 mutex_init(&tegra->clients_lock); 167 mutex_init(&tegra->clients_lock);
@@ -161,6 +181,8 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
161 drm->mode_config.max_width = 4096; 181 drm->mode_config.max_width = 4096;
162 drm->mode_config.max_height = 4096; 182 drm->mode_config.max_height = 4096;
163 183
184 drm->mode_config.allow_fb_modifiers = true;
185
164 drm->mode_config.funcs = &tegra_drm_mode_funcs; 186 drm->mode_config.funcs = &tegra_drm_mode_funcs;
165 187
166 err = tegra_drm_fb_prepare(drm); 188 err = tegra_drm_fb_prepare(drm);
@@ -208,6 +230,8 @@ config:
208 if (tegra->domain) { 230 if (tegra->domain) {
209 iommu_domain_free(tegra->domain); 231 iommu_domain_free(tegra->domain);
210 drm_mm_takedown(&tegra->mm); 232 drm_mm_takedown(&tegra->mm);
233 mutex_destroy(&tegra->mm_lock);
234 put_iova_domain(&tegra->carveout.domain);
211 } 235 }
212free: 236free:
213 kfree(tegra); 237 kfree(tegra);
@@ -232,6 +256,8 @@ static void tegra_drm_unload(struct drm_device *drm)
232 if (tegra->domain) { 256 if (tegra->domain) {
233 iommu_domain_free(tegra->domain); 257 iommu_domain_free(tegra->domain);
234 drm_mm_takedown(&tegra->mm); 258 drm_mm_takedown(&tegra->mm);
259 mutex_destroy(&tegra->mm_lock);
260 put_iova_domain(&tegra->carveout.domain);
235 } 261 }
236 262
237 kfree(tegra); 263 kfree(tegra);
@@ -245,7 +271,8 @@ static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
245 if (!fpriv) 271 if (!fpriv)
246 return -ENOMEM; 272 return -ENOMEM;
247 273
248 INIT_LIST_HEAD(&fpriv->contexts); 274 idr_init(&fpriv->contexts);
275 mutex_init(&fpriv->lock);
249 filp->driver_priv = fpriv; 276 filp->driver_priv = fpriv;
250 277
251 return 0; 278 return 0;
@@ -424,21 +451,16 @@ fail:
424 451
425 452
426#ifdef CONFIG_DRM_TEGRA_STAGING 453#ifdef CONFIG_DRM_TEGRA_STAGING
427static struct tegra_drm_context *tegra_drm_get_context(__u64 context) 454static struct tegra_drm_context *
428{ 455tegra_drm_file_get_context(struct tegra_drm_file *file, u32 id)
429 return (struct tegra_drm_context *)(uintptr_t)context;
430}
431
432static bool tegra_drm_file_owns_context(struct tegra_drm_file *file,
433 struct tegra_drm_context *context)
434{ 456{
435 struct tegra_drm_context *ctx; 457 struct tegra_drm_context *context;
436 458
437 list_for_each_entry(ctx, &file->contexts, list) 459 mutex_lock(&file->lock);
438 if (ctx == context) 460 context = idr_find(&file->contexts, id);
439 return true; 461 mutex_unlock(&file->lock);
440 462
441 return false; 463 return context;
442} 464}
443 465
444static int tegra_gem_create(struct drm_device *drm, void *data, 466static int tegra_gem_create(struct drm_device *drm, void *data,
@@ -519,6 +541,28 @@ static int tegra_syncpt_wait(struct drm_device *drm, void *data,
519 &args->value); 541 &args->value);
520} 542}
521 543
544static int tegra_client_open(struct tegra_drm_file *fpriv,
545 struct tegra_drm_client *client,
546 struct tegra_drm_context *context)
547{
548 int err;
549
550 err = client->ops->open_channel(client, context);
551 if (err < 0)
552 return err;
553
554 err = idr_alloc(&fpriv->contexts, context, 0, 0, GFP_KERNEL);
555 if (err < 0) {
556 client->ops->close_channel(context);
557 return err;
558 }
559
560 context->client = client;
561 context->id = err;
562
563 return 0;
564}
565
522static int tegra_open_channel(struct drm_device *drm, void *data, 566static int tegra_open_channel(struct drm_device *drm, void *data,
523 struct drm_file *file) 567 struct drm_file *file)
524{ 568{
@@ -533,19 +577,22 @@ static int tegra_open_channel(struct drm_device *drm, void *data,
533 if (!context) 577 if (!context)
534 return -ENOMEM; 578 return -ENOMEM;
535 579
580 mutex_lock(&fpriv->lock);
581
536 list_for_each_entry(client, &tegra->clients, list) 582 list_for_each_entry(client, &tegra->clients, list)
537 if (client->base.class == args->client) { 583 if (client->base.class == args->client) {
538 err = client->ops->open_channel(client, context); 584 err = tegra_client_open(fpriv, client, context);
539 if (err) 585 if (err < 0)
540 break; 586 break;
541 587
542 list_add(&context->list, &fpriv->contexts); 588 args->context = context->id;
543 args->context = (uintptr_t)context; 589 break;
544 context->client = client;
545 return 0;
546 } 590 }
547 591
548 kfree(context); 592 if (err < 0)
593 kfree(context);
594
595 mutex_unlock(&fpriv->lock);
549 return err; 596 return err;
550} 597}
551 598
@@ -555,16 +602,22 @@ static int tegra_close_channel(struct drm_device *drm, void *data,
555 struct tegra_drm_file *fpriv = file->driver_priv; 602 struct tegra_drm_file *fpriv = file->driver_priv;
556 struct drm_tegra_close_channel *args = data; 603 struct drm_tegra_close_channel *args = data;
557 struct tegra_drm_context *context; 604 struct tegra_drm_context *context;
605 int err = 0;
558 606
559 context = tegra_drm_get_context(args->context); 607 mutex_lock(&fpriv->lock);
560 608
561 if (!tegra_drm_file_owns_context(fpriv, context)) 609 context = tegra_drm_file_get_context(fpriv, args->context);
562 return -EINVAL; 610 if (!context) {
611 err = -EINVAL;
612 goto unlock;
613 }
563 614
564 list_del(&context->list); 615 idr_remove(&fpriv->contexts, context->id);
565 tegra_drm_context_free(context); 616 tegra_drm_context_free(context);
566 617
567 return 0; 618unlock:
619 mutex_unlock(&fpriv->lock);
620 return err;
568} 621}
569 622
570static int tegra_get_syncpt(struct drm_device *drm, void *data, 623static int tegra_get_syncpt(struct drm_device *drm, void *data,
@@ -574,19 +627,27 @@ static int tegra_get_syncpt(struct drm_device *drm, void *data,
574 struct drm_tegra_get_syncpt *args = data; 627 struct drm_tegra_get_syncpt *args = data;
575 struct tegra_drm_context *context; 628 struct tegra_drm_context *context;
576 struct host1x_syncpt *syncpt; 629 struct host1x_syncpt *syncpt;
630 int err = 0;
577 631
578 context = tegra_drm_get_context(args->context); 632 mutex_lock(&fpriv->lock);
579 633
580 if (!tegra_drm_file_owns_context(fpriv, context)) 634 context = tegra_drm_file_get_context(fpriv, args->context);
581 return -ENODEV; 635 if (!context) {
636 err = -ENODEV;
637 goto unlock;
638 }
582 639
583 if (args->index >= context->client->base.num_syncpts) 640 if (args->index >= context->client->base.num_syncpts) {
584 return -EINVAL; 641 err = -EINVAL;
642 goto unlock;
643 }
585 644
586 syncpt = context->client->base.syncpts[args->index]; 645 syncpt = context->client->base.syncpts[args->index];
587 args->id = host1x_syncpt_id(syncpt); 646 args->id = host1x_syncpt_id(syncpt);
588 647
589 return 0; 648unlock:
649 mutex_unlock(&fpriv->lock);
650 return err;
590} 651}
591 652
592static int tegra_submit(struct drm_device *drm, void *data, 653static int tegra_submit(struct drm_device *drm, void *data,
@@ -595,13 +656,21 @@ static int tegra_submit(struct drm_device *drm, void *data,
595 struct tegra_drm_file *fpriv = file->driver_priv; 656 struct tegra_drm_file *fpriv = file->driver_priv;
596 struct drm_tegra_submit *args = data; 657 struct drm_tegra_submit *args = data;
597 struct tegra_drm_context *context; 658 struct tegra_drm_context *context;
659 int err;
598 660
599 context = tegra_drm_get_context(args->context); 661 mutex_lock(&fpriv->lock);
662
663 context = tegra_drm_file_get_context(fpriv, args->context);
664 if (!context) {
665 err = -ENODEV;
666 goto unlock;
667 }
600 668
601 if (!tegra_drm_file_owns_context(fpriv, context)) 669 err = context->client->ops->submit(context, args, drm, file);
602 return -ENODEV;
603 670
604 return context->client->ops->submit(context, args, drm, file); 671unlock:
672 mutex_unlock(&fpriv->lock);
673 return err;
605} 674}
606 675
607static int tegra_get_syncpt_base(struct drm_device *drm, void *data, 676static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
@@ -612,24 +681,34 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
612 struct tegra_drm_context *context; 681 struct tegra_drm_context *context;
613 struct host1x_syncpt_base *base; 682 struct host1x_syncpt_base *base;
614 struct host1x_syncpt *syncpt; 683 struct host1x_syncpt *syncpt;
684 int err = 0;
615 685
616 context = tegra_drm_get_context(args->context); 686 mutex_lock(&fpriv->lock);
617 687
618 if (!tegra_drm_file_owns_context(fpriv, context)) 688 context = tegra_drm_file_get_context(fpriv, args->context);
619 return -ENODEV; 689 if (!context) {
690 err = -ENODEV;
691 goto unlock;
692 }
620 693
621 if (args->syncpt >= context->client->base.num_syncpts) 694 if (args->syncpt >= context->client->base.num_syncpts) {
622 return -EINVAL; 695 err = -EINVAL;
696 goto unlock;
697 }
623 698
624 syncpt = context->client->base.syncpts[args->syncpt]; 699 syncpt = context->client->base.syncpts[args->syncpt];
625 700
626 base = host1x_syncpt_get_base(syncpt); 701 base = host1x_syncpt_get_base(syncpt);
627 if (!base) 702 if (!base) {
628 return -ENXIO; 703 err = -ENXIO;
704 goto unlock;
705 }
629 706
630 args->id = host1x_syncpt_base_id(base); 707 args->id = host1x_syncpt_base_id(base);
631 708
632 return 0; 709unlock:
710 mutex_unlock(&fpriv->lock);
711 return err;
633} 712}
634 713
635static int tegra_gem_set_tiling(struct drm_device *drm, void *data, 714static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
@@ -804,14 +883,25 @@ static const struct file_operations tegra_drm_fops = {
804 .llseek = noop_llseek, 883 .llseek = noop_llseek,
805}; 884};
806 885
886static int tegra_drm_context_cleanup(int id, void *p, void *data)
887{
888 struct tegra_drm_context *context = p;
889
890 tegra_drm_context_free(context);
891
892 return 0;
893}
894
807static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file) 895static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file)
808{ 896{
809 struct tegra_drm_file *fpriv = file->driver_priv; 897 struct tegra_drm_file *fpriv = file->driver_priv;
810 struct tegra_drm_context *context, *tmp;
811 898
812 list_for_each_entry_safe(context, tmp, &fpriv->contexts, list) 899 mutex_lock(&fpriv->lock);
813 tegra_drm_context_free(context); 900 idr_for_each(&fpriv->contexts, tegra_drm_context_cleanup, NULL);
901 mutex_unlock(&fpriv->lock);
814 902
903 idr_destroy(&fpriv->contexts);
904 mutex_destroy(&fpriv->lock);
815 kfree(fpriv); 905 kfree(fpriv);
816} 906}
817 907
@@ -844,7 +934,9 @@ static int tegra_debugfs_iova(struct seq_file *s, void *data)
844 struct tegra_drm *tegra = drm->dev_private; 934 struct tegra_drm *tegra = drm->dev_private;
845 struct drm_printer p = drm_seq_file_printer(s); 935 struct drm_printer p = drm_seq_file_printer(s);
846 936
937 mutex_lock(&tegra->mm_lock);
847 drm_mm_print(&tegra->mm, &p); 938 drm_mm_print(&tegra->mm, &p);
939 mutex_unlock(&tegra->mm_lock);
848 940
849 return 0; 941 return 0;
850} 942}
@@ -919,6 +1011,84 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
919 return 0; 1011 return 0;
920} 1012}
921 1013
1014void *tegra_drm_alloc(struct tegra_drm *tegra, size_t size,
1015 dma_addr_t *dma)
1016{
1017 struct iova *alloc;
1018 void *virt;
1019 gfp_t gfp;
1020 int err;
1021
1022 if (tegra->domain)
1023 size = iova_align(&tegra->carveout.domain, size);
1024 else
1025 size = PAGE_ALIGN(size);
1026
1027 gfp = GFP_KERNEL | __GFP_ZERO;
1028 if (!tegra->domain) {
1029 /*
1030 * Many units only support 32-bit addresses, even on 64-bit
1031 * SoCs. If there is no IOMMU to translate into a 32-bit IO
1032 * virtual address space, force allocations to be in the
1033 * lower 32-bit range.
1034 */
1035 gfp |= GFP_DMA;
1036 }
1037
1038 virt = (void *)__get_free_pages(gfp, get_order(size));
1039 if (!virt)
1040 return ERR_PTR(-ENOMEM);
1041
1042 if (!tegra->domain) {
1043 /*
1044 * If IOMMU is disabled, devices address physical memory
1045 * directly.
1046 */
1047 *dma = virt_to_phys(virt);
1048 return virt;
1049 }
1050
1051 alloc = alloc_iova(&tegra->carveout.domain,
1052 size >> tegra->carveout.shift,
1053 tegra->carveout.limit, true);
1054 if (!alloc) {
1055 err = -EBUSY;
1056 goto free_pages;
1057 }
1058
1059 *dma = iova_dma_addr(&tegra->carveout.domain, alloc);
1060 err = iommu_map(tegra->domain, *dma, virt_to_phys(virt),
1061 size, IOMMU_READ | IOMMU_WRITE);
1062 if (err < 0)
1063 goto free_iova;
1064
1065 return virt;
1066
1067free_iova:
1068 __free_iova(&tegra->carveout.domain, alloc);
1069free_pages:
1070 free_pages((unsigned long)virt, get_order(size));
1071
1072 return ERR_PTR(err);
1073}
1074
1075void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt,
1076 dma_addr_t dma)
1077{
1078 if (tegra->domain)
1079 size = iova_align(&tegra->carveout.domain, size);
1080 else
1081 size = PAGE_ALIGN(size);
1082
1083 if (tegra->domain) {
1084 iommu_unmap(tegra->domain, dma, size);
1085 free_iova(&tegra->carveout.domain,
1086 iova_pfn(&tegra->carveout.domain, dma));
1087 }
1088
1089 free_pages((unsigned long)virt, get_order(size));
1090}
1091
922static int host1x_drm_probe(struct host1x_device *dev) 1092static int host1x_drm_probe(struct host1x_device *dev)
923{ 1093{
924 struct drm_driver *driver = &tegra_drm_driver; 1094 struct drm_driver *driver = &tegra_drm_driver;
@@ -1003,11 +1173,13 @@ static const struct of_device_id host1x_drm_subdevs[] = {
1003 { .compatible = "nvidia,tegra124-sor", }, 1173 { .compatible = "nvidia,tegra124-sor", },
1004 { .compatible = "nvidia,tegra124-hdmi", }, 1174 { .compatible = "nvidia,tegra124-hdmi", },
1005 { .compatible = "nvidia,tegra124-dsi", }, 1175 { .compatible = "nvidia,tegra124-dsi", },
1176 { .compatible = "nvidia,tegra124-vic", },
1006 { .compatible = "nvidia,tegra132-dsi", }, 1177 { .compatible = "nvidia,tegra132-dsi", },
1007 { .compatible = "nvidia,tegra210-dc", }, 1178 { .compatible = "nvidia,tegra210-dc", },
1008 { .compatible = "nvidia,tegra210-dsi", }, 1179 { .compatible = "nvidia,tegra210-dsi", },
1009 { .compatible = "nvidia,tegra210-sor", }, 1180 { .compatible = "nvidia,tegra210-sor", },
1010 { .compatible = "nvidia,tegra210-sor1", }, 1181 { .compatible = "nvidia,tegra210-sor1", },
1182 { .compatible = "nvidia,tegra210-vic", },
1011 { /* sentinel */ } 1183 { /* sentinel */ }
1012}; 1184};
1013 1185
@@ -1029,6 +1201,7 @@ static struct platform_driver * const drivers[] = {
1029 &tegra_sor_driver, 1201 &tegra_sor_driver,
1030 &tegra_gr2d_driver, 1202 &tegra_gr2d_driver,
1031 &tegra_gr3d_driver, 1203 &tegra_gr3d_driver,
1204 &tegra_vic_driver,
1032}; 1205};
1033 1206
1034static int __init host1x_drm_init(void) 1207static int __init host1x_drm_init(void)
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 5747accb2271..85aa2e3d9d4e 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -12,6 +12,7 @@
12 12
13#include <uapi/drm/tegra_drm.h> 13#include <uapi/drm/tegra_drm.h>
14#include <linux/host1x.h> 14#include <linux/host1x.h>
15#include <linux/iova.h>
15#include <linux/of_gpio.h> 16#include <linux/of_gpio.h>
16 17
17#include <drm/drmP.h> 18#include <drm/drmP.h>
@@ -42,8 +43,15 @@ struct tegra_drm {
42 struct drm_device *drm; 43 struct drm_device *drm;
43 44
44 struct iommu_domain *domain; 45 struct iommu_domain *domain;
46 struct mutex mm_lock;
45 struct drm_mm mm; 47 struct drm_mm mm;
46 48
49 struct {
50 struct iova_domain domain;
51 unsigned long shift;
52 unsigned long limit;
53 } carveout;
54
47 struct mutex clients_lock; 55 struct mutex clients_lock;
48 struct list_head clients; 56 struct list_head clients;
49 57
@@ -67,7 +75,7 @@ struct tegra_drm_client;
67struct tegra_drm_context { 75struct tegra_drm_context {
68 struct tegra_drm_client *client; 76 struct tegra_drm_client *client;
69 struct host1x_channel *channel; 77 struct host1x_channel *channel;
70 struct list_head list; 78 unsigned int id;
71}; 79};
72 80
73struct tegra_drm_client_ops { 81struct tegra_drm_client_ops {
@@ -105,6 +113,10 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
105int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm); 113int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
106int tegra_drm_exit(struct tegra_drm *tegra); 114int tegra_drm_exit(struct tegra_drm *tegra);
107 115
116void *tegra_drm_alloc(struct tegra_drm *tegra, size_t size, dma_addr_t *iova);
117void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt,
118 dma_addr_t iova);
119
108struct tegra_dc_soc_info; 120struct tegra_dc_soc_info;
109struct tegra_output; 121struct tegra_output;
110 122
@@ -283,5 +295,6 @@ extern struct platform_driver tegra_dpaux_driver;
283extern struct platform_driver tegra_sor_driver; 295extern struct platform_driver tegra_sor_driver;
284extern struct platform_driver tegra_gr2d_driver; 296extern struct platform_driver tegra_gr2d_driver;
285extern struct platform_driver tegra_gr3d_driver; 297extern struct platform_driver tegra_gr3d_driver;
298extern struct platform_driver tegra_vic_driver;
286 299
287#endif /* HOST1X_DRM_H */ 300#endif /* HOST1X_DRM_H */
diff --git a/drivers/gpu/drm/tegra/falcon.c b/drivers/gpu/drm/tegra/falcon.c
new file mode 100644
index 000000000000..f685e72949d1
--- /dev/null
+++ b/drivers/gpu/drm/tegra/falcon.c
@@ -0,0 +1,259 @@
1/*
2 * Copyright (c) 2015, NVIDIA Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/platform_device.h>
10#include <linux/dma-mapping.h>
11#include <linux/firmware.h>
12#include <linux/pci_ids.h>
13#include <linux/iopoll.h>
14
15#include "falcon.h"
16#include "drm.h"
17
18enum falcon_memory {
19 FALCON_MEMORY_IMEM,
20 FALCON_MEMORY_DATA,
21};
22
23static void falcon_writel(struct falcon *falcon, u32 value, u32 offset)
24{
25 writel(value, falcon->regs + offset);
26}
27
28int falcon_wait_idle(struct falcon *falcon)
29{
30 u32 value;
31
32 return readl_poll_timeout(falcon->regs + FALCON_IDLESTATE, value,
33 (value == 0), 10, 100000);
34}
35
36static int falcon_dma_wait_idle(struct falcon *falcon)
37{
38 u32 value;
39
40 return readl_poll_timeout(falcon->regs + FALCON_DMATRFCMD, value,
41 (value & FALCON_DMATRFCMD_IDLE), 10, 100000);
42}
43
44static int falcon_copy_chunk(struct falcon *falcon,
45 phys_addr_t base,
46 unsigned long offset,
47 enum falcon_memory target)
48{
49 u32 cmd = FALCON_DMATRFCMD_SIZE_256B;
50
51 if (target == FALCON_MEMORY_IMEM)
52 cmd |= FALCON_DMATRFCMD_IMEM;
53
54 falcon_writel(falcon, offset, FALCON_DMATRFMOFFS);
55 falcon_writel(falcon, base, FALCON_DMATRFFBOFFS);
56 falcon_writel(falcon, cmd, FALCON_DMATRFCMD);
57
58 return falcon_dma_wait_idle(falcon);
59}
60
61static void falcon_copy_firmware_image(struct falcon *falcon,
62 const struct firmware *firmware)
63{
64 u32 *firmware_vaddr = falcon->firmware.vaddr;
65 dma_addr_t daddr;
66 size_t i;
67 int err;
68
69 /* copy the whole thing taking into account endianness */
70 for (i = 0; i < firmware->size / sizeof(u32); i++)
71 firmware_vaddr[i] = le32_to_cpu(((u32 *)firmware->data)[i]);
72
73 /* ensure that caches are flushed and falcon can see the firmware */
74 daddr = dma_map_single(falcon->dev, firmware_vaddr,
75 falcon->firmware.size, DMA_TO_DEVICE);
76 err = dma_mapping_error(falcon->dev, daddr);
77 if (err) {
78 dev_err(falcon->dev, "failed to map firmware: %d\n", err);
79 return;
80 }
81 dma_sync_single_for_device(falcon->dev, daddr,
82 falcon->firmware.size, DMA_TO_DEVICE);
83 dma_unmap_single(falcon->dev, daddr, falcon->firmware.size,
84 DMA_TO_DEVICE);
85}
86
87static int falcon_parse_firmware_image(struct falcon *falcon)
88{
89 struct falcon_fw_bin_header_v1 *bin = (void *)falcon->firmware.vaddr;
90 struct falcon_fw_os_header_v1 *os;
91
92 /* endian problems would show up right here */
93 if (bin->magic != PCI_VENDOR_ID_NVIDIA) {
94 dev_err(falcon->dev, "incorrect firmware magic\n");
95 return -EINVAL;
96 }
97
98 /* currently only version 1 is supported */
99 if (bin->version != 1) {
100 dev_err(falcon->dev, "unsupported firmware version\n");
101 return -EINVAL;
102 }
103
104 /* check that the firmware size is consistent */
105 if (bin->size > falcon->firmware.size) {
106 dev_err(falcon->dev, "firmware image size inconsistency\n");
107 return -EINVAL;
108 }
109
110 os = falcon->firmware.vaddr + bin->os_header_offset;
111
112 falcon->firmware.bin_data.size = bin->os_size;
113 falcon->firmware.bin_data.offset = bin->os_data_offset;
114 falcon->firmware.code.offset = os->code_offset;
115 falcon->firmware.code.size = os->code_size;
116 falcon->firmware.data.offset = os->data_offset;
117 falcon->firmware.data.size = os->data_size;
118
119 return 0;
120}
121
122int falcon_read_firmware(struct falcon *falcon, const char *name)
123{
124 int err;
125
126 /* request_firmware prints error if it fails */
127 err = request_firmware(&falcon->firmware.firmware, name, falcon->dev);
128 if (err < 0)
129 return err;
130
131 return 0;
132}
133
134int falcon_load_firmware(struct falcon *falcon)
135{
136 const struct firmware *firmware = falcon->firmware.firmware;
137 int err;
138
139 falcon->firmware.size = firmware->size;
140
141 /* allocate iova space for the firmware */
142 falcon->firmware.vaddr = falcon->ops->alloc(falcon, firmware->size,
143 &falcon->firmware.paddr);
144 if (!falcon->firmware.vaddr) {
145 dev_err(falcon->dev, "dma memory mapping failed\n");
146 return -ENOMEM;
147 }
148
149 /* copy firmware image into local area. this also ensures endianness */
150 falcon_copy_firmware_image(falcon, firmware);
151
152 /* parse the image data */
153 err = falcon_parse_firmware_image(falcon);
154 if (err < 0) {
155 dev_err(falcon->dev, "failed to parse firmware image\n");
156 goto err_setup_firmware_image;
157 }
158
159 release_firmware(firmware);
160 falcon->firmware.firmware = NULL;
161
162 return 0;
163
164err_setup_firmware_image:
165 falcon->ops->free(falcon, falcon->firmware.size,
166 falcon->firmware.paddr, falcon->firmware.vaddr);
167
168 return err;
169}
170
171int falcon_init(struct falcon *falcon)
172{
173 /* check mandatory ops */
174 if (!falcon->ops || !falcon->ops->alloc || !falcon->ops->free)
175 return -EINVAL;
176
177 falcon->firmware.vaddr = NULL;
178
179 return 0;
180}
181
182void falcon_exit(struct falcon *falcon)
183{
184 if (falcon->firmware.firmware) {
185 release_firmware(falcon->firmware.firmware);
186 falcon->firmware.firmware = NULL;
187 }
188
189 if (falcon->firmware.vaddr) {
190 falcon->ops->free(falcon, falcon->firmware.size,
191 falcon->firmware.paddr,
192 falcon->firmware.vaddr);
193 falcon->firmware.vaddr = NULL;
194 }
195}
196
197int falcon_boot(struct falcon *falcon)
198{
199 unsigned long offset;
200 int err;
201
202 if (!falcon->firmware.vaddr)
203 return -EINVAL;
204
205 falcon_writel(falcon, 0, FALCON_DMACTL);
206
207 /* setup the address of the binary data so Falcon can access it later */
208 falcon_writel(falcon, (falcon->firmware.paddr +
209 falcon->firmware.bin_data.offset) >> 8,
210 FALCON_DMATRFBASE);
211
212 /* copy the data segment into Falcon internal memory */
213 for (offset = 0; offset < falcon->firmware.data.size; offset += 256)
214 falcon_copy_chunk(falcon,
215 falcon->firmware.data.offset + offset,
216 offset, FALCON_MEMORY_DATA);
217
218 /* copy the first code segment into Falcon internal memory */
219 falcon_copy_chunk(falcon, falcon->firmware.code.offset,
220 0, FALCON_MEMORY_IMEM);
221
222 /* setup falcon interrupts */
223 falcon_writel(falcon, FALCON_IRQMSET_EXT(0xff) |
224 FALCON_IRQMSET_SWGEN1 |
225 FALCON_IRQMSET_SWGEN0 |
226 FALCON_IRQMSET_EXTERR |
227 FALCON_IRQMSET_HALT |
228 FALCON_IRQMSET_WDTMR,
229 FALCON_IRQMSET);
230 falcon_writel(falcon, FALCON_IRQDEST_EXT(0xff) |
231 FALCON_IRQDEST_SWGEN1 |
232 FALCON_IRQDEST_SWGEN0 |
233 FALCON_IRQDEST_EXTERR |
234 FALCON_IRQDEST_HALT,
235 FALCON_IRQDEST);
236
237 /* enable interface */
238 falcon_writel(falcon, FALCON_ITFEN_MTHDEN |
239 FALCON_ITFEN_CTXEN,
240 FALCON_ITFEN);
241
242 /* boot falcon */
243 falcon_writel(falcon, 0x00000000, FALCON_BOOTVEC);
244 falcon_writel(falcon, FALCON_CPUCTL_STARTCPU, FALCON_CPUCTL);
245
246 err = falcon_wait_idle(falcon);
247 if (err < 0) {
248 dev_err(falcon->dev, "Falcon boot failed due to timeout\n");
249 return err;
250 }
251
252 return 0;
253}
254
255void falcon_execute_method(struct falcon *falcon, u32 method, u32 data)
256{
257 falcon_writel(falcon, method >> 2, FALCON_UCLASS_METHOD_OFFSET);
258 falcon_writel(falcon, data, FALCON_UCLASS_METHOD_DATA);
259}
diff --git a/drivers/gpu/drm/tegra/falcon.h b/drivers/gpu/drm/tegra/falcon.h
new file mode 100644
index 000000000000..4504ed5a199e
--- /dev/null
+++ b/drivers/gpu/drm/tegra/falcon.h
@@ -0,0 +1,127 @@
1/*
2 * Copyright (c) 2015, NVIDIA Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _FALCON_H_
10#define _FALCON_H_
11
12#include <linux/types.h>
13
14#define FALCON_UCLASS_METHOD_OFFSET 0x00000040
15
16#define FALCON_UCLASS_METHOD_DATA 0x00000044
17
18#define FALCON_IRQMSET 0x00001010
19#define FALCON_IRQMSET_WDTMR (1 << 1)
20#define FALCON_IRQMSET_HALT (1 << 4)
21#define FALCON_IRQMSET_EXTERR (1 << 5)
22#define FALCON_IRQMSET_SWGEN0 (1 << 6)
23#define FALCON_IRQMSET_SWGEN1 (1 << 7)
24#define FALCON_IRQMSET_EXT(v) (((v) & 0xff) << 8)
25
26#define FALCON_IRQDEST 0x0000101c
27#define FALCON_IRQDEST_HALT (1 << 4)
28#define FALCON_IRQDEST_EXTERR (1 << 5)
29#define FALCON_IRQDEST_SWGEN0 (1 << 6)
30#define FALCON_IRQDEST_SWGEN1 (1 << 7)
31#define FALCON_IRQDEST_EXT(v) (((v) & 0xff) << 8)
32
33#define FALCON_ITFEN 0x00001048
34#define FALCON_ITFEN_CTXEN (1 << 0)
35#define FALCON_ITFEN_MTHDEN (1 << 1)
36
37#define FALCON_IDLESTATE 0x0000104c
38
39#define FALCON_CPUCTL 0x00001100
40#define FALCON_CPUCTL_STARTCPU (1 << 1)
41
42#define FALCON_BOOTVEC 0x00001104
43
44#define FALCON_DMACTL 0x0000110c
45#define FALCON_DMACTL_DMEM_SCRUBBING (1 << 1)
46#define FALCON_DMACTL_IMEM_SCRUBBING (1 << 2)
47
48#define FALCON_DMATRFBASE 0x00001110
49
50#define FALCON_DMATRFMOFFS 0x00001114
51
52#define FALCON_DMATRFCMD 0x00001118
53#define FALCON_DMATRFCMD_IDLE (1 << 1)
54#define FALCON_DMATRFCMD_IMEM (1 << 4)
55#define FALCON_DMATRFCMD_SIZE_256B (6 << 8)
56
57#define FALCON_DMATRFFBOFFS 0x0000111c
58
59struct falcon_fw_bin_header_v1 {
60 u32 magic; /* 0x10de */
61 u32 version; /* version of bin format (1) */
62 u32 size; /* entire image size including this header */
63 u32 os_header_offset;
64 u32 os_data_offset;
65 u32 os_size;
66};
67
68struct falcon_fw_os_app_v1 {
69 u32 offset;
70 u32 size;
71};
72
73struct falcon_fw_os_header_v1 {
74 u32 code_offset;
75 u32 code_size;
76 u32 data_offset;
77 u32 data_size;
78};
79
80struct falcon;
81
82struct falcon_ops {
83 void *(*alloc)(struct falcon *falcon, size_t size,
84 dma_addr_t *paddr);
85 void (*free)(struct falcon *falcon, size_t size,
86 dma_addr_t paddr, void *vaddr);
87};
88
89struct falcon_firmware_section {
90 unsigned long offset;
91 size_t size;
92};
93
94struct falcon_firmware {
95 /* Firmware after it is read but not loaded */
96 const struct firmware *firmware;
97
98 /* Raw firmware data */
99 dma_addr_t paddr;
100 void *vaddr;
101 size_t size;
102
103 /* Parsed firmware information */
104 struct falcon_firmware_section bin_data;
105 struct falcon_firmware_section data;
106 struct falcon_firmware_section code;
107};
108
109struct falcon {
110 /* Set by falcon client */
111 struct device *dev;
112 void __iomem *regs;
113 const struct falcon_ops *ops;
114 void *data;
115
116 struct falcon_firmware firmware;
117};
118
119int falcon_init(struct falcon *falcon);
120void falcon_exit(struct falcon *falcon);
121int falcon_read_firmware(struct falcon *falcon, const char *firmware_name);
122int falcon_load_firmware(struct falcon *falcon);
123int falcon_boot(struct falcon *falcon);
124void falcon_execute_method(struct falcon *falcon, u32 method, u32 data);
125int falcon_wait_idle(struct falcon *falcon);
126
127#endif /* _FALCON_H_ */
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index c61d67d16ce3..25acb73ee728 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -52,9 +52,26 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
52 struct tegra_bo_tiling *tiling) 52 struct tegra_bo_tiling *tiling)
53{ 53{
54 struct tegra_fb *fb = to_tegra_fb(framebuffer); 54 struct tegra_fb *fb = to_tegra_fb(framebuffer);
55 55 uint64_t modifier = fb->base.modifier;
56 /* TODO: handle YUV formats? */ 56
57 *tiling = fb->planes[0]->tiling; 57 switch (fourcc_mod_tegra_mod(modifier)) {
58 case NV_FORMAT_MOD_TEGRA_TILED:
59 tiling->mode = TEGRA_BO_TILING_MODE_TILED;
60 tiling->value = 0;
61 break;
62
63 case NV_FORMAT_MOD_TEGRA_16BX2_BLOCK(0):
64 tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
65 tiling->value = fourcc_mod_tegra_param(modifier);
66 if (tiling->value > 5)
67 return -EINVAL;
68 break;
69
70 default:
71 /* TODO: handle YUV formats? */
72 *tiling = fb->planes[0]->tiling;
73 break;
74 }
58 75
59 return 0; 76 return 0;
60} 77}
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index 8672f5d2f237..424569b53e57 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -128,12 +128,14 @@ static int tegra_bo_iommu_map(struct tegra_drm *tegra, struct tegra_bo *bo)
128 if (!bo->mm) 128 if (!bo->mm)
129 return -ENOMEM; 129 return -ENOMEM;
130 130
131 mutex_lock(&tegra->mm_lock);
132
131 err = drm_mm_insert_node_generic(&tegra->mm, 133 err = drm_mm_insert_node_generic(&tegra->mm,
132 bo->mm, bo->gem.size, PAGE_SIZE, 0, 0); 134 bo->mm, bo->gem.size, PAGE_SIZE, 0, 0);
133 if (err < 0) { 135 if (err < 0) {
134 dev_err(tegra->drm->dev, "out of I/O virtual memory: %zd\n", 136 dev_err(tegra->drm->dev, "out of I/O virtual memory: %zd\n",
135 err); 137 err);
136 goto free; 138 goto unlock;
137 } 139 }
138 140
139 bo->paddr = bo->mm->start; 141 bo->paddr = bo->mm->start;
@@ -147,11 +149,14 @@ static int tegra_bo_iommu_map(struct tegra_drm *tegra, struct tegra_bo *bo)
147 149
148 bo->size = err; 150 bo->size = err;
149 151
152 mutex_unlock(&tegra->mm_lock);
153
150 return 0; 154 return 0;
151 155
152remove: 156remove:
153 drm_mm_remove_node(bo->mm); 157 drm_mm_remove_node(bo->mm);
154free: 158unlock:
159 mutex_unlock(&tegra->mm_lock);
155 kfree(bo->mm); 160 kfree(bo->mm);
156 return err; 161 return err;
157} 162}
@@ -161,8 +166,11 @@ static int tegra_bo_iommu_unmap(struct tegra_drm *tegra, struct tegra_bo *bo)
161 if (!bo->mm) 166 if (!bo->mm)
162 return 0; 167 return 0;
163 168
169 mutex_lock(&tegra->mm_lock);
164 iommu_unmap(tegra->domain, bo->paddr, bo->size); 170 iommu_unmap(tegra->domain, bo->paddr, bo->size);
165 drm_mm_remove_node(bo->mm); 171 drm_mm_remove_node(bo->mm);
172 mutex_unlock(&tegra->mm_lock);
173
166 kfree(bo->mm); 174 kfree(bo->mm);
167 175
168 return 0; 176 return 0;
diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
new file mode 100644
index 000000000000..cd804e404a11
--- /dev/null
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -0,0 +1,396 @@
1/*
2 * Copyright (c) 2015, NVIDIA Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clk.h>
10#include <linux/host1x.h>
11#include <linux/iommu.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/of_device.h>
15#include <linux/of_platform.h>
16#include <linux/platform_device.h>
17#include <linux/pm_runtime.h>
18#include <linux/reset.h>
19
20#include <soc/tegra/pmc.h>
21
22#include "drm.h"
23#include "falcon.h"
24#include "vic.h"
25
26struct vic_config {
27 const char *firmware;
28};
29
30struct vic {
31 struct falcon falcon;
32 bool booted;
33
34 void __iomem *regs;
35 struct tegra_drm_client client;
36 struct host1x_channel *channel;
37 struct iommu_domain *domain;
38 struct device *dev;
39 struct clk *clk;
40
41 /* Platform configuration */
42 const struct vic_config *config;
43};
44
45static inline struct vic *to_vic(struct tegra_drm_client *client)
46{
47 return container_of(client, struct vic, client);
48}
49
50static void vic_writel(struct vic *vic, u32 value, unsigned int offset)
51{
52 writel(value, vic->regs + offset);
53}
54
55static int vic_runtime_resume(struct device *dev)
56{
57 struct vic *vic = dev_get_drvdata(dev);
58
59 return clk_prepare_enable(vic->clk);
60}
61
62static int vic_runtime_suspend(struct device *dev)
63{
64 struct vic *vic = dev_get_drvdata(dev);
65
66 clk_disable_unprepare(vic->clk);
67
68 vic->booted = false;
69
70 return 0;
71}
72
73static int vic_boot(struct vic *vic)
74{
75 u32 fce_ucode_size, fce_bin_data_offset;
76 void *hdr;
77 int err = 0;
78
79 if (vic->booted)
80 return 0;
81
82 /* setup clockgating registers */
83 vic_writel(vic, CG_IDLE_CG_DLY_CNT(4) |
84 CG_IDLE_CG_EN |
85 CG_WAKEUP_DLY_CNT(4),
86 NV_PVIC_MISC_PRI_VIC_CG);
87
88 err = falcon_boot(&vic->falcon);
89 if (err < 0)
90 return err;
91
92 hdr = vic->falcon.firmware.vaddr;
93 fce_bin_data_offset = *(u32 *)(hdr + VIC_UCODE_FCE_DATA_OFFSET);
94 hdr = vic->falcon.firmware.vaddr +
95 *(u32 *)(hdr + VIC_UCODE_FCE_HEADER_OFFSET);
96 fce_ucode_size = *(u32 *)(hdr + FCE_UCODE_SIZE_OFFSET);
97
98 falcon_execute_method(&vic->falcon, VIC_SET_APPLICATION_ID, 1);
99 falcon_execute_method(&vic->falcon, VIC_SET_FCE_UCODE_SIZE,
100 fce_ucode_size);
101 falcon_execute_method(&vic->falcon, VIC_SET_FCE_UCODE_OFFSET,
102 (vic->falcon.firmware.paddr + fce_bin_data_offset)
103 >> 8);
104
105 err = falcon_wait_idle(&vic->falcon);
106 if (err < 0) {
107 dev_err(vic->dev,
108 "failed to set application ID and FCE base\n");
109 return err;
110 }
111
112 vic->booted = true;
113
114 return 0;
115}
116
117static void *vic_falcon_alloc(struct falcon *falcon, size_t size,
118 dma_addr_t *iova)
119{
120 struct tegra_drm *tegra = falcon->data;
121
122 return tegra_drm_alloc(tegra, size, iova);
123}
124
125static void vic_falcon_free(struct falcon *falcon, size_t size,
126 dma_addr_t iova, void *va)
127{
128 struct tegra_drm *tegra = falcon->data;
129
130 return tegra_drm_free(tegra, size, va, iova);
131}
132
133static const struct falcon_ops vic_falcon_ops = {
134 .alloc = vic_falcon_alloc,
135 .free = vic_falcon_free
136};
137
138static int vic_init(struct host1x_client *client)
139{
140 struct tegra_drm_client *drm = host1x_to_drm_client(client);
141 struct drm_device *dev = dev_get_drvdata(client->parent);
142 struct tegra_drm *tegra = dev->dev_private;
143 struct vic *vic = to_vic(drm);
144 int err;
145
146 if (tegra->domain) {
147 err = iommu_attach_device(tegra->domain, vic->dev);
148 if (err < 0) {
149 dev_err(vic->dev, "failed to attach to domain: %d\n",
150 err);
151 return err;
152 }
153
154 vic->domain = tegra->domain;
155 }
156
157 if (!vic->falcon.data) {
158 vic->falcon.data = tegra;
159 err = falcon_load_firmware(&vic->falcon);
160 if (err < 0)
161 goto detach_device;
162 }
163
164 vic->channel = host1x_channel_request(client->dev);
165 if (!vic->channel) {
166 err = -ENOMEM;
167 goto detach_device;
168 }
169
170 client->syncpts[0] = host1x_syncpt_request(client->dev, 0);
171 if (!client->syncpts[0]) {
172 err = -ENOMEM;
173 goto free_channel;
174 }
175
176 err = tegra_drm_register_client(tegra, drm);
177 if (err < 0)
178 goto free_syncpt;
179
180 return 0;
181
182free_syncpt:
183 host1x_syncpt_free(client->syncpts[0]);
184free_channel:
185 host1x_channel_free(vic->channel);
186detach_device:
187 if (tegra->domain)
188 iommu_detach_device(tegra->domain, vic->dev);
189
190 return err;
191}
192
193static int vic_exit(struct host1x_client *client)
194{
195 struct tegra_drm_client *drm = host1x_to_drm_client(client);
196 struct drm_device *dev = dev_get_drvdata(client->parent);
197 struct tegra_drm *tegra = dev->dev_private;
198 struct vic *vic = to_vic(drm);
199 int err;
200
201 err = tegra_drm_unregister_client(tegra, drm);
202 if (err < 0)
203 return err;
204
205 host1x_syncpt_free(client->syncpts[0]);
206 host1x_channel_free(vic->channel);
207
208 if (vic->domain) {
209 iommu_detach_device(vic->domain, vic->dev);
210 vic->domain = NULL;
211 }
212
213 return 0;
214}
215
216static const struct host1x_client_ops vic_client_ops = {
217 .init = vic_init,
218 .exit = vic_exit,
219};
220
221static int vic_open_channel(struct tegra_drm_client *client,
222 struct tegra_drm_context *context)
223{
224 struct vic *vic = to_vic(client);
225 int err;
226
227 err = pm_runtime_get_sync(vic->dev);
228 if (err < 0)
229 return err;
230
231 err = vic_boot(vic);
232 if (err < 0) {
233 pm_runtime_put(vic->dev);
234 return err;
235 }
236
237 context->channel = host1x_channel_get(vic->channel);
238 if (!context->channel) {
239 pm_runtime_put(vic->dev);
240 return -ENOMEM;
241 }
242
243 return 0;
244}
245
246static void vic_close_channel(struct tegra_drm_context *context)
247{
248 struct vic *vic = to_vic(context->client);
249
250 host1x_channel_put(context->channel);
251
252 pm_runtime_put(vic->dev);
253}
254
255static const struct tegra_drm_client_ops vic_ops = {
256 .open_channel = vic_open_channel,
257 .close_channel = vic_close_channel,
258 .submit = tegra_drm_submit,
259};
260
261static const struct vic_config vic_t124_config = {
262 .firmware = "nvidia/tegra124/vic03_ucode.bin",
263};
264
265static const struct vic_config vic_t210_config = {
266 .firmware = "nvidia/tegra210/vic04_ucode.bin",
267};
268
269static const struct of_device_id vic_match[] = {
270 { .compatible = "nvidia,tegra124-vic", .data = &vic_t124_config },
271 { .compatible = "nvidia,tegra210-vic", .data = &vic_t210_config },
272 { },
273};
274
275static int vic_probe(struct platform_device *pdev)
276{
277 struct vic_config *vic_config = NULL;
278 struct device *dev = &pdev->dev;
279 struct host1x_syncpt **syncpts;
280 struct resource *regs;
281 const struct of_device_id *match;
282 struct vic *vic;
283 int err;
284
285 match = of_match_device(vic_match, dev);
286 vic_config = (struct vic_config *)match->data;
287
288 vic = devm_kzalloc(dev, sizeof(*vic), GFP_KERNEL);
289 if (!vic)
290 return -ENOMEM;
291
292 syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
293 if (!syncpts)
294 return -ENOMEM;
295
296 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
297 if (!regs) {
298 dev_err(&pdev->dev, "failed to get registers\n");
299 return -ENXIO;
300 }
301
302 vic->regs = devm_ioremap_resource(dev, regs);
303 if (IS_ERR(vic->regs))
304 return PTR_ERR(vic->regs);
305
306 vic->clk = devm_clk_get(dev, NULL);
307 if (IS_ERR(vic->clk)) {
308 dev_err(&pdev->dev, "failed to get clock\n");
309 return PTR_ERR(vic->clk);
310 }
311
312 vic->falcon.dev = dev;
313 vic->falcon.regs = vic->regs;
314 vic->falcon.ops = &vic_falcon_ops;
315
316 err = falcon_init(&vic->falcon);
317 if (err < 0)
318 return err;
319
320 err = falcon_read_firmware(&vic->falcon, vic_config->firmware);
321 if (err < 0)
322 goto exit_falcon;
323
324 platform_set_drvdata(pdev, vic);
325
326 INIT_LIST_HEAD(&vic->client.base.list);
327 vic->client.base.ops = &vic_client_ops;
328 vic->client.base.dev = dev;
329 vic->client.base.class = HOST1X_CLASS_VIC;
330 vic->client.base.syncpts = syncpts;
331 vic->client.base.num_syncpts = 1;
332 vic->dev = dev;
333 vic->config = vic_config;
334
335 INIT_LIST_HEAD(&vic->client.list);
336 vic->client.ops = &vic_ops;
337
338 err = host1x_client_register(&vic->client.base);
339 if (err < 0) {
340 dev_err(dev, "failed to register host1x client: %d\n", err);
341 platform_set_drvdata(pdev, NULL);
342 goto exit_falcon;
343 }
344
345 pm_runtime_enable(&pdev->dev);
346 if (!pm_runtime_enabled(&pdev->dev)) {
347 err = vic_runtime_resume(&pdev->dev);
348 if (err < 0)
349 goto unregister_client;
350 }
351
352 return 0;
353
354unregister_client:
355 host1x_client_unregister(&vic->client.base);
356exit_falcon:
357 falcon_exit(&vic->falcon);
358
359 return err;
360}
361
362static int vic_remove(struct platform_device *pdev)
363{
364 struct vic *vic = platform_get_drvdata(pdev);
365 int err;
366
367 err = host1x_client_unregister(&vic->client.base);
368 if (err < 0) {
369 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
370 err);
371 return err;
372 }
373
374 if (pm_runtime_enabled(&pdev->dev))
375 pm_runtime_disable(&pdev->dev);
376 else
377 vic_runtime_suspend(&pdev->dev);
378
379 falcon_exit(&vic->falcon);
380
381 return 0;
382}
383
384static const struct dev_pm_ops vic_pm_ops = {
385 SET_RUNTIME_PM_OPS(vic_runtime_suspend, vic_runtime_resume, NULL)
386};
387
388struct platform_driver tegra_vic_driver = {
389 .driver = {
390 .name = "tegra-vic",
391 .of_match_table = vic_match,
392 .pm = &vic_pm_ops
393 },
394 .probe = vic_probe,
395 .remove = vic_remove,
396};
diff --git a/drivers/gpu/drm/tegra/vic.h b/drivers/gpu/drm/tegra/vic.h
new file mode 100644
index 000000000000..21844817a7e1
--- /dev/null
+++ b/drivers/gpu/drm/tegra/vic.h
@@ -0,0 +1,31 @@
1/*
2 * Copyright (c) 2015, NVIDIA Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef TEGRA_VIC_H
10#define TEGRA_VIC_H
11
12/* VIC methods */
13
14#define VIC_SET_APPLICATION_ID 0x00000200
15#define VIC_SET_FCE_UCODE_SIZE 0x0000071C
16#define VIC_SET_FCE_UCODE_OFFSET 0x0000072C
17
18/* VIC registers */
19
20#define NV_PVIC_MISC_PRI_VIC_CG 0x000016d0
21#define CG_IDLE_CG_DLY_CNT(val) ((val & 0x3f) << 0)
22#define CG_IDLE_CG_EN (1 << 6)
23#define CG_WAKEUP_DLY_CNT(val) ((val & 0xf) << 16)
24
25/* Firmware offsets */
26
27#define VIC_UCODE_FCE_HEADER_OFFSET (6*4)
28#define VIC_UCODE_FCE_DATA_OFFSET (7*4)
29#define FCE_UCODE_SIZE_OFFSET (2*4)
30
31#endif /* TEGRA_VIC_H */
diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
index eeb021fe6410..561831e1ae2c 100644
--- a/drivers/gpu/host1x/bus.c
+++ b/drivers/gpu/host1x/bus.c
@@ -267,37 +267,6 @@ static int host1x_device_match(struct device *dev, struct device_driver *drv)
267 return strcmp(dev_name(dev), drv->name) == 0; 267 return strcmp(dev_name(dev), drv->name) == 0;
268} 268}
269 269
270static int host1x_device_probe(struct device *dev)
271{
272 struct host1x_driver *driver = to_host1x_driver(dev->driver);
273 struct host1x_device *device = to_host1x_device(dev);
274
275 if (driver->probe)
276 return driver->probe(device);
277
278 return 0;
279}
280
281static int host1x_device_remove(struct device *dev)
282{
283 struct host1x_driver *driver = to_host1x_driver(dev->driver);
284 struct host1x_device *device = to_host1x_device(dev);
285
286 if (driver->remove)
287 return driver->remove(device);
288
289 return 0;
290}
291
292static void host1x_device_shutdown(struct device *dev)
293{
294 struct host1x_driver *driver = to_host1x_driver(dev->driver);
295 struct host1x_device *device = to_host1x_device(dev);
296
297 if (driver->shutdown)
298 driver->shutdown(device);
299}
300
301static const struct dev_pm_ops host1x_device_pm_ops = { 270static const struct dev_pm_ops host1x_device_pm_ops = {
302 .suspend = pm_generic_suspend, 271 .suspend = pm_generic_suspend,
303 .resume = pm_generic_resume, 272 .resume = pm_generic_resume,
@@ -310,9 +279,6 @@ static const struct dev_pm_ops host1x_device_pm_ops = {
310struct bus_type host1x_bus_type = { 279struct bus_type host1x_bus_type = {
311 .name = "host1x", 280 .name = "host1x",
312 .match = host1x_device_match, 281 .match = host1x_device_match,
313 .probe = host1x_device_probe,
314 .remove = host1x_device_remove,
315 .shutdown = host1x_device_shutdown,
316 .pm = &host1x_device_pm_ops, 282 .pm = &host1x_device_pm_ops,
317}; 283};
318 284
@@ -516,6 +482,37 @@ int host1x_unregister(struct host1x *host1x)
516 return 0; 482 return 0;
517} 483}
518 484
485static int host1x_device_probe(struct device *dev)
486{
487 struct host1x_driver *driver = to_host1x_driver(dev->driver);
488 struct host1x_device *device = to_host1x_device(dev);
489
490 if (driver->probe)
491 return driver->probe(device);
492
493 return 0;
494}
495
496static int host1x_device_remove(struct device *dev)
497{
498 struct host1x_driver *driver = to_host1x_driver(dev->driver);
499 struct host1x_device *device = to_host1x_device(dev);
500
501 if (driver->remove)
502 return driver->remove(device);
503
504 return 0;
505}
506
507static void host1x_device_shutdown(struct device *dev)
508{
509 struct host1x_driver *driver = to_host1x_driver(dev->driver);
510 struct host1x_device *device = to_host1x_device(dev);
511
512 if (driver->shutdown)
513 driver->shutdown(device);
514}
515
519int host1x_driver_register_full(struct host1x_driver *driver, 516int host1x_driver_register_full(struct host1x_driver *driver,
520 struct module *owner) 517 struct module *owner)
521{ 518{
@@ -536,6 +533,9 @@ int host1x_driver_register_full(struct host1x_driver *driver,
536 533
537 driver->driver.bus = &host1x_bus_type; 534 driver->driver.bus = &host1x_bus_type;
538 driver->driver.owner = owner; 535 driver->driver.owner = owner;
536 driver->driver.probe = host1x_device_probe;
537 driver->driver.remove = host1x_device_remove;
538 driver->driver.shutdown = host1x_device_shutdown;
539 539
540 return driver_register(&driver->driver); 540 return driver_register(&driver->driver);
541} 541}
diff --git a/drivers/gpu/host1x/cdma.c b/drivers/gpu/host1x/cdma.c
index c5d82a8a2ec9..28541b280739 100644
--- a/drivers/gpu/host1x/cdma.c
+++ b/drivers/gpu/host1x/cdma.c
@@ -51,9 +51,15 @@ static void host1x_pushbuffer_destroy(struct push_buffer *pb)
51 struct host1x_cdma *cdma = pb_to_cdma(pb); 51 struct host1x_cdma *cdma = pb_to_cdma(pb);
52 struct host1x *host1x = cdma_to_host1x(cdma); 52 struct host1x *host1x = cdma_to_host1x(cdma);
53 53
54 if (pb->phys != 0) 54 if (!pb->phys)
55 dma_free_wc(host1x->dev, pb->size_bytes + 4, pb->mapped, 55 return;
56 pb->phys); 56
57 if (host1x->domain) {
58 iommu_unmap(host1x->domain, pb->dma, pb->alloc_size);
59 free_iova(&host1x->iova, iova_pfn(&host1x->iova, pb->dma));
60 }
61
62 dma_free_wc(host1x->dev, pb->alloc_size, pb->mapped, pb->phys);
57 63
58 pb->mapped = NULL; 64 pb->mapped = NULL;
59 pb->phys = 0; 65 pb->phys = 0;
@@ -66,28 +72,64 @@ static int host1x_pushbuffer_init(struct push_buffer *pb)
66{ 72{
67 struct host1x_cdma *cdma = pb_to_cdma(pb); 73 struct host1x_cdma *cdma = pb_to_cdma(pb);
68 struct host1x *host1x = cdma_to_host1x(cdma); 74 struct host1x *host1x = cdma_to_host1x(cdma);
75 struct iova *alloc;
76 u32 size;
77 int err;
69 78
70 pb->mapped = NULL; 79 pb->mapped = NULL;
71 pb->phys = 0; 80 pb->phys = 0;
72 pb->size_bytes = HOST1X_PUSHBUFFER_SLOTS * 8; 81 pb->size = HOST1X_PUSHBUFFER_SLOTS * 8;
82
83 size = pb->size + 4;
73 84
74 /* initialize buffer pointers */ 85 /* initialize buffer pointers */
75 pb->fence = pb->size_bytes - 8; 86 pb->fence = pb->size - 8;
76 pb->pos = 0; 87 pb->pos = 0;
77 88
78 /* allocate and map pushbuffer memory */ 89 if (host1x->domain) {
79 pb->mapped = dma_alloc_wc(host1x->dev, pb->size_bytes + 4, &pb->phys, 90 unsigned long shift;
80 GFP_KERNEL); 91
81 if (!pb->mapped) 92 size = iova_align(&host1x->iova, size);
82 goto fail; 93
94 pb->mapped = dma_alloc_wc(host1x->dev, size, &pb->phys,
95 GFP_KERNEL);
96 if (!pb->mapped)
97 return -ENOMEM;
98
99 shift = iova_shift(&host1x->iova);
100 alloc = alloc_iova(&host1x->iova, size >> shift,
101 host1x->iova_end >> shift, true);
102 if (!alloc) {
103 err = -ENOMEM;
104 goto iommu_free_mem;
105 }
106
107 pb->dma = iova_dma_addr(&host1x->iova, alloc);
108 err = iommu_map(host1x->domain, pb->dma, pb->phys, size,
109 IOMMU_READ);
110 if (err)
111 goto iommu_free_iova;
112 } else {
113 pb->mapped = dma_alloc_wc(host1x->dev, size, &pb->phys,
114 GFP_KERNEL);
115 if (!pb->mapped)
116 return -ENOMEM;
117
118 pb->dma = pb->phys;
119 }
120
121 pb->alloc_size = size;
83 122
84 host1x_hw_pushbuffer_init(host1x, pb); 123 host1x_hw_pushbuffer_init(host1x, pb);
85 124
86 return 0; 125 return 0;
87 126
88fail: 127iommu_free_iova:
89 host1x_pushbuffer_destroy(pb); 128 __free_iova(&host1x->iova, alloc);
90 return -ENOMEM; 129iommu_free_mem:
130 dma_free_wc(host1x->dev, pb->alloc_size, pb->mapped, pb->phys);
131
132 return err;
91} 133}
92 134
93/* 135/*
@@ -101,7 +143,7 @@ static void host1x_pushbuffer_push(struct push_buffer *pb, u32 op1, u32 op2)
101 WARN_ON(pb->pos == pb->fence); 143 WARN_ON(pb->pos == pb->fence);
102 *(p++) = op1; 144 *(p++) = op1;
103 *(p++) = op2; 145 *(p++) = op2;
104 pb->pos = (pb->pos + 8) & (pb->size_bytes - 1); 146 pb->pos = (pb->pos + 8) & (pb->size - 1);
105} 147}
106 148
107/* 149/*
@@ -111,7 +153,7 @@ static void host1x_pushbuffer_push(struct push_buffer *pb, u32 op1, u32 op2)
111static void host1x_pushbuffer_pop(struct push_buffer *pb, unsigned int slots) 153static void host1x_pushbuffer_pop(struct push_buffer *pb, unsigned int slots)
112{ 154{
113 /* Advance the next write position */ 155 /* Advance the next write position */
114 pb->fence = (pb->fence + slots * 8) & (pb->size_bytes - 1); 156 pb->fence = (pb->fence + slots * 8) & (pb->size - 1);
115} 157}
116 158
117/* 159/*
@@ -119,7 +161,7 @@ static void host1x_pushbuffer_pop(struct push_buffer *pb, unsigned int slots)
119 */ 161 */
120static u32 host1x_pushbuffer_space(struct push_buffer *pb) 162static u32 host1x_pushbuffer_space(struct push_buffer *pb)
121{ 163{
122 return ((pb->fence - pb->pos) & (pb->size_bytes - 1)) / 8; 164 return ((pb->fence - pb->pos) & (pb->size - 1)) / 8;
123} 165}
124 166
125/* 167/*
diff --git a/drivers/gpu/host1x/cdma.h b/drivers/gpu/host1x/cdma.h
index 470087af8fe5..ec170a78f4e1 100644
--- a/drivers/gpu/host1x/cdma.h
+++ b/drivers/gpu/host1x/cdma.h
@@ -43,10 +43,12 @@ struct host1x_job;
43 43
44struct push_buffer { 44struct push_buffer {
45 void *mapped; /* mapped pushbuffer memory */ 45 void *mapped; /* mapped pushbuffer memory */
46 dma_addr_t phys; /* physical address of pushbuffer */ 46 dma_addr_t dma; /* device address of pushbuffer */
47 phys_addr_t phys; /* physical address of pushbuffer */
47 u32 fence; /* index we've written */ 48 u32 fence; /* index we've written */
48 u32 pos; /* index to write to */ 49 u32 pos; /* index to write to */
49 u32 size_bytes; 50 u32 size;
51 u32 alloc_size;
50}; 52};
51 53
52struct buffer_timeout { 54struct buffer_timeout {
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index a62317af76ad..f05ebb14fa63 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -16,23 +16,25 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 17 */
18 18
19#include <linux/module.h>
20#include <linux/list.h>
21#include <linux/slab.h>
22#include <linux/of.h>
23#include <linux/of_device.h>
24#include <linux/clk.h> 19#include <linux/clk.h>
25#include <linux/io.h>
26#include <linux/dma-mapping.h> 20#include <linux/dma-mapping.h>
21#include <linux/io.h>
22#include <linux/list.h>
23#include <linux/module.h>
24#include <linux/of_device.h>
25#include <linux/of.h>
26#include <linux/slab.h>
27 27
28#define CREATE_TRACE_POINTS 28#define CREATE_TRACE_POINTS
29#include <trace/events/host1x.h> 29#include <trace/events/host1x.h>
30#undef CREATE_TRACE_POINTS
30 31
31#include "bus.h" 32#include "bus.h"
32#include "dev.h"
33#include "intr.h"
34#include "channel.h" 33#include "channel.h"
35#include "debug.h" 34#include "debug.h"
35#include "dev.h"
36#include "intr.h"
37
36#include "hw/host1x01.h" 38#include "hw/host1x01.h"
37#include "hw/host1x02.h" 39#include "hw/host1x02.h"
38#include "hw/host1x04.h" 40#include "hw/host1x04.h"
@@ -168,22 +170,56 @@ static int host1x_probe(struct platform_device *pdev)
168 return err; 170 return err;
169 } 171 }
170 172
173 host->rst = devm_reset_control_get(&pdev->dev, "host1x");
174 if (IS_ERR(host->rst)) {
175 err = PTR_ERR(host->clk);
176 dev_err(&pdev->dev, "failed to get reset: %d\n", err);
177 return err;
178 }
179
180 if (iommu_present(&platform_bus_type)) {
181 struct iommu_domain_geometry *geometry;
182 unsigned long order;
183
184 host->domain = iommu_domain_alloc(&platform_bus_type);
185 if (!host->domain)
186 return -ENOMEM;
187
188 err = iommu_attach_device(host->domain, &pdev->dev);
189 if (err)
190 goto fail_free_domain;
191
192 geometry = &host->domain->geometry;
193
194 order = __ffs(host->domain->pgsize_bitmap);
195 init_iova_domain(&host->iova, 1UL << order,
196 geometry->aperture_start >> order,
197 geometry->aperture_end >> order);
198 host->iova_end = geometry->aperture_end;
199 }
200
171 err = host1x_channel_list_init(host); 201 err = host1x_channel_list_init(host);
172 if (err) { 202 if (err) {
173 dev_err(&pdev->dev, "failed to initialize channel list\n"); 203 dev_err(&pdev->dev, "failed to initialize channel list\n");
174 return err; 204 goto fail_detach_device;
175 } 205 }
176 206
177 err = clk_prepare_enable(host->clk); 207 err = clk_prepare_enable(host->clk);
178 if (err < 0) { 208 if (err < 0) {
179 dev_err(&pdev->dev, "failed to enable clock\n"); 209 dev_err(&pdev->dev, "failed to enable clock\n");
180 return err; 210 goto fail_detach_device;
211 }
212
213 err = reset_control_deassert(host->rst);
214 if (err < 0) {
215 dev_err(&pdev->dev, "failed to deassert reset: %d\n", err);
216 goto fail_unprepare_disable;
181 } 217 }
182 218
183 err = host1x_syncpt_init(host); 219 err = host1x_syncpt_init(host);
184 if (err) { 220 if (err) {
185 dev_err(&pdev->dev, "failed to initialize syncpts\n"); 221 dev_err(&pdev->dev, "failed to initialize syncpts\n");
186 goto fail_unprepare_disable; 222 goto fail_reset_assert;
187 } 223 }
188 224
189 err = host1x_intr_init(host, syncpt_irq); 225 err = host1x_intr_init(host, syncpt_irq);
@@ -204,8 +240,19 @@ fail_deinit_intr:
204 host1x_intr_deinit(host); 240 host1x_intr_deinit(host);
205fail_deinit_syncpt: 241fail_deinit_syncpt:
206 host1x_syncpt_deinit(host); 242 host1x_syncpt_deinit(host);
243fail_reset_assert:
244 reset_control_assert(host->rst);
207fail_unprepare_disable: 245fail_unprepare_disable:
208 clk_disable_unprepare(host->clk); 246 clk_disable_unprepare(host->clk);
247fail_detach_device:
248 if (host->domain) {
249 put_iova_domain(&host->iova);
250 iommu_detach_device(host->domain, &pdev->dev);
251 }
252fail_free_domain:
253 if (host->domain)
254 iommu_domain_free(host->domain);
255
209 return err; 256 return err;
210} 257}
211 258
@@ -216,8 +263,15 @@ static int host1x_remove(struct platform_device *pdev)
216 host1x_unregister(host); 263 host1x_unregister(host);
217 host1x_intr_deinit(host); 264 host1x_intr_deinit(host);
218 host1x_syncpt_deinit(host); 265 host1x_syncpt_deinit(host);
266 reset_control_assert(host->rst);
219 clk_disable_unprepare(host->clk); 267 clk_disable_unprepare(host->clk);
220 268
269 if (host->domain) {
270 put_iova_domain(&host->iova);
271 iommu_detach_device(host->domain, &pdev->dev);
272 iommu_domain_free(host->domain);
273 }
274
221 return 0; 275 return 0;
222} 276}
223 277
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index 06dd4f85125f..229d08b6a45e 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -17,14 +17,17 @@
17#ifndef HOST1X_DEV_H 17#ifndef HOST1X_DEV_H
18#define HOST1X_DEV_H 18#define HOST1X_DEV_H
19 19
20#include <linux/platform_device.h>
21#include <linux/device.h> 20#include <linux/device.h>
21#include <linux/iommu.h>
22#include <linux/iova.h>
23#include <linux/platform_device.h>
24#include <linux/reset.h>
22 25
26#include "cdma.h"
23#include "channel.h" 27#include "channel.h"
24#include "syncpt.h"
25#include "intr.h" 28#include "intr.h"
26#include "cdma.h"
27#include "job.h" 29#include "job.h"
30#include "syncpt.h"
28 31
29struct host1x_syncpt; 32struct host1x_syncpt;
30struct host1x_syncpt_base; 33struct host1x_syncpt_base;
@@ -107,6 +110,11 @@ struct host1x {
107 struct host1x_syncpt_base *bases; 110 struct host1x_syncpt_base *bases;
108 struct device *dev; 111 struct device *dev;
109 struct clk *clk; 112 struct clk *clk;
113 struct reset_control *rst;
114
115 struct iommu_domain *domain;
116 struct iova_domain iova;
117 dma_addr_t iova_end;
110 118
111 struct mutex intr_mutex; 119 struct mutex intr_mutex;
112 int intr_syncpt_irq; 120 int intr_syncpt_irq;
diff --git a/drivers/gpu/host1x/hw/cdma_hw.c b/drivers/gpu/host1x/hw/cdma_hw.c
index 659c1bbfeeba..6b231119193e 100644
--- a/drivers/gpu/host1x/hw/cdma_hw.c
+++ b/drivers/gpu/host1x/hw/cdma_hw.c
@@ -30,7 +30,7 @@
30 */ 30 */
31static void push_buffer_init(struct push_buffer *pb) 31static void push_buffer_init(struct push_buffer *pb)
32{ 32{
33 *(u32 *)(pb->mapped + pb->size_bytes) = host1x_opcode_restart(0); 33 *(u32 *)(pb->mapped + pb->size) = host1x_opcode_restart(0);
34} 34}
35 35
36/* 36/*
@@ -55,8 +55,8 @@ static void cdma_timeout_cpu_incr(struct host1x_cdma *cdma, u32 getptr,
55 *(p++) = HOST1X_OPCODE_NOP; 55 *(p++) = HOST1X_OPCODE_NOP;
56 *(p++) = HOST1X_OPCODE_NOP; 56 *(p++) = HOST1X_OPCODE_NOP;
57 dev_dbg(host1x->dev, "%s: NOP at %pad+%#x\n", __func__, 57 dev_dbg(host1x->dev, "%s: NOP at %pad+%#x\n", __func__,
58 &pb->phys, getptr); 58 &pb->dma, getptr);
59 getptr = (getptr + 8) & (pb->size_bytes - 1); 59 getptr = (getptr + 8) & (pb->size - 1);
60 } 60 }
61 61
62 wmb(); 62 wmb();
@@ -78,10 +78,9 @@ static void cdma_start(struct host1x_cdma *cdma)
78 HOST1X_CHANNEL_DMACTRL); 78 HOST1X_CHANNEL_DMACTRL);
79 79
80 /* set base, put and end pointer */ 80 /* set base, put and end pointer */
81 host1x_ch_writel(ch, cdma->push_buffer.phys, HOST1X_CHANNEL_DMASTART); 81 host1x_ch_writel(ch, cdma->push_buffer.dma, HOST1X_CHANNEL_DMASTART);
82 host1x_ch_writel(ch, cdma->push_buffer.pos, HOST1X_CHANNEL_DMAPUT); 82 host1x_ch_writel(ch, cdma->push_buffer.pos, HOST1X_CHANNEL_DMAPUT);
83 host1x_ch_writel(ch, cdma->push_buffer.phys + 83 host1x_ch_writel(ch, cdma->push_buffer.dma + cdma->push_buffer.size + 4,
84 cdma->push_buffer.size_bytes + 4,
85 HOST1X_CHANNEL_DMAEND); 84 HOST1X_CHANNEL_DMAEND);
86 85
87 /* reset GET */ 86 /* reset GET */
@@ -115,9 +114,8 @@ static void cdma_timeout_restart(struct host1x_cdma *cdma, u32 getptr)
115 HOST1X_CHANNEL_DMACTRL); 114 HOST1X_CHANNEL_DMACTRL);
116 115
117 /* set base, end pointer (all of memory) */ 116 /* set base, end pointer (all of memory) */
118 host1x_ch_writel(ch, cdma->push_buffer.phys, HOST1X_CHANNEL_DMASTART); 117 host1x_ch_writel(ch, cdma->push_buffer.dma, HOST1X_CHANNEL_DMASTART);
119 host1x_ch_writel(ch, cdma->push_buffer.phys + 118 host1x_ch_writel(ch, cdma->push_buffer.dma + cdma->push_buffer.size,
120 cdma->push_buffer.size_bytes,
121 HOST1X_CHANNEL_DMAEND); 119 HOST1X_CHANNEL_DMAEND);
122 120
123 /* set GET, by loading the value in PUT (then reset GET) */ 121 /* set GET, by loading the value in PUT (then reset GET) */
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c
index 92c3df933303..5f5f8ee6143d 100644
--- a/drivers/gpu/host1x/job.c
+++ b/drivers/gpu/host1x/job.c
@@ -174,9 +174,10 @@ static int do_waitchks(struct host1x_job *job, struct host1x *host,
174 return 0; 174 return 0;
175} 175}
176 176
177static unsigned int pin_job(struct host1x_job *job) 177static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
178{ 178{
179 unsigned int i; 179 unsigned int i;
180 int err;
180 181
181 job->num_unpins = 0; 182 job->num_unpins = 0;
182 183
@@ -186,12 +187,16 @@ static unsigned int pin_job(struct host1x_job *job)
186 dma_addr_t phys_addr; 187 dma_addr_t phys_addr;
187 188
188 reloc->target.bo = host1x_bo_get(reloc->target.bo); 189 reloc->target.bo = host1x_bo_get(reloc->target.bo);
189 if (!reloc->target.bo) 190 if (!reloc->target.bo) {
191 err = -EINVAL;
190 goto unpin; 192 goto unpin;
193 }
191 194
192 phys_addr = host1x_bo_pin(reloc->target.bo, &sgt); 195 phys_addr = host1x_bo_pin(reloc->target.bo, &sgt);
193 if (!phys_addr) 196 if (!phys_addr) {
197 err = -EINVAL;
194 goto unpin; 198 goto unpin;
199 }
195 200
196 job->addr_phys[job->num_unpins] = phys_addr; 201 job->addr_phys[job->num_unpins] = phys_addr;
197 job->unpins[job->num_unpins].bo = reloc->target.bo; 202 job->unpins[job->num_unpins].bo = reloc->target.bo;
@@ -201,28 +206,67 @@ static unsigned int pin_job(struct host1x_job *job)
201 206
202 for (i = 0; i < job->num_gathers; i++) { 207 for (i = 0; i < job->num_gathers; i++) {
203 struct host1x_job_gather *g = &job->gathers[i]; 208 struct host1x_job_gather *g = &job->gathers[i];
209 size_t gather_size = 0;
210 struct scatterlist *sg;
204 struct sg_table *sgt; 211 struct sg_table *sgt;
205 dma_addr_t phys_addr; 212 dma_addr_t phys_addr;
213 unsigned long shift;
214 struct iova *alloc;
215 unsigned int j;
206 216
207 g->bo = host1x_bo_get(g->bo); 217 g->bo = host1x_bo_get(g->bo);
208 if (!g->bo) 218 if (!g->bo) {
219 err = -EINVAL;
209 goto unpin; 220 goto unpin;
221 }
210 222
211 phys_addr = host1x_bo_pin(g->bo, &sgt); 223 phys_addr = host1x_bo_pin(g->bo, &sgt);
212 if (!phys_addr) 224 if (!phys_addr) {
225 err = -EINVAL;
213 goto unpin; 226 goto unpin;
227 }
228
229 if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) {
230 for_each_sg(sgt->sgl, sg, sgt->nents, j)
231 gather_size += sg->length;
232 gather_size = iova_align(&host->iova, gather_size);
233
234 shift = iova_shift(&host->iova);
235 alloc = alloc_iova(&host->iova, gather_size >> shift,
236 host->iova_end >> shift, true);
237 if (!alloc) {
238 err = -ENOMEM;
239 goto unpin;
240 }
241
242 err = iommu_map_sg(host->domain,
243 iova_dma_addr(&host->iova, alloc),
244 sgt->sgl, sgt->nents, IOMMU_READ);
245 if (err == 0) {
246 __free_iova(&host->iova, alloc);
247 err = -EINVAL;
248 goto unpin;
249 }
250
251 job->addr_phys[job->num_unpins] =
252 iova_dma_addr(&host->iova, alloc);
253 job->unpins[job->num_unpins].size = gather_size;
254 } else {
255 job->addr_phys[job->num_unpins] = phys_addr;
256 }
257
258 job->gather_addr_phys[i] = job->addr_phys[job->num_unpins];
214 259
215 job->addr_phys[job->num_unpins] = phys_addr;
216 job->unpins[job->num_unpins].bo = g->bo; 260 job->unpins[job->num_unpins].bo = g->bo;
217 job->unpins[job->num_unpins].sgt = sgt; 261 job->unpins[job->num_unpins].sgt = sgt;
218 job->num_unpins++; 262 job->num_unpins++;
219 } 263 }
220 264
221 return job->num_unpins; 265 return 0;
222 266
223unpin: 267unpin:
224 host1x_job_unpin(job); 268 host1x_job_unpin(job);
225 return 0; 269 return err;
226} 270}
227 271
228static int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf) 272static int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
@@ -525,8 +569,8 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
525 host1x_syncpt_load(host->syncpt + i); 569 host1x_syncpt_load(host->syncpt + i);
526 570
527 /* pin memory */ 571 /* pin memory */
528 err = pin_job(job); 572 err = pin_job(host, job);
529 if (!err) 573 if (err)
530 goto out; 574 goto out;
531 575
532 /* patch gathers */ 576 /* patch gathers */
@@ -572,11 +616,19 @@ EXPORT_SYMBOL(host1x_job_pin);
572 616
573void host1x_job_unpin(struct host1x_job *job) 617void host1x_job_unpin(struct host1x_job *job)
574{ 618{
619 struct host1x *host = dev_get_drvdata(job->channel->dev->parent);
575 unsigned int i; 620 unsigned int i;
576 621
577 for (i = 0; i < job->num_unpins; i++) { 622 for (i = 0; i < job->num_unpins; i++) {
578 struct host1x_job_unpin_data *unpin = &job->unpins[i]; 623 struct host1x_job_unpin_data *unpin = &job->unpins[i];
579 624
625 if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) {
626 iommu_unmap(host->domain, job->addr_phys[i],
627 unpin->size);
628 free_iova(&host->iova,
629 iova_pfn(&host->iova, job->addr_phys[i]));
630 }
631
580 host1x_bo_unpin(unpin->bo, unpin->sgt); 632 host1x_bo_unpin(unpin->bo, unpin->sgt);
581 host1x_bo_put(unpin->bo); 633 host1x_bo_put(unpin->bo);
582 } 634 }
diff --git a/drivers/gpu/host1x/job.h b/drivers/gpu/host1x/job.h
index 8b3c15df0660..878239c476d2 100644
--- a/drivers/gpu/host1x/job.h
+++ b/drivers/gpu/host1x/job.h
@@ -44,6 +44,7 @@ struct host1x_waitchk {
44struct host1x_job_unpin_data { 44struct host1x_job_unpin_data {
45 struct host1x_bo *bo; 45 struct host1x_bo *bo;
46 struct sg_table *sgt; 46 struct sg_table *sgt;
47 size_t size;
47}; 48};
48 49
49/* 50/*
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index 25c11a85050b..0ac026cdc30c 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -484,7 +484,7 @@ unsigned int host1x_syncpt_nb_mlocks(struct host1x *host)
484 484
485struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, unsigned int id) 485struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, unsigned int id)
486{ 486{
487 if (host->info->nb_pts < id) 487 if (id >= host->info->nb_pts)
488 return NULL; 488 return NULL;
489 489
490 return host->syncpt + id; 490 return host->syncpt + id;
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index b7268a14184f..e80a4105ac2a 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -100,6 +100,34 @@ __cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
100 } 100 }
101} 101}
102 102
103/* Insert the iova into domain rbtree by holding writer lock */
104static void
105iova_insert_rbtree(struct rb_root *root, struct iova *iova,
106 struct rb_node *start)
107{
108 struct rb_node **new, *parent = NULL;
109
110 new = (start) ? &start : &(root->rb_node);
111 /* Figure out where to put new node */
112 while (*new) {
113 struct iova *this = rb_entry(*new, struct iova, node);
114
115 parent = *new;
116
117 if (iova->pfn_lo < this->pfn_lo)
118 new = &((*new)->rb_left);
119 else if (iova->pfn_lo > this->pfn_lo)
120 new = &((*new)->rb_right);
121 else {
122 WARN_ON(1); /* this should not happen */
123 return;
124 }
125 }
126 /* Add new node and rebalance tree. */
127 rb_link_node(&iova->node, parent, new);
128 rb_insert_color(&iova->node, root);
129}
130
103/* 131/*
104 * Computes the padding size required, to make the start address 132 * Computes the padding size required, to make the start address
105 * naturally aligned on the power-of-two order of its size 133 * naturally aligned on the power-of-two order of its size
@@ -157,35 +185,8 @@ move_left:
157 new->pfn_lo = limit_pfn - (size + pad_size) + 1; 185 new->pfn_lo = limit_pfn - (size + pad_size) + 1;
158 new->pfn_hi = new->pfn_lo + size - 1; 186 new->pfn_hi = new->pfn_lo + size - 1;
159 187
160 /* Insert the new_iova into domain rbtree by holding writer lock */ 188 /* If we have 'prev', it's a valid place to start the insertion. */
161 /* Add new node and rebalance tree. */ 189 iova_insert_rbtree(&iovad->rbroot, new, prev);
162 {
163 struct rb_node **entry, *parent = NULL;
164
165 /* If we have 'prev', it's a valid place to start the
166 insertion. Otherwise, start from the root. */
167 if (prev)
168 entry = &prev;
169 else
170 entry = &iovad->rbroot.rb_node;
171
172 /* Figure out where to put new node */
173 while (*entry) {
174 struct iova *this = rb_entry(*entry, struct iova, node);
175 parent = *entry;
176
177 if (new->pfn_lo < this->pfn_lo)
178 entry = &((*entry)->rb_left);
179 else if (new->pfn_lo > this->pfn_lo)
180 entry = &((*entry)->rb_right);
181 else
182 BUG(); /* this should not happen */
183 }
184
185 /* Add new node and rebalance tree. */
186 rb_link_node(&new->node, parent, entry);
187 rb_insert_color(&new->node, &iovad->rbroot);
188 }
189 __cached_rbnode_insert_update(iovad, saved_pfn, new); 190 __cached_rbnode_insert_update(iovad, saved_pfn, new);
190 191
191 spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); 192 spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
@@ -194,28 +195,6 @@ move_left:
194 return 0; 195 return 0;
195} 196}
196 197
197static void
198iova_insert_rbtree(struct rb_root *root, struct iova *iova)
199{
200 struct rb_node **new = &(root->rb_node), *parent = NULL;
201 /* Figure out where to put new node */
202 while (*new) {
203 struct iova *this = rb_entry(*new, struct iova, node);
204
205 parent = *new;
206
207 if (iova->pfn_lo < this->pfn_lo)
208 new = &((*new)->rb_left);
209 else if (iova->pfn_lo > this->pfn_lo)
210 new = &((*new)->rb_right);
211 else
212 BUG(); /* this should not happen */
213 }
214 /* Add new node and rebalance tree. */
215 rb_link_node(&iova->node, parent, new);
216 rb_insert_color(&iova->node, root);
217}
218
219static struct kmem_cache *iova_cache; 198static struct kmem_cache *iova_cache;
220static unsigned int iova_cache_users; 199static unsigned int iova_cache_users;
221static DEFINE_MUTEX(iova_cache_mutex); 200static DEFINE_MUTEX(iova_cache_mutex);
@@ -505,7 +484,7 @@ __insert_new_range(struct iova_domain *iovad,
505 484
506 iova = alloc_and_init_iova(pfn_lo, pfn_hi); 485 iova = alloc_and_init_iova(pfn_lo, pfn_hi);
507 if (iova) 486 if (iova)
508 iova_insert_rbtree(&iovad->rbroot, iova); 487 iova_insert_rbtree(&iovad->rbroot, iova, NULL);
509 488
510 return iova; 489 return iova;
511} 490}
@@ -612,11 +591,11 @@ split_and_remove_iova(struct iova_domain *iovad, struct iova *iova,
612 rb_erase(&iova->node, &iovad->rbroot); 591 rb_erase(&iova->node, &iovad->rbroot);
613 592
614 if (prev) { 593 if (prev) {
615 iova_insert_rbtree(&iovad->rbroot, prev); 594 iova_insert_rbtree(&iovad->rbroot, prev, NULL);
616 iova->pfn_lo = pfn_lo; 595 iova->pfn_lo = pfn_lo;
617 } 596 }
618 if (next) { 597 if (next) {
619 iova_insert_rbtree(&iovad->rbroot, next); 598 iova_insert_rbtree(&iovad->rbroot, next, NULL);
620 iova->pfn_hi = pfn_hi; 599 iova->pfn_hi = pfn_hi;
621 } 600 }
622 spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); 601 spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 1ffbf2a8cb99..3d04aa1dc83e 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -26,6 +26,7 @@ enum host1x_class {
26 HOST1X_CLASS_HOST1X = 0x1, 26 HOST1X_CLASS_HOST1X = 0x1,
27 HOST1X_CLASS_GR2D = 0x51, 27 HOST1X_CLASS_GR2D = 0x51,
28 HOST1X_CLASS_GR2D_SB = 0x52, 28 HOST1X_CLASS_GR2D_SB = 0x52,
29 HOST1X_CLASS_VIC = 0x5D,
29 HOST1X_CLASS_GR3D = 0x60, 30 HOST1X_CLASS_GR3D = 0x60,
30}; 31};
31 32
diff --git a/include/linux/iova.h b/include/linux/iova.h
index f27bb2c62fca..e0a892ae45c0 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -82,6 +82,7 @@ static inline unsigned long iova_pfn(struct iova_domain *iovad, dma_addr_t iova)
82 return iova >> iova_shift(iovad); 82 return iova >> iova_shift(iovad);
83} 83}
84 84
85#if IS_ENABLED(CONFIG_IOMMU_IOVA)
85int iova_cache_get(void); 86int iova_cache_get(void);
86void iova_cache_put(void); 87void iova_cache_put(void);
87 88
@@ -106,5 +107,95 @@ void put_iova_domain(struct iova_domain *iovad);
106struct iova *split_and_remove_iova(struct iova_domain *iovad, 107struct iova *split_and_remove_iova(struct iova_domain *iovad,
107 struct iova *iova, unsigned long pfn_lo, unsigned long pfn_hi); 108 struct iova *iova, unsigned long pfn_lo, unsigned long pfn_hi);
108void free_cpu_cached_iovas(unsigned int cpu, struct iova_domain *iovad); 109void free_cpu_cached_iovas(unsigned int cpu, struct iova_domain *iovad);
110#else
111static inline int iova_cache_get(void)
112{
113 return -ENOTSUPP;
114}
115
116static inline void iova_cache_put(void)
117{
118}
119
120static inline struct iova *alloc_iova_mem(void)
121{
122 return NULL;
123}
124
125static inline void free_iova_mem(struct iova *iova)
126{
127}
128
129static inline void free_iova(struct iova_domain *iovad, unsigned long pfn)
130{
131}
132
133static inline void __free_iova(struct iova_domain *iovad, struct iova *iova)
134{
135}
136
137static inline struct iova *alloc_iova(struct iova_domain *iovad,
138 unsigned long size,
139 unsigned long limit_pfn,
140 bool size_aligned)
141{
142 return NULL;
143}
144
145static inline void free_iova_fast(struct iova_domain *iovad,
146 unsigned long pfn,
147 unsigned long size)
148{
149}
150
151static inline unsigned long alloc_iova_fast(struct iova_domain *iovad,
152 unsigned long size,
153 unsigned long limit_pfn)
154{
155 return 0;
156}
157
158static inline struct iova *reserve_iova(struct iova_domain *iovad,
159 unsigned long pfn_lo,
160 unsigned long pfn_hi)
161{
162 return NULL;
163}
164
165static inline void copy_reserved_iova(struct iova_domain *from,
166 struct iova_domain *to)
167{
168}
169
170static inline void init_iova_domain(struct iova_domain *iovad,
171 unsigned long granule,
172 unsigned long start_pfn,
173 unsigned long pfn_32bit)
174{
175}
176
177static inline struct iova *find_iova(struct iova_domain *iovad,
178 unsigned long pfn)
179{
180 return NULL;
181}
182
183static inline void put_iova_domain(struct iova_domain *iovad)
184{
185}
186
187static inline struct iova *split_and_remove_iova(struct iova_domain *iovad,
188 struct iova *iova,
189 unsigned long pfn_lo,
190 unsigned long pfn_hi)
191{
192 return NULL;
193}
194
195static inline void free_cpu_cached_iovas(unsigned int cpu,
196 struct iova_domain *iovad)
197{
198}
199#endif
109 200
110#endif 201#endif
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 995c8f9c692f..55e301047b3e 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -306,6 +306,51 @@ extern "C" {
306 */ 306 */
307#define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4) 307#define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4)
308 308
309
310/* NVIDIA Tegra frame buffer modifiers */
311
312/*
313 * Some modifiers take parameters, for example the number of vertical GOBs in
314 * a block. Reserve the lower 32 bits for parameters
315 */
316#define __fourcc_mod_tegra_mode_shift 32
317#define fourcc_mod_tegra_code(val, params) \
318 fourcc_mod_code(NV, ((((__u64)val) << __fourcc_mod_tegra_mode_shift) | params))
319#define fourcc_mod_tegra_mod(m) \
320 (m & ~((1ULL << __fourcc_mod_tegra_mode_shift) - 1))
321#define fourcc_mod_tegra_param(m) \
322 (m & ((1ULL << __fourcc_mod_tegra_mode_shift) - 1))
323
324/*
325 * Tegra Tiled Layout, used by Tegra 2, 3 and 4.
326 *
327 * Pixels are arranged in simple tiles of 16 x 16 bytes.
328 */
329#define NV_FORMAT_MOD_TEGRA_TILED fourcc_mod_tegra_code(1, 0)
330
331/*
332 * Tegra 16Bx2 Block Linear layout, used by TK1/TX1
333 *
334 * Pixels are arranged in 64x8 Groups Of Bytes (GOBs). GOBs are then stacked
335 * vertically by a power of 2 (1 to 32 GOBs) to form a block.
336 *
337 * Within a GOB, data is ordered as 16B x 2 lines sectors laid in Z-shape.
338 *
339 * Parameter 'v' is the log2 encoding of the number of GOBs stacked vertically.
340 * Valid values are:
341 *
342 * 0 == ONE_GOB
343 * 1 == TWO_GOBS
344 * 2 == FOUR_GOBS
345 * 3 == EIGHT_GOBS
346 * 4 == SIXTEEN_GOBS
347 * 5 == THIRTYTWO_GOBS
348 *
349 * Chapter 20 "Pixel Memory Formats" of the Tegra X1 TRM describes this format
350 * in full detail.
351 */
352#define NV_FORMAT_MOD_TEGRA_16BX2_BLOCK(v) fourcc_mod_tegra_code(2, v)
353
309#if defined(__cplusplus) 354#if defined(__cplusplus)
310} 355}
311#endif 356#endif