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 | 128 | goto free_chunk; |
| 129 | 129 | } |
| 130 | 130 | |
| 131 | + mutex_lock(&p->ctx->lock); | |
| 132 | + | |
| 131 | 133 | /* skip guilty context job */ |
| 132 | 134 | if (atomic_read(&p->ctx->guilty) == 1) { |
| 133 | 135 | ret = -ECANCELED; |
| @@ -709,6 +711,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, · 575 unmodified lines | ||
| 709 | 711 | dma_fence_put(parser->fence); |
| 710 | 712 | |
| 711 | 713 | if (parser->ctx) { |
| 714 | + mutex_unlock(&parser->ctx->lock); | |
| 712 | 715 | amdgpu_ctx_put(parser->ctx); |
| 713 | 716 | } |
| 714 | 717 | if (parser->bo_list) |
| @@ -1157,6 +1160,9 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, · 442 unmodified lines | ||
| 1157 | 1160 | { |
| 1158 | 1161 | int i, r; |
| 1159 | 1162 | |
| 1163 | + /* TODO: Investigate why we still need the context lock */ | |
| 1164 | + mutex_unlock(&p->ctx->lock); | |
| 1165 | + | |
| 1160 | 1166 | for (i = 0; i < p->nchunks; ++i) { |
| 1161 | 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 | 1173 | case AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES: |
| 1168 | 1174 | r = amdgpu_cs_process_fence_dep(p, chunk); |
| 1169 | 1175 | if (r) |
| 1170 | − return r; | |
| 1176 | + goto out; | |
| 1171 | 1177 | break; |
| 1172 | 1178 | case AMDGPU_CHUNK_ID_SYNCOBJ_IN: |
| 1173 | 1179 | r = amdgpu_cs_process_syncobj_in_dep(p, chunk); |
| 1174 | 1180 | if (r) |
| 1175 | − return r; | |
| 1181 | + goto out; | |
| 1176 | 1182 | break; |
| 1177 | 1183 | case AMDGPU_CHUNK_ID_SYNCOBJ_OUT: |
| 1178 | 1184 | r = amdgpu_cs_process_syncobj_out_dep(p, chunk); |
| 1179 | 1185 | if (r) |
| 1180 | − return r; | |
| 1186 | + goto out; | |
| 1181 | 1187 | break; |
| 1182 | 1188 | case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT: |
| 1183 | 1189 | r = amdgpu_cs_process_syncobj_timeline_in_dep(p, chunk); |
| 1184 | 1190 | if (r) |
| 1185 | − return r; | |
| 1191 | + goto out; | |
| 1186 | 1192 | break; |
| 1187 | 1193 | case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL: |
| 1188 | 1194 | r = amdgpu_cs_process_syncobj_timeline_out_dep(p, chunk); |
| 1189 | 1195 | if (r) |
| 1190 | − return r; | |
| 1196 | + goto out; | |
| 1191 | 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 | 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 | 1376 | goto out; |
| 1369 | 1377 | |
| 1370 | 1378 | r = amdgpu_cs_submit(&parser, cs); |
| 1379 | + | |
| 1371 | 1380 | out: |
| 1372 | 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 | 238 | kref_init(&ctx->refcount); |
| 239 | 239 | spin_lock_init(&ctx->ring_lock); |
| 240 | + mutex_init(&ctx->lock); | |
| 240 | 241 | |
| 241 | 242 | ctx->reset_counter = atomic_read(&adev->gpu_reset_counter); |
| 242 | 243 | ctx->reset_counter_query = ctx->reset_counter; |
| @@ -357,6 +358,7 @@ static void amdgpu_ctx_fini(struct kref *ref) · 114 unmodified lines | ||
| 357 | 358 | drm_dev_exit(idx); |
| 358 | 359 | } |
| 359 | 360 | |
| 361 | + mutex_destroy(&ctx->lock); | |
| 360 | 362 | kfree(ctx); |
| 361 | 363 | } |
| 362 | 364 | |
| @@ -49,6 +49,7 @@ struct amdgpu_ctx { · 48 unmodified lines | ||
| 49 | 49 | bool preamble_presented; |
| 50 | 50 | int32_t init_priority; |
| 51 | 51 | int32_t override_priority; |
| 52 | + struct mutex lock; | |
| 52 | 53 | atomic_t guilty; |
| 53 | 54 | unsigned long ras_counter_ce; |
| 54 | 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 | 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 | 218 | * drm_of_find_panel_or_bridge - return connected panel or bridge device |
| 242 | 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 | 236 | struct drm_panel **panel, |
| 260 | 237 | struct drm_bridge **bridge) |
| 261 | 238 | { |
| 262 | − struct device_node *node; | |
| 263 | − int ret; | |
| 239 | + int ret = -EPROBE_DEFER; | |
| 240 | + struct device_node *remote; | |
| 264 | 241 | |
| 265 | 242 | if (!panel && !bridge) |
| 266 | 243 | return -EINVAL; |
| 267 | − | |
| 268 | 244 | if (panel) |
| 269 | 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. */ | |
| 286 | − for_each_available_child_of_node(np, node) { | |
| 287 | − if (of_node_name_eq(node, "port") || | |
| 288 | − of_node_name_eq(node, "ports")) | |
| 289 | − continue; | |
| 247 | + /* | |
| 248 | + * of_graph_get_remote_node() produces a noisy error message if port | |
| 249 | + * node isn't found and the absence of the port is a legit case here, | |
| 250 | + * so at first we silently check whether graph presents in the | |
| 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); | |
| 292 | − of_node_put(node); | |
| 256 | + remote = of_graph_get_remote_node(np, port, endpoint); | |
| 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 | 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 | 230 | ret = i2c_smbus_write_byte_data(ts->i2c, reg, val); |
| 231 | 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 | 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 | 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 | 270 | struct rpi_touchscreen *ts = panel_to_ts(panel); |
| 271 | 271 | int i; |
| @@ -295,6 +295,13 @@ static int rpi_touchscreen_enable(struct drm_panel *panel) · 23 unmodified lines | ||
| 295 | 295 | rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01); |
| 296 | 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 | 305 | /* Turn on the backlight. */ |
| 299 | 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 | 356 | static const struct drm_panel_funcs rpi_touchscreen_funcs = { |
| 350 | 357 | .disable = rpi_touchscreen_disable, |
| 351 | 358 | .unprepare = rpi_touchscreen_noop, |
| 352 | − .prepare = rpi_touchscreen_noop, | |
| 359 | + .prepare = rpi_touchscreen_prepare, | |
| 353 | 360 | .enable = rpi_touchscreen_enable, |
| 354 | 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 | 96 | struct dma_fence *f; |
| 97 | 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 | 100 | fence = to_radeon_fence(f); |
| 101 | 101 | if (fence && fence->rdev == rdev) |
| 102 | 102 | radeon_sync_fence(sync, fence); |
| @@ -2,6 +2,9 @@ · 1 unmodified line | ||
| 2 | 2 | config DRM_VC4 |
| 3 | 3 | tristate "Broadcom VC4 Graphics" |
| 4 | 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 | 8 | depends on DRM |
| 6 | 9 | depends on SND && SND_SOC |
| 7 | 10 | depends on COMMON_CLK |
| @@ -846,7 +846,7 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) · 845 unmodified lines | ||
| 846 | 846 | unsigned long phy_clock; |
| 847 | 847 | int ret; |
| 848 | 848 | |
| 849 | − ret = pm_runtime_get_sync(dev); | |
| 849 | + ret = pm_runtime_resume_and_get(dev); | |
| 850 | 850 | if (ret) { |
| 851 | 851 | DRM_ERROR("Failed to runtime PM enable on DSI%d\n", dsi->variant->port); |
| 852 | 852 | return; |
| @@ -46,6 +46,21 @@ vmw_buffer_object(struct ttm_buffer_object *bo) · 45 unmodified lines | ||
| 46 | 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 | 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 | 631 | ret = vmw_user_bo_synccpu_grab(vbo, arg->flags); |
| 617 | 632 | vmw_bo_unreference(&vbo); |
| 618 | − if (unlikely(ret != 0 && ret != -ERESTARTSYS && | |
| 619 | − ret != -EBUSY)) { | |
| 633 | + if (unlikely(ret != 0)) { | |
| 634 | + if (ret == -ERESTARTSYS || ret == -EBUSY) | |
| 635 | + return -EBUSY; | |
| 620 | 636 | DRM_ERROR("Failed synccpu grab on handle 0x%08x.\n", |
| 621 | 637 | (unsigned int) arg->handle); |
| 622 | 638 | return ret; |
| @@ -798,7 +814,7 @@ int vmw_dumb_create(struct drm_file *file_priv, · 175 unmodified lines | ||
| 798 | 814 | void vmw_bo_swap_notify(struct ttm_buffer_object *bo) |
| 799 | 815 | { |
| 800 | 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 | 818 | return; |
| 803 | 819 | |
| 804 | 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 | 838 | struct vmw_buffer_object *vbo; |
| 823 | 839 | |
| 824 | 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 | 842 | return; |
| 827 | 843 | |
| 828 | 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 | 859 | if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB) |
| 844 | 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 | 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 | 1001 | ret = ttm_device_init(&dev_priv->bdev, &vmw_bo_driver, |
| 1005 | 1002 | dev_priv->drm.dev, |
| 1006 | 1003 | dev_priv->drm.anon_inode->i_mapping, |
| 1007 | − &dev_priv->vma_manager, | |
| 1004 | + dev_priv->drm.vma_offset_manager, | |
| 1008 | 1005 | dev_priv->map_mode == vmw_dma_alloc_coherent, |
| 1009 | 1006 | false); |
| 1010 | 1007 | if (unlikely(ret != 0)) { |
| @@ -1174,7 +1171,6 @@ static void vmw_driver_unload(struct drm_device *dev) · 163 unmodified lines | ||
| 1174 | 1171 | vmw_devcaps_destroy(dev_priv); |
| 1175 | 1172 | vmw_vram_manager_fini(dev_priv); |
| 1176 | 1173 | ttm_device_fini(&dev_priv->bdev); |
| 1177 | − drm_vma_offset_manager_destroy(&dev_priv->vma_manager); | |
| 1178 | 1174 | vmw_release_device_late(dev_priv); |
| 1179 | 1175 | vmw_fence_manager_takedown(dev_priv->fman); |
| 1180 | 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 | 1394 | struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev); |
| 1399 | 1395 | |
| 1400 | 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 | 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 | 683 | container_of(base, struct vmw_user_surface, prime.base); |
| 684 | 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 | 689 | *p_base = NULL; |
| 687 | 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 | 860 | goto out_unlock; |
| 858 | 861 | } |
| 859 | 862 | vmw_bo_reference(res->backup); |
| 863 | + drm_gem_object_get(&res->backup->base.base); | |
| 860 | 864 | } |
| 861 | 865 | |
| 862 | 866 | tmp = vmw_resource_reference(&srf->res); |
| @@ -1513,7 +1517,6 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 650 unmodified lines | ||
| 1513 | 1517 | &res->backup); |
| 1514 | 1518 | if (ret == 0) |
| 1515 | 1519 | vmw_bo_reference(res->backup); |
| 1516 | − | |
| 1517 | 1520 | } |
| 1518 | 1521 | |
| 1519 | 1522 | if (unlikely(ret != 0)) { |
| @@ -1561,6 +1564,8 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 41 unmodified lines | ||
| 1561 | 1564 | drm_vma_node_offset_addr(&res->backup->base.base.vma_node); |
| 1562 | 1565 | rep->buffer_size = res->backup->base.base.size; |
| 1563 | 1566 | rep->buffer_handle = backup_handle; |
| 1567 | + if (user_srf->prime.base.shareable) | |
| 1568 | + drm_gem_object_get(&res->backup->base.base); | |
| 1564 | 1569 | } else { |
| 1565 | 1570 | rep->buffer_map_handle = 0; |
| 1566 | 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__ */ | |