diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/drm_mm.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index d0a8e8482fe0..276a7a27c166 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
@@ -47,6 +47,45 @@ | |||
47 | #include <linux/seq_file.h> | 47 | #include <linux/seq_file.h> |
48 | #include <linux/export.h> | 48 | #include <linux/export.h> |
49 | 49 | ||
50 | /** | ||
51 | * DOC: Overview | ||
52 | * | ||
53 | * drm_mm provides a simple range allocator. The drivers are free to use the | ||
54 | * resource allocator from the linux core if it suits them, the upside of drm_mm | ||
55 | * is that it's in the DRM core. Which means that it's easier to extend for | ||
56 | * some of the crazier special purpose needs of gpus. | ||
57 | * | ||
58 | * The main data struct is &drm_mm, allocations are tracked in &drm_mm_node. | ||
59 | * Drivers are free to embed either of them into their own suitable | ||
60 | * datastructures. drm_mm itself will not do any allocations of its own, so if | ||
61 | * drivers choose not to embed nodes they need to still allocate them | ||
62 | * themselves. | ||
63 | * | ||
64 | * The range allocator also supports reservation of preallocated blocks. This is | ||
65 | * useful for taking over initial mode setting configurations from the firmware, | ||
66 | * where an object needs to be created which exactly matches the firmware's | ||
67 | * scanout target. As long as the range is still free it can be inserted anytime | ||
68 | * after the allocator is initialized, which helps with avoiding looped | ||
69 | * depencies in the driver load sequence. | ||
70 | * | ||
71 | * drm_mm maintains a stack of most recently freed holes, which of all | ||
72 | * simplistic datastructures seems to be a fairly decent approach to clustering | ||
73 | * allocations and avoiding too much fragmentation. This means free space | ||
74 | * searches are O(num_holes). Given that all the fancy features drm_mm supports | ||
75 | * something better would be fairly complex and since gfx thrashing is a fairly | ||
76 | * steep cliff not a real concern. Removing a node again is O(1). | ||
77 | * | ||
78 | * drm_mm supports a few features: Alignment and range restrictions can be | ||
79 | * supplied. Further more every &drm_mm_node has a color value (which is just an | ||
80 | * opaqua unsigned long) which in conjunction with a driver callback can be used | ||
81 | * to implement sophisticated placement restrictions. The i915 DRM driver uses | ||
82 | * this to implement guard pages between incompatible caching domains in the | ||
83 | * graphics TT. | ||
84 | * | ||
85 | * Finally iteration helpers to walk all nodes and all holes are provided as are | ||
86 | * some basic allocator dumpers for debugging. | ||
87 | */ | ||
88 | |||
50 | static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, | 89 | static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, |
51 | unsigned long size, | 90 | unsigned long size, |
52 | unsigned alignment, | 91 | unsigned alignment, |
@@ -400,6 +439,34 @@ void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new) | |||
400 | EXPORT_SYMBOL(drm_mm_replace_node); | 439 | EXPORT_SYMBOL(drm_mm_replace_node); |
401 | 440 | ||
402 | /** | 441 | /** |
442 | * DOC: lru scan roaster | ||
443 | * | ||
444 | * Very often GPUs need to have continuous allocations for a given object. When | ||
445 | * evicting objects to make space for a new one it is therefore not most | ||
446 | * efficient when we simply start to select all objects from the tail of an LRU | ||
447 | * until there's a suitable hole: Especially for big objects or nodes that | ||
448 | * otherwise have special allocation constraints there's a good chance we evict | ||
449 | * lots of (smaller) objects unecessarily. | ||
450 | * | ||
451 | * The DRM range allocator supports this use-case through the scanning | ||
452 | * interfaces. First a scan operation needs to be initialized with | ||
453 | * drm_mm_init_scan() or drm_mm_init_scan_with_range(). The the driver adds | ||
454 | * objects to the roaster (probably by walking an LRU list, but this can be | ||
455 | * freely implemented) until a suitable hole is found or there's no further | ||
456 | * evitable object. | ||
457 | * | ||
458 | * The the driver must walk through all objects again in exactly the reverse | ||
459 | * order to restore the allocator state. Note that while the allocator is used | ||
460 | * in the scan mode no other operation is allowed. | ||
461 | * | ||
462 | * Finally the driver evicts all objects selected in the scan. Adding and | ||
463 | * removing an object is O(1), and since freeing a node is also O(1) the overall | ||
464 | * complexity is O(scanned_objects). So like the free stack which needs to be | ||
465 | * walked before a scan operation even begins this is linear in the number of | ||
466 | * objects. It doesn't seem to hurt badly. | ||
467 | */ | ||
468 | |||
469 | /** | ||
403 | * Initializa lru scanning. | 470 | * Initializa lru scanning. |
404 | * | 471 | * |
405 | * This simply sets up the scanning routines with the parameters for the desired | 472 | * This simply sets up the scanning routines with the parameters for the desired |