@@ -5,6 +5,7 @@
#ifndef _ASM_POWERPC_VAS_H
#define _ASM_POWERPC_VAS_H
+#include <uapi/asm/vas-api.h>
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 */
@@ -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;
-
- 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));
+ if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->open_win) {
+ pr_err("VAS API is not registered\n");
+ return -EACCES;
+ }
- 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);
@@ -16,6 +16,7 @@
#include <linux/mmu_context.h>
#include <asm/switch_to.h>
#include <asm/ppc-opcode.h>
+#include <asm/vas.h>
#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);
@@ -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)
{