diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_resource.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 42 |
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 | |||
35 | struct vmw_user_dma_buffer { | 37 | struct 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 | */ |
1095 | int vmw_resource_do_evict(struct vmw_resource *res) | 1098 | int 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 | */ |
1258 | static void vmw_resource_evict_type(struct vmw_private *dev_priv, | 1275 | static 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 | ||