Two fixes for the raspberrypi panel initialisation, one fix for a logic inversion in radeon, a build and pm refcounting fix for vc4, two reverts for drm_of_get_bridge that caused a number of regression and a locking regression for amdgpu. Signed-off-by: Dave Airlie <airlied@redhat.com>
Unified · Split
| @@ -128,6 +128,8 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs · 127 unmodified lines | |||
| 128 | goto free_chunk; | 128 | goto free_chunk; |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | mutex_lock(&p->ctx->lock); | ||
| 132 | |||
| 131 | /* skip guilty context job */ | 133 | /* skip guilty context job */ |
| 132 | if (atomic_read(&p->ctx->guilty) == 1) { | 134 | if (atomic_read(&p->ctx->guilty) == 1) { |
| 133 | ret = -ECANCELED; | 135 | ret = -ECANCELED; |
| @@ -709,6 +711,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, · 575 unmodified lines | |||
| 709 | dma_fence_put(parser->fence); | 711 | dma_fence_put(parser->fence); |
| 710 | 712 | ||
| 711 | if (parser->ctx) { | 713 | if (parser->ctx) { |
| 714 | mutex_unlock(&parser->ctx->lock); | ||
| 712 | amdgpu_ctx_put(parser->ctx); | 715 | amdgpu_ctx_put(parser->ctx); |
| 713 | } | 716 | } |
| 714 | if (parser->bo_list) | 717 | if (parser->bo_list) |
| @@ -1157,6 +1160,9 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, · 442 unmodified lines | |||
| 1157 | { | 1160 | { |
| 1158 | int i, r; | 1161 | int i, r; |
| 1159 | 1162 | ||
| 1163 | /* TODO: Investigate why we still need the context lock */ | ||
| 1164 | mutex_unlock(&p->ctx->lock); | ||
| 1165 | |||
| 1160 | for (i = 0; i < p->nchunks; ++i) { | 1166 | for (i = 0; i < p->nchunks; ++i) { |
| 1161 | struct amdgpu_cs_chunk *chunk; | 1167 | struct amdgpu_cs_chunk *chunk; |
| 1162 | 1168 | ||
| @@ -1167,32 +1173,34 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, · 4 unmodified lines | |||
| 1167 | case AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES: | 1173 | case AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES: |
| 1168 | r = amdgpu_cs_process_fence_dep(p, chunk); | 1174 | r = amdgpu_cs_process_fence_dep(p, chunk); |
| 1169 | if (r) | 1175 | if (r) |
| 1170 | return r; | 1176 | goto out; |
| 1171 | break; | 1177 | break; |
| 1172 | case AMDGPU_CHUNK_ID_SYNCOBJ_IN: | 1178 | case AMDGPU_CHUNK_ID_SYNCOBJ_IN: |
| 1173 | r = amdgpu_cs_process_syncobj_in_dep(p, chunk); | 1179 | r = amdgpu_cs_process_syncobj_in_dep(p, chunk); |
| 1174 | if (r) | 1180 | if (r) |
| 1175 | return r; | 1181 | goto out; |
| 1176 | break; | 1182 | break; |
| 1177 | case AMDGPU_CHUNK_ID_SYNCOBJ_OUT: | 1183 | case AMDGPU_CHUNK_ID_SYNCOBJ_OUT: |
| 1178 | r = amdgpu_cs_process_syncobj_out_dep(p, chunk); | 1184 | r = amdgpu_cs_process_syncobj_out_dep(p, chunk); |
| 1179 | if (r) | 1185 | if (r) |
| 1180 | return r; | 1186 | goto out; |
| 1181 | break; | 1187 | break; |
| 1182 | case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT: | 1188 | case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT: |
| 1183 | r = amdgpu_cs_process_syncobj_timeline_in_dep(p, chunk); | 1189 | r = amdgpu_cs_process_syncobj_timeline_in_dep(p, chunk); |
| 1184 | if (r) | 1190 | if (r) |
| 1185 | return r; | 1191 | goto out; |
| 1186 | break; | 1192 | break; |
| 1187 | case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL: | 1193 | case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL: |
| 1188 | r = amdgpu_cs_process_syncobj_timeline_out_dep(p, chunk); | 1194 | r = amdgpu_cs_process_syncobj_timeline_out_dep(p, chunk); |
| 1189 | if (r) | 1195 | if (r) |
| 1190 | return r; | 1196 | goto out; |
| 1191 | break; | 1197 | break; |
| 1192 | } | 1198 | } |
| 1193 | } | 1199 | } |
| 1194 | 1200 | ||
| 1195 | return 0; | 1201 | out: |
| 1202 | mutex_lock(&p->ctx->lock); | ||
| 1203 | return r; | ||
| 1196 | } | 1204 | } |
| 1197 | 1205 | ||
| 1198 | static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p) | 1206 | static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p) |
| @@ -1368,6 +1376,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) · 169 unmodified lines | |||
| 1368 | goto out; | 1376 | goto out; |
| 1369 | 1377 | ||
| 1370 | r = amdgpu_cs_submit(&parser, cs); | 1378 | r = amdgpu_cs_submit(&parser, cs); |
| 1379 | |||
| 1371 | out: | 1380 | out: |
| 1372 | amdgpu_cs_parser_fini(&parser, r, reserved_buffers); | 1381 | amdgpu_cs_parser_fini(&parser, r, reserved_buffers); |
| 1373 | 1382 | ||
| @@ -237,6 +237,7 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, · 236 unmodified lines | |||
| 237 | 237 | ||
| 238 | kref_init(&ctx->refcount); | 238 | kref_init(&ctx->refcount); |
| 239 | spin_lock_init(&ctx->ring_lock); | 239 | spin_lock_init(&ctx->ring_lock); |
| 240 | mutex_init(&ctx->lock); | ||
| 240 | 241 | ||
| 241 | ctx->reset_counter = atomic_read(&adev->gpu_reset_counter); | 242 | ctx->reset_counter = atomic_read(&adev->gpu_reset_counter); |
| 242 | ctx->reset_counter_query = ctx->reset_counter; | 243 | ctx->reset_counter_query = ctx->reset_counter; |
| @@ -357,6 +358,7 @@ static void amdgpu_ctx_fini(struct kref *ref) · 114 unmodified lines | |||
| 357 | drm_dev_exit(idx); | 358 | drm_dev_exit(idx); |
| 358 | } | 359 | } |
| 359 | 360 | ||
| 361 | mutex_destroy(&ctx->lock); | ||
| 360 | kfree(ctx); | 362 | kfree(ctx); |
| 361 | } | 363 | } |
| 362 | 364 | ||
| @@ -49,6 +49,7 @@ struct amdgpu_ctx { · 48 unmodified lines | |||
| 49 | bool preamble_presented; | 49 | bool preamble_presented; |
| 50 | int32_t init_priority; | 50 | int32_t init_priority; |
| 51 | int32_t override_priority; | 51 | int32_t override_priority; |
| 52 | struct mutex lock; | ||
| 52 | atomic_t guilty; | 53 | atomic_t guilty; |
| 53 | unsigned long ras_counter_ce; | 54 | unsigned long ras_counter_ce; |
| 54 | unsigned long ras_counter_ue; | 55 | unsigned long ras_counter_ue; |
| @@ -214,29 +214,6 @@ int drm_of_encoder_active_endpoint(struct device_node *node, · 213 unmodified lines | |||
| 214 | } | 214 | } |
| 215 | EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint); | 215 | EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint); |
| 216 | 216 | ||
| 217 | static int find_panel_or_bridge(struct device_node *node, | ||
| 218 | struct drm_panel **panel, | ||
| 219 | struct drm_bridge **bridge) | ||
| 220 | { | ||
| 221 | if (panel) { | ||
| 222 | *panel = of_drm_find_panel(node); | ||
| 223 | if (!IS_ERR(*panel)) | ||
| 224 | return 0; | ||
| 225 | |||
| 226 | /* Clear the panel pointer in case of error. */ | ||
| 227 | *panel = NULL; | ||
| 228 | } | ||
| 229 | |||
| 230 | /* No panel found yet, check for a bridge next. */ | ||
| 231 | if (bridge) { | ||
| 232 | *bridge = of_drm_find_bridge(node); | ||
| 233 | if (*bridge) | ||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | |||
| 237 | return -EPROBE_DEFER; | ||
| 238 | } | ||
| 239 | |||
| 240 | /** | 217 | /** |
| 241 | * drm_of_find_panel_or_bridge - return connected panel or bridge device | 218 | * drm_of_find_panel_or_bridge - return connected panel or bridge device |
| 242 | * @np: device tree node containing encoder output ports | 219 | * @np: device tree node containing encoder output ports |
| @@ -259,44 +236,49 @@ int drm_of_find_panel_or_bridge(const struct device_node *np, · 16 unmodified lines | |||
| 259 | struct drm_panel **panel, | 236 | struct drm_panel **panel, |
| 260 | struct drm_bridge **bridge) | 237 | struct drm_bridge **bridge) |
| 261 | { | 238 | { |
| 262 | struct device_node *node; | 239 | int ret = -EPROBE_DEFER; |
| 263 | int ret; | 240 | struct device_node *remote; |
| 264 | 241 | ||
| 265 | if (!panel && !bridge) | 242 | if (!panel && !bridge) |
| 266 | return -EINVAL; | 243 | return -EINVAL; |
| 267 | |||
| 268 | if (panel) | 244 | if (panel) |
| 269 | *panel = NULL; | 245 | *panel = NULL; |
| 270 | if (bridge) | ||
| 271 | *bridge = NULL; | ||
| 272 | |||
| 273 | /* Check for a graph on the device node first. */ | ||
| 274 | if (of_graph_is_present(np)) { | ||
| 275 | node = of_graph_get_remote_node(np, port, endpoint); | ||
| 276 | if (node) { | ||
| 277 | ret = find_panel_or_bridge(node, panel, bridge); | ||
| 278 | of_node_put(node); | ||
| 279 | |||
| 280 | if (!ret) | ||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | } | ||
| 284 | 246 | ||
| 285 | /* Otherwise check for any child node other than port/ports. */ | 247 | /* |
| 286 | for_each_available_child_of_node(np, node) { | 248 | * of_graph_get_remote_node() produces a noisy error message if port |
| 287 | if (of_node_name_eq(node, "port") || | 249 | * node isn't found and the absence of the port is a legit case here, |
| 288 | of_node_name_eq(node, "ports")) | 250 | * so at first we silently check whether graph presents in the |
| 289 | continue; | 251 | * device-tree node. |
| 252 | */ | ||
| 253 | if (!of_graph_is_present(np)) | ||
| 254 | return -ENODEV; | ||
| 290 | 255 | ||
| 291 | ret = find_panel_or_bridge(node, panel, bridge); | 256 | remote = of_graph_get_remote_node(np, port, endpoint); |
| 292 | of_node_put(node); | 257 | if (!remote) |
| 258 | return -ENODEV; | ||
| 259 | |||
| 260 | if (panel) { | ||
| 261 | *panel = of_drm_find_panel(remote); | ||
| 262 | if (!IS_ERR(*panel)) | ||
| 263 | ret = 0; | ||
| 264 | else | ||
| 265 | *panel = NULL; | ||
| 266 | } | ||
| 267 | |||
| 268 | /* No panel found yet, check for a bridge next. */ | ||
| 269 | if (bridge) { | ||
| 270 | if (ret) { | ||
| 271 | *bridge = of_drm_find_bridge(remote); | ||
| 272 | if (*bridge) | ||
| 273 | ret = 0; | ||
| 274 | } else { | ||
| 275 | *bridge = NULL; | ||
| 276 | } | ||
| 293 | 277 | ||
| 294 | /* Stop at the first found occurrence. */ | ||
| 295 | if (!ret) | ||
| 296 | return 0; | ||
| 297 | } | 278 | } |
| 298 | 279 | ||
| 299 | return -EPROBE_DEFER; | 280 | of_node_put(remote); |
| 281 | return ret; | ||
| 300 | } | 282 | } |
| 301 | EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge); | 283 | EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge); |
| 302 | 284 | ||
| @@ -229,7 +229,7 @@ static void rpi_touchscreen_i2c_write(struct rpi_touchscreen *ts, · 228 unmodified lines | |||
| 229 | 229 | ||
| 230 | ret = i2c_smbus_write_byte_data(ts->i2c, reg, val); | 230 | ret = i2c_smbus_write_byte_data(ts->i2c, reg, val); |
| 231 | if (ret) | 231 | if (ret) |
| 232 | dev_err(&ts->dsi->dev, "I2C write failed: %d\n", ret); | 232 | dev_err(&ts->i2c->dev, "I2C write failed: %d\n", ret); |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val) | 235 | static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val) |
| @@ -265,7 +265,7 @@ static int rpi_touchscreen_noop(struct drm_panel *panel) · 29 unmodified lines | |||
| 265 | return 0; | 265 | return 0; |
| 266 | } | 266 | } |
| 267 | 267 | ||
| 268 | static int rpi_touchscreen_enable(struct drm_panel *panel) | 268 | static int rpi_touchscreen_prepare(struct drm_panel *panel) |
| 269 | { | 269 | { |
| 270 | struct rpi_touchscreen *ts = panel_to_ts(panel); | 270 | struct rpi_touchscreen *ts = panel_to_ts(panel); |
| 271 | int i; | 271 | int i; |
| @@ -295,6 +295,13 @@ static int rpi_touchscreen_enable(struct drm_panel *panel) · 23 unmodified lines | |||
| 295 | rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01); | 295 | rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01); |
| 296 | msleep(100); | 296 | msleep(100); |
| 297 | 297 | ||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | |||
| 301 | static int rpi_touchscreen_enable(struct drm_panel *panel) | ||
| 302 | { | ||
| 303 | struct rpi_touchscreen *ts = panel_to_ts(panel); | ||
| 304 | |||
| 298 | /* Turn on the backlight. */ | 305 | /* Turn on the backlight. */ |
| 299 | rpi_touchscreen_i2c_write(ts, REG_PWM, 255); | 306 | rpi_touchscreen_i2c_write(ts, REG_PWM, 255); |
| 300 | 307 | ||
| @@ -349,7 +356,7 @@ static int rpi_touchscreen_get_modes(struct drm_panel *panel, · 48 unmodified lines | |||
| 349 | static const struct drm_panel_funcs rpi_touchscreen_funcs = { | 356 | static const struct drm_panel_funcs rpi_touchscreen_funcs = { |
| 350 | .disable = rpi_touchscreen_disable, | 357 | .disable = rpi_touchscreen_disable, |
| 351 | .unprepare = rpi_touchscreen_noop, | 358 | .unprepare = rpi_touchscreen_noop, |
| 352 | .prepare = rpi_touchscreen_noop, | 359 | .prepare = rpi_touchscreen_prepare, |
| 353 | .enable = rpi_touchscreen_enable, | 360 | .enable = rpi_touchscreen_enable, |
| 354 | .get_modes = rpi_touchscreen_get_modes, | 361 | .get_modes = rpi_touchscreen_get_modes, |
| 355 | }; | 362 | }; |
| @@ -96,7 +96,7 @@ int radeon_sync_resv(struct radeon_device *rdev, · 95 unmodified lines | |||
| 96 | struct dma_fence *f; | 96 | struct dma_fence *f; |
| 97 | int r = 0; | 97 | int r = 0; |
| 98 | 98 | ||
| 99 | dma_resv_for_each_fence(&cursor, resv, shared, f) { | 99 | dma_resv_for_each_fence(&cursor, resv, !shared, f) { |
| 100 | fence = to_radeon_fence(f); | 100 | fence = to_radeon_fence(f); |
| 101 | if (fence && fence->rdev == rdev) | 101 | if (fence && fence->rdev == rdev) |
| 102 | radeon_sync_fence(sync, fence); | 102 | radeon_sync_fence(sync, fence); |
| @@ -2,6 +2,9 @@ · 1 unmodified line | |||
| 2 | config DRM_VC4 | 2 | config DRM_VC4 |
| 3 | tristate "Broadcom VC4 Graphics" | 3 | tristate "Broadcom VC4 Graphics" |
| 4 | depends on ARCH_BCM || ARCH_BCM2835 || COMPILE_TEST | 4 | depends on ARCH_BCM || ARCH_BCM2835 || COMPILE_TEST |
| 5 | # Make sure not 'y' when RASPBERRYPI_FIRMWARE is 'm'. This can only | ||
| 6 | # happen when COMPILE_TEST=y, hence the added !RASPBERRYPI_FIRMWARE. | ||
| 7 | depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE) | ||
| 5 | depends on DRM | 8 | depends on DRM |
| 6 | depends on SND && SND_SOC | 9 | depends on SND && SND_SOC |
| 7 | depends on COMMON_CLK | 10 | depends on COMMON_CLK |
| @@ -846,7 +846,7 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) · 845 unmodified lines | |||
| 846 | unsigned long phy_clock; | 846 | unsigned long phy_clock; |
| 847 | int ret; | 847 | int ret; |
| 848 | 848 | ||
| 849 | ret = pm_runtime_get_sync(dev); | 849 | ret = pm_runtime_resume_and_get(dev); |
| 850 | if (ret) { | 850 | if (ret) { |
| 851 | DRM_ERROR("Failed to runtime PM enable on DSI%d\n", dsi->variant->port); | 851 | DRM_ERROR("Failed to runtime PM enable on DSI%d\n", dsi->variant->port); |
| 852 | return; | 852 | return; |
| @@ -46,6 +46,21 @@ vmw_buffer_object(struct ttm_buffer_object *bo) · 45 unmodified lines | |||
| 46 | return container_of(bo, struct vmw_buffer_object, base); | 46 | return container_of(bo, struct vmw_buffer_object, base); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | /** | ||
| 50 | * bo_is_vmw - check if the buffer object is a &vmw_buffer_object | ||
| 51 | * @bo: ttm buffer object to be checked | ||
| 52 | * | ||
| 53 | * Uses destroy function associated with the object to determine if this is | ||
| 54 | * a &vmw_buffer_object. | ||
| 55 | * | ||
| 56 | * Returns: | ||
| 57 | * true if the object is of &vmw_buffer_object type, false if not. | ||
| 58 | */ | ||
| 59 | static bool bo_is_vmw(struct ttm_buffer_object *bo) | ||
| 60 | { | ||
| 61 | return bo->destroy == &vmw_bo_bo_free || | ||
| 62 | bo->destroy == &vmw_gem_destroy; | ||
| 63 | } | ||
| 49 | 64 | ||
| 50 | /** | 65 | /** |
| 51 | * vmw_bo_pin_in_placement - Validate a buffer to placement. | 66 | * vmw_bo_pin_in_placement - Validate a buffer to placement. |
| @@ -615,8 +630,9 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, · 563 unmodified lines | |||
| 615 | 630 | ||
| 616 | ret = vmw_user_bo_synccpu_grab(vbo, arg->flags); | 631 | ret = vmw_user_bo_synccpu_grab(vbo, arg->flags); |
| 617 | vmw_bo_unreference(&vbo); | 632 | vmw_bo_unreference(&vbo); |
| 618 | if (unlikely(ret != 0 && ret != -ERESTARTSYS && | 633 | if (unlikely(ret != 0)) { |
| 619 | ret != -EBUSY)) { | 634 | if (ret == -ERESTARTSYS || ret == -EBUSY) |
| 635 | return -EBUSY; | ||
| 620 | DRM_ERROR("Failed synccpu grab on handle 0x%08x.\n", | 636 | DRM_ERROR("Failed synccpu grab on handle 0x%08x.\n", |
| 621 | (unsigned int) arg->handle); | 637 | (unsigned int) arg->handle); |
| 622 | return ret; | 638 | return ret; |
| @@ -798,7 +814,7 @@ int vmw_dumb_create(struct drm_file *file_priv, · 175 unmodified lines | |||
| 798 | void vmw_bo_swap_notify(struct ttm_buffer_object *bo) | 814 | void vmw_bo_swap_notify(struct ttm_buffer_object *bo) |
| 799 | { | 815 | { |
| 800 | /* Is @bo embedded in a struct vmw_buffer_object? */ | 816 | /* Is @bo embedded in a struct vmw_buffer_object? */ |
| 801 | if (vmw_bo_is_vmw_bo(bo)) | 817 | if (!bo_is_vmw(bo)) |
| 802 | return; | 818 | return; |
| 803 | 819 | ||
| 804 | /* Kill any cached kernel maps before swapout */ | 820 | /* Kill any cached kernel maps before swapout */ |
| @@ -822,7 +838,7 @@ void vmw_bo_move_notify(struct ttm_buffer_object *bo, · 17 unmodified lines | |||
| 822 | struct vmw_buffer_object *vbo; | 838 | struct vmw_buffer_object *vbo; |
| 823 | 839 | ||
| 824 | /* Make sure @bo is embedded in a struct vmw_buffer_object? */ | 840 | /* Make sure @bo is embedded in a struct vmw_buffer_object? */ |
| 825 | if (vmw_bo_is_vmw_bo(bo)) | 841 | if (!bo_is_vmw(bo)) |
| 826 | return; | 842 | return; |
| 827 | 843 | ||
| 828 | vbo = container_of(bo, struct vmw_buffer_object, base); | 844 | vbo = container_of(bo, struct vmw_buffer_object, base); |
| @@ -843,22 +859,3 @@ void vmw_bo_move_notify(struct ttm_buffer_object *bo, · 14 unmodified lines | |||
| 843 | if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB) | 859 | if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB) |
| 844 | vmw_resource_unbind_list(vbo); | 860 | vmw_resource_unbind_list(vbo); |
| 845 | } | 861 | } |
| 846 | |||
| 847 | /** | ||
| 848 | * vmw_bo_is_vmw_bo - check if the buffer object is a &vmw_buffer_object | ||
| 849 | * @bo: buffer object to be checked | ||
| 850 | * | ||
| 851 | * Uses destroy function associated with the object to determine if this is | ||
| 852 | * a &vmw_buffer_object. | ||
| 853 | * | ||
| 854 | * Returns: | ||
| 855 | * true if the object is of &vmw_buffer_object type, false if not. | ||
| 856 | */ | ||
| 857 | bool vmw_bo_is_vmw_bo(struct ttm_buffer_object *bo) | ||
| 858 | { | ||
| 859 | if (bo->destroy == &vmw_bo_bo_free || | ||
| 860 | bo->destroy == &vmw_gem_destroy) | ||
| 861 | return true; | ||
| 862 | |||
| 863 | return false; | ||
| 864 | } | ||
| @@ -998,13 +998,10 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) · 997 unmodified lines | |||
| 998 | goto out_no_fman; | 998 | goto out_no_fman; |
| 999 | } | 999 | } |
| 1000 | 1000 | ||
| 1001 | drm_vma_offset_manager_init(&dev_priv->vma_manager, | ||
| 1002 | DRM_FILE_PAGE_OFFSET_START, | ||
| 1003 | DRM_FILE_PAGE_OFFSET_SIZE); | ||
| 1004 | ret = ttm_device_init(&dev_priv->bdev, &vmw_bo_driver, | 1001 | ret = ttm_device_init(&dev_priv->bdev, &vmw_bo_driver, |
| 1005 | dev_priv->drm.dev, | 1002 | dev_priv->drm.dev, |
| 1006 | dev_priv->drm.anon_inode->i_mapping, | 1003 | dev_priv->drm.anon_inode->i_mapping, |
| 1007 | &dev_priv->vma_manager, | 1004 | dev_priv->drm.vma_offset_manager, |
| 1008 | dev_priv->map_mode == vmw_dma_alloc_coherent, | 1005 | dev_priv->map_mode == vmw_dma_alloc_coherent, |
| 1009 | false); | 1006 | false); |
| 1010 | if (unlikely(ret != 0)) { | 1007 | if (unlikely(ret != 0)) { |
| @@ -1174,7 +1171,6 @@ static void vmw_driver_unload(struct drm_device *dev) · 163 unmodified lines | |||
| 1174 | vmw_devcaps_destroy(dev_priv); | 1171 | vmw_devcaps_destroy(dev_priv); |
| 1175 | vmw_vram_manager_fini(dev_priv); | 1172 | vmw_vram_manager_fini(dev_priv); |
| 1176 | ttm_device_fini(&dev_priv->bdev); | 1173 | ttm_device_fini(&dev_priv->bdev); |
| 1177 | drm_vma_offset_manager_destroy(&dev_priv->vma_manager); | ||
| 1178 | vmw_release_device_late(dev_priv); | 1174 | vmw_release_device_late(dev_priv); |
| 1179 | vmw_fence_manager_takedown(dev_priv->fman); | 1175 | vmw_fence_manager_takedown(dev_priv->fman); |
| 1180 | if (dev_priv->capabilities & SVGA_CAP_IRQMASK) | 1176 | if (dev_priv->capabilities & SVGA_CAP_IRQMASK) |
| @@ -1398,7 +1394,7 @@ vmw_get_unmapped_area(struct file *file, unsigned long uaddr, · 217 unmodified lines | |||
| 1398 | struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev); | 1394 | struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev); |
| 1399 | 1395 | ||
| 1400 | return drm_get_unmapped_area(file, uaddr, len, pgoff, flags, | 1396 | return drm_get_unmapped_area(file, uaddr, len, pgoff, flags, |
| 1401 | &dev_priv->vma_manager); | 1397 | dev_priv->drm.vma_offset_manager); |
| 1402 | } | 1398 | } |
| 1403 | 1399 | ||
| 1404 | static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, | 1400 | static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, |
| @@ -683,6 +683,9 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base) · 682 unmodified lines | |||
| 683 | container_of(base, struct vmw_user_surface, prime.base); | 683 | container_of(base, struct vmw_user_surface, prime.base); |
| 684 | struct vmw_resource *res = &user_srf->srf.res; | 684 | struct vmw_resource *res = &user_srf->srf.res; |
| 685 | 685 | ||
| 686 | if (base->shareable && res && res->backup) | ||
| 687 | drm_gem_object_put(&res->backup->base.base); | ||
| 688 | |||
| 686 | *p_base = NULL; | 689 | *p_base = NULL; |
| 687 | vmw_resource_unreference(&res); | 690 | vmw_resource_unreference(&res); |
| 688 | } | 691 | } |
| @@ -857,6 +860,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, · 168 unmodified lines | |||
| 857 | goto out_unlock; | 860 | goto out_unlock; |
| 858 | } | 861 | } |
| 859 | vmw_bo_reference(res->backup); | 862 | vmw_bo_reference(res->backup); |
| 863 | drm_gem_object_get(&res->backup->base.base); | ||
| 860 | } | 864 | } |
| 861 | 865 | ||
| 862 | tmp = vmw_resource_reference(&srf->res); | 866 | tmp = vmw_resource_reference(&srf->res); |
| @@ -1513,7 +1517,6 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 650 unmodified lines | |||
| 1513 | &res->backup); | 1517 | &res->backup); |
| 1514 | if (ret == 0) | 1518 | if (ret == 0) |
| 1515 | vmw_bo_reference(res->backup); | 1519 | vmw_bo_reference(res->backup); |
| 1516 | |||
| 1517 | } | 1520 | } |
| 1518 | 1521 | ||
| 1519 | if (unlikely(ret != 0)) { | 1522 | if (unlikely(ret != 0)) { |
| @@ -1561,6 +1564,8 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 41 unmodified lines | |||
| 1561 | drm_vma_node_offset_addr(&res->backup->base.base.vma_node); | 1564 | drm_vma_node_offset_addr(&res->backup->base.base.vma_node); |
| 1562 | rep->buffer_size = res->backup->base.base.size; | 1565 | rep->buffer_size = res->backup->base.base.size; |
| 1563 | rep->buffer_handle = backup_handle; | 1566 | rep->buffer_handle = backup_handle; |
| 1567 | if (user_srf->prime.base.shareable) | ||
| 1568 | drm_gem_object_get(&res->backup->base.base); | ||
| 1564 | } else { | 1569 | } else { |
| 1565 | rep->buffer_map_handle = 0; | 1570 | rep->buffer_map_handle = 0; |
| 1566 | rep->buffer_size = 0; | 1571 | rep->buffer_size = 0; |
| @@ -1,266 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Pointer to dma-buf-mapped memory, plus helpers. | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __DMA_BUF_MAP_H__ | ||
| 7 | #define __DMA_BUF_MAP_H__ | ||
| 8 | |||
| 9 | #include <linux/io.h> | ||
| 10 | #include <linux/string.h> | ||
| 11 | |||
| 12 | /** | ||
| 13 | * DOC: overview | ||
| 14 | * | ||
| 15 | * Calling dma-buf's vmap operation returns a pointer to the buffer's memory. | ||
| 16 | * Depending on the location of the buffer, users may have to access it with | ||
| 17 | * I/O operations or memory load/store operations. For example, copying to | ||
| 18 | * system memory could be done with memcpy(), copying to I/O memory would be | ||
| 19 | * done with memcpy_toio(). | ||
| 20 | * | ||
| 21 | * .. code-block:: c | ||
| 22 | * | ||
| 23 | * void *vaddr = ...; // pointer to system memory | ||
| 24 | * memcpy(vaddr, src, len); | ||
| 25 | * | ||
| 26 | * void *vaddr_iomem = ...; // pointer to I/O memory | ||
| 27 | * memcpy_toio(vaddr, _iomem, src, len); | ||
| 28 | * | ||
| 29 | * When using dma-buf's vmap operation, the returned pointer is encoded as | ||
| 30 | * :c:type:`struct dma_buf_map <dma_buf_map>`. | ||
| 31 | * :c:type:`struct dma_buf_map <dma_buf_map>` stores the buffer's address in | ||
| 32 | * system or I/O memory and a flag that signals the required method of | ||
| 33 | * accessing the buffer. Use the returned instance and the helper functions | ||
| 34 | * to access the buffer's memory in the correct way. | ||
| 35 | * | ||
| 36 | * The type :c:type:`struct dma_buf_map <dma_buf_map>` and its helpers are | ||
| 37 | * actually independent from the dma-buf infrastructure. When sharing buffers | ||
| 38 | * among devices, drivers have to know the location of the memory to access | ||
| 39 | * the buffers in a safe way. :c:type:`struct dma_buf_map <dma_buf_map>` | ||
| 40 | * solves this problem for dma-buf and its users. If other drivers or | ||
| 41 | * sub-systems require similar functionality, the type could be generalized | ||
| 42 | * and moved to a more prominent header file. | ||
| 43 | * | ||
| 44 | * Open-coding access to :c:type:`struct dma_buf_map <dma_buf_map>` is | ||
| 45 | * considered bad style. Rather then accessing its fields directly, use one | ||
| 46 | * of the provided helper functions, or implement your own. For example, | ||
| 47 | * instances of :c:type:`struct dma_buf_map <dma_buf_map>` can be initialized | ||
| 48 | * statically with DMA_BUF_MAP_INIT_VADDR(), or at runtime with | ||
| 49 | * dma_buf_map_set_vaddr(). These helpers will set an address in system memory. | ||
| 50 | * | ||
| 51 | * .. code-block:: c | ||
| 52 | * | ||
| 53 | * struct dma_buf_map map = DMA_BUF_MAP_INIT_VADDR(0xdeadbeaf); | ||
| 54 | * | ||
| 55 | * dma_buf_map_set_vaddr(&map, 0xdeadbeaf); | ||
| 56 | * | ||
| 57 | * To set an address in I/O memory, use dma_buf_map_set_vaddr_iomem(). | ||
| 58 | * | ||
| 59 | * .. code-block:: c | ||
| 60 | * | ||
| 61 | * dma_buf_map_set_vaddr_iomem(&map, 0xdeadbeaf); | ||
| 62 | * | ||
| 63 | * Instances of struct dma_buf_map do not have to be cleaned up, but | ||
| 64 | * can be cleared to NULL with dma_buf_map_clear(). Cleared mappings | ||
| 65 | * always refer to system memory. | ||
| 66 | * | ||
| 67 | * .. code-block:: c | ||
| 68 | * | ||
| 69 | * dma_buf_map_clear(&map); | ||
| 70 | * | ||
| 71 | * Test if a mapping is valid with either dma_buf_map_is_set() or | ||
| 72 | * dma_buf_map_is_null(). | ||
| 73 | * | ||
| 74 | * .. code-block:: c | ||
| 75 | * | ||
| 76 | * if (dma_buf_map_is_set(&map) != dma_buf_map_is_null(&map)) | ||
| 77 | * // always true | ||
| 78 | * | ||
| 79 | * Instances of :c:type:`struct dma_buf_map <dma_buf_map>` can be compared | ||
| 80 | * for equality with dma_buf_map_is_equal(). Mappings the point to different | ||
| 81 | * memory spaces, system or I/O, are never equal. That's even true if both | ||
| 82 | * spaces are located in the same address space, both mappings contain the | ||
| 83 | * same address value, or both mappings refer to NULL. | ||
| 84 | * | ||
| 85 | * .. code-block:: c | ||
| 86 | * | ||
| 87 | * struct dma_buf_map sys_map; // refers to system memory | ||
| 88 | * struct dma_buf_map io_map; // refers to I/O memory | ||
| 89 | * | ||
| 90 | * if (dma_buf_map_is_equal(&sys_map, &io_map)) | ||
| 91 | * // always false | ||
| 92 | * | ||
| 93 | * A set up instance of struct dma_buf_map can be used to access or manipulate | ||
| 94 | * the buffer memory. Depending on the location of the memory, the provided | ||
| 95 | * helpers will pick the correct operations. Data can be copied into the memory | ||
| 96 | * with dma_buf_map_memcpy_to(). The address can be manipulated with | ||
| 97 | * dma_buf_map_incr(). | ||
| 98 | * | ||
| 99 | * .. code-block:: c | ||
| 100 | * | ||
| 101 | * const void *src = ...; // source buffer | ||
| 102 | * size_t len = ...; // length of src | ||
| 103 | * | ||
| 104 | * dma_buf_map_memcpy_to(&map, src, len); | ||
| 105 | * dma_buf_map_incr(&map, len); // go to first byte after the memcpy | ||
| 106 | */ | ||
| 107 | |||
| 108 | /** | ||
| 109 | * struct dma_buf_map - Pointer to vmap'ed dma-buf memory. | ||
| 110 | * @vaddr_iomem: The buffer's address if in I/O memory | ||
| 111 | * @vaddr: The buffer's address if in system memory | ||
| 112 | * @is_iomem: True if the dma-buf memory is located in I/O | ||
| 113 | * memory, or false otherwise. | ||
| 114 | */ | ||
| 115 | struct dma_buf_map { | ||
| 116 | union { | ||
| 117 | void __iomem *vaddr_iomem; | ||
| 118 | void *vaddr; | ||
| 119 | }; | ||
| 120 | bool is_iomem; | ||
| 121 | }; | ||
| 122 | |||
| 123 | /** | ||
| 124 | * DMA_BUF_MAP_INIT_VADDR - Initializes struct dma_buf_map to an address in system memory | ||
| 125 | * @vaddr_: A system-memory address | ||
| 126 | */ | ||
| 127 | #define DMA_BUF_MAP_INIT_VADDR(vaddr_) \ | ||
| 128 | { \ | ||
| 129 | .vaddr = (vaddr_), \ | ||
| 130 | .is_iomem = false, \ | ||
| 131 | } | ||
| 132 | |||
| 133 | /** | ||
| 134 | * dma_buf_map_set_vaddr - Sets a dma-buf mapping structure to an address in system memory | ||
| 135 | * @map: The dma-buf mapping structure | ||
| 136 | * @vaddr: A system-memory address | ||
| 137 | * | ||
| 138 | * Sets the address and clears the I/O-memory flag. | ||
| 139 | */ | ||
| 140 | static inline void dma_buf_map_set_vaddr(struct dma_buf_map *map, void *vaddr) | ||
| 141 | { | ||
| 142 | map->vaddr = vaddr; | ||
| 143 | map->is_iomem = false; | ||
| 144 | } | ||
| 145 | |||
| 146 | /** | ||
| 147 | * dma_buf_map_set_vaddr_iomem - Sets a dma-buf mapping structure to an address in I/O memory | ||
| 148 | * @map: The dma-buf mapping structure | ||
| 149 | * @vaddr_iomem: An I/O-memory address | ||
| 150 | * | ||
| 151 | * Sets the address and the I/O-memory flag. | ||
| 152 | */ | ||
| 153 | static inline void dma_buf_map_set_vaddr_iomem(struct dma_buf_map *map, | ||
| 154 | void __iomem *vaddr_iomem) | ||
| 155 | { | ||
| 156 | map->vaddr_iomem = vaddr_iomem; | ||
| 157 | map->is_iomem = true; | ||
| 158 | } | ||
| 159 | |||
| 160 | /** | ||
| 161 | * dma_buf_map_is_equal - Compares two dma-buf mapping structures for equality | ||
| 162 | * @lhs: The dma-buf mapping structure | ||
| 163 | * @rhs: A dma-buf mapping structure to compare with | ||
| 164 | * | ||
| 165 | * Two dma-buf mapping structures are equal if they both refer to the same type of memory | ||
| 166 | * and to the same address within that memory. | ||
| 167 | * | ||
| 168 | * Returns: | ||
| 169 | * True is both structures are equal, or false otherwise. | ||
| 170 | */ | ||
| 171 | static inline bool dma_buf_map_is_equal(const struct dma_buf_map *lhs, | ||
| 172 | const struct dma_buf_map *rhs) | ||
| 173 | { | ||
| 174 | if (lhs->is_iomem != rhs->is_iomem) | ||
| 175 | return false; | ||
| 176 | else if (lhs->is_iomem) | ||
| 177 | return lhs->vaddr_iomem == rhs->vaddr_iomem; | ||
| 178 | else | ||
| 179 | return lhs->vaddr == rhs->vaddr; | ||
| 180 | } | ||
| 181 | |||
| 182 | /** | ||
| 183 | * dma_buf_map_is_null - Tests for a dma-buf mapping to be NULL | ||
| 184 | * @map: The dma-buf mapping structure | ||
| 185 | * | ||
| 186 | * Depending on the state of struct dma_buf_map.is_iomem, tests if the | ||
| 187 | * mapping is NULL. | ||
| 188 | * | ||
| 189 | * Returns: | ||
| 190 | * True if the mapping is NULL, or false otherwise. | ||
| 191 | */ | ||
| 192 | static inline bool dma_buf_map_is_null(const struct dma_buf_map *map) | ||
| 193 | { | ||
| 194 | if (map->is_iomem) | ||
| 195 | return !map->vaddr_iomem; | ||
| 196 | return !map->vaddr; | ||
| 197 | } | ||
| 198 | |||
| 199 | /** | ||
| 200 | * dma_buf_map_is_set - Tests is the dma-buf mapping has been set | ||
| 201 | * @map: The dma-buf mapping structure | ||
| 202 | * | ||
| 203 | * Depending on the state of struct dma_buf_map.is_iomem, tests if the | ||
| 204 | * mapping has been set. | ||
| 205 | * | ||
| 206 | * Returns: | ||
| 207 | * True if the mapping is been set, or false otherwise. | ||
| 208 | */ | ||
| 209 | static inline bool dma_buf_map_is_set(const struct dma_buf_map *map) | ||
| 210 | { | ||
| 211 | return !dma_buf_map_is_null(map); | ||
| 212 | } | ||
| 213 | |||
| 214 | /** | ||
| 215 | * dma_buf_map_clear - Clears a dma-buf mapping structure | ||
| 216 | * @map: The dma-buf mapping structure | ||
| 217 | * | ||
| 218 | * Clears all fields to zero; including struct dma_buf_map.is_iomem. So | ||
| 219 | * mapping structures that were set to point to I/O memory are reset for | ||
| 220 | * system memory. Pointers are cleared to NULL. This is the default. | ||
| 221 | */ | ||
| 222 | static inline void dma_buf_map_clear(struct dma_buf_map *map) | ||
| 223 | { | ||
| 224 | if (map->is_iomem) { | ||
| 225 | map->vaddr_iomem = NULL; | ||
| 226 | map->is_iomem = false; | ||
| 227 | } else { | ||
| 228 | map->vaddr = NULL; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | /** | ||
| 233 | * dma_buf_map_memcpy_to - Memcpy into dma-buf mapping | ||
| 234 | * @dst: The dma-buf mapping structure | ||
| 235 | * @src: The source buffer | ||
| 236 | * @len: The number of byte in src | ||
| 237 | * | ||
| 238 | * Copies data into a dma-buf mapping. The source buffer is in system | ||
| 239 | * memory. Depending on the buffer's location, the helper picks the correct | ||
| 240 | * method of accessing the memory. | ||
| 241 | */ | ||
| 242 | static inline void dma_buf_map_memcpy_to(struct dma_buf_map *dst, const void *src, size_t len) | ||
| 243 | { | ||
| 244 | if (dst->is_iomem) | ||
| 245 | memcpy_toio(dst->vaddr_iomem, src, len); | ||
| 246 | else | ||
| 247 | memcpy(dst->vaddr, src, len); | ||
| 248 | } | ||
| 249 | |||
| 250 | /** | ||
| 251 | * dma_buf_map_incr - Increments the address stored in a dma-buf mapping | ||
| 252 | * @map: The dma-buf mapping structure | ||
| 253 | * @incr: The number of bytes to increment | ||
| 254 | * | ||
| 255 | * Increments the address stored in a dma-buf mapping. Depending on the | ||
| 256 | * buffer's location, the correct value will be updated. | ||
| 257 | */ | ||
| 258 | static inline void dma_buf_map_incr(struct dma_buf_map *map, size_t incr) | ||
| 259 | { | ||
| 260 | if (map->is_iomem) | ||
| 261 | map->vaddr_iomem += incr; | ||
| 262 | else | ||
| 263 | map->vaddr += incr; | ||
| 264 | } | ||
| 265 | |||
| 266 | #endif /* __DMA_BUF_MAP_H__ */ | ||