summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/msm_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/msm_drv.c')
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c81
1 files changed, 78 insertions, 3 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 14ab9a627d8b..1ed4cd09dbf8 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -26,6 +26,7 @@
#include "msm_gem.h"
#include "msm_gpu.h"
#include "msm_kms.h"
+#include "msm_mmu.h"
#include "adreno/adreno_gpu.h"
/*
@@ -267,12 +268,56 @@ static int msm_drm_uninit(struct device *dev)
#include <linux/of_address.h>
+struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev)
+{
+ struct iommu_domain *domain;
+ struct msm_gem_address_space *aspace;
+ struct msm_mmu *mmu;
+ struct device *mdp_dev = dev->dev;
+ struct device *mdss_dev = mdp_dev->parent;
+ struct device *iommu_dev;
+
+ /*
+ * IOMMUs can be a part of MDSS device tree binding, or the
+ * MDP/DPU device.
+ */
+ if (device_iommu_mapped(mdp_dev))
+ iommu_dev = mdp_dev;
+ else
+ iommu_dev = mdss_dev;
+
+ domain = iommu_domain_alloc(iommu_dev->bus);
+ if (!domain) {
+ drm_info(dev, "no IOMMU, fallback to phys contig buffers for scanout\n");
+ return NULL;
+ }
+
+ mmu = msm_iommu_new(iommu_dev, domain);
+ if (IS_ERR(mmu)) {
+ iommu_domain_free(domain);
+ return ERR_CAST(mmu);
+ }
+
+ aspace = msm_gem_address_space_create(mmu, "mdp_kms",
+ 0x1000, 0x100000000 - 0x1000);
+ if (IS_ERR(aspace))
+ mmu->funcs->destroy(mmu);
+
+ return aspace;
+}
+
bool msm_use_mmu(struct drm_device *dev)
{
struct msm_drm_private *priv = dev->dev_private;
- /* a2xx comes with its own MMU */
- return priv->is_a2xx || iommu_present(&platform_bus_type);
+ /*
+ * a2xx comes with its own MMU
+ * On other platforms IOMMU can be declared specified either for the
+ * MDP/DPU device or for its parent, MDSS device.
+ */
+ return priv->is_a2xx ||
+ device_iommu_mapped(dev->dev) ||
+ device_iommu_mapped(dev->dev->parent);
}
static int msm_init_vram(struct drm_device *dev)
@@ -633,12 +678,25 @@ static int msm_ioctl_gem_new(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct drm_msm_gem_new *args = data;
+ uint32_t flags = args->flags;
if (args->flags & ~MSM_BO_FLAGS) {
DRM_ERROR("invalid flags: %08x\n", args->flags);
return -EINVAL;
}
+ /*
+ * Uncached CPU mappings are deprecated, as of:
+ *
+ * 9ef364432db4 ("drm/msm: deprecate MSM_BO_UNCACHED (map as writecombine instead)")
+ *
+ * So promote them to WC.
+ */
+ if (flags & MSM_BO_UNCACHED) {
+ flags &= ~MSM_BO_CACHED;
+ flags |= MSM_BO_WC;
+ }
+
return msm_gem_new_handle(dev, file, args->size,
args->flags, &args->handle, NULL);
}
@@ -948,7 +1006,24 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW),
};
-DEFINE_DRM_GEM_FOPS(fops);
+static void msm_fop_show_fdinfo(struct seq_file *m, struct file *f)
+{
+ struct drm_file *file = f->private_data;
+ struct drm_device *dev = file->minor->dev;
+ struct msm_drm_private *priv = dev->dev_private;
+ struct drm_printer p = drm_seq_file_printer(m);
+
+ if (!priv->gpu)
+ return;
+
+ msm_gpu_show_fdinfo(priv->gpu, file->driver_priv, &p);
+}
+
+static const struct file_operations fops = {
+ .owner = THIS_MODULE,
+ DRM_GEM_FOPS,
+ .show_fdinfo = msm_fop_show_fdinfo,
+};
static const struct drm_driver msm_driver = {
.driver_features = DRIVER_GEM |