2 * CXL Flash Device Driver
4 * Written by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>, IBM Corporation
5 * Uma Krishnan <ukrishn@linux.vnet.ibm.com>, IBM Corporation
7 * Copyright (C) 2018 IBM Corporation
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.
15 #include <linux/file.h>
16 #include <linux/idr.h>
17 #include <linux/module.h>
18 #include <linux/mount.h>
20 #include <misc/ocxl.h>
26 * Pseudo-filesystem to allocate inodes.
29 #define OCXLFLASH_FS_MAGIC 0x1697698f
31 static int ocxlflash_fs_cnt
;
32 static struct vfsmount
*ocxlflash_vfs_mount
;
34 static const struct dentry_operations ocxlflash_fs_dops
= {
35 .d_dname
= simple_dname
,
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.
45 * Return: pointer to the directory entry structure
47 static struct dentry
*ocxlflash_fs_mount(struct file_system_type
*fs_type
,
48 int flags
, const char *dev_name
,
51 return mount_pseudo(fs_type
, "ocxlflash:", NULL
, &ocxlflash_fs_dops
,
55 static struct file_system_type ocxlflash_fs_type
= {
58 .mount
= ocxlflash_fs_mount
,
59 .kill_sb
= kill_anon_super
,
63 * ocxlflash_release_mapping() - release the memory mapping
64 * @ctx: Context whose mapping is to be released.
66 static void ocxlflash_release_mapping(struct ocxlflash_context
*ctx
)
69 simple_release_fs(&ocxlflash_vfs_mount
, &ocxlflash_fs_cnt
);
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.
81 * Return: pointer to the file on success, ERR_PTR on failure
83 static struct file
*ocxlflash_getfile(struct device
*dev
, const char *name
,
84 const struct file_operations
*fops
,
85 void *priv
, int flags
)
90 struct inode
*inode
= NULL
;
93 if (fops
->owner
&& !try_module_get(fops
->owner
)) {
94 dev_err(dev
, "%s: Owner does not exist\n", __func__
);
99 rc
= simple_pin_fs(&ocxlflash_fs_type
, &ocxlflash_vfs_mount
,
101 if (unlikely(rc
< 0)) {
102 dev_err(dev
, "%s: Cannot mount ocxlflash pseudofs rc=%d\n",
107 inode
= alloc_anon_inode(ocxlflash_vfs_mount
->mnt_sb
);
110 dev_err(dev
, "%s: alloc_anon_inode failed rc=%d\n",
116 this.len
= strlen(name
);
118 path
.dentry
= d_alloc_pseudo(ocxlflash_vfs_mount
->mnt_sb
, &this);
120 dev_err(dev
, "%s: d_alloc_pseudo failed\n", __func__
);
125 path
.mnt
= mntget(ocxlflash_vfs_mount
);
126 d_instantiate(path
.dentry
, inode
);
128 file
= alloc_file(&path
, OPEN_FMODE(flags
), fops
);
131 dev_err(dev
, "%s: alloc_file failed rc=%d\n",
136 file
->f_flags
= flags
& (O_ACCMODE
| O_NONBLOCK
);
137 file
->private_data
= priv
;
145 simple_release_fs(&ocxlflash_vfs_mount
, &ocxlflash_fs_cnt
);
147 module_put(fops
->owner
);
154 * ocxlflash_process_element() - get process element of the adapter context
155 * @ctx_cookie: Adapter context associated with the process element.
157 * Return: process element of the adapter context
159 static int ocxlflash_process_element(void *ctx_cookie
)
161 struct ocxlflash_context
*ctx
= ctx_cookie
;
167 * ocxlflash_set_master() - sets the context as master
168 * @ctx_cookie: Adapter context to set as master.
170 static void ocxlflash_set_master(void *ctx_cookie
)
172 struct ocxlflash_context
*ctx
= ctx_cookie
;
178 * ocxlflash_get_context() - obtains the context associated with the host
179 * @pdev: PCI device associated with the host.
180 * @afu_cookie: Hardware AFU associated with the host.
182 * Return: returns the pointer to host adapter context
184 static void *ocxlflash_get_context(struct pci_dev
*pdev
, void *afu_cookie
)
186 struct ocxl_hw_afu
*afu
= afu_cookie
;
188 return afu
->ocxl_ctx
;
192 * ocxlflash_dev_context_init() - allocate and initialize an adapter context
193 * @pdev: PCI device associated with the host.
194 * @afu_cookie: Hardware AFU associated with the host.
196 * Return: returns the adapter context on success, ERR_PTR on failure
198 static void *ocxlflash_dev_context_init(struct pci_dev
*pdev
, void *afu_cookie
)
200 struct ocxl_hw_afu
*afu
= afu_cookie
;
201 struct device
*dev
= afu
->dev
;
202 struct ocxlflash_context
*ctx
;
205 ctx
= kzalloc(sizeof(*ctx
), GFP_KERNEL
);
206 if (unlikely(!ctx
)) {
207 dev_err(dev
, "%s: Context allocation failed\n", __func__
);
212 idr_preload(GFP_KERNEL
);
213 rc
= idr_alloc(&afu
->idr
, ctx
, 0, afu
->max_pasid
, GFP_NOWAIT
);
215 if (unlikely(rc
< 0)) {
216 dev_err(dev
, "%s: idr_alloc failed rc=%d\n", __func__
, rc
);
234 * ocxlflash_release_context() - releases an adapter context
235 * @ctx_cookie: Adapter context to be released.
237 * Return: 0 on success, -errno on failure
239 static int ocxlflash_release_context(void *ctx_cookie
)
241 struct ocxlflash_context
*ctx
= ctx_cookie
;
247 idr_remove(&ctx
->hw_afu
->idr
, ctx
->pe
);
248 ocxlflash_release_mapping(ctx
);
255 * ocxlflash_perst_reloads_same_image() - sets the image reload policy
256 * @afu_cookie: Hardware AFU associated with the host.
257 * @image: Whether to load the same image on PERST.
259 static void ocxlflash_perst_reloads_same_image(void *afu_cookie
, bool image
)
261 struct ocxl_hw_afu
*afu
= afu_cookie
;
263 afu
->perst_same_image
= image
;
267 * ocxlflash_destroy_afu() - destroy the AFU structure
268 * @afu_cookie: AFU to be freed.
270 static void ocxlflash_destroy_afu(void *afu_cookie
)
272 struct ocxl_hw_afu
*afu
= afu_cookie
;
277 ocxlflash_release_context(afu
->ocxl_ctx
);
278 idr_destroy(&afu
->idr
);
283 * ocxlflash_config_fn() - configure the host function
284 * @pdev: PCI device associated with the host.
285 * @afu: AFU associated with the host.
287 * Return: 0 on success, -errno on failure
289 static int ocxlflash_config_fn(struct pci_dev
*pdev
, struct ocxl_hw_afu
*afu
)
291 struct ocxl_fn_config
*fcfg
= &afu
->fcfg
;
292 struct device
*dev
= &pdev
->dev
;
293 u16 base
, enabled
, supported
;
296 /* Read DVSEC config of the function */
297 rc
= ocxl_config_read_function(pdev
, fcfg
);
299 dev_err(dev
, "%s: ocxl_config_read_function failed rc=%d\n",
304 /* Only one AFU per function is supported by ocxlflash */
305 if (fcfg
->max_afu_index
!= 0)
306 dev_warn(dev
, "%s: Unexpected AFU index value %d\n",
307 __func__
, fcfg
->max_afu_index
);
309 rc
= ocxl_config_get_actag_info(pdev
, &base
, &enabled
, &supported
);
311 dev_err(dev
, "%s: ocxl_config_get_actag_info failed rc=%d\n",
316 afu
->fn_actag_base
= base
;
317 afu
->fn_actag_enabled
= enabled
;
319 ocxl_config_set_actag(pdev
, fcfg
->dvsec_function_pos
, base
, enabled
);
320 dev_dbg(dev
, "%s: Function acTag range base=%u enabled=%u\n",
321 __func__
, base
, enabled
);
327 * ocxlflash_config_afu() - configure the host AFU
328 * @pdev: PCI device associated with the host.
329 * @afu: AFU associated with the host.
331 * Must be called _after_ host function configuration.
333 * Return: 0 on success, -errno on failure
335 static int ocxlflash_config_afu(struct pci_dev
*pdev
, struct ocxl_hw_afu
*afu
)
337 struct ocxl_afu_config
*acfg
= &afu
->acfg
;
338 struct ocxl_fn_config
*fcfg
= &afu
->fcfg
;
339 struct device
*dev
= &pdev
->dev
;
345 /* Read AFU config at index 0 */
346 rc
= ocxl_config_read_afu(pdev
, fcfg
, acfg
, 0);
348 dev_err(dev
, "%s: ocxl_config_read_afu failed rc=%d\n",
353 /* Only one AFU per function is supported, so actag_base is same */
354 base
= afu
->fn_actag_base
;
355 count
= min_t(int, acfg
->actag_supported
, afu
->fn_actag_enabled
);
356 pos
= acfg
->dvsec_afu_control_pos
;
358 ocxl_config_set_afu_actag(pdev
, pos
, base
, count
);
359 dev_dbg(dev
, "%s: acTag base=%d enabled=%d\n", __func__
, base
, count
);
360 afu
->afu_actag_base
= base
;
361 afu
->afu_actag_enabled
= count
;
362 afu
->max_pasid
= 1 << acfg
->pasid_supported_log
;
364 ocxl_config_set_afu_pasid(pdev
, pos
, 0, acfg
->pasid_supported_log
);
370 * ocxlflash_create_afu() - create the AFU for OCXL
371 * @pdev: PCI device associated with the host.
373 * Return: AFU on success, NULL on failure
375 static void *ocxlflash_create_afu(struct pci_dev
*pdev
)
377 struct device
*dev
= &pdev
->dev
;
378 struct ocxlflash_context
*ctx
;
379 struct ocxl_hw_afu
*afu
;
382 afu
= kzalloc(sizeof(*afu
), GFP_KERNEL
);
383 if (unlikely(!afu
)) {
384 dev_err(dev
, "%s: HW AFU allocation failed\n", __func__
);
391 rc
= ocxlflash_config_fn(pdev
, afu
);
393 dev_err(dev
, "%s: Function configuration failed rc=%d\n",
398 rc
= ocxlflash_config_afu(pdev
, afu
);
400 dev_err(dev
, "%s: AFU configuration failed rc=%d\n",
405 ctx
= ocxlflash_dev_context_init(pdev
, afu
);
408 dev_err(dev
, "%s: ocxlflash_dev_context_init failed rc=%d\n",
423 static const struct file_operations ocxl_afu_fops
= {
424 .owner
= THIS_MODULE
,
428 * ocxlflash_get_fd() - get file descriptor for an adapter context
429 * @ctx_cookie: Adapter context.
430 * @fops: File operations to be associated.
431 * @fd: File descriptor to be returned back.
433 * Return: pointer to the file on success, ERR_PTR on failure
435 static struct file
*ocxlflash_get_fd(void *ctx_cookie
,
436 struct file_operations
*fops
, int *fd
)
438 struct ocxlflash_context
*ctx
= ctx_cookie
;
439 struct device
*dev
= ctx
->hw_afu
->dev
;
445 /* Only allow one fd per context */
447 dev_err(dev
, "%s: Context is already mapped to an fd\n",
453 flags
= O_RDWR
| O_CLOEXEC
;
455 /* This code is similar to anon_inode_getfd() */
456 rc
= get_unused_fd_flags(flags
);
457 if (unlikely(rc
< 0)) {
458 dev_err(dev
, "%s: get_unused_fd_flags failed rc=%d\n",
464 /* Use default ops if there is no fops */
466 fops
= (struct file_operations
*)&ocxl_afu_fops
;
468 name
= kasprintf(GFP_KERNEL
, "ocxlflash:%d", ctx
->pe
);
469 file
= ocxlflash_getfile(dev
, name
, fops
, ctx
, flags
);
473 dev_err(dev
, "%s: ocxlflash_getfile failed rc=%d\n",
478 ctx
->mapping
= file
->f_mapping
;
483 put_unused_fd(fdtmp
);
490 * ocxlflash_fops_get_context() - get the context associated with the file
491 * @file: File associated with the adapter context.
493 * Return: pointer to the context
495 static void *ocxlflash_fops_get_context(struct file
*file
)
497 return file
->private_data
;
500 /* Backend ops to ocxlflash services */
501 const struct cxlflash_backend_ops cxlflash_ocxl_ops
= {
502 .module
= THIS_MODULE
,
503 .process_element
= ocxlflash_process_element
,
504 .set_master
= ocxlflash_set_master
,
505 .get_context
= ocxlflash_get_context
,
506 .dev_context_init
= ocxlflash_dev_context_init
,
507 .release_context
= ocxlflash_release_context
,
508 .perst_reloads_same_image
= ocxlflash_perst_reloads_same_image
,
509 .create_afu
= ocxlflash_create_afu
,
510 .destroy_afu
= ocxlflash_destroy_afu
,
511 .get_fd
= ocxlflash_get_fd
,
512 .fops_get_context
= ocxlflash_fops_get_context
,