History

Merge tag 'drm/tegra/for-4.12-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next

drm/tegra: Changes for v4.12-rc1 This contains various fixes to the host1x driver as well as a plug for a leak of kernel pointers to userspace. A fairly big addition this time around is the Video Image Composer (VIC) support that can be used to accelerate some 2D and image compositing operations. Furthermore the driver now supports FB modifiers, so we no longer rely on a custom IOCTL to set those. Finally this contains a few preparatory patches for Tegra186 support which unfortunately didn't quite make it this time, but will hopefully be ready for v4.13. * tag 'drm/tegra/for-4.12-rc1' of git://anongit.freedesktop.org/tegra/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

Dave Airlie committed 9 years ago

Commit 644b4932 parents 8b03d1e b0d36da25 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
@@ -6780,6 +6780,8 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git · 6779 unmodified lines
67806780 S: Maintained
67816781 F: Documentation/devicetree/bindings/iommu/
67826782 F: drivers/iommu/
6783+F: include/linux/iommu.h
6784+F: include/linux/iova.h
67836785
67846786 IP MASQUERADING
67856787 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

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t