16f7f0b3dSMichael Neuling /* 26f7f0b3dSMichael Neuling * Copyright 2014 IBM Corp. 36f7f0b3dSMichael Neuling * 46f7f0b3dSMichael Neuling * This program is free software; you can redistribute it and/or 56f7f0b3dSMichael Neuling * modify it under the terms of the GNU General Public License 66f7f0b3dSMichael Neuling * as published by the Free Software Foundation; either version 76f7f0b3dSMichael Neuling * 2 of the License, or (at your option) any later version. 86f7f0b3dSMichael Neuling */ 96f7f0b3dSMichael Neuling 106f7f0b3dSMichael Neuling #include <linux/pci.h> 116f7f0b3dSMichael Neuling #include <linux/slab.h> 126f7f0b3dSMichael Neuling #include <linux/anon_inodes.h> 136f7f0b3dSMichael Neuling #include <linux/file.h> 146f7f0b3dSMichael Neuling #include <misc/cxl.h> 1555e07668SIan Munsie #include <linux/fs.h> 166f7f0b3dSMichael Neuling 176f7f0b3dSMichael Neuling #include "cxl.h" 186f7f0b3dSMichael Neuling 196f7f0b3dSMichael Neuling struct cxl_context *cxl_dev_context_init(struct pci_dev *dev) 206f7f0b3dSMichael Neuling { 2155e07668SIan Munsie struct address_space *mapping; 226f7f0b3dSMichael Neuling struct cxl_afu *afu; 236f7f0b3dSMichael Neuling struct cxl_context *ctx; 246f7f0b3dSMichael Neuling int rc; 256f7f0b3dSMichael Neuling 266f7f0b3dSMichael Neuling afu = cxl_pci_to_afu(dev); 276f7f0b3dSMichael Neuling 286f7f0b3dSMichael Neuling ctx = cxl_context_alloc(); 29af2a50bbSIan Munsie if (IS_ERR(ctx)) { 30af2a50bbSIan Munsie rc = PTR_ERR(ctx); 31af2a50bbSIan Munsie goto err_dev; 32af2a50bbSIan Munsie } 336f7f0b3dSMichael Neuling 3455e07668SIan Munsie ctx->kernelapi = true; 3555e07668SIan Munsie 3655e07668SIan Munsie /* 3755e07668SIan Munsie * Make our own address space since we won't have one from the 3855e07668SIan Munsie * filesystem like the user api has, and even if we do associate a file 3955e07668SIan Munsie * with this context we don't want to use the global anonymous inode's 4055e07668SIan Munsie * address space as that can invalidate unrelated users: 4155e07668SIan Munsie */ 4255e07668SIan Munsie mapping = kmalloc(sizeof(struct address_space), GFP_KERNEL); 4355e07668SIan Munsie if (!mapping) { 4455e07668SIan Munsie rc = -ENOMEM; 45af2a50bbSIan Munsie goto err_ctx; 4655e07668SIan Munsie } 4755e07668SIan Munsie address_space_init_once(mapping); 4855e07668SIan Munsie 4955e07668SIan Munsie /* Make it a slave context. We can promote it later? */ 5055e07668SIan Munsie rc = cxl_context_init(ctx, afu, false, mapping); 5155e07668SIan Munsie if (rc) 5255e07668SIan Munsie goto err_mapping; 5355e07668SIan Munsie 546f7f0b3dSMichael Neuling return ctx; 55af2a50bbSIan Munsie 5655e07668SIan Munsie err_mapping: 5755e07668SIan Munsie kfree(mapping); 58af2a50bbSIan Munsie err_ctx: 59af2a50bbSIan Munsie kfree(ctx); 60af2a50bbSIan Munsie err_dev: 61af2a50bbSIan Munsie return ERR_PTR(rc); 626f7f0b3dSMichael Neuling } 636f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_dev_context_init); 646f7f0b3dSMichael Neuling 656f7f0b3dSMichael Neuling struct cxl_context *cxl_get_context(struct pci_dev *dev) 666f7f0b3dSMichael Neuling { 676f7f0b3dSMichael Neuling return dev->dev.archdata.cxl_ctx; 686f7f0b3dSMichael Neuling } 696f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_get_context); 706f7f0b3dSMichael Neuling 716f7f0b3dSMichael Neuling int cxl_release_context(struct cxl_context *ctx) 726f7f0b3dSMichael Neuling { 737c26b9cfSAndrew Donnellan if (ctx->status >= STARTED) 746f7f0b3dSMichael Neuling return -EBUSY; 756f7f0b3dSMichael Neuling 766f7f0b3dSMichael Neuling cxl_context_free(ctx); 776f7f0b3dSMichael Neuling 786f7f0b3dSMichael Neuling return 0; 796f7f0b3dSMichael Neuling } 806f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_release_context); 816f7f0b3dSMichael Neuling 826f7f0b3dSMichael Neuling static irq_hw_number_t cxl_find_afu_irq(struct cxl_context *ctx, int num) 836f7f0b3dSMichael Neuling { 846f7f0b3dSMichael Neuling __u16 range; 856f7f0b3dSMichael Neuling int r; 866f7f0b3dSMichael Neuling 876f7f0b3dSMichael Neuling for (r = 0; r < CXL_IRQ_RANGES; r++) { 886f7f0b3dSMichael Neuling range = ctx->irqs.range[r]; 896f7f0b3dSMichael Neuling if (num < range) { 906f7f0b3dSMichael Neuling return ctx->irqs.offset[r] + num; 916f7f0b3dSMichael Neuling } 926f7f0b3dSMichael Neuling num -= range; 936f7f0b3dSMichael Neuling } 946f7f0b3dSMichael Neuling return 0; 956f7f0b3dSMichael Neuling } 966f7f0b3dSMichael Neuling 97d601ea91SFrederic Barrat int cxl_allocate_afu_irqs(struct cxl_context *ctx, int num) 98d601ea91SFrederic Barrat { 99d601ea91SFrederic Barrat int res; 100d601ea91SFrederic Barrat irq_hw_number_t hwirq; 101d601ea91SFrederic Barrat 102d601ea91SFrederic Barrat if (num == 0) 103d601ea91SFrederic Barrat num = ctx->afu->pp_irqs; 104d601ea91SFrederic Barrat res = afu_allocate_irqs(ctx, num); 105292841b0SIan Munsie if (res) 106292841b0SIan Munsie return res; 107292841b0SIan Munsie 108292841b0SIan Munsie if (!cpu_has_feature(CPU_FTR_HVMODE)) { 109d601ea91SFrederic Barrat /* In a guest, the PSL interrupt is not multiplexed. It was 110d601ea91SFrederic Barrat * allocated above, and we need to set its handler 111d601ea91SFrederic Barrat */ 112d601ea91SFrederic Barrat hwirq = cxl_find_afu_irq(ctx, 0); 113d601ea91SFrederic Barrat if (hwirq) 114d601ea91SFrederic Barrat cxl_map_irq(ctx->afu->adapter, hwirq, cxl_ops->psl_interrupt, ctx, "psl"); 115d601ea91SFrederic Barrat } 116292841b0SIan Munsie 117292841b0SIan Munsie if (ctx->status == STARTED) { 118292841b0SIan Munsie if (cxl_ops->update_ivtes) 119292841b0SIan Munsie cxl_ops->update_ivtes(ctx); 120292841b0SIan Munsie else WARN(1, "BUG: cxl_allocate_afu_irqs must be called prior to starting the context on this platform\n"); 121292841b0SIan Munsie } 122292841b0SIan Munsie 123d601ea91SFrederic Barrat return res; 124d601ea91SFrederic Barrat } 125d601ea91SFrederic Barrat EXPORT_SYMBOL_GPL(cxl_allocate_afu_irqs); 126d601ea91SFrederic Barrat 127d601ea91SFrederic Barrat void cxl_free_afu_irqs(struct cxl_context *ctx) 128d601ea91SFrederic Barrat { 129d601ea91SFrederic Barrat irq_hw_number_t hwirq; 130d601ea91SFrederic Barrat unsigned int virq; 131d601ea91SFrederic Barrat 132d601ea91SFrederic Barrat if (!cpu_has_feature(CPU_FTR_HVMODE)) { 133d601ea91SFrederic Barrat hwirq = cxl_find_afu_irq(ctx, 0); 134d601ea91SFrederic Barrat if (hwirq) { 135d601ea91SFrederic Barrat virq = irq_find_mapping(NULL, hwirq); 136d601ea91SFrederic Barrat if (virq) 137d601ea91SFrederic Barrat cxl_unmap_irq(virq, ctx); 138d601ea91SFrederic Barrat } 139d601ea91SFrederic Barrat } 140d601ea91SFrederic Barrat afu_irq_name_free(ctx); 141d601ea91SFrederic Barrat cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter); 142d601ea91SFrederic Barrat } 143d601ea91SFrederic Barrat EXPORT_SYMBOL_GPL(cxl_free_afu_irqs); 144d601ea91SFrederic Barrat 1456f7f0b3dSMichael Neuling int cxl_map_afu_irq(struct cxl_context *ctx, int num, 1466f7f0b3dSMichael Neuling irq_handler_t handler, void *cookie, char *name) 1476f7f0b3dSMichael Neuling { 1486f7f0b3dSMichael Neuling irq_hw_number_t hwirq; 1496f7f0b3dSMichael Neuling 1506f7f0b3dSMichael Neuling /* 1516f7f0b3dSMichael Neuling * Find interrupt we are to register. 1526f7f0b3dSMichael Neuling */ 1536f7f0b3dSMichael Neuling hwirq = cxl_find_afu_irq(ctx, num); 1546f7f0b3dSMichael Neuling if (!hwirq) 1556f7f0b3dSMichael Neuling return -ENOENT; 1566f7f0b3dSMichael Neuling 1576f7f0b3dSMichael Neuling return cxl_map_irq(ctx->afu->adapter, hwirq, handler, cookie, name); 1586f7f0b3dSMichael Neuling } 1596f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_map_afu_irq); 1606f7f0b3dSMichael Neuling 1616f7f0b3dSMichael Neuling void cxl_unmap_afu_irq(struct cxl_context *ctx, int num, void *cookie) 1626f7f0b3dSMichael Neuling { 1636f7f0b3dSMichael Neuling irq_hw_number_t hwirq; 1646f7f0b3dSMichael Neuling unsigned int virq; 1656f7f0b3dSMichael Neuling 1666f7f0b3dSMichael Neuling hwirq = cxl_find_afu_irq(ctx, num); 1676f7f0b3dSMichael Neuling if (!hwirq) 1686f7f0b3dSMichael Neuling return; 1696f7f0b3dSMichael Neuling 1706f7f0b3dSMichael Neuling virq = irq_find_mapping(NULL, hwirq); 1716f7f0b3dSMichael Neuling if (virq) 1726f7f0b3dSMichael Neuling cxl_unmap_irq(virq, cookie); 1736f7f0b3dSMichael Neuling } 1746f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_unmap_afu_irq); 1756f7f0b3dSMichael Neuling 1766f7f0b3dSMichael Neuling /* 1776f7f0b3dSMichael Neuling * Start a context 1786f7f0b3dSMichael Neuling * Code here similar to afu_ioctl_start_work(). 1796f7f0b3dSMichael Neuling */ 1806f7f0b3dSMichael Neuling int cxl_start_context(struct cxl_context *ctx, u64 wed, 1816f7f0b3dSMichael Neuling struct task_struct *task) 1826f7f0b3dSMichael Neuling { 1836f7f0b3dSMichael Neuling int rc = 0; 1846f7f0b3dSMichael Neuling bool kernel = true; 1856f7f0b3dSMichael Neuling 1866f7f0b3dSMichael Neuling pr_devel("%s: pe: %i\n", __func__, ctx->pe); 1876f7f0b3dSMichael Neuling 1886f7f0b3dSMichael Neuling mutex_lock(&ctx->status_mutex); 1896f7f0b3dSMichael Neuling if (ctx->status == STARTED) 1906f7f0b3dSMichael Neuling goto out; /* already started */ 1916f7f0b3dSMichael Neuling 1926f7f0b3dSMichael Neuling if (task) { 1936f7f0b3dSMichael Neuling ctx->pid = get_task_pid(task, PIDTYPE_PID); 1947b8ad495SVaibhav Jain ctx->glpid = get_task_pid(task->group_leader, PIDTYPE_PID); 1956f7f0b3dSMichael Neuling kernel = false; 1967a0d85d3SIan Munsie ctx->real_mode = false; 1976f7f0b3dSMichael Neuling } 1986f7f0b3dSMichael Neuling 1996f7f0b3dSMichael Neuling cxl_ctx_get(); 2006f7f0b3dSMichael Neuling 2015be587b1SFrederic Barrat if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) { 2026f7f0b3dSMichael Neuling put_pid(ctx->pid); 2036f7f0b3dSMichael Neuling cxl_ctx_put(); 2046f7f0b3dSMichael Neuling goto out; 2056f7f0b3dSMichael Neuling } 2066f7f0b3dSMichael Neuling 2076f7f0b3dSMichael Neuling ctx->status = STARTED; 2086f7f0b3dSMichael Neuling out: 2096f7f0b3dSMichael Neuling mutex_unlock(&ctx->status_mutex); 2106f7f0b3dSMichael Neuling return rc; 2116f7f0b3dSMichael Neuling } 2126f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_start_context); 2136f7f0b3dSMichael Neuling 2146f7f0b3dSMichael Neuling int cxl_process_element(struct cxl_context *ctx) 2156f7f0b3dSMichael Neuling { 21614baf4d9SChristophe Lombard return ctx->external_pe; 2176f7f0b3dSMichael Neuling } 2186f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_process_element); 2196f7f0b3dSMichael Neuling 2206f7f0b3dSMichael Neuling /* Stop a context. Returns 0 on success, otherwise -Errno */ 2216f7f0b3dSMichael Neuling int cxl_stop_context(struct cxl_context *ctx) 2226f7f0b3dSMichael Neuling { 2233f8dc44dSMichael Neuling return __detach_context(ctx); 2246f7f0b3dSMichael Neuling } 2256f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_stop_context); 2266f7f0b3dSMichael Neuling 2276f7f0b3dSMichael Neuling void cxl_set_master(struct cxl_context *ctx) 2286f7f0b3dSMichael Neuling { 2296f7f0b3dSMichael Neuling ctx->master = true; 2306f7f0b3dSMichael Neuling } 2316f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_set_master); 2326f7f0b3dSMichael Neuling 2337a0d85d3SIan Munsie int cxl_set_translation_mode(struct cxl_context *ctx, bool real_mode) 2347a0d85d3SIan Munsie { 2357a0d85d3SIan Munsie if (ctx->status == STARTED) { 2367a0d85d3SIan Munsie /* 2377a0d85d3SIan Munsie * We could potentially update the PE and issue an update LLCMD 2387a0d85d3SIan Munsie * to support this, but it doesn't seem to have a good use case 2397a0d85d3SIan Munsie * since it's trivial to just create a second kernel context 2407a0d85d3SIan Munsie * with different translation modes, so until someone convinces 2417a0d85d3SIan Munsie * me otherwise: 2427a0d85d3SIan Munsie */ 2437a0d85d3SIan Munsie return -EBUSY; 2447a0d85d3SIan Munsie } 2457a0d85d3SIan Munsie 2467a0d85d3SIan Munsie ctx->real_mode = real_mode; 2477a0d85d3SIan Munsie return 0; 2487a0d85d3SIan Munsie } 2497a0d85d3SIan Munsie EXPORT_SYMBOL_GPL(cxl_set_translation_mode); 2507a0d85d3SIan Munsie 2516f7f0b3dSMichael Neuling /* wrappers around afu_* file ops which are EXPORTED */ 2526f7f0b3dSMichael Neuling int cxl_fd_open(struct inode *inode, struct file *file) 2536f7f0b3dSMichael Neuling { 2546f7f0b3dSMichael Neuling return afu_open(inode, file); 2556f7f0b3dSMichael Neuling } 2566f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_open); 2576f7f0b3dSMichael Neuling int cxl_fd_release(struct inode *inode, struct file *file) 2586f7f0b3dSMichael Neuling { 2596f7f0b3dSMichael Neuling return afu_release(inode, file); 2606f7f0b3dSMichael Neuling } 2616f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_release); 2626f7f0b3dSMichael Neuling long cxl_fd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 2636f7f0b3dSMichael Neuling { 2646f7f0b3dSMichael Neuling return afu_ioctl(file, cmd, arg); 2656f7f0b3dSMichael Neuling } 2666f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_ioctl); 2676f7f0b3dSMichael Neuling int cxl_fd_mmap(struct file *file, struct vm_area_struct *vm) 2686f7f0b3dSMichael Neuling { 2696f7f0b3dSMichael Neuling return afu_mmap(file, vm); 2706f7f0b3dSMichael Neuling } 2716f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_mmap); 2726f7f0b3dSMichael Neuling unsigned int cxl_fd_poll(struct file *file, struct poll_table_struct *poll) 2736f7f0b3dSMichael Neuling { 2746f7f0b3dSMichael Neuling return afu_poll(file, poll); 2756f7f0b3dSMichael Neuling } 2766f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_poll); 2776f7f0b3dSMichael Neuling ssize_t cxl_fd_read(struct file *file, char __user *buf, size_t count, 2786f7f0b3dSMichael Neuling loff_t *off) 2796f7f0b3dSMichael Neuling { 2806f7f0b3dSMichael Neuling return afu_read(file, buf, count, off); 2816f7f0b3dSMichael Neuling } 2826f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_read); 2836f7f0b3dSMichael Neuling 2846f7f0b3dSMichael Neuling #define PATCH_FOPS(NAME) if (!fops->NAME) fops->NAME = afu_fops.NAME 2856f7f0b3dSMichael Neuling 2866f7f0b3dSMichael Neuling /* Get a struct file and fd for a context and attach the ops */ 2876f7f0b3dSMichael Neuling struct file *cxl_get_fd(struct cxl_context *ctx, struct file_operations *fops, 2886f7f0b3dSMichael Neuling int *fd) 2896f7f0b3dSMichael Neuling { 2906f7f0b3dSMichael Neuling struct file *file; 2916f7f0b3dSMichael Neuling int rc, flags, fdtmp; 2926f7f0b3dSMichael Neuling 2936f7f0b3dSMichael Neuling flags = O_RDWR | O_CLOEXEC; 2946f7f0b3dSMichael Neuling 2956f7f0b3dSMichael Neuling /* This code is similar to anon_inode_getfd() */ 2966f7f0b3dSMichael Neuling rc = get_unused_fd_flags(flags); 2976f7f0b3dSMichael Neuling if (rc < 0) 2986f7f0b3dSMichael Neuling return ERR_PTR(rc); 2996f7f0b3dSMichael Neuling fdtmp = rc; 3006f7f0b3dSMichael Neuling 3016f7f0b3dSMichael Neuling /* 3026f7f0b3dSMichael Neuling * Patch the file ops. Needs to be careful that this is rentrant safe. 3036f7f0b3dSMichael Neuling */ 3046f7f0b3dSMichael Neuling if (fops) { 3056f7f0b3dSMichael Neuling PATCH_FOPS(open); 3066f7f0b3dSMichael Neuling PATCH_FOPS(poll); 3076f7f0b3dSMichael Neuling PATCH_FOPS(read); 3086f7f0b3dSMichael Neuling PATCH_FOPS(release); 3096f7f0b3dSMichael Neuling PATCH_FOPS(unlocked_ioctl); 3106f7f0b3dSMichael Neuling PATCH_FOPS(compat_ioctl); 3116f7f0b3dSMichael Neuling PATCH_FOPS(mmap); 3126f7f0b3dSMichael Neuling } else /* use default ops */ 3136f7f0b3dSMichael Neuling fops = (struct file_operations *)&afu_fops; 3146f7f0b3dSMichael Neuling 3156f7f0b3dSMichael Neuling file = anon_inode_getfile("cxl", fops, ctx, flags); 3166f7f0b3dSMichael Neuling if (IS_ERR(file)) 31755e07668SIan Munsie goto err_fd; 31855e07668SIan Munsie 31955e07668SIan Munsie file->f_mapping = ctx->mapping; 32055e07668SIan Munsie 3216f7f0b3dSMichael Neuling *fd = fdtmp; 3226f7f0b3dSMichael Neuling return file; 32355e07668SIan Munsie 32455e07668SIan Munsie err_fd: 32555e07668SIan Munsie put_unused_fd(fdtmp); 32655e07668SIan Munsie return NULL; 3276f7f0b3dSMichael Neuling } 3286f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_get_fd); 3296f7f0b3dSMichael Neuling 3306f7f0b3dSMichael Neuling struct cxl_context *cxl_fops_get_context(struct file *file) 3316f7f0b3dSMichael Neuling { 3326f7f0b3dSMichael Neuling return file->private_data; 3336f7f0b3dSMichael Neuling } 3346f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fops_get_context); 3356f7f0b3dSMichael Neuling 336b810253bSPhilippe Bergheaud void cxl_set_driver_ops(struct cxl_context *ctx, 337b810253bSPhilippe Bergheaud struct cxl_afu_driver_ops *ops) 338b810253bSPhilippe Bergheaud { 339b810253bSPhilippe Bergheaud WARN_ON(!ops->fetch_event || !ops->event_delivered); 340b810253bSPhilippe Bergheaud atomic_set(&ctx->afu_driver_events, 0); 341b810253bSPhilippe Bergheaud ctx->afu_driver_ops = ops; 342b810253bSPhilippe Bergheaud } 343b810253bSPhilippe Bergheaud EXPORT_SYMBOL_GPL(cxl_set_driver_ops); 344b810253bSPhilippe Bergheaud 345b810253bSPhilippe Bergheaud void cxl_context_events_pending(struct cxl_context *ctx, 346b810253bSPhilippe Bergheaud unsigned int new_events) 347b810253bSPhilippe Bergheaud { 348b810253bSPhilippe Bergheaud atomic_add(new_events, &ctx->afu_driver_events); 349b810253bSPhilippe Bergheaud wake_up_all(&ctx->wq); 350b810253bSPhilippe Bergheaud } 351b810253bSPhilippe Bergheaud EXPORT_SYMBOL_GPL(cxl_context_events_pending); 352b810253bSPhilippe Bergheaud 3536f7f0b3dSMichael Neuling int cxl_start_work(struct cxl_context *ctx, 3546f7f0b3dSMichael Neuling struct cxl_ioctl_start_work *work) 3556f7f0b3dSMichael Neuling { 3566f7f0b3dSMichael Neuling int rc; 3576f7f0b3dSMichael Neuling 3586f7f0b3dSMichael Neuling /* code taken from afu_ioctl_start_work */ 3596f7f0b3dSMichael Neuling if (!(work->flags & CXL_START_WORK_NUM_IRQS)) 3606f7f0b3dSMichael Neuling work->num_interrupts = ctx->afu->pp_irqs; 3616f7f0b3dSMichael Neuling else if ((work->num_interrupts < ctx->afu->pp_irqs) || 3626f7f0b3dSMichael Neuling (work->num_interrupts > ctx->afu->irqs_max)) { 3636f7f0b3dSMichael Neuling return -EINVAL; 3646f7f0b3dSMichael Neuling } 3656f7f0b3dSMichael Neuling 3666f7f0b3dSMichael Neuling rc = afu_register_irqs(ctx, work->num_interrupts); 3676f7f0b3dSMichael Neuling if (rc) 3686f7f0b3dSMichael Neuling return rc; 3696f7f0b3dSMichael Neuling 3706f7f0b3dSMichael Neuling rc = cxl_start_context(ctx, work->work_element_descriptor, current); 3716f7f0b3dSMichael Neuling if (rc < 0) { 3726f7f0b3dSMichael Neuling afu_release_irqs(ctx, ctx); 3736f7f0b3dSMichael Neuling return rc; 3746f7f0b3dSMichael Neuling } 3756f7f0b3dSMichael Neuling 3766f7f0b3dSMichael Neuling return 0; 3776f7f0b3dSMichael Neuling } 3786f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_start_work); 3796f7f0b3dSMichael Neuling 3806f7f0b3dSMichael Neuling void __iomem *cxl_psa_map(struct cxl_context *ctx) 3816f7f0b3dSMichael Neuling { 382cca44c01SFrederic Barrat if (ctx->status != STARTED) 3836f7f0b3dSMichael Neuling return NULL; 3846f7f0b3dSMichael Neuling 3856f7f0b3dSMichael Neuling pr_devel("%s: psn_phys%llx size:%llx\n", 386cca44c01SFrederic Barrat __func__, ctx->psn_phys, ctx->psn_size); 3876f7f0b3dSMichael Neuling return ioremap(ctx->psn_phys, ctx->psn_size); 3886f7f0b3dSMichael Neuling } 3896f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_psa_map); 3906f7f0b3dSMichael Neuling 3916f7f0b3dSMichael Neuling void cxl_psa_unmap(void __iomem *addr) 3926f7f0b3dSMichael Neuling { 3936f7f0b3dSMichael Neuling iounmap(addr); 3946f7f0b3dSMichael Neuling } 3956f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_psa_unmap); 3966f7f0b3dSMichael Neuling 3976f7f0b3dSMichael Neuling int cxl_afu_reset(struct cxl_context *ctx) 3986f7f0b3dSMichael Neuling { 3996f7f0b3dSMichael Neuling struct cxl_afu *afu = ctx->afu; 4006f7f0b3dSMichael Neuling int rc; 4016f7f0b3dSMichael Neuling 4025be587b1SFrederic Barrat rc = cxl_ops->afu_reset(afu); 4036f7f0b3dSMichael Neuling if (rc) 4046f7f0b3dSMichael Neuling return rc; 4056f7f0b3dSMichael Neuling 4065be587b1SFrederic Barrat return cxl_ops->afu_check_and_enable(afu); 4076f7f0b3dSMichael Neuling } 4086f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_afu_reset); 40913e68d8bSDaniel Axtens 41013e68d8bSDaniel Axtens void cxl_perst_reloads_same_image(struct cxl_afu *afu, 41113e68d8bSDaniel Axtens bool perst_reloads_same_image) 41213e68d8bSDaniel Axtens { 41313e68d8bSDaniel Axtens afu->adapter->perst_same_image = perst_reloads_same_image; 41413e68d8bSDaniel Axtens } 41513e68d8bSDaniel Axtens EXPORT_SYMBOL_GPL(cxl_perst_reloads_same_image); 416d601ea91SFrederic Barrat 417d601ea91SFrederic Barrat ssize_t cxl_read_adapter_vpd(struct pci_dev *dev, void *buf, size_t count) 418d601ea91SFrederic Barrat { 419d601ea91SFrederic Barrat struct cxl_afu *afu = cxl_pci_to_afu(dev); 420d601ea91SFrederic Barrat 421d601ea91SFrederic Barrat return cxl_ops->read_adapter_vpd(afu->adapter, buf, count); 422d601ea91SFrederic Barrat } 423d601ea91SFrederic Barrat EXPORT_SYMBOL_GPL(cxl_read_adapter_vpd); 424