diff options
| author | Oded Gabbay <oded.gabbay@amd.com> | 2014-12-29 07:20:05 -0500 |
|---|---|---|
| committer | Oded Gabbay <oded.gabbay@amd.com> | 2015-01-06 12:44:36 -0500 |
| commit | 76baee6c733bfef30fcf86cbd121e336b839e408 (patch) | |
| tree | 1ba6313aa81b5c69ed5591e0cb8598c2fd69434b | |
| parent | b81c55db1053805866a242cd0bfbfb0c60c499b3 (diff) | |
drm/amdkfd: rewrite kfd_ioctl() according to drm_ioctl()
This patch changes kfd_ioctl() to be very similar to drm_ioctl().
The patch defines an array of amdkfd_ioctls, which maps IOCTL definition to the
ioctl function.
The kfd_ioctl() uses that mapping to call the appropriate ioctl function,
through a function pointer.
This patch also declares a new typedef for the ioctl function pointer.
v2: Renamed KFD_COMMAND_(START|END) to AMDKFD_...
Signed-off-by: Oded Gabbay <oded.gabbay@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
| -rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 116 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 18 |
2 files changed, 86 insertions, 48 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 6fbde9e411e0..fcfdf23e1913 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | |||
| @@ -482,21 +482,79 @@ static int kfd_ioctl_get_process_apertures(struct file *filp, | |||
| 482 | return 0; | 482 | return 0; |
| 483 | } | 483 | } |
| 484 | 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 | |||
| 485 | 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) |
| 486 | { | 515 | { |
| 487 | struct kfd_process *process; | 516 | struct kfd_process *process; |
| 517 | amdkfd_ioctl_t *func; | ||
| 518 | const struct amdkfd_ioctl_desc *ioctl = NULL; | ||
| 519 | unsigned int nr = _IOC_NR(cmd); | ||
| 488 | char stack_kdata[128]; | 520 | char stack_kdata[128]; |
| 489 | char *kdata = NULL; | 521 | char *kdata = NULL; |
| 490 | unsigned int usize, asize; | 522 | unsigned int usize, asize; |
| 491 | int retcode = -EINVAL; | 523 | int retcode = -EINVAL; |
| 492 | 524 | ||
| 493 | dev_dbg(kfd_device, | 525 | if (nr >= AMDKFD_CORE_IOCTL_COUNT) |
| 494 | "ioctl cmd 0x%x (#%d), arg 0x%lx\n", | 526 | goto err_i1; |
| 495 | 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); | ||
| 496 | 543 | ||
| 497 | process = kfd_get_process(current); | 544 | process = kfd_get_process(current); |
| 498 | if (IS_ERR(process)) | 545 | if (IS_ERR(process)) { |
| 499 | return PTR_ERR(process); | 546 | dev_dbg(kfd_device, "no process\n"); |
| 547 | goto err_i1; | ||
| 548 | } | ||
| 549 | |||
| 550 | /* Do not trust userspace, use our own definition */ | ||
| 551 | func = ioctl->func; | ||
| 552 | |||
| 553 | if (unlikely(!func)) { | ||
| 554 | dev_dbg(kfd_device, "no function\n"); | ||
| 555 | retcode = -EINVAL; | ||
| 556 | goto err_i1; | ||
| 557 | } | ||
| 500 | 558 | ||
| 501 | if (cmd & (IOC_IN | IOC_OUT)) { | 559 | if (cmd & (IOC_IN | IOC_OUT)) { |
| 502 | if (asize <= sizeof(stack_kdata)) { | 560 | if (asize <= sizeof(stack_kdata)) { |
| @@ -521,55 +579,17 @@ static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) | |||
| 521 | memset(kdata, 0, usize); | 579 | memset(kdata, 0, usize); |
| 522 | } | 580 | } |
| 523 | 581 | ||
| 524 | 582 | retcode = func(filep, process, kdata); | |
| 525 | switch (cmd) { | ||
| 526 | case AMDKFD_IOC_GET_VERSION: | ||
| 527 | retcode = kfd_ioctl_get_version(filep, process, kdata); | ||
| 528 | break; | ||
| 529 | |||
| 530 | case AMDKFD_IOC_CREATE_QUEUE: | ||
| 531 | retcode = kfd_ioctl_create_queue(filep, process, | ||
| 532 | kdata); | ||
| 533 | break; | ||
| 534 | |||
| 535 | case AMDKFD_IOC_DESTROY_QUEUE: | ||
| 536 | retcode = kfd_ioctl_destroy_queue(filep, process, | ||
| 537 | kdata); | ||
| 538 | break; | ||
| 539 | |||
| 540 | case AMDKFD_IOC_SET_MEMORY_POLICY: | ||
| 541 | retcode = kfd_ioctl_set_memory_policy(filep, process, | ||
| 542 | kdata); | ||
| 543 | break; | ||
| 544 | |||
| 545 | case AMDKFD_IOC_GET_CLOCK_COUNTERS: | ||
| 546 | retcode = kfd_ioctl_get_clock_counters(filep, process, | ||
| 547 | kdata); | ||
| 548 | break; | ||
| 549 | |||
| 550 | case AMDKFD_IOC_GET_PROCESS_APERTURES: | ||
| 551 | retcode = kfd_ioctl_get_process_apertures(filep, process, | ||
| 552 | kdata); | ||
| 553 | break; | ||
| 554 | |||
| 555 | case AMDKFD_IOC_UPDATE_QUEUE: | ||
| 556 | retcode = kfd_ioctl_update_queue(filep, process, | ||
| 557 | kdata); | ||
| 558 | break; | ||
| 559 | |||
| 560 | default: | ||
| 561 | dev_dbg(kfd_device, | ||
| 562 | "unknown ioctl cmd 0x%x, arg 0x%lx)\n", | ||
| 563 | cmd, arg); | ||
| 564 | retcode = -EINVAL; | ||
| 565 | break; | ||
| 566 | } | ||
| 567 | 583 | ||
| 568 | if (cmd & IOC_OUT) | 584 | if (cmd & IOC_OUT) |
| 569 | if (copy_to_user((void __user *)arg, kdata, usize) != 0) | 585 | if (copy_to_user((void __user *)arg, kdata, usize) != 0) |
| 570 | retcode = -EFAULT; | 586 | retcode = -EFAULT; |
| 571 | 587 | ||
| 572 | err_i1: | 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 | |||
| 573 | if (kdata != stack_kdata) | 593 | if (kdata != stack_kdata) |
| 574 | kfree(kdata); | 594 | kfree(kdata); |
| 575 | 595 | ||
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 *); |
