]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/scsi/cxlflash/ocxl_hw.c
scsi: cxlflash: Support AFU interrupt management
[mirror_ubuntu-focal-kernel.git] / drivers / scsi / cxlflash / ocxl_hw.c
CommitLineData
76ebe01f
UK
1/*
2 * CXL Flash Device Driver
3 *
4 * Written by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>, IBM Corporation
5 * Uma Krishnan <ukrishn@linux.vnet.ibm.com>, IBM Corporation
6 *
7 * Copyright (C) 2018 IBM Corporation
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
926a62f9 15#include <linux/file.h>
429ebfa6 16#include <linux/idr.h>
926a62f9
UK
17#include <linux/module.h>
18#include <linux/mount.h>
429ebfa6 19
76ebe01f
UK
20#include <misc/ocxl.h>
21
22#include "backend.h"
48e077db
UK
23#include "ocxl_hw.h"
24
926a62f9
UK
25/*
26 * Pseudo-filesystem to allocate inodes.
27 */
28
29#define OCXLFLASH_FS_MAGIC 0x1697698f
30
31static int ocxlflash_fs_cnt;
32static struct vfsmount *ocxlflash_vfs_mount;
33
34static const struct dentry_operations ocxlflash_fs_dops = {
35 .d_dname = simple_dname,
36};
37
38/*
39 * ocxlflash_fs_mount() - mount the pseudo-filesystem
40 * @fs_type: File system type.
41 * @flags: Flags for the filesystem.
42 * @dev_name: Device name associated with the filesystem.
43 * @data: Data pointer.
44 *
45 * Return: pointer to the directory entry structure
46 */
47static struct dentry *ocxlflash_fs_mount(struct file_system_type *fs_type,
48 int flags, const char *dev_name,
49 void *data)
50{
51 return mount_pseudo(fs_type, "ocxlflash:", NULL, &ocxlflash_fs_dops,
52 OCXLFLASH_FS_MAGIC);
53}
54
55static struct file_system_type ocxlflash_fs_type = {
56 .name = "ocxlflash",
57 .owner = THIS_MODULE,
58 .mount = ocxlflash_fs_mount,
59 .kill_sb = kill_anon_super,
60};
61
62/*
63 * ocxlflash_release_mapping() - release the memory mapping
64 * @ctx: Context whose mapping is to be released.
65 */
66static void ocxlflash_release_mapping(struct ocxlflash_context *ctx)
67{
68 if (ctx->mapping)
69 simple_release_fs(&ocxlflash_vfs_mount, &ocxlflash_fs_cnt);
70 ctx->mapping = NULL;
71}
72
73/*
74 * ocxlflash_getfile() - allocate pseudo filesystem, inode, and the file
75 * @dev: Generic device of the host.
76 * @name: Name of the pseudo filesystem.
77 * @fops: File operations.
78 * @priv: Private data.
79 * @flags: Flags for the file.
80 *
81 * Return: pointer to the file on success, ERR_PTR on failure
82 */
83static struct file *ocxlflash_getfile(struct device *dev, const char *name,
84 const struct file_operations *fops,
85 void *priv, int flags)
86{
87 struct qstr this;
88 struct path path;
89 struct file *file;
90 struct inode *inode = NULL;
91 int rc;
92
93 if (fops->owner && !try_module_get(fops->owner)) {
94 dev_err(dev, "%s: Owner does not exist\n", __func__);
95 rc = -ENOENT;
96 goto err1;
97 }
98
99 rc = simple_pin_fs(&ocxlflash_fs_type, &ocxlflash_vfs_mount,
100 &ocxlflash_fs_cnt);
101 if (unlikely(rc < 0)) {
102 dev_err(dev, "%s: Cannot mount ocxlflash pseudofs rc=%d\n",
103 __func__, rc);
104 goto err2;
105 }
106
107 inode = alloc_anon_inode(ocxlflash_vfs_mount->mnt_sb);
108 if (IS_ERR(inode)) {
109 rc = PTR_ERR(inode);
110 dev_err(dev, "%s: alloc_anon_inode failed rc=%d\n",
111 __func__, rc);
112 goto err3;
113 }
114
115 this.name = name;
116 this.len = strlen(name);
117 this.hash = 0;
118 path.dentry = d_alloc_pseudo(ocxlflash_vfs_mount->mnt_sb, &this);
119 if (!path.dentry) {
120 dev_err(dev, "%s: d_alloc_pseudo failed\n", __func__);
121 rc = -ENOMEM;
122 goto err4;
123 }
124
125 path.mnt = mntget(ocxlflash_vfs_mount);
126 d_instantiate(path.dentry, inode);
127
128 file = alloc_file(&path, OPEN_FMODE(flags), fops);
129 if (IS_ERR(file)) {
130 rc = PTR_ERR(file);
131 dev_err(dev, "%s: alloc_file failed rc=%d\n",
132 __func__, rc);
133 goto err5;
134 }
135
136 file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
137 file->private_data = priv;
138out:
139 return file;
140err5:
141 path_put(&path);
142err4:
143 iput(inode);
144err3:
145 simple_release_fs(&ocxlflash_vfs_mount, &ocxlflash_fs_cnt);
146err2:
147 module_put(fops->owner);
148err1:
149 file = ERR_PTR(rc);
150 goto out;
151}
152
012f394c
UK
153/**
154 * ocxlflash_psa_map() - map the process specific MMIO space
155 * @ctx_cookie: Adapter context for which the mapping needs to be done.
156 *
157 * Return: MMIO pointer of the mapped region
158 */
159static void __iomem *ocxlflash_psa_map(void *ctx_cookie)
160{
161 struct ocxlflash_context *ctx = ctx_cookie;
162
163 return ioremap(ctx->psn_phys, ctx->psn_size);
164}
165
166/**
167 * ocxlflash_psa_unmap() - unmap the process specific MMIO space
168 * @addr: MMIO pointer to unmap.
169 */
170static void ocxlflash_psa_unmap(void __iomem *addr)
171{
172 iounmap(addr);
173}
174
b18718c6
UK
175/**
176 * ocxlflash_process_element() - get process element of the adapter context
177 * @ctx_cookie: Adapter context associated with the process element.
178 *
179 * Return: process element of the adapter context
180 */
181static int ocxlflash_process_element(void *ctx_cookie)
182{
183 struct ocxlflash_context *ctx = ctx_cookie;
184
185 return ctx->pe;
186}
187
6b938ac9
UK
188/**
189 * start_context() - local routine to start a context
190 * @ctx: Adapter context to be started.
191 *
c207b571 192 * Assign the context specific MMIO space, add and enable the PE.
6b938ac9
UK
193 *
194 * Return: 0 on success, -errno on failure
195 */
196static int start_context(struct ocxlflash_context *ctx)
197{
198 struct ocxl_hw_afu *afu = ctx->hw_afu;
199 struct ocxl_afu_config *acfg = &afu->acfg;
c207b571
UK
200 void *link_token = afu->link_token;
201 struct device *dev = afu->dev;
6b938ac9 202 bool master = ctx->master;
c207b571 203 int rc = 0;
6b938ac9
UK
204
205 if (master) {
206 ctx->psn_size = acfg->global_mmio_size;
207 ctx->psn_phys = afu->gmmio_phys;
208 } else {
209 ctx->psn_size = acfg->pp_mmio_stride;
210 ctx->psn_phys = afu->ppmmio_phys + (ctx->pe * ctx->psn_size);
211 }
212
c207b571
UK
213
214 /* pid, tid, amr and mm are zeroes/NULL for a kernel context */
215 rc = ocxl_link_add_pe(link_token, ctx->pe, 0, 0, 0, NULL, NULL, NULL);
216 if (unlikely(rc)) {
217 dev_err(dev, "%s: ocxl_link_add_pe failed rc=%d\n",
218 __func__, rc);
219 goto out;
220 }
221out:
222 return rc;
6b938ac9
UK
223}
224
225/**
226 * ocxlflash_start_context() - start a kernel context
227 * @ctx_cookie: Adapter context to be started.
228 *
229 * Return: 0 on success, -errno on failure
230 */
231static int ocxlflash_start_context(void *ctx_cookie)
232{
233 struct ocxlflash_context *ctx = ctx_cookie;
234
235 return start_context(ctx);
236}
237
c207b571
UK
238/**
239 * ocxlflash_stop_context() - stop a context
240 * @ctx_cookie: Adapter context to be stopped.
241 *
242 * Return: 0 on success, -errno on failure
243 */
244static int ocxlflash_stop_context(void *ctx_cookie)
245{
246 struct ocxlflash_context *ctx = ctx_cookie;
247 struct ocxl_hw_afu *afu = ctx->hw_afu;
248 struct ocxl_afu_config *acfg = &afu->acfg;
249 struct pci_dev *pdev = afu->pdev;
250 struct device *dev = afu->dev;
251 int rc;
252
253 rc = ocxl_config_terminate_pasid(pdev, acfg->dvsec_afu_control_pos,
254 ctx->pe);
255 if (unlikely(rc)) {
256 dev_err(dev, "%s: ocxl_config_terminate_pasid failed rc=%d\n",
257 __func__, rc);
258 /* If EBUSY, PE could be referenced in future by the AFU */
259 if (rc == -EBUSY)
260 goto out;
261 }
262
263 rc = ocxl_link_remove_pe(afu->link_token, ctx->pe);
264 if (unlikely(rc)) {
265 dev_err(dev, "%s: ocxl_link_remove_pe failed rc=%d\n",
266 __func__, rc);
267 goto out;
268 }
269out:
270 return rc;
271}
272
f6b4557c
UK
273/**
274 * ocxlflash_set_master() - sets the context as master
275 * @ctx_cookie: Adapter context to set as master.
276 */
277static void ocxlflash_set_master(void *ctx_cookie)
278{
279 struct ocxlflash_context *ctx = ctx_cookie;
280
281 ctx->master = true;
282}
283
284/**
285 * ocxlflash_get_context() - obtains the context associated with the host
286 * @pdev: PCI device associated with the host.
287 * @afu_cookie: Hardware AFU associated with the host.
288 *
289 * Return: returns the pointer to host adapter context
290 */
291static void *ocxlflash_get_context(struct pci_dev *pdev, void *afu_cookie)
292{
293 struct ocxl_hw_afu *afu = afu_cookie;
294
295 return afu->ocxl_ctx;
296}
297
298/**
299 * ocxlflash_dev_context_init() - allocate and initialize an adapter context
300 * @pdev: PCI device associated with the host.
301 * @afu_cookie: Hardware AFU associated with the host.
302 *
303 * Return: returns the adapter context on success, ERR_PTR on failure
304 */
305static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie)
306{
307 struct ocxl_hw_afu *afu = afu_cookie;
308 struct device *dev = afu->dev;
309 struct ocxlflash_context *ctx;
310 int rc;
311
312 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
313 if (unlikely(!ctx)) {
314 dev_err(dev, "%s: Context allocation failed\n", __func__);
315 rc = -ENOMEM;
429ebfa6
UK
316 goto err1;
317 }
318
319 idr_preload(GFP_KERNEL);
320 rc = idr_alloc(&afu->idr, ctx, 0, afu->max_pasid, GFP_NOWAIT);
321 idr_preload_end();
322 if (unlikely(rc < 0)) {
323 dev_err(dev, "%s: idr_alloc failed rc=%d\n", __func__, rc);
324 goto err2;
f6b4557c
UK
325 }
326
429ebfa6 327 ctx->pe = rc;
f6b4557c 328 ctx->master = false;
926a62f9 329 ctx->mapping = NULL;
f6b4557c
UK
330 ctx->hw_afu = afu;
331out:
332 return ctx;
429ebfa6
UK
333err2:
334 kfree(ctx);
335err1:
f6b4557c
UK
336 ctx = ERR_PTR(rc);
337 goto out;
338}
339
340/**
341 * ocxlflash_release_context() - releases an adapter context
342 * @ctx_cookie: Adapter context to be released.
343 *
344 * Return: 0 on success, -errno on failure
345 */
346static int ocxlflash_release_context(void *ctx_cookie)
347{
348 struct ocxlflash_context *ctx = ctx_cookie;
349 int rc = 0;
350
351 if (!ctx)
352 goto out;
353
429ebfa6 354 idr_remove(&ctx->hw_afu->idr, ctx->pe);
926a62f9 355 ocxlflash_release_mapping(ctx);
f6b4557c
UK
356 kfree(ctx);
357out:
358 return rc;
359}
360
8b7a5521
UK
361/**
362 * ocxlflash_perst_reloads_same_image() - sets the image reload policy
363 * @afu_cookie: Hardware AFU associated with the host.
364 * @image: Whether to load the same image on PERST.
365 */
366static void ocxlflash_perst_reloads_same_image(void *afu_cookie, bool image)
367{
368 struct ocxl_hw_afu *afu = afu_cookie;
369
370 afu->perst_same_image = image;
371}
372
119c9200
UK
373/**
374 * ocxlflash_read_adapter_vpd() - reads the adapter VPD
375 * @pdev: PCI device associated with the host.
376 * @buf: Buffer to get the VPD data.
377 * @count: Size of buffer (maximum bytes that can be read).
378 *
379 * Return: size of VPD on success, -errno on failure
380 */
381static ssize_t ocxlflash_read_adapter_vpd(struct pci_dev *pdev, void *buf,
382 size_t count)
383{
384 return pci_read_vpd(pdev, 0, count, buf);
385}
386
bc65c1c7
UK
387/**
388 * free_afu_irqs() - internal service to free interrupts
389 * @ctx: Adapter context.
390 */
391static void free_afu_irqs(struct ocxlflash_context *ctx)
392{
393 struct ocxl_hw_afu *afu = ctx->hw_afu;
394 struct device *dev = afu->dev;
395 int i;
396
397 if (!ctx->irqs) {
398 dev_err(dev, "%s: Interrupts not allocated\n", __func__);
399 return;
400 }
401
402 for (i = ctx->num_irqs; i >= 0; i--)
403 ocxl_link_free_irq(afu->link_token, ctx->irqs[i].hwirq);
404
405 kfree(ctx->irqs);
406 ctx->irqs = NULL;
407}
408
409/**
410 * alloc_afu_irqs() - internal service to allocate interrupts
411 * @ctx: Context associated with the request.
412 * @num: Number of interrupts requested.
413 *
414 * Return: 0 on success, -errno on failure
415 */
416static int alloc_afu_irqs(struct ocxlflash_context *ctx, int num)
417{
418 struct ocxl_hw_afu *afu = ctx->hw_afu;
419 struct device *dev = afu->dev;
420 struct ocxlflash_irqs *irqs;
421 u64 addr;
422 int rc = 0;
423 int hwirq;
424 int i;
425
426 if (ctx->irqs) {
427 dev_err(dev, "%s: Interrupts already allocated\n", __func__);
428 rc = -EEXIST;
429 goto out;
430 }
431
432 if (num > OCXL_MAX_IRQS) {
433 dev_err(dev, "%s: Too many interrupts num=%d\n", __func__, num);
434 rc = -EINVAL;
435 goto out;
436 }
437
438 irqs = kcalloc(num, sizeof(*irqs), GFP_KERNEL);
439 if (unlikely(!irqs)) {
440 dev_err(dev, "%s: Context irqs allocation failed\n", __func__);
441 rc = -ENOMEM;
442 goto out;
443 }
444
445 for (i = 0; i < num; i++) {
446 rc = ocxl_link_irq_alloc(afu->link_token, &hwirq, &addr);
447 if (unlikely(rc)) {
448 dev_err(dev, "%s: ocxl_link_irq_alloc failed rc=%d\n",
449 __func__, rc);
450 goto err;
451 }
452
453 irqs[i].hwirq = hwirq;
454 irqs[i].ptrig = addr;
455 }
456
457 ctx->irqs = irqs;
458 ctx->num_irqs = num;
459out:
460 return rc;
461err:
462 for (i = i-1; i >= 0; i--)
463 ocxl_link_free_irq(afu->link_token, irqs[i].hwirq);
464 kfree(irqs);
465 goto out;
466}
467
468/**
469 * ocxlflash_allocate_afu_irqs() - allocates the requested number of interrupts
470 * @ctx_cookie: Context associated with the request.
471 * @num: Number of interrupts requested.
472 *
473 * Return: 0 on success, -errno on failure
474 */
475static int ocxlflash_allocate_afu_irqs(void *ctx_cookie, int num)
476{
477 return alloc_afu_irqs(ctx_cookie, num);
478}
479
480/**
481 * ocxlflash_free_afu_irqs() - frees the interrupts of an adapter context
482 * @ctx_cookie: Adapter context.
483 */
484static void ocxlflash_free_afu_irqs(void *ctx_cookie)
485{
486 free_afu_irqs(ctx_cookie);
487}
488
54370503
UK
489/**
490 * ocxlflash_unconfig_afu() - unconfigure the AFU
491 * @afu: AFU associated with the host.
492 */
493static void ocxlflash_unconfig_afu(struct ocxl_hw_afu *afu)
494{
495 if (afu->gmmio_virt) {
496 iounmap(afu->gmmio_virt);
497 afu->gmmio_virt = NULL;
498 }
499}
500
48e077db
UK
501/**
502 * ocxlflash_destroy_afu() - destroy the AFU structure
503 * @afu_cookie: AFU to be freed.
504 */
505static void ocxlflash_destroy_afu(void *afu_cookie)
506{
507 struct ocxl_hw_afu *afu = afu_cookie;
3351e4f0 508 int pos;
48e077db
UK
509
510 if (!afu)
511 return;
512
f6b4557c 513 ocxlflash_release_context(afu->ocxl_ctx);
429ebfa6 514 idr_destroy(&afu->idr);
3351e4f0
UK
515
516 /* Disable the AFU */
517 pos = afu->acfg.dvsec_afu_control_pos;
518 ocxl_config_set_afu_state(afu->pdev, pos, 0);
519
54370503 520 ocxlflash_unconfig_afu(afu);
48e077db
UK
521 kfree(afu);
522}
523
e9dfceda
UK
524/**
525 * ocxlflash_config_fn() - configure the host function
526 * @pdev: PCI device associated with the host.
527 * @afu: AFU associated with the host.
528 *
529 * Return: 0 on success, -errno on failure
530 */
531static int ocxlflash_config_fn(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
532{
533 struct ocxl_fn_config *fcfg = &afu->fcfg;
534 struct device *dev = &pdev->dev;
2e222779 535 u16 base, enabled, supported;
e9dfceda
UK
536 int rc = 0;
537
538 /* Read DVSEC config of the function */
539 rc = ocxl_config_read_function(pdev, fcfg);
540 if (unlikely(rc)) {
541 dev_err(dev, "%s: ocxl_config_read_function failed rc=%d\n",
542 __func__, rc);
543 goto out;
544 }
545
546 /* Check if function has AFUs defined, only 1 per function supported */
547 if (fcfg->max_afu_index >= 0) {
548 afu->is_present = true;
549 if (fcfg->max_afu_index != 0)
550 dev_warn(dev, "%s: Unexpected AFU index value %d\n",
551 __func__, fcfg->max_afu_index);
552 }
2e222779
UK
553
554 rc = ocxl_config_get_actag_info(pdev, &base, &enabled, &supported);
555 if (unlikely(rc)) {
556 dev_err(dev, "%s: ocxl_config_get_actag_info failed rc=%d\n",
557 __func__, rc);
558 goto out;
559 }
560
561 afu->fn_actag_base = base;
562 afu->fn_actag_enabled = enabled;
563
564 ocxl_config_set_actag(pdev, fcfg->dvsec_function_pos, base, enabled);
565 dev_dbg(dev, "%s: Function acTag range base=%u enabled=%u\n",
566 __func__, base, enabled);
73904823
UK
567
568 rc = ocxl_link_setup(pdev, 0, &afu->link_token);
569 if (unlikely(rc)) {
570 dev_err(dev, "%s: ocxl_link_setup failed rc=%d\n",
571 __func__, rc);
572 goto out;
573 }
c52bf5b3
UK
574
575 rc = ocxl_config_set_TL(pdev, fcfg->dvsec_tl_pos);
576 if (unlikely(rc)) {
577 dev_err(dev, "%s: ocxl_config_set_TL failed rc=%d\n",
578 __func__, rc);
579 goto err;
580 }
e9dfceda
UK
581out:
582 return rc;
c52bf5b3
UK
583err:
584 ocxl_link_release(pdev, afu->link_token);
585 goto out;
e9dfceda
UK
586}
587
73904823
UK
588/**
589 * ocxlflash_unconfig_fn() - unconfigure the host function
590 * @pdev: PCI device associated with the host.
591 * @afu: AFU associated with the host.
592 */
593static void ocxlflash_unconfig_fn(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
594{
595 ocxl_link_release(pdev, afu->link_token);
596}
597
54370503
UK
598/**
599 * ocxlflash_map_mmio() - map the AFU MMIO space
600 * @afu: AFU associated with the host.
601 *
602 * Return: 0 on success, -errno on failure
603 */
604static int ocxlflash_map_mmio(struct ocxl_hw_afu *afu)
605{
606 struct ocxl_afu_config *acfg = &afu->acfg;
607 struct pci_dev *pdev = afu->pdev;
608 struct device *dev = afu->dev;
609 phys_addr_t gmmio, ppmmio;
610 int rc = 0;
611
612 rc = pci_request_region(pdev, acfg->global_mmio_bar, "ocxlflash");
613 if (unlikely(rc)) {
614 dev_err(dev, "%s: pci_request_region for global failed rc=%d\n",
615 __func__, rc);
616 goto out;
617 }
618 gmmio = pci_resource_start(pdev, acfg->global_mmio_bar);
619 gmmio += acfg->global_mmio_offset;
620
621 rc = pci_request_region(pdev, acfg->pp_mmio_bar, "ocxlflash");
622 if (unlikely(rc)) {
623 dev_err(dev, "%s: pci_request_region for pp bar failed rc=%d\n",
624 __func__, rc);
625 goto err1;
626 }
627 ppmmio = pci_resource_start(pdev, acfg->pp_mmio_bar);
628 ppmmio += acfg->pp_mmio_offset;
629
630 afu->gmmio_virt = ioremap(gmmio, acfg->global_mmio_size);
631 if (unlikely(!afu->gmmio_virt)) {
632 dev_err(dev, "%s: MMIO mapping failed\n", __func__);
633 rc = -ENOMEM;
634 goto err2;
635 }
636
637 afu->gmmio_phys = gmmio;
638 afu->ppmmio_phys = ppmmio;
639out:
640 return rc;
641err2:
642 pci_release_region(pdev, acfg->pp_mmio_bar);
643err1:
644 pci_release_region(pdev, acfg->global_mmio_bar);
645 goto out;
646}
647
9cc84291
UK
648/**
649 * ocxlflash_config_afu() - configure the host AFU
650 * @pdev: PCI device associated with the host.
651 * @afu: AFU associated with the host.
652 *
653 * Must be called _after_ host function configuration.
654 *
655 * Return: 0 on success, -errno on failure
656 */
657static int ocxlflash_config_afu(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
658{
659 struct ocxl_afu_config *acfg = &afu->acfg;
660 struct ocxl_fn_config *fcfg = &afu->fcfg;
661 struct device *dev = &pdev->dev;
d926519e
UK
662 int count;
663 int base;
664 int pos;
9cc84291
UK
665 int rc = 0;
666
667 /* This HW AFU function does not have any AFUs defined */
668 if (!afu->is_present)
669 goto out;
670
671 /* Read AFU config at index 0 */
672 rc = ocxl_config_read_afu(pdev, fcfg, acfg, 0);
673 if (unlikely(rc)) {
674 dev_err(dev, "%s: ocxl_config_read_afu failed rc=%d\n",
675 __func__, rc);
676 goto out;
677 }
d926519e
UK
678
679 /* Only one AFU per function is supported, so actag_base is same */
680 base = afu->fn_actag_base;
681 count = min_t(int, acfg->actag_supported, afu->fn_actag_enabled);
682 pos = acfg->dvsec_afu_control_pos;
683
684 ocxl_config_set_afu_actag(pdev, pos, base, count);
685 dev_dbg(dev, "%s: acTag base=%d enabled=%d\n", __func__, base, count);
686 afu->afu_actag_base = base;
687 afu->afu_actag_enabled = count;
41df40d8
UK
688 afu->max_pasid = 1 << acfg->pasid_supported_log;
689
690 ocxl_config_set_afu_pasid(pdev, pos, 0, acfg->pasid_supported_log);
54370503
UK
691
692 rc = ocxlflash_map_mmio(afu);
693 if (unlikely(rc)) {
694 dev_err(dev, "%s: ocxlflash_map_mmio failed rc=%d\n",
695 __func__, rc);
696 goto out;
697 }
3351e4f0
UK
698
699 /* Enable the AFU */
700 ocxl_config_set_afu_state(pdev, acfg->dvsec_afu_control_pos, 1);
9cc84291
UK
701out:
702 return rc;
703}
704
48e077db
UK
705/**
706 * ocxlflash_create_afu() - create the AFU for OCXL
707 * @pdev: PCI device associated with the host.
708 *
709 * Return: AFU on success, NULL on failure
710 */
711static void *ocxlflash_create_afu(struct pci_dev *pdev)
712{
713 struct device *dev = &pdev->dev;
f6b4557c 714 struct ocxlflash_context *ctx;
48e077db 715 struct ocxl_hw_afu *afu;
e9dfceda 716 int rc;
48e077db
UK
717
718 afu = kzalloc(sizeof(*afu), GFP_KERNEL);
719 if (unlikely(!afu)) {
720 dev_err(dev, "%s: HW AFU allocation failed\n", __func__);
721 goto out;
722 }
723
724 afu->pdev = pdev;
725 afu->dev = dev;
429ebfa6 726 idr_init(&afu->idr);
e9dfceda
UK
727
728 rc = ocxlflash_config_fn(pdev, afu);
729 if (unlikely(rc)) {
730 dev_err(dev, "%s: Function configuration failed rc=%d\n",
731 __func__, rc);
732 goto err1;
733 }
9cc84291
UK
734
735 rc = ocxlflash_config_afu(pdev, afu);
736 if (unlikely(rc)) {
737 dev_err(dev, "%s: AFU configuration failed rc=%d\n",
738 __func__, rc);
73904823 739 goto err2;
9cc84291 740 }
f6b4557c
UK
741
742 ctx = ocxlflash_dev_context_init(pdev, afu);
743 if (IS_ERR(ctx)) {
744 rc = PTR_ERR(ctx);
745 dev_err(dev, "%s: ocxlflash_dev_context_init failed rc=%d\n",
746 __func__, rc);
73904823 747 goto err3;
f6b4557c
UK
748 }
749
750 afu->ocxl_ctx = ctx;
48e077db
UK
751out:
752 return afu;
73904823 753err3:
54370503 754 ocxlflash_unconfig_afu(afu);
73904823
UK
755err2:
756 ocxlflash_unconfig_fn(pdev, afu);
e9dfceda 757err1:
429ebfa6 758 idr_destroy(&afu->idr);
e9dfceda
UK
759 kfree(afu);
760 afu = NULL;
761 goto out;
48e077db 762}
76ebe01f 763
926a62f9
UK
764static const struct file_operations ocxl_afu_fops = {
765 .owner = THIS_MODULE,
766};
767
768/**
769 * ocxlflash_get_fd() - get file descriptor for an adapter context
770 * @ctx_cookie: Adapter context.
771 * @fops: File operations to be associated.
772 * @fd: File descriptor to be returned back.
773 *
774 * Return: pointer to the file on success, ERR_PTR on failure
775 */
776static struct file *ocxlflash_get_fd(void *ctx_cookie,
777 struct file_operations *fops, int *fd)
778{
779 struct ocxlflash_context *ctx = ctx_cookie;
780 struct device *dev = ctx->hw_afu->dev;
781 struct file *file;
782 int flags, fdtmp;
783 int rc = 0;
784 char *name = NULL;
785
786 /* Only allow one fd per context */
787 if (ctx->mapping) {
788 dev_err(dev, "%s: Context is already mapped to an fd\n",
789 __func__);
790 rc = -EEXIST;
791 goto err1;
792 }
793
794 flags = O_RDWR | O_CLOEXEC;
795
796 /* This code is similar to anon_inode_getfd() */
797 rc = get_unused_fd_flags(flags);
798 if (unlikely(rc < 0)) {
799 dev_err(dev, "%s: get_unused_fd_flags failed rc=%d\n",
800 __func__, rc);
801 goto err1;
802 }
803 fdtmp = rc;
804
805 /* Use default ops if there is no fops */
806 if (!fops)
807 fops = (struct file_operations *)&ocxl_afu_fops;
808
809 name = kasprintf(GFP_KERNEL, "ocxlflash:%d", ctx->pe);
810 file = ocxlflash_getfile(dev, name, fops, ctx, flags);
811 kfree(name);
812 if (IS_ERR(file)) {
813 rc = PTR_ERR(file);
814 dev_err(dev, "%s: ocxlflash_getfile failed rc=%d\n",
815 __func__, rc);
816 goto err2;
817 }
818
819 ctx->mapping = file->f_mapping;
820 *fd = fdtmp;
821out:
822 return file;
823err2:
824 put_unused_fd(fdtmp);
825err1:
826 file = ERR_PTR(rc);
827 goto out;
828}
829
b18718c6
UK
830/**
831 * ocxlflash_fops_get_context() - get the context associated with the file
832 * @file: File associated with the adapter context.
833 *
834 * Return: pointer to the context
835 */
836static void *ocxlflash_fops_get_context(struct file *file)
837{
838 return file->private_data;
839}
840
76ebe01f
UK
841/* Backend ops to ocxlflash services */
842const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
843 .module = THIS_MODULE,
012f394c
UK
844 .psa_map = ocxlflash_psa_map,
845 .psa_unmap = ocxlflash_psa_unmap,
b18718c6 846 .process_element = ocxlflash_process_element,
6b938ac9 847 .start_context = ocxlflash_start_context,
c207b571 848 .stop_context = ocxlflash_stop_context,
f6b4557c
UK
849 .set_master = ocxlflash_set_master,
850 .get_context = ocxlflash_get_context,
851 .dev_context_init = ocxlflash_dev_context_init,
852 .release_context = ocxlflash_release_context,
8b7a5521 853 .perst_reloads_same_image = ocxlflash_perst_reloads_same_image,
119c9200 854 .read_adapter_vpd = ocxlflash_read_adapter_vpd,
bc65c1c7
UK
855 .allocate_afu_irqs = ocxlflash_allocate_afu_irqs,
856 .free_afu_irqs = ocxlflash_free_afu_irqs,
48e077db
UK
857 .create_afu = ocxlflash_create_afu,
858 .destroy_afu = ocxlflash_destroy_afu,
926a62f9 859 .get_fd = ocxlflash_get_fd,
b18718c6 860 .fops_get_context = ocxlflash_fops_get_context,
76ebe01f 861};