diff options
author | Junwei Zhang <Jerry.Zhang@amd.com> | 2016-11-04 16:16:10 -0400 |
---|---|---|
committer | Sumit Semwal <sumit.semwal@linaro.org> | 2016-11-08 13:58:42 -0500 |
commit | eef18a827a9ec58aa9fc1ccfb7e65ff04ebc25f3 (patch) | |
tree | 49c837bcadf201bcdf4a4002edd9b4dc683de573 | |
parent | 7392b4bb702b05749539ff0936e94976248240c9 (diff) |
drm/amdgpu: add the interface of waiting multiple fences (v4)
v2: agd: rebase and squash in all the previous optimizations and
changes so everything compiles.
v3: squash in Slava's 32bit build fix
v4: rebase on drm-next (fence -> dma_fence),
squash in Monk's ioctl update patch
Signed-off-by: Junwei Zhang <Jerry.Zhang@amd.com>
Reviewed-by: Monk Liu <monk.liu@amd.com>
Reviewed-by: Jammy Zhou <Jammy.Zhou@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
[sumits: fix checkpatch warnings]
Link: http://patchwork.freedesktop.org/patch/msgid/1478290570-30982-2-git-send-email-alexander.deucher@amd.com
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 174 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c | 3 | ||||
-rw-r--r-- | include/uapi/drm/amdgpu_drm.h | 28 |
5 files changed, 207 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 2ec7b3baeec2..c2b8496cdf63 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h | |||
@@ -1212,6 +1212,8 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, | |||
1212 | struct drm_file *filp); | 1212 | struct drm_file *filp); |
1213 | int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); | 1213 | int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); |
1214 | int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); | 1214 | int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); |
1215 | int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data, | ||
1216 | struct drm_file *filp); | ||
1215 | 1217 | ||
1216 | int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data, | 1218 | int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data, |
1217 | struct drm_file *filp); | 1219 | struct drm_file *filp); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index a024217896fd..b4bc83aa5999 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | |||
@@ -1140,6 +1140,180 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, | |||
1140 | } | 1140 | } |
1141 | 1141 | ||
1142 | /** | 1142 | /** |
1143 | * amdgpu_cs_get_fence - helper to get fence from drm_amdgpu_fence | ||
1144 | * | ||
1145 | * @adev: amdgpu device | ||
1146 | * @filp: file private | ||
1147 | * @user: drm_amdgpu_fence copied from user space | ||
1148 | */ | ||
1149 | static struct dma_fence *amdgpu_cs_get_fence(struct amdgpu_device *adev, | ||
1150 | struct drm_file *filp, | ||
1151 | struct drm_amdgpu_fence *user) | ||
1152 | { | ||
1153 | struct amdgpu_ring *ring; | ||
1154 | struct amdgpu_ctx *ctx; | ||
1155 | struct dma_fence *fence; | ||
1156 | int r; | ||
1157 | |||
1158 | r = amdgpu_cs_get_ring(adev, user->ip_type, user->ip_instance, | ||
1159 | user->ring, &ring); | ||
1160 | if (r) | ||
1161 | return ERR_PTR(r); | ||
1162 | |||
1163 | ctx = amdgpu_ctx_get(filp->driver_priv, user->ctx_id); | ||
1164 | if (ctx == NULL) | ||
1165 | return ERR_PTR(-EINVAL); | ||
1166 | |||
1167 | fence = amdgpu_ctx_get_fence(ctx, ring, user->seq_no); | ||
1168 | amdgpu_ctx_put(ctx); | ||
1169 | |||
1170 | return fence; | ||
1171 | } | ||
1172 | |||
1173 | /** | ||
1174 | * amdgpu_cs_wait_all_fence - wait on all fences to signal | ||
1175 | * | ||
1176 | * @adev: amdgpu device | ||
1177 | * @filp: file private | ||
1178 | * @wait: wait parameters | ||
1179 | * @fences: array of drm_amdgpu_fence | ||
1180 | */ | ||
1181 | static int amdgpu_cs_wait_all_fences(struct amdgpu_device *adev, | ||
1182 | struct drm_file *filp, | ||
1183 | union drm_amdgpu_wait_fences *wait, | ||
1184 | struct drm_amdgpu_fence *fences) | ||
1185 | { | ||
1186 | uint32_t fence_count = wait->in.fence_count; | ||
1187 | unsigned int i; | ||
1188 | long r = 1; | ||
1189 | |||
1190 | for (i = 0; i < fence_count; i++) { | ||
1191 | struct dma_fence *fence; | ||
1192 | unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout_ns); | ||
1193 | |||
1194 | fence = amdgpu_cs_get_fence(adev, filp, &fences[i]); | ||
1195 | if (IS_ERR(fence)) | ||
1196 | return PTR_ERR(fence); | ||
1197 | else if (!fence) | ||
1198 | continue; | ||
1199 | |||
1200 | r = dma_fence_wait_timeout(fence, true, timeout); | ||
1201 | if (r < 0) | ||
1202 | return r; | ||
1203 | |||
1204 | if (r == 0) | ||
1205 | break; | ||
1206 | } | ||
1207 | |||
1208 | memset(wait, 0, sizeof(*wait)); | ||
1209 | wait->out.status = (r > 0); | ||
1210 | |||
1211 | return 0; | ||
1212 | } | ||
1213 | |||
1214 | /** | ||
1215 | * amdgpu_cs_wait_any_fence - wait on any fence to signal | ||
1216 | * | ||
1217 | * @adev: amdgpu device | ||
1218 | * @filp: file private | ||
1219 | * @wait: wait parameters | ||
1220 | * @fences: array of drm_amdgpu_fence | ||
1221 | */ | ||
1222 | static int amdgpu_cs_wait_any_fence(struct amdgpu_device *adev, | ||
1223 | struct drm_file *filp, | ||
1224 | union drm_amdgpu_wait_fences *wait, | ||
1225 | struct drm_amdgpu_fence *fences) | ||
1226 | { | ||
1227 | unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout_ns); | ||
1228 | uint32_t fence_count = wait->in.fence_count; | ||
1229 | uint32_t first = ~0; | ||
1230 | struct dma_fence **array; | ||
1231 | unsigned int i; | ||
1232 | long r; | ||
1233 | |||
1234 | /* Prepare the fence array */ | ||
1235 | array = kcalloc(fence_count, sizeof(struct dma_fence *), GFP_KERNEL); | ||
1236 | |||
1237 | if (array == NULL) | ||
1238 | return -ENOMEM; | ||
1239 | |||
1240 | for (i = 0; i < fence_count; i++) { | ||
1241 | struct dma_fence *fence; | ||
1242 | |||
1243 | fence = amdgpu_cs_get_fence(adev, filp, &fences[i]); | ||
1244 | if (IS_ERR(fence)) { | ||
1245 | r = PTR_ERR(fence); | ||
1246 | goto err_free_fence_array; | ||
1247 | } else if (fence) { | ||
1248 | array[i] = fence; | ||
1249 | } else { /* NULL, the fence has been already signaled */ | ||
1250 | r = 1; | ||
1251 | goto out; | ||
1252 | } | ||
1253 | } | ||
1254 | |||
1255 | r = dma_fence_wait_any_timeout(array, fence_count, true, timeout, | ||
1256 | &first); | ||
1257 | if (r < 0) | ||
1258 | goto err_free_fence_array; | ||
1259 | |||
1260 | out: | ||
1261 | memset(wait, 0, sizeof(*wait)); | ||
1262 | wait->out.status = (r > 0); | ||
1263 | wait->out.first_signaled = first; | ||
1264 | /* set return value 0 to indicate success */ | ||
1265 | r = 0; | ||
1266 | |||
1267 | err_free_fence_array: | ||
1268 | for (i = 0; i < fence_count; i++) | ||
1269 | dma_fence_put(array[i]); | ||
1270 | kfree(array); | ||
1271 | |||
1272 | return r; | ||
1273 | } | ||
1274 | |||
1275 | /** | ||
1276 | * amdgpu_cs_wait_fences_ioctl - wait for multiple command submissions to finish | ||
1277 | * | ||
1278 | * @dev: drm device | ||
1279 | * @data: data from userspace | ||
1280 | * @filp: file private | ||
1281 | */ | ||
1282 | int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data, | ||
1283 | struct drm_file *filp) | ||
1284 | { | ||
1285 | struct amdgpu_device *adev = dev->dev_private; | ||
1286 | union drm_amdgpu_wait_fences *wait = data; | ||
1287 | uint32_t fence_count = wait->in.fence_count; | ||
1288 | struct drm_amdgpu_fence *fences_user; | ||
1289 | struct drm_amdgpu_fence *fences; | ||
1290 | int r; | ||
1291 | |||
1292 | /* Get the fences from userspace */ | ||
1293 | fences = kmalloc_array(fence_count, sizeof(struct drm_amdgpu_fence), | ||
1294 | GFP_KERNEL); | ||
1295 | if (fences == NULL) | ||
1296 | return -ENOMEM; | ||
1297 | |||
1298 | fences_user = (void __user *)(unsigned long)(wait->in.fences); | ||
1299 | if (copy_from_user(fences, fences_user, | ||
1300 | sizeof(struct drm_amdgpu_fence) * fence_count)) { | ||
1301 | r = -EFAULT; | ||
1302 | goto err_free_fences; | ||
1303 | } | ||
1304 | |||
1305 | if (wait->in.wait_all) | ||
1306 | r = amdgpu_cs_wait_all_fences(adev, filp, wait, fences); | ||
1307 | else | ||
1308 | r = amdgpu_cs_wait_any_fence(adev, filp, wait, fences); | ||
1309 | |||
1310 | err_free_fences: | ||
1311 | kfree(fences); | ||
1312 | |||
1313 | return r; | ||
1314 | } | ||
1315 | |||
1316 | /** | ||
1143 | * amdgpu_cs_find_bo_va - find bo_va for VM address | 1317 | * amdgpu_cs_find_bo_va - find bo_va for VM address |
1144 | * | 1318 | * |
1145 | * @parser: command submission parser context | 1319 | * @parser: command submission parser context |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 78392671046a..06e145b5afd7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | |||
@@ -825,6 +825,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = { | |||
825 | DRM_IOCTL_DEF_DRV(AMDGPU_CS, amdgpu_cs_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), | 825 | DRM_IOCTL_DEF_DRV(AMDGPU_CS, amdgpu_cs_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), |
826 | DRM_IOCTL_DEF_DRV(AMDGPU_INFO, amdgpu_info_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), | 826 | DRM_IOCTL_DEF_DRV(AMDGPU_INFO, amdgpu_info_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), |
827 | DRM_IOCTL_DEF_DRV(AMDGPU_WAIT_CS, amdgpu_cs_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), | 827 | DRM_IOCTL_DEF_DRV(AMDGPU_WAIT_CS, amdgpu_cs_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), |
828 | DRM_IOCTL_DEF_DRV(AMDGPU_WAIT_FENCES, amdgpu_cs_wait_fences_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), | ||
828 | DRM_IOCTL_DEF_DRV(AMDGPU_GEM_METADATA, amdgpu_gem_metadata_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), | 829 | DRM_IOCTL_DEF_DRV(AMDGPU_GEM_METADATA, amdgpu_gem_metadata_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), |
829 | DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), | 830 | DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), |
830 | DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), | 831 | DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c index fd26c4b8d793..34a795463988 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c | |||
@@ -361,7 +361,8 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, | |||
361 | if (count) { | 361 | if (count) { |
362 | spin_unlock(&sa_manager->wq.lock); | 362 | spin_unlock(&sa_manager->wq.lock); |
363 | t = dma_fence_wait_any_timeout(fences, count, false, | 363 | t = dma_fence_wait_any_timeout(fences, count, false, |
364 | MAX_SCHEDULE_TIMEOUT); | 364 | MAX_SCHEDULE_TIMEOUT, |
365 | NULL); | ||
365 | for (i = 0; i < count; ++i) | 366 | for (i = 0; i < count; ++i) |
366 | dma_fence_put(fences[i]); | 367 | dma_fence_put(fences[i]); |
367 | 368 | ||
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 4684f378f046..2191a9e4f3db 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h | |||
@@ -50,6 +50,7 @@ extern "C" { | |||
50 | #define DRM_AMDGPU_WAIT_CS 0x09 | 50 | #define DRM_AMDGPU_WAIT_CS 0x09 |
51 | #define DRM_AMDGPU_GEM_OP 0x10 | 51 | #define DRM_AMDGPU_GEM_OP 0x10 |
52 | #define DRM_AMDGPU_GEM_USERPTR 0x11 | 52 | #define DRM_AMDGPU_GEM_USERPTR 0x11 |
53 | #define DRM_AMDGPU_WAIT_FENCES 0x12 | ||
53 | 54 | ||
54 | #define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create) | 55 | #define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create) |
55 | #define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap) | 56 | #define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap) |
@@ -63,6 +64,7 @@ extern "C" { | |||
63 | #define DRM_IOCTL_AMDGPU_WAIT_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_CS, union drm_amdgpu_wait_cs) | 64 | #define DRM_IOCTL_AMDGPU_WAIT_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_CS, union drm_amdgpu_wait_cs) |
64 | #define DRM_IOCTL_AMDGPU_GEM_OP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_OP, struct drm_amdgpu_gem_op) | 65 | #define DRM_IOCTL_AMDGPU_GEM_OP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_OP, struct drm_amdgpu_gem_op) |
65 | #define DRM_IOCTL_AMDGPU_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr) | 66 | #define DRM_IOCTL_AMDGPU_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr) |
67 | #define DRM_IOCTL_AMDGPU_WAIT_FENCES DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_FENCES, union drm_amdgpu_wait_fences) | ||
66 | 68 | ||
67 | #define AMDGPU_GEM_DOMAIN_CPU 0x1 | 69 | #define AMDGPU_GEM_DOMAIN_CPU 0x1 |
68 | #define AMDGPU_GEM_DOMAIN_GTT 0x2 | 70 | #define AMDGPU_GEM_DOMAIN_GTT 0x2 |
@@ -307,6 +309,32 @@ union drm_amdgpu_wait_cs { | |||
307 | struct drm_amdgpu_wait_cs_out out; | 309 | struct drm_amdgpu_wait_cs_out out; |
308 | }; | 310 | }; |
309 | 311 | ||
312 | struct drm_amdgpu_fence { | ||
313 | __u32 ctx_id; | ||
314 | __u32 ip_type; | ||
315 | __u32 ip_instance; | ||
316 | __u32 ring; | ||
317 | __u64 seq_no; | ||
318 | }; | ||
319 | |||
320 | struct drm_amdgpu_wait_fences_in { | ||
321 | /** This points to uint64_t * which points to fences */ | ||
322 | __u64 fences; | ||
323 | __u32 fence_count; | ||
324 | __u32 wait_all; | ||
325 | __u64 timeout_ns; | ||
326 | }; | ||
327 | |||
328 | struct drm_amdgpu_wait_fences_out { | ||
329 | __u32 status; | ||
330 | __u32 first_signaled; | ||
331 | }; | ||
332 | |||
333 | union drm_amdgpu_wait_fences { | ||
334 | struct drm_amdgpu_wait_fences_in in; | ||
335 | struct drm_amdgpu_wait_fences_out out; | ||
336 | }; | ||
337 | |||
310 | #define AMDGPU_GEM_OP_GET_GEM_CREATE_INFO 0 | 338 | #define AMDGPU_GEM_OP_GET_GEM_CREATE_INFO 0 |
311 | #define AMDGPU_GEM_OP_SET_PLACEMENT 1 | 339 | #define AMDGPU_GEM_OP_SET_PLACEMENT 1 |
312 | 340 | ||