int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_busy *args = data; struct drm_gem_object *gobj; struct radeon_bo *robj; int r; uint32_t cur_placement = 0; gobj = drm_gem_object_lookup(dev, filp, args->handle); if (gobj == NULL) { return -ENOENT; } robj = gem_to_radeon_bo(gobj); r = radeon_bo_wait(robj, &cur_placement, true); switch (cur_placement) { case TTM_PL_VRAM: args->domain = RADEON_GEM_DOMAIN_VRAM; break; case TTM_PL_TT: args->domain = RADEON_GEM_DOMAIN_GTT; break; case TTM_PL_SYSTEM: args->domain = RADEON_GEM_DOMAIN_CPU; default: break; } drm_gem_object_unreference_unlocked(gobj); r = radeon_gem_handle_lockup(rdev, r); return r; }
static int radeon_gem_set_domain(struct drm_gem_object *gobj, uint32_t rdomain, uint32_t wdomain) { struct radeon_bo *robj; uint32_t domain; int r; /* FIXME: reeimplement */ robj = gem_to_radeon_bo(gobj); /* work out where to validate the buffer to */ domain = wdomain; if (!domain) { domain = rdomain; } if (!domain) { /* Do nothings */ DRM_ERROR("Set domain without domain !\n"); return 0; } if (domain == RADEON_GEM_DOMAIN_CPU) { /* Asking for cpu access wait for object idle */ r = radeon_bo_wait(robj, NULL, false); if (r) { DRM_ERROR("Failed to wait for object !\n"); return r; } } return 0; }
static Bool radeon_glamor_prepare_access_cpu(ScrnInfoPtr scrn, RADEONInfoPtr info, PixmapPtr pixmap, struct radeon_pixmap *priv, Bool need_sync) { struct radeon_bo *bo = priv->bo; int ret; /* When falling back to swrast, flush all pending operations */ if (need_sync) { glamor_block_handler(scrn->pScreen); info->gpu_flushed++; } if (!pixmap->devPrivate.ptr) { ret = radeon_bo_map(bo, 1); if (ret) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: bo map (tiling_flags %d) failed: %s\n", __FUNCTION__, priv->tiling_flags, strerror(-ret)); return FALSE; } pixmap->devPrivate.ptr = bo->ptr; info->gpu_synced = info->gpu_flushed; } else if (need_sync) { radeon_bo_wait(bo); info->gpu_synced = info->gpu_flushed; } return TRUE; }
int radeon_gem_set_domain(struct drm_gem_object *gobj, uint32_t rdomain, uint32_t wdomain) { struct radeon_bo *robj; uint32_t domain; int r; /* FIXME: reeimplement */ robj = gobj->driver_private; /* work out where to validate the buffer to */ domain = wdomain; if (!domain) { domain = rdomain; } if (!domain) { /* Do nothings */ printk(KERN_WARNING "Set domain withou domain !\n"); return 0; } if (domain == RADEON_GEM_DOMAIN_CPU) { /* Asking for cpu access wait for object idle */ r = radeon_bo_wait(robj, NULL, false); if (r) { printk(KERN_ERR "Failed to wait for object !\n"); return r; } } return 0; }
int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct drm_radeon_gem_wait_idle *args = data; struct drm_gem_object *gobj; struct radeon_bo *robj; int r; gobj = drm_gem_object_lookup(dev, filp, args->handle); if (gobj == NULL) { return -ENOENT; } robj = gobj->driver_private; r = radeon_bo_wait(robj, NULL, false); /* callback hw specific functions if any */ if (robj->rdev->asic->ioctl_wait_idle) robj->rdev->asic->ioctl_wait_idle(robj->rdev, robj); drm_gem_object_unreference_unlocked(gobj); return r; }
void* r600_texture_transfer_map(struct pipe_context *ctx, struct pipe_transfer* transfer) { struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; struct radeon_bo *bo; enum pipe_format format = transfer->resource->format; struct r600_screen *rscreen = r600_screen(ctx->screen); struct r600_resource_texture *rtex; unsigned long offset = 0; char *map; int r; r600_flush(ctx, 0, NULL); if (rtransfer->linear_texture) { bo = ((struct r600_resource *)rtransfer->linear_texture)->bo; } else { rtex = (struct r600_resource_texture*)transfer->resource; if (rtex->depth) { r = r600_texture_from_depth(ctx, rtex, transfer->sr.level); if (r) { return NULL; } r600_flush(ctx, 0, NULL); bo = rtex->uncompressed; } else { bo = ((struct r600_resource *)transfer->resource)->bo; } offset = rtransfer->offset + transfer->box.y / util_format_get_blockheight(format) * transfer->stride + transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); } if (radeon_bo_map(rscreen->rw, bo)) { return NULL; } radeon_bo_wait(rscreen->rw, bo); map = bo->data; return map + offset; }
static void *radeon_bo_map_internal(struct pb_buffer *_buf, unsigned flags, void *flush_ctx) { struct radeon_bo *bo = radeon_bo(_buf); struct radeon_drm_cs *cs = flush_ctx; struct drm_radeon_gem_mmap args = {}; void *ptr; /* If it's not unsynchronized bo_map, flush CS if needed and then wait. */ if (!(flags & PB_USAGE_UNSYNCHRONIZED)) { /* DONTBLOCK doesn't make sense with UNSYNCHRONIZED. */ if (flags & PB_USAGE_DONTBLOCK) { if (!(flags & PB_USAGE_CPU_WRITE)) { /* Mapping for read. * * Since we are mapping for read, we don't need to wait * if the GPU is using the buffer for read too * (neither one is changing it). * * Only check whether the buffer is being used for write. */ if (radeon_bo_is_referenced_by_cs_for_write(cs, bo)) { cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC); return NULL; } if (radeon_bo_is_busy((struct pb_buffer*)bo, RADEON_USAGE_WRITE)) { return NULL; } } else { if (radeon_bo_is_referenced_by_cs(cs, bo)) { cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC); return NULL; } if (radeon_bo_is_busy((struct pb_buffer*)bo, RADEON_USAGE_READWRITE)) { return NULL; } } } else { if (!(flags & PB_USAGE_CPU_WRITE)) { /* Mapping for read. * * Since we are mapping for read, we don't need to wait * if the GPU is using the buffer for read too * (neither one is changing it). * * Only check whether the buffer is being used for write. */ if (radeon_bo_is_referenced_by_cs_for_write(cs, bo)) { cs->flush_cs(cs->flush_data, 0); } radeon_bo_wait((struct pb_buffer*)bo, RADEON_USAGE_WRITE); } else { /* Mapping for write. */ if (radeon_bo_is_referenced_by_cs(cs, bo)) { cs->flush_cs(cs->flush_data, 0); } else { /* Try to avoid busy-waiting in radeon_bo_wait. */ if (p_atomic_read(&bo->num_active_ioctls)) radeon_drm_cs_sync_flush(cs); } radeon_bo_wait((struct pb_buffer*)bo, RADEON_USAGE_READWRITE); } } } /* Return the pointer if it's already mapped. */ if (bo->ptr) return bo->ptr; /* Map the buffer. */ pipe_mutex_lock(bo->map_mutex); /* Return the pointer if it's already mapped (in case of a race). */ if (bo->ptr) { pipe_mutex_unlock(bo->map_mutex); return bo->ptr; } args.handle = bo->handle; args.offset = 0; args.size = (uint64_t)bo->size; if (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_MMAP, &args, sizeof(args))) { pipe_mutex_unlock(bo->map_mutex); fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n", bo, bo->handle); return NULL; } ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, bo->rws->fd, args.addr_ptr); if (ptr == MAP_FAILED) { pipe_mutex_unlock(bo->map_mutex); fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno); return NULL; } bo->ptr = ptr; pipe_mutex_unlock(bo->map_mutex); return bo->ptr; }