mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
drm/gpusvm: embed struct drm_device into drm_gpusvm_pages
drm_gpusvm_pages is the layer that actually represents physical
pages/mappings it owns the dma_addr array, the dma_iova_state...
With the previous patch, so drm_gpusvm_pages is now strictly about
physical pages and their DMA view.
Since now the drm_gpusvm_pages instance is inherently bound to one
specific drm_device, make that ownership explicit by giving
drm_gpusvm_pages its own drm_device handle, and drive all DMA through
it instead of through the gpusvm:
- Add drm to struct drm_gpusvm_pages and route all DMA in
drm_gpusvm_get_pages() / __drm_gpusvm_unmap_pages() through
svm_pages->drm instead of gpusvm->drm.
- Bind svm_pages->drm where the pages object is initialised
(drm_gpusvm_range_alloc() and the xe userptr setup) and require
it to be set on entry to drm_gpusvm_get_pages(); the dma device
is immutable for the lifetime of the pages instance. A later
patch introduces drm_gpusvm_init_pages() to centralise this.
Suggested-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Honglei Huang <honghuan@amd.com>
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Link: https://patch.msgid.link/20260630102127.392396-3-honghuan@amd.com
This commit is contained in:
parent
ba40db3697
commit
1d0c4c15c2
|
|
@ -641,6 +641,7 @@ drm_gpusvm_range_alloc(struct drm_gpusvm *gpusvm,
|
|||
range->itree.last = ALIGN(fault_addr + 1, chunk_size) - 1;
|
||||
INIT_LIST_HEAD(&range->entry);
|
||||
range->pages.notifier_seq = LONG_MAX;
|
||||
range->pages.drm = gpusvm->drm;
|
||||
range->flags.migrate_devmem = migrate_devmem ? 1 : 0;
|
||||
|
||||
return range;
|
||||
|
|
@ -1135,11 +1136,16 @@ static void __drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
|
|||
unsigned long npages)
|
||||
{
|
||||
struct drm_pagemap *dpagemap = svm_pages->dpagemap;
|
||||
struct device *dev = gpusvm->drm->dev;
|
||||
struct device *dev;
|
||||
unsigned long i, j;
|
||||
|
||||
lockdep_assert_held(&gpusvm->notifier_lock);
|
||||
|
||||
if (!svm_pages->drm)
|
||||
return;
|
||||
|
||||
dev = svm_pages->drm->dev;
|
||||
|
||||
if (svm_pages->flags.has_dma_mapping) {
|
||||
struct drm_gpusvm_pages_flags flags = {
|
||||
.__flags = svm_pages->flags.__flags,
|
||||
|
|
@ -1421,6 +1427,9 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
|
|||
DMA_BIDIRECTIONAL;
|
||||
struct dma_iova_state *state = &svm_pages->state;
|
||||
|
||||
if (!svm_pages->drm)
|
||||
return -EINVAL;
|
||||
|
||||
retry:
|
||||
if (time_after(jiffies, timeout))
|
||||
return -EBUSY;
|
||||
|
|
@ -1520,7 +1529,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
|
|||
|
||||
pagemap = page_pgmap(page);
|
||||
dpagemap = drm_pagemap_page_to_dpagemap(page);
|
||||
if (drm_WARN_ON(gpusvm->drm, !dpagemap)) {
|
||||
if (drm_WARN_ON(svm_pages->drm, !dpagemap)) {
|
||||
/*
|
||||
* Raced. This is not supposed to happen
|
||||
* since hmm_range_fault() should've migrated
|
||||
|
|
@ -1532,10 +1541,10 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
|
|||
}
|
||||
svm_pages->dma_addr[j] =
|
||||
dpagemap->ops->device_map(dpagemap,
|
||||
gpusvm->drm->dev,
|
||||
svm_pages->drm->dev,
|
||||
page, order,
|
||||
dma_dir);
|
||||
if (dma_mapping_error(gpusvm->drm->dev,
|
||||
if (dma_mapping_error(svm_pages->drm->dev,
|
||||
svm_pages->dma_addr[j].addr)) {
|
||||
err = -EFAULT;
|
||||
goto err_unmap;
|
||||
|
|
@ -1555,11 +1564,11 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
|
|||
}
|
||||
|
||||
if (!i)
|
||||
dma_iova_try_alloc(gpusvm->drm->dev, state,
|
||||
dma_iova_try_alloc(svm_pages->drm->dev, state,
|
||||
0, npages * PAGE_SIZE);
|
||||
|
||||
if (dma_use_iova(state)) {
|
||||
err = dma_iova_link(gpusvm->drm->dev, state,
|
||||
err = dma_iova_link(svm_pages->drm->dev, state,
|
||||
hmm_pfn_to_phys(pfns[i]),
|
||||
svm_pages->state_offset,
|
||||
PAGE_SIZE << order,
|
||||
|
|
@ -1570,11 +1579,11 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
|
|||
addr = state->addr + svm_pages->state_offset;
|
||||
svm_pages->state_offset += PAGE_SIZE << order;
|
||||
} else {
|
||||
addr = dma_map_page(gpusvm->drm->dev,
|
||||
addr = dma_map_page(svm_pages->drm->dev,
|
||||
page, 0,
|
||||
PAGE_SIZE << order,
|
||||
dma_dir);
|
||||
if (dma_mapping_error(gpusvm->drm->dev, addr)) {
|
||||
if (dma_mapping_error(svm_pages->drm->dev, addr)) {
|
||||
err = -EFAULT;
|
||||
goto err_unmap;
|
||||
}
|
||||
|
|
@ -1590,7 +1599,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
|
|||
}
|
||||
|
||||
if (dma_use_iova(state)) {
|
||||
err = dma_iova_sync(gpusvm->drm->dev, state, 0,
|
||||
err = dma_iova_sync(svm_pages->drm->dev, state, 0,
|
||||
svm_pages->state_offset);
|
||||
if (err)
|
||||
goto err_unmap;
|
||||
|
|
@ -1640,7 +1649,8 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
|
|||
struct drm_gpusvm_range *range,
|
||||
const struct drm_gpusvm_ctx *ctx)
|
||||
{
|
||||
return drm_gpusvm_get_pages(gpusvm, &range->pages, gpusvm->mm,
|
||||
return drm_gpusvm_get_pages(gpusvm, &range->pages,
|
||||
gpusvm->mm,
|
||||
&range->notifier->notifier,
|
||||
drm_gpusvm_range_start(range),
|
||||
drm_gpusvm_range_end(range), ctx);
|
||||
|
|
|
|||
|
|
@ -390,6 +390,7 @@ int xe_userptr_setup(struct xe_userptr_vma *uvma, unsigned long start,
|
|||
unsigned long range)
|
||||
{
|
||||
struct xe_userptr *userptr = &uvma->userptr;
|
||||
struct xe_vm *vm = xe_vma_vm(&uvma->vma);
|
||||
int err;
|
||||
|
||||
INIT_LIST_HEAD(&userptr->invalidate_link);
|
||||
|
|
@ -402,6 +403,7 @@ int xe_userptr_setup(struct xe_userptr_vma *uvma, unsigned long start,
|
|||
return err;
|
||||
|
||||
userptr->pages.notifier_seq = LONG_MAX;
|
||||
userptr->pages.drm = &vm->xe->drm;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ struct drm_gpusvm_pages_flags {
|
|||
/**
|
||||
* struct drm_gpusvm_pages - Structure representing a GPU SVM mapped pages
|
||||
*
|
||||
* @drm: The DRM device that owns the dma mappings
|
||||
* @dma_addr: Device address array
|
||||
* @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping.
|
||||
* Note this is assuming only one drm_pagemap per range is allowed.
|
||||
|
|
@ -138,6 +139,7 @@ struct drm_gpusvm_pages_flags {
|
|||
* @flags: Flags for the range; see &struct drm_gpusvm_pages_flags
|
||||
*/
|
||||
struct drm_gpusvm_pages {
|
||||
struct drm_device *drm;
|
||||
struct drm_pagemap_addr *dma_addr;
|
||||
struct drm_pagemap *dpagemap;
|
||||
struct dma_iova_state state;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user