History

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

Linus Torvalds committed 9 years ago

Commit 1062ae42 parents 1a5fb64 644b49325 files · +1517 −202Browse files

Unified · Split

25 files
  1. Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt +13 −0
  2. MAINTAINERS +2 −0
  3. drivers/gpu/drm/tegra/Kconfig +1 −0
  4. drivers/gpu/drm/tegra/Makefile +3 −1
  5. drivers/gpu/drm/tegra/drm.c +228 −55
  6. drivers/gpu/drm/tegra/drm.h +14 −1
  7. drivers/gpu/drm/tegra/falcon.c +259 −0
  8. drivers/gpu/drm/tegra/falcon.h +127 −0
  9. drivers/gpu/drm/tegra/fb.c +20 −3
  10. drivers/gpu/drm/tegra/gem.c +10 −2
  11. drivers/gpu/drm/tegra/vic.c +396 −0
  12. drivers/gpu/drm/tegra/vic.h +31 −0
  13. drivers/gpu/host1x/bus.c +34 −34
  14. drivers/gpu/host1x/cdma.c +58 −16
  15. drivers/gpu/host1x/cdma.h +4 −2
  16. drivers/gpu/host1x/dev.c +65 −11
  17. drivers/gpu/host1x/dev.h +11 −3
  18. drivers/gpu/host1x/hw/cdma_hw.c +7 −9
  19. drivers/gpu/host1x/job.c +62 −10
  20. drivers/gpu/host1x/job.h +1 −0
  21. drivers/gpu/host1x/syncpt.c +1 −1
  22. drivers/iommu/iova.c +33 −54
  23. include/linux/host1x.h +1 −0
  24. include/linux/iova.h +91 −0
  25. include/uapi/drm/drm_fourcc.h +45 −0
Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt+13−0
@@ -249,6 +249,19 @@ of the following host1x client modules: · 248 unmodified lines
249249 See ../pinctrl/nvidia,tegra124-dpaux-padctl.txt for information
250250 regarding the DPAUX pad controller bindings.
251251
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+
252265 Example:
253266
254267 / {
MAINTAINERS+2−0
@@ -6843,6 +6843,8 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git · 6842 unmodified lines
68436843 S: Maintained
68446844 F: Documentation/devicetree/bindings/iommu/
68456845 F: drivers/iommu/
6846+F: include/linux/iommu.h
6847+F: include/linux/iova.h
68466848
68476849 IP MASQUERADING
68486850 M: Juanjo Ciarlante <jjciarla@raiz.uncu.edu.ar>
drivers/gpu/drm/tegra/Kconfig+1−0
@@ -7,6 +7,7 @@ config DRM_TEGRA · 6 unmodified lines
77 select DRM_MIPI_DSI
88 select DRM_PANEL
99 select TEGRA_HOST1X
10+ select IOMMU_IOVA if IOMMU_SUPPORT
1011 help
1112 Choose this option if you have an NVIDIA Tegra SoC.
1213
drivers/gpu/drm/tegra/Makefile+3−1
@@ -13,6 +13,8 @@ tegra-drm-y := \ · 12 unmodified lines
1313 sor.o \
1414 dpaux.o \
1515 gr2d.o \
16− gr3d.o
16+ gr3d.o \
17+ falcon.o \
18+ vic.o
1719
1820 obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o
drivers/gpu/drm/tegra/drm.c+228−55
@@ -1,13 +1,15 @@
11 /*
22 * 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.
44 *
55 * This program is free software; you can redistribute it and/or modify
66 * it under the terms of the GNU General Public License version 2 as
77 * published by the Free Software Foundation.
88 */
99
10+#include <linux/bitops.h>
1011 #include <linux/host1x.h>
12+#include <linux/idr.h>
1113 #include <linux/iommu.h>
1214
1315 #include <drm/drm_atomic.h>
@@ -23,8 +25,11 @@ · 9 unmodified lines
2325 #define DRIVER_MINOR 0
2426 #define DRIVER_PATCHLEVEL 0
2527
28+#define CARVEOUT_SZ SZ_64M
29+
2630 struct tegra_drm_file {
27− struct list_head contexts;
31+ struct idr contexts;
32+ struct mutex lock;
2833 };
2934
3035 static void tegra_atomic_schedule(struct tegra_drm *tegra,
@@ -126,8 +131,9 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) · 95 unmodified lines
126131 return -ENOMEM;
127132
128133 if (iommu_present(&platform_bus_type)) {
134+ u64 carveout_start, carveout_end, gem_start, gem_end;
129135 struct iommu_domain_geometry *geometry;
130− u64 start, end;
136+ unsigned long order;
131137
132138 tegra->domain = iommu_domain_alloc(&platform_bus_type);
133139 if (!tegra->domain) {
@@ -136,12 +142,26 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) · 2 unmodified lines
136142 }
137143
138144 geometry = &tegra->domain->geometry;
139− start = geometry->aperture_start;
140− end = geometry->aperture_end;
141−
142− DRM_DEBUG_DRIVER("IOMMU aperture initialized (%#llx-%#llx)\n",
143− start, end);
144− drm_mm_init(&tegra->mm, start, end - start + 1);
145+ gem_start = geometry->aperture_start;
146+ gem_end = geometry->aperture_end - CARVEOUT_SZ;
147+ carveout_start = gem_end + 1;
148+ carveout_end = geometry->aperture_end;
149+
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);
145165 }
146166
147167 mutex_init(&tegra->clients_lock);
@@ -161,6 +181,8 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) · 13 unmodified lines
161181 drm->mode_config.max_width = 4096;
162182 drm->mode_config.max_height = 4096;
163183
184+ drm->mode_config.allow_fb_modifiers = true;
185+
164186 drm->mode_config.funcs = &tegra_drm_mode_funcs;
165187
166188 err = tegra_drm_fb_prepare(drm);
@@ -208,6 +230,8 @@ config: · 41 unmodified lines
208230 if (tegra->domain) {
209231 iommu_domain_free(tegra->domain);
210232 drm_mm_takedown(&tegra->mm);
233+ mutex_destroy(&tegra->mm_lock);
234+ put_iova_domain(&tegra->carveout.domain);
211235 }
212236 free:
213237 kfree(tegra);
@@ -232,6 +256,8 @@ static void tegra_drm_unload(struct drm_device *drm) · 18 unmodified lines
232256 if (tegra->domain) {
233257 iommu_domain_free(tegra->domain);
234258 drm_mm_takedown(&tegra->mm);
259+ mutex_destroy(&tegra->mm_lock);
260+ put_iova_domain(&tegra->carveout.domain);
235261 }
236262
237263 kfree(tegra);
@@ -245,7 +271,8 @@ static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp) · 7 unmodified lines
245271 if (!fpriv)
246272 return -ENOMEM;
247273
248− INIT_LIST_HEAD(&fpriv->contexts);
274+ idr_init(&fpriv->contexts);
275+ mutex_init(&fpriv->lock);
249276 filp->driver_priv = fpriv;
250277
251278 return 0;
@@ -424,21 +451,16 @@ fail: · 172 unmodified lines
424451
425452
426453 #ifdef CONFIG_DRM_TEGRA_STAGING
427−static struct tegra_drm_context *tegra_drm_get_context(__u64 context)
428−{
429− return (struct tegra_drm_context *)(uintptr_t)context;
430−}
431−
432−static bool tegra_drm_file_owns_context(struct tegra_drm_file *file,
433− struct tegra_drm_context *context)
454+static struct tegra_drm_context *
455+tegra_drm_file_get_context(struct tegra_drm_file *file, u32 id)
434456 {
435− struct tegra_drm_context *ctx;
457+ struct tegra_drm_context *context;
436458
437− list_for_each_entry(ctx, &file->contexts, list)
438− if (ctx == context)
439− return true;
459+ mutex_lock(&file->lock);
460+ context = idr_find(&file->contexts, id);
461+ mutex_unlock(&file->lock);
440462
441− return false;
463+ return context;
442464 }
443465
444466 static 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, · 74 unmodified lines
519541 &args->value);
520542 }
521543
544+static 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+
522566 static int tegra_open_channel(struct drm_device *drm, void *data,
523567 struct drm_file *file)
524568 {
@@ -533,19 +577,22 @@ static int tegra_open_channel(struct drm_device *drm, void *data, · 8 unmodified lines
533577 if (!context)
534578 return -ENOMEM;
535579
580+ mutex_lock(&fpriv->lock);
581+
536582 list_for_each_entry(client, &tegra->clients, list)
537583 if (client->base.class == args->client) {
538− err = client->ops->open_channel(client, context);
539− if (err)
584+ err = tegra_client_open(fpriv, client, context);
585+ if (err < 0)
540586 break;
541587
542− list_add(&context->list, &fpriv->contexts);
543− args->context = (uintptr_t)context;
544− context->client = client;
545− return 0;
588+ args->context = context->id;
589+ break;
546590 }
547591
548− kfree(context);
592+ if (err < 0)
593+ kfree(context);
594+
595+ mutex_unlock(&fpriv->lock);
549596 return err;
550597 }
551598
@@ -555,16 +602,22 @@ static int tegra_close_channel(struct drm_device *drm, void *data, · 3 unmodified lines
555602 struct tegra_drm_file *fpriv = file->driver_priv;
556603 struct drm_tegra_close_channel *args = data;
557604 struct tegra_drm_context *context;
605+ int err = 0;
558606
559− context = tegra_drm_get_context(args->context);
607+ mutex_lock(&fpriv->lock);
560608
561− if (!tegra_drm_file_owns_context(fpriv, context))
562− return -EINVAL;
609+ context = tegra_drm_file_get_context(fpriv, args->context);
610+ if (!context) {
611+ err = -EINVAL;
612+ goto unlock;
613+ }
563614
564− list_del(&context->list);
615+ idr_remove(&fpriv->contexts, context->id);
565616 tegra_drm_context_free(context);
566617
567− return 0;
618+unlock:
619+ mutex_unlock(&fpriv->lock);
620+ return err;
568621 }
569622
570623 static 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, · 3 unmodified lines
574627 struct drm_tegra_get_syncpt *args = data;
575628 struct tegra_drm_context *context;
576629 struct host1x_syncpt *syncpt;
630+ int err = 0;
577631
578− context = tegra_drm_get_context(args->context);
632+ mutex_lock(&fpriv->lock);
579633
580− if (!tegra_drm_file_owns_context(fpriv, context))
581− return -ENODEV;
634+ context = tegra_drm_file_get_context(fpriv, args->context);
635+ if (!context) {
636+ err = -ENODEV;
637+ goto unlock;
638+ }
582639
583− if (args->index >= context->client->base.num_syncpts)
584− return -EINVAL;
640+ if (args->index >= context->client->base.num_syncpts) {
641+ err = -EINVAL;
642+ goto unlock;
643+ }
585644
586645 syncpt = context->client->base.syncpts[args->index];
587646 args->id = host1x_syncpt_id(syncpt);
588647
589− return 0;
648+unlock:
649+ mutex_unlock(&fpriv->lock);
650+ return err;
590651 }
591652
592653 static int tegra_submit(struct drm_device *drm, void *data,
@@ -595,13 +656,21 @@ static int tegra_submit(struct drm_device *drm, void *data, · 2 unmodified lines
595656 struct tegra_drm_file *fpriv = file->driver_priv;
596657 struct drm_tegra_submit *args = data;
597658 struct tegra_drm_context *context;
659+ int err;
598660
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+ }
600668
601− if (!tegra_drm_file_owns_context(fpriv, context))
602− return -ENODEV;
669+ err = context->client->ops->submit(context, args, drm, file);
603670
604− return context->client->ops->submit(context, args, drm, file);
671+unlock:
672+ mutex_unlock(&fpriv->lock);
673+ return err;
605674 }
606675
607676 static 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, · 4 unmodified lines
612681 struct tegra_drm_context *context;
613682 struct host1x_syncpt_base *base;
614683 struct host1x_syncpt *syncpt;
684+ int err = 0;
615685
616− context = tegra_drm_get_context(args->context);
686+ mutex_lock(&fpriv->lock);
617687
618− if (!tegra_drm_file_owns_context(fpriv, context))
619− return -ENODEV;
688+ context = tegra_drm_file_get_context(fpriv, args->context);
689+ if (!context) {
690+ err = -ENODEV;
691+ goto unlock;
692+ }
620693
621− if (args->syncpt >= context->client->base.num_syncpts)
622− return -EINVAL;
694+ if (args->syncpt >= context->client->base.num_syncpts) {
695+ err = -EINVAL;
696+ goto unlock;
697+ }
623698
624699 syncpt = context->client->base.syncpts[args->syncpt];
625700
626701 base = host1x_syncpt_get_base(syncpt);
627− if (!base)
628− return -ENXIO;
702+ if (!base) {
703+ err = -ENXIO;
704+ goto unlock;
705+ }
629706
630707 args->id = host1x_syncpt_base_id(base);
631708
632− return 0;
709+unlock:
710+ mutex_unlock(&fpriv->lock);
711+ return err;
633712 }
634713
635714 static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
@@ -804,14 +883,25 @@ static const struct file_operations tegra_drm_fops = { · 168 unmodified lines
804883 .llseek = noop_llseek,
805884 };
806885
886+static 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+
807895 static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file)
808896 {
809897 struct tegra_drm_file *fpriv = file->driver_priv;
810− struct tegra_drm_context *context, *tmp;
811898
812− list_for_each_entry_safe(context, tmp, &fpriv->contexts, list)
813− tegra_drm_context_free(context);
899+ mutex_lock(&fpriv->lock);
900+ idr_for_each(&fpriv->contexts, tegra_drm_context_cleanup, NULL);
901+ mutex_unlock(&fpriv->lock);
814902
903+ idr_destroy(&fpriv->contexts);
904+ mutex_destroy(&fpriv->lock);
815905 kfree(fpriv);
816906 }
817907
@@ -844,7 +934,9 @@ static int tegra_debugfs_iova(struct seq_file *s, void *data) · 26 unmodified lines
844934 struct tegra_drm *tegra = drm->dev_private;
845935 struct drm_printer p = drm_seq_file_printer(s);
846936
937+ mutex_lock(&tegra->mm_lock);
847938 drm_mm_print(&tegra->mm, &p);
939+ mutex_unlock(&tegra->mm_lock);
848940
849941 return 0;
850942 }
@@ -919,6 +1011,84 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra, · 68 unmodified lines
9191011 return 0;
9201012 }
9211013
1014+void *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+
1067+free_iova:
1068+ __free_iova(&tegra->carveout.domain, alloc);
1069+free_pages:
1070+ free_pages((unsigned long)virt, get_order(size));
1071+
1072+ return ERR_PTR(err);
1073+}
1074+
1075+void 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+
9221092 static int host1x_drm_probe(struct host1x_device *dev)
9231093 {
9241094 struct drm_driver *driver = &tegra_drm_driver;
@@ -1003,11 +1173,13 @@ static const struct of_device_id host1x_drm_subdevs[] = { · 78 unmodified lines
10031173 { .compatible = "nvidia,tegra124-sor", },
10041174 { .compatible = "nvidia,tegra124-hdmi", },
10051175 { .compatible = "nvidia,tegra124-dsi", },
1176+ { .compatible = "nvidia,tegra124-vic", },
10061177 { .compatible = "nvidia,tegra132-dsi", },
10071178 { .compatible = "nvidia,tegra210-dc", },
10081179 { .compatible = "nvidia,tegra210-dsi", },
10091180 { .compatible = "nvidia,tegra210-sor", },
10101181 { .compatible = "nvidia,tegra210-sor1", },
1182+ { .compatible = "nvidia,tegra210-vic", },
10111183 { /* sentinel */ }
10121184 };
10131185
@@ -1029,6 +1201,7 @@ static struct platform_driver * const drivers[] = { · 15 unmodified lines
10291201 &tegra_sor_driver,
10301202 &tegra_gr2d_driver,
10311203 &tegra_gr3d_driver,
1204+ &tegra_vic_driver,
10321205 };
10331206
10341207 static int __init host1x_drm_init(void)
drivers/gpu/drm/tegra/drm.h+14−1
@@ -12,6 +12,7 @@ · 11 unmodified lines
1212
1313 #include <uapi/drm/tegra_drm.h>
1414 #include <linux/host1x.h>
15+#include <linux/iova.h>
1516 #include <linux/of_gpio.h>
1617
1718 #include <drm/drmP.h>
@@ -42,8 +43,15 @@ struct tegra_drm { · 24 unmodified lines
4243 struct drm_device *drm;
4344
4445 struct iommu_domain *domain;
46+ struct mutex mm_lock;
4547 struct drm_mm mm;
4648
49+ struct {
50+ struct iova_domain domain;
51+ unsigned long shift;
52+ unsigned long limit;
53+ } carveout;
54+
4755 struct mutex clients_lock;
4856 struct list_head clients;
4957
@@ -67,7 +75,7 @@ struct tegra_drm_client; · 17 unmodified lines
6775 struct tegra_drm_context {
6876 struct tegra_drm_client *client;
6977 struct host1x_channel *channel;
70− struct list_head list;
78+ unsigned int id;
7179 };
7280
7381 struct tegra_drm_client_ops {
@@ -105,6 +113,10 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra, · 31 unmodified lines
105113 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
106114 int tegra_drm_exit(struct tegra_drm *tegra);
107115
116+void *tegra_drm_alloc(struct tegra_drm *tegra, size_t size, dma_addr_t *iova);
117+void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt,
118+ dma_addr_t iova);
119+
108120 struct tegra_dc_soc_info;
109121 struct tegra_output;
110122
@@ -283,5 +295,6 @@ extern struct platform_driver tegra_dpaux_driver; · 172 unmodified lines
283295 extern struct platform_driver tegra_sor_driver;
284296 extern struct platform_driver tegra_gr2d_driver;
285297 extern struct platform_driver tegra_gr3d_driver;
298+extern struct platform_driver tegra_vic_driver;
286299
287300 #endif /* HOST1X_DRM_H */
drivers/gpu/drm/tegra/falcon.c+259−0
@@ -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+
18+enum falcon_memory {
19+ FALCON_MEMORY_IMEM,
20+ FALCON_MEMORY_DATA,
21+};
22+
23+static void falcon_writel(struct falcon *falcon, u32 value, u32 offset)
24+{
25+ writel(value, falcon->regs + offset);
26+}
27+
28+int 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+
36+static 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+
44+static 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+
61+static 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+
87+static 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+
122+int 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+
134+int 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+
164+err_setup_firmware_image:
165+ falcon->ops->free(falcon, falcon->firmware.size,
166+ falcon->firmware.paddr, falcon->firmware.vaddr);
167+
168+ return err;
169+}
170+
171+int 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+
182+void 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+
197+int 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+
255+void 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+}
drivers/gpu/drm/tegra/falcon.h+127−0
@@ -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+
59+struct 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+
68+struct falcon_fw_os_app_v1 {
69+ u32 offset;
70+ u32 size;
71+};
72+
73+struct falcon_fw_os_header_v1 {
74+ u32 code_offset;
75+ u32 code_size;
76+ u32 data_offset;
77+ u32 data_size;
78+};
79+
80+struct falcon;
81+
82+struct 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+
89+struct falcon_firmware_section {
90+ unsigned long offset;
91+ size_t size;
92+};
93+
94+struct 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+
109+struct 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+
119+int falcon_init(struct falcon *falcon);
120+void falcon_exit(struct falcon *falcon);
121+int falcon_read_firmware(struct falcon *falcon, const char *firmware_name);
122+int falcon_load_firmware(struct falcon *falcon);
123+int falcon_boot(struct falcon *falcon);
124+void falcon_execute_method(struct falcon *falcon, u32 method, u32 data);
125+int falcon_wait_idle(struct falcon *falcon);
126+
127+#endif /* _FALCON_H_ */
drivers/gpu/drm/tegra/fb.c+20−3
@@ -52,9 +52,26 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer, · 51 unmodified lines
5252 struct tegra_bo_tiling *tiling)
5353 {
5454 struct tegra_fb *fb = to_tegra_fb(framebuffer);
55−
56− /* TODO: handle YUV formats? */
57− *tiling = fb->planes[0]->tiling;
55+ uint64_t modifier = fb->base.modifier;
56+
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+ }
5875
5976 return 0;
6077 }
drivers/gpu/drm/tegra/gem.c+10−2
@@ -128,12 +128,14 @@ static int tegra_bo_iommu_map(struct tegra_drm *tegra, struct tegra_bo *bo) · 127 unmodified lines
128128 if (!bo->mm)
129129 return -ENOMEM;
130130
131+ mutex_lock(&tegra->mm_lock);
132+
131133 err = drm_mm_insert_node_generic(&tegra->mm,
132134 bo->mm, bo->gem.size, PAGE_SIZE, 0, 0);
133135 if (err < 0) {
134136 dev_err(tegra->drm->dev, "out of I/O virtual memory: %zd\n",
135137 err);
136− goto free;
138+ goto unlock;
137139 }
138140
139141 bo->paddr = bo->mm->start;
@@ -147,11 +149,14 @@ static int tegra_bo_iommu_map(struct tegra_drm *tegra, struct tegra_bo *bo) · 7 unmodified lines
147149
148150 bo->size = err;
149151
152+ mutex_unlock(&tegra->mm_lock);
153+
150154 return 0;
151155
152156 remove:
153157 drm_mm_remove_node(bo->mm);
154−free:
158+unlock:
159+ mutex_unlock(&tegra->mm_lock);
155160 kfree(bo->mm);
156161 return err;
157162 }
@@ -161,8 +166,11 @@ static int tegra_bo_iommu_unmap(struct tegra_drm *tegra, struct tegra_bo *bo) · 3 unmodified lines
161166 if (!bo->mm)
162167 return 0;
163168
169+ mutex_lock(&tegra->mm_lock);
164170 iommu_unmap(tegra->domain, bo->paddr, bo->size);
165171 drm_mm_remove_node(bo->mm);
172+ mutex_unlock(&tegra->mm_lock);
173+
166174 kfree(bo->mm);
167175
168176 return 0;
drivers/gpu/drm/tegra/vic.c+396−0
@@ -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+
26+struct vic_config {
27+ const char *firmware;
28+};
29+
30+struct 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+
45+static inline struct vic *to_vic(struct tegra_drm_client *client)
46+{
47+ return container_of(client, struct vic, client);
48+}
49+
50+static void vic_writel(struct vic *vic, u32 value, unsigned int offset)
51+{
52+ writel(value, vic->regs + offset);
53+}
54+
55+static 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+
62+static 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+
73+static 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+
117+static 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+
125+static 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+
133+static const struct falcon_ops vic_falcon_ops = {
134+ .alloc = vic_falcon_alloc,
135+ .free = vic_falcon_free
136+};
137+
138+static 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+
182+free_syncpt:
183+ host1x_syncpt_free(client->syncpts[0]);
184+free_channel:
185+ host1x_channel_free(vic->channel);
186+detach_device:
187+ if (tegra->domain)
188+ iommu_detach_device(tegra->domain, vic->dev);
189+
190+ return err;
191+}
192+
193+static 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+
216+static const struct host1x_client_ops vic_client_ops = {
217+ .init = vic_init,
218+ .exit = vic_exit,
219+};
220+
221+static 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+
246+static 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+
255+static 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+
261+static const struct vic_config vic_t124_config = {
262+ .firmware = "nvidia/tegra124/vic03_ucode.bin",
263+};
264+
265+static const struct vic_config vic_t210_config = {
266+ .firmware = "nvidia/tegra210/vic04_ucode.bin",
267+};
268+
269+static 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+
275+static 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+
354+unregister_client:
355+ host1x_client_unregister(&vic->client.base);
356+exit_falcon:
357+ falcon_exit(&vic->falcon);
358+
359+ return err;
360+}
361+
362+static 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+
384+static const struct dev_pm_ops vic_pm_ops = {
385+ SET_RUNTIME_PM_OPS(vic_runtime_suspend, vic_runtime_resume, NULL)
386+};
387+
388+struct 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+};
drivers/gpu/drm/tegra/vic.h+31−0
@@ -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 */
drivers/gpu/host1x/bus.c+34−34
@@ -267,37 +267,6 @@ static int host1x_device_match(struct device *dev, struct device_driver *drv) · 266 unmodified lines
267267 return strcmp(dev_name(dev), drv->name) == 0;
268268 }
269269
270−static 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−
281−static 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−
292−static 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−
301270 static const struct dev_pm_ops host1x_device_pm_ops = {
302271 .suspend = pm_generic_suspend,
303272 .resume = pm_generic_resume,
@@ -310,9 +279,6 @@ static const struct dev_pm_ops host1x_device_pm_ops = { · 6 unmodified lines
310279 struct bus_type host1x_bus_type = {
311280 .name = "host1x",
312281 .match = host1x_device_match,
313− .probe = host1x_device_probe,
314− .remove = host1x_device_remove,
315− .shutdown = host1x_device_shutdown,
316282 .pm = &host1x_device_pm_ops,
317283 };
318284
@@ -516,6 +482,37 @@ int host1x_unregister(struct host1x *host1x) · 197 unmodified lines
516482 return 0;
517483 }
518484
485+static 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+
496+static 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+
507+static 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+
519516 int host1x_driver_register_full(struct host1x_driver *driver,
520517 struct module *owner)
521518 {
@@ -536,6 +533,9 @@ int host1x_driver_register_full(struct host1x_driver *driver, · 14 unmodified lines
536533
537534 driver->driver.bus = &host1x_bus_type;
538535 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;
539539
540540 return driver_register(&driver->driver);
541541 }
drivers/gpu/host1x/cdma.c+58−16
@@ -51,9 +51,15 @@ static void host1x_pushbuffer_destroy(struct push_buffer *pb) · 50 unmodified lines
5151 struct host1x_cdma *cdma = pb_to_cdma(pb);
5252 struct host1x *host1x = cdma_to_host1x(cdma);
5353
54− if (pb->phys != 0)
55− dma_free_wc(host1x->dev, pb->size_bytes + 4, pb->mapped,
56− pb->phys);
54+ if (!pb->phys)
55+ return;
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);
5763
5864 pb->mapped = NULL;
5965 pb->phys = 0;
@@ -66,28 +72,64 @@ static int host1x_pushbuffer_init(struct push_buffer *pb) · 6 unmodified lines
6672 {
6773 struct host1x_cdma *cdma = pb_to_cdma(pb);
6874 struct host1x *host1x = cdma_to_host1x(cdma);
75+ struct iova *alloc;
76+ u32 size;
77+ int err;
6978
7079 pb->mapped = NULL;
7180 pb->phys = 0;
72− pb->size_bytes = HOST1X_PUSHBUFFER_SLOTS * 8;
81+ pb->size = HOST1X_PUSHBUFFER_SLOTS * 8;
82+
83+ size = pb->size + 4;
7384
7485 /* initialize buffer pointers */
75− pb->fence = pb->size_bytes - 8;
86+ pb->fence = pb->size - 8;
7687 pb->pos = 0;
7788
78− /* allocate and map pushbuffer memory */
79− pb->mapped = dma_alloc_wc(host1x->dev, pb->size_bytes + 4, &pb->phys,
80− GFP_KERNEL);
81− if (!pb->mapped)
82− goto fail;
89+ if (host1x->domain) {
90+ unsigned long shift;
91+
92+ size = iova_align(&host1x->iova, size);
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;
83122
84123 host1x_hw_pushbuffer_init(host1x, pb);
85124
86125 return 0;
87126
88−fail:
89− host1x_pushbuffer_destroy(pb);
90− return -ENOMEM;
127+iommu_free_iova:
128+ __free_iova(&host1x->iova, alloc);
129+iommu_free_mem:
130+ dma_free_wc(host1x->dev, pb->alloc_size, pb->mapped, pb->phys);
131+
132+ return err;
91133 }
92134
93135 /*
@@ -101,7 +143,7 @@ static void host1x_pushbuffer_push(struct push_buffer *pb, u32 op1, u32 op2) · 7 unmodified lines
101143 WARN_ON(pb->pos == pb->fence);
102144 *(p++) = op1;
103145 *(p++) = op2;
104− pb->pos = (pb->pos + 8) & (pb->size_bytes - 1);
146+ pb->pos = (pb->pos + 8) & (pb->size - 1);
105147 }
106148
107149 /*
@@ -111,7 +153,7 @@ static void host1x_pushbuffer_push(struct push_buffer *pb, u32 op1, u32 op2) · 3 unmodified lines
111153 static void host1x_pushbuffer_pop(struct push_buffer *pb, unsigned int slots)
112154 {
113155 /* 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);
115157 }
116158
117159 /*
@@ -119,7 +161,7 @@ static void host1x_pushbuffer_pop(struct push_buffer *pb, unsigned int slots) · 1 unmodified line
119161 */
120162 static u32 host1x_pushbuffer_space(struct push_buffer *pb)
121163 {
122− return ((pb->fence - pb->pos) & (pb->size_bytes - 1)) / 8;
164+ return ((pb->fence - pb->pos) & (pb->size - 1)) / 8;
123165 }
124166
125167 /*
drivers/gpu/host1x/cdma.h+4−2
@@ -43,10 +43,12 @@ struct host1x_job; · 42 unmodified lines
4343
4444 struct push_buffer {
4545 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 */
4748 u32 fence; /* index we've written */
4849 u32 pos; /* index to write to */
49− u32 size_bytes;
50+ u32 size;
51+ u32 alloc_size;
5052 };
5153
5254 struct buffer_timeout {
drivers/gpu/host1x/dev.c+65−11
@@ -16,23 +16,25 @@ · 15 unmodified lines
1616 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1717 */
1818
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>
2419 #include <linux/clk.h>
25−#include <linux/io.h>
2620 #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>
2727
2828 #define CREATE_TRACE_POINTS
2929 #include <trace/events/host1x.h>
30+#undef CREATE_TRACE_POINTS
3031
3132 #include "bus.h"
32−#include "dev.h"
33−#include "intr.h"
3433 #include "channel.h"
3534 #include "debug.h"
35+#include "dev.h"
36+#include "intr.h"
37+
3638 #include "hw/host1x01.h"
3739 #include "hw/host1x02.h"
3840 #include "hw/host1x04.h"
@@ -168,22 +170,56 @@ static int host1x_probe(struct platform_device *pdev) · 129 unmodified lines
168170 return err;
169171 }
170172
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+
171201 err = host1x_channel_list_init(host);
172202 if (err) {
173203 dev_err(&pdev->dev, "failed to initialize channel list\n");
174− return err;
204+ goto fail_detach_device;
175205 }
176206
177207 err = clk_prepare_enable(host->clk);
178208 if (err < 0) {
179209 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;
181217 }
182218
183219 err = host1x_syncpt_init(host);
184220 if (err) {
185221 dev_err(&pdev->dev, "failed to initialize syncpts\n");
186− goto fail_unprepare_disable;
222+ goto fail_reset_assert;
187223 }
188224
189225 err = host1x_intr_init(host, syncpt_irq);
@@ -204,8 +240,19 @@ fail_deinit_intr: · 14 unmodified lines
204240 host1x_intr_deinit(host);
205241 fail_deinit_syncpt:
206242 host1x_syncpt_deinit(host);
243+fail_reset_assert:
244+ reset_control_assert(host->rst);
207245 fail_unprepare_disable:
208246 clk_disable_unprepare(host->clk);
247+fail_detach_device:
248+ if (host->domain) {
249+ put_iova_domain(&host->iova);
250+ iommu_detach_device(host->domain, &pdev->dev);
251+ }
252+fail_free_domain:
253+ if (host->domain)
254+ iommu_domain_free(host->domain);
255+
209256 return err;
210257 }
211258
@@ -216,8 +263,15 @@ static int host1x_remove(struct platform_device *pdev) · 4 unmodified lines
216263 host1x_unregister(host);
217264 host1x_intr_deinit(host);
218265 host1x_syncpt_deinit(host);
266+ reset_control_assert(host->rst);
219267 clk_disable_unprepare(host->clk);
220268
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+
221275 return 0;
222276 }
223277
drivers/gpu/host1x/dev.h+11−3
@@ -17,14 +17,17 @@ · 16 unmodified lines
1717 #ifndef HOST1X_DEV_H
1818 #define HOST1X_DEV_H
1919
20−#include <linux/platform_device.h>
2120 #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>
2225
26+#include "cdma.h"
2327 #include "channel.h"
24−#include "syncpt.h"
2528 #include "intr.h"
26−#include "cdma.h"
2729 #include "job.h"
30+#include "syncpt.h"
2831
2932 struct host1x_syncpt;
3033 struct host1x_syncpt_base;
@@ -107,6 +110,11 @@ struct host1x { · 76 unmodified lines
107110 struct host1x_syncpt_base *bases;
108111 struct device *dev;
109112 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;
110118
111119 struct mutex intr_mutex;
112120 int intr_syncpt_irq;
drivers/gpu/host1x/hw/cdma_hw.c+7−9
@@ -30,7 +30,7 @@ · 29 unmodified lines
3030 */
3131 static void push_buffer_init(struct push_buffer *pb)
3232 {
33− *(u32 *)(pb->mapped + pb->size_bytes) = host1x_opcode_restart(0);
33+ *(u32 *)(pb->mapped + pb->size) = host1x_opcode_restart(0);
3434 }
3535
3636 /*
@@ -55,8 +55,8 @@ static void cdma_timeout_cpu_incr(struct host1x_cdma *cdma, u32 getptr, · 18 unmodified lines
5555 *(p++) = HOST1X_OPCODE_NOP;
5656 *(p++) = HOST1X_OPCODE_NOP;
5757 dev_dbg(host1x->dev, "%s: NOP at %pad+%#x\n", __func__,
58− &pb->phys, getptr);
59− getptr = (getptr + 8) & (pb->size_bytes - 1);
58+ &pb->dma, getptr);
59+ getptr = (getptr + 8) & (pb->size - 1);
6060 }
6161
6262 wmb();
@@ -78,10 +78,9 @@ static void cdma_start(struct host1x_cdma *cdma) · 15 unmodified lines
7878 HOST1X_CHANNEL_DMACTRL);
7979
8080 /* 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);
8282 host1x_ch_writel(ch, cdma->push_buffer.pos, HOST1X_CHANNEL_DMAPUT);
83− host1x_ch_writel(ch, cdma->push_buffer.phys +
84− cdma->push_buffer.size_bytes + 4,
83+ host1x_ch_writel(ch, cdma->push_buffer.dma + cdma->push_buffer.size + 4,
8584 HOST1X_CHANNEL_DMAEND);
8685
8786 /* reset GET */
@@ -115,9 +114,8 @@ static void cdma_timeout_restart(struct host1x_cdma *cdma, u32 getptr) · 27 unmodified lines
115114 HOST1X_CHANNEL_DMACTRL);
116115
117116 /* set base, end pointer (all of memory) */
118− host1x_ch_writel(ch, cdma->push_buffer.phys, HOST1X_CHANNEL_DMASTART);
119− host1x_ch_writel(ch, cdma->push_buffer.phys +
120− cdma->push_buffer.size_bytes,
117+ host1x_ch_writel(ch, cdma->push_buffer.dma, HOST1X_CHANNEL_DMASTART);
118+ host1x_ch_writel(ch, cdma->push_buffer.dma + cdma->push_buffer.size,
121119 HOST1X_CHANNEL_DMAEND);
122120
123121 /* set GET, by loading the value in PUT (then reset GET) */
drivers/gpu/host1x/job.c+62−10
@@ -174,9 +174,10 @@ static int do_waitchks(struct host1x_job *job, struct host1x *host, · 173 unmodified lines
174174 return 0;
175175 }
176176
177−static unsigned int pin_job(struct host1x_job *job)
177+static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
178178 {
179179 unsigned int i;
180+ int err;
180181
181182 job->num_unpins = 0;
182183
@@ -186,12 +187,16 @@ static unsigned int pin_job(struct host1x_job *job) · 3 unmodified lines
186187 dma_addr_t phys_addr;
187188
188189 reloc->target.bo = host1x_bo_get(reloc->target.bo);
189− if (!reloc->target.bo)
190+ if (!reloc->target.bo) {
191+ err = -EINVAL;
190192 goto unpin;
193+ }
191194
192195 phys_addr = host1x_bo_pin(reloc->target.bo, &sgt);
193− if (!phys_addr)
196+ if (!phys_addr) {
197+ err = -EINVAL;
194198 goto unpin;
199+ }
195200
196201 job->addr_phys[job->num_unpins] = phys_addr;
197202 job->unpins[job->num_unpins].bo = reloc->target.bo;
@@ -201,28 +206,67 @@ static unsigned int pin_job(struct host1x_job *job) · 3 unmodified lines
201206
202207 for (i = 0; i < job->num_gathers; i++) {
203208 struct host1x_job_gather *g = &job->gathers[i];
209+ size_t gather_size = 0;
210+ struct scatterlist *sg;
204211 struct sg_table *sgt;
205212 dma_addr_t phys_addr;
213+ unsigned long shift;
214+ struct iova *alloc;
215+ unsigned int j;
206216
207217 g->bo = host1x_bo_get(g->bo);
208− if (!g->bo)
218+ if (!g->bo) {
219+ err = -EINVAL;
209220 goto unpin;
221+ }
210222
211223 phys_addr = host1x_bo_pin(g->bo, &sgt);
212− if (!phys_addr)
224+ if (!phys_addr) {
225+ err = -EINVAL;
213226 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];
214259
215− job->addr_phys[job->num_unpins] = phys_addr;
216260 job->unpins[job->num_unpins].bo = g->bo;
217261 job->unpins[job->num_unpins].sgt = sgt;
218262 job->num_unpins++;
219263 }
220264
221− return job->num_unpins;
265+ return 0;
222266
223267 unpin:
224268 host1x_job_unpin(job);
225− return 0;
269+ return err;
226270 }
227271
228272 static 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) · 296 unmodified lines
525569 host1x_syncpt_load(host->syncpt + i);
526570
527571 /* pin memory */
528− err = pin_job(job);
529− if (!err)
572+ err = pin_job(host, job);
573+ if (err)
530574 goto out;
531575
532576 /* patch gathers */
@@ -572,11 +616,19 @@ EXPORT_SYMBOL(host1x_job_pin); · 39 unmodified lines
572616
573617 void host1x_job_unpin(struct host1x_job *job)
574618 {
619+ struct host1x *host = dev_get_drvdata(job->channel->dev->parent);
575620 unsigned int i;
576621
577622 for (i = 0; i < job->num_unpins; i++) {
578623 struct host1x_job_unpin_data *unpin = &job->unpins[i];
579624
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+
580632 host1x_bo_unpin(unpin->bo, unpin->sgt);
581633 host1x_bo_put(unpin->bo);
582634 }
drivers/gpu/host1x/job.h+1−0
@@ -44,6 +44,7 @@ struct host1x_waitchk { · 43 unmodified lines
4444 struct host1x_job_unpin_data {
4545 struct host1x_bo *bo;
4646 struct sg_table *sgt;
47+ size_t size;
4748 };
4849
4950 /*
drivers/gpu/host1x/syncpt.c+1−1
@@ -484,7 +484,7 @@ unsigned int host1x_syncpt_nb_mlocks(struct host1x *host) · 483 unmodified lines
484484
485485 struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, unsigned int id)
486486 {
487− if (host->info->nb_pts < id)
487+ if (id >= host->info->nb_pts)
488488 return NULL;
489489
490490 return host->syncpt + id;
drivers/iommu/iova.c+33−54
@@ -100,6 +100,34 @@ __cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free) · 99 unmodified lines
100100 }
101101 }
102102
103+/* Insert the iova into domain rbtree by holding writer lock */
104+static void
105+iova_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+
103131 /*
104132 * Computes the padding size required, to make the start address
105133 * naturally aligned on the power-of-two order of its size
@@ -157,35 +185,8 @@ move_left: · 51 unmodified lines
157185 new->pfn_lo = limit_pfn - (size + pad_size) + 1;
158186 new->pfn_hi = new->pfn_lo + size - 1;
159187
160− /* Insert the new_iova into domain rbtree by holding writer lock */
161− /* Add new node and rebalance tree. */
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− }
188+ /* If we have 'prev', it's a valid place to start the insertion. */
189+ iova_insert_rbtree(&iovad->rbroot, new, prev);
189190 __cached_rbnode_insert_update(iovad, saved_pfn, new);
190191
191192 spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
@@ -194,28 +195,6 @@ move_left: · 2 unmodified lines
194195 return 0;
195196 }
196197
197−static void
198−iova_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−
219198 static struct kmem_cache *iova_cache;
220199 static unsigned int iova_cache_users;
221200 static DEFINE_MUTEX(iova_cache_mutex);
@@ -505,7 +484,7 @@ __insert_new_range(struct iova_domain *iovad, · 283 unmodified lines
505484
506485 iova = alloc_and_init_iova(pfn_lo, pfn_hi);
507486 if (iova)
508− iova_insert_rbtree(&iovad->rbroot, iova);
487+ iova_insert_rbtree(&iovad->rbroot, iova, NULL);
509488
510489 return iova;
511490 }
@@ -612,11 +591,11 @@ split_and_remove_iova(struct iova_domain *iovad, struct iova *iova, · 100 unmodified lines
612591 rb_erase(&iova->node, &iovad->rbroot);
613592
614593 if (prev) {
615− iova_insert_rbtree(&iovad->rbroot, prev);
594+ iova_insert_rbtree(&iovad->rbroot, prev, NULL);
616595 iova->pfn_lo = pfn_lo;
617596 }
618597 if (next) {
619− iova_insert_rbtree(&iovad->rbroot, next);
598+ iova_insert_rbtree(&iovad->rbroot, next, NULL);
620599 iova->pfn_hi = pfn_hi;
621600 }
622601 spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
include/linux/host1x.h+1−0
@@ -26,6 +26,7 @@ enum host1x_class { · 25 unmodified lines
2626 HOST1X_CLASS_HOST1X = 0x1,
2727 HOST1X_CLASS_GR2D = 0x51,
2828 HOST1X_CLASS_GR2D_SB = 0x52,
29+ HOST1X_CLASS_VIC = 0x5D,
2930 HOST1X_CLASS_GR3D = 0x60,
3031 };
3132
include/linux/iova.h+91−0
@@ -82,6 +82,7 @@ static inline unsigned long iova_pfn(struct iova_domain *iovad, dma_addr_t iova) · 81 unmodified lines
8282 return iova >> iova_shift(iovad);
8383 }
8484
85+#if IS_ENABLED(CONFIG_IOMMU_IOVA)
8586 int iova_cache_get(void);
8687 void iova_cache_put(void);
8788
@@ -106,5 +107,95 @@ void put_iova_domain(struct iova_domain *iovad); · 18 unmodified lines
106107 struct iova *split_and_remove_iova(struct iova_domain *iovad,
107108 struct iova *iova, unsigned long pfn_lo, unsigned long pfn_hi);
108109 void free_cpu_cached_iovas(unsigned int cpu, struct iova_domain *iovad);
110+#else
111+static inline int iova_cache_get(void)
112+{
113+ return -ENOTSUPP;
114+}
115+
116+static inline void iova_cache_put(void)
117+{
118+}
119+
120+static inline struct iova *alloc_iova_mem(void)
121+{
122+ return NULL;
123+}
124+
125+static inline void free_iova_mem(struct iova *iova)
126+{
127+}
128+
129+static inline void free_iova(struct iova_domain *iovad, unsigned long pfn)
130+{
131+}
132+
133+static inline void __free_iova(struct iova_domain *iovad, struct iova *iova)
134+{
135+}
136+
137+static 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+
145+static inline void free_iova_fast(struct iova_domain *iovad,
146+ unsigned long pfn,
147+ unsigned long size)
148+{
149+}
150+
151+static 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+
158+static 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+
165+static inline void copy_reserved_iova(struct iova_domain *from,
166+ struct iova_domain *to)
167+{
168+}
169+
170+static 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+
177+static inline struct iova *find_iova(struct iova_domain *iovad,
178+ unsigned long pfn)
179+{
180+ return NULL;
181+}
182+
183+static inline void put_iova_domain(struct iova_domain *iovad)
184+{
185+}
186+
187+static 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+
195+static inline void free_cpu_cached_iovas(unsigned int cpu,
196+ struct iova_domain *iovad)
197+{
198+}
199+#endif
109200
110201 #endif
include/uapi/drm/drm_fourcc.h+45−0
@@ -306,6 +306,51 @@ extern "C" { · 305 unmodified lines
306306 */
307307 #define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4)
308308
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+
309354 #if defined(__cplusplus)
310355 }
311356 #endif