int qxl_hw_surface_alloc(struct qxl_device *qdev, struct qxl_bo *surf, struct ttm_mem_reg *new_mem) { struct qxl_surface_cmd *cmd; struct qxl_release *release; int ret; if (surf->hw_surf_alloc) return 0; ret = qxl_alloc_surface_release_reserved(qdev, QXL_SURFACE_CMD_CREATE, NULL, &release); if (ret) return ret; ret = qxl_release_reserve_list(release, true); if (ret) return ret; cmd = (struct qxl_surface_cmd *)qxl_release_map(qdev, release); cmd->type = QXL_SURFACE_CMD_CREATE; cmd->flags = QXL_SURF_FLAG_KEEP_DATA; cmd->u.surface_create.format = surf->surf.format; cmd->u.surface_create.width = surf->surf.width; cmd->u.surface_create.height = surf->surf.height; cmd->u.surface_create.stride = surf->surf.stride; if (new_mem) { int slot_id = surf->type == QXL_GEM_DOMAIN_VRAM ? qdev->main_mem_slot : qdev->surfaces_mem_slot; struct qxl_memslot *slot = &(qdev->mem_slots[slot_id]); /* TODO - need to hold one of the locks to read tbo.offset */ cmd->u.surface_create.data = slot->high_bits; cmd->u.surface_create.data |= (new_mem->start << PAGE_SHIFT) + surf->tbo.bdev->man[new_mem->mem_type].gpu_offset; } else cmd->u.surface_create.data = qxl_bo_physical_address(qdev, surf, 0); cmd->surface_id = surf->surface_id; qxl_release_unmap(qdev, release, &cmd->release_info); surf->surf_create = release; /* no need to add a release to the fence for this surface bo, since it is only released when we ask to destroy the surface and it would never signal otherwise */ qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false); qxl_release_fence_buffer_objects(release); surf->hw_surf_alloc = true; spin_lock(&qdev->surf_id_idr_lock); idr_replace(&qdev->surf_id_idr, surf, surf->surface_id); spin_unlock(&qdev->surf_id_idr_lock); return 0; }
int qxl_hw_surface_dealloc(struct qxl_device *qdev, struct qxl_bo *surf) { struct qxl_surface_cmd *cmd; struct qxl_release *release; int ret; int id; if (!surf->hw_surf_alloc) return 0; ret = qxl_alloc_surface_release_reserved(qdev, QXL_SURFACE_CMD_DESTROY, surf->surf_create, &release); if (ret) return ret; surf->surf_create = NULL; /* remove the surface from the idr, but not the surface id yet */ spin_lock(&qdev->surf_id_idr_lock); idr_replace(&qdev->surf_id_idr, NULL, surf->surface_id); spin_unlock(&qdev->surf_id_idr_lock); surf->hw_surf_alloc = false; id = surf->surface_id; surf->surface_id = 0; release->surface_release_id = id; cmd = (struct qxl_surface_cmd *)qxl_release_map(qdev, release); cmd->type = QXL_SURFACE_CMD_DESTROY; cmd->surface_id = id; qxl_release_unmap(qdev, release, &cmd->release_info); qxl_fence_releaseable(qdev, release); qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false); qxl_release_unreserve(qdev, release); return 0; }