On Tue, Sep 12, 2017 at 7:05 PM, Felix Kuehling <Felix.Kuehling at amd.com> wrote: > PASID management is moving into KGD. Limiting the PASID range to the > number of doorbell pages is no longer practical. > > Signed-off-by: Felix Kuehling <Felix.Kuehling at amd.com> Maybe you want this before patches 2 and 3? Acked-by: Alex Deucher <alexander.deucher at amd.com> > --- > drivers/gpu/drm/amd/amdkfd/kfd_device.c | 7 ----- > drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c | 50 +++++++++++++++++++++---------- > drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 10 +++---- > drivers/gpu/drm/amd/amdkfd/kfd_process.c | 6 ++++ > 4 files changed, 45 insertions(+), 28 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c > index 61fff25..5df12b2 100644 > --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c > @@ -168,13 +168,6 @@ static bool device_iommu_pasid_init(struct kfd_dev *kfd) > pasid_limit = min_t(unsigned int, > (unsigned int)(1 << kfd->device_info->max_pasid_bits), > iommu_info.max_pasids); > - /* > - * last pasid is used for kernel queues doorbells > - * in the future the last pasid might be used for a kernel thread. > - */ > - pasid_limit = min_t(unsigned int, > - pasid_limit, > - kfd->doorbell_process_limit - 1); > > err = amd_iommu_init_device(kfd->pdev, pasid_limit); > if (err < 0) { > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c > index acf4d2a..feb76c2 100644 > --- a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c > @@ -24,16 +24,15 @@ > #include <linux/mman.h> > #include <linux/slab.h> > #include <linux/io.h> > +#include <linux/idr.h> > > /* > - * This extension supports a kernel level doorbells management for > - * the kernel queues. > - * Basically the last doorbells page is devoted to kernel queues > - * and that's assures that any user process won't get access to the > - * kernel doorbells page > + * This extension supports a kernel level doorbells management for the > + * kernel queues using the first doorbell page reserved for the kernel. > */ > > -#define KERNEL_DOORBELL_PASID 1 > +static DEFINE_IDA(doorbell_ida); > +static unsigned int max_doorbell_slices; > #define KFD_SIZE_OF_DOORBELL_IN_BYTES 4 > > /* > @@ -84,13 +83,16 @@ int kfd_doorbell_init(struct kfd_dev *kfd) > (doorbell_aperture_size - doorbell_start_offset) / > doorbell_process_allocation(); > else > - doorbell_process_limit = 0; > + return -ENOSPC; > + > + if (!max_doorbell_slices || > + doorbell_process_limit < max_doorbell_slices) > + max_doorbell_slices = doorbell_process_limit; > > kfd->doorbell_base = kfd->shared_resources.doorbell_physical_address + > doorbell_start_offset; > > kfd->doorbell_id_offset = doorbell_start_offset / sizeof(u32); > - kfd->doorbell_process_limit = doorbell_process_limit - 1; > > kfd->doorbell_kernel_ptr = ioremap(kfd->doorbell_base, > doorbell_process_allocation()); > @@ -185,11 +187,10 @@ u32 __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd, > return NULL; > > /* > - * Calculating the kernel doorbell offset using "faked" kernel > - * pasid that allocated for kernel queues only > + * Calculating the kernel doorbell offset using the first > + * doorbell page. > */ > - *doorbell_off = KERNEL_DOORBELL_PASID * (doorbell_process_allocation() / > - sizeof(u32)) + inx; > + *doorbell_off = kfd->doorbell_id_offset + inx; > > pr_debug("Get kernel queue doorbell\n" > " doorbell offset == 0x%08X\n" > @@ -228,11 +229,12 @@ unsigned int kfd_queue_id_to_doorbell(struct kfd_dev *kfd, > { > /* > * doorbell_id_offset accounts for doorbells taken by KGD. > - * pasid * doorbell_process_allocation/sizeof(u32) adjusts > - * to the process's doorbells > + * index * doorbell_process_allocation/sizeof(u32) adjusts to > + * the process's doorbells. > */ > return kfd->doorbell_id_offset + > - process->pasid * (doorbell_process_allocation()/sizeof(u32)) + > + process->doorbell_index > + * doorbell_process_allocation() / sizeof(u32) + > queue_id; > } > > @@ -250,5 +252,21 @@ phys_addr_t kfd_get_process_doorbells(struct kfd_dev *dev, > struct kfd_process *process) > { > return dev->doorbell_base + > - process->pasid * doorbell_process_allocation(); > + process->doorbell_index * doorbell_process_allocation(); > +} > + > +int kfd_alloc_process_doorbells(struct kfd_process *process) > +{ > + int r = ida_simple_get(&doorbell_ida, 1, max_doorbell_slices, > + GFP_KERNEL); > + if (r > 0) > + process->doorbell_index = r; > + > + return r; > +} > + > +void kfd_free_process_doorbells(struct kfd_process *process) > +{ > + if (process->doorbell_index) > + ida_simple_remove(&doorbell_ida, process->doorbell_index); > } > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h > index b397ec7..4cb90f5 100644 > --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h > @@ -157,9 +157,6 @@ struct kfd_dev { > * to HW doorbell, GFX reserved some > * at the start) > */ > - size_t doorbell_process_limit; /* Number of processes we have doorbell > - * space for. > - */ > u32 __iomem *doorbell_kernel_ptr; /* This is a pointer for a doorbells > * page used by kernel queue > */ > @@ -495,6 +492,7 @@ struct kfd_process { > struct rcu_head rcu; > > unsigned int pasid; > + unsigned int doorbell_index; > > /* > * List of kfd_process_device structures, > @@ -583,6 +581,10 @@ void write_kernel_doorbell(u32 __iomem *db, u32 value); > unsigned int kfd_queue_id_to_doorbell(struct kfd_dev *kfd, > struct kfd_process *process, > unsigned int queue_id); > +phys_addr_t kfd_get_process_doorbells(struct kfd_dev *dev, > + struct kfd_process *process); > +int kfd_alloc_process_doorbells(struct kfd_process *process); > +void kfd_free_process_doorbells(struct kfd_process *process); > > /* GTT Sub-Allocator */ > > @@ -694,8 +696,6 @@ int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type, > void pm_release_ib(struct packet_manager *pm); > > uint64_t kfd_get_number_elems(struct kfd_dev *kfd); > -phys_addr_t kfd_get_process_doorbells(struct kfd_dev *dev, > - struct kfd_process *process); > > /* Events */ > extern const struct kfd_event_interrupt_class event_interrupt_class_cik; > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c > index c74cf22..9e65ce3 100644 > --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c > @@ -183,6 +183,7 @@ static void kfd_process_wq_release(struct work_struct *work) > kfd_event_free_process(p); > > kfd_pasid_free(p->pasid); > + kfd_free_process_doorbells(p); > > mutex_unlock(&p->mutex); > > @@ -288,6 +289,9 @@ static struct kfd_process *create_process(const struct task_struct *thread) > if (process->pasid == 0) > goto err_alloc_pasid; > > + if (kfd_alloc_process_doorbells(process) < 0) > + goto err_alloc_doorbells; > + > mutex_init(&process->mutex); > > process->mm = thread->mm; > @@ -329,6 +333,8 @@ static struct kfd_process *create_process(const struct task_struct *thread) > mmu_notifier_unregister_no_release(&process->mmu_notifier, process->mm); > err_mmu_notifier: > mutex_destroy(&process->mutex); > + kfd_free_process_doorbells(process); > +err_alloc_doorbells: > kfd_pasid_free(process->pasid); > err_alloc_pasid: > kfree(process->queues); > -- > 2.7.4 > > _______________________________________________ > amd-gfx mailing list > amd-gfx at lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx