summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/etnaviv/etnaviv_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/etnaviv/etnaviv_drv.c')
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.c139
1 files changed, 93 insertions, 46 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 31a7f59ccb49..54ceae87b401 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -6,7 +6,9 @@
#include <linux/component.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
-#include <linux/of_platform.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <drm/drm_debugfs.h>
@@ -15,6 +17,7 @@
#include <drm/drm_ioctl.h>
#include <drm/drm_of.h>
#include <drm/drm_prime.h>
+#include <drm/drm_print.h>
#include "etnaviv_cmdbuf.h"
#include "etnaviv_drv.h"
@@ -27,6 +30,17 @@
* DRM operations:
*/
+static struct device_node *etnaviv_of_first_available_node(void)
+{
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "vivante,gc") {
+ if (of_device_is_available(np))
+ return np;
+ }
+
+ return NULL;
+}
static void load_gpu(struct drm_device *dev)
{
@@ -77,7 +91,7 @@ static int etnaviv_open(struct drm_device *dev, struct drm_file *file)
drm_sched_entity_init(&ctx->sched_entity[i],
DRM_SCHED_PRIORITY_NORMAL, &sched,
1, NULL);
- }
+ }
}
file->driver_priv = ctx;
@@ -231,11 +245,11 @@ static int show_each_gpu(struct seq_file *m, void *arg)
}
static struct drm_info_list etnaviv_debugfs_list[] = {
- {"gpu", show_each_gpu, 0, etnaviv_gpu_debugfs},
- {"gem", show_unlocked, 0, etnaviv_gem_show},
- { "mm", show_unlocked, 0, etnaviv_mm_show },
- {"mmu", show_each_gpu, 0, etnaviv_mmu_show},
- {"ring", show_each_gpu, 0, etnaviv_ring_show},
+ {"gpu", show_each_gpu, 0, etnaviv_gpu_debugfs},
+ {"gem", show_unlocked, 0, etnaviv_gem_show},
+ { "mm", show_unlocked, 0, etnaviv_mm_show },
+ {"mmu", show_each_gpu, 0, etnaviv_mmu_show},
+ {"ring", show_each_gpu, 0, etnaviv_ring_show},
};
static void etnaviv_debugfs_init(struct drm_minor *minor)
@@ -475,27 +489,33 @@ static const struct drm_ioctl_desc etnaviv_ioctls[] = {
ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_RENDER_ALLOW),
};
-DEFINE_DRM_GEM_FOPS(fops);
+static void etnaviv_show_fdinfo(struct drm_printer *p, struct drm_file *file)
+{
+ drm_show_memory_stats(p, file);
+}
+
+static const struct file_operations fops = {
+ .owner = THIS_MODULE,
+ DRM_GEM_FOPS,
+ .show_fdinfo = drm_show_fdinfo,
+};
static const struct drm_driver etnaviv_drm_driver = {
.driver_features = DRIVER_GEM | DRIVER_RENDER,
.open = etnaviv_open,
.postclose = etnaviv_postclose,
- .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
- .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_import_sg_table = etnaviv_gem_prime_import_sg_table,
- .gem_prime_mmap = drm_gem_prime_mmap,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = etnaviv_debugfs_init,
#endif
+ .show_fdinfo = etnaviv_show_fdinfo,
.ioctls = etnaviv_ioctls,
.num_ioctls = DRM_ETNAVIV_NUM_IOCTLS,
.fops = &fops,
.name = "etnaviv",
.desc = "etnaviv DRM",
- .date = "20151214",
.major = 1,
- .minor = 3,
+ .minor = 4,
};
/*
@@ -528,6 +548,16 @@ static int etnaviv_bind(struct device *dev)
priv->num_gpus = 0;
priv->shm_gfp_mask = GFP_HIGHUSER | __GFP_RETRY_MAYFAIL | __GFP_NOWARN;
+ /*
+ * If the GPU is part of a system with DMA addressing limitations,
+ * request pages for our SHM backend buffers from the DMA32 zone to
+ * hopefully avoid performance killing SWIOTLB bounce buffering.
+ */
+ if (dma_addressing_limited(dev)) {
+ priv->shm_gfp_mask |= GFP_DMA32;
+ priv->shm_gfp_mask &= ~__GFP_HIGHMEM;
+ }
+
priv->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(drm->dev);
if (IS_ERR(priv->cmdbuf_suballoc)) {
dev_err(drm->dev, "Failed to create cmdbuf suballocator\n");
@@ -554,6 +584,7 @@ out_unbind:
out_destroy_suballoc:
etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc);
out_free_priv:
+ mutex_destroy(&priv->gem_lock);
kfree(priv);
out_put:
drm_dev_put(drm);
@@ -598,10 +629,7 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
if (!of_device_is_available(core_node))
continue;
- if (!first_node)
- first_node = core_node;
-
- drm_of_component_match_add(&pdev->dev, &match,
+ drm_of_component_match_add(dev, &match,
component_compare_of, core_node);
}
} else {
@@ -624,9 +652,9 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
* bit to make sure we are allocating the command buffers and
* TLBs in the lower 4 GiB address space.
*/
- if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)) ||
- dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) {
- dev_dbg(&pdev->dev, "No suitable DMA available\n");
+ if (dma_set_mask(dev, DMA_BIT_MASK(40)) ||
+ dma_set_coherent_mask(dev, DMA_BIT_MASK(32))) {
+ dev_dbg(dev, "No suitable DMA available\n");
return -ENODEV;
}
@@ -635,17 +663,18 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
* device as the GPU we found. This assumes that all Vivante
* GPUs in the system share the same DMA constraints.
*/
- if (first_node)
- of_dma_configure(&pdev->dev, first_node, true);
+ first_node = etnaviv_of_first_available_node();
+ if (first_node) {
+ of_dma_configure(dev, first_node, true);
+ of_node_put(first_node);
+ }
return component_master_add_with_match(dev, &etnaviv_master_ops, match);
}
-static int etnaviv_pdev_remove(struct platform_device *pdev)
+static void etnaviv_pdev_remove(struct platform_device *pdev)
{
component_master_del(&pdev->dev, &etnaviv_master_ops);
-
- return 0;
}
static struct platform_driver etnaviv_platform_driver = {
@@ -656,11 +685,43 @@ static struct platform_driver etnaviv_platform_driver = {
},
};
+static int etnaviv_create_platform_device(const char *name,
+ struct platform_device **ppdev)
+{
+ struct platform_device *pdev;
+ int ret;
+
+ pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE);
+ if (!pdev)
+ return -ENOMEM;
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ platform_device_put(pdev);
+ return ret;
+ }
+
+ *ppdev = pdev;
+
+ return 0;
+}
+
+static void etnaviv_destroy_platform_device(struct platform_device **ppdev)
+{
+ struct platform_device *pdev = *ppdev;
+
+ if (!pdev)
+ return;
+
+ platform_device_unregister(pdev);
+
+ *ppdev = NULL;
+}
+
static struct platform_device *etnaviv_drm;
static int __init etnaviv_init(void)
{
- struct platform_device *pdev;
int ret;
struct device_node *np;
@@ -678,27 +739,13 @@ static int __init etnaviv_init(void)
* If the DT contains at least one available GPU device, instantiate
* the DRM platform device.
*/
- for_each_compatible_node(np, NULL, "vivante,gc") {
- if (!of_device_is_available(np))
- continue;
-
- pdev = platform_device_alloc("etnaviv", PLATFORM_DEVID_NONE);
- if (!pdev) {
- ret = -ENOMEM;
- of_node_put(np);
- goto unregister_platform_driver;
- }
+ np = etnaviv_of_first_available_node();
+ if (np) {
+ of_node_put(np);
- ret = platform_device_add(pdev);
- if (ret) {
- platform_device_put(pdev);
- of_node_put(np);
+ ret = etnaviv_create_platform_device("etnaviv", &etnaviv_drm);
+ if (ret)
goto unregister_platform_driver;
- }
-
- etnaviv_drm = pdev;
- of_node_put(np);
- break;
}
return 0;
@@ -713,7 +760,7 @@ module_init(etnaviv_init);
static void __exit etnaviv_exit(void)
{
- platform_device_unregister(etnaviv_drm);
+ etnaviv_destroy_platform_device(&etnaviv_drm);
platform_driver_unregister(&etnaviv_platform_driver);
platform_driver_unregister(&etnaviv_gpu_driver);
}