/* Get a struct file and fd for a context and attach the ops */ struct file *cxl_get_fd(struct cxl_context *ctx, struct file_operations *fops, int *fd) { struct file *file; int rc, flags, fdtmp; char *name = NULL; /* only allow one per context */ if (ctx->mapping) return ERR_PTR(-EEXIST); flags = O_RDWR | O_CLOEXEC; /* This code is similar to anon_inode_getfd() */ rc = get_unused_fd_flags(flags); if (rc < 0) return ERR_PTR(rc); fdtmp = rc; /* * Patch the file ops. Needs to be careful that this is rentrant safe. */ if (fops) { PATCH_FOPS(open); PATCH_FOPS(poll); PATCH_FOPS(read); PATCH_FOPS(release); PATCH_FOPS(unlocked_ioctl); PATCH_FOPS(compat_ioctl); PATCH_FOPS(mmap); } else /* use default ops */ fops = (struct file_operations *)&afu_fops; name = kasprintf(GFP_KERNEL, "cxl:%d", ctx->pe); file = cxl_getfile(name, fops, ctx, flags); kfree(name); if (IS_ERR(file)) goto err_fd; cxl_context_set_mapping(ctx, file->f_mapping); *fd = fdtmp; return file; err_fd: put_unused_fd(fdtmp); return NULL; }
static int __afu_open(struct inode *inode, struct file *file, bool master) { struct cxl *adapter; struct cxl_afu *afu; struct cxl_context *ctx; int adapter_num = CXL_DEVT_ADAPTER(inode->i_rdev); int slice = CXL_DEVT_AFU(inode->i_rdev); int rc = -ENODEV; pr_devel("afu_open afu%i.%i\n", slice, adapter_num); if (!(adapter = get_cxl_adapter(adapter_num))) return -ENODEV; if (slice > adapter->slices) goto err_put_adapter; spin_lock(&adapter->afu_list_lock); if (!(afu = adapter->afu[slice])) { spin_unlock(&adapter->afu_list_lock); goto err_put_adapter; } /* * taking a ref to the afu so that it doesn't go away * for rest of the function. This ref is released before * we return. */ cxl_afu_get(afu); spin_unlock(&adapter->afu_list_lock); if (!afu->current_mode) goto err_put_afu; if (!cxl_ops->link_ok(adapter, afu)) { rc = -EIO; goto err_put_afu; } if (!(ctx = cxl_context_alloc())) { rc = -ENOMEM; goto err_put_afu; } rc = cxl_context_init(ctx, afu, master); if (rc) goto err_put_afu; cxl_context_set_mapping(ctx, inode->i_mapping); pr_devel("afu_open pe: %i\n", ctx->pe); file->private_data = ctx; cxl_ctx_get(); /* indicate success */ rc = 0; err_put_afu: /* release the ref taken earlier */ cxl_afu_put(afu); err_put_adapter: put_device(&adapter->dev); return rc; }