]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/scsi/cxlflash/ocxl_hw.c
scsi: cxlflash: Support process specific mappings
[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 *
192 * Assign the context specific MMIO space.
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;
200 bool master = ctx->master;
201
202 if (master) {
203 ctx->psn_size = acfg->global_mmio_size;
204 ctx->psn_phys = afu->gmmio_phys;
205 } else {
206 ctx->psn_size = acfg->pp_mmio_stride;
207 ctx->psn_phys = afu->ppmmio_phys + (ctx->pe * ctx->psn_size);
208 }
209
210 return 0;
211}
212
213/**
214 * ocxlflash_start_context() - start a kernel context
215 * @ctx_cookie: Adapter context to be started.
216 *
217 * Return: 0 on success, -errno on failure
218 */
219static int ocxlflash_start_context(void *ctx_cookie)
220{
221 struct ocxlflash_context *ctx = ctx_cookie;
222
223 return start_context(ctx);
224}
225
f6b4557c
UK
226/**
227 * ocxlflash_set_master() - sets the context as master
228 * @ctx_cookie: Adapter context to set as master.
229 */
230static void ocxlflash_set_master(void *ctx_cookie)
231{
232 struct ocxlflash_context *ctx = ctx_cookie;
233
234 ctx->master = true;
235}
236
237/**
238 * ocxlflash_get_context() - obtains the context associated with the host
239 * @pdev: PCI device associated with the host.
240 * @afu_cookie: Hardware AFU associated with the host.
241 *
242 * Return: returns the pointer to host adapter context
243 */
244static void *ocxlflash_get_context(struct pci_dev *pdev, void *afu_cookie)
245{
246 struct ocxl_hw_afu *afu = afu_cookie;
247
248 return afu->ocxl_ctx;
249}
250
251/**
252 * ocxlflash_dev_context_init() - allocate and initialize an adapter context
253 * @pdev: PCI device associated with the host.
254 * @afu_cookie: Hardware AFU associated with the host.
255 *
256 * Return: returns the adapter context on success, ERR_PTR on failure
257 */
258static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie)
259{
260 struct ocxl_hw_afu *afu = afu_cookie;
261 struct device *dev = afu->dev;
262 struct ocxlflash_context *ctx;
263 int rc;
264
265 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
266 if (unlikely(!ctx)) {
267 dev_err(dev, "%s: Context allocation failed\n", __func__);
268 rc = -ENOMEM;
429ebfa6
UK
269 goto err1;
270 }
271
272 idr_preload(GFP_KERNEL);
273 rc = idr_alloc(&afu->idr, ctx, 0, afu->max_pasid, GFP_NOWAIT);
274 idr_preload_end();
275 if (unlikely(rc < 0)) {
276 dev_err(dev, "%s: idr_alloc failed rc=%d\n", __func__, rc);
277 goto err2;
f6b4557c
UK
278 }
279
429ebfa6 280 ctx->pe = rc;
f6b4557c 281 ctx->master = false;
926a62f9 282 ctx->mapping = NULL;
f6b4557c
UK
283 ctx->hw_afu = afu;
284out:
285 return ctx;
429ebfa6
UK
286err2:
287 kfree(ctx);
288err1:
f6b4557c
UK
289 ctx = ERR_PTR(rc);
290 goto out;
291}
292
293/**
294 * ocxlflash_release_context() - releases an adapter context
295 * @ctx_cookie: Adapter context to be released.
296 *
297 * Return: 0 on success, -errno on failure
298 */
299static int ocxlflash_release_context(void *ctx_cookie)
300{
301 struct ocxlflash_context *ctx = ctx_cookie;
302 int rc = 0;
303
304 if (!ctx)
305 goto out;
306
429ebfa6 307 idr_remove(&ctx->hw_afu->idr, ctx->pe);
926a62f9 308 ocxlflash_release_mapping(ctx);
f6b4557c
UK
309 kfree(ctx);
310out:
311 return rc;
312}
313
8b7a5521
UK
314/**
315 * ocxlflash_perst_reloads_same_image() - sets the image reload policy
316 * @afu_cookie: Hardware AFU associated with the host.
317 * @image: Whether to load the same image on PERST.
318 */
319static void ocxlflash_perst_reloads_same_image(void *afu_cookie, bool image)
320{
321 struct ocxl_hw_afu *afu = afu_cookie;
322
323 afu->perst_same_image = image;
324}
325
54370503
UK
326/**
327 * ocxlflash_unconfig_afu() - unconfigure the AFU
328 * @afu: AFU associated with the host.
329 */
330static void ocxlflash_unconfig_afu(struct ocxl_hw_afu *afu)
331{
332 if (afu->gmmio_virt) {
333 iounmap(afu->gmmio_virt);
334 afu->gmmio_virt = NULL;
335 }
336}
337
48e077db
UK
338/**
339 * ocxlflash_destroy_afu() - destroy the AFU structure
340 * @afu_cookie: AFU to be freed.
341 */
342static void ocxlflash_destroy_afu(void *afu_cookie)
343{
344 struct ocxl_hw_afu *afu = afu_cookie;
345
346 if (!afu)
347 return;
348
f6b4557c 349 ocxlflash_release_context(afu->ocxl_ctx);
429ebfa6 350 idr_destroy(&afu->idr);
54370503 351 ocxlflash_unconfig_afu(afu);
48e077db
UK
352 kfree(afu);
353}
354
e9dfceda
UK
355/**
356 * ocxlflash_config_fn() - configure the host function
357 * @pdev: PCI device associated with the host.
358 * @afu: AFU associated with the host.
359 *
360 * Return: 0 on success, -errno on failure
361 */
362static int ocxlflash_config_fn(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
363{
364 struct ocxl_fn_config *fcfg = &afu->fcfg;
365 struct device *dev = &pdev->dev;
2e222779 366 u16 base, enabled, supported;
e9dfceda
UK
367 int rc = 0;
368
369 /* Read DVSEC config of the function */
370 rc = ocxl_config_read_function(pdev, fcfg);
371 if (unlikely(rc)) {
372 dev_err(dev, "%s: ocxl_config_read_function failed rc=%d\n",
373 __func__, rc);
374 goto out;
375 }
376
377 /* Check if function has AFUs defined, only 1 per function supported */
378 if (fcfg->max_afu_index >= 0) {
379 afu->is_present = true;
380 if (fcfg->max_afu_index != 0)
381 dev_warn(dev, "%s: Unexpected AFU index value %d\n",
382 __func__, fcfg->max_afu_index);
383 }
2e222779
UK
384
385 rc = ocxl_config_get_actag_info(pdev, &base, &enabled, &supported);
386 if (unlikely(rc)) {
387 dev_err(dev, "%s: ocxl_config_get_actag_info failed rc=%d\n",
388 __func__, rc);
389 goto out;
390 }
391
392 afu->fn_actag_base = base;
393 afu->fn_actag_enabled = enabled;
394
395 ocxl_config_set_actag(pdev, fcfg->dvsec_function_pos, base, enabled);
396 dev_dbg(dev, "%s: Function acTag range base=%u enabled=%u\n",
397 __func__, base, enabled);
e9dfceda
UK
398out:
399 return rc;
400}
401
54370503
UK
402/**
403 * ocxlflash_map_mmio() - map the AFU MMIO space
404 * @afu: AFU associated with the host.
405 *
406 * Return: 0 on success, -errno on failure
407 */
408static int ocxlflash_map_mmio(struct ocxl_hw_afu *afu)
409{
410 struct ocxl_afu_config *acfg = &afu->acfg;
411 struct pci_dev *pdev = afu->pdev;
412 struct device *dev = afu->dev;
413 phys_addr_t gmmio, ppmmio;
414 int rc = 0;
415
416 rc = pci_request_region(pdev, acfg->global_mmio_bar, "ocxlflash");
417 if (unlikely(rc)) {
418 dev_err(dev, "%s: pci_request_region for global failed rc=%d\n",
419 __func__, rc);
420 goto out;
421 }
422 gmmio = pci_resource_start(pdev, acfg->global_mmio_bar);
423 gmmio += acfg->global_mmio_offset;
424
425 rc = pci_request_region(pdev, acfg->pp_mmio_bar, "ocxlflash");
426 if (unlikely(rc)) {
427 dev_err(dev, "%s: pci_request_region for pp bar failed rc=%d\n",
428 __func__, rc);
429 goto err1;
430 }
431 ppmmio = pci_resource_start(pdev, acfg->pp_mmio_bar);
432 ppmmio += acfg->pp_mmio_offset;
433
434 afu->gmmio_virt = ioremap(gmmio, acfg->global_mmio_size);
435 if (unlikely(!afu->gmmio_virt)) {
436 dev_err(dev, "%s: MMIO mapping failed\n", __func__);
437 rc = -ENOMEM;
438 goto err2;
439 }
440
441 afu->gmmio_phys = gmmio;
442 afu->ppmmio_phys = ppmmio;
443out:
444 return rc;
445err2:
446 pci_release_region(pdev, acfg->pp_mmio_bar);
447err1:
448 pci_release_region(pdev, acfg->global_mmio_bar);
449 goto out;
450}
451
9cc84291
UK
452/**
453 * ocxlflash_config_afu() - configure the host AFU
454 * @pdev: PCI device associated with the host.
455 * @afu: AFU associated with the host.
456 *
457 * Must be called _after_ host function configuration.
458 *
459 * Return: 0 on success, -errno on failure
460 */
461static int ocxlflash_config_afu(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
462{
463 struct ocxl_afu_config *acfg = &afu->acfg;
464 struct ocxl_fn_config *fcfg = &afu->fcfg;
465 struct device *dev = &pdev->dev;
d926519e
UK
466 int count;
467 int base;
468 int pos;
9cc84291
UK
469 int rc = 0;
470
471 /* This HW AFU function does not have any AFUs defined */
472 if (!afu->is_present)
473 goto out;
474
475 /* Read AFU config at index 0 */
476 rc = ocxl_config_read_afu(pdev, fcfg, acfg, 0);
477 if (unlikely(rc)) {
478 dev_err(dev, "%s: ocxl_config_read_afu failed rc=%d\n",
479 __func__, rc);
480 goto out;
481 }
d926519e
UK
482
483 /* Only one AFU per function is supported, so actag_base is same */
484 base = afu->fn_actag_base;
485 count = min_t(int, acfg->actag_supported, afu->fn_actag_enabled);
486 pos = acfg->dvsec_afu_control_pos;
487
488 ocxl_config_set_afu_actag(pdev, pos, base, count);
489 dev_dbg(dev, "%s: acTag base=%d enabled=%d\n", __func__, base, count);
490 afu->afu_actag_base = base;
491 afu->afu_actag_enabled = count;
41df40d8
UK
492 afu->max_pasid = 1 << acfg->pasid_supported_log;
493
494 ocxl_config_set_afu_pasid(pdev, pos, 0, acfg->pasid_supported_log);
54370503
UK
495
496 rc = ocxlflash_map_mmio(afu);
497 if (unlikely(rc)) {
498 dev_err(dev, "%s: ocxlflash_map_mmio failed rc=%d\n",
499 __func__, rc);
500 goto out;
501 }
9cc84291
UK
502out:
503 return rc;
504}
505
48e077db
UK
506/**
507 * ocxlflash_create_afu() - create the AFU for OCXL
508 * @pdev: PCI device associated with the host.
509 *
510 * Return: AFU on success, NULL on failure
511 */
512static void *ocxlflash_create_afu(struct pci_dev *pdev)
513{
514 struct device *dev = &pdev->dev;
f6b4557c 515 struct ocxlflash_context *ctx;
48e077db 516 struct ocxl_hw_afu *afu;
e9dfceda 517 int rc;
48e077db
UK
518
519 afu = kzalloc(sizeof(*afu), GFP_KERNEL);
520 if (unlikely(!afu)) {
521 dev_err(dev, "%s: HW AFU allocation failed\n", __func__);
522 goto out;
523 }
524
525 afu->pdev = pdev;
526 afu->dev = dev;
429ebfa6 527 idr_init(&afu->idr);
e9dfceda
UK
528
529 rc = ocxlflash_config_fn(pdev, afu);
530 if (unlikely(rc)) {
531 dev_err(dev, "%s: Function configuration failed rc=%d\n",
532 __func__, rc);
533 goto err1;
534 }
9cc84291
UK
535
536 rc = ocxlflash_config_afu(pdev, afu);
537 if (unlikely(rc)) {
538 dev_err(dev, "%s: AFU configuration failed rc=%d\n",
539 __func__, rc);
540 goto err1;
541 }
f6b4557c
UK
542
543 ctx = ocxlflash_dev_context_init(pdev, afu);
544 if (IS_ERR(ctx)) {
545 rc = PTR_ERR(ctx);
546 dev_err(dev, "%s: ocxlflash_dev_context_init failed rc=%d\n",
547 __func__, rc);
54370503 548 goto err2;
f6b4557c
UK
549 }
550
551 afu->ocxl_ctx = ctx;
48e077db
UK
552out:
553 return afu;
54370503
UK
554err2:
555 ocxlflash_unconfig_afu(afu);
e9dfceda 556err1:
429ebfa6 557 idr_destroy(&afu->idr);
e9dfceda
UK
558 kfree(afu);
559 afu = NULL;
560 goto out;
48e077db 561}
76ebe01f 562
926a62f9
UK
563static const struct file_operations ocxl_afu_fops = {
564 .owner = THIS_MODULE,
565};
566
567/**
568 * ocxlflash_get_fd() - get file descriptor for an adapter context
569 * @ctx_cookie: Adapter context.
570 * @fops: File operations to be associated.
571 * @fd: File descriptor to be returned back.
572 *
573 * Return: pointer to the file on success, ERR_PTR on failure
574 */
575static struct file *ocxlflash_get_fd(void *ctx_cookie,
576 struct file_operations *fops, int *fd)
577{
578 struct ocxlflash_context *ctx = ctx_cookie;
579 struct device *dev = ctx->hw_afu->dev;
580 struct file *file;
581 int flags, fdtmp;
582 int rc = 0;
583 char *name = NULL;
584
585 /* Only allow one fd per context */
586 if (ctx->mapping) {
587 dev_err(dev, "%s: Context is already mapped to an fd\n",
588 __func__);
589 rc = -EEXIST;
590 goto err1;
591 }
592
593 flags = O_RDWR | O_CLOEXEC;
594
595 /* This code is similar to anon_inode_getfd() */
596 rc = get_unused_fd_flags(flags);
597 if (unlikely(rc < 0)) {
598 dev_err(dev, "%s: get_unused_fd_flags failed rc=%d\n",
599 __func__, rc);
600 goto err1;
601 }
602 fdtmp = rc;
603
604 /* Use default ops if there is no fops */
605 if (!fops)
606 fops = (struct file_operations *)&ocxl_afu_fops;
607
608 name = kasprintf(GFP_KERNEL, "ocxlflash:%d", ctx->pe);
609 file = ocxlflash_getfile(dev, name, fops, ctx, flags);
610 kfree(name);
611 if (IS_ERR(file)) {
612 rc = PTR_ERR(file);
613 dev_err(dev, "%s: ocxlflash_getfile failed rc=%d\n",
614 __func__, rc);
615 goto err2;
616 }
617
618 ctx->mapping = file->f_mapping;
619 *fd = fdtmp;
620out:
621 return file;
622err2:
623 put_unused_fd(fdtmp);
624err1:
625 file = ERR_PTR(rc);
626 goto out;
627}
628
b18718c6
UK
629/**
630 * ocxlflash_fops_get_context() - get the context associated with the file
631 * @file: File associated with the adapter context.
632 *
633 * Return: pointer to the context
634 */
635static void *ocxlflash_fops_get_context(struct file *file)
636{
637 return file->private_data;
638}
639
76ebe01f
UK
640/* Backend ops to ocxlflash services */
641const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
642 .module = THIS_MODULE,
012f394c
UK
643 .psa_map = ocxlflash_psa_map,
644 .psa_unmap = ocxlflash_psa_unmap,
b18718c6 645 .process_element = ocxlflash_process_element,
6b938ac9 646 .start_context = ocxlflash_start_context,
f6b4557c
UK
647 .set_master = ocxlflash_set_master,
648 .get_context = ocxlflash_get_context,
649 .dev_context_init = ocxlflash_dev_context_init,
650 .release_context = ocxlflash_release_context,
8b7a5521 651 .perst_reloads_same_image = ocxlflash_perst_reloads_same_image,
48e077db
UK
652 .create_afu = ocxlflash_create_afu,
653 .destroy_afu = ocxlflash_destroy_afu,
926a62f9 654 .get_fd = ocxlflash_get_fd,
b18718c6 655 .fops_get_context = ocxlflash_fops_get_context,
76ebe01f 656};