diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h index 6076adf9ab4f..163a8bb85d02 100644 --- a/arch/powerpc/include/asm/vas.h +++ b/arch/powerpc/include/asm/vas.h @@ -5,6 +5,7 @@ #ifndef _ASM_POWERPC_VAS_H #define _ASM_POWERPC_VAS_H +#include struct vas_window; @@ -48,6 +49,16 @@ enum vas_cop_type { VAS_COP_TYPE_MAX, }; +/* + * User space window operations used for powernv and powerVM + */ +struct vas_user_win_ops { + struct vas_window * (*open_win)(int vas_id, u64 flags, + enum vas_cop_type); + u64 (*paste_addr)(struct vas_window *); + int (*close_win)(struct vas_window *); +}; + /* * Receive window attributes specified by the (in-kernel) owner of window. */ @@ -162,8 +173,6 @@ int vas_copy_crb(void *crb, int offset); */ int vas_paste_crb(struct vas_window *win, int offset, bool re); -void vas_win_paste_addr(struct vas_window *window, u64 *addr, - int *len); int vas_register_api_powernv(struct module *mod, enum vas_cop_type cop_type, const char *name); void vas_unregister_api_powernv(void); @@ -177,7 +186,8 @@ void vas_unregister_api_powernv(void); * used for others in future. */ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type, - const char *name); + const char *name, + const struct vas_user_win_ops *vops); void vas_unregister_coproc_api(void); #endif /* __ASM_POWERPC_VAS_H */ diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c index 72c126d87216..ad566464b55b 100644 --- a/arch/powerpc/platforms/book3s/vas-api.c +++ b/arch/powerpc/platforms/book3s/vas-api.c @@ -42,6 +42,7 @@ static struct coproc_dev { dev_t devt; struct class *class; enum vas_cop_type cop_type; + const struct vas_user_win_ops *vops; } coproc_device; struct coproc_instance { @@ -72,11 +73,10 @@ static int coproc_open(struct inode *inode, struct file *fp) static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg) { void __user *uptr = (void __user *)arg; - struct vas_tx_win_attr txattr = {}; struct vas_tx_win_open_attr uattr; struct coproc_instance *cp_inst; struct vas_window *txwin; - int rc, vasid; + int rc; cp_inst = fp->private_data; @@ -93,27 +93,20 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg) } if (uattr.version != 1) { - pr_err("Invalid version\n"); + pr_err("Invalid window open API version\n"); return -EINVAL; } - vasid = uattr.vas_id; + if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->open_win) { + pr_err("VAS API is not registered\n"); + return -EACCES; + } - vas_init_tx_win_attr(&txattr, cp_inst->coproc->cop_type); - - txattr.lpid = mfspr(SPRN_LPID); - txattr.pidr = mfspr(SPRN_PID); - txattr.user_win = true; - txattr.rsvd_txbuf_count = false; - txattr.pswid = false; - - pr_devel("Pid %d: Opening txwin, PIDR %ld\n", txattr.pidr, - mfspr(SPRN_PID)); - - txwin = vas_tx_win_open(vasid, cp_inst->coproc->cop_type, &txattr); + txwin = cp_inst->coproc->vops->open_win(uattr.vas_id, uattr.flags, + cp_inst->coproc->cop_type); if (IS_ERR(txwin)) { - pr_err("%s() vas_tx_win_open() failed, %ld\n", __func__, - PTR_ERR(txwin)); + pr_err("%s() VAS window open failed, %ld\n", __func__, + PTR_ERR(txwin)); return PTR_ERR(txwin); } @@ -125,9 +118,15 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg) static int coproc_release(struct inode *inode, struct file *fp) { struct coproc_instance *cp_inst = fp->private_data; + int rc; if (cp_inst->txwin) { - vas_win_close(cp_inst->txwin); + if (cp_inst->coproc->vops && + cp_inst->coproc->vops->close_win) { + rc = cp_inst->coproc->vops->close_win(cp_inst->txwin); + if (rc) + return rc; + } cp_inst->txwin = NULL; } @@ -168,7 +167,17 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma) return -EINVAL; } - vas_win_paste_addr(txwin, &paste_addr, NULL); + if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->paste_addr) { + pr_err("%s(): VAS API is not registered\n", __func__); + return -EACCES; + } + + paste_addr = cp_inst->coproc->vops->paste_addr(txwin); + if (!paste_addr) { + pr_err("%s(): Window paste address failed\n", __func__); + return -EINVAL; + } + pfn = paste_addr >> PAGE_SHIFT; /* flags, page_prot from cxl_mmap(), except we want cachable */ @@ -208,7 +217,8 @@ static struct file_operations coproc_fops = { * extended to other coprocessor types later. */ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type, - const char *name) + const char *name, + const struct vas_user_win_ops *vops) { int rc = -EINVAL; dev_t devno; @@ -230,6 +240,7 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type, } coproc_device.class->devnode = coproc_devnode; coproc_device.cop_type = cop_type; + coproc_device.vops = vops; coproc_fops.owner = mod; cdev_init(&coproc_device.cdev, &coproc_fops); diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c index 41712b4b268e..26440da4fc6a 100644 --- a/arch/powerpc/platforms/powernv/vas-window.c +++ b/arch/powerpc/platforms/powernv/vas-window.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "vas.h" #include "copy-paste.h" @@ -1443,6 +1444,48 @@ struct vas_window *vas_pswid_to_window(struct vas_instance *vinst, return window; } +static struct vas_window *vas_user_win_open(int vas_id, u64 flags, + enum vas_cop_type cop_type) +{ + struct vas_tx_win_attr txattr = {}; + + vas_init_tx_win_attr(&txattr, cop_type); + + txattr.lpid = mfspr(SPRN_LPID); + txattr.pidr = mfspr(SPRN_PID); + txattr.user_win = true; + txattr.rsvd_txbuf_count = false; + txattr.pswid = false; + + pr_devel("Pid %d: Opening txwin, PIDR %ld\n", txattr.pidr, + mfspr(SPRN_PID)); + + return vas_tx_win_open(vas_id, cop_type, &txattr); +} + +static u64 vas_user_win_paste_addr(struct vas_window *win) +{ + u64 paste_addr; + + vas_win_paste_addr(win, &paste_addr, NULL); + + return paste_addr; +} + +static int vas_user_win_close(struct vas_window *txwin) +{ + + vas_win_close(txwin); + + return 0; +} + +static const struct vas_user_win_ops vops = { + .open_win = vas_user_win_open, + .paste_addr = vas_user_win_paste_addr, + .close_win = vas_user_win_close, +}; + /* * Supporting only nx-gzip coprocessor type now, but this API code * extended to other coprocessor types later. @@ -1451,7 +1494,7 @@ int vas_register_api_powernv(struct module *mod, enum vas_cop_type cop_type, const char *name) { - return vas_register_coproc_api(mod, cop_type, name); + return vas_register_coproc_api(mod, cop_type, name, &vops); } EXPORT_SYMBOL_GPL(vas_register_api_powernv); diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h index e5027c4226df..c2b1e12efca5 100644 --- a/arch/powerpc/platforms/powernv/vas.h +++ b/arch/powerpc/platforms/powernv/vas.h @@ -438,6 +438,8 @@ extern irqreturn_t vas_fault_handler(int irq, void *dev_id); extern void vas_return_credit(struct vas_window *window, bool tx); extern struct vas_window *vas_pswid_to_window(struct vas_instance *vinst, uint32_t pswid); +extern void vas_win_paste_addr(struct vas_window *window, u64 *addr, + int *len); static inline int vas_window_pid(struct vas_window *window) {