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 struct device *cxl_get_phys_dev(struct pci_dev *dev) 726f7f0b3dSMichael Neuling { 736f7f0b3dSMichael Neuling struct cxl_afu *afu; 746f7f0b3dSMichael Neuling 756f7f0b3dSMichael Neuling afu = cxl_pci_to_afu(dev); 766f7f0b3dSMichael Neuling 776f7f0b3dSMichael Neuling return afu->adapter->dev.parent; 786f7f0b3dSMichael Neuling } 796f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_get_phys_dev); 806f7f0b3dSMichael Neuling 816f7f0b3dSMichael Neuling int cxl_release_context(struct cxl_context *ctx) 826f7f0b3dSMichael Neuling { 837c26b9cfSAndrew Donnellan if (ctx->status >= STARTED) 846f7f0b3dSMichael Neuling return -EBUSY; 856f7f0b3dSMichael Neuling 866f7f0b3dSMichael Neuling cxl_context_free(ctx); 876f7f0b3dSMichael Neuling 886f7f0b3dSMichael Neuling return 0; 896f7f0b3dSMichael Neuling } 906f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_release_context); 916f7f0b3dSMichael Neuling 926f7f0b3dSMichael Neuling static irq_hw_number_t cxl_find_afu_irq(struct cxl_context *ctx, int num) 936f7f0b3dSMichael Neuling { 946f7f0b3dSMichael Neuling __u16 range; 956f7f0b3dSMichael Neuling int r; 966f7f0b3dSMichael Neuling 976f7f0b3dSMichael Neuling for (r = 0; r < CXL_IRQ_RANGES; r++) { 986f7f0b3dSMichael Neuling range = ctx->irqs.range[r]; 996f7f0b3dSMichael Neuling if (num < range) { 1006f7f0b3dSMichael Neuling return ctx->irqs.offset[r] + num; 1016f7f0b3dSMichael Neuling } 1026f7f0b3dSMichael Neuling num -= range; 1036f7f0b3dSMichael Neuling } 1046f7f0b3dSMichael Neuling return 0; 1056f7f0b3dSMichael Neuling } 1066f7f0b3dSMichael Neuling 107*d601ea91SFrederic Barrat int cxl_allocate_afu_irqs(struct cxl_context *ctx, int num) 108*d601ea91SFrederic Barrat { 109*d601ea91SFrederic Barrat int res; 110*d601ea91SFrederic Barrat irq_hw_number_t hwirq; 111*d601ea91SFrederic Barrat 112*d601ea91SFrederic Barrat if (num == 0) 113*d601ea91SFrederic Barrat num = ctx->afu->pp_irqs; 114*d601ea91SFrederic Barrat res = afu_allocate_irqs(ctx, num); 115*d601ea91SFrederic Barrat if (!res && !cpu_has_feature(CPU_FTR_HVMODE)) { 116*d601ea91SFrederic Barrat /* In a guest, the PSL interrupt is not multiplexed. It was 117*d601ea91SFrederic Barrat * allocated above, and we need to set its handler 118*d601ea91SFrederic Barrat */ 119*d601ea91SFrederic Barrat hwirq = cxl_find_afu_irq(ctx, 0); 120*d601ea91SFrederic Barrat if (hwirq) 121*d601ea91SFrederic Barrat cxl_map_irq(ctx->afu->adapter, hwirq, cxl_ops->psl_interrupt, ctx, "psl"); 122*d601ea91SFrederic Barrat } 123*d601ea91SFrederic Barrat return res; 124*d601ea91SFrederic Barrat } 125*d601ea91SFrederic Barrat EXPORT_SYMBOL_GPL(cxl_allocate_afu_irqs); 126*d601ea91SFrederic Barrat 127*d601ea91SFrederic Barrat void cxl_free_afu_irqs(struct cxl_context *ctx) 128*d601ea91SFrederic Barrat { 129*d601ea91SFrederic Barrat irq_hw_number_t hwirq; 130*d601ea91SFrederic Barrat unsigned int virq; 131*d601ea91SFrederic Barrat 132*d601ea91SFrederic Barrat if (!cpu_has_feature(CPU_FTR_HVMODE)) { 133*d601ea91SFrederic Barrat hwirq = cxl_find_afu_irq(ctx, 0); 134*d601ea91SFrederic Barrat if (hwirq) { 135*d601ea91SFrederic Barrat virq = irq_find_mapping(NULL, hwirq); 136*d601ea91SFrederic Barrat if (virq) 137*d601ea91SFrederic Barrat cxl_unmap_irq(virq, ctx); 138*d601ea91SFrederic Barrat } 139*d601ea91SFrederic Barrat } 140*d601ea91SFrederic Barrat afu_irq_name_free(ctx); 141*d601ea91SFrederic Barrat cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter); 142*d601ea91SFrederic Barrat } 143*d601ea91SFrederic Barrat EXPORT_SYMBOL_GPL(cxl_free_afu_irqs); 144*d601ea91SFrederic 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; 1966f7f0b3dSMichael Neuling } 1976f7f0b3dSMichael Neuling 1986f7f0b3dSMichael Neuling cxl_ctx_get(); 1996f7f0b3dSMichael Neuling 2005be587b1SFrederic Barrat if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) { 2016f7f0b3dSMichael Neuling put_pid(ctx->pid); 2026f7f0b3dSMichael Neuling cxl_ctx_put(); 2036f7f0b3dSMichael Neuling goto out; 2046f7f0b3dSMichael Neuling } 2056f7f0b3dSMichael Neuling 2066f7f0b3dSMichael Neuling ctx->status = STARTED; 2076f7f0b3dSMichael Neuling out: 2086f7f0b3dSMichael Neuling mutex_unlock(&ctx->status_mutex); 2096f7f0b3dSMichael Neuling return rc; 2106f7f0b3dSMichael Neuling } 2116f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_start_context); 2126f7f0b3dSMichael Neuling 2136f7f0b3dSMichael Neuling int cxl_process_element(struct cxl_context *ctx) 2146f7f0b3dSMichael Neuling { 21514baf4d9SChristophe Lombard return ctx->external_pe; 2166f7f0b3dSMichael Neuling } 2176f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_process_element); 2186f7f0b3dSMichael Neuling 2196f7f0b3dSMichael Neuling /* Stop a context. Returns 0 on success, otherwise -Errno */ 2206f7f0b3dSMichael Neuling int cxl_stop_context(struct cxl_context *ctx) 2216f7f0b3dSMichael Neuling { 2223f8dc44dSMichael Neuling return __detach_context(ctx); 2236f7f0b3dSMichael Neuling } 2246f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_stop_context); 2256f7f0b3dSMichael Neuling 2266f7f0b3dSMichael Neuling void cxl_set_master(struct cxl_context *ctx) 2276f7f0b3dSMichael Neuling { 2286f7f0b3dSMichael Neuling ctx->master = true; 2296f7f0b3dSMichael Neuling } 2306f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_set_master); 2316f7f0b3dSMichael Neuling 2326f7f0b3dSMichael Neuling /* wrappers around afu_* file ops which are EXPORTED */ 2336f7f0b3dSMichael Neuling int cxl_fd_open(struct inode *inode, struct file *file) 2346f7f0b3dSMichael Neuling { 2356f7f0b3dSMichael Neuling return afu_open(inode, file); 2366f7f0b3dSMichael Neuling } 2376f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_open); 2386f7f0b3dSMichael Neuling int cxl_fd_release(struct inode *inode, struct file *file) 2396f7f0b3dSMichael Neuling { 2406f7f0b3dSMichael Neuling return afu_release(inode, file); 2416f7f0b3dSMichael Neuling } 2426f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_release); 2436f7f0b3dSMichael Neuling long cxl_fd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 2446f7f0b3dSMichael Neuling { 2456f7f0b3dSMichael Neuling return afu_ioctl(file, cmd, arg); 2466f7f0b3dSMichael Neuling } 2476f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_ioctl); 2486f7f0b3dSMichael Neuling int cxl_fd_mmap(struct file *file, struct vm_area_struct *vm) 2496f7f0b3dSMichael Neuling { 2506f7f0b3dSMichael Neuling return afu_mmap(file, vm); 2516f7f0b3dSMichael Neuling } 2526f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_mmap); 2536f7f0b3dSMichael Neuling unsigned int cxl_fd_poll(struct file *file, struct poll_table_struct *poll) 2546f7f0b3dSMichael Neuling { 2556f7f0b3dSMichael Neuling return afu_poll(file, poll); 2566f7f0b3dSMichael Neuling } 2576f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_poll); 2586f7f0b3dSMichael Neuling ssize_t cxl_fd_read(struct file *file, char __user *buf, size_t count, 2596f7f0b3dSMichael Neuling loff_t *off) 2606f7f0b3dSMichael Neuling { 2616f7f0b3dSMichael Neuling return afu_read(file, buf, count, off); 2626f7f0b3dSMichael Neuling } 2636f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_read); 2646f7f0b3dSMichael Neuling 2656f7f0b3dSMichael Neuling #define PATCH_FOPS(NAME) if (!fops->NAME) fops->NAME = afu_fops.NAME 2666f7f0b3dSMichael Neuling 2676f7f0b3dSMichael Neuling /* Get a struct file and fd for a context and attach the ops */ 2686f7f0b3dSMichael Neuling struct file *cxl_get_fd(struct cxl_context *ctx, struct file_operations *fops, 2696f7f0b3dSMichael Neuling int *fd) 2706f7f0b3dSMichael Neuling { 2716f7f0b3dSMichael Neuling struct file *file; 2726f7f0b3dSMichael Neuling int rc, flags, fdtmp; 2736f7f0b3dSMichael Neuling 2746f7f0b3dSMichael Neuling flags = O_RDWR | O_CLOEXEC; 2756f7f0b3dSMichael Neuling 2766f7f0b3dSMichael Neuling /* This code is similar to anon_inode_getfd() */ 2776f7f0b3dSMichael Neuling rc = get_unused_fd_flags(flags); 2786f7f0b3dSMichael Neuling if (rc < 0) 2796f7f0b3dSMichael Neuling return ERR_PTR(rc); 2806f7f0b3dSMichael Neuling fdtmp = rc; 2816f7f0b3dSMichael Neuling 2826f7f0b3dSMichael Neuling /* 2836f7f0b3dSMichael Neuling * Patch the file ops. Needs to be careful that this is rentrant safe. 2846f7f0b3dSMichael Neuling */ 2856f7f0b3dSMichael Neuling if (fops) { 2866f7f0b3dSMichael Neuling PATCH_FOPS(open); 2876f7f0b3dSMichael Neuling PATCH_FOPS(poll); 2886f7f0b3dSMichael Neuling PATCH_FOPS(read); 2896f7f0b3dSMichael Neuling PATCH_FOPS(release); 2906f7f0b3dSMichael Neuling PATCH_FOPS(unlocked_ioctl); 2916f7f0b3dSMichael Neuling PATCH_FOPS(compat_ioctl); 2926f7f0b3dSMichael Neuling PATCH_FOPS(mmap); 2936f7f0b3dSMichael Neuling } else /* use default ops */ 2946f7f0b3dSMichael Neuling fops = (struct file_operations *)&afu_fops; 2956f7f0b3dSMichael Neuling 2966f7f0b3dSMichael Neuling file = anon_inode_getfile("cxl", fops, ctx, flags); 2976f7f0b3dSMichael Neuling if (IS_ERR(file)) 29855e07668SIan Munsie goto err_fd; 29955e07668SIan Munsie 30055e07668SIan Munsie file->f_mapping = ctx->mapping; 30155e07668SIan Munsie 3026f7f0b3dSMichael Neuling *fd = fdtmp; 3036f7f0b3dSMichael Neuling return file; 30455e07668SIan Munsie 30555e07668SIan Munsie err_fd: 30655e07668SIan Munsie put_unused_fd(fdtmp); 30755e07668SIan Munsie return NULL; 3086f7f0b3dSMichael Neuling } 3096f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_get_fd); 3106f7f0b3dSMichael Neuling 3116f7f0b3dSMichael Neuling struct cxl_context *cxl_fops_get_context(struct file *file) 3126f7f0b3dSMichael Neuling { 3136f7f0b3dSMichael Neuling return file->private_data; 3146f7f0b3dSMichael Neuling } 3156f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fops_get_context); 3166f7f0b3dSMichael Neuling 3176f7f0b3dSMichael Neuling int cxl_start_work(struct cxl_context *ctx, 3186f7f0b3dSMichael Neuling struct cxl_ioctl_start_work *work) 3196f7f0b3dSMichael Neuling { 3206f7f0b3dSMichael Neuling int rc; 3216f7f0b3dSMichael Neuling 3226f7f0b3dSMichael Neuling /* code taken from afu_ioctl_start_work */ 3236f7f0b3dSMichael Neuling if (!(work->flags & CXL_START_WORK_NUM_IRQS)) 3246f7f0b3dSMichael Neuling work->num_interrupts = ctx->afu->pp_irqs; 3256f7f0b3dSMichael Neuling else if ((work->num_interrupts < ctx->afu->pp_irqs) || 3266f7f0b3dSMichael Neuling (work->num_interrupts > ctx->afu->irqs_max)) { 3276f7f0b3dSMichael Neuling return -EINVAL; 3286f7f0b3dSMichael Neuling } 3296f7f0b3dSMichael Neuling 3306f7f0b3dSMichael Neuling rc = afu_register_irqs(ctx, work->num_interrupts); 3316f7f0b3dSMichael Neuling if (rc) 3326f7f0b3dSMichael Neuling return rc; 3336f7f0b3dSMichael Neuling 3346f7f0b3dSMichael Neuling rc = cxl_start_context(ctx, work->work_element_descriptor, current); 3356f7f0b3dSMichael Neuling if (rc < 0) { 3366f7f0b3dSMichael Neuling afu_release_irqs(ctx, ctx); 3376f7f0b3dSMichael Neuling return rc; 3386f7f0b3dSMichael Neuling } 3396f7f0b3dSMichael Neuling 3406f7f0b3dSMichael Neuling return 0; 3416f7f0b3dSMichael Neuling } 3426f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_start_work); 3436f7f0b3dSMichael Neuling 3446f7f0b3dSMichael Neuling void __iomem *cxl_psa_map(struct cxl_context *ctx) 3456f7f0b3dSMichael Neuling { 346cca44c01SFrederic Barrat if (ctx->status != STARTED) 3476f7f0b3dSMichael Neuling return NULL; 3486f7f0b3dSMichael Neuling 3496f7f0b3dSMichael Neuling pr_devel("%s: psn_phys%llx size:%llx\n", 350cca44c01SFrederic Barrat __func__, ctx->psn_phys, ctx->psn_size); 3516f7f0b3dSMichael Neuling return ioremap(ctx->psn_phys, ctx->psn_size); 3526f7f0b3dSMichael Neuling } 3536f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_psa_map); 3546f7f0b3dSMichael Neuling 3556f7f0b3dSMichael Neuling void cxl_psa_unmap(void __iomem *addr) 3566f7f0b3dSMichael Neuling { 3576f7f0b3dSMichael Neuling iounmap(addr); 3586f7f0b3dSMichael Neuling } 3596f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_psa_unmap); 3606f7f0b3dSMichael Neuling 3616f7f0b3dSMichael Neuling int cxl_afu_reset(struct cxl_context *ctx) 3626f7f0b3dSMichael Neuling { 3636f7f0b3dSMichael Neuling struct cxl_afu *afu = ctx->afu; 3646f7f0b3dSMichael Neuling int rc; 3656f7f0b3dSMichael Neuling 3665be587b1SFrederic Barrat rc = cxl_ops->afu_reset(afu); 3676f7f0b3dSMichael Neuling if (rc) 3686f7f0b3dSMichael Neuling return rc; 3696f7f0b3dSMichael Neuling 3705be587b1SFrederic Barrat return cxl_ops->afu_check_and_enable(afu); 3716f7f0b3dSMichael Neuling } 3726f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_afu_reset); 37313e68d8bSDaniel Axtens 37413e68d8bSDaniel Axtens void cxl_perst_reloads_same_image(struct cxl_afu *afu, 37513e68d8bSDaniel Axtens bool perst_reloads_same_image) 37613e68d8bSDaniel Axtens { 37713e68d8bSDaniel Axtens afu->adapter->perst_same_image = perst_reloads_same_image; 37813e68d8bSDaniel Axtens } 37913e68d8bSDaniel Axtens EXPORT_SYMBOL_GPL(cxl_perst_reloads_same_image); 380*d601ea91SFrederic Barrat 381*d601ea91SFrederic Barrat ssize_t cxl_read_adapter_vpd(struct pci_dev *dev, void *buf, size_t count) 382*d601ea91SFrederic Barrat { 383*d601ea91SFrederic Barrat struct cxl_afu *afu = cxl_pci_to_afu(dev); 384*d601ea91SFrederic Barrat 385*d601ea91SFrederic Barrat return cxl_ops->read_adapter_vpd(afu->adapter, buf, count); 386*d601ea91SFrederic Barrat } 387*d601ea91SFrederic Barrat EXPORT_SYMBOL_GPL(cxl_read_adapter_vpd); 388