aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_resource.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 37fb4befec82..252501a54def 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -32,6 +32,8 @@
32#include <drm/drmP.h> 32#include <drm/drmP.h>
33#include "vmwgfx_resource_priv.h" 33#include "vmwgfx_resource_priv.h"
34 34
35#define VMW_RES_EVICT_ERR_COUNT 10
36
35struct vmw_user_dma_buffer { 37struct vmw_user_dma_buffer {
36 struct ttm_base_object base; 38 struct ttm_base_object base;
37 struct vmw_dma_buffer dma; 39 struct vmw_dma_buffer dma;
@@ -1091,8 +1093,9 @@ vmw_resource_backoff_reservation(struct ww_acquire_ctx *ticket,
1091 * to a backup buffer. 1093 * to a backup buffer.
1092 * 1094 *
1093 * @res: The resource to evict. 1095 * @res: The resource to evict.
1096 * @interruptible: Whether to wait interruptible.
1094 */ 1097 */
1095int vmw_resource_do_evict(struct vmw_resource *res) 1098int vmw_resource_do_evict(struct vmw_resource *res, bool interruptible)
1096{ 1099{
1097 struct ttm_validate_buffer val_buf; 1100 struct ttm_validate_buffer val_buf;
1098 const struct vmw_res_func *func = res->func; 1101 const struct vmw_res_func *func = res->func;
@@ -1102,7 +1105,8 @@ int vmw_resource_do_evict(struct vmw_resource *res)
1102 BUG_ON(!func->may_evict); 1105 BUG_ON(!func->may_evict);
1103 1106
1104 val_buf.bo = NULL; 1107 val_buf.bo = NULL;
1105 ret = vmw_resource_check_buffer(res, &ticket, true, &val_buf); 1108 ret = vmw_resource_check_buffer(res, &ticket, interruptible,
1109 &val_buf);
1106 if (unlikely(ret != 0)) 1110 if (unlikely(ret != 0))
1107 return ret; 1111 return ret;
1108 1112
@@ -1141,6 +1145,7 @@ int vmw_resource_validate(struct vmw_resource *res)
1141 struct vmw_private *dev_priv = res->dev_priv; 1145 struct vmw_private *dev_priv = res->dev_priv;
1142 struct list_head *lru_list = &dev_priv->res_lru[res->func->res_type]; 1146 struct list_head *lru_list = &dev_priv->res_lru[res->func->res_type];
1143 struct ttm_validate_buffer val_buf; 1147 struct ttm_validate_buffer val_buf;
1148 unsigned err_count = 0;
1144 1149
1145 if (likely(!res->func->may_evict)) 1150 if (likely(!res->func->may_evict))
1146 return 0; 1151 return 0;
@@ -1155,7 +1160,7 @@ int vmw_resource_validate(struct vmw_resource *res)
1155 1160
1156 write_lock(&dev_priv->resource_lock); 1161 write_lock(&dev_priv->resource_lock);
1157 if (list_empty(lru_list) || !res->func->may_evict) { 1162 if (list_empty(lru_list) || !res->func->may_evict) {
1158 DRM_ERROR("Out of device device id entries " 1163 DRM_ERROR("Out of device device resources "
1159 "for %s.\n", res->func->type_name); 1164 "for %s.\n", res->func->type_name);
1160 ret = -EBUSY; 1165 ret = -EBUSY;
1161 write_unlock(&dev_priv->resource_lock); 1166 write_unlock(&dev_priv->resource_lock);
@@ -1168,7 +1173,19 @@ int vmw_resource_validate(struct vmw_resource *res)
1168 list_del_init(&evict_res->lru_head); 1173 list_del_init(&evict_res->lru_head);
1169 1174
1170 write_unlock(&dev_priv->resource_lock); 1175 write_unlock(&dev_priv->resource_lock);
1171 vmw_resource_do_evict(evict_res); 1176
1177 ret = vmw_resource_do_evict(evict_res, true);
1178 if (unlikely(ret != 0)) {
1179 write_lock(&dev_priv->resource_lock);
1180 list_add_tail(&evict_res->lru_head, lru_list);
1181 write_unlock(&dev_priv->resource_lock);
1182 if (ret == -ERESTARTSYS ||
1183 ++err_count > VMW_RES_EVICT_ERR_COUNT) {
1184 vmw_resource_unreference(&evict_res);
1185 goto out_no_validate;
1186 }
1187 }
1188
1172 vmw_resource_unreference(&evict_res); 1189 vmw_resource_unreference(&evict_res);
1173 } while (1); 1190 } while (1);
1174 1191
@@ -1253,13 +1270,15 @@ bool vmw_resource_needs_backup(const struct vmw_resource *res)
1253 * @type: The resource type to evict 1270 * @type: The resource type to evict
1254 * 1271 *
1255 * To avoid thrashing starvation or as part of the hibernation sequence, 1272 * To avoid thrashing starvation or as part of the hibernation sequence,
1256 * evict all evictable resources of a specific type. 1273 * try to evict all evictable resources of a specific type.
1257 */ 1274 */
1258static void vmw_resource_evict_type(struct vmw_private *dev_priv, 1275static void vmw_resource_evict_type(struct vmw_private *dev_priv,
1259 enum vmw_res_type type) 1276 enum vmw_res_type type)
1260{ 1277{
1261 struct list_head *lru_list = &dev_priv->res_lru[type]; 1278 struct list_head *lru_list = &dev_priv->res_lru[type];
1262 struct vmw_resource *evict_res; 1279 struct vmw_resource *evict_res;
1280 unsigned err_count = 0;
1281 int ret;
1263 1282
1264 do { 1283 do {
1265 write_lock(&dev_priv->resource_lock); 1284 write_lock(&dev_priv->resource_lock);
@@ -1272,7 +1291,18 @@ static void vmw_resource_evict_type(struct vmw_private *dev_priv,
1272 lru_head)); 1291 lru_head));
1273 list_del_init(&evict_res->lru_head); 1292 list_del_init(&evict_res->lru_head);
1274 write_unlock(&dev_priv->resource_lock); 1293 write_unlock(&dev_priv->resource_lock);
1275 vmw_resource_do_evict(evict_res); 1294
1295 ret = vmw_resource_do_evict(evict_res, false);
1296 if (unlikely(ret != 0)) {
1297 write_lock(&dev_priv->resource_lock);
1298 list_add_tail(&evict_res->lru_head, lru_list);
1299 write_unlock(&dev_priv->resource_lock);
1300 if (++err_count > VMW_RES_EVICT_ERR_COUNT) {
1301 vmw_resource_unreference(&evict_res);
1302 return;
1303 }
1304 }
1305
1276 vmw_resource_unreference(&evict_res); 1306 vmw_resource_unreference(&evict_res);
1277 } while (1); 1307 } while (1);
1278 1308