diff options
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 315 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/cikd.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_kfd.c | 11 | ||||
-rw-r--r-- | include/uapi/linux/kfd_ioctl.h | 37 |
8 files changed, 235 insertions, 167 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index fe5c543599b0..fcfdf23e1913 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | |||
@@ -126,17 +126,14 @@ static int kfd_open(struct inode *inode, struct file *filep) | |||
126 | return 0; | 126 | return 0; |
127 | } | 127 | } |
128 | 128 | ||
129 | static long kfd_ioctl_get_version(struct file *filep, struct kfd_process *p, | 129 | static int kfd_ioctl_get_version(struct file *filep, struct kfd_process *p, |
130 | void __user *arg) | 130 | void *data) |
131 | { | 131 | { |
132 | struct kfd_ioctl_get_version_args args; | 132 | struct kfd_ioctl_get_version_args *args = data; |
133 | int err = 0; | 133 | int err = 0; |
134 | 134 | ||
135 | args.major_version = KFD_IOCTL_MAJOR_VERSION; | 135 | args->major_version = KFD_IOCTL_MAJOR_VERSION; |
136 | args.minor_version = KFD_IOCTL_MINOR_VERSION; | 136 | args->minor_version = KFD_IOCTL_MINOR_VERSION; |
137 | |||
138 | if (copy_to_user(arg, &args, sizeof(args))) | ||
139 | err = -EFAULT; | ||
140 | 137 | ||
141 | return err; | 138 | return err; |
142 | } | 139 | } |
@@ -220,10 +217,10 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties, | |||
220 | return 0; | 217 | return 0; |
221 | } | 218 | } |
222 | 219 | ||
223 | static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, | 220 | static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, |
224 | void __user *arg) | 221 | void *data) |
225 | { | 222 | { |
226 | struct kfd_ioctl_create_queue_args args; | 223 | struct kfd_ioctl_create_queue_args *args = data; |
227 | struct kfd_dev *dev; | 224 | struct kfd_dev *dev; |
228 | int err = 0; | 225 | int err = 0; |
229 | unsigned int queue_id; | 226 | unsigned int queue_id; |
@@ -232,16 +229,13 @@ static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, | |||
232 | 229 | ||
233 | memset(&q_properties, 0, sizeof(struct queue_properties)); | 230 | memset(&q_properties, 0, sizeof(struct queue_properties)); |
234 | 231 | ||
235 | if (copy_from_user(&args, arg, sizeof(args))) | ||
236 | return -EFAULT; | ||
237 | |||
238 | pr_debug("kfd: creating queue ioctl\n"); | 232 | pr_debug("kfd: creating queue ioctl\n"); |
239 | 233 | ||
240 | err = set_queue_properties_from_user(&q_properties, &args); | 234 | err = set_queue_properties_from_user(&q_properties, args); |
241 | if (err) | 235 | if (err) |
242 | return err; | 236 | return err; |
243 | 237 | ||
244 | dev = kfd_device_by_id(args.gpu_id); | 238 | dev = kfd_device_by_id(args->gpu_id); |
245 | if (dev == NULL) | 239 | if (dev == NULL) |
246 | return -EINVAL; | 240 | return -EINVAL; |
247 | 241 | ||
@@ -249,7 +243,7 @@ static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, | |||
249 | 243 | ||
250 | pdd = kfd_bind_process_to_device(dev, p); | 244 | pdd = kfd_bind_process_to_device(dev, p); |
251 | if (IS_ERR(pdd)) { | 245 | if (IS_ERR(pdd)) { |
252 | err = PTR_ERR(pdd); | 246 | err = -ESRCH; |
253 | goto err_bind_process; | 247 | goto err_bind_process; |
254 | } | 248 | } |
255 | 249 | ||
@@ -262,33 +256,26 @@ static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, | |||
262 | if (err != 0) | 256 | if (err != 0) |
263 | goto err_create_queue; | 257 | goto err_create_queue; |
264 | 258 | ||
265 | args.queue_id = queue_id; | 259 | args->queue_id = queue_id; |
266 | 260 | ||
267 | /* Return gpu_id as doorbell offset for mmap usage */ | 261 | /* Return gpu_id as doorbell offset for mmap usage */ |
268 | args.doorbell_offset = args.gpu_id << PAGE_SHIFT; | 262 | args->doorbell_offset = args->gpu_id << PAGE_SHIFT; |
269 | |||
270 | if (copy_to_user(arg, &args, sizeof(args))) { | ||
271 | err = -EFAULT; | ||
272 | goto err_copy_args_out; | ||
273 | } | ||
274 | 263 | ||
275 | mutex_unlock(&p->mutex); | 264 | mutex_unlock(&p->mutex); |
276 | 265 | ||
277 | pr_debug("kfd: queue id %d was created successfully\n", args.queue_id); | 266 | pr_debug("kfd: queue id %d was created successfully\n", args->queue_id); |
278 | 267 | ||
279 | pr_debug("ring buffer address == 0x%016llX\n", | 268 | pr_debug("ring buffer address == 0x%016llX\n", |
280 | args.ring_base_address); | 269 | args->ring_base_address); |
281 | 270 | ||
282 | pr_debug("read ptr address == 0x%016llX\n", | 271 | pr_debug("read ptr address == 0x%016llX\n", |
283 | args.read_pointer_address); | 272 | args->read_pointer_address); |
284 | 273 | ||
285 | pr_debug("write ptr address == 0x%016llX\n", | 274 | pr_debug("write ptr address == 0x%016llX\n", |
286 | args.write_pointer_address); | 275 | args->write_pointer_address); |
287 | 276 | ||
288 | return 0; | 277 | return 0; |
289 | 278 | ||
290 | err_copy_args_out: | ||
291 | pqm_destroy_queue(&p->pqm, queue_id); | ||
292 | err_create_queue: | 279 | err_create_queue: |
293 | err_bind_process: | 280 | err_bind_process: |
294 | mutex_unlock(&p->mutex); | 281 | mutex_unlock(&p->mutex); |
@@ -296,99 +283,90 @@ err_bind_process: | |||
296 | } | 283 | } |
297 | 284 | ||
298 | static int kfd_ioctl_destroy_queue(struct file *filp, struct kfd_process *p, | 285 | static int kfd_ioctl_destroy_queue(struct file *filp, struct kfd_process *p, |
299 | void __user *arg) | 286 | void *data) |
300 | { | 287 | { |
301 | int retval; | 288 | int retval; |
302 | struct kfd_ioctl_destroy_queue_args args; | 289 | struct kfd_ioctl_destroy_queue_args *args = data; |
303 | |||
304 | if (copy_from_user(&args, arg, sizeof(args))) | ||
305 | return -EFAULT; | ||
306 | 290 | ||
307 | pr_debug("kfd: destroying queue id %d for PASID %d\n", | 291 | pr_debug("kfd: destroying queue id %d for PASID %d\n", |
308 | args.queue_id, | 292 | args->queue_id, |
309 | p->pasid); | 293 | p->pasid); |
310 | 294 | ||
311 | mutex_lock(&p->mutex); | 295 | mutex_lock(&p->mutex); |
312 | 296 | ||
313 | retval = pqm_destroy_queue(&p->pqm, args.queue_id); | 297 | retval = pqm_destroy_queue(&p->pqm, args->queue_id); |
314 | 298 | ||
315 | mutex_unlock(&p->mutex); | 299 | mutex_unlock(&p->mutex); |
316 | return retval; | 300 | return retval; |
317 | } | 301 | } |
318 | 302 | ||
319 | static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p, | 303 | static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p, |
320 | void __user *arg) | 304 | void *data) |
321 | { | 305 | { |
322 | int retval; | 306 | int retval; |
323 | struct kfd_ioctl_update_queue_args args; | 307 | struct kfd_ioctl_update_queue_args *args = data; |
324 | struct queue_properties properties; | 308 | struct queue_properties properties; |
325 | 309 | ||
326 | if (copy_from_user(&args, arg, sizeof(args))) | 310 | if (args->queue_percentage > KFD_MAX_QUEUE_PERCENTAGE) { |
327 | return -EFAULT; | ||
328 | |||
329 | if (args.queue_percentage > KFD_MAX_QUEUE_PERCENTAGE) { | ||
330 | pr_err("kfd: queue percentage must be between 0 to KFD_MAX_QUEUE_PERCENTAGE\n"); | 311 | pr_err("kfd: queue percentage must be between 0 to KFD_MAX_QUEUE_PERCENTAGE\n"); |
331 | return -EINVAL; | 312 | return -EINVAL; |
332 | } | 313 | } |
333 | 314 | ||
334 | if (args.queue_priority > KFD_MAX_QUEUE_PRIORITY) { | 315 | if (args->queue_priority > KFD_MAX_QUEUE_PRIORITY) { |
335 | pr_err("kfd: queue priority must be between 0 to KFD_MAX_QUEUE_PRIORITY\n"); | 316 | pr_err("kfd: queue priority must be between 0 to KFD_MAX_QUEUE_PRIORITY\n"); |
336 | return -EINVAL; | 317 | return -EINVAL; |
337 | } | 318 | } |
338 | 319 | ||
339 | if ((args.ring_base_address) && | 320 | if ((args->ring_base_address) && |
340 | (!access_ok(VERIFY_WRITE, | 321 | (!access_ok(VERIFY_WRITE, |
341 | (const void __user *) args.ring_base_address, | 322 | (const void __user *) args->ring_base_address, |
342 | sizeof(uint64_t)))) { | 323 | sizeof(uint64_t)))) { |
343 | pr_err("kfd: can't access ring base address\n"); | 324 | pr_err("kfd: can't access ring base address\n"); |
344 | return -EFAULT; | 325 | return -EFAULT; |
345 | } | 326 | } |
346 | 327 | ||
347 | if (!is_power_of_2(args.ring_size) && (args.ring_size != 0)) { | 328 | if (!is_power_of_2(args->ring_size) && (args->ring_size != 0)) { |
348 | pr_err("kfd: ring size must be a power of 2 or 0\n"); | 329 | pr_err("kfd: ring size must be a power of 2 or 0\n"); |
349 | return -EINVAL; | 330 | return -EINVAL; |
350 | } | 331 | } |
351 | 332 | ||
352 | properties.queue_address = args.ring_base_address; | 333 | properties.queue_address = args->ring_base_address; |
353 | properties.queue_size = args.ring_size; | 334 | properties.queue_size = args->ring_size; |
354 | properties.queue_percent = args.queue_percentage; | 335 | properties.queue_percent = args->queue_percentage; |
355 | properties.priority = args.queue_priority; | 336 | properties.priority = args->queue_priority; |
356 | 337 | ||
357 | pr_debug("kfd: updating queue id %d for PASID %d\n", | 338 | pr_debug("kfd: updating queue id %d for PASID %d\n", |
358 | args.queue_id, p->pasid); | 339 | args->queue_id, p->pasid); |
359 | 340 | ||
360 | mutex_lock(&p->mutex); | 341 | mutex_lock(&p->mutex); |
361 | 342 | ||
362 | retval = pqm_update_queue(&p->pqm, args.queue_id, &properties); | 343 | retval = pqm_update_queue(&p->pqm, args->queue_id, &properties); |
363 | 344 | ||
364 | mutex_unlock(&p->mutex); | 345 | mutex_unlock(&p->mutex); |
365 | 346 | ||
366 | return retval; | 347 | return retval; |
367 | } | 348 | } |
368 | 349 | ||
369 | static long kfd_ioctl_set_memory_policy(struct file *filep, | 350 | static int kfd_ioctl_set_memory_policy(struct file *filep, |
370 | struct kfd_process *p, void __user *arg) | 351 | struct kfd_process *p, void *data) |
371 | { | 352 | { |
372 | struct kfd_ioctl_set_memory_policy_args args; | 353 | struct kfd_ioctl_set_memory_policy_args *args = data; |
373 | struct kfd_dev *dev; | 354 | struct kfd_dev *dev; |
374 | int err = 0; | 355 | int err = 0; |
375 | struct kfd_process_device *pdd; | 356 | struct kfd_process_device *pdd; |
376 | enum cache_policy default_policy, alternate_policy; | 357 | enum cache_policy default_policy, alternate_policy; |
377 | 358 | ||
378 | if (copy_from_user(&args, arg, sizeof(args))) | 359 | if (args->default_policy != KFD_IOC_CACHE_POLICY_COHERENT |
379 | return -EFAULT; | 360 | && args->default_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { |
380 | |||
381 | if (args.default_policy != KFD_IOC_CACHE_POLICY_COHERENT | ||
382 | && args.default_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { | ||
383 | return -EINVAL; | 361 | return -EINVAL; |
384 | } | 362 | } |
385 | 363 | ||
386 | if (args.alternate_policy != KFD_IOC_CACHE_POLICY_COHERENT | 364 | if (args->alternate_policy != KFD_IOC_CACHE_POLICY_COHERENT |
387 | && args.alternate_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { | 365 | && args->alternate_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { |
388 | return -EINVAL; | 366 | return -EINVAL; |
389 | } | 367 | } |
390 | 368 | ||
391 | dev = kfd_device_by_id(args.gpu_id); | 369 | dev = kfd_device_by_id(args->gpu_id); |
392 | if (dev == NULL) | 370 | if (dev == NULL) |
393 | return -EINVAL; | 371 | return -EINVAL; |
394 | 372 | ||
@@ -396,23 +374,23 @@ static long kfd_ioctl_set_memory_policy(struct file *filep, | |||
396 | 374 | ||
397 | pdd = kfd_bind_process_to_device(dev, p); | 375 | pdd = kfd_bind_process_to_device(dev, p); |
398 | if (IS_ERR(pdd)) { | 376 | if (IS_ERR(pdd)) { |
399 | err = PTR_ERR(pdd); | 377 | err = -ESRCH; |
400 | goto out; | 378 | goto out; |
401 | } | 379 | } |
402 | 380 | ||
403 | default_policy = (args.default_policy == KFD_IOC_CACHE_POLICY_COHERENT) | 381 | default_policy = (args->default_policy == KFD_IOC_CACHE_POLICY_COHERENT) |
404 | ? cache_policy_coherent : cache_policy_noncoherent; | 382 | ? cache_policy_coherent : cache_policy_noncoherent; |
405 | 383 | ||
406 | alternate_policy = | 384 | alternate_policy = |
407 | (args.alternate_policy == KFD_IOC_CACHE_POLICY_COHERENT) | 385 | (args->alternate_policy == KFD_IOC_CACHE_POLICY_COHERENT) |
408 | ? cache_policy_coherent : cache_policy_noncoherent; | 386 | ? cache_policy_coherent : cache_policy_noncoherent; |
409 | 387 | ||
410 | if (!dev->dqm->set_cache_memory_policy(dev->dqm, | 388 | if (!dev->dqm->set_cache_memory_policy(dev->dqm, |
411 | &pdd->qpd, | 389 | &pdd->qpd, |
412 | default_policy, | 390 | default_policy, |
413 | alternate_policy, | 391 | alternate_policy, |
414 | (void __user *)args.alternate_aperture_base, | 392 | (void __user *)args->alternate_aperture_base, |
415 | args.alternate_aperture_size)) | 393 | args->alternate_aperture_size)) |
416 | err = -EINVAL; | 394 | err = -EINVAL; |
417 | 395 | ||
418 | out: | 396 | out: |
@@ -421,53 +399,44 @@ out: | |||
421 | return err; | 399 | return err; |
422 | } | 400 | } |
423 | 401 | ||
424 | static long kfd_ioctl_get_clock_counters(struct file *filep, | 402 | static int kfd_ioctl_get_clock_counters(struct file *filep, |
425 | struct kfd_process *p, void __user *arg) | 403 | struct kfd_process *p, void *data) |
426 | { | 404 | { |
427 | struct kfd_ioctl_get_clock_counters_args args; | 405 | struct kfd_ioctl_get_clock_counters_args *args = data; |
428 | struct kfd_dev *dev; | 406 | struct kfd_dev *dev; |
429 | struct timespec time; | 407 | struct timespec time; |
430 | 408 | ||
431 | if (copy_from_user(&args, arg, sizeof(args))) | 409 | dev = kfd_device_by_id(args->gpu_id); |
432 | return -EFAULT; | ||
433 | |||
434 | dev = kfd_device_by_id(args.gpu_id); | ||
435 | if (dev == NULL) | 410 | if (dev == NULL) |
436 | return -EINVAL; | 411 | return -EINVAL; |
437 | 412 | ||
438 | /* Reading GPU clock counter from KGD */ | 413 | /* Reading GPU clock counter from KGD */ |
439 | args.gpu_clock_counter = kfd2kgd->get_gpu_clock_counter(dev->kgd); | 414 | args->gpu_clock_counter = kfd2kgd->get_gpu_clock_counter(dev->kgd); |
440 | 415 | ||
441 | /* No access to rdtsc. Using raw monotonic time */ | 416 | /* No access to rdtsc. Using raw monotonic time */ |
442 | getrawmonotonic(&time); | 417 | getrawmonotonic(&time); |
443 | args.cpu_clock_counter = (uint64_t)timespec_to_ns(&time); | 418 | args->cpu_clock_counter = (uint64_t)timespec_to_ns(&time); |
444 | 419 | ||
445 | get_monotonic_boottime(&time); | 420 | get_monotonic_boottime(&time); |
446 | args.system_clock_counter = (uint64_t)timespec_to_ns(&time); | 421 | args->system_clock_counter = (uint64_t)timespec_to_ns(&time); |
447 | 422 | ||
448 | /* Since the counter is in nano-seconds we use 1GHz frequency */ | 423 | /* Since the counter is in nano-seconds we use 1GHz frequency */ |
449 | args.system_clock_freq = 1000000000; | 424 | args->system_clock_freq = 1000000000; |
450 | |||
451 | if (copy_to_user(arg, &args, sizeof(args))) | ||
452 | return -EFAULT; | ||
453 | 425 | ||
454 | return 0; | 426 | return 0; |
455 | } | 427 | } |
456 | 428 | ||
457 | 429 | ||
458 | static int kfd_ioctl_get_process_apertures(struct file *filp, | 430 | static int kfd_ioctl_get_process_apertures(struct file *filp, |
459 | struct kfd_process *p, void __user *arg) | 431 | struct kfd_process *p, void *data) |
460 | { | 432 | { |
461 | struct kfd_ioctl_get_process_apertures_args args; | 433 | struct kfd_ioctl_get_process_apertures_args *args = data; |
462 | struct kfd_process_device_apertures *pAperture; | 434 | struct kfd_process_device_apertures *pAperture; |
463 | struct kfd_process_device *pdd; | 435 | struct kfd_process_device *pdd; |
464 | 436 | ||
465 | dev_dbg(kfd_device, "get apertures for PASID %d", p->pasid); | 437 | dev_dbg(kfd_device, "get apertures for PASID %d", p->pasid); |
466 | 438 | ||
467 | if (copy_from_user(&args, arg, sizeof(args))) | 439 | args->num_of_nodes = 0; |
468 | return -EFAULT; | ||
469 | |||
470 | args.num_of_nodes = 0; | ||
471 | 440 | ||
472 | mutex_lock(&p->mutex); | 441 | mutex_lock(&p->mutex); |
473 | 442 | ||
@@ -476,7 +445,8 @@ static int kfd_ioctl_get_process_apertures(struct file *filp, | |||
476 | /* Run over all pdd of the process */ | 445 | /* Run over all pdd of the process */ |
477 | pdd = kfd_get_first_process_device_data(p); | 446 | pdd = kfd_get_first_process_device_data(p); |
478 | do { | 447 | do { |
479 | pAperture = &args.process_apertures[args.num_of_nodes]; | 448 | pAperture = |
449 | &args->process_apertures[args->num_of_nodes]; | ||
480 | pAperture->gpu_id = pdd->dev->id; | 450 | pAperture->gpu_id = pdd->dev->id; |
481 | pAperture->lds_base = pdd->lds_base; | 451 | pAperture->lds_base = pdd->lds_base; |
482 | pAperture->lds_limit = pdd->lds_limit; | 452 | pAperture->lds_limit = pdd->lds_limit; |
@@ -486,7 +456,7 @@ static int kfd_ioctl_get_process_apertures(struct file *filp, | |||
486 | pAperture->scratch_limit = pdd->scratch_limit; | 456 | pAperture->scratch_limit = pdd->scratch_limit; |
487 | 457 | ||
488 | dev_dbg(kfd_device, | 458 | dev_dbg(kfd_device, |
489 | "node id %u\n", args.num_of_nodes); | 459 | "node id %u\n", args->num_of_nodes); |
490 | dev_dbg(kfd_device, | 460 | dev_dbg(kfd_device, |
491 | "gpu id %u\n", pdd->dev->id); | 461 | "gpu id %u\n", pdd->dev->id); |
492 | dev_dbg(kfd_device, | 462 | dev_dbg(kfd_device, |
@@ -502,80 +472,131 @@ static int kfd_ioctl_get_process_apertures(struct file *filp, | |||
502 | dev_dbg(kfd_device, | 472 | dev_dbg(kfd_device, |
503 | "scratch_limit %llX\n", pdd->scratch_limit); | 473 | "scratch_limit %llX\n", pdd->scratch_limit); |
504 | 474 | ||
505 | args.num_of_nodes++; | 475 | args->num_of_nodes++; |
506 | } while ((pdd = kfd_get_next_process_device_data(p, pdd)) != NULL && | 476 | } while ((pdd = kfd_get_next_process_device_data(p, pdd)) != NULL && |
507 | (args.num_of_nodes < NUM_OF_SUPPORTED_GPUS)); | 477 | (args->num_of_nodes < NUM_OF_SUPPORTED_GPUS)); |
508 | } | 478 | } |
509 | 479 | ||
510 | mutex_unlock(&p->mutex); | 480 | mutex_unlock(&p->mutex); |
511 | 481 | ||
512 | if (copy_to_user(arg, &args, sizeof(args))) | ||
513 | return -EFAULT; | ||
514 | |||
515 | return 0; | 482 | return 0; |
516 | } | 483 | } |
517 | 484 | ||
485 | #define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \ | ||
486 | [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl} | ||
487 | |||
488 | /** Ioctl table */ | ||
489 | static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { | ||
490 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_VERSION, | ||
491 | kfd_ioctl_get_version, 0), | ||
492 | |||
493 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_CREATE_QUEUE, | ||
494 | kfd_ioctl_create_queue, 0), | ||
495 | |||
496 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_DESTROY_QUEUE, | ||
497 | kfd_ioctl_destroy_queue, 0), | ||
498 | |||
499 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_MEMORY_POLICY, | ||
500 | kfd_ioctl_set_memory_policy, 0), | ||
501 | |||
502 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_CLOCK_COUNTERS, | ||
503 | kfd_ioctl_get_clock_counters, 0), | ||
504 | |||
505 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_PROCESS_APERTURES, | ||
506 | kfd_ioctl_get_process_apertures, 0), | ||
507 | |||
508 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_UPDATE_QUEUE, | ||
509 | kfd_ioctl_update_queue, 0), | ||
510 | }; | ||
511 | |||
512 | #define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls) | ||
513 | |||
518 | static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) | 514 | static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) |
519 | { | 515 | { |
520 | struct kfd_process *process; | 516 | struct kfd_process *process; |
521 | long err = -EINVAL; | 517 | amdkfd_ioctl_t *func; |
518 | const struct amdkfd_ioctl_desc *ioctl = NULL; | ||
519 | unsigned int nr = _IOC_NR(cmd); | ||
520 | char stack_kdata[128]; | ||
521 | char *kdata = NULL; | ||
522 | unsigned int usize, asize; | ||
523 | int retcode = -EINVAL; | ||
522 | 524 | ||
523 | dev_dbg(kfd_device, | 525 | if (nr >= AMDKFD_CORE_IOCTL_COUNT) |
524 | "ioctl cmd 0x%x (#%d), arg 0x%lx\n", | 526 | goto err_i1; |
525 | cmd, _IOC_NR(cmd), arg); | 527 | |
528 | if ((nr >= AMDKFD_COMMAND_START) && (nr < AMDKFD_COMMAND_END)) { | ||
529 | u32 amdkfd_size; | ||
530 | |||
531 | ioctl = &amdkfd_ioctls[nr]; | ||
532 | |||
533 | amdkfd_size = _IOC_SIZE(ioctl->cmd); | ||
534 | usize = asize = _IOC_SIZE(cmd); | ||
535 | if (amdkfd_size > asize) | ||
536 | asize = amdkfd_size; | ||
537 | |||
538 | cmd = ioctl->cmd; | ||
539 | } else | ||
540 | goto err_i1; | ||
541 | |||
542 | dev_dbg(kfd_device, "ioctl cmd 0x%x (#%d), arg 0x%lx\n", cmd, nr, arg); | ||
526 | 543 | ||
527 | process = kfd_get_process(current); | 544 | process = kfd_get_process(current); |
528 | if (IS_ERR(process)) | 545 | if (IS_ERR(process)) { |
529 | return PTR_ERR(process); | 546 | dev_dbg(kfd_device, "no process\n"); |
547 | goto err_i1; | ||
548 | } | ||
530 | 549 | ||
531 | switch (cmd) { | 550 | /* Do not trust userspace, use our own definition */ |
532 | case KFD_IOC_GET_VERSION: | 551 | func = ioctl->func; |
533 | err = kfd_ioctl_get_version(filep, process, (void __user *)arg); | 552 | |
534 | break; | 553 | if (unlikely(!func)) { |
535 | case KFD_IOC_CREATE_QUEUE: | 554 | dev_dbg(kfd_device, "no function\n"); |
536 | err = kfd_ioctl_create_queue(filep, process, | 555 | retcode = -EINVAL; |
537 | (void __user *)arg); | 556 | goto err_i1; |
538 | break; | ||
539 | |||
540 | case KFD_IOC_DESTROY_QUEUE: | ||
541 | err = kfd_ioctl_destroy_queue(filep, process, | ||
542 | (void __user *)arg); | ||
543 | break; | ||
544 | |||
545 | case KFD_IOC_SET_MEMORY_POLICY: | ||
546 | err = kfd_ioctl_set_memory_policy(filep, process, | ||
547 | (void __user *)arg); | ||
548 | break; | ||
549 | |||
550 | case KFD_IOC_GET_CLOCK_COUNTERS: | ||
551 | err = kfd_ioctl_get_clock_counters(filep, process, | ||
552 | (void __user *)arg); | ||
553 | break; | ||
554 | |||
555 | case KFD_IOC_GET_PROCESS_APERTURES: | ||
556 | err = kfd_ioctl_get_process_apertures(filep, process, | ||
557 | (void __user *)arg); | ||
558 | break; | ||
559 | |||
560 | case KFD_IOC_UPDATE_QUEUE: | ||
561 | err = kfd_ioctl_update_queue(filep, process, | ||
562 | (void __user *)arg); | ||
563 | break; | ||
564 | |||
565 | default: | ||
566 | dev_err(kfd_device, | ||
567 | "unknown ioctl cmd 0x%x, arg 0x%lx)\n", | ||
568 | cmd, arg); | ||
569 | err = -EINVAL; | ||
570 | break; | ||
571 | } | 557 | } |
572 | 558 | ||
573 | if (err < 0) | 559 | if (cmd & (IOC_IN | IOC_OUT)) { |
574 | dev_err(kfd_device, | 560 | if (asize <= sizeof(stack_kdata)) { |
575 | "ioctl error %ld for ioctl cmd 0x%x (#%d)\n", | 561 | kdata = stack_kdata; |
576 | err, cmd, _IOC_NR(cmd)); | 562 | } else { |
563 | kdata = kmalloc(asize, GFP_KERNEL); | ||
564 | if (!kdata) { | ||
565 | retcode = -ENOMEM; | ||
566 | goto err_i1; | ||
567 | } | ||
568 | } | ||
569 | if (asize > usize) | ||
570 | memset(kdata + usize, 0, asize - usize); | ||
571 | } | ||
577 | 572 | ||
578 | return err; | 573 | if (cmd & IOC_IN) { |
574 | if (copy_from_user(kdata, (void __user *)arg, usize) != 0) { | ||
575 | retcode = -EFAULT; | ||
576 | goto err_i1; | ||
577 | } | ||
578 | } else if (cmd & IOC_OUT) { | ||
579 | memset(kdata, 0, usize); | ||
580 | } | ||
581 | |||
582 | retcode = func(filep, process, kdata); | ||
583 | |||
584 | if (cmd & IOC_OUT) | ||
585 | if (copy_to_user((void __user *)arg, kdata, usize) != 0) | ||
586 | retcode = -EFAULT; | ||
587 | |||
588 | err_i1: | ||
589 | if (!ioctl) | ||
590 | dev_dbg(kfd_device, "invalid ioctl: pid=%d, cmd=0x%02x, nr=0x%02x\n", | ||
591 | task_pid_nr(current), cmd, nr); | ||
592 | |||
593 | if (kdata != stack_kdata) | ||
594 | kfree(kdata); | ||
595 | |||
596 | if (retcode) | ||
597 | dev_dbg(kfd_device, "ret = %d\n", retcode); | ||
598 | |||
599 | return retcode; | ||
579 | } | 600 | } |
580 | 601 | ||
581 | static int kfd_mmap(struct file *filp, struct vm_area_struct *vma) | 602 | static int kfd_mmap(struct file *filp, struct vm_area_struct *vma) |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index f44d6737b65a..9c8961d22360 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | |||
@@ -161,6 +161,9 @@ static void deallocate_vmid(struct device_queue_manager *dqm, | |||
161 | { | 161 | { |
162 | int bit = qpd->vmid - KFD_VMID_START_OFFSET; | 162 | int bit = qpd->vmid - KFD_VMID_START_OFFSET; |
163 | 163 | ||
164 | /* Release the vmid mapping */ | ||
165 | set_pasid_vmid_mapping(dqm, 0, qpd->vmid); | ||
166 | |||
164 | set_bit(bit, (unsigned long *)&dqm->vmid_bitmap); | 167 | set_bit(bit, (unsigned long *)&dqm->vmid_bitmap); |
165 | qpd->vmid = 0; | 168 | qpd->vmid = 0; |
166 | q->properties.vmid = 0; | 169 | q->properties.vmid = 0; |
@@ -272,6 +275,18 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm, | |||
272 | return retval; | 275 | return retval; |
273 | } | 276 | } |
274 | 277 | ||
278 | pr_debug("kfd: loading mqd to hqd on pipe (%d) queue (%d)\n", | ||
279 | q->pipe, | ||
280 | q->queue); | ||
281 | |||
282 | retval = mqd->load_mqd(mqd, q->mqd, q->pipe, | ||
283 | q->queue, q->properties.write_ptr); | ||
284 | if (retval != 0) { | ||
285 | deallocate_hqd(dqm, q); | ||
286 | mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj); | ||
287 | return retval; | ||
288 | } | ||
289 | |||
275 | return 0; | 290 | return 0; |
276 | } | 291 | } |
277 | 292 | ||
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c index adc31474e786..4c3828cf45bf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c | |||
@@ -184,7 +184,7 @@ static bool is_occupied(struct mqd_manager *mm, void *mqd, | |||
184 | uint32_t queue_id) | 184 | uint32_t queue_id) |
185 | { | 185 | { |
186 | 186 | ||
187 | return kfd2kgd->hqd_is_occupies(mm->dev->kgd, queue_address, | 187 | return kfd2kgd->hqd_is_occupied(mm->dev->kgd, queue_address, |
188 | pipe_id, queue_id); | 188 | pipe_id, queue_id); |
189 | 189 | ||
190 | } | 190 | } |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index f9fb81e3bb09..a5edb29507e3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h | |||
@@ -463,6 +463,24 @@ struct kfd_process { | |||
463 | bool is_32bit_user_mode; | 463 | bool is_32bit_user_mode; |
464 | }; | 464 | }; |
465 | 465 | ||
466 | /** | ||
467 | * Ioctl function type. | ||
468 | * | ||
469 | * \param filep pointer to file structure. | ||
470 | * \param p amdkfd process pointer. | ||
471 | * \param data pointer to arg that was copied from user. | ||
472 | */ | ||
473 | typedef int amdkfd_ioctl_t(struct file *filep, struct kfd_process *p, | ||
474 | void *data); | ||
475 | |||
476 | struct amdkfd_ioctl_desc { | ||
477 | unsigned int cmd; | ||
478 | int flags; | ||
479 | amdkfd_ioctl_t *func; | ||
480 | unsigned int cmd_drv; | ||
481 | const char *name; | ||
482 | }; | ||
483 | |||
466 | void kfd_process_create_wq(void); | 484 | void kfd_process_create_wq(void); |
467 | void kfd_process_destroy_wq(void); | 485 | void kfd_process_destroy_wq(void); |
468 | struct kfd_process *kfd_create_process(const struct task_struct *); | 486 | struct kfd_process *kfd_create_process(const struct task_struct *); |
diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index 47b551970a14..96a512208fad 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h | |||
@@ -183,7 +183,7 @@ struct kfd2kgd_calls { | |||
183 | int (*hqd_load)(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, | 183 | int (*hqd_load)(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, |
184 | uint32_t queue_id, uint32_t __user *wptr); | 184 | uint32_t queue_id, uint32_t __user *wptr); |
185 | 185 | ||
186 | bool (*hqd_is_occupies)(struct kgd_dev *kgd, uint64_t queue_address, | 186 | bool (*hqd_is_occupied)(struct kgd_dev *kgd, uint64_t queue_address, |
187 | uint32_t pipe_id, uint32_t queue_id); | 187 | uint32_t pipe_id, uint32_t queue_id); |
188 | 188 | ||
189 | int (*hqd_destroy)(struct kgd_dev *kgd, uint32_t reset_type, | 189 | int (*hqd_destroy)(struct kgd_dev *kgd, uint32_t reset_type, |
diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index ba85986febea..03003f8a6de6 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h | |||
@@ -2156,4 +2156,6 @@ | |||
2156 | #define ATC_VM_APERTURE1_HIGH_ADDR 0x330Cu | 2156 | #define ATC_VM_APERTURE1_HIGH_ADDR 0x330Cu |
2157 | #define ATC_VM_APERTURE1_LOW_ADDR 0x3304u | 2157 | #define ATC_VM_APERTURE1_LOW_ADDR 0x3304u |
2158 | 2158 | ||
2159 | #define IH_VMID_0_LUT 0x3D40u | ||
2160 | |||
2159 | #endif | 2161 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c b/drivers/gpu/drm/radeon/radeon_kfd.c index d3e78b4a6b75..8bf87f1203cc 100644 --- a/drivers/gpu/drm/radeon/radeon_kfd.c +++ b/drivers/gpu/drm/radeon/radeon_kfd.c | |||
@@ -72,7 +72,7 @@ static int kgd_init_pipeline(struct kgd_dev *kgd, uint32_t pipe_id, | |||
72 | static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, | 72 | static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, |
73 | uint32_t queue_id, uint32_t __user *wptr); | 73 | uint32_t queue_id, uint32_t __user *wptr); |
74 | 74 | ||
75 | static bool kgd_hqd_is_occupies(struct kgd_dev *kgd, uint64_t queue_address, | 75 | static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address, |
76 | uint32_t pipe_id, uint32_t queue_id); | 76 | uint32_t pipe_id, uint32_t queue_id); |
77 | 77 | ||
78 | static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, | 78 | static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, |
@@ -92,7 +92,7 @@ static const struct kfd2kgd_calls kfd2kgd = { | |||
92 | .init_memory = kgd_init_memory, | 92 | .init_memory = kgd_init_memory, |
93 | .init_pipeline = kgd_init_pipeline, | 93 | .init_pipeline = kgd_init_pipeline, |
94 | .hqd_load = kgd_hqd_load, | 94 | .hqd_load = kgd_hqd_load, |
95 | .hqd_is_occupies = kgd_hqd_is_occupies, | 95 | .hqd_is_occupied = kgd_hqd_is_occupied, |
96 | .hqd_destroy = kgd_hqd_destroy, | 96 | .hqd_destroy = kgd_hqd_destroy, |
97 | .get_fw_version = get_fw_version | 97 | .get_fw_version = get_fw_version |
98 | }; | 98 | }; |
@@ -390,6 +390,10 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid, | |||
390 | cpu_relax(); | 390 | cpu_relax(); |
391 | write_register(kgd, ATC_VMID_PASID_MAPPING_UPDATE_STATUS, 1U << vmid); | 391 | write_register(kgd, ATC_VMID_PASID_MAPPING_UPDATE_STATUS, 1U << vmid); |
392 | 392 | ||
393 | /* Mapping vmid to pasid also for IH block */ | ||
394 | write_register(kgd, IH_VMID_0_LUT + vmid * sizeof(uint32_t), | ||
395 | pasid_mapping); | ||
396 | |||
393 | return 0; | 397 | return 0; |
394 | } | 398 | } |
395 | 399 | ||
@@ -529,7 +533,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, | |||
529 | return 0; | 533 | return 0; |
530 | } | 534 | } |
531 | 535 | ||
532 | static bool kgd_hqd_is_occupies(struct kgd_dev *kgd, uint64_t queue_address, | 536 | static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address, |
533 | uint32_t pipe_id, uint32_t queue_id) | 537 | uint32_t pipe_id, uint32_t queue_id) |
534 | { | 538 | { |
535 | uint32_t act; | 539 | uint32_t act; |
@@ -568,6 +572,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, | |||
568 | if (timeout == 0) { | 572 | if (timeout == 0) { |
569 | pr_err("kfd: cp queue preemption time out (%dms)\n", | 573 | pr_err("kfd: cp queue preemption time out (%dms)\n", |
570 | temp); | 574 | temp); |
575 | release_queue(kgd); | ||
571 | return -ETIME; | 576 | return -ETIME; |
572 | } | 577 | } |
573 | msleep(20); | 578 | msleep(20); |
diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index 7acef41fc209..af94f31e33ac 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h | |||
@@ -128,27 +128,34 @@ struct kfd_ioctl_get_process_apertures_args { | |||
128 | uint32_t pad; | 128 | uint32_t pad; |
129 | }; | 129 | }; |
130 | 130 | ||
131 | #define KFD_IOC_MAGIC 'K' | 131 | #define AMDKFD_IOCTL_BASE 'K' |
132 | #define AMDKFD_IO(nr) _IO(AMDKFD_IOCTL_BASE, nr) | ||
133 | #define AMDKFD_IOR(nr, type) _IOR(AMDKFD_IOCTL_BASE, nr, type) | ||
134 | #define AMDKFD_IOW(nr, type) _IOW(AMDKFD_IOCTL_BASE, nr, type) | ||
135 | #define AMDKFD_IOWR(nr, type) _IOWR(AMDKFD_IOCTL_BASE, nr, type) | ||
132 | 136 | ||
133 | #define KFD_IOC_GET_VERSION \ | 137 | #define AMDKFD_IOC_GET_VERSION \ |
134 | _IOR(KFD_IOC_MAGIC, 1, struct kfd_ioctl_get_version_args) | 138 | AMDKFD_IOR(0x01, struct kfd_ioctl_get_version_args) |
135 | 139 | ||
136 | #define KFD_IOC_CREATE_QUEUE \ | 140 | #define AMDKFD_IOC_CREATE_QUEUE \ |
137 | _IOWR(KFD_IOC_MAGIC, 2, struct kfd_ioctl_create_queue_args) | 141 | AMDKFD_IOWR(0x02, struct kfd_ioctl_create_queue_args) |
138 | 142 | ||
139 | #define KFD_IOC_DESTROY_QUEUE \ | 143 | #define AMDKFD_IOC_DESTROY_QUEUE \ |
140 | _IOWR(KFD_IOC_MAGIC, 3, struct kfd_ioctl_destroy_queue_args) | 144 | AMDKFD_IOWR(0x03, struct kfd_ioctl_destroy_queue_args) |
141 | 145 | ||
142 | #define KFD_IOC_SET_MEMORY_POLICY \ | 146 | #define AMDKFD_IOC_SET_MEMORY_POLICY \ |
143 | _IOW(KFD_IOC_MAGIC, 4, struct kfd_ioctl_set_memory_policy_args) | 147 | AMDKFD_IOW(0x04, struct kfd_ioctl_set_memory_policy_args) |
144 | 148 | ||
145 | #define KFD_IOC_GET_CLOCK_COUNTERS \ | 149 | #define AMDKFD_IOC_GET_CLOCK_COUNTERS \ |
146 | _IOWR(KFD_IOC_MAGIC, 5, struct kfd_ioctl_get_clock_counters_args) | 150 | AMDKFD_IOWR(0x05, struct kfd_ioctl_get_clock_counters_args) |
147 | 151 | ||
148 | #define KFD_IOC_GET_PROCESS_APERTURES \ | 152 | #define AMDKFD_IOC_GET_PROCESS_APERTURES \ |
149 | _IOR(KFD_IOC_MAGIC, 6, struct kfd_ioctl_get_process_apertures_args) | 153 | AMDKFD_IOR(0x06, struct kfd_ioctl_get_process_apertures_args) |
150 | 154 | ||
151 | #define KFD_IOC_UPDATE_QUEUE \ | 155 | #define AMDKFD_IOC_UPDATE_QUEUE \ |
152 | _IOW(KFD_IOC_MAGIC, 7, struct kfd_ioctl_update_queue_args) | 156 | AMDKFD_IOW(0x07, struct kfd_ioctl_update_queue_args) |
157 | |||
158 | #define AMDKFD_COMMAND_START 0x01 | ||
159 | #define AMDKFD_COMMAND_END 0x08 | ||
153 | 160 | ||
154 | #endif | 161 | #endif |