]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/scsi/cxlflash/ocxl_hw.c
7717a63fdd8ec4161e1cbbde3051cd2aca34a7ed
[mirror_ubuntu-bionic-kernel.git] / drivers / scsi / cxlflash / ocxl_hw.c
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
15 #include <linux/file.h>
16 #include <linux/idr.h>
17 #include <linux/module.h>
18 #include <linux/mount.h>
19
20 #include <misc/ocxl.h>
21
22 #include "backend.h"
23 #include "ocxl_hw.h"
24
25 /*
26 * Pseudo-filesystem to allocate inodes.
27 */
28
29 #define OCXLFLASH_FS_MAGIC 0x1697698f
30
31 static int ocxlflash_fs_cnt;
32 static struct vfsmount *ocxlflash_vfs_mount;
33
34 static 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 */
47 static 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
55 static 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 */
66 static 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 */
83 static 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;
138 out:
139 return file;
140 err5:
141 path_put(&path);
142 err4:
143 iput(inode);
144 err3:
145 simple_release_fs(&ocxlflash_vfs_mount, &ocxlflash_fs_cnt);
146 err2:
147 module_put(fops->owner);
148 err1:
149 file = ERR_PTR(rc);
150 goto out;
151 }
152
153 /**
154 * ocxlflash_process_element() - get process element of the adapter context
155 * @ctx_cookie: Adapter context associated with the process element.
156 *
157 * Return: process element of the adapter context
158 */
159 static int ocxlflash_process_element(void *ctx_cookie)
160 {
161 struct ocxlflash_context *ctx = ctx_cookie;
162
163 return ctx->pe;
164 }
165
166 /**
167 * ocxlflash_set_master() - sets the context as master
168 * @ctx_cookie: Adapter context to set as master.
169 */
170 static void ocxlflash_set_master(void *ctx_cookie)
171 {
172 struct ocxlflash_context *ctx = ctx_cookie;
173
174 ctx->master = true;
175 }
176
177 /**
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.
181 *
182 * Return: returns the pointer to host adapter context
183 */
184 static void *ocxlflash_get_context(struct pci_dev *pdev, void *afu_cookie)
185 {
186 struct ocxl_hw_afu *afu = afu_cookie;
187
188 return afu->ocxl_ctx;
189 }
190
191 /**
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.
195 *
196 * Return: returns the adapter context on success, ERR_PTR on failure
197 */
198 static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie)
199 {
200 struct ocxl_hw_afu *afu = afu_cookie;
201 struct device *dev = afu->dev;
202 struct ocxlflash_context *ctx;
203 int rc;
204
205 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
206 if (unlikely(!ctx)) {
207 dev_err(dev, "%s: Context allocation failed\n", __func__);
208 rc = -ENOMEM;
209 goto err1;
210 }
211
212 idr_preload(GFP_KERNEL);
213 rc = idr_alloc(&afu->idr, ctx, 0, afu->max_pasid, GFP_NOWAIT);
214 idr_preload_end();
215 if (unlikely(rc < 0)) {
216 dev_err(dev, "%s: idr_alloc failed rc=%d\n", __func__, rc);
217 goto err2;
218 }
219
220 ctx->pe = rc;
221 ctx->master = false;
222 ctx->mapping = NULL;
223 ctx->hw_afu = afu;
224 out:
225 return ctx;
226 err2:
227 kfree(ctx);
228 err1:
229 ctx = ERR_PTR(rc);
230 goto out;
231 }
232
233 /**
234 * ocxlflash_release_context() - releases an adapter context
235 * @ctx_cookie: Adapter context to be released.
236 *
237 * Return: 0 on success, -errno on failure
238 */
239 static int ocxlflash_release_context(void *ctx_cookie)
240 {
241 struct ocxlflash_context *ctx = ctx_cookie;
242 int rc = 0;
243
244 if (!ctx)
245 goto out;
246
247 idr_remove(&ctx->hw_afu->idr, ctx->pe);
248 ocxlflash_release_mapping(ctx);
249 kfree(ctx);
250 out:
251 return rc;
252 }
253
254 /**
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.
258 */
259 static void ocxlflash_perst_reloads_same_image(void *afu_cookie, bool image)
260 {
261 struct ocxl_hw_afu *afu = afu_cookie;
262
263 afu->perst_same_image = image;
264 }
265
266 /**
267 * ocxlflash_destroy_afu() - destroy the AFU structure
268 * @afu_cookie: AFU to be freed.
269 */
270 static void ocxlflash_destroy_afu(void *afu_cookie)
271 {
272 struct ocxl_hw_afu *afu = afu_cookie;
273
274 if (!afu)
275 return;
276
277 ocxlflash_release_context(afu->ocxl_ctx);
278 idr_destroy(&afu->idr);
279 kfree(afu);
280 }
281
282 /**
283 * ocxlflash_config_fn() - configure the host function
284 * @pdev: PCI device associated with the host.
285 * @afu: AFU associated with the host.
286 *
287 * Return: 0 on success, -errno on failure
288 */
289 static int ocxlflash_config_fn(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
290 {
291 struct ocxl_fn_config *fcfg = &afu->fcfg;
292 struct device *dev = &pdev->dev;
293 u16 base, enabled, supported;
294 int rc = 0;
295
296 /* Read DVSEC config of the function */
297 rc = ocxl_config_read_function(pdev, fcfg);
298 if (unlikely(rc)) {
299 dev_err(dev, "%s: ocxl_config_read_function failed rc=%d\n",
300 __func__, rc);
301 goto out;
302 }
303
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);
308
309 rc = ocxl_config_get_actag_info(pdev, &base, &enabled, &supported);
310 if (unlikely(rc)) {
311 dev_err(dev, "%s: ocxl_config_get_actag_info failed rc=%d\n",
312 __func__, rc);
313 goto out;
314 }
315
316 afu->fn_actag_base = base;
317 afu->fn_actag_enabled = enabled;
318
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);
322 out:
323 return rc;
324 }
325
326 /**
327 * ocxlflash_config_afu() - configure the host AFU
328 * @pdev: PCI device associated with the host.
329 * @afu: AFU associated with the host.
330 *
331 * Must be called _after_ host function configuration.
332 *
333 * Return: 0 on success, -errno on failure
334 */
335 static int ocxlflash_config_afu(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
336 {
337 struct ocxl_afu_config *acfg = &afu->acfg;
338 struct ocxl_fn_config *fcfg = &afu->fcfg;
339 struct device *dev = &pdev->dev;
340 int count;
341 int base;
342 int pos;
343 int rc = 0;
344
345 /* Read AFU config at index 0 */
346 rc = ocxl_config_read_afu(pdev, fcfg, acfg, 0);
347 if (unlikely(rc)) {
348 dev_err(dev, "%s: ocxl_config_read_afu failed rc=%d\n",
349 __func__, rc);
350 goto out;
351 }
352
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;
357
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;
363
364 ocxl_config_set_afu_pasid(pdev, pos, 0, acfg->pasid_supported_log);
365 out:
366 return rc;
367 }
368
369 /**
370 * ocxlflash_create_afu() - create the AFU for OCXL
371 * @pdev: PCI device associated with the host.
372 *
373 * Return: AFU on success, NULL on failure
374 */
375 static void *ocxlflash_create_afu(struct pci_dev *pdev)
376 {
377 struct device *dev = &pdev->dev;
378 struct ocxlflash_context *ctx;
379 struct ocxl_hw_afu *afu;
380 int rc;
381
382 afu = kzalloc(sizeof(*afu), GFP_KERNEL);
383 if (unlikely(!afu)) {
384 dev_err(dev, "%s: HW AFU allocation failed\n", __func__);
385 goto out;
386 }
387
388 afu->pdev = pdev;
389 afu->dev = dev;
390
391 rc = ocxlflash_config_fn(pdev, afu);
392 if (unlikely(rc)) {
393 dev_err(dev, "%s: Function configuration failed rc=%d\n",
394 __func__, rc);
395 goto err1;
396 }
397
398 rc = ocxlflash_config_afu(pdev, afu);
399 if (unlikely(rc)) {
400 dev_err(dev, "%s: AFU configuration failed rc=%d\n",
401 __func__, rc);
402 goto err1;
403 }
404
405 ctx = ocxlflash_dev_context_init(pdev, afu);
406 if (IS_ERR(ctx)) {
407 rc = PTR_ERR(ctx);
408 dev_err(dev, "%s: ocxlflash_dev_context_init failed rc=%d\n",
409 __func__, rc);
410 goto err1;
411 }
412
413 idr_init(&afu->idr);
414 afu->ocxl_ctx = ctx;
415 out:
416 return afu;
417 err1:
418 kfree(afu);
419 afu = NULL;
420 goto out;
421 }
422
423 static const struct file_operations ocxl_afu_fops = {
424 .owner = THIS_MODULE,
425 };
426
427 /**
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.
432 *
433 * Return: pointer to the file on success, ERR_PTR on failure
434 */
435 static struct file *ocxlflash_get_fd(void *ctx_cookie,
436 struct file_operations *fops, int *fd)
437 {
438 struct ocxlflash_context *ctx = ctx_cookie;
439 struct device *dev = ctx->hw_afu->dev;
440 struct file *file;
441 int flags, fdtmp;
442 int rc = 0;
443 char *name = NULL;
444
445 /* Only allow one fd per context */
446 if (ctx->mapping) {
447 dev_err(dev, "%s: Context is already mapped to an fd\n",
448 __func__);
449 rc = -EEXIST;
450 goto err1;
451 }
452
453 flags = O_RDWR | O_CLOEXEC;
454
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",
459 __func__, rc);
460 goto err1;
461 }
462 fdtmp = rc;
463
464 /* Use default ops if there is no fops */
465 if (!fops)
466 fops = (struct file_operations *)&ocxl_afu_fops;
467
468 name = kasprintf(GFP_KERNEL, "ocxlflash:%d", ctx->pe);
469 file = ocxlflash_getfile(dev, name, fops, ctx, flags);
470 kfree(name);
471 if (IS_ERR(file)) {
472 rc = PTR_ERR(file);
473 dev_err(dev, "%s: ocxlflash_getfile failed rc=%d\n",
474 __func__, rc);
475 goto err2;
476 }
477
478 ctx->mapping = file->f_mapping;
479 *fd = fdtmp;
480 out:
481 return file;
482 err2:
483 put_unused_fd(fdtmp);
484 err1:
485 file = ERR_PTR(rc);
486 goto out;
487 }
488
489 /**
490 * ocxlflash_fops_get_context() - get the context associated with the file
491 * @file: File associated with the adapter context.
492 *
493 * Return: pointer to the context
494 */
495 static void *ocxlflash_fops_get_context(struct file *file)
496 {
497 return file->private_data;
498 }
499
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,
513 };