xref: /linux/drivers/misc/cxl/api.c (revision 8dde152ea34860403c839598bdef3f07239eb25a)
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