forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 ee930fffee469d076998274a2ca55e13dc1efb67
kernel/drivers/misc/ocxl/file.c
....@@ -3,6 +3,7 @@
33 #include <linux/fs.h>
44 #include <linux/poll.h>
55 #include <linux/sched/signal.h>
6
+#include <linux/eventfd.h>
67 #include <linux/uaccess.h>
78 #include <uapi/misc/ocxl.h>
89 #include <asm/reg.h>
....@@ -17,70 +18,55 @@
1718 static struct mutex minors_idr_lock;
1819 static struct idr minors_idr;
1920
20
-static struct ocxl_afu *find_and_get_afu(dev_t devno)
21
+static struct ocxl_file_info *find_and_get_file_info(dev_t devno)
2122 {
22
- struct ocxl_afu *afu;
23
- int afu_minor;
23
+ struct ocxl_file_info *info;
2424
25
- afu_minor = MINOR(devno);
26
- /*
27
- * We don't declare an RCU critical section here, as our AFU
28
- * is protected by a reference counter on the device. By the time the
29
- * minor number of a device is removed from the idr, the ref count of
30
- * the device is already at 0, so no user API will access that AFU and
31
- * this function can't return it.
32
- */
33
- afu = idr_find(&minors_idr, afu_minor);
34
- if (afu)
35
- ocxl_afu_get(afu);
36
- return afu;
25
+ mutex_lock(&minors_idr_lock);
26
+ info = idr_find(&minors_idr, MINOR(devno));
27
+ if (info)
28
+ get_device(&info->dev);
29
+ mutex_unlock(&minors_idr_lock);
30
+ return info;
3731 }
3832
39
-static int allocate_afu_minor(struct ocxl_afu *afu)
33
+static int allocate_minor(struct ocxl_file_info *info)
4034 {
4135 int minor;
4236
4337 mutex_lock(&minors_idr_lock);
44
- minor = idr_alloc(&minors_idr, afu, 0, OCXL_NUM_MINORS, GFP_KERNEL);
38
+ minor = idr_alloc(&minors_idr, info, 0, OCXL_NUM_MINORS, GFP_KERNEL);
4539 mutex_unlock(&minors_idr_lock);
4640 return minor;
4741 }
4842
49
-static void free_afu_minor(struct ocxl_afu *afu)
43
+static void free_minor(struct ocxl_file_info *info)
5044 {
5145 mutex_lock(&minors_idr_lock);
52
- idr_remove(&minors_idr, MINOR(afu->dev.devt));
46
+ idr_remove(&minors_idr, MINOR(info->dev.devt));
5347 mutex_unlock(&minors_idr_lock);
5448 }
5549
5650 static int afu_open(struct inode *inode, struct file *file)
5751 {
58
- struct ocxl_afu *afu;
52
+ struct ocxl_file_info *info;
5953 struct ocxl_context *ctx;
6054 int rc;
6155
6256 pr_debug("%s for device %x\n", __func__, inode->i_rdev);
6357
64
- afu = find_and_get_afu(inode->i_rdev);
65
- if (!afu)
58
+ info = find_and_get_file_info(inode->i_rdev);
59
+ if (!info)
6660 return -ENODEV;
6761
68
- ctx = ocxl_context_alloc();
69
- if (!ctx) {
70
- rc = -ENOMEM;
71
- goto put_afu;
62
+ rc = ocxl_context_alloc(&ctx, info->afu, inode->i_mapping);
63
+ if (rc) {
64
+ put_device(&info->dev);
65
+ return rc;
7266 }
73
-
74
- rc = ocxl_context_init(ctx, afu, inode->i_mapping);
75
- if (rc)
76
- goto put_afu;
67
+ put_device(&info->dev);
7768 file->private_data = ctx;
78
- ocxl_afu_put(afu);
7969 return 0;
80
-
81
-put_afu:
82
- ocxl_afu_put(afu);
83
- return rc;
8470 }
8571
8672 static long afu_ioctl_attach(struct ocxl_context *ctx,
....@@ -100,7 +86,7 @@
10086 return -EINVAL;
10187
10288 amr = arg.amr & mfspr(SPRN_UAMOR);
103
- rc = ocxl_context_attach(ctx, amr);
89
+ rc = ocxl_context_attach(ctx, amr, current->mm);
10490 return rc;
10591 }
10692
....@@ -151,10 +137,9 @@
151137 mutex_unlock(&ctx->status_mutex);
152138
153139 if (status == ATTACHED) {
154
- int rc;
155
- struct link *link = ctx->afu->fn->link;
140
+ int rc = ocxl_link_update_pe(ctx->afu->fn->link,
141
+ ctx->pasid, ctx->tidr);
156142
157
- rc = ocxl_link_update_pe(link, ctx->pasid, ctx->tidr);
158143 if (rc)
159144 return rc;
160145 }
....@@ -198,18 +183,40 @@
198183 x == OCXL_IOCTL_GET_FEATURES ? "GET_FEATURES" : \
199184 "UNKNOWN")
200185
186
+static irqreturn_t irq_handler(void *private)
187
+{
188
+ struct eventfd_ctx *ev_ctx = private;
189
+
190
+ eventfd_signal(ev_ctx, 1);
191
+ return IRQ_HANDLED;
192
+}
193
+
194
+static void irq_free(void *private)
195
+{
196
+ struct eventfd_ctx *ev_ctx = private;
197
+
198
+ eventfd_ctx_put(ev_ctx);
199
+}
200
+
201201 static long afu_ioctl(struct file *file, unsigned int cmd,
202202 unsigned long args)
203203 {
204204 struct ocxl_context *ctx = file->private_data;
205205 struct ocxl_ioctl_irq_fd irq_fd;
206
+ struct eventfd_ctx *ev_ctx;
207
+ int irq_id;
206208 u64 irq_offset;
207209 long rc;
210
+ bool closed;
208211
209212 pr_debug("%s for context %d, command %s\n", __func__, ctx->pasid,
210213 CMD_STR(cmd));
211214
212
- if (ctx->status == CLOSED)
215
+ mutex_lock(&ctx->status_mutex);
216
+ closed = (ctx->status == CLOSED);
217
+ mutex_unlock(&ctx->status_mutex);
218
+
219
+ if (closed)
213220 return -EIO;
214221
215222 switch (cmd) {
....@@ -219,12 +226,13 @@
219226 break;
220227
221228 case OCXL_IOCTL_IRQ_ALLOC:
222
- rc = ocxl_afu_irq_alloc(ctx, &irq_offset);
229
+ rc = ocxl_afu_irq_alloc(ctx, &irq_id);
223230 if (!rc) {
231
+ irq_offset = ocxl_irq_id_to_offset(ctx, irq_id);
224232 rc = copy_to_user((u64 __user *) args, &irq_offset,
225233 sizeof(irq_offset));
226234 if (rc) {
227
- ocxl_afu_irq_free(ctx, irq_offset);
235
+ ocxl_afu_irq_free(ctx, irq_id);
228236 return -EFAULT;
229237 }
230238 }
....@@ -235,7 +243,8 @@
235243 sizeof(irq_offset));
236244 if (rc)
237245 return -EFAULT;
238
- rc = ocxl_afu_irq_free(ctx, irq_offset);
246
+ irq_id = ocxl_irq_offset_to_id(ctx, irq_offset);
247
+ rc = ocxl_afu_irq_free(ctx, irq_id);
239248 break;
240249
241250 case OCXL_IOCTL_IRQ_SET_FD:
....@@ -245,8 +254,13 @@
245254 return -EFAULT;
246255 if (irq_fd.reserved)
247256 return -EINVAL;
248
- rc = ocxl_afu_irq_set_fd(ctx, irq_fd.irq_offset,
249
- irq_fd.eventfd);
257
+ irq_id = ocxl_irq_offset_to_id(ctx, irq_fd.irq_offset);
258
+ ev_ctx = eventfd_ctx_fdget(irq_fd.eventfd);
259
+ if (IS_ERR(ev_ctx))
260
+ return PTR_ERR(ev_ctx);
261
+ rc = ocxl_irq_set_handler(ctx, irq_id, irq_handler, irq_free, ev_ctx);
262
+ if (rc)
263
+ eventfd_ctx_put(ev_ctx);
250264 break;
251265
252266 case OCXL_IOCTL_GET_METADATA:
....@@ -469,39 +483,107 @@
469483 .release = afu_release,
470484 };
471485
472
-int ocxl_create_cdev(struct ocxl_afu *afu)
486
+// Free the info struct
487
+static void info_release(struct device *dev)
488
+{
489
+ struct ocxl_file_info *info = container_of(dev, struct ocxl_file_info, dev);
490
+
491
+ ocxl_afu_put(info->afu);
492
+ kfree(info);
493
+}
494
+
495
+static int ocxl_file_make_visible(struct ocxl_file_info *info)
473496 {
474497 int rc;
475498
476
- cdev_init(&afu->cdev, &ocxl_afu_fops);
477
- rc = cdev_add(&afu->cdev, afu->dev.devt, 1);
499
+ cdev_init(&info->cdev, &ocxl_afu_fops);
500
+ rc = cdev_add(&info->cdev, info->dev.devt, 1);
478501 if (rc) {
479
- dev_err(&afu->dev, "Unable to add afu char device: %d\n", rc);
502
+ dev_err(&info->dev, "Unable to add afu char device: %d\n", rc);
480503 return rc;
481504 }
505
+
482506 return 0;
483507 }
484508
485
-void ocxl_destroy_cdev(struct ocxl_afu *afu)
509
+static void ocxl_file_make_invisible(struct ocxl_file_info *info)
486510 {
487
- cdev_del(&afu->cdev);
511
+ cdev_del(&info->cdev);
488512 }
489513
490
-int ocxl_register_afu(struct ocxl_afu *afu)
514
+int ocxl_file_register_afu(struct ocxl_afu *afu)
491515 {
492516 int minor;
517
+ int rc;
518
+ struct ocxl_file_info *info;
519
+ struct ocxl_fn *fn = afu->fn;
520
+ struct pci_dev *pci_dev = to_pci_dev(fn->dev.parent);
493521
494
- minor = allocate_afu_minor(afu);
495
- if (minor < 0)
522
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
523
+ if (info == NULL)
524
+ return -ENOMEM;
525
+
526
+ minor = allocate_minor(info);
527
+ if (minor < 0) {
528
+ kfree(info);
496529 return minor;
497
- afu->dev.devt = MKDEV(MAJOR(ocxl_dev), minor);
498
- afu->dev.class = ocxl_class;
499
- return device_register(&afu->dev);
530
+ }
531
+
532
+ info->dev.parent = &fn->dev;
533
+ info->dev.devt = MKDEV(MAJOR(ocxl_dev), minor);
534
+ info->dev.class = ocxl_class;
535
+ info->dev.release = info_release;
536
+
537
+ info->afu = afu;
538
+ ocxl_afu_get(afu);
539
+
540
+ rc = dev_set_name(&info->dev, "%s.%s.%hhu",
541
+ afu->config.name, dev_name(&pci_dev->dev), afu->config.idx);
542
+ if (rc)
543
+ goto err_put;
544
+
545
+ rc = device_register(&info->dev);
546
+ if (rc) {
547
+ free_minor(info);
548
+ put_device(&info->dev);
549
+ return rc;
550
+ }
551
+
552
+ rc = ocxl_sysfs_register_afu(info);
553
+ if (rc)
554
+ goto err_unregister;
555
+
556
+ rc = ocxl_file_make_visible(info);
557
+ if (rc)
558
+ goto err_unregister;
559
+
560
+ ocxl_afu_set_private(afu, info);
561
+
562
+ return 0;
563
+
564
+err_unregister:
565
+ ocxl_sysfs_unregister_afu(info); // safe to call even if register failed
566
+ free_minor(info);
567
+ device_unregister(&info->dev);
568
+ return rc;
569
+err_put:
570
+ ocxl_afu_put(afu);
571
+ free_minor(info);
572
+ kfree(info);
573
+ return rc;
500574 }
501575
502
-void ocxl_unregister_afu(struct ocxl_afu *afu)
576
+void ocxl_file_unregister_afu(struct ocxl_afu *afu)
503577 {
504
- free_afu_minor(afu);
578
+ struct ocxl_file_info *info = ocxl_afu_get_private(afu);
579
+
580
+ if (!info)
581
+ return;
582
+
583
+ ocxl_file_make_invisible(info);
584
+ ocxl_sysfs_unregister_afu(info);
585
+ free_minor(info);
586
+ device_unregister(&info->dev);
505587 }
506588
507589 static char *ocxl_devnode(struct device *dev, umode_t *mode)