xref: /linux/drivers/scsi/cxlflash/ocxl_hw.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
276ebe01fSUma Krishnan /*
376ebe01fSUma Krishnan  * CXL Flash Device Driver
476ebe01fSUma Krishnan  *
576ebe01fSUma Krishnan  * Written by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>, IBM Corporation
676ebe01fSUma Krishnan  *             Uma Krishnan <ukrishn@linux.vnet.ibm.com>, IBM Corporation
776ebe01fSUma Krishnan  *
876ebe01fSUma Krishnan  * Copyright (C) 2018 IBM Corporation
976ebe01fSUma Krishnan  */
1076ebe01fSUma Krishnan 
11926a62f9SUma Krishnan #include <linux/file.h>
12429ebfa6SUma Krishnan #include <linux/idr.h>
13926a62f9SUma Krishnan #include <linux/module.h>
14926a62f9SUma Krishnan #include <linux/mount.h>
15219e6963SDavid Howells #include <linux/pseudo_fs.h>
1656f1db1aSUma Krishnan #include <linux/poll.h>
1703aa9c51SUma Krishnan #include <linux/sched/signal.h>
181e89da5eSFrederic Barrat #include <linux/interrupt.h>
1961657dcdSChristophe Leroy #include <linux/irqdomain.h>
201e89da5eSFrederic Barrat #include <asm/xive.h>
2176ebe01fSUma Krishnan #include <misc/ocxl.h>
2276ebe01fSUma Krishnan 
2303aa9c51SUma Krishnan #include <uapi/misc/cxl.h>
2403aa9c51SUma Krishnan 
2576ebe01fSUma Krishnan #include "backend.h"
2648e077dbSUma Krishnan #include "ocxl_hw.h"
2748e077dbSUma Krishnan 
28926a62f9SUma Krishnan /*
29926a62f9SUma Krishnan  * Pseudo-filesystem to allocate inodes.
30926a62f9SUma Krishnan  */
31926a62f9SUma Krishnan 
32926a62f9SUma Krishnan #define OCXLFLASH_FS_MAGIC      0x1697698f
33926a62f9SUma Krishnan 
34926a62f9SUma Krishnan static int ocxlflash_fs_cnt;
35926a62f9SUma Krishnan static struct vfsmount *ocxlflash_vfs_mount;
36926a62f9SUma Krishnan 
ocxlflash_fs_init_fs_context(struct fs_context * fc)37219e6963SDavid Howells static int ocxlflash_fs_init_fs_context(struct fs_context *fc)
38926a62f9SUma Krishnan {
39219e6963SDavid Howells 	return init_pseudo(fc, OCXLFLASH_FS_MAGIC) ? 0 : -ENOMEM;
40926a62f9SUma Krishnan }
41926a62f9SUma Krishnan 
42926a62f9SUma Krishnan static struct file_system_type ocxlflash_fs_type = {
43926a62f9SUma Krishnan 	.name		= "ocxlflash",
44926a62f9SUma Krishnan 	.owner		= THIS_MODULE,
45219e6963SDavid Howells 	.init_fs_context = ocxlflash_fs_init_fs_context,
46926a62f9SUma Krishnan 	.kill_sb	= kill_anon_super,
47926a62f9SUma Krishnan };
48926a62f9SUma Krishnan 
49926a62f9SUma Krishnan /*
50926a62f9SUma Krishnan  * ocxlflash_release_mapping() - release the memory mapping
51926a62f9SUma Krishnan  * @ctx:	Context whose mapping is to be released.
52926a62f9SUma Krishnan  */
ocxlflash_release_mapping(struct ocxlflash_context * ctx)53926a62f9SUma Krishnan static void ocxlflash_release_mapping(struct ocxlflash_context *ctx)
54926a62f9SUma Krishnan {
55926a62f9SUma Krishnan 	if (ctx->mapping)
56926a62f9SUma Krishnan 		simple_release_fs(&ocxlflash_vfs_mount, &ocxlflash_fs_cnt);
57926a62f9SUma Krishnan 	ctx->mapping = NULL;
58926a62f9SUma Krishnan }
59926a62f9SUma Krishnan 
60926a62f9SUma Krishnan /*
61926a62f9SUma Krishnan  * ocxlflash_getfile() - allocate pseudo filesystem, inode, and the file
62926a62f9SUma Krishnan  * @dev:	Generic device of the host.
63926a62f9SUma Krishnan  * @name:	Name of the pseudo filesystem.
64926a62f9SUma Krishnan  * @fops:	File operations.
65926a62f9SUma Krishnan  * @priv:	Private data.
66926a62f9SUma Krishnan  * @flags:	Flags for the file.
67926a62f9SUma Krishnan  *
68926a62f9SUma Krishnan  * Return: pointer to the file on success, ERR_PTR on failure
69926a62f9SUma Krishnan  */
ocxlflash_getfile(struct device * dev,const char * name,const struct file_operations * fops,void * priv,int flags)70926a62f9SUma Krishnan static struct file *ocxlflash_getfile(struct device *dev, const char *name,
71926a62f9SUma Krishnan 				      const struct file_operations *fops,
72926a62f9SUma Krishnan 				      void *priv, int flags)
73926a62f9SUma Krishnan {
74926a62f9SUma Krishnan 	struct file *file;
75118f4868SAl Viro 	struct inode *inode;
76926a62f9SUma Krishnan 	int rc;
77926a62f9SUma Krishnan 
78926a62f9SUma Krishnan 	if (fops->owner && !try_module_get(fops->owner)) {
79926a62f9SUma Krishnan 		dev_err(dev, "%s: Owner does not exist\n", __func__);
80926a62f9SUma Krishnan 		rc = -ENOENT;
81926a62f9SUma Krishnan 		goto err1;
82926a62f9SUma Krishnan 	}
83926a62f9SUma Krishnan 
84926a62f9SUma Krishnan 	rc = simple_pin_fs(&ocxlflash_fs_type, &ocxlflash_vfs_mount,
85926a62f9SUma Krishnan 			   &ocxlflash_fs_cnt);
86926a62f9SUma Krishnan 	if (unlikely(rc < 0)) {
87926a62f9SUma Krishnan 		dev_err(dev, "%s: Cannot mount ocxlflash pseudofs rc=%d\n",
88926a62f9SUma Krishnan 			__func__, rc);
89926a62f9SUma Krishnan 		goto err2;
90926a62f9SUma Krishnan 	}
91926a62f9SUma Krishnan 
92926a62f9SUma Krishnan 	inode = alloc_anon_inode(ocxlflash_vfs_mount->mnt_sb);
93926a62f9SUma Krishnan 	if (IS_ERR(inode)) {
94926a62f9SUma Krishnan 		rc = PTR_ERR(inode);
95926a62f9SUma Krishnan 		dev_err(dev, "%s: alloc_anon_inode failed rc=%d\n",
96926a62f9SUma Krishnan 			__func__, rc);
97926a62f9SUma Krishnan 		goto err3;
98926a62f9SUma Krishnan 	}
99926a62f9SUma Krishnan 
100118f4868SAl Viro 	file = alloc_file_pseudo(inode, ocxlflash_vfs_mount, name,
101118f4868SAl Viro 				 flags & (O_ACCMODE | O_NONBLOCK), fops);
102926a62f9SUma Krishnan 	if (IS_ERR(file)) {
103926a62f9SUma Krishnan 		rc = PTR_ERR(file);
104926a62f9SUma Krishnan 		dev_err(dev, "%s: alloc_file failed rc=%d\n",
105926a62f9SUma Krishnan 			__func__, rc);
106118f4868SAl Viro 		goto err4;
107926a62f9SUma Krishnan 	}
108926a62f9SUma Krishnan 
109926a62f9SUma Krishnan 	file->private_data = priv;
110926a62f9SUma Krishnan out:
111926a62f9SUma Krishnan 	return file;
112926a62f9SUma Krishnan err4:
113926a62f9SUma Krishnan 	iput(inode);
114926a62f9SUma Krishnan err3:
115926a62f9SUma Krishnan 	simple_release_fs(&ocxlflash_vfs_mount, &ocxlflash_fs_cnt);
116926a62f9SUma Krishnan err2:
117926a62f9SUma Krishnan 	module_put(fops->owner);
118926a62f9SUma Krishnan err1:
119926a62f9SUma Krishnan 	file = ERR_PTR(rc);
120926a62f9SUma Krishnan 	goto out;
121926a62f9SUma Krishnan }
122926a62f9SUma Krishnan 
12348e077dbSUma Krishnan /**
124012f394cSUma Krishnan  * ocxlflash_psa_map() - map the process specific MMIO space
125012f394cSUma Krishnan  * @ctx_cookie:	Adapter context for which the mapping needs to be done.
126012f394cSUma Krishnan  *
127012f394cSUma Krishnan  * Return: MMIO pointer of the mapped region
128012f394cSUma Krishnan  */
ocxlflash_psa_map(void * ctx_cookie)129012f394cSUma Krishnan static void __iomem *ocxlflash_psa_map(void *ctx_cookie)
130012f394cSUma Krishnan {
131012f394cSUma Krishnan 	struct ocxlflash_context *ctx = ctx_cookie;
132f81face7SUma Krishnan 	struct device *dev = ctx->hw_afu->dev;
133f81face7SUma Krishnan 
134f81face7SUma Krishnan 	mutex_lock(&ctx->state_mutex);
135f81face7SUma Krishnan 	if (ctx->state != STARTED) {
136f81face7SUma Krishnan 		dev_err(dev, "%s: Context not started, state=%d\n", __func__,
137f81face7SUma Krishnan 			ctx->state);
138f81face7SUma Krishnan 		mutex_unlock(&ctx->state_mutex);
139f81face7SUma Krishnan 		return NULL;
140f81face7SUma Krishnan 	}
141f81face7SUma Krishnan 	mutex_unlock(&ctx->state_mutex);
142012f394cSUma Krishnan 
143012f394cSUma Krishnan 	return ioremap(ctx->psn_phys, ctx->psn_size);
144012f394cSUma Krishnan }
145012f394cSUma Krishnan 
146012f394cSUma Krishnan /**
147012f394cSUma Krishnan  * ocxlflash_psa_unmap() - unmap the process specific MMIO space
148012f394cSUma Krishnan  * @addr:	MMIO pointer to unmap.
149012f394cSUma Krishnan  */
ocxlflash_psa_unmap(void __iomem * addr)150012f394cSUma Krishnan static void ocxlflash_psa_unmap(void __iomem *addr)
151012f394cSUma Krishnan {
152012f394cSUma Krishnan 	iounmap(addr);
153012f394cSUma Krishnan }
154012f394cSUma Krishnan 
155012f394cSUma Krishnan /**
156b18718c6SUma Krishnan  * ocxlflash_process_element() - get process element of the adapter context
157b18718c6SUma Krishnan  * @ctx_cookie:	Adapter context associated with the process element.
158b18718c6SUma Krishnan  *
159b18718c6SUma Krishnan  * Return: process element of the adapter context
160b18718c6SUma Krishnan  */
ocxlflash_process_element(void * ctx_cookie)161b18718c6SUma Krishnan static int ocxlflash_process_element(void *ctx_cookie)
162b18718c6SUma Krishnan {
163b18718c6SUma Krishnan 	struct ocxlflash_context *ctx = ctx_cookie;
164b18718c6SUma Krishnan 
165b18718c6SUma Krishnan 	return ctx->pe;
166b18718c6SUma Krishnan }
167b18718c6SUma Krishnan 
168b18718c6SUma Krishnan /**
169a06b1cfcSUma Krishnan  * afu_map_irq() - map the interrupt of the adapter context
170a06b1cfcSUma Krishnan  * @flags:	Flags.
171a06b1cfcSUma Krishnan  * @ctx:	Adapter context.
172a06b1cfcSUma Krishnan  * @num:	Per-context AFU interrupt number.
173a06b1cfcSUma Krishnan  * @handler:	Interrupt handler to register.
174a06b1cfcSUma Krishnan  * @cookie:	Interrupt handler private data.
175a06b1cfcSUma Krishnan  * @name:	Name of the interrupt.
176a06b1cfcSUma Krishnan  *
177a06b1cfcSUma Krishnan  * Return: 0 on success, -errno on failure
178a06b1cfcSUma Krishnan  */
afu_map_irq(u64 flags,struct ocxlflash_context * ctx,int num,irq_handler_t handler,void * cookie,char * name)179a06b1cfcSUma Krishnan static int afu_map_irq(u64 flags, struct ocxlflash_context *ctx, int num,
180a06b1cfcSUma Krishnan 		       irq_handler_t handler, void *cookie, char *name)
181a06b1cfcSUma Krishnan {
182a06b1cfcSUma Krishnan 	struct ocxl_hw_afu *afu = ctx->hw_afu;
183a06b1cfcSUma Krishnan 	struct device *dev = afu->dev;
184a06b1cfcSUma Krishnan 	struct ocxlflash_irqs *irq;
1851e89da5eSFrederic Barrat 	struct xive_irq_data *xd;
186a06b1cfcSUma Krishnan 	u32 virq;
187a06b1cfcSUma Krishnan 	int rc = 0;
188a06b1cfcSUma Krishnan 
189a06b1cfcSUma Krishnan 	if (num < 0 || num >= ctx->num_irqs) {
190a06b1cfcSUma Krishnan 		dev_err(dev, "%s: Interrupt %d not allocated\n", __func__, num);
191a06b1cfcSUma Krishnan 		rc = -ENOENT;
192a06b1cfcSUma Krishnan 		goto out;
193a06b1cfcSUma Krishnan 	}
194a06b1cfcSUma Krishnan 
195a06b1cfcSUma Krishnan 	irq = &ctx->irqs[num];
196a06b1cfcSUma Krishnan 	virq = irq_create_mapping(NULL, irq->hwirq);
197a06b1cfcSUma Krishnan 	if (unlikely(!virq)) {
198a06b1cfcSUma Krishnan 		dev_err(dev, "%s: irq_create_mapping failed\n", __func__);
199a06b1cfcSUma Krishnan 		rc = -ENOMEM;
200a06b1cfcSUma Krishnan 		goto out;
201a06b1cfcSUma Krishnan 	}
202a06b1cfcSUma Krishnan 
203a06b1cfcSUma Krishnan 	rc = request_irq(virq, handler, 0, name, cookie);
204a06b1cfcSUma Krishnan 	if (unlikely(rc)) {
205a06b1cfcSUma Krishnan 		dev_err(dev, "%s: request_irq failed rc=%d\n", __func__, rc);
206a06b1cfcSUma Krishnan 		goto err1;
207a06b1cfcSUma Krishnan 	}
208a06b1cfcSUma Krishnan 
2091e89da5eSFrederic Barrat 	xd = irq_get_handler_data(virq);
2101e89da5eSFrederic Barrat 	if (unlikely(!xd)) {
2111e89da5eSFrederic Barrat 		dev_err(dev, "%s: Can't get interrupt data\n", __func__);
2121e89da5eSFrederic Barrat 		rc = -ENXIO;
213a06b1cfcSUma Krishnan 		goto err2;
214a06b1cfcSUma Krishnan 	}
215a06b1cfcSUma Krishnan 
216a06b1cfcSUma Krishnan 	irq->virq = virq;
2171e89da5eSFrederic Barrat 	irq->vtrig = xd->trig_mmio;
218a06b1cfcSUma Krishnan out:
219a06b1cfcSUma Krishnan 	return rc;
220a06b1cfcSUma Krishnan err2:
221a06b1cfcSUma Krishnan 	free_irq(virq, cookie);
222a06b1cfcSUma Krishnan err1:
223a06b1cfcSUma Krishnan 	irq_dispose_mapping(virq);
224a06b1cfcSUma Krishnan 	goto out;
225a06b1cfcSUma Krishnan }
226a06b1cfcSUma Krishnan 
227a06b1cfcSUma Krishnan /**
228a06b1cfcSUma Krishnan  * ocxlflash_map_afu_irq() - map the interrupt of the adapter context
229a06b1cfcSUma Krishnan  * @ctx_cookie:	Adapter context.
230a06b1cfcSUma Krishnan  * @num:	Per-context AFU interrupt number.
231a06b1cfcSUma Krishnan  * @handler:	Interrupt handler to register.
232a06b1cfcSUma Krishnan  * @cookie:	Interrupt handler private data.
233a06b1cfcSUma Krishnan  * @name:	Name of the interrupt.
234a06b1cfcSUma Krishnan  *
235a06b1cfcSUma Krishnan  * Return: 0 on success, -errno on failure
236a06b1cfcSUma Krishnan  */
ocxlflash_map_afu_irq(void * ctx_cookie,int num,irq_handler_t handler,void * cookie,char * name)237a06b1cfcSUma Krishnan static int ocxlflash_map_afu_irq(void *ctx_cookie, int num,
238a06b1cfcSUma Krishnan 				 irq_handler_t handler, void *cookie,
239a06b1cfcSUma Krishnan 				 char *name)
240a06b1cfcSUma Krishnan {
241a06b1cfcSUma Krishnan 	return afu_map_irq(0, ctx_cookie, num, handler, cookie, name);
242a06b1cfcSUma Krishnan }
243a06b1cfcSUma Krishnan 
244a06b1cfcSUma Krishnan /**
245a06b1cfcSUma Krishnan  * afu_unmap_irq() - unmap the interrupt
246a06b1cfcSUma Krishnan  * @flags:	Flags.
247a06b1cfcSUma Krishnan  * @ctx:	Adapter context.
248a06b1cfcSUma Krishnan  * @num:	Per-context AFU interrupt number.
249a06b1cfcSUma Krishnan  * @cookie:	Interrupt handler private data.
250a06b1cfcSUma Krishnan  */
afu_unmap_irq(u64 flags,struct ocxlflash_context * ctx,int num,void * cookie)251a06b1cfcSUma Krishnan static void afu_unmap_irq(u64 flags, struct ocxlflash_context *ctx, int num,
252a06b1cfcSUma Krishnan 			  void *cookie)
253a06b1cfcSUma Krishnan {
254a06b1cfcSUma Krishnan 	struct ocxl_hw_afu *afu = ctx->hw_afu;
255a06b1cfcSUma Krishnan 	struct device *dev = afu->dev;
256a06b1cfcSUma Krishnan 	struct ocxlflash_irqs *irq;
257a06b1cfcSUma Krishnan 
258a06b1cfcSUma Krishnan 	if (num < 0 || num >= ctx->num_irqs) {
259a06b1cfcSUma Krishnan 		dev_err(dev, "%s: Interrupt %d not allocated\n", __func__, num);
260a06b1cfcSUma Krishnan 		return;
261a06b1cfcSUma Krishnan 	}
262a06b1cfcSUma Krishnan 
263a06b1cfcSUma Krishnan 	irq = &ctx->irqs[num];
264a06b1cfcSUma Krishnan 
265a06b1cfcSUma Krishnan 	if (irq_find_mapping(NULL, irq->hwirq)) {
266a06b1cfcSUma Krishnan 		free_irq(irq->virq, cookie);
267a06b1cfcSUma Krishnan 		irq_dispose_mapping(irq->virq);
268a06b1cfcSUma Krishnan 	}
269a06b1cfcSUma Krishnan 
270a06b1cfcSUma Krishnan 	memset(irq, 0, sizeof(*irq));
271a06b1cfcSUma Krishnan }
272a06b1cfcSUma Krishnan 
273a06b1cfcSUma Krishnan /**
274a06b1cfcSUma Krishnan  * ocxlflash_unmap_afu_irq() - unmap the interrupt
275a06b1cfcSUma Krishnan  * @ctx_cookie:	Adapter context.
276a06b1cfcSUma Krishnan  * @num:	Per-context AFU interrupt number.
277a06b1cfcSUma Krishnan  * @cookie:	Interrupt handler private data.
278a06b1cfcSUma Krishnan  */
ocxlflash_unmap_afu_irq(void * ctx_cookie,int num,void * cookie)279a06b1cfcSUma Krishnan static void ocxlflash_unmap_afu_irq(void *ctx_cookie, int num, void *cookie)
280a06b1cfcSUma Krishnan {
281a06b1cfcSUma Krishnan 	return afu_unmap_irq(0, ctx_cookie, num, cookie);
282a06b1cfcSUma Krishnan }
283a06b1cfcSUma Krishnan 
284a06b1cfcSUma Krishnan /**
285402a55eaSUma Krishnan  * ocxlflash_get_irq_objhndl() - get the object handle for an interrupt
286402a55eaSUma Krishnan  * @ctx_cookie:	Context associated with the interrupt.
287402a55eaSUma Krishnan  * @irq:	Interrupt number.
288402a55eaSUma Krishnan  *
289402a55eaSUma Krishnan  * Return: effective address of the mapped region
290402a55eaSUma Krishnan  */
ocxlflash_get_irq_objhndl(void * ctx_cookie,int irq)291402a55eaSUma Krishnan static u64 ocxlflash_get_irq_objhndl(void *ctx_cookie, int irq)
292402a55eaSUma Krishnan {
293402a55eaSUma Krishnan 	struct ocxlflash_context *ctx = ctx_cookie;
294402a55eaSUma Krishnan 
295402a55eaSUma Krishnan 	if (irq < 0 || irq >= ctx->num_irqs)
296402a55eaSUma Krishnan 		return 0;
297402a55eaSUma Krishnan 
298402a55eaSUma Krishnan 	return (__force u64)ctx->irqs[irq].vtrig;
299402a55eaSUma Krishnan }
300402a55eaSUma Krishnan 
301402a55eaSUma Krishnan /**
30266ae644bSUma Krishnan  * ocxlflash_xsl_fault() - callback when translation error is triggered
30366ae644bSUma Krishnan  * @data:	Private data provided at callback registration, the context.
30466ae644bSUma Krishnan  * @addr:	Address that triggered the error.
30566ae644bSUma Krishnan  * @dsisr:	Value of dsisr register.
30666ae644bSUma Krishnan  */
ocxlflash_xsl_fault(void * data,u64 addr,u64 dsisr)30766ae644bSUma Krishnan static void ocxlflash_xsl_fault(void *data, u64 addr, u64 dsisr)
30866ae644bSUma Krishnan {
30966ae644bSUma Krishnan 	struct ocxlflash_context *ctx = data;
31066ae644bSUma Krishnan 
31166ae644bSUma Krishnan 	spin_lock(&ctx->slock);
31266ae644bSUma Krishnan 	ctx->fault_addr = addr;
31366ae644bSUma Krishnan 	ctx->fault_dsisr = dsisr;
31466ae644bSUma Krishnan 	ctx->pending_fault = true;
31566ae644bSUma Krishnan 	spin_unlock(&ctx->slock);
31666ae644bSUma Krishnan 
31766ae644bSUma Krishnan 	wake_up_all(&ctx->wq);
31866ae644bSUma Krishnan }
31966ae644bSUma Krishnan 
32066ae644bSUma Krishnan /**
3216b938ac9SUma Krishnan  * start_context() - local routine to start a context
3226b938ac9SUma Krishnan  * @ctx:	Adapter context to be started.
3236b938ac9SUma Krishnan  *
324c207b571SUma Krishnan  * Assign the context specific MMIO space, add and enable the PE.
3256b938ac9SUma Krishnan  *
3266b938ac9SUma Krishnan  * Return: 0 on success, -errno on failure
3276b938ac9SUma Krishnan  */
start_context(struct ocxlflash_context * ctx)3286b938ac9SUma Krishnan static int start_context(struct ocxlflash_context *ctx)
3296b938ac9SUma Krishnan {
3306b938ac9SUma Krishnan 	struct ocxl_hw_afu *afu = ctx->hw_afu;
3316b938ac9SUma Krishnan 	struct ocxl_afu_config *acfg = &afu->acfg;
332c207b571SUma Krishnan 	void *link_token = afu->link_token;
333d731feeaSChristophe Lombard 	struct pci_dev *pdev = afu->pdev;
334c207b571SUma Krishnan 	struct device *dev = afu->dev;
3356b938ac9SUma Krishnan 	bool master = ctx->master;
336762c7e93SUma Krishnan 	struct mm_struct *mm;
337c207b571SUma Krishnan 	int rc = 0;
338762c7e93SUma Krishnan 	u32 pid;
3396b938ac9SUma Krishnan 
340f81face7SUma Krishnan 	mutex_lock(&ctx->state_mutex);
341f81face7SUma Krishnan 	if (ctx->state != OPENED) {
342f81face7SUma Krishnan 		dev_err(dev, "%s: Context state invalid, state=%d\n",
343f81face7SUma Krishnan 			__func__, ctx->state);
344f81face7SUma Krishnan 		rc = -EINVAL;
345f81face7SUma Krishnan 		goto out;
346f81face7SUma Krishnan 	}
347f81face7SUma Krishnan 
3486b938ac9SUma Krishnan 	if (master) {
3496b938ac9SUma Krishnan 		ctx->psn_size = acfg->global_mmio_size;
3506b938ac9SUma Krishnan 		ctx->psn_phys = afu->gmmio_phys;
3516b938ac9SUma Krishnan 	} else {
3526b938ac9SUma Krishnan 		ctx->psn_size = acfg->pp_mmio_stride;
3536b938ac9SUma Krishnan 		ctx->psn_phys = afu->ppmmio_phys + (ctx->pe * ctx->psn_size);
3546b938ac9SUma Krishnan 	}
3556b938ac9SUma Krishnan 
356762c7e93SUma Krishnan 	/* pid and mm not set for master contexts */
357762c7e93SUma Krishnan 	if (master) {
358762c7e93SUma Krishnan 		pid = 0;
359762c7e93SUma Krishnan 		mm = NULL;
360762c7e93SUma Krishnan 	} else {
361762c7e93SUma Krishnan 		pid = current->mm->context.id;
362762c7e93SUma Krishnan 		mm = current->mm;
363762c7e93SUma Krishnan 	}
364c207b571SUma Krishnan 
365d731feeaSChristophe Lombard 	rc = ocxl_link_add_pe(link_token, ctx->pe, pid, 0, 0,
366d731feeaSChristophe Lombard 			      pci_dev_id(pdev), mm, ocxlflash_xsl_fault,
367d731feeaSChristophe Lombard 			      ctx);
368c207b571SUma Krishnan 	if (unlikely(rc)) {
369c207b571SUma Krishnan 		dev_err(dev, "%s: ocxl_link_add_pe failed rc=%d\n",
370c207b571SUma Krishnan 			__func__, rc);
371c207b571SUma Krishnan 		goto out;
372c207b571SUma Krishnan 	}
373f81face7SUma Krishnan 
374f81face7SUma Krishnan 	ctx->state = STARTED;
375c207b571SUma Krishnan out:
376f81face7SUma Krishnan 	mutex_unlock(&ctx->state_mutex);
377c207b571SUma Krishnan 	return rc;
3786b938ac9SUma Krishnan }
3796b938ac9SUma Krishnan 
3806b938ac9SUma Krishnan /**
3816b938ac9SUma Krishnan  * ocxlflash_start_context() - start a kernel context
3826b938ac9SUma Krishnan  * @ctx_cookie:	Adapter context to be started.
3836b938ac9SUma Krishnan  *
3846b938ac9SUma Krishnan  * Return: 0 on success, -errno on failure
3856b938ac9SUma Krishnan  */
ocxlflash_start_context(void * ctx_cookie)3866b938ac9SUma Krishnan static int ocxlflash_start_context(void *ctx_cookie)
3876b938ac9SUma Krishnan {
3886b938ac9SUma Krishnan 	struct ocxlflash_context *ctx = ctx_cookie;
3896b938ac9SUma Krishnan 
3906b938ac9SUma Krishnan 	return start_context(ctx);
3916b938ac9SUma Krishnan }
3926b938ac9SUma Krishnan 
3936b938ac9SUma Krishnan /**
394c207b571SUma Krishnan  * ocxlflash_stop_context() - stop a context
395c207b571SUma Krishnan  * @ctx_cookie:	Adapter context to be stopped.
396c207b571SUma Krishnan  *
397c207b571SUma Krishnan  * Return: 0 on success, -errno on failure
398c207b571SUma Krishnan  */
ocxlflash_stop_context(void * ctx_cookie)399c207b571SUma Krishnan static int ocxlflash_stop_context(void *ctx_cookie)
400c207b571SUma Krishnan {
401c207b571SUma Krishnan 	struct ocxlflash_context *ctx = ctx_cookie;
402c207b571SUma Krishnan 	struct ocxl_hw_afu *afu = ctx->hw_afu;
403c207b571SUma Krishnan 	struct ocxl_afu_config *acfg = &afu->acfg;
404c207b571SUma Krishnan 	struct pci_dev *pdev = afu->pdev;
405c207b571SUma Krishnan 	struct device *dev = afu->dev;
406f81face7SUma Krishnan 	enum ocxlflash_ctx_state state;
407f81face7SUma Krishnan 	int rc = 0;
408f81face7SUma Krishnan 
409f81face7SUma Krishnan 	mutex_lock(&ctx->state_mutex);
410f81face7SUma Krishnan 	state = ctx->state;
411f81face7SUma Krishnan 	ctx->state = CLOSED;
412f81face7SUma Krishnan 	mutex_unlock(&ctx->state_mutex);
413f81face7SUma Krishnan 	if (state != STARTED)
414f81face7SUma Krishnan 		goto out;
415c207b571SUma Krishnan 
416c207b571SUma Krishnan 	rc = ocxl_config_terminate_pasid(pdev, acfg->dvsec_afu_control_pos,
417c207b571SUma Krishnan 					 ctx->pe);
418c207b571SUma Krishnan 	if (unlikely(rc)) {
419c207b571SUma Krishnan 		dev_err(dev, "%s: ocxl_config_terminate_pasid failed rc=%d\n",
420c207b571SUma Krishnan 			__func__, rc);
421c207b571SUma Krishnan 		/* If EBUSY, PE could be referenced in future by the AFU */
422c207b571SUma Krishnan 		if (rc == -EBUSY)
423c207b571SUma Krishnan 			goto out;
424c207b571SUma Krishnan 	}
425c207b571SUma Krishnan 
426c207b571SUma Krishnan 	rc = ocxl_link_remove_pe(afu->link_token, ctx->pe);
427c207b571SUma Krishnan 	if (unlikely(rc)) {
428c207b571SUma Krishnan 		dev_err(dev, "%s: ocxl_link_remove_pe failed rc=%d\n",
429c207b571SUma Krishnan 			__func__, rc);
430c207b571SUma Krishnan 		goto out;
431c207b571SUma Krishnan 	}
432c207b571SUma Krishnan out:
433c207b571SUma Krishnan 	return rc;
434c207b571SUma Krishnan }
435c207b571SUma Krishnan 
436c207b571SUma Krishnan /**
4379433fb32SUma Krishnan  * ocxlflash_afu_reset() - reset the AFU
4389433fb32SUma Krishnan  * @ctx_cookie:	Adapter context.
4399433fb32SUma Krishnan  */
ocxlflash_afu_reset(void * ctx_cookie)4409433fb32SUma Krishnan static int ocxlflash_afu_reset(void *ctx_cookie)
4419433fb32SUma Krishnan {
4429433fb32SUma Krishnan 	struct ocxlflash_context *ctx = ctx_cookie;
4439433fb32SUma Krishnan 	struct device *dev = ctx->hw_afu->dev;
4449433fb32SUma Krishnan 
4459433fb32SUma Krishnan 	/* Pending implementation from OCXL transport services */
4469433fb32SUma Krishnan 	dev_err_once(dev, "%s: afu_reset() fop not supported\n", __func__);
4479433fb32SUma Krishnan 
4489433fb32SUma Krishnan 	/* Silently return success until it is implemented */
4499433fb32SUma Krishnan 	return 0;
4509433fb32SUma Krishnan }
4519433fb32SUma Krishnan 
4529433fb32SUma Krishnan /**
453f6b4557cSUma Krishnan  * ocxlflash_set_master() - sets the context as master
454f6b4557cSUma Krishnan  * @ctx_cookie:	Adapter context to set as master.
455f6b4557cSUma Krishnan  */
ocxlflash_set_master(void * ctx_cookie)456f6b4557cSUma Krishnan static void ocxlflash_set_master(void *ctx_cookie)
457f6b4557cSUma Krishnan {
458f6b4557cSUma Krishnan 	struct ocxlflash_context *ctx = ctx_cookie;
459f6b4557cSUma Krishnan 
460f6b4557cSUma Krishnan 	ctx->master = true;
461f6b4557cSUma Krishnan }
462f6b4557cSUma Krishnan 
463f6b4557cSUma Krishnan /**
464f6b4557cSUma Krishnan  * ocxlflash_get_context() - obtains the context associated with the host
465f6b4557cSUma Krishnan  * @pdev:	PCI device associated with the host.
466f6b4557cSUma Krishnan  * @afu_cookie:	Hardware AFU associated with the host.
467f6b4557cSUma Krishnan  *
468f6b4557cSUma Krishnan  * Return: returns the pointer to host adapter context
469f6b4557cSUma Krishnan  */
ocxlflash_get_context(struct pci_dev * pdev,void * afu_cookie)470f6b4557cSUma Krishnan static void *ocxlflash_get_context(struct pci_dev *pdev, void *afu_cookie)
471f6b4557cSUma Krishnan {
472f6b4557cSUma Krishnan 	struct ocxl_hw_afu *afu = afu_cookie;
473f6b4557cSUma Krishnan 
474f6b4557cSUma Krishnan 	return afu->ocxl_ctx;
475f6b4557cSUma Krishnan }
476f6b4557cSUma Krishnan 
477f6b4557cSUma Krishnan /**
478f6b4557cSUma Krishnan  * ocxlflash_dev_context_init() - allocate and initialize an adapter context
479f6b4557cSUma Krishnan  * @pdev:	PCI device associated with the host.
480f6b4557cSUma Krishnan  * @afu_cookie:	Hardware AFU associated with the host.
481f6b4557cSUma Krishnan  *
482f6b4557cSUma Krishnan  * Return: returns the adapter context on success, ERR_PTR on failure
483f6b4557cSUma Krishnan  */
ocxlflash_dev_context_init(struct pci_dev * pdev,void * afu_cookie)484f6b4557cSUma Krishnan static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie)
485f6b4557cSUma Krishnan {
486f6b4557cSUma Krishnan 	struct ocxl_hw_afu *afu = afu_cookie;
487f6b4557cSUma Krishnan 	struct device *dev = afu->dev;
488f6b4557cSUma Krishnan 	struct ocxlflash_context *ctx;
489f6b4557cSUma Krishnan 	int rc;
490f6b4557cSUma Krishnan 
491f6b4557cSUma Krishnan 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
492f6b4557cSUma Krishnan 	if (unlikely(!ctx)) {
493f6b4557cSUma Krishnan 		dev_err(dev, "%s: Context allocation failed\n", __func__);
494f6b4557cSUma Krishnan 		rc = -ENOMEM;
495429ebfa6SUma Krishnan 		goto err1;
496f6b4557cSUma Krishnan 	}
497f6b4557cSUma Krishnan 
498429ebfa6SUma Krishnan 	idr_preload(GFP_KERNEL);
499429ebfa6SUma Krishnan 	rc = idr_alloc(&afu->idr, ctx, 0, afu->max_pasid, GFP_NOWAIT);
500429ebfa6SUma Krishnan 	idr_preload_end();
501429ebfa6SUma Krishnan 	if (unlikely(rc < 0)) {
502429ebfa6SUma Krishnan 		dev_err(dev, "%s: idr_alloc failed rc=%d\n", __func__, rc);
503429ebfa6SUma Krishnan 		goto err2;
504429ebfa6SUma Krishnan 	}
505429ebfa6SUma Krishnan 
506762c7e93SUma Krishnan 	spin_lock_init(&ctx->slock);
50756f1db1aSUma Krishnan 	init_waitqueue_head(&ctx->wq);
508f81face7SUma Krishnan 	mutex_init(&ctx->state_mutex);
509762c7e93SUma Krishnan 
510f81face7SUma Krishnan 	ctx->state = OPENED;
511429ebfa6SUma Krishnan 	ctx->pe = rc;
512f6b4557cSUma Krishnan 	ctx->master = false;
513926a62f9SUma Krishnan 	ctx->mapping = NULL;
514f6b4557cSUma Krishnan 	ctx->hw_afu = afu;
515762c7e93SUma Krishnan 	ctx->irq_bitmap = 0;
516762c7e93SUma Krishnan 	ctx->pending_irq = false;
51766ae644bSUma Krishnan 	ctx->pending_fault = false;
518f6b4557cSUma Krishnan out:
519f6b4557cSUma Krishnan 	return ctx;
520429ebfa6SUma Krishnan err2:
521429ebfa6SUma Krishnan 	kfree(ctx);
522429ebfa6SUma Krishnan err1:
523f6b4557cSUma Krishnan 	ctx = ERR_PTR(rc);
524f6b4557cSUma Krishnan 	goto out;
525f6b4557cSUma Krishnan }
526f6b4557cSUma Krishnan 
527f6b4557cSUma Krishnan /**
528f6b4557cSUma Krishnan  * ocxlflash_release_context() - releases an adapter context
529f6b4557cSUma Krishnan  * @ctx_cookie:	Adapter context to be released.
530f6b4557cSUma Krishnan  *
531f6b4557cSUma Krishnan  * Return: 0 on success, -errno on failure
532f6b4557cSUma Krishnan  */
ocxlflash_release_context(void * ctx_cookie)533f6b4557cSUma Krishnan static int ocxlflash_release_context(void *ctx_cookie)
534f6b4557cSUma Krishnan {
535f6b4557cSUma Krishnan 	struct ocxlflash_context *ctx = ctx_cookie;
536f81face7SUma Krishnan 	struct device *dev;
537f6b4557cSUma Krishnan 	int rc = 0;
538f6b4557cSUma Krishnan 
539f6b4557cSUma Krishnan 	if (!ctx)
540f6b4557cSUma Krishnan 		goto out;
541f6b4557cSUma Krishnan 
542f81face7SUma Krishnan 	dev = ctx->hw_afu->dev;
543f81face7SUma Krishnan 	mutex_lock(&ctx->state_mutex);
544f81face7SUma Krishnan 	if (ctx->state >= STARTED) {
545f81face7SUma Krishnan 		dev_err(dev, "%s: Context in use, state=%d\n", __func__,
546f81face7SUma Krishnan 			ctx->state);
547f81face7SUma Krishnan 		mutex_unlock(&ctx->state_mutex);
548f81face7SUma Krishnan 		rc = -EBUSY;
549f81face7SUma Krishnan 		goto out;
550f81face7SUma Krishnan 	}
551f81face7SUma Krishnan 	mutex_unlock(&ctx->state_mutex);
552f81face7SUma Krishnan 
553429ebfa6SUma Krishnan 	idr_remove(&ctx->hw_afu->idr, ctx->pe);
554926a62f9SUma Krishnan 	ocxlflash_release_mapping(ctx);
555f6b4557cSUma Krishnan 	kfree(ctx);
556f6b4557cSUma Krishnan out:
557f6b4557cSUma Krishnan 	return rc;
558f6b4557cSUma Krishnan }
559f6b4557cSUma Krishnan 
560f6b4557cSUma Krishnan /**
5618b7a5521SUma Krishnan  * ocxlflash_perst_reloads_same_image() - sets the image reload policy
5628b7a5521SUma Krishnan  * @afu_cookie:	Hardware AFU associated with the host.
5638b7a5521SUma Krishnan  * @image:	Whether to load the same image on PERST.
5648b7a5521SUma Krishnan  */
ocxlflash_perst_reloads_same_image(void * afu_cookie,bool image)5658b7a5521SUma Krishnan static void ocxlflash_perst_reloads_same_image(void *afu_cookie, bool image)
5668b7a5521SUma Krishnan {
5678b7a5521SUma Krishnan 	struct ocxl_hw_afu *afu = afu_cookie;
5688b7a5521SUma Krishnan 
5698b7a5521SUma Krishnan 	afu->perst_same_image = image;
5708b7a5521SUma Krishnan }
5718b7a5521SUma Krishnan 
5728b7a5521SUma Krishnan /**
573119c9200SUma Krishnan  * ocxlflash_read_adapter_vpd() - reads the adapter VPD
574119c9200SUma Krishnan  * @pdev:	PCI device associated with the host.
575119c9200SUma Krishnan  * @buf:	Buffer to get the VPD data.
576119c9200SUma Krishnan  * @count:	Size of buffer (maximum bytes that can be read).
577119c9200SUma Krishnan  *
578119c9200SUma Krishnan  * Return: size of VPD on success, -errno on failure
579119c9200SUma Krishnan  */
ocxlflash_read_adapter_vpd(struct pci_dev * pdev,void * buf,size_t count)580119c9200SUma Krishnan static ssize_t ocxlflash_read_adapter_vpd(struct pci_dev *pdev, void *buf,
581119c9200SUma Krishnan 					  size_t count)
582119c9200SUma Krishnan {
583119c9200SUma Krishnan 	return pci_read_vpd(pdev, 0, count, buf);
584119c9200SUma Krishnan }
585119c9200SUma Krishnan 
586119c9200SUma Krishnan /**
587bc65c1c7SUma Krishnan  * free_afu_irqs() - internal service to free interrupts
588bc65c1c7SUma Krishnan  * @ctx:	Adapter context.
589bc65c1c7SUma Krishnan  */
free_afu_irqs(struct ocxlflash_context * ctx)590bc65c1c7SUma Krishnan static void free_afu_irqs(struct ocxlflash_context *ctx)
591bc65c1c7SUma Krishnan {
592bc65c1c7SUma Krishnan 	struct ocxl_hw_afu *afu = ctx->hw_afu;
593bc65c1c7SUma Krishnan 	struct device *dev = afu->dev;
594bc65c1c7SUma Krishnan 	int i;
595bc65c1c7SUma Krishnan 
596bc65c1c7SUma Krishnan 	if (!ctx->irqs) {
597bc65c1c7SUma Krishnan 		dev_err(dev, "%s: Interrupts not allocated\n", __func__);
598bc65c1c7SUma Krishnan 		return;
599bc65c1c7SUma Krishnan 	}
600bc65c1c7SUma Krishnan 
601bc65c1c7SUma Krishnan 	for (i = ctx->num_irqs; i >= 0; i--)
602bc65c1c7SUma Krishnan 		ocxl_link_free_irq(afu->link_token, ctx->irqs[i].hwirq);
603bc65c1c7SUma Krishnan 
604bc65c1c7SUma Krishnan 	kfree(ctx->irqs);
605bc65c1c7SUma Krishnan 	ctx->irqs = NULL;
606bc65c1c7SUma Krishnan }
607bc65c1c7SUma Krishnan 
608bc65c1c7SUma Krishnan /**
609bc65c1c7SUma Krishnan  * alloc_afu_irqs() - internal service to allocate interrupts
610bc65c1c7SUma Krishnan  * @ctx:	Context associated with the request.
611bc65c1c7SUma Krishnan  * @num:	Number of interrupts requested.
612bc65c1c7SUma Krishnan  *
613bc65c1c7SUma Krishnan  * Return: 0 on success, -errno on failure
614bc65c1c7SUma Krishnan  */
alloc_afu_irqs(struct ocxlflash_context * ctx,int num)615bc65c1c7SUma Krishnan static int alloc_afu_irqs(struct ocxlflash_context *ctx, int num)
616bc65c1c7SUma Krishnan {
617bc65c1c7SUma Krishnan 	struct ocxl_hw_afu *afu = ctx->hw_afu;
618bc65c1c7SUma Krishnan 	struct device *dev = afu->dev;
619bc65c1c7SUma Krishnan 	struct ocxlflash_irqs *irqs;
620bc65c1c7SUma Krishnan 	int rc = 0;
621bc65c1c7SUma Krishnan 	int hwirq;
622bc65c1c7SUma Krishnan 	int i;
623bc65c1c7SUma Krishnan 
624bc65c1c7SUma Krishnan 	if (ctx->irqs) {
625bc65c1c7SUma Krishnan 		dev_err(dev, "%s: Interrupts already allocated\n", __func__);
626bc65c1c7SUma Krishnan 		rc = -EEXIST;
627bc65c1c7SUma Krishnan 		goto out;
628bc65c1c7SUma Krishnan 	}
629bc65c1c7SUma Krishnan 
630bc65c1c7SUma Krishnan 	if (num > OCXL_MAX_IRQS) {
631bc65c1c7SUma Krishnan 		dev_err(dev, "%s: Too many interrupts num=%d\n", __func__, num);
632bc65c1c7SUma Krishnan 		rc = -EINVAL;
633bc65c1c7SUma Krishnan 		goto out;
634bc65c1c7SUma Krishnan 	}
635bc65c1c7SUma Krishnan 
636bc65c1c7SUma Krishnan 	irqs = kcalloc(num, sizeof(*irqs), GFP_KERNEL);
637bc65c1c7SUma Krishnan 	if (unlikely(!irqs)) {
638bc65c1c7SUma Krishnan 		dev_err(dev, "%s: Context irqs allocation failed\n", __func__);
639bc65c1c7SUma Krishnan 		rc = -ENOMEM;
640bc65c1c7SUma Krishnan 		goto out;
641bc65c1c7SUma Krishnan 	}
642bc65c1c7SUma Krishnan 
643bc65c1c7SUma Krishnan 	for (i = 0; i < num; i++) {
644dde6f18aSFrederic Barrat 		rc = ocxl_link_irq_alloc(afu->link_token, &hwirq);
645bc65c1c7SUma Krishnan 		if (unlikely(rc)) {
646bc65c1c7SUma Krishnan 			dev_err(dev, "%s: ocxl_link_irq_alloc failed rc=%d\n",
647bc65c1c7SUma Krishnan 				__func__, rc);
648bc65c1c7SUma Krishnan 			goto err;
649bc65c1c7SUma Krishnan 		}
650bc65c1c7SUma Krishnan 
651bc65c1c7SUma Krishnan 		irqs[i].hwirq = hwirq;
652bc65c1c7SUma Krishnan 	}
653bc65c1c7SUma Krishnan 
654bc65c1c7SUma Krishnan 	ctx->irqs = irqs;
655bc65c1c7SUma Krishnan 	ctx->num_irqs = num;
656bc65c1c7SUma Krishnan out:
657bc65c1c7SUma Krishnan 	return rc;
658bc65c1c7SUma Krishnan err:
659bc65c1c7SUma Krishnan 	for (i = i-1; i >= 0; i--)
660bc65c1c7SUma Krishnan 		ocxl_link_free_irq(afu->link_token, irqs[i].hwirq);
661bc65c1c7SUma Krishnan 	kfree(irqs);
662bc65c1c7SUma Krishnan 	goto out;
663bc65c1c7SUma Krishnan }
664bc65c1c7SUma Krishnan 
665bc65c1c7SUma Krishnan /**
666bc65c1c7SUma Krishnan  * ocxlflash_allocate_afu_irqs() - allocates the requested number of interrupts
667bc65c1c7SUma Krishnan  * @ctx_cookie:	Context associated with the request.
668bc65c1c7SUma Krishnan  * @num:	Number of interrupts requested.
669bc65c1c7SUma Krishnan  *
670bc65c1c7SUma Krishnan  * Return: 0 on success, -errno on failure
671bc65c1c7SUma Krishnan  */
ocxlflash_allocate_afu_irqs(void * ctx_cookie,int num)672bc65c1c7SUma Krishnan static int ocxlflash_allocate_afu_irqs(void *ctx_cookie, int num)
673bc65c1c7SUma Krishnan {
674bc65c1c7SUma Krishnan 	return alloc_afu_irqs(ctx_cookie, num);
675bc65c1c7SUma Krishnan }
676bc65c1c7SUma Krishnan 
677bc65c1c7SUma Krishnan /**
678bc65c1c7SUma Krishnan  * ocxlflash_free_afu_irqs() - frees the interrupts of an adapter context
679bc65c1c7SUma Krishnan  * @ctx_cookie:	Adapter context.
680bc65c1c7SUma Krishnan  */
ocxlflash_free_afu_irqs(void * ctx_cookie)681bc65c1c7SUma Krishnan static void ocxlflash_free_afu_irqs(void *ctx_cookie)
682bc65c1c7SUma Krishnan {
683bc65c1c7SUma Krishnan 	free_afu_irqs(ctx_cookie);
684bc65c1c7SUma Krishnan }
685bc65c1c7SUma Krishnan 
686bc65c1c7SUma Krishnan /**
68754370503SUma Krishnan  * ocxlflash_unconfig_afu() - unconfigure the AFU
68854370503SUma Krishnan  * @afu: AFU associated with the host.
68954370503SUma Krishnan  */
ocxlflash_unconfig_afu(struct ocxl_hw_afu * afu)69054370503SUma Krishnan static void ocxlflash_unconfig_afu(struct ocxl_hw_afu *afu)
69154370503SUma Krishnan {
69254370503SUma Krishnan 	if (afu->gmmio_virt) {
69354370503SUma Krishnan 		iounmap(afu->gmmio_virt);
69454370503SUma Krishnan 		afu->gmmio_virt = NULL;
69554370503SUma Krishnan 	}
69654370503SUma Krishnan }
69754370503SUma Krishnan 
69854370503SUma Krishnan /**
69948e077dbSUma Krishnan  * ocxlflash_destroy_afu() - destroy the AFU structure
70048e077dbSUma Krishnan  * @afu_cookie:	AFU to be freed.
70148e077dbSUma Krishnan  */
ocxlflash_destroy_afu(void * afu_cookie)70248e077dbSUma Krishnan static void ocxlflash_destroy_afu(void *afu_cookie)
70348e077dbSUma Krishnan {
70448e077dbSUma Krishnan 	struct ocxl_hw_afu *afu = afu_cookie;
7053351e4f0SUma Krishnan 	int pos;
70648e077dbSUma Krishnan 
70748e077dbSUma Krishnan 	if (!afu)
70848e077dbSUma Krishnan 		return;
70948e077dbSUma Krishnan 
710f6b4557cSUma Krishnan 	ocxlflash_release_context(afu->ocxl_ctx);
711429ebfa6SUma Krishnan 	idr_destroy(&afu->idr);
7123351e4f0SUma Krishnan 
7133351e4f0SUma Krishnan 	/* Disable the AFU */
7143351e4f0SUma Krishnan 	pos = afu->acfg.dvsec_afu_control_pos;
7153351e4f0SUma Krishnan 	ocxl_config_set_afu_state(afu->pdev, pos, 0);
7163351e4f0SUma Krishnan 
71754370503SUma Krishnan 	ocxlflash_unconfig_afu(afu);
71848e077dbSUma Krishnan 	kfree(afu);
71948e077dbSUma Krishnan }
72048e077dbSUma Krishnan 
72148e077dbSUma Krishnan /**
722e9dfcedaSUma Krishnan  * ocxlflash_config_fn() - configure the host function
723e9dfcedaSUma Krishnan  * @pdev:	PCI device associated with the host.
724e9dfcedaSUma Krishnan  * @afu:	AFU associated with the host.
725e9dfcedaSUma Krishnan  *
726e9dfcedaSUma Krishnan  * Return: 0 on success, -errno on failure
727e9dfcedaSUma Krishnan  */
ocxlflash_config_fn(struct pci_dev * pdev,struct ocxl_hw_afu * afu)728e9dfcedaSUma Krishnan static int ocxlflash_config_fn(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
729e9dfcedaSUma Krishnan {
730e9dfcedaSUma Krishnan 	struct ocxl_fn_config *fcfg = &afu->fcfg;
731e9dfcedaSUma Krishnan 	struct device *dev = &pdev->dev;
7322e222779SUma Krishnan 	u16 base, enabled, supported;
733e9dfcedaSUma Krishnan 	int rc = 0;
734e9dfcedaSUma Krishnan 
735e9dfcedaSUma Krishnan 	/* Read DVSEC config of the function */
736e9dfcedaSUma Krishnan 	rc = ocxl_config_read_function(pdev, fcfg);
737e9dfcedaSUma Krishnan 	if (unlikely(rc)) {
738e9dfcedaSUma Krishnan 		dev_err(dev, "%s: ocxl_config_read_function failed rc=%d\n",
739e9dfcedaSUma Krishnan 			__func__, rc);
740e9dfcedaSUma Krishnan 		goto out;
741e9dfcedaSUma Krishnan 	}
742e9dfcedaSUma Krishnan 
743e9dfcedaSUma Krishnan 	/* Check if function has AFUs defined, only 1 per function supported */
744e9dfcedaSUma Krishnan 	if (fcfg->max_afu_index >= 0) {
745e9dfcedaSUma Krishnan 		afu->is_present = true;
746e9dfcedaSUma Krishnan 		if (fcfg->max_afu_index != 0)
747e9dfcedaSUma Krishnan 			dev_warn(dev, "%s: Unexpected AFU index value %d\n",
748e9dfcedaSUma Krishnan 				 __func__, fcfg->max_afu_index);
749e9dfcedaSUma Krishnan 	}
7502e222779SUma Krishnan 
7512e222779SUma Krishnan 	rc = ocxl_config_get_actag_info(pdev, &base, &enabled, &supported);
7522e222779SUma Krishnan 	if (unlikely(rc)) {
7532e222779SUma Krishnan 		dev_err(dev, "%s: ocxl_config_get_actag_info failed rc=%d\n",
7542e222779SUma Krishnan 			__func__, rc);
7552e222779SUma Krishnan 		goto out;
7562e222779SUma Krishnan 	}
7572e222779SUma Krishnan 
7582e222779SUma Krishnan 	afu->fn_actag_base = base;
7592e222779SUma Krishnan 	afu->fn_actag_enabled = enabled;
7602e222779SUma Krishnan 
7612e222779SUma Krishnan 	ocxl_config_set_actag(pdev, fcfg->dvsec_function_pos, base, enabled);
7622e222779SUma Krishnan 	dev_dbg(dev, "%s: Function acTag range base=%u enabled=%u\n",
7632e222779SUma Krishnan 		__func__, base, enabled);
76473904823SUma Krishnan 
76573904823SUma Krishnan 	rc = ocxl_link_setup(pdev, 0, &afu->link_token);
76673904823SUma Krishnan 	if (unlikely(rc)) {
76773904823SUma Krishnan 		dev_err(dev, "%s: ocxl_link_setup failed rc=%d\n",
76873904823SUma Krishnan 			__func__, rc);
76973904823SUma Krishnan 		goto out;
77073904823SUma Krishnan 	}
771c52bf5b3SUma Krishnan 
772c52bf5b3SUma Krishnan 	rc = ocxl_config_set_TL(pdev, fcfg->dvsec_tl_pos);
773c52bf5b3SUma Krishnan 	if (unlikely(rc)) {
774c52bf5b3SUma Krishnan 		dev_err(dev, "%s: ocxl_config_set_TL failed rc=%d\n",
775c52bf5b3SUma Krishnan 			__func__, rc);
776c52bf5b3SUma Krishnan 		goto err;
777c52bf5b3SUma Krishnan 	}
778e9dfcedaSUma Krishnan out:
779e9dfcedaSUma Krishnan 	return rc;
780c52bf5b3SUma Krishnan err:
781c52bf5b3SUma Krishnan 	ocxl_link_release(pdev, afu->link_token);
782c52bf5b3SUma Krishnan 	goto out;
783e9dfcedaSUma Krishnan }
784e9dfcedaSUma Krishnan 
785e9dfcedaSUma Krishnan /**
78673904823SUma Krishnan  * ocxlflash_unconfig_fn() - unconfigure the host function
78773904823SUma Krishnan  * @pdev:	PCI device associated with the host.
78873904823SUma Krishnan  * @afu:	AFU associated with the host.
78973904823SUma Krishnan  */
ocxlflash_unconfig_fn(struct pci_dev * pdev,struct ocxl_hw_afu * afu)79073904823SUma Krishnan static void ocxlflash_unconfig_fn(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
79173904823SUma Krishnan {
79273904823SUma Krishnan 	ocxl_link_release(pdev, afu->link_token);
79373904823SUma Krishnan }
79473904823SUma Krishnan 
79573904823SUma Krishnan /**
79654370503SUma Krishnan  * ocxlflash_map_mmio() - map the AFU MMIO space
79754370503SUma Krishnan  * @afu: AFU associated with the host.
79854370503SUma Krishnan  *
79954370503SUma Krishnan  * Return: 0 on success, -errno on failure
80054370503SUma Krishnan  */
ocxlflash_map_mmio(struct ocxl_hw_afu * afu)80154370503SUma Krishnan static int ocxlflash_map_mmio(struct ocxl_hw_afu *afu)
80254370503SUma Krishnan {
80354370503SUma Krishnan 	struct ocxl_afu_config *acfg = &afu->acfg;
80454370503SUma Krishnan 	struct pci_dev *pdev = afu->pdev;
80554370503SUma Krishnan 	struct device *dev = afu->dev;
80654370503SUma Krishnan 	phys_addr_t gmmio, ppmmio;
80754370503SUma Krishnan 	int rc = 0;
80854370503SUma Krishnan 
80954370503SUma Krishnan 	rc = pci_request_region(pdev, acfg->global_mmio_bar, "ocxlflash");
81054370503SUma Krishnan 	if (unlikely(rc)) {
81154370503SUma Krishnan 		dev_err(dev, "%s: pci_request_region for global failed rc=%d\n",
81254370503SUma Krishnan 			__func__, rc);
81354370503SUma Krishnan 		goto out;
81454370503SUma Krishnan 	}
81554370503SUma Krishnan 	gmmio = pci_resource_start(pdev, acfg->global_mmio_bar);
81654370503SUma Krishnan 	gmmio += acfg->global_mmio_offset;
81754370503SUma Krishnan 
81854370503SUma Krishnan 	rc = pci_request_region(pdev, acfg->pp_mmio_bar, "ocxlflash");
81954370503SUma Krishnan 	if (unlikely(rc)) {
82054370503SUma Krishnan 		dev_err(dev, "%s: pci_request_region for pp bar failed rc=%d\n",
82154370503SUma Krishnan 			__func__, rc);
82254370503SUma Krishnan 		goto err1;
82354370503SUma Krishnan 	}
82454370503SUma Krishnan 	ppmmio = pci_resource_start(pdev, acfg->pp_mmio_bar);
82554370503SUma Krishnan 	ppmmio += acfg->pp_mmio_offset;
82654370503SUma Krishnan 
82754370503SUma Krishnan 	afu->gmmio_virt = ioremap(gmmio, acfg->global_mmio_size);
82854370503SUma Krishnan 	if (unlikely(!afu->gmmio_virt)) {
82954370503SUma Krishnan 		dev_err(dev, "%s: MMIO mapping failed\n", __func__);
83054370503SUma Krishnan 		rc = -ENOMEM;
83154370503SUma Krishnan 		goto err2;
83254370503SUma Krishnan 	}
83354370503SUma Krishnan 
83454370503SUma Krishnan 	afu->gmmio_phys = gmmio;
83554370503SUma Krishnan 	afu->ppmmio_phys = ppmmio;
83654370503SUma Krishnan out:
83754370503SUma Krishnan 	return rc;
83854370503SUma Krishnan err2:
83954370503SUma Krishnan 	pci_release_region(pdev, acfg->pp_mmio_bar);
84054370503SUma Krishnan err1:
84154370503SUma Krishnan 	pci_release_region(pdev, acfg->global_mmio_bar);
84254370503SUma Krishnan 	goto out;
84354370503SUma Krishnan }
84454370503SUma Krishnan 
84554370503SUma Krishnan /**
8469cc84291SUma Krishnan  * ocxlflash_config_afu() - configure the host AFU
8479cc84291SUma Krishnan  * @pdev:	PCI device associated with the host.
8489cc84291SUma Krishnan  * @afu:	AFU associated with the host.
8499cc84291SUma Krishnan  *
8509cc84291SUma Krishnan  * Must be called _after_ host function configuration.
8519cc84291SUma Krishnan  *
8529cc84291SUma Krishnan  * Return: 0 on success, -errno on failure
8539cc84291SUma Krishnan  */
ocxlflash_config_afu(struct pci_dev * pdev,struct ocxl_hw_afu * afu)8549cc84291SUma Krishnan static int ocxlflash_config_afu(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
8559cc84291SUma Krishnan {
8569cc84291SUma Krishnan 	struct ocxl_afu_config *acfg = &afu->acfg;
8579cc84291SUma Krishnan 	struct ocxl_fn_config *fcfg = &afu->fcfg;
8589cc84291SUma Krishnan 	struct device *dev = &pdev->dev;
859d926519eSUma Krishnan 	int count;
860d926519eSUma Krishnan 	int base;
861d926519eSUma Krishnan 	int pos;
8629cc84291SUma Krishnan 	int rc = 0;
8639cc84291SUma Krishnan 
8649cc84291SUma Krishnan 	/* This HW AFU function does not have any AFUs defined */
8659cc84291SUma Krishnan 	if (!afu->is_present)
8669cc84291SUma Krishnan 		goto out;
8679cc84291SUma Krishnan 
8689cc84291SUma Krishnan 	/* Read AFU config at index 0 */
8699cc84291SUma Krishnan 	rc = ocxl_config_read_afu(pdev, fcfg, acfg, 0);
8709cc84291SUma Krishnan 	if (unlikely(rc)) {
8719cc84291SUma Krishnan 		dev_err(dev, "%s: ocxl_config_read_afu failed rc=%d\n",
8729cc84291SUma Krishnan 			__func__, rc);
8739cc84291SUma Krishnan 		goto out;
8749cc84291SUma Krishnan 	}
875d926519eSUma Krishnan 
876d926519eSUma Krishnan 	/* Only one AFU per function is supported, so actag_base is same */
877d926519eSUma Krishnan 	base = afu->fn_actag_base;
878d926519eSUma Krishnan 	count = min_t(int, acfg->actag_supported, afu->fn_actag_enabled);
879d926519eSUma Krishnan 	pos = acfg->dvsec_afu_control_pos;
880d926519eSUma Krishnan 
881d926519eSUma Krishnan 	ocxl_config_set_afu_actag(pdev, pos, base, count);
882d926519eSUma Krishnan 	dev_dbg(dev, "%s: acTag base=%d enabled=%d\n", __func__, base, count);
883d926519eSUma Krishnan 	afu->afu_actag_base = base;
884d926519eSUma Krishnan 	afu->afu_actag_enabled = count;
88541df40d8SUma Krishnan 	afu->max_pasid = 1 << acfg->pasid_supported_log;
88641df40d8SUma Krishnan 
88741df40d8SUma Krishnan 	ocxl_config_set_afu_pasid(pdev, pos, 0, acfg->pasid_supported_log);
88854370503SUma Krishnan 
88954370503SUma Krishnan 	rc = ocxlflash_map_mmio(afu);
89054370503SUma Krishnan 	if (unlikely(rc)) {
89154370503SUma Krishnan 		dev_err(dev, "%s: ocxlflash_map_mmio failed rc=%d\n",
89254370503SUma Krishnan 			__func__, rc);
89354370503SUma Krishnan 		goto out;
89454370503SUma Krishnan 	}
8953351e4f0SUma Krishnan 
8963351e4f0SUma Krishnan 	/* Enable the AFU */
8973351e4f0SUma Krishnan 	ocxl_config_set_afu_state(pdev, acfg->dvsec_afu_control_pos, 1);
8989cc84291SUma Krishnan out:
8999cc84291SUma Krishnan 	return rc;
9009cc84291SUma Krishnan }
9019cc84291SUma Krishnan 
9029cc84291SUma Krishnan /**
90348e077dbSUma Krishnan  * ocxlflash_create_afu() - create the AFU for OCXL
90448e077dbSUma Krishnan  * @pdev:	PCI device associated with the host.
90548e077dbSUma Krishnan  *
90648e077dbSUma Krishnan  * Return: AFU on success, NULL on failure
90748e077dbSUma Krishnan  */
ocxlflash_create_afu(struct pci_dev * pdev)90848e077dbSUma Krishnan static void *ocxlflash_create_afu(struct pci_dev *pdev)
90948e077dbSUma Krishnan {
91048e077dbSUma Krishnan 	struct device *dev = &pdev->dev;
911f6b4557cSUma Krishnan 	struct ocxlflash_context *ctx;
91248e077dbSUma Krishnan 	struct ocxl_hw_afu *afu;
913e9dfcedaSUma Krishnan 	int rc;
91448e077dbSUma Krishnan 
91548e077dbSUma Krishnan 	afu = kzalloc(sizeof(*afu), GFP_KERNEL);
91648e077dbSUma Krishnan 	if (unlikely(!afu)) {
91748e077dbSUma Krishnan 		dev_err(dev, "%s: HW AFU allocation failed\n", __func__);
91848e077dbSUma Krishnan 		goto out;
91948e077dbSUma Krishnan 	}
92048e077dbSUma Krishnan 
92148e077dbSUma Krishnan 	afu->pdev = pdev;
92248e077dbSUma Krishnan 	afu->dev = dev;
923429ebfa6SUma Krishnan 	idr_init(&afu->idr);
924e9dfcedaSUma Krishnan 
925e9dfcedaSUma Krishnan 	rc = ocxlflash_config_fn(pdev, afu);
926e9dfcedaSUma Krishnan 	if (unlikely(rc)) {
927e9dfcedaSUma Krishnan 		dev_err(dev, "%s: Function configuration failed rc=%d\n",
928e9dfcedaSUma Krishnan 			__func__, rc);
929e9dfcedaSUma Krishnan 		goto err1;
930e9dfcedaSUma Krishnan 	}
9319cc84291SUma Krishnan 
9329cc84291SUma Krishnan 	rc = ocxlflash_config_afu(pdev, afu);
9339cc84291SUma Krishnan 	if (unlikely(rc)) {
9349cc84291SUma Krishnan 		dev_err(dev, "%s: AFU configuration failed rc=%d\n",
9359cc84291SUma Krishnan 			__func__, rc);
93673904823SUma Krishnan 		goto err2;
9379cc84291SUma Krishnan 	}
938f6b4557cSUma Krishnan 
939f6b4557cSUma Krishnan 	ctx = ocxlflash_dev_context_init(pdev, afu);
940f6b4557cSUma Krishnan 	if (IS_ERR(ctx)) {
941f6b4557cSUma Krishnan 		rc = PTR_ERR(ctx);
942f6b4557cSUma Krishnan 		dev_err(dev, "%s: ocxlflash_dev_context_init failed rc=%d\n",
943f6b4557cSUma Krishnan 			__func__, rc);
94473904823SUma Krishnan 		goto err3;
945f6b4557cSUma Krishnan 	}
946f6b4557cSUma Krishnan 
947f6b4557cSUma Krishnan 	afu->ocxl_ctx = ctx;
94848e077dbSUma Krishnan out:
94948e077dbSUma Krishnan 	return afu;
95073904823SUma Krishnan err3:
95154370503SUma Krishnan 	ocxlflash_unconfig_afu(afu);
95273904823SUma Krishnan err2:
95373904823SUma Krishnan 	ocxlflash_unconfig_fn(pdev, afu);
954e9dfcedaSUma Krishnan err1:
955429ebfa6SUma Krishnan 	idr_destroy(&afu->idr);
956e9dfcedaSUma Krishnan 	kfree(afu);
957e9dfcedaSUma Krishnan 	afu = NULL;
958e9dfcedaSUma Krishnan 	goto out;
95948e077dbSUma Krishnan }
96076ebe01fSUma Krishnan 
96156f1db1aSUma Krishnan /**
96256f1db1aSUma Krishnan  * ctx_event_pending() - check for any event pending on the context
96356f1db1aSUma Krishnan  * @ctx:	Context to be checked.
96456f1db1aSUma Krishnan  *
96556f1db1aSUma Krishnan  * Return: true if there is an event pending, false if none pending
96656f1db1aSUma Krishnan  */
ctx_event_pending(struct ocxlflash_context * ctx)96756f1db1aSUma Krishnan static inline bool ctx_event_pending(struct ocxlflash_context *ctx)
96856f1db1aSUma Krishnan {
96966ae644bSUma Krishnan 	if (ctx->pending_irq || ctx->pending_fault)
97056f1db1aSUma Krishnan 		return true;
97156f1db1aSUma Krishnan 
97256f1db1aSUma Krishnan 	return false;
97356f1db1aSUma Krishnan }
97456f1db1aSUma Krishnan 
97556f1db1aSUma Krishnan /**
97656f1db1aSUma Krishnan  * afu_poll() - poll the AFU for events on the context
97756f1db1aSUma Krishnan  * @file:	File associated with the adapter context.
97856f1db1aSUma Krishnan  * @poll:	Poll structure from the user.
97956f1db1aSUma Krishnan  *
98056f1db1aSUma Krishnan  * Return: poll mask
98156f1db1aSUma Krishnan  */
afu_poll(struct file * file,struct poll_table_struct * poll)98256f1db1aSUma Krishnan static unsigned int afu_poll(struct file *file, struct poll_table_struct *poll)
98356f1db1aSUma Krishnan {
98456f1db1aSUma Krishnan 	struct ocxlflash_context *ctx = file->private_data;
98556f1db1aSUma Krishnan 	struct device *dev = ctx->hw_afu->dev;
98656f1db1aSUma Krishnan 	ulong lock_flags;
98756f1db1aSUma Krishnan 	int mask = 0;
98856f1db1aSUma Krishnan 
98956f1db1aSUma Krishnan 	poll_wait(file, &ctx->wq, poll);
99056f1db1aSUma Krishnan 
99156f1db1aSUma Krishnan 	spin_lock_irqsave(&ctx->slock, lock_flags);
99256f1db1aSUma Krishnan 	if (ctx_event_pending(ctx))
99356f1db1aSUma Krishnan 		mask |= POLLIN | POLLRDNORM;
994f81face7SUma Krishnan 	else if (ctx->state == CLOSED)
99556f1db1aSUma Krishnan 		mask |= POLLERR;
99656f1db1aSUma Krishnan 	spin_unlock_irqrestore(&ctx->slock, lock_flags);
99756f1db1aSUma Krishnan 
99856f1db1aSUma Krishnan 	dev_dbg(dev, "%s: Poll wait completed for pe %i mask %i\n",
99956f1db1aSUma Krishnan 		__func__, ctx->pe, mask);
100056f1db1aSUma Krishnan 
100156f1db1aSUma Krishnan 	return mask;
100256f1db1aSUma Krishnan }
100356f1db1aSUma Krishnan 
100403aa9c51SUma Krishnan /**
100503aa9c51SUma Krishnan  * afu_read() - perform a read on the context for any event
100603aa9c51SUma Krishnan  * @file:	File associated with the adapter context.
100703aa9c51SUma Krishnan  * @buf:	Buffer to receive the data.
100803aa9c51SUma Krishnan  * @count:	Size of buffer (maximum bytes that can be read).
100903aa9c51SUma Krishnan  * @off:	Offset.
101003aa9c51SUma Krishnan  *
101103aa9c51SUma Krishnan  * Return: size of the data read on success, -errno on failure
101203aa9c51SUma Krishnan  */
afu_read(struct file * file,char __user * buf,size_t count,loff_t * off)101303aa9c51SUma Krishnan static ssize_t afu_read(struct file *file, char __user *buf, size_t count,
101403aa9c51SUma Krishnan 			loff_t *off)
101503aa9c51SUma Krishnan {
101603aa9c51SUma Krishnan 	struct ocxlflash_context *ctx = file->private_data;
101703aa9c51SUma Krishnan 	struct device *dev = ctx->hw_afu->dev;
101803aa9c51SUma Krishnan 	struct cxl_event event;
101903aa9c51SUma Krishnan 	ulong lock_flags;
102003aa9c51SUma Krishnan 	ssize_t esize;
102103aa9c51SUma Krishnan 	ssize_t rc;
102203aa9c51SUma Krishnan 	int bit;
102303aa9c51SUma Krishnan 	DEFINE_WAIT(event_wait);
102403aa9c51SUma Krishnan 
102503aa9c51SUma Krishnan 	if (*off != 0) {
102603aa9c51SUma Krishnan 		dev_err(dev, "%s: Non-zero offset not supported, off=%lld\n",
102703aa9c51SUma Krishnan 			__func__, *off);
102803aa9c51SUma Krishnan 		rc = -EINVAL;
102903aa9c51SUma Krishnan 		goto out;
103003aa9c51SUma Krishnan 	}
103103aa9c51SUma Krishnan 
103203aa9c51SUma Krishnan 	spin_lock_irqsave(&ctx->slock, lock_flags);
103303aa9c51SUma Krishnan 
103403aa9c51SUma Krishnan 	for (;;) {
103503aa9c51SUma Krishnan 		prepare_to_wait(&ctx->wq, &event_wait, TASK_INTERRUPTIBLE);
103603aa9c51SUma Krishnan 
1037f81face7SUma Krishnan 		if (ctx_event_pending(ctx) || (ctx->state == CLOSED))
103803aa9c51SUma Krishnan 			break;
103903aa9c51SUma Krishnan 
104003aa9c51SUma Krishnan 		if (file->f_flags & O_NONBLOCK) {
104103aa9c51SUma Krishnan 			dev_err(dev, "%s: File cannot be blocked on I/O\n",
104203aa9c51SUma Krishnan 				__func__);
104303aa9c51SUma Krishnan 			rc = -EAGAIN;
104403aa9c51SUma Krishnan 			goto err;
104503aa9c51SUma Krishnan 		}
104603aa9c51SUma Krishnan 
104703aa9c51SUma Krishnan 		if (signal_pending(current)) {
104803aa9c51SUma Krishnan 			dev_err(dev, "%s: Signal pending on the process\n",
104903aa9c51SUma Krishnan 				__func__);
105003aa9c51SUma Krishnan 			rc = -ERESTARTSYS;
105103aa9c51SUma Krishnan 			goto err;
105203aa9c51SUma Krishnan 		}
105303aa9c51SUma Krishnan 
105403aa9c51SUma Krishnan 		spin_unlock_irqrestore(&ctx->slock, lock_flags);
105503aa9c51SUma Krishnan 		schedule();
105603aa9c51SUma Krishnan 		spin_lock_irqsave(&ctx->slock, lock_flags);
105703aa9c51SUma Krishnan 	}
105803aa9c51SUma Krishnan 
105903aa9c51SUma Krishnan 	finish_wait(&ctx->wq, &event_wait);
106003aa9c51SUma Krishnan 
106103aa9c51SUma Krishnan 	memset(&event, 0, sizeof(event));
106203aa9c51SUma Krishnan 	event.header.process_element = ctx->pe;
106303aa9c51SUma Krishnan 	event.header.size = sizeof(struct cxl_event_header);
106403aa9c51SUma Krishnan 	if (ctx->pending_irq) {
106503aa9c51SUma Krishnan 		esize = sizeof(struct cxl_event_afu_interrupt);
106603aa9c51SUma Krishnan 		event.header.size += esize;
106703aa9c51SUma Krishnan 		event.header.type = CXL_EVENT_AFU_INTERRUPT;
106803aa9c51SUma Krishnan 
106903aa9c51SUma Krishnan 		bit = find_first_bit(&ctx->irq_bitmap, ctx->num_irqs);
107003aa9c51SUma Krishnan 		clear_bit(bit, &ctx->irq_bitmap);
107103aa9c51SUma Krishnan 		event.irq.irq = bit + 1;
107203aa9c51SUma Krishnan 		if (bitmap_empty(&ctx->irq_bitmap, ctx->num_irqs))
107303aa9c51SUma Krishnan 			ctx->pending_irq = false;
107466ae644bSUma Krishnan 	} else if (ctx->pending_fault) {
107566ae644bSUma Krishnan 		event.header.size += sizeof(struct cxl_event_data_storage);
107666ae644bSUma Krishnan 		event.header.type = CXL_EVENT_DATA_STORAGE;
107766ae644bSUma Krishnan 		event.fault.addr = ctx->fault_addr;
107866ae644bSUma Krishnan 		event.fault.dsisr = ctx->fault_dsisr;
107966ae644bSUma Krishnan 		ctx->pending_fault = false;
108003aa9c51SUma Krishnan 	}
108103aa9c51SUma Krishnan 
108203aa9c51SUma Krishnan 	spin_unlock_irqrestore(&ctx->slock, lock_flags);
108303aa9c51SUma Krishnan 
108403aa9c51SUma Krishnan 	if (copy_to_user(buf, &event, event.header.size)) {
108503aa9c51SUma Krishnan 		dev_err(dev, "%s: copy_to_user failed\n", __func__);
108603aa9c51SUma Krishnan 		rc = -EFAULT;
108703aa9c51SUma Krishnan 		goto out;
108803aa9c51SUma Krishnan 	}
108903aa9c51SUma Krishnan 
109003aa9c51SUma Krishnan 	rc = event.header.size;
109103aa9c51SUma Krishnan out:
109203aa9c51SUma Krishnan 	return rc;
109303aa9c51SUma Krishnan err:
109403aa9c51SUma Krishnan 	finish_wait(&ctx->wq, &event_wait);
109503aa9c51SUma Krishnan 	spin_unlock_irqrestore(&ctx->slock, lock_flags);
109603aa9c51SUma Krishnan 	goto out;
109703aa9c51SUma Krishnan }
109803aa9c51SUma Krishnan 
109993b8f8dfSUma Krishnan /**
110093b8f8dfSUma Krishnan  * afu_release() - release and free the context
110193b8f8dfSUma Krishnan  * @inode:	File inode pointer.
110293b8f8dfSUma Krishnan  * @file:	File associated with the context.
110393b8f8dfSUma Krishnan  *
110493b8f8dfSUma Krishnan  * Return: 0 on success, -errno on failure
110593b8f8dfSUma Krishnan  */
afu_release(struct inode * inode,struct file * file)110693b8f8dfSUma Krishnan static int afu_release(struct inode *inode, struct file *file)
110793b8f8dfSUma Krishnan {
110893b8f8dfSUma Krishnan 	struct ocxlflash_context *ctx = file->private_data;
110993b8f8dfSUma Krishnan 	int i;
111093b8f8dfSUma Krishnan 
111193b8f8dfSUma Krishnan 	/* Unmap and free the interrupts associated with the context */
111293b8f8dfSUma Krishnan 	for (i = ctx->num_irqs; i >= 0; i--)
111393b8f8dfSUma Krishnan 		afu_unmap_irq(0, ctx, i, ctx);
111493b8f8dfSUma Krishnan 	free_afu_irqs(ctx);
111593b8f8dfSUma Krishnan 
111693b8f8dfSUma Krishnan 	return ocxlflash_release_context(ctx);
111793b8f8dfSUma Krishnan }
111893b8f8dfSUma Krishnan 
111993b8f8dfSUma Krishnan /**
112093b8f8dfSUma Krishnan  * ocxlflash_mmap_fault() - mmap fault handler
112193b8f8dfSUma Krishnan  * @vmf:	VM fault associated with current fault.
112293b8f8dfSUma Krishnan  *
112393b8f8dfSUma Krishnan  * Return: 0 on success, -errno on failure
112493b8f8dfSUma Krishnan  */
ocxlflash_mmap_fault(struct vm_fault * vmf)1125a38b80c5SSouptick Joarder static vm_fault_t ocxlflash_mmap_fault(struct vm_fault *vmf)
112693b8f8dfSUma Krishnan {
112793b8f8dfSUma Krishnan 	struct vm_area_struct *vma = vmf->vma;
112893b8f8dfSUma Krishnan 	struct ocxlflash_context *ctx = vma->vm_file->private_data;
1129f81face7SUma Krishnan 	struct device *dev = ctx->hw_afu->dev;
113093b8f8dfSUma Krishnan 	u64 mmio_area, offset;
113193b8f8dfSUma Krishnan 
113293b8f8dfSUma Krishnan 	offset = vmf->pgoff << PAGE_SHIFT;
113393b8f8dfSUma Krishnan 	if (offset >= ctx->psn_size)
113493b8f8dfSUma Krishnan 		return VM_FAULT_SIGBUS;
113593b8f8dfSUma Krishnan 
1136f81face7SUma Krishnan 	mutex_lock(&ctx->state_mutex);
1137f81face7SUma Krishnan 	if (ctx->state != STARTED) {
1138f81face7SUma Krishnan 		dev_err(dev, "%s: Context not started, state=%d\n",
1139f81face7SUma Krishnan 			__func__, ctx->state);
1140f81face7SUma Krishnan 		mutex_unlock(&ctx->state_mutex);
1141f81face7SUma Krishnan 		return VM_FAULT_SIGBUS;
1142f81face7SUma Krishnan 	}
1143f81face7SUma Krishnan 	mutex_unlock(&ctx->state_mutex);
1144f81face7SUma Krishnan 
114593b8f8dfSUma Krishnan 	mmio_area = ctx->psn_phys;
114693b8f8dfSUma Krishnan 	mmio_area += offset;
114793b8f8dfSUma Krishnan 
1148a38b80c5SSouptick Joarder 	return vmf_insert_pfn(vma, vmf->address, mmio_area >> PAGE_SHIFT);
114993b8f8dfSUma Krishnan }
115093b8f8dfSUma Krishnan 
115193b8f8dfSUma Krishnan static const struct vm_operations_struct ocxlflash_vmops = {
115293b8f8dfSUma Krishnan 	.fault = ocxlflash_mmap_fault,
115393b8f8dfSUma Krishnan };
115493b8f8dfSUma Krishnan 
115593b8f8dfSUma Krishnan /**
115693b8f8dfSUma Krishnan  * afu_mmap() - map the fault handler operations
115793b8f8dfSUma Krishnan  * @file:	File associated with the context.
115893b8f8dfSUma Krishnan  * @vma:	VM area associated with mapping.
115993b8f8dfSUma Krishnan  *
116093b8f8dfSUma Krishnan  * Return: 0 on success, -errno on failure
116193b8f8dfSUma Krishnan  */
afu_mmap(struct file * file,struct vm_area_struct * vma)116293b8f8dfSUma Krishnan static int afu_mmap(struct file *file, struct vm_area_struct *vma)
116393b8f8dfSUma Krishnan {
116493b8f8dfSUma Krishnan 	struct ocxlflash_context *ctx = file->private_data;
116593b8f8dfSUma Krishnan 
116693b8f8dfSUma Krishnan 	if ((vma_pages(vma) + vma->vm_pgoff) >
116793b8f8dfSUma Krishnan 	    (ctx->psn_size >> PAGE_SHIFT))
116893b8f8dfSUma Krishnan 		return -EINVAL;
116993b8f8dfSUma Krishnan 
1170*1c71222eSSuren Baghdasaryan 	vm_flags_set(vma, VM_IO | VM_PFNMAP);
117193b8f8dfSUma Krishnan 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
117293b8f8dfSUma Krishnan 	vma->vm_ops = &ocxlflash_vmops;
117393b8f8dfSUma Krishnan 	return 0;
117493b8f8dfSUma Krishnan }
117593b8f8dfSUma Krishnan 
1176926a62f9SUma Krishnan static const struct file_operations ocxl_afu_fops = {
1177926a62f9SUma Krishnan 	.owner		= THIS_MODULE,
117856f1db1aSUma Krishnan 	.poll		= afu_poll,
117903aa9c51SUma Krishnan 	.read		= afu_read,
118093b8f8dfSUma Krishnan 	.release	= afu_release,
118193b8f8dfSUma Krishnan 	.mmap		= afu_mmap,
1182926a62f9SUma Krishnan };
1183926a62f9SUma Krishnan 
118456f1db1aSUma Krishnan #define PATCH_FOPS(NAME)						\
118556f1db1aSUma Krishnan 	do { if (!fops->NAME) fops->NAME = ocxl_afu_fops.NAME; } while (0)
118656f1db1aSUma Krishnan 
1187926a62f9SUma Krishnan /**
1188926a62f9SUma Krishnan  * ocxlflash_get_fd() - get file descriptor for an adapter context
1189926a62f9SUma Krishnan  * @ctx_cookie:	Adapter context.
1190926a62f9SUma Krishnan  * @fops:	File operations to be associated.
1191926a62f9SUma Krishnan  * @fd:		File descriptor to be returned back.
1192926a62f9SUma Krishnan  *
1193926a62f9SUma Krishnan  * Return: pointer to the file on success, ERR_PTR on failure
1194926a62f9SUma Krishnan  */
ocxlflash_get_fd(void * ctx_cookie,struct file_operations * fops,int * fd)1195926a62f9SUma Krishnan static struct file *ocxlflash_get_fd(void *ctx_cookie,
1196926a62f9SUma Krishnan 				     struct file_operations *fops, int *fd)
1197926a62f9SUma Krishnan {
1198926a62f9SUma Krishnan 	struct ocxlflash_context *ctx = ctx_cookie;
1199926a62f9SUma Krishnan 	struct device *dev = ctx->hw_afu->dev;
1200926a62f9SUma Krishnan 	struct file *file;
1201926a62f9SUma Krishnan 	int flags, fdtmp;
1202926a62f9SUma Krishnan 	int rc = 0;
1203926a62f9SUma Krishnan 	char *name = NULL;
1204926a62f9SUma Krishnan 
1205926a62f9SUma Krishnan 	/* Only allow one fd per context */
1206926a62f9SUma Krishnan 	if (ctx->mapping) {
1207926a62f9SUma Krishnan 		dev_err(dev, "%s: Context is already mapped to an fd\n",
1208926a62f9SUma Krishnan 			__func__);
1209926a62f9SUma Krishnan 		rc = -EEXIST;
1210926a62f9SUma Krishnan 		goto err1;
1211926a62f9SUma Krishnan 	}
1212926a62f9SUma Krishnan 
1213926a62f9SUma Krishnan 	flags = O_RDWR | O_CLOEXEC;
1214926a62f9SUma Krishnan 
1215926a62f9SUma Krishnan 	/* This code is similar to anon_inode_getfd() */
1216926a62f9SUma Krishnan 	rc = get_unused_fd_flags(flags);
1217926a62f9SUma Krishnan 	if (unlikely(rc < 0)) {
1218926a62f9SUma Krishnan 		dev_err(dev, "%s: get_unused_fd_flags failed rc=%d\n",
1219926a62f9SUma Krishnan 			__func__, rc);
1220926a62f9SUma Krishnan 		goto err1;
1221926a62f9SUma Krishnan 	}
1222926a62f9SUma Krishnan 	fdtmp = rc;
1223926a62f9SUma Krishnan 
122456f1db1aSUma Krishnan 	/* Patch the file ops that are not defined */
122556f1db1aSUma Krishnan 	if (fops) {
122656f1db1aSUma Krishnan 		PATCH_FOPS(poll);
122703aa9c51SUma Krishnan 		PATCH_FOPS(read);
122893b8f8dfSUma Krishnan 		PATCH_FOPS(release);
122993b8f8dfSUma Krishnan 		PATCH_FOPS(mmap);
123056f1db1aSUma Krishnan 	} else /* Use default ops */
1231926a62f9SUma Krishnan 		fops = (struct file_operations *)&ocxl_afu_fops;
1232926a62f9SUma Krishnan 
1233926a62f9SUma Krishnan 	name = kasprintf(GFP_KERNEL, "ocxlflash:%d", ctx->pe);
1234926a62f9SUma Krishnan 	file = ocxlflash_getfile(dev, name, fops, ctx, flags);
1235926a62f9SUma Krishnan 	kfree(name);
1236926a62f9SUma Krishnan 	if (IS_ERR(file)) {
1237926a62f9SUma Krishnan 		rc = PTR_ERR(file);
1238926a62f9SUma Krishnan 		dev_err(dev, "%s: ocxlflash_getfile failed rc=%d\n",
1239926a62f9SUma Krishnan 			__func__, rc);
1240926a62f9SUma Krishnan 		goto err2;
1241926a62f9SUma Krishnan 	}
1242926a62f9SUma Krishnan 
1243926a62f9SUma Krishnan 	ctx->mapping = file->f_mapping;
1244926a62f9SUma Krishnan 	*fd = fdtmp;
1245926a62f9SUma Krishnan out:
1246926a62f9SUma Krishnan 	return file;
1247926a62f9SUma Krishnan err2:
1248926a62f9SUma Krishnan 	put_unused_fd(fdtmp);
1249926a62f9SUma Krishnan err1:
1250926a62f9SUma Krishnan 	file = ERR_PTR(rc);
1251926a62f9SUma Krishnan 	goto out;
1252926a62f9SUma Krishnan }
1253926a62f9SUma Krishnan 
1254b18718c6SUma Krishnan /**
1255b18718c6SUma Krishnan  * ocxlflash_fops_get_context() - get the context associated with the file
1256b18718c6SUma Krishnan  * @file:	File associated with the adapter context.
1257b18718c6SUma Krishnan  *
1258b18718c6SUma Krishnan  * Return: pointer to the context
1259b18718c6SUma Krishnan  */
ocxlflash_fops_get_context(struct file * file)1260b18718c6SUma Krishnan static void *ocxlflash_fops_get_context(struct file *file)
1261b18718c6SUma Krishnan {
1262b18718c6SUma Krishnan 	return file->private_data;
1263b18718c6SUma Krishnan }
1264b18718c6SUma Krishnan 
1265762c7e93SUma Krishnan /**
1266762c7e93SUma Krishnan  * ocxlflash_afu_irq() - interrupt handler for user contexts
1267762c7e93SUma Krishnan  * @irq:	Interrupt number.
1268762c7e93SUma Krishnan  * @data:	Private data provided at interrupt registration, the context.
1269762c7e93SUma Krishnan  *
1270762c7e93SUma Krishnan  * Return: Always return IRQ_HANDLED.
1271762c7e93SUma Krishnan  */
ocxlflash_afu_irq(int irq,void * data)1272762c7e93SUma Krishnan static irqreturn_t ocxlflash_afu_irq(int irq, void *data)
1273762c7e93SUma Krishnan {
1274762c7e93SUma Krishnan 	struct ocxlflash_context *ctx = data;
1275762c7e93SUma Krishnan 	struct device *dev = ctx->hw_afu->dev;
1276762c7e93SUma Krishnan 	int i;
1277762c7e93SUma Krishnan 
1278762c7e93SUma Krishnan 	dev_dbg(dev, "%s: Interrupt raised for pe %i virq %i\n",
1279762c7e93SUma Krishnan 		__func__, ctx->pe, irq);
1280762c7e93SUma Krishnan 
1281762c7e93SUma Krishnan 	for (i = 0; i < ctx->num_irqs; i++) {
1282762c7e93SUma Krishnan 		if (ctx->irqs[i].virq == irq)
1283762c7e93SUma Krishnan 			break;
1284762c7e93SUma Krishnan 	}
1285762c7e93SUma Krishnan 	if (unlikely(i >= ctx->num_irqs)) {
1286762c7e93SUma Krishnan 		dev_err(dev, "%s: Received AFU IRQ out of range\n", __func__);
1287762c7e93SUma Krishnan 		goto out;
1288762c7e93SUma Krishnan 	}
1289762c7e93SUma Krishnan 
1290762c7e93SUma Krishnan 	spin_lock(&ctx->slock);
1291762c7e93SUma Krishnan 	set_bit(i - 1, &ctx->irq_bitmap);
1292762c7e93SUma Krishnan 	ctx->pending_irq = true;
1293762c7e93SUma Krishnan 	spin_unlock(&ctx->slock);
129456f1db1aSUma Krishnan 
129556f1db1aSUma Krishnan 	wake_up_all(&ctx->wq);
1296762c7e93SUma Krishnan out:
1297762c7e93SUma Krishnan 	return IRQ_HANDLED;
1298762c7e93SUma Krishnan }
1299762c7e93SUma Krishnan 
1300762c7e93SUma Krishnan /**
1301762c7e93SUma Krishnan  * ocxlflash_start_work() - start a user context
1302762c7e93SUma Krishnan  * @ctx_cookie:	Context to be started.
1303762c7e93SUma Krishnan  * @num_irqs:	Number of interrupts requested.
1304762c7e93SUma Krishnan  *
1305762c7e93SUma Krishnan  * Return: 0 on success, -errno on failure
1306762c7e93SUma Krishnan  */
ocxlflash_start_work(void * ctx_cookie,u64 num_irqs)1307762c7e93SUma Krishnan static int ocxlflash_start_work(void *ctx_cookie, u64 num_irqs)
1308762c7e93SUma Krishnan {
1309762c7e93SUma Krishnan 	struct ocxlflash_context *ctx = ctx_cookie;
1310762c7e93SUma Krishnan 	struct ocxl_hw_afu *afu = ctx->hw_afu;
1311762c7e93SUma Krishnan 	struct device *dev = afu->dev;
1312762c7e93SUma Krishnan 	char *name;
1313762c7e93SUma Krishnan 	int rc = 0;
1314762c7e93SUma Krishnan 	int i;
1315762c7e93SUma Krishnan 
1316762c7e93SUma Krishnan 	rc = alloc_afu_irqs(ctx, num_irqs);
1317762c7e93SUma Krishnan 	if (unlikely(rc < 0)) {
1318762c7e93SUma Krishnan 		dev_err(dev, "%s: alloc_afu_irqs failed rc=%d\n", __func__, rc);
1319762c7e93SUma Krishnan 		goto out;
1320762c7e93SUma Krishnan 	}
1321762c7e93SUma Krishnan 
1322762c7e93SUma Krishnan 	for (i = 0; i < num_irqs; i++) {
1323762c7e93SUma Krishnan 		name = kasprintf(GFP_KERNEL, "ocxlflash-%s-pe%i-%i",
1324762c7e93SUma Krishnan 				 dev_name(dev), ctx->pe, i);
1325762c7e93SUma Krishnan 		rc = afu_map_irq(0, ctx, i, ocxlflash_afu_irq, ctx, name);
1326762c7e93SUma Krishnan 		kfree(name);
1327762c7e93SUma Krishnan 		if (unlikely(rc < 0)) {
1328762c7e93SUma Krishnan 			dev_err(dev, "%s: afu_map_irq failed rc=%d\n",
1329762c7e93SUma Krishnan 				__func__, rc);
1330762c7e93SUma Krishnan 			goto err;
1331762c7e93SUma Krishnan 		}
1332762c7e93SUma Krishnan 	}
1333762c7e93SUma Krishnan 
1334762c7e93SUma Krishnan 	rc = start_context(ctx);
1335762c7e93SUma Krishnan 	if (unlikely(rc)) {
1336762c7e93SUma Krishnan 		dev_err(dev, "%s: start_context failed rc=%d\n", __func__, rc);
1337762c7e93SUma Krishnan 		goto err;
1338762c7e93SUma Krishnan 	}
1339762c7e93SUma Krishnan out:
1340762c7e93SUma Krishnan 	return rc;
1341762c7e93SUma Krishnan err:
1342762c7e93SUma Krishnan 	for (i = i-1; i >= 0; i--)
1343762c7e93SUma Krishnan 		afu_unmap_irq(0, ctx, i, ctx);
1344762c7e93SUma Krishnan 	free_afu_irqs(ctx);
1345762c7e93SUma Krishnan 	goto out;
1346e117c3c7SUma Krishnan };
1347e117c3c7SUma Krishnan 
1348e117c3c7SUma Krishnan /**
1349e117c3c7SUma Krishnan  * ocxlflash_fd_mmap() - mmap handler for adapter file descriptor
1350e117c3c7SUma Krishnan  * @file:	File installed with adapter file descriptor.
1351e117c3c7SUma Krishnan  * @vma:	VM area associated with mapping.
1352e117c3c7SUma Krishnan  *
1353e117c3c7SUma Krishnan  * Return: 0 on success, -errno on failure
1354e117c3c7SUma Krishnan  */
ocxlflash_fd_mmap(struct file * file,struct vm_area_struct * vma)1355e117c3c7SUma Krishnan static int ocxlflash_fd_mmap(struct file *file, struct vm_area_struct *vma)
1356e117c3c7SUma Krishnan {
1357e117c3c7SUma Krishnan 	return afu_mmap(file, vma);
1358e117c3c7SUma Krishnan }
1359e117c3c7SUma Krishnan 
1360e117c3c7SUma Krishnan /**
1361e117c3c7SUma Krishnan  * ocxlflash_fd_release() - release the context associated with the file
1362e117c3c7SUma Krishnan  * @inode:	File inode pointer.
1363e117c3c7SUma Krishnan  * @file:	File associated with the adapter context.
1364e117c3c7SUma Krishnan  *
1365e117c3c7SUma Krishnan  * Return: 0 on success, -errno on failure
1366e117c3c7SUma Krishnan  */
ocxlflash_fd_release(struct inode * inode,struct file * file)1367e117c3c7SUma Krishnan static int ocxlflash_fd_release(struct inode *inode, struct file *file)
1368e117c3c7SUma Krishnan {
1369e117c3c7SUma Krishnan 	return afu_release(inode, file);
1370762c7e93SUma Krishnan }
1371762c7e93SUma Krishnan 
137276ebe01fSUma Krishnan /* Backend ops to ocxlflash services */
137376ebe01fSUma Krishnan const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
137476ebe01fSUma Krishnan 	.module			= THIS_MODULE,
1375012f394cSUma Krishnan 	.psa_map		= ocxlflash_psa_map,
1376012f394cSUma Krishnan 	.psa_unmap		= ocxlflash_psa_unmap,
1377b18718c6SUma Krishnan 	.process_element	= ocxlflash_process_element,
1378a06b1cfcSUma Krishnan 	.map_afu_irq		= ocxlflash_map_afu_irq,
1379a06b1cfcSUma Krishnan 	.unmap_afu_irq		= ocxlflash_unmap_afu_irq,
1380402a55eaSUma Krishnan 	.get_irq_objhndl	= ocxlflash_get_irq_objhndl,
13816b938ac9SUma Krishnan 	.start_context		= ocxlflash_start_context,
1382c207b571SUma Krishnan 	.stop_context		= ocxlflash_stop_context,
13839433fb32SUma Krishnan 	.afu_reset		= ocxlflash_afu_reset,
1384f6b4557cSUma Krishnan 	.set_master		= ocxlflash_set_master,
1385f6b4557cSUma Krishnan 	.get_context		= ocxlflash_get_context,
1386f6b4557cSUma Krishnan 	.dev_context_init	= ocxlflash_dev_context_init,
1387f6b4557cSUma Krishnan 	.release_context	= ocxlflash_release_context,
13888b7a5521SUma Krishnan 	.perst_reloads_same_image = ocxlflash_perst_reloads_same_image,
1389119c9200SUma Krishnan 	.read_adapter_vpd	= ocxlflash_read_adapter_vpd,
1390bc65c1c7SUma Krishnan 	.allocate_afu_irqs	= ocxlflash_allocate_afu_irqs,
1391bc65c1c7SUma Krishnan 	.free_afu_irqs		= ocxlflash_free_afu_irqs,
139248e077dbSUma Krishnan 	.create_afu		= ocxlflash_create_afu,
139348e077dbSUma Krishnan 	.destroy_afu		= ocxlflash_destroy_afu,
1394926a62f9SUma Krishnan 	.get_fd			= ocxlflash_get_fd,
1395b18718c6SUma Krishnan 	.fops_get_context	= ocxlflash_fops_get_context,
1396762c7e93SUma Krishnan 	.start_work		= ocxlflash_start_work,
1397e117c3c7SUma Krishnan 	.fd_mmap		= ocxlflash_fd_mmap,
1398e117c3c7SUma Krishnan 	.fd_release		= ocxlflash_fd_release,
139976ebe01fSUma Krishnan };
1400