- ADDR_COMPUTE_SURFACE_INFO_INPUT addr_surf_info_in = { 0 };
- ADDR_TILEINFO addr_tile_info = { 0 };
- ADDR_TILEINFO addr_tile_info_out = { 0 };
- uint32_t bits_per_pixel;
-
- addr_surf_info_in.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT);
-
- /* Set the requested tiling mode. */
- addr_surf_info_in.tileMode = ADDR_TM_2D_TILED_THIN1;
- if (use_flags &
- (BO_USE_CURSOR | BO_USE_LINEAR | BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN))
- addr_surf_info_in.tileMode = ADDR_TM_LINEAR_ALIGNED;
- else if (width <= 16 || height <= 16)
- addr_surf_info_in.tileMode = ADDR_TM_1D_TILED_THIN1;
-
- bits_per_pixel = drv_stride_from_format(format, 1, 0) * 8;
- /* Bits per pixel should be calculated from format*/
- addr_surf_info_in.bpp = bits_per_pixel;
- addr_surf_info_in.numSamples = 1;
- addr_surf_info_in.width = width;
- addr_surf_info_in.height = height;
- addr_surf_info_in.numSlices = 1;
- addr_surf_info_in.pTileInfo = &addr_tile_info;
- addr_surf_info_in.tileIndex = -1;
-
- /* This disables incorrect calculations (hacks) in addrlib. */
- addr_surf_info_in.flags.noStencil = 1;
-
- /* Set the micro tile type. */
- if (use_flags & BO_USE_SCANOUT)
- addr_surf_info_in.tileType = ADDR_DISPLAYABLE;
- else
- addr_surf_info_in.tileType = ADDR_NON_DISPLAYABLE;
-
- addr_out->size = sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT);
- addr_out->pTileInfo = &addr_tile_info_out;
+ const uint64_t max_size_per_cmd = 0x3fff00;
+ const uint32_t cmd_size = 7 * sizeof(uint32_t); /* 7 dwords, see loop below. */
+ const uint64_t max_commands = priv->sdma_cmdbuf_size / cmd_size;
+ uint64_t src_addr = priv->sdma_cmdbuf_addr + priv->sdma_cmdbuf_size;
+ uint64_t dst_addr = src_addr + size;
+ struct drm_amdgpu_gem_va va_args = { 0 };
+ unsigned cmd = 0;
+ uint64_t remaining_size = size;
+ uint64_t cur_src_addr = src_addr;
+ uint64_t cur_dst_addr = dst_addr;
+ struct drm_amdgpu_cs_chunk_ib ib = { 0 };
+ struct drm_amdgpu_cs_chunk chunks[2] = { { 0 } };
+ uint64_t chunk_ptrs[2];
+ union drm_amdgpu_cs cs = { { 0 } };
+ struct drm_amdgpu_bo_list_in bo_list = { 0 };
+ struct drm_amdgpu_bo_list_entry bo_list_entries[3] = { { 0 } };
+ union drm_amdgpu_wait_cs wait_cs = { { 0 } };
+ int ret = 0;
+
+ if (size > UINT64_MAX - max_size_per_cmd ||
+ DIV_ROUND_UP(size, max_size_per_cmd) > max_commands)
+ return -ENOMEM;
+
+ /* Map both buffers into the GPU address space so we can access them from the GPU. */
+ va_args.handle = src_handle;
+ va_args.operation = AMDGPU_VA_OP_MAP;
+ va_args.flags = AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_DELAY_UPDATE;
+ va_args.va_address = src_addr;
+ va_args.map_size = size;
+
+ ret = drmCommandWrite(fd, DRM_AMDGPU_GEM_VA, &va_args, sizeof(va_args));
+ if (ret)
+ return ret;