diff options
author | Benjamin Gaignard <benjamin.gaignard@linaro.org> | 2017-01-04 04:12:57 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-01-06 05:04:54 -0500 |
commit | 62a0d98a188cc4ebd8ea54b37d274ec20465e464 (patch) | |
tree | bb649f5cc408727179380fce600adeba99b2ebbd | |
parent | 99c48e1e38f0aeaa107ad67c8d91f6c9d9d567a9 (diff) |
drm: allow to use mmuless SoC
Some SoC without MMU have display driver where a drm/kms driver
could be implemented.
Before doing such kind of thing drm/kms must allow to use mmuless devices.
This patch propose to remove MMU configuration flag and add a cma helper
function to help implementing mmuless display driver
version 4:
- add documentation about drm_gem_cma_get_unmapped_area()
- stub it MMU case
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
[danvet: Use recommended struct member references in kernel-doc.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1483521177-21794-4-git-send-email-benjamin.gaignard@linaro.org
-rw-r--r-- | Documentation/gpu/drm-mm.rst | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/Kconfig | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_gem_cma_helper.c | 71 | ||||
-rw-r--r-- | include/drm/drm_gem_cma_helper.h | 17 |
4 files changed, 101 insertions, 2 deletions
diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index d3c6d77246cd..1ea94fc86caa 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst | |||
@@ -310,6 +310,17 @@ created. | |||
310 | Drivers that want to map the GEM object upfront instead of handling page | 310 | Drivers that want to map the GEM object upfront instead of handling page |
311 | faults can implement their own mmap file operation handler. | 311 | faults can implement their own mmap file operation handler. |
312 | 312 | ||
313 | For platforms without MMU the GEM core provides a helper method | ||
314 | :c:func:`drm_gem_cma_get_unmapped_area`. The mmap() routines will call | ||
315 | this to get a proposed address for the mapping. | ||
316 | |||
317 | To use :c:func:`drm_gem_cma_get_unmapped_area`, drivers must fill the | ||
318 | struct :c:type:`struct file_operations <file_operations>` get_unmapped_area | ||
319 | field with a pointer on :c:func:`drm_gem_cma_get_unmapped_area`. | ||
320 | |||
321 | More detailed information about get_unmapped_area can be found in | ||
322 | Documentation/nommu-mmap.txt | ||
323 | |||
313 | Memory Coherency | 324 | Memory Coherency |
314 | ---------------- | 325 | ---------------- |
315 | 326 | ||
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index d56b85c03b7b..505ca1d262ee 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
@@ -6,7 +6,7 @@ | |||
6 | # | 6 | # |
7 | menuconfig DRM | 7 | menuconfig DRM |
8 | tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" | 8 | tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" |
9 | depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU && HAS_DMA | 9 | depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA |
10 | select HDMI | 10 | select HDMI |
11 | select FB_CMDLINE | 11 | select FB_CMDLINE |
12 | select I2C | 12 | select I2C |
@@ -113,7 +113,7 @@ config DRM_LOAD_EDID_FIRMWARE | |||
113 | 113 | ||
114 | config DRM_TTM | 114 | config DRM_TTM |
115 | tristate | 115 | tristate |
116 | depends on DRM | 116 | depends on DRM && MMU |
117 | help | 117 | help |
118 | GPU memory management subsystem for devices with multiple | 118 | GPU memory management subsystem for devices with multiple |
119 | GPU memory types. Will be enabled automatically if a device driver | 119 | GPU memory types. Will be enabled automatically if a device driver |
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c index e0806a2ad11c..5cf38a474845 100644 --- a/drivers/gpu/drm/drm_gem_cma_helper.c +++ b/drivers/gpu/drm/drm_gem_cma_helper.c | |||
@@ -358,6 +358,77 @@ int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma) | |||
358 | } | 358 | } |
359 | EXPORT_SYMBOL_GPL(drm_gem_cma_mmap); | 359 | EXPORT_SYMBOL_GPL(drm_gem_cma_mmap); |
360 | 360 | ||
361 | #ifndef CONFIG_MMU | ||
362 | /** | ||
363 | * drm_gem_cma_get_unmapped_area - propose address for mapping in noMMU cases | ||
364 | * @filp: file object | ||
365 | * @addr: memory address | ||
366 | * @len: buffer size | ||
367 | * @pgoff: page offset | ||
368 | * @flags: memory flags | ||
369 | * | ||
370 | * This function is used in noMMU platforms to propose address mapping | ||
371 | * for a given buffer. | ||
372 | * It's intended to be used as a direct handler for the struct | ||
373 | * &file_operations.get_unmapped_area operation. | ||
374 | * | ||
375 | * Returns: | ||
376 | * mapping address on success or a negative error code on failure. | ||
377 | */ | ||
378 | unsigned long drm_gem_cma_get_unmapped_area(struct file *filp, | ||
379 | unsigned long addr, | ||
380 | unsigned long len, | ||
381 | unsigned long pgoff, | ||
382 | unsigned long flags) | ||
383 | { | ||
384 | struct drm_gem_cma_object *cma_obj; | ||
385 | struct drm_gem_object *obj = NULL; | ||
386 | struct drm_file *priv = filp->private_data; | ||
387 | struct drm_device *dev = priv->minor->dev; | ||
388 | struct drm_vma_offset_node *node; | ||
389 | |||
390 | if (drm_device_is_unplugged(dev)) | ||
391 | return -ENODEV; | ||
392 | |||
393 | drm_vma_offset_lock_lookup(dev->vma_offset_manager); | ||
394 | node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager, | ||
395 | pgoff, | ||
396 | len >> PAGE_SHIFT); | ||
397 | if (likely(node)) { | ||
398 | obj = container_of(node, struct drm_gem_object, vma_node); | ||
399 | /* | ||
400 | * When the object is being freed, after it hits 0-refcnt it | ||
401 | * proceeds to tear down the object. In the process it will | ||
402 | * attempt to remove the VMA offset and so acquire this | ||
403 | * mgr->vm_lock. Therefore if we find an object with a 0-refcnt | ||
404 | * that matches our range, we know it is in the process of being | ||
405 | * destroyed and will be freed as soon as we release the lock - | ||
406 | * so we have to check for the 0-refcnted object and treat it as | ||
407 | * invalid. | ||
408 | */ | ||
409 | if (!kref_get_unless_zero(&obj->refcount)) | ||
410 | obj = NULL; | ||
411 | } | ||
412 | |||
413 | drm_vma_offset_unlock_lookup(dev->vma_offset_manager); | ||
414 | |||
415 | if (!obj) | ||
416 | return -EINVAL; | ||
417 | |||
418 | if (!drm_vma_node_is_allowed(node, priv)) { | ||
419 | drm_gem_object_unreference_unlocked(obj); | ||
420 | return -EACCES; | ||
421 | } | ||
422 | |||
423 | cma_obj = to_drm_gem_cma_obj(obj); | ||
424 | |||
425 | drm_gem_object_unreference_unlocked(obj); | ||
426 | |||
427 | return cma_obj->vaddr ? (unsigned long)cma_obj->vaddr : -EINVAL; | ||
428 | } | ||
429 | EXPORT_SYMBOL_GPL(drm_gem_cma_get_unmapped_area); | ||
430 | #endif | ||
431 | |||
361 | #ifdef CONFIG_DEBUG_FS | 432 | #ifdef CONFIG_DEBUG_FS |
362 | /** | 433 | /** |
363 | * drm_gem_cma_describe - describe a CMA GEM object for debugfs | 434 | * drm_gem_cma_describe - describe a CMA GEM object for debugfs |
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h index acd6af8a8e67..2abcd5190cc1 100644 --- a/include/drm/drm_gem_cma_helper.h +++ b/include/drm/drm_gem_cma_helper.h | |||
@@ -53,6 +53,23 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, | |||
53 | 53 | ||
54 | extern const struct vm_operations_struct drm_gem_cma_vm_ops; | 54 | extern const struct vm_operations_struct drm_gem_cma_vm_ops; |
55 | 55 | ||
56 | #ifndef CONFIG_MMU | ||
57 | unsigned long drm_gem_cma_get_unmapped_area(struct file *filp, | ||
58 | unsigned long addr, | ||
59 | unsigned long len, | ||
60 | unsigned long pgoff, | ||
61 | unsigned long flags); | ||
62 | #else | ||
63 | static inline unsigned long drm_gem_cma_get_unmapped_area(struct file *filp, | ||
64 | unsigned long addr, | ||
65 | unsigned long len, | ||
66 | unsigned long pgoff, | ||
67 | unsigned long flags) | ||
68 | { | ||
69 | return -EINVAL; | ||
70 | } | ||
71 | #endif | ||
72 | |||
56 | #ifdef CONFIG_DEBUG_FS | 73 | #ifdef CONFIG_DEBUG_FS |
57 | void drm_gem_cma_describe(struct drm_gem_cma_object *obj, struct seq_file *m); | 74 | void drm_gem_cma_describe(struct drm_gem_cma_object *obj, struct seq_file *m); |
58 | #endif | 75 | #endif |