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 283f8dc44dSMichael Neuling get_device(&afu->dev); 296f7f0b3dSMichael Neuling ctx = cxl_context_alloc(); 30af2a50bbSIan Munsie if (IS_ERR(ctx)) { 31af2a50bbSIan Munsie rc = PTR_ERR(ctx); 32af2a50bbSIan Munsie goto err_dev; 33af2a50bbSIan Munsie } 346f7f0b3dSMichael Neuling 3555e07668SIan Munsie ctx->kernelapi = true; 3655e07668SIan Munsie 3755e07668SIan Munsie /* 3855e07668SIan Munsie * Make our own address space since we won't have one from the 3955e07668SIan Munsie * filesystem like the user api has, and even if we do associate a file 4055e07668SIan Munsie * with this context we don't want to use the global anonymous inode's 4155e07668SIan Munsie * address space as that can invalidate unrelated users: 4255e07668SIan Munsie */ 4355e07668SIan Munsie mapping = kmalloc(sizeof(struct address_space), GFP_KERNEL); 4455e07668SIan Munsie if (!mapping) { 4555e07668SIan Munsie rc = -ENOMEM; 46af2a50bbSIan Munsie goto err_ctx; 4755e07668SIan Munsie } 4855e07668SIan Munsie address_space_init_once(mapping); 4955e07668SIan Munsie 5055e07668SIan Munsie /* Make it a slave context. We can promote it later? */ 5155e07668SIan Munsie rc = cxl_context_init(ctx, afu, false, mapping); 5255e07668SIan Munsie if (rc) 5355e07668SIan Munsie goto err_mapping; 5455e07668SIan Munsie 556f7f0b3dSMichael Neuling cxl_assign_psn_space(ctx); 566f7f0b3dSMichael Neuling 576f7f0b3dSMichael Neuling return ctx; 58af2a50bbSIan Munsie 5955e07668SIan Munsie err_mapping: 6055e07668SIan Munsie kfree(mapping); 61af2a50bbSIan Munsie err_ctx: 62af2a50bbSIan Munsie kfree(ctx); 63af2a50bbSIan Munsie err_dev: 64af2a50bbSIan Munsie put_device(&afu->dev); 65af2a50bbSIan Munsie return ERR_PTR(rc); 666f7f0b3dSMichael Neuling } 676f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_dev_context_init); 686f7f0b3dSMichael Neuling 696f7f0b3dSMichael Neuling struct cxl_context *cxl_get_context(struct pci_dev *dev) 706f7f0b3dSMichael Neuling { 716f7f0b3dSMichael Neuling return dev->dev.archdata.cxl_ctx; 726f7f0b3dSMichael Neuling } 736f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_get_context); 746f7f0b3dSMichael Neuling 756f7f0b3dSMichael Neuling struct device *cxl_get_phys_dev(struct pci_dev *dev) 766f7f0b3dSMichael Neuling { 776f7f0b3dSMichael Neuling struct cxl_afu *afu; 786f7f0b3dSMichael Neuling 796f7f0b3dSMichael Neuling afu = cxl_pci_to_afu(dev); 806f7f0b3dSMichael Neuling 816f7f0b3dSMichael Neuling return afu->adapter->dev.parent; 826f7f0b3dSMichael Neuling } 836f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_get_phys_dev); 846f7f0b3dSMichael Neuling 856f7f0b3dSMichael Neuling int cxl_release_context(struct cxl_context *ctx) 866f7f0b3dSMichael Neuling { 877c26b9cfSAndrew Donnellan if (ctx->status >= STARTED) 886f7f0b3dSMichael Neuling return -EBUSY; 896f7f0b3dSMichael Neuling 903f8dc44dSMichael Neuling put_device(&ctx->afu->dev); 913f8dc44dSMichael Neuling 926f7f0b3dSMichael Neuling cxl_context_free(ctx); 936f7f0b3dSMichael Neuling 946f7f0b3dSMichael Neuling return 0; 956f7f0b3dSMichael Neuling } 966f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_release_context); 976f7f0b3dSMichael Neuling 986f7f0b3dSMichael Neuling int cxl_allocate_afu_irqs(struct cxl_context *ctx, int num) 996f7f0b3dSMichael Neuling { 1006f7f0b3dSMichael Neuling if (num == 0) 1016f7f0b3dSMichael Neuling num = ctx->afu->pp_irqs; 1026f7f0b3dSMichael Neuling return afu_allocate_irqs(ctx, num); 1036f7f0b3dSMichael Neuling } 1046f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_allocate_afu_irqs); 1056f7f0b3dSMichael Neuling 1066f7f0b3dSMichael Neuling void cxl_free_afu_irqs(struct cxl_context *ctx) 1076f7f0b3dSMichael Neuling { 108*8dde152eSAndrew Donnellan afu_irq_name_free(ctx); 1096f7f0b3dSMichael Neuling cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter); 1106f7f0b3dSMichael Neuling } 1116f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_free_afu_irqs); 1126f7f0b3dSMichael Neuling 1136f7f0b3dSMichael Neuling static irq_hw_number_t cxl_find_afu_irq(struct cxl_context *ctx, int num) 1146f7f0b3dSMichael Neuling { 1156f7f0b3dSMichael Neuling __u16 range; 1166f7f0b3dSMichael Neuling int r; 1176f7f0b3dSMichael Neuling 1186f7f0b3dSMichael Neuling WARN_ON(num == 0); 1196f7f0b3dSMichael Neuling 1206f7f0b3dSMichael Neuling for (r = 0; r < CXL_IRQ_RANGES; r++) { 1216f7f0b3dSMichael Neuling range = ctx->irqs.range[r]; 1226f7f0b3dSMichael Neuling if (num < range) { 1236f7f0b3dSMichael Neuling return ctx->irqs.offset[r] + num; 1246f7f0b3dSMichael Neuling } 1256f7f0b3dSMichael Neuling num -= range; 1266f7f0b3dSMichael Neuling } 1276f7f0b3dSMichael Neuling return 0; 1286f7f0b3dSMichael Neuling } 1296f7f0b3dSMichael Neuling 1306f7f0b3dSMichael Neuling int cxl_map_afu_irq(struct cxl_context *ctx, int num, 1316f7f0b3dSMichael Neuling irq_handler_t handler, void *cookie, char *name) 1326f7f0b3dSMichael Neuling { 1336f7f0b3dSMichael Neuling irq_hw_number_t hwirq; 1346f7f0b3dSMichael Neuling 1356f7f0b3dSMichael Neuling /* 1366f7f0b3dSMichael Neuling * Find interrupt we are to register. 1376f7f0b3dSMichael Neuling */ 1386f7f0b3dSMichael Neuling hwirq = cxl_find_afu_irq(ctx, num); 1396f7f0b3dSMichael Neuling if (!hwirq) 1406f7f0b3dSMichael Neuling return -ENOENT; 1416f7f0b3dSMichael Neuling 1426f7f0b3dSMichael Neuling return cxl_map_irq(ctx->afu->adapter, hwirq, handler, cookie, name); 1436f7f0b3dSMichael Neuling } 1446f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_map_afu_irq); 1456f7f0b3dSMichael Neuling 1466f7f0b3dSMichael Neuling void cxl_unmap_afu_irq(struct cxl_context *ctx, int num, void *cookie) 1476f7f0b3dSMichael Neuling { 1486f7f0b3dSMichael Neuling irq_hw_number_t hwirq; 1496f7f0b3dSMichael Neuling unsigned int virq; 1506f7f0b3dSMichael Neuling 1516f7f0b3dSMichael Neuling hwirq = cxl_find_afu_irq(ctx, num); 1526f7f0b3dSMichael Neuling if (!hwirq) 1536f7f0b3dSMichael Neuling return; 1546f7f0b3dSMichael Neuling 1556f7f0b3dSMichael Neuling virq = irq_find_mapping(NULL, hwirq); 1566f7f0b3dSMichael Neuling if (virq) 1576f7f0b3dSMichael Neuling cxl_unmap_irq(virq, cookie); 1586f7f0b3dSMichael Neuling } 1596f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_unmap_afu_irq); 1606f7f0b3dSMichael Neuling 1616f7f0b3dSMichael Neuling /* 1626f7f0b3dSMichael Neuling * Start a context 1636f7f0b3dSMichael Neuling * Code here similar to afu_ioctl_start_work(). 1646f7f0b3dSMichael Neuling */ 1656f7f0b3dSMichael Neuling int cxl_start_context(struct cxl_context *ctx, u64 wed, 1666f7f0b3dSMichael Neuling struct task_struct *task) 1676f7f0b3dSMichael Neuling { 1686f7f0b3dSMichael Neuling int rc = 0; 1696f7f0b3dSMichael Neuling bool kernel = true; 1706f7f0b3dSMichael Neuling 1716f7f0b3dSMichael Neuling pr_devel("%s: pe: %i\n", __func__, ctx->pe); 1726f7f0b3dSMichael Neuling 1736f7f0b3dSMichael Neuling mutex_lock(&ctx->status_mutex); 1746f7f0b3dSMichael Neuling if (ctx->status == STARTED) 1756f7f0b3dSMichael Neuling goto out; /* already started */ 1766f7f0b3dSMichael Neuling 1776f7f0b3dSMichael Neuling if (task) { 1786f7f0b3dSMichael Neuling ctx->pid = get_task_pid(task, PIDTYPE_PID); 1796f7f0b3dSMichael Neuling get_pid(ctx->pid); 1806f7f0b3dSMichael Neuling kernel = false; 1816f7f0b3dSMichael Neuling } 1826f7f0b3dSMichael Neuling 1836f7f0b3dSMichael Neuling cxl_ctx_get(); 1846f7f0b3dSMichael Neuling 1856f7f0b3dSMichael Neuling if ((rc = cxl_attach_process(ctx, kernel, wed , 0))) { 1866f7f0b3dSMichael Neuling put_pid(ctx->pid); 1876f7f0b3dSMichael Neuling cxl_ctx_put(); 1886f7f0b3dSMichael Neuling goto out; 1896f7f0b3dSMichael Neuling } 1906f7f0b3dSMichael Neuling 1916f7f0b3dSMichael Neuling ctx->status = STARTED; 1926f7f0b3dSMichael Neuling out: 1936f7f0b3dSMichael Neuling mutex_unlock(&ctx->status_mutex); 1946f7f0b3dSMichael Neuling return rc; 1956f7f0b3dSMichael Neuling } 1966f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_start_context); 1976f7f0b3dSMichael Neuling 1986f7f0b3dSMichael Neuling int cxl_process_element(struct cxl_context *ctx) 1996f7f0b3dSMichael Neuling { 2006f7f0b3dSMichael Neuling return ctx->pe; 2016f7f0b3dSMichael Neuling } 2026f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_process_element); 2036f7f0b3dSMichael Neuling 2046f7f0b3dSMichael Neuling /* Stop a context. Returns 0 on success, otherwise -Errno */ 2056f7f0b3dSMichael Neuling int cxl_stop_context(struct cxl_context *ctx) 2066f7f0b3dSMichael Neuling { 2073f8dc44dSMichael Neuling return __detach_context(ctx); 2086f7f0b3dSMichael Neuling } 2096f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_stop_context); 2106f7f0b3dSMichael Neuling 2116f7f0b3dSMichael Neuling void cxl_set_master(struct cxl_context *ctx) 2126f7f0b3dSMichael Neuling { 2136f7f0b3dSMichael Neuling ctx->master = true; 2146f7f0b3dSMichael Neuling cxl_assign_psn_space(ctx); 2156f7f0b3dSMichael Neuling } 2166f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_set_master); 2176f7f0b3dSMichael Neuling 2186f7f0b3dSMichael Neuling /* wrappers around afu_* file ops which are EXPORTED */ 2196f7f0b3dSMichael Neuling int cxl_fd_open(struct inode *inode, struct file *file) 2206f7f0b3dSMichael Neuling { 2216f7f0b3dSMichael Neuling return afu_open(inode, file); 2226f7f0b3dSMichael Neuling } 2236f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_open); 2246f7f0b3dSMichael Neuling int cxl_fd_release(struct inode *inode, struct file *file) 2256f7f0b3dSMichael Neuling { 2266f7f0b3dSMichael Neuling return afu_release(inode, file); 2276f7f0b3dSMichael Neuling } 2286f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_release); 2296f7f0b3dSMichael Neuling long cxl_fd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 2306f7f0b3dSMichael Neuling { 2316f7f0b3dSMichael Neuling return afu_ioctl(file, cmd, arg); 2326f7f0b3dSMichael Neuling } 2336f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_ioctl); 2346f7f0b3dSMichael Neuling int cxl_fd_mmap(struct file *file, struct vm_area_struct *vm) 2356f7f0b3dSMichael Neuling { 2366f7f0b3dSMichael Neuling return afu_mmap(file, vm); 2376f7f0b3dSMichael Neuling } 2386f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_mmap); 2396f7f0b3dSMichael Neuling unsigned int cxl_fd_poll(struct file *file, struct poll_table_struct *poll) 2406f7f0b3dSMichael Neuling { 2416f7f0b3dSMichael Neuling return afu_poll(file, poll); 2426f7f0b3dSMichael Neuling } 2436f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_poll); 2446f7f0b3dSMichael Neuling ssize_t cxl_fd_read(struct file *file, char __user *buf, size_t count, 2456f7f0b3dSMichael Neuling loff_t *off) 2466f7f0b3dSMichael Neuling { 2476f7f0b3dSMichael Neuling return afu_read(file, buf, count, off); 2486f7f0b3dSMichael Neuling } 2496f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_read); 2506f7f0b3dSMichael Neuling 2516f7f0b3dSMichael Neuling #define PATCH_FOPS(NAME) if (!fops->NAME) fops->NAME = afu_fops.NAME 2526f7f0b3dSMichael Neuling 2536f7f0b3dSMichael Neuling /* Get a struct file and fd for a context and attach the ops */ 2546f7f0b3dSMichael Neuling struct file *cxl_get_fd(struct cxl_context *ctx, struct file_operations *fops, 2556f7f0b3dSMichael Neuling int *fd) 2566f7f0b3dSMichael Neuling { 2576f7f0b3dSMichael Neuling struct file *file; 2586f7f0b3dSMichael Neuling int rc, flags, fdtmp; 2596f7f0b3dSMichael Neuling 2606f7f0b3dSMichael Neuling flags = O_RDWR | O_CLOEXEC; 2616f7f0b3dSMichael Neuling 2626f7f0b3dSMichael Neuling /* This code is similar to anon_inode_getfd() */ 2636f7f0b3dSMichael Neuling rc = get_unused_fd_flags(flags); 2646f7f0b3dSMichael Neuling if (rc < 0) 2656f7f0b3dSMichael Neuling return ERR_PTR(rc); 2666f7f0b3dSMichael Neuling fdtmp = rc; 2676f7f0b3dSMichael Neuling 2686f7f0b3dSMichael Neuling /* 2696f7f0b3dSMichael Neuling * Patch the file ops. Needs to be careful that this is rentrant safe. 2706f7f0b3dSMichael Neuling */ 2716f7f0b3dSMichael Neuling if (fops) { 2726f7f0b3dSMichael Neuling PATCH_FOPS(open); 2736f7f0b3dSMichael Neuling PATCH_FOPS(poll); 2746f7f0b3dSMichael Neuling PATCH_FOPS(read); 2756f7f0b3dSMichael Neuling PATCH_FOPS(release); 2766f7f0b3dSMichael Neuling PATCH_FOPS(unlocked_ioctl); 2776f7f0b3dSMichael Neuling PATCH_FOPS(compat_ioctl); 2786f7f0b3dSMichael Neuling PATCH_FOPS(mmap); 2796f7f0b3dSMichael Neuling } else /* use default ops */ 2806f7f0b3dSMichael Neuling fops = (struct file_operations *)&afu_fops; 2816f7f0b3dSMichael Neuling 2826f7f0b3dSMichael Neuling file = anon_inode_getfile("cxl", fops, ctx, flags); 2836f7f0b3dSMichael Neuling if (IS_ERR(file)) 28455e07668SIan Munsie goto err_fd; 28555e07668SIan Munsie 28655e07668SIan Munsie file->f_mapping = ctx->mapping; 28755e07668SIan Munsie 2886f7f0b3dSMichael Neuling *fd = fdtmp; 2896f7f0b3dSMichael Neuling return file; 29055e07668SIan Munsie 29155e07668SIan Munsie err_fd: 29255e07668SIan Munsie put_unused_fd(fdtmp); 29355e07668SIan Munsie return NULL; 2946f7f0b3dSMichael Neuling } 2956f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_get_fd); 2966f7f0b3dSMichael Neuling 2976f7f0b3dSMichael Neuling struct cxl_context *cxl_fops_get_context(struct file *file) 2986f7f0b3dSMichael Neuling { 2996f7f0b3dSMichael Neuling return file->private_data; 3006f7f0b3dSMichael Neuling } 3016f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fops_get_context); 3026f7f0b3dSMichael Neuling 3036f7f0b3dSMichael Neuling int cxl_start_work(struct cxl_context *ctx, 3046f7f0b3dSMichael Neuling struct cxl_ioctl_start_work *work) 3056f7f0b3dSMichael Neuling { 3066f7f0b3dSMichael Neuling int rc; 3076f7f0b3dSMichael Neuling 3086f7f0b3dSMichael Neuling /* code taken from afu_ioctl_start_work */ 3096f7f0b3dSMichael Neuling if (!(work->flags & CXL_START_WORK_NUM_IRQS)) 3106f7f0b3dSMichael Neuling work->num_interrupts = ctx->afu->pp_irqs; 3116f7f0b3dSMichael Neuling else if ((work->num_interrupts < ctx->afu->pp_irqs) || 3126f7f0b3dSMichael Neuling (work->num_interrupts > ctx->afu->irqs_max)) { 3136f7f0b3dSMichael Neuling return -EINVAL; 3146f7f0b3dSMichael Neuling } 3156f7f0b3dSMichael Neuling 3166f7f0b3dSMichael Neuling rc = afu_register_irqs(ctx, work->num_interrupts); 3176f7f0b3dSMichael Neuling if (rc) 3186f7f0b3dSMichael Neuling return rc; 3196f7f0b3dSMichael Neuling 3206f7f0b3dSMichael Neuling rc = cxl_start_context(ctx, work->work_element_descriptor, current); 3216f7f0b3dSMichael Neuling if (rc < 0) { 3226f7f0b3dSMichael Neuling afu_release_irqs(ctx, ctx); 3236f7f0b3dSMichael Neuling return rc; 3246f7f0b3dSMichael Neuling } 3256f7f0b3dSMichael Neuling 3266f7f0b3dSMichael Neuling return 0; 3276f7f0b3dSMichael Neuling } 3286f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_start_work); 3296f7f0b3dSMichael Neuling 3306f7f0b3dSMichael Neuling void __iomem *cxl_psa_map(struct cxl_context *ctx) 3316f7f0b3dSMichael Neuling { 3326f7f0b3dSMichael Neuling struct cxl_afu *afu = ctx->afu; 3336f7f0b3dSMichael Neuling int rc; 3346f7f0b3dSMichael Neuling 3356f7f0b3dSMichael Neuling rc = cxl_afu_check_and_enable(afu); 3366f7f0b3dSMichael Neuling if (rc) 3376f7f0b3dSMichael Neuling return NULL; 3386f7f0b3dSMichael Neuling 3396f7f0b3dSMichael Neuling pr_devel("%s: psn_phys%llx size:%llx\n", 3406f7f0b3dSMichael Neuling __func__, afu->psn_phys, afu->adapter->ps_size); 3416f7f0b3dSMichael Neuling return ioremap(ctx->psn_phys, ctx->psn_size); 3426f7f0b3dSMichael Neuling } 3436f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_psa_map); 3446f7f0b3dSMichael Neuling 3456f7f0b3dSMichael Neuling void cxl_psa_unmap(void __iomem *addr) 3466f7f0b3dSMichael Neuling { 3476f7f0b3dSMichael Neuling iounmap(addr); 3486f7f0b3dSMichael Neuling } 3496f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_psa_unmap); 3506f7f0b3dSMichael Neuling 3516f7f0b3dSMichael Neuling int cxl_afu_reset(struct cxl_context *ctx) 3526f7f0b3dSMichael Neuling { 3536f7f0b3dSMichael Neuling struct cxl_afu *afu = ctx->afu; 3546f7f0b3dSMichael Neuling int rc; 3556f7f0b3dSMichael Neuling 3566f7f0b3dSMichael Neuling rc = __cxl_afu_reset(afu); 3576f7f0b3dSMichael Neuling if (rc) 3586f7f0b3dSMichael Neuling return rc; 3596f7f0b3dSMichael Neuling 3606f7f0b3dSMichael Neuling return cxl_afu_check_and_enable(afu); 3616f7f0b3dSMichael Neuling } 3626f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_afu_reset); 36313e68d8bSDaniel Axtens 36413e68d8bSDaniel Axtens void cxl_perst_reloads_same_image(struct cxl_afu *afu, 36513e68d8bSDaniel Axtens bool perst_reloads_same_image) 36613e68d8bSDaniel Axtens { 36713e68d8bSDaniel Axtens afu->adapter->perst_same_image = perst_reloads_same_image; 36813e68d8bSDaniel Axtens } 36913e68d8bSDaniel Axtens EXPORT_SYMBOL_GPL(cxl_perst_reloads_same_image); 370