diff options
author | Rob Clark <robdclark@gmail.com> | 2016-05-27 11:16:28 -0400 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2016-07-16 10:09:07 -0400 |
commit | e1e9db2ca79575b8d6b4b5891194bb29c630c42d (patch) | |
tree | 645b6ec8caf75d2a26d6e62836eb514a5f78ad90 | |
parent | 18f23049f640e2590930c34009418c66e6ebf7b6 (diff) |
drm/msm: wire up vmap shrinker
Signed-off-by: Rob Clark <robdclark@gmail.com>
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem_shrinker.c | 40 |
4 files changed, 72 insertions, 5 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index ecf0b3b03e0e..b4bc7f1ef717 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h | |||
@@ -153,6 +153,7 @@ struct msm_drm_private { | |||
153 | struct drm_mm mm; | 153 | struct drm_mm mm; |
154 | } vram; | 154 | } vram; |
155 | 155 | ||
156 | struct notifier_block vmap_notifier; | ||
156 | struct shrinker shrinker; | 157 | struct shrinker shrinker; |
157 | 158 | ||
158 | struct msm_vblank_ctrl vblank_ctrl; | 159 | struct msm_vblank_ctrl vblank_ctrl; |
@@ -206,6 +207,7 @@ void msm_gem_put_vaddr_locked(struct drm_gem_object *obj); | |||
206 | void msm_gem_put_vaddr(struct drm_gem_object *obj); | 207 | void msm_gem_put_vaddr(struct drm_gem_object *obj); |
207 | int msm_gem_madvise(struct drm_gem_object *obj, unsigned madv); | 208 | int msm_gem_madvise(struct drm_gem_object *obj, unsigned madv); |
208 | void msm_gem_purge(struct drm_gem_object *obj); | 209 | void msm_gem_purge(struct drm_gem_object *obj); |
210 | void msm_gem_vunmap(struct drm_gem_object *obj); | ||
209 | int msm_gem_sync_object(struct drm_gem_object *obj, | 211 | int msm_gem_sync_object(struct drm_gem_object *obj, |
210 | struct msm_fence_context *fctx, bool exclusive); | 212 | struct msm_fence_context *fctx, bool exclusive); |
211 | void msm_gem_move_to_active(struct drm_gem_object *obj, | 213 | void msm_gem_move_to_active(struct drm_gem_object *obj, |
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index c05fc1d0dce7..886cfe0383ff 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c | |||
@@ -421,6 +421,7 @@ void *msm_gem_get_vaddr_locked(struct drm_gem_object *obj) | |||
421 | if (msm_obj->vaddr == NULL) | 421 | if (msm_obj->vaddr == NULL) |
422 | return ERR_PTR(-ENOMEM); | 422 | return ERR_PTR(-ENOMEM); |
423 | } | 423 | } |
424 | msm_obj->vmap_count++; | ||
424 | return msm_obj->vaddr; | 425 | return msm_obj->vaddr; |
425 | } | 426 | } |
426 | 427 | ||
@@ -435,13 +436,17 @@ void *msm_gem_get_vaddr(struct drm_gem_object *obj) | |||
435 | 436 | ||
436 | void msm_gem_put_vaddr_locked(struct drm_gem_object *obj) | 437 | void msm_gem_put_vaddr_locked(struct drm_gem_object *obj) |
437 | { | 438 | { |
439 | struct msm_gem_object *msm_obj = to_msm_bo(obj); | ||
438 | WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); | 440 | WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); |
439 | /* no-op for now */ | 441 | WARN_ON(msm_obj->vmap_count < 1); |
442 | msm_obj->vmap_count--; | ||
440 | } | 443 | } |
441 | 444 | ||
442 | void msm_gem_put_vaddr(struct drm_gem_object *obj) | 445 | void msm_gem_put_vaddr(struct drm_gem_object *obj) |
443 | { | 446 | { |
444 | /* no-op for now */ | 447 | mutex_lock(&obj->dev->struct_mutex); |
448 | msm_gem_put_vaddr_locked(obj); | ||
449 | mutex_unlock(&obj->dev->struct_mutex); | ||
445 | } | 450 | } |
446 | 451 | ||
447 | /* Update madvise status, returns true if not purged, else | 452 | /* Update madvise status, returns true if not purged, else |
@@ -470,8 +475,7 @@ void msm_gem_purge(struct drm_gem_object *obj) | |||
470 | 475 | ||
471 | put_iova(obj); | 476 | put_iova(obj); |
472 | 477 | ||
473 | vunmap(msm_obj->vaddr); | 478 | msm_gem_vunmap(obj); |
474 | msm_obj->vaddr = NULL; | ||
475 | 479 | ||
476 | put_pages(obj); | 480 | put_pages(obj); |
477 | 481 | ||
@@ -491,6 +495,17 @@ void msm_gem_purge(struct drm_gem_object *obj) | |||
491 | 0, (loff_t)-1); | 495 | 0, (loff_t)-1); |
492 | } | 496 | } |
493 | 497 | ||
498 | void msm_gem_vunmap(struct drm_gem_object *obj) | ||
499 | { | ||
500 | struct msm_gem_object *msm_obj = to_msm_bo(obj); | ||
501 | |||
502 | if (!msm_obj->vaddr || WARN_ON(!is_vunmapable(msm_obj))) | ||
503 | return; | ||
504 | |||
505 | vunmap(msm_obj->vaddr); | ||
506 | msm_obj->vaddr = NULL; | ||
507 | } | ||
508 | |||
494 | /* must be called before _move_to_active().. */ | 509 | /* must be called before _move_to_active().. */ |
495 | int msm_gem_sync_object(struct drm_gem_object *obj, | 510 | int msm_gem_sync_object(struct drm_gem_object *obj, |
496 | struct msm_fence_context *fctx, bool exclusive) | 511 | struct msm_fence_context *fctx, bool exclusive) |
@@ -694,7 +709,7 @@ void msm_gem_free_object(struct drm_gem_object *obj) | |||
694 | 709 | ||
695 | drm_prime_gem_destroy(obj, msm_obj->sgt); | 710 | drm_prime_gem_destroy(obj, msm_obj->sgt); |
696 | } else { | 711 | } else { |
697 | vunmap(msm_obj->vaddr); | 712 | msm_gem_vunmap(obj); |
698 | put_pages(obj); | 713 | put_pages(obj); |
699 | } | 714 | } |
700 | 715 | ||
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 631dab56b8fd..7a4da819731a 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h | |||
@@ -34,6 +34,11 @@ struct msm_gem_object { | |||
34 | */ | 34 | */ |
35 | uint8_t madv; | 35 | uint8_t madv; |
36 | 36 | ||
37 | /** | ||
38 | * count of active vmap'ing | ||
39 | */ | ||
40 | uint8_t vmap_count; | ||
41 | |||
37 | /* And object is either: | 42 | /* And object is either: |
38 | * inactive - on priv->inactive_list | 43 | * inactive - on priv->inactive_list |
39 | * active - on one one of the gpu's active_list.. well, at | 44 | * active - on one one of the gpu's active_list.. well, at |
@@ -83,6 +88,11 @@ static inline bool is_purgeable(struct msm_gem_object *msm_obj) | |||
83 | !msm_obj->base.dma_buf && !msm_obj->base.import_attach; | 88 | !msm_obj->base.dma_buf && !msm_obj->base.import_attach; |
84 | } | 89 | } |
85 | 90 | ||
91 | static inline bool is_vunmapable(struct msm_gem_object *msm_obj) | ||
92 | { | ||
93 | return (msm_obj->vmap_count == 0) && msm_obj->vaddr; | ||
94 | } | ||
95 | |||
86 | #define MAX_CMDS 4 | 96 | #define MAX_CMDS 4 |
87 | 97 | ||
88 | /* Created per submit-ioctl, to track bo's and cmdstream bufs, etc, | 98 | /* Created per submit-ioctl, to track bo's and cmdstream bufs, etc, |
diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c index 70fba9baddde..283d2841ba58 100644 --- a/drivers/gpu/drm/msm/msm_gem_shrinker.c +++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c | |||
@@ -100,6 +100,42 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) | |||
100 | return freed; | 100 | return freed; |
101 | } | 101 | } |
102 | 102 | ||
103 | static int | ||
104 | msm_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr) | ||
105 | { | ||
106 | struct msm_drm_private *priv = | ||
107 | container_of(nb, struct msm_drm_private, vmap_notifier); | ||
108 | struct drm_device *dev = priv->dev; | ||
109 | struct msm_gem_object *msm_obj; | ||
110 | unsigned unmapped = 0; | ||
111 | bool unlock; | ||
112 | |||
113 | if (!msm_gem_shrinker_lock(dev, &unlock)) | ||
114 | return NOTIFY_DONE; | ||
115 | |||
116 | list_for_each_entry(msm_obj, &priv->inactive_list, mm_list) { | ||
117 | if (is_vunmapable(msm_obj)) { | ||
118 | msm_gem_vunmap(&msm_obj->base); | ||
119 | /* since we don't know any better, lets bail after a few | ||
120 | * and if necessary the shrinker will be invoked again. | ||
121 | * Seems better than unmapping *everything* | ||
122 | */ | ||
123 | if (++unmapped >= 15) | ||
124 | break; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | if (unlock) | ||
129 | mutex_unlock(&dev->struct_mutex); | ||
130 | |||
131 | *(unsigned long *)ptr += unmapped; | ||
132 | |||
133 | if (unmapped > 0) | ||
134 | pr_info_ratelimited("Purging %u vmaps\n", unmapped); | ||
135 | |||
136 | return NOTIFY_DONE; | ||
137 | } | ||
138 | |||
103 | /** | 139 | /** |
104 | * msm_gem_shrinker_init - Initialize msm shrinker | 140 | * msm_gem_shrinker_init - Initialize msm shrinker |
105 | * @dev_priv: msm device | 141 | * @dev_priv: msm device |
@@ -113,6 +149,9 @@ void msm_gem_shrinker_init(struct drm_device *dev) | |||
113 | priv->shrinker.scan_objects = msm_gem_shrinker_scan; | 149 | priv->shrinker.scan_objects = msm_gem_shrinker_scan; |
114 | priv->shrinker.seeks = DEFAULT_SEEKS; | 150 | priv->shrinker.seeks = DEFAULT_SEEKS; |
115 | WARN_ON(register_shrinker(&priv->shrinker)); | 151 | WARN_ON(register_shrinker(&priv->shrinker)); |
152 | |||
153 | priv->vmap_notifier.notifier_call = msm_gem_shrinker_vmap; | ||
154 | WARN_ON(register_vmap_purge_notifier(&priv->vmap_notifier)); | ||
116 | } | 155 | } |
117 | 156 | ||
118 | /** | 157 | /** |
@@ -124,5 +163,6 @@ void msm_gem_shrinker_init(struct drm_device *dev) | |||
124 | void msm_gem_shrinker_cleanup(struct drm_device *dev) | 163 | void msm_gem_shrinker_cleanup(struct drm_device *dev) |
125 | { | 164 | { |
126 | struct msm_drm_private *priv = dev->dev_private; | 165 | struct msm_drm_private *priv = dev->dev_private; |
166 | WARN_ON(unregister_vmap_purge_notifier(&priv->vmap_notifier)); | ||
127 | unregister_shrinker(&priv->shrinker); | 167 | unregister_shrinker(&priv->shrinker); |
128 | } | 168 | } |