diff options
author | Christian König <christian.koenig@amd.com> | 2018-07-30 10:16:01 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-07-31 17:58:19 -0400 |
commit | 920990cb080a44203bf6c8eb706e79ad23241ad3 (patch) | |
tree | c561ae3c784ad5930fd2db05389b2516b89693e4 | |
parent | 39f7f69a6054bb9777b47b6afdb5ce2fae30dbee (diff) |
drm/amdgpu: allocate the bo_list array after the list
This avoids multiple allocations for the head and the array.
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Chunming Zhou <david1.zhou@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 114 | ||||
-rw-r--r-- | 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 @@ | |||
35 | #define AMDGPU_BO_LIST_MAX_PRIORITY 32u | 35 | #define AMDGPU_BO_LIST_MAX_PRIORITY 32u |
36 | #define AMDGPU_BO_LIST_NUM_BUCKETS (AMDGPU_BO_LIST_MAX_PRIORITY + 1) | 36 | #define AMDGPU_BO_LIST_NUM_BUCKETS (AMDGPU_BO_LIST_MAX_PRIORITY + 1) |
37 | 37 | ||
38 | static int amdgpu_bo_list_set(struct amdgpu_device *adev, | 38 | static void amdgpu_bo_list_free_rcu(struct rcu_head *rcu) |
39 | struct drm_file *filp, | 39 | { |
40 | struct amdgpu_bo_list *list, | 40 | struct amdgpu_bo_list *list = container_of(rcu, struct amdgpu_bo_list, |
41 | struct drm_amdgpu_bo_list_entry *info, | 41 | rhead); |
42 | unsigned num_entries); | 42 | |
43 | kvfree(list); | ||
44 | } | ||
43 | 45 | ||
44 | static void amdgpu_bo_list_release_rcu(struct kref *ref) | 46 | static void amdgpu_bo_list_free(struct kref *ref) |
45 | { | 47 | { |
46 | struct amdgpu_bo_list *list = container_of(ref, struct amdgpu_bo_list, | 48 | struct amdgpu_bo_list *list = container_of(ref, struct amdgpu_bo_list, |
47 | refcount); | 49 | refcount); |
@@ -50,67 +52,36 @@ static void amdgpu_bo_list_release_rcu(struct kref *ref) | |||
50 | amdgpu_bo_list_for_each_entry(e, list) | 52 | amdgpu_bo_list_for_each_entry(e, list) |
51 | amdgpu_bo_unref(&e->robj); | 53 | amdgpu_bo_unref(&e->robj); |
52 | 54 | ||
53 | kvfree(list->array); | 55 | call_rcu(&list->rhead, amdgpu_bo_list_free_rcu); |
54 | kfree_rcu(list, rhead); | ||
55 | } | 56 | } |
56 | 57 | ||
57 | int amdgpu_bo_list_create(struct amdgpu_device *adev, | 58 | int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp, |
58 | struct drm_file *filp, | 59 | struct drm_amdgpu_bo_list_entry *info, |
59 | struct drm_amdgpu_bo_list_entry *info, | 60 | unsigned num_entries, struct amdgpu_bo_list **result) |
60 | unsigned num_entries, | ||
61 | struct amdgpu_bo_list **list_out) | ||
62 | { | 61 | { |
62 | unsigned last_entry = 0, first_userptr = num_entries; | ||
63 | struct amdgpu_bo_list_entry *array; | ||
63 | struct amdgpu_bo_list *list; | 64 | struct amdgpu_bo_list *list; |
65 | uint64_t total_size = 0; | ||
66 | size_t size; | ||
67 | unsigned i; | ||
64 | int r; | 68 | int r; |
65 | 69 | ||
70 | if (num_entries > SIZE_MAX / sizeof(struct amdgpu_bo_list_entry)) | ||
71 | return -EINVAL; | ||
66 | 72 | ||
67 | list = kzalloc(sizeof(struct amdgpu_bo_list), GFP_KERNEL); | 73 | size = sizeof(struct amdgpu_bo_list); |
74 | size += num_entries * sizeof(struct amdgpu_bo_list_entry); | ||
75 | list = kvmalloc(size, GFP_KERNEL); | ||
68 | if (!list) | 76 | if (!list) |
69 | return -ENOMEM; | 77 | return -ENOMEM; |
70 | 78 | ||
71 | /* initialize bo list*/ | ||
72 | kref_init(&list->refcount); | 79 | kref_init(&list->refcount); |
73 | r = amdgpu_bo_list_set(adev, filp, list, info, num_entries); | 80 | list->gds_obj = adev->gds.gds_gfx_bo; |
74 | if (r) { | 81 | list->gws_obj = adev->gds.gws_gfx_bo; |
75 | kfree(list); | 82 | list->oa_obj = adev->gds.oa_gfx_bo; |
76 | return r; | ||
77 | } | ||
78 | |||
79 | *list_out = list; | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id) | ||
84 | { | ||
85 | struct amdgpu_bo_list *list; | ||
86 | |||
87 | mutex_lock(&fpriv->bo_list_lock); | ||
88 | list = idr_remove(&fpriv->bo_list_handles, id); | ||
89 | mutex_unlock(&fpriv->bo_list_lock); | ||
90 | if (list) | ||
91 | kref_put(&list->refcount, amdgpu_bo_list_release_rcu); | ||
92 | } | ||
93 | |||
94 | static int amdgpu_bo_list_set(struct amdgpu_device *adev, | ||
95 | struct drm_file *filp, | ||
96 | struct amdgpu_bo_list *list, | ||
97 | struct drm_amdgpu_bo_list_entry *info, | ||
98 | unsigned num_entries) | ||
99 | { | ||
100 | struct amdgpu_bo_list_entry *array; | ||
101 | struct amdgpu_bo *gds_obj = adev->gds.gds_gfx_bo; | ||
102 | struct amdgpu_bo *gws_obj = adev->gds.gws_gfx_bo; | ||
103 | struct amdgpu_bo *oa_obj = adev->gds.oa_gfx_bo; | ||
104 | |||
105 | unsigned last_entry = 0, first_userptr = num_entries; | ||
106 | struct amdgpu_bo_list_entry *e; | ||
107 | uint64_t total_size = 0; | ||
108 | unsigned i; | ||
109 | int r; | ||
110 | 83 | ||
111 | array = kvmalloc_array(num_entries, sizeof(struct amdgpu_bo_list_entry), GFP_KERNEL); | 84 | array = amdgpu_bo_list_array_entry(list, 0); |
112 | if (!array) | ||
113 | return -ENOMEM; | ||
114 | memset(array, 0, num_entries * sizeof(struct amdgpu_bo_list_entry)); | 85 | memset(array, 0, num_entries * sizeof(struct amdgpu_bo_list_entry)); |
115 | 86 | ||
116 | for (i = 0; i < num_entries; ++i) { | 87 | for (i = 0; i < num_entries; ++i) { |
@@ -147,36 +118,41 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev, | |||
147 | entry->tv.shared = !entry->robj->prime_shared_count; | 118 | entry->tv.shared = !entry->robj->prime_shared_count; |
148 | 119 | ||
149 | if (entry->robj->preferred_domains == AMDGPU_GEM_DOMAIN_GDS) | 120 | if (entry->robj->preferred_domains == AMDGPU_GEM_DOMAIN_GDS) |
150 | gds_obj = entry->robj; | 121 | list->gds_obj = entry->robj; |
151 | if (entry->robj->preferred_domains == AMDGPU_GEM_DOMAIN_GWS) | 122 | if (entry->robj->preferred_domains == AMDGPU_GEM_DOMAIN_GWS) |
152 | gws_obj = entry->robj; | 123 | list->gws_obj = entry->robj; |
153 | if (entry->robj->preferred_domains == AMDGPU_GEM_DOMAIN_OA) | 124 | if (entry->robj->preferred_domains == AMDGPU_GEM_DOMAIN_OA) |
154 | oa_obj = entry->robj; | 125 | list->oa_obj = entry->robj; |
155 | 126 | ||
156 | total_size += amdgpu_bo_size(entry->robj); | 127 | total_size += amdgpu_bo_size(entry->robj); |
157 | trace_amdgpu_bo_list_set(list, entry->robj); | 128 | trace_amdgpu_bo_list_set(list, entry->robj); |
158 | } | 129 | } |
159 | 130 | ||
160 | amdgpu_bo_list_for_each_entry(e, list) | ||
161 | amdgpu_bo_unref(&list->array[i].robj); | ||
162 | |||
163 | kvfree(list->array); | ||
164 | |||
165 | list->gds_obj = gds_obj; | ||
166 | list->gws_obj = gws_obj; | ||
167 | list->oa_obj = oa_obj; | ||
168 | list->first_userptr = first_userptr; | 131 | list->first_userptr = first_userptr; |
169 | list->array = array; | ||
170 | list->num_entries = num_entries; | 132 | list->num_entries = num_entries; |
171 | 133 | ||
172 | trace_amdgpu_cs_bo_status(list->num_entries, total_size); | 134 | trace_amdgpu_cs_bo_status(list->num_entries, total_size); |
135 | |||
136 | *result = list; | ||
173 | return 0; | 137 | return 0; |
174 | 138 | ||
175 | error_free: | 139 | error_free: |
176 | while (i--) | 140 | while (i--) |
177 | amdgpu_bo_unref(&array[i].robj); | 141 | amdgpu_bo_unref(&array[i].robj); |
178 | kvfree(array); | 142 | kvfree(list); |
179 | return r; | 143 | return r; |
144 | |||
145 | } | ||
146 | |||
147 | static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id) | ||
148 | { | ||
149 | struct amdgpu_bo_list *list; | ||
150 | |||
151 | mutex_lock(&fpriv->bo_list_lock); | ||
152 | list = idr_remove(&fpriv->bo_list_handles, id); | ||
153 | mutex_unlock(&fpriv->bo_list_lock); | ||
154 | if (list) | ||
155 | kref_put(&list->refcount, amdgpu_bo_list_free); | ||
180 | } | 156 | } |
181 | 157 | ||
182 | int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, | 158 | 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, | |||
229 | 205 | ||
230 | void amdgpu_bo_list_put(struct amdgpu_bo_list *list) | 206 | void amdgpu_bo_list_put(struct amdgpu_bo_list *list) |
231 | { | 207 | { |
232 | kref_put(&list->refcount, amdgpu_bo_list_release_rcu); | 208 | kref_put(&list->refcount, amdgpu_bo_list_free); |
233 | } | 209 | } |
234 | 210 | ||
235 | int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, | 211 | 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 { | |||
48 | struct amdgpu_bo *oa_obj; | 48 | struct amdgpu_bo *oa_obj; |
49 | unsigned first_userptr; | 49 | unsigned first_userptr; |
50 | unsigned num_entries; | 50 | unsigned num_entries; |
51 | struct amdgpu_bo_list_entry *array; | ||
52 | }; | 51 | }; |
53 | 52 | ||
54 | int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, | 53 | int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, |
@@ -65,14 +64,22 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev, | |||
65 | unsigned num_entries, | 64 | unsigned num_entries, |
66 | struct amdgpu_bo_list **list); | 65 | struct amdgpu_bo_list **list); |
67 | 66 | ||
67 | static inline struct amdgpu_bo_list_entry * | ||
68 | amdgpu_bo_list_array_entry(struct amdgpu_bo_list *list, unsigned index) | ||
69 | { | ||
70 | struct amdgpu_bo_list_entry *array = (void *)&list[1]; | ||
71 | |||
72 | return &array[index]; | ||
73 | } | ||
74 | |||
68 | #define amdgpu_bo_list_for_each_entry(e, list) \ | 75 | #define amdgpu_bo_list_for_each_entry(e, list) \ |
69 | for (e = &(list)->array[0]; \ | 76 | for (e = amdgpu_bo_list_array_entry(list, 0); \ |
70 | e != &(list)->array[(list)->num_entries]; \ | 77 | e != amdgpu_bo_list_array_entry(list, (list)->num_entries); \ |
71 | ++e) | 78 | ++e) |
72 | 79 | ||
73 | #define amdgpu_bo_list_for_each_userptr_entry(e, list) \ | 80 | #define amdgpu_bo_list_for_each_userptr_entry(e, list) \ |
74 | for (e = &(list)->array[(list)->first_userptr]; \ | 81 | for (e = amdgpu_bo_list_array_entry(list, (list)->first_userptr); \ |
75 | e != &(list)->array[(list)->num_entries]; \ | 82 | e != amdgpu_bo_list_array_entry(list, (list)->num_entries); \ |
76 | ++e) | 83 | ++e) |
77 | 84 | ||
78 | #endif | 85 | #endif |