xref: /openbmc/linux/drivers/misc/cxl/api.c (revision 14baf4d9)
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 int cxl_allocate_afu_irqs(struct cxl_context *ctx, int num)
936f7f0b3dSMichael Neuling {
946f7f0b3dSMichael Neuling 	if (num == 0)
956f7f0b3dSMichael Neuling 		num = ctx->afu->pp_irqs;
966f7f0b3dSMichael Neuling 	return afu_allocate_irqs(ctx, num);
976f7f0b3dSMichael Neuling }
986f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_allocate_afu_irqs);
996f7f0b3dSMichael Neuling 
1006f7f0b3dSMichael Neuling void cxl_free_afu_irqs(struct cxl_context *ctx)
1016f7f0b3dSMichael Neuling {
1028dde152eSAndrew Donnellan 	afu_irq_name_free(ctx);
1035be587b1SFrederic Barrat 	cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
1046f7f0b3dSMichael Neuling }
1056f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_free_afu_irqs);
1066f7f0b3dSMichael Neuling 
1076f7f0b3dSMichael Neuling static irq_hw_number_t cxl_find_afu_irq(struct cxl_context *ctx, int num)
1086f7f0b3dSMichael Neuling {
1096f7f0b3dSMichael Neuling 	__u16 range;
1106f7f0b3dSMichael Neuling 	int r;
1116f7f0b3dSMichael Neuling 
1126f7f0b3dSMichael Neuling 	WARN_ON(num == 0);
1136f7f0b3dSMichael Neuling 
1146f7f0b3dSMichael Neuling 	for (r = 0; r < CXL_IRQ_RANGES; r++) {
1156f7f0b3dSMichael Neuling 		range = ctx->irqs.range[r];
1166f7f0b3dSMichael Neuling 		if (num < range) {
1176f7f0b3dSMichael Neuling 			return ctx->irqs.offset[r] + num;
1186f7f0b3dSMichael Neuling 		}
1196f7f0b3dSMichael Neuling 		num -= range;
1206f7f0b3dSMichael Neuling 	}
1216f7f0b3dSMichael Neuling 	return 0;
1226f7f0b3dSMichael Neuling }
1236f7f0b3dSMichael Neuling 
1246f7f0b3dSMichael Neuling int cxl_map_afu_irq(struct cxl_context *ctx, int num,
1256f7f0b3dSMichael Neuling 		    irq_handler_t handler, void *cookie, char *name)
1266f7f0b3dSMichael Neuling {
1276f7f0b3dSMichael Neuling 	irq_hw_number_t hwirq;
1286f7f0b3dSMichael Neuling 
1296f7f0b3dSMichael Neuling 	/*
1306f7f0b3dSMichael Neuling 	 * Find interrupt we are to register.
1316f7f0b3dSMichael Neuling 	 */
1326f7f0b3dSMichael Neuling 	hwirq = cxl_find_afu_irq(ctx, num);
1336f7f0b3dSMichael Neuling 	if (!hwirq)
1346f7f0b3dSMichael Neuling 		return -ENOENT;
1356f7f0b3dSMichael Neuling 
1366f7f0b3dSMichael Neuling 	return cxl_map_irq(ctx->afu->adapter, hwirq, handler, cookie, name);
1376f7f0b3dSMichael Neuling }
1386f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_map_afu_irq);
1396f7f0b3dSMichael Neuling 
1406f7f0b3dSMichael Neuling void cxl_unmap_afu_irq(struct cxl_context *ctx, int num, void *cookie)
1416f7f0b3dSMichael Neuling {
1426f7f0b3dSMichael Neuling 	irq_hw_number_t hwirq;
1436f7f0b3dSMichael Neuling 	unsigned int virq;
1446f7f0b3dSMichael Neuling 
1456f7f0b3dSMichael Neuling 	hwirq = cxl_find_afu_irq(ctx, num);
1466f7f0b3dSMichael Neuling 	if (!hwirq)
1476f7f0b3dSMichael Neuling 		return;
1486f7f0b3dSMichael Neuling 
1496f7f0b3dSMichael Neuling 	virq = irq_find_mapping(NULL, hwirq);
1506f7f0b3dSMichael Neuling 	if (virq)
1516f7f0b3dSMichael Neuling 		cxl_unmap_irq(virq, cookie);
1526f7f0b3dSMichael Neuling }
1536f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_unmap_afu_irq);
1546f7f0b3dSMichael Neuling 
1556f7f0b3dSMichael Neuling /*
1566f7f0b3dSMichael Neuling  * Start a context
1576f7f0b3dSMichael Neuling  * Code here similar to afu_ioctl_start_work().
1586f7f0b3dSMichael Neuling  */
1596f7f0b3dSMichael Neuling int cxl_start_context(struct cxl_context *ctx, u64 wed,
1606f7f0b3dSMichael Neuling 		      struct task_struct *task)
1616f7f0b3dSMichael Neuling {
1626f7f0b3dSMichael Neuling 	int rc = 0;
1636f7f0b3dSMichael Neuling 	bool kernel = true;
1646f7f0b3dSMichael Neuling 
1656f7f0b3dSMichael Neuling 	pr_devel("%s: pe: %i\n", __func__, ctx->pe);
1666f7f0b3dSMichael Neuling 
1676f7f0b3dSMichael Neuling 	mutex_lock(&ctx->status_mutex);
1686f7f0b3dSMichael Neuling 	if (ctx->status == STARTED)
1696f7f0b3dSMichael Neuling 		goto out; /* already started */
1706f7f0b3dSMichael Neuling 
1716f7f0b3dSMichael Neuling 	if (task) {
1726f7f0b3dSMichael Neuling 		ctx->pid = get_task_pid(task, PIDTYPE_PID);
1737b8ad495SVaibhav Jain 		ctx->glpid = get_task_pid(task->group_leader, PIDTYPE_PID);
1746f7f0b3dSMichael Neuling 		kernel = false;
1756f7f0b3dSMichael Neuling 	}
1766f7f0b3dSMichael Neuling 
1776f7f0b3dSMichael Neuling 	cxl_ctx_get();
1786f7f0b3dSMichael Neuling 
1795be587b1SFrederic Barrat 	if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) {
1806f7f0b3dSMichael Neuling 		put_pid(ctx->pid);
1816f7f0b3dSMichael Neuling 		cxl_ctx_put();
1826f7f0b3dSMichael Neuling 		goto out;
1836f7f0b3dSMichael Neuling 	}
1846f7f0b3dSMichael Neuling 
1856f7f0b3dSMichael Neuling 	ctx->status = STARTED;
1866f7f0b3dSMichael Neuling out:
1876f7f0b3dSMichael Neuling 	mutex_unlock(&ctx->status_mutex);
1886f7f0b3dSMichael Neuling 	return rc;
1896f7f0b3dSMichael Neuling }
1906f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_start_context);
1916f7f0b3dSMichael Neuling 
1926f7f0b3dSMichael Neuling int cxl_process_element(struct cxl_context *ctx)
1936f7f0b3dSMichael Neuling {
19414baf4d9SChristophe Lombard 	return ctx->external_pe;
1956f7f0b3dSMichael Neuling }
1966f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_process_element);
1976f7f0b3dSMichael Neuling 
1986f7f0b3dSMichael Neuling /* Stop a context.  Returns 0 on success, otherwise -Errno */
1996f7f0b3dSMichael Neuling int cxl_stop_context(struct cxl_context *ctx)
2006f7f0b3dSMichael Neuling {
2013f8dc44dSMichael Neuling 	return __detach_context(ctx);
2026f7f0b3dSMichael Neuling }
2036f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_stop_context);
2046f7f0b3dSMichael Neuling 
2056f7f0b3dSMichael Neuling void cxl_set_master(struct cxl_context *ctx)
2066f7f0b3dSMichael Neuling {
2076f7f0b3dSMichael Neuling 	ctx->master = true;
2086f7f0b3dSMichael Neuling }
2096f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_set_master);
2106f7f0b3dSMichael Neuling 
2116f7f0b3dSMichael Neuling /* wrappers around afu_* file ops which are EXPORTED */
2126f7f0b3dSMichael Neuling int cxl_fd_open(struct inode *inode, struct file *file)
2136f7f0b3dSMichael Neuling {
2146f7f0b3dSMichael Neuling 	return afu_open(inode, file);
2156f7f0b3dSMichael Neuling }
2166f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_open);
2176f7f0b3dSMichael Neuling int cxl_fd_release(struct inode *inode, struct file *file)
2186f7f0b3dSMichael Neuling {
2196f7f0b3dSMichael Neuling 	return afu_release(inode, file);
2206f7f0b3dSMichael Neuling }
2216f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_release);
2226f7f0b3dSMichael Neuling long cxl_fd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2236f7f0b3dSMichael Neuling {
2246f7f0b3dSMichael Neuling 	return afu_ioctl(file, cmd, arg);
2256f7f0b3dSMichael Neuling }
2266f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_ioctl);
2276f7f0b3dSMichael Neuling int cxl_fd_mmap(struct file *file, struct vm_area_struct *vm)
2286f7f0b3dSMichael Neuling {
2296f7f0b3dSMichael Neuling 	return afu_mmap(file, vm);
2306f7f0b3dSMichael Neuling }
2316f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_mmap);
2326f7f0b3dSMichael Neuling unsigned int cxl_fd_poll(struct file *file, struct poll_table_struct *poll)
2336f7f0b3dSMichael Neuling {
2346f7f0b3dSMichael Neuling 	return afu_poll(file, poll);
2356f7f0b3dSMichael Neuling }
2366f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_poll);
2376f7f0b3dSMichael Neuling ssize_t cxl_fd_read(struct file *file, char __user *buf, size_t count,
2386f7f0b3dSMichael Neuling 			loff_t *off)
2396f7f0b3dSMichael Neuling {
2406f7f0b3dSMichael Neuling 	return afu_read(file, buf, count, off);
2416f7f0b3dSMichael Neuling }
2426f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fd_read);
2436f7f0b3dSMichael Neuling 
2446f7f0b3dSMichael Neuling #define PATCH_FOPS(NAME) if (!fops->NAME) fops->NAME = afu_fops.NAME
2456f7f0b3dSMichael Neuling 
2466f7f0b3dSMichael Neuling /* Get a struct file and fd for a context and attach the ops */
2476f7f0b3dSMichael Neuling struct file *cxl_get_fd(struct cxl_context *ctx, struct file_operations *fops,
2486f7f0b3dSMichael Neuling 			int *fd)
2496f7f0b3dSMichael Neuling {
2506f7f0b3dSMichael Neuling 	struct file *file;
2516f7f0b3dSMichael Neuling 	int rc, flags, fdtmp;
2526f7f0b3dSMichael Neuling 
2536f7f0b3dSMichael Neuling 	flags = O_RDWR | O_CLOEXEC;
2546f7f0b3dSMichael Neuling 
2556f7f0b3dSMichael Neuling 	/* This code is similar to anon_inode_getfd() */
2566f7f0b3dSMichael Neuling 	rc = get_unused_fd_flags(flags);
2576f7f0b3dSMichael Neuling 	if (rc < 0)
2586f7f0b3dSMichael Neuling 		return ERR_PTR(rc);
2596f7f0b3dSMichael Neuling 	fdtmp = rc;
2606f7f0b3dSMichael Neuling 
2616f7f0b3dSMichael Neuling 	/*
2626f7f0b3dSMichael Neuling 	 * Patch the file ops.  Needs to be careful that this is rentrant safe.
2636f7f0b3dSMichael Neuling 	 */
2646f7f0b3dSMichael Neuling 	if (fops) {
2656f7f0b3dSMichael Neuling 		PATCH_FOPS(open);
2666f7f0b3dSMichael Neuling 		PATCH_FOPS(poll);
2676f7f0b3dSMichael Neuling 		PATCH_FOPS(read);
2686f7f0b3dSMichael Neuling 		PATCH_FOPS(release);
2696f7f0b3dSMichael Neuling 		PATCH_FOPS(unlocked_ioctl);
2706f7f0b3dSMichael Neuling 		PATCH_FOPS(compat_ioctl);
2716f7f0b3dSMichael Neuling 		PATCH_FOPS(mmap);
2726f7f0b3dSMichael Neuling 	} else /* use default ops */
2736f7f0b3dSMichael Neuling 		fops = (struct file_operations *)&afu_fops;
2746f7f0b3dSMichael Neuling 
2756f7f0b3dSMichael Neuling 	file = anon_inode_getfile("cxl", fops, ctx, flags);
2766f7f0b3dSMichael Neuling 	if (IS_ERR(file))
27755e07668SIan Munsie 		goto err_fd;
27855e07668SIan Munsie 
27955e07668SIan Munsie 	file->f_mapping = ctx->mapping;
28055e07668SIan Munsie 
2816f7f0b3dSMichael Neuling 	*fd = fdtmp;
2826f7f0b3dSMichael Neuling 	return file;
28355e07668SIan Munsie 
28455e07668SIan Munsie err_fd:
28555e07668SIan Munsie 	put_unused_fd(fdtmp);
28655e07668SIan Munsie 	return NULL;
2876f7f0b3dSMichael Neuling }
2886f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_get_fd);
2896f7f0b3dSMichael Neuling 
2906f7f0b3dSMichael Neuling struct cxl_context *cxl_fops_get_context(struct file *file)
2916f7f0b3dSMichael Neuling {
2926f7f0b3dSMichael Neuling 	return file->private_data;
2936f7f0b3dSMichael Neuling }
2946f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_fops_get_context);
2956f7f0b3dSMichael Neuling 
2966f7f0b3dSMichael Neuling int cxl_start_work(struct cxl_context *ctx,
2976f7f0b3dSMichael Neuling 		   struct cxl_ioctl_start_work *work)
2986f7f0b3dSMichael Neuling {
2996f7f0b3dSMichael Neuling 	int rc;
3006f7f0b3dSMichael Neuling 
3016f7f0b3dSMichael Neuling 	/* code taken from afu_ioctl_start_work */
3026f7f0b3dSMichael Neuling 	if (!(work->flags & CXL_START_WORK_NUM_IRQS))
3036f7f0b3dSMichael Neuling 		work->num_interrupts = ctx->afu->pp_irqs;
3046f7f0b3dSMichael Neuling 	else if ((work->num_interrupts < ctx->afu->pp_irqs) ||
3056f7f0b3dSMichael Neuling 		 (work->num_interrupts > ctx->afu->irqs_max)) {
3066f7f0b3dSMichael Neuling 		return -EINVAL;
3076f7f0b3dSMichael Neuling 	}
3086f7f0b3dSMichael Neuling 
3096f7f0b3dSMichael Neuling 	rc = afu_register_irqs(ctx, work->num_interrupts);
3106f7f0b3dSMichael Neuling 	if (rc)
3116f7f0b3dSMichael Neuling 		return rc;
3126f7f0b3dSMichael Neuling 
3136f7f0b3dSMichael Neuling 	rc = cxl_start_context(ctx, work->work_element_descriptor, current);
3146f7f0b3dSMichael Neuling 	if (rc < 0) {
3156f7f0b3dSMichael Neuling 		afu_release_irqs(ctx, ctx);
3166f7f0b3dSMichael Neuling 		return rc;
3176f7f0b3dSMichael Neuling 	}
3186f7f0b3dSMichael Neuling 
3196f7f0b3dSMichael Neuling 	return 0;
3206f7f0b3dSMichael Neuling }
3216f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_start_work);
3226f7f0b3dSMichael Neuling 
3236f7f0b3dSMichael Neuling void __iomem *cxl_psa_map(struct cxl_context *ctx)
3246f7f0b3dSMichael Neuling {
325cca44c01SFrederic Barrat 	if (ctx->status != STARTED)
3266f7f0b3dSMichael Neuling 		return NULL;
3276f7f0b3dSMichael Neuling 
3286f7f0b3dSMichael Neuling 	pr_devel("%s: psn_phys%llx size:%llx\n",
329cca44c01SFrederic Barrat 		__func__, ctx->psn_phys, ctx->psn_size);
3306f7f0b3dSMichael Neuling 	return ioremap(ctx->psn_phys, ctx->psn_size);
3316f7f0b3dSMichael Neuling }
3326f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_psa_map);
3336f7f0b3dSMichael Neuling 
3346f7f0b3dSMichael Neuling void cxl_psa_unmap(void __iomem *addr)
3356f7f0b3dSMichael Neuling {
3366f7f0b3dSMichael Neuling 	iounmap(addr);
3376f7f0b3dSMichael Neuling }
3386f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_psa_unmap);
3396f7f0b3dSMichael Neuling 
3406f7f0b3dSMichael Neuling int cxl_afu_reset(struct cxl_context *ctx)
3416f7f0b3dSMichael Neuling {
3426f7f0b3dSMichael Neuling 	struct cxl_afu *afu = ctx->afu;
3436f7f0b3dSMichael Neuling 	int rc;
3446f7f0b3dSMichael Neuling 
3455be587b1SFrederic Barrat 	rc = cxl_ops->afu_reset(afu);
3466f7f0b3dSMichael Neuling 	if (rc)
3476f7f0b3dSMichael Neuling 		return rc;
3486f7f0b3dSMichael Neuling 
3495be587b1SFrederic Barrat 	return cxl_ops->afu_check_and_enable(afu);
3506f7f0b3dSMichael Neuling }
3516f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_afu_reset);
35213e68d8bSDaniel Axtens 
35313e68d8bSDaniel Axtens void cxl_perst_reloads_same_image(struct cxl_afu *afu,
35413e68d8bSDaniel Axtens 				  bool perst_reloads_same_image)
35513e68d8bSDaniel Axtens {
35613e68d8bSDaniel Axtens 	afu->adapter->perst_same_image = perst_reloads_same_image;
35713e68d8bSDaniel Axtens }
35813e68d8bSDaniel Axtens EXPORT_SYMBOL_GPL(cxl_perst_reloads_same_image);
359