On Mon, Jul 30, 2018 at 04:51:58PM +0200, Christian König wrote: > This avoids multiple allocations for the head and the array. > I am afraid I don't get the point that how to avoid multiple times of allocations. Could you please explain more? Thanks, Ray > Signed-off-by: Christian König <christian.koenig at amd.com> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 114 +++++++++++----------------- > drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h | 17 +++-- > 2 files changed, 57 insertions(+), 74 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c > index 096bcf4a6334..d472a2c8399f 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c > @@ -35,13 +35,15 @@ > #define AMDGPU_BO_LIST_MAX_PRIORITY 32u > #define AMDGPU_BO_LIST_NUM_BUCKETS (AMDGPU_BO_LIST_MAX_PRIORITY + 1) > > -static int amdgpu_bo_list_set(struct amdgpu_device *adev, > - struct drm_file *filp, > - struct amdgpu_bo_list *list, > - struct drm_amdgpu_bo_list_entry *info, > - unsigned num_entries); > +static void amdgpu_bo_list_free_rcu(struct rcu_head *rcu) > +{ > + struct amdgpu_bo_list *list = container_of(rcu, struct amdgpu_bo_list, > + rhead); > + > + kvfree(list); > +} > > -static void amdgpu_bo_list_release_rcu(struct kref *ref) > +static void amdgpu_bo_list_free(struct kref *ref) > { > struct amdgpu_bo_list *list = container_of(ref, struct amdgpu_bo_list, > refcount); > @@ -50,67 +52,36 @@ static void amdgpu_bo_list_release_rcu(struct kref *ref) > amdgpu_bo_list_for_each_entry(e, list) > amdgpu_bo_unref(&e->robj); > > - kvfree(list->array); > - kfree_rcu(list, rhead); > + call_rcu(&list->rhead, amdgpu_bo_list_free_rcu); > } > > -int amdgpu_bo_list_create(struct amdgpu_device *adev, > - struct drm_file *filp, > - struct drm_amdgpu_bo_list_entry *info, > - unsigned num_entries, > - struct amdgpu_bo_list **list_out) > +int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp, > + struct drm_amdgpu_bo_list_entry *info, > + unsigned num_entries, struct amdgpu_bo_list **result) > { > + unsigned last_entry = 0, first_userptr = num_entries; > + struct amdgpu_bo_list_entry *array; > struct amdgpu_bo_list *list; > + uint64_t total_size = 0; > + size_t size; > + unsigned i; > int r; > > + if (num_entries > SIZE_MAX / sizeof(struct amdgpu_bo_list_entry)) > + return -EINVAL; > > - list = kzalloc(sizeof(struct amdgpu_bo_list), GFP_KERNEL); > + size = sizeof(struct amdgpu_bo_list); > + size += num_entries * sizeof(struct amdgpu_bo_list_entry); > + list = kvmalloc(size, GFP_KERNEL); > if (!list) > return -ENOMEM; > > - /* initialize bo list*/ > kref_init(&list->refcount); > - r = amdgpu_bo_list_set(adev, filp, list, info, num_entries); > - if (r) { > - kfree(list); > - return r; > - } > - > - *list_out = list; > - return 0; > -} > - > -static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id) > -{ > - struct amdgpu_bo_list *list; > - > - mutex_lock(&fpriv->bo_list_lock); > - list = idr_remove(&fpriv->bo_list_handles, id); > - mutex_unlock(&fpriv->bo_list_lock); > - if (list) > - kref_put(&list->refcount, amdgpu_bo_list_release_rcu); > -} > - > -static int amdgpu_bo_list_set(struct amdgpu_device *adev, > - struct drm_file *filp, > - struct amdgpu_bo_list *list, > - struct drm_amdgpu_bo_list_entry *info, > - unsigned num_entries) > -{ > - struct amdgpu_bo_list_entry *array; > - struct amdgpu_bo *gds_obj = adev->gds.gds_gfx_bo; > - struct amdgpu_bo *gws_obj = adev->gds.gws_gfx_bo; > - struct amdgpu_bo *oa_obj = adev->gds.oa_gfx_bo; > - > - unsigned last_entry = 0, first_userptr = num_entries; > - struct amdgpu_bo_list_entry *e; > - uint64_t total_size = 0; > - unsigned i; > - int r; > + list->gds_obj = adev->gds.gds_gfx_bo; > + list->gws_obj = adev->gds.gws_gfx_bo; > + list->oa_obj = adev->gds.oa_gfx_bo; > > - array = kvmalloc_array(num_entries, sizeof(struct amdgpu_bo_list_entry), GFP_KERNEL); > - if (!array) > - return -ENOMEM; > + array = amdgpu_bo_list_array_entry(list, 0); > memset(array, 0, num_entries * sizeof(struct amdgpu_bo_list_entry)); > > for (i = 0; i < num_entries; ++i) { > @@ -147,36 +118,41 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev, > entry->tv.shared = !entry->robj->prime_shared_count; > > if (entry->robj->preferred_domains == AMDGPU_GEM_DOMAIN_GDS) > - gds_obj = entry->robj; > + list->gds_obj = entry->robj; > if (entry->robj->preferred_domains == AMDGPU_GEM_DOMAIN_GWS) > - gws_obj = entry->robj; > + list->gws_obj = entry->robj; > if (entry->robj->preferred_domains == AMDGPU_GEM_DOMAIN_OA) > - oa_obj = entry->robj; > + list->oa_obj = entry->robj; > > total_size += amdgpu_bo_size(entry->robj); > trace_amdgpu_bo_list_set(list, entry->robj); > } > > - amdgpu_bo_list_for_each_entry(e, list) > - amdgpu_bo_unref(&list->array[i].robj); > - > - kvfree(list->array); > - > - list->gds_obj = gds_obj; > - list->gws_obj = gws_obj; > - list->oa_obj = oa_obj; > list->first_userptr = first_userptr; > - list->array = array; > list->num_entries = num_entries; > > trace_amdgpu_cs_bo_status(list->num_entries, total_size); > + > + *result = list; > return 0; > > error_free: > while (i--) > amdgpu_bo_unref(&array[i].robj); > - kvfree(array); > + kvfree(list); > return r; > + > +} > + > +static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id) > +{ > + struct amdgpu_bo_list *list; > + > + mutex_lock(&fpriv->bo_list_lock); > + list = idr_remove(&fpriv->bo_list_handles, id); > + mutex_unlock(&fpriv->bo_list_lock); > + if (list) > + kref_put(&list->refcount, amdgpu_bo_list_free); > } > > int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, > @@ -229,7 +205,7 @@ void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, > > void amdgpu_bo_list_put(struct amdgpu_bo_list *list) > { > - kref_put(&list->refcount, amdgpu_bo_list_release_rcu); > + kref_put(&list->refcount, amdgpu_bo_list_free); > } > > int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h > index 3d77abfcd4a6..61b089768e1c 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h > @@ -48,7 +48,6 @@ struct amdgpu_bo_list { > struct amdgpu_bo *oa_obj; > unsigned first_userptr; > unsigned num_entries; > - struct amdgpu_bo_list_entry *array; > }; > > int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, > @@ -65,14 +64,22 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev, > unsigned num_entries, > struct amdgpu_bo_list **list); > > +static inline struct amdgpu_bo_list_entry * > +amdgpu_bo_list_array_entry(struct amdgpu_bo_list *list, unsigned index) > +{ > + struct amdgpu_bo_list_entry *array = (void *)&list[1]; > + > + return &array[index]; > +} > + > #define amdgpu_bo_list_for_each_entry(e, list) \ > - for (e = &(list)->array[0]; \ > - e != &(list)->array[(list)->num_entries]; \ > + for (e = amdgpu_bo_list_array_entry(list, 0); \ > + e != amdgpu_bo_list_array_entry(list, (list)->num_entries); \ > ++e) > > #define amdgpu_bo_list_for_each_userptr_entry(e, list) \ > - for (e = &(list)->array[(list)->first_userptr]; \ > - e != &(list)->array[(list)->num_entries]; \ > + for (e = amdgpu_bo_list_array_entry(list, (list)->first_userptr); \ > + e != amdgpu_bo_list_array_entry(list, (list)->num_entries); \ > ++e) > > #endif > -- > 2.14.1 > > _______________________________________________ > amd-gfx mailing list > amd-gfx at lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx