drm/i915/gem: Add a helper to read data from a GEM object page
Add a simple helper to read data with the CPU from the page of a GEM object. Do the read either via a kmap if the object has struct pages or an iomap otherwise. This is needed by the next patch, reading a u64 value from the object (w/o requiring the obj to be mapped to the GPU). Suggested by Chris. v2 (Chris): - Sanitize the type and order of func params. - Avoid consts requiring too many casts. - Use BUG_ON instead of WARN_ON, simplify the conditions. - Fix __iomem sparse errors. - Leave locking/syncing/pinning up to the caller, require only that the caller has pinned the object pages. - Check for iomem backing store before reading via an iomap. v3: - Fix offset passed to io_mapping_map_wc() missing a mem.region.start delta. (Chris, Matthew) Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Matthew Auld <matthew.william.auld@gmail.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20210120213834.1435710-1-imre.deak@intel.com
This commit is contained in:
parent
87199e4c24
commit
5fbc2c2bfa
|
@ -32,6 +32,7 @@
|
|||
#include "i915_gem_mman.h"
|
||||
#include "i915_gem_object.h"
|
||||
#include "i915_globals.h"
|
||||
#include "i915_memcpy.h"
|
||||
#include "i915_trace.h"
|
||||
|
||||
static struct i915_global_object {
|
||||
|
@ -383,6 +384,70 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
|
||||
{
|
||||
void *src_map;
|
||||
void *src_ptr;
|
||||
|
||||
src_map = kmap_atomic(i915_gem_object_get_page(obj, offset >> PAGE_SHIFT));
|
||||
|
||||
src_ptr = src_map + offset_in_page(offset);
|
||||
if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
|
||||
drm_clflush_virt_range(src_ptr, size);
|
||||
memcpy(dst, src_ptr, size);
|
||||
|
||||
kunmap_atomic(src_map);
|
||||
}
|
||||
|
||||
static void
|
||||
i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
|
||||
{
|
||||
void __iomem *src_map;
|
||||
void __iomem *src_ptr;
|
||||
dma_addr_t dma = i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT);
|
||||
|
||||
src_map = io_mapping_map_wc(&obj->mm.region->iomap,
|
||||
dma - obj->mm.region->region.start,
|
||||
PAGE_SIZE);
|
||||
|
||||
src_ptr = src_map + offset_in_page(offset);
|
||||
if (!i915_memcpy_from_wc(dst, (void __force *)src_ptr, size))
|
||||
memcpy_fromio(dst, src_ptr, size);
|
||||
|
||||
io_mapping_unmap(src_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_gem_object_read_from_page - read data from the page of a GEM object
|
||||
* @obj: GEM object to read from
|
||||
* @offset: offset within the object
|
||||
* @dst: buffer to store the read data
|
||||
* @size: size to read
|
||||
*
|
||||
* Reads data from @obj at the specified offset. The requested region to read
|
||||
* from can't cross a page boundary. The caller must ensure that @obj pages
|
||||
* are pinned and that @obj is synced wrt. any related writes.
|
||||
*
|
||||
* Returns 0 on success or -ENODEV if the type of @obj's backing store is
|
||||
* unsupported.
|
||||
*/
|
||||
int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
|
||||
{
|
||||
GEM_BUG_ON(offset >= obj->base.size);
|
||||
GEM_BUG_ON(offset_in_page(offset) > PAGE_SIZE - size);
|
||||
GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
|
||||
|
||||
if (i915_gem_object_has_struct_page(obj))
|
||||
i915_gem_object_read_from_page_kmap(obj, offset, dst, size);
|
||||
else if (i915_gem_object_has_iomem(obj))
|
||||
i915_gem_object_read_from_page_iomap(obj, offset, dst, size);
|
||||
else
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i915_gem_init__objects(struct drm_i915_private *i915)
|
||||
{
|
||||
INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
|
||||
|
|
|
@ -200,6 +200,12 @@ i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj)
|
|||
return i915_gem_object_type_has(obj, I915_GEM_OBJECT_HAS_STRUCT_PAGE);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
i915_gem_object_has_iomem(const struct drm_i915_gem_object *obj)
|
||||
{
|
||||
return i915_gem_object_type_has(obj, I915_GEM_OBJECT_HAS_IOMEM);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
i915_gem_object_is_shrinkable(const struct drm_i915_gem_object *obj)
|
||||
{
|
||||
|
@ -540,4 +546,6 @@ i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
|
|||
__i915_gem_object_invalidate_frontbuffer(obj, origin);
|
||||
}
|
||||
|
||||
int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue