diff options
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 42 |
3 files changed, 47 insertions, 9 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 814665b7a117..20d5485eaf98 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
| @@ -453,12 +453,13 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv) | |||
| 453 | */ | 453 | */ |
| 454 | static int vmw_dma_select_mode(struct vmw_private *dev_priv) | 454 | static int vmw_dma_select_mode(struct vmw_private *dev_priv) |
| 455 | { | 455 | { |
| 456 | const struct dma_map_ops *dma_ops = get_dma_ops(dev_priv->dev->dev); | ||
| 457 | static const char *names[vmw_dma_map_max] = { | 456 | static const char *names[vmw_dma_map_max] = { |
| 458 | [vmw_dma_phys] = "Using physical TTM page addresses.", | 457 | [vmw_dma_phys] = "Using physical TTM page addresses.", |
| 459 | [vmw_dma_alloc_coherent] = "Using coherent TTM pages.", | 458 | [vmw_dma_alloc_coherent] = "Using coherent TTM pages.", |
| 460 | [vmw_dma_map_populate] = "Keeping DMA mappings.", | 459 | [vmw_dma_map_populate] = "Keeping DMA mappings.", |
| 461 | [vmw_dma_map_bind] = "Giving up DMA mappings early."}; | 460 | [vmw_dma_map_bind] = "Giving up DMA mappings early."}; |
| 461 | #ifdef CONFIG_X86 | ||
| 462 | const struct dma_map_ops *dma_ops = get_dma_ops(dev_priv->dev->dev); | ||
| 462 | 463 | ||
| 463 | #ifdef CONFIG_INTEL_IOMMU | 464 | #ifdef CONFIG_INTEL_IOMMU |
| 464 | if (intel_iommu_enabled) { | 465 | if (intel_iommu_enabled) { |
| @@ -500,6 +501,10 @@ out_fixup: | |||
| 500 | return -EINVAL; | 501 | return -EINVAL; |
| 501 | #endif | 502 | #endif |
| 502 | 503 | ||
| 504 | #else /* CONFIG_X86 */ | ||
| 505 | dev_priv->map_mode = vmw_dma_map_populate; | ||
| 506 | #endif /* CONFIG_X86 */ | ||
| 507 | |||
| 503 | DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]); | 508 | DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]); |
| 504 | 509 | ||
| 505 | return 0; | 510 | return 0; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c index 6d0952366f91..6ef0b035becb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c | |||
| @@ -145,7 +145,9 @@ static void vmw_gmr_free_descriptors(struct device *dev, dma_addr_t desc_dma, | |||
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | page_virtual = kmap_atomic(page); | 147 | page_virtual = kmap_atomic(page); |
| 148 | desc_dma = page_virtual[desc_per_page].ppn << PAGE_SHIFT; | 148 | desc_dma = (dma_addr_t) |
| 149 | le32_to_cpu(page_virtual[desc_per_page].ppn) << | ||
| 150 | PAGE_SHIFT; | ||
| 149 | kunmap_atomic(page_virtual); | 151 | kunmap_atomic(page_virtual); |
| 150 | 152 | ||
| 151 | __free_page(page); | 153 | __free_page(page); |
| @@ -217,7 +219,8 @@ static int vmw_gmr_build_descriptors(struct device *dev, | |||
| 217 | desc_dma = 0; | 219 | desc_dma = 0; |
| 218 | list_for_each_entry_reverse(page, desc_pages, lru) { | 220 | list_for_each_entry_reverse(page, desc_pages, lru) { |
| 219 | page_virtual = kmap_atomic(page); | 221 | page_virtual = kmap_atomic(page); |
| 220 | page_virtual[desc_per_page].ppn = desc_dma >> PAGE_SHIFT; | 222 | page_virtual[desc_per_page].ppn = cpu_to_le32 |
| 223 | (desc_dma >> PAGE_SHIFT); | ||
| 221 | kunmap_atomic(page_virtual); | 224 | kunmap_atomic(page_virtual); |
| 222 | desc_dma = dma_map_page(dev, page, 0, PAGE_SIZE, | 225 | desc_dma = dma_map_page(dev, page, 0, PAGE_SIZE, |
| 223 | DMA_TO_DEVICE); | 226 | DMA_TO_DEVICE); |
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 | ||
