int cxl_start_work(struct cxl_context *ctx, struct cxl_ioctl_start_work *work) { int rc; /* code taken from afu_ioctl_start_work */ if (!(work->flags & CXL_START_WORK_NUM_IRQS)) work->num_interrupts = ctx->afu->pp_irqs; else if ((work->num_interrupts < ctx->afu->pp_irqs) || (work->num_interrupts > ctx->afu->irqs_max)) { return -EINVAL; } rc = afu_register_irqs(ctx, work->num_interrupts); if (rc) return rc; rc = cxl_start_context(ctx, work->work_element_descriptor, current); if (rc < 0) { afu_release_irqs(ctx, ctx); return rc; } return 0; }
static long afu_ioctl_start_work(struct cxl_context *ctx, struct cxl_ioctl_start_work __user *uwork) { struct cxl_ioctl_start_work work; u64 amr = 0; int rc; pr_devel("%s: pe: %i\n", __func__, ctx->pe); /* Do this outside the status_mutex to avoid a circular dependency with * the locking in cxl_mmap_fault() */ if (copy_from_user(&work, uwork, sizeof(struct cxl_ioctl_start_work))) { rc = -EFAULT; goto out; } mutex_lock(&ctx->status_mutex); if (ctx->status != OPENED) { rc = -EIO; goto out; } /* * if any of the reserved fields are set or any of the unused * flags are set it's invalid */ if (work.reserved1 || work.reserved2 || work.reserved3 || work.reserved4 || work.reserved5 || work.reserved6 || (work.flags & ~CXL_START_WORK_ALL)) { rc = -EINVAL; goto out; } if (!(work.flags & CXL_START_WORK_NUM_IRQS)) work.num_interrupts = ctx->afu->pp_irqs; else if ((work.num_interrupts < ctx->afu->pp_irqs) || (work.num_interrupts > ctx->afu->irqs_max)) { rc = -EINVAL; goto out; } if ((rc = afu_register_irqs(ctx, work.num_interrupts))) goto out; if (work.flags & CXL_START_WORK_AMR) amr = work.amr & mfspr(SPRN_UAMOR); /* * We grab the PID here and not in the file open to allow for the case * where a process (master, some daemon, etc) has opened the chardev on * behalf of another process, so the AFU's mm gets bound to the process * that performs this ioctl and not the process that opened the file. */ ctx->pid = get_pid(get_task_pid(current, PIDTYPE_PID)); trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); if ((rc = cxl_attach_process(ctx, false, work.work_element_descriptor, amr))) { afu_release_irqs(ctx); goto out; } ctx->status = STARTED; rc = 0; out: mutex_unlock(&ctx->status_mutex); return rc; }