cdev.c (0ea8a56de21be24cb79abb03dee79aabcd60a316) cdev.c (8e50d392652f20616a136165dff516b86baf5e49)
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright(c) 2019 Intel Corporation. All rights rsvd. */
3#include <linux/init.h>
4#include <linux/kernel.h>
5#include <linux/module.h>
6#include <linux/pci.h>
7#include <linux/device.h>
8#include <linux/sched/task.h>
9#include <linux/intel-svm.h>
10#include <linux/io-64-nonatomic-lo-hi.h>
11#include <linux/cdev.h>
12#include <linux/fs.h>
13#include <linux/poll.h>
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright(c) 2019 Intel Corporation. All rights rsvd. */
3#include <linux/init.h>
4#include <linux/kernel.h>
5#include <linux/module.h>
6#include <linux/pci.h>
7#include <linux/device.h>
8#include <linux/sched/task.h>
9#include <linux/intel-svm.h>
10#include <linux/io-64-nonatomic-lo-hi.h>
11#include <linux/cdev.h>
12#include <linux/fs.h>
13#include <linux/poll.h>
14#include <linux/iommu.h>
14#include <uapi/linux/idxd.h>
15#include "registers.h"
16#include "idxd.h"
17
18struct idxd_cdev_context {
19 const char *name;
20 dev_t devt;
21 struct ida minor_ida;

--- 5 unchanged lines hidden (view full) ---

27 */
28static struct idxd_cdev_context ictx[IDXD_TYPE_MAX] = {
29 { .name = "dsa" },
30};
31
32struct idxd_user_context {
33 struct idxd_wq *wq;
34 struct task_struct *task;
15#include <uapi/linux/idxd.h>
16#include "registers.h"
17#include "idxd.h"
18
19struct idxd_cdev_context {
20 const char *name;
21 dev_t devt;
22 struct ida minor_ida;

--- 5 unchanged lines hidden (view full) ---

28 */
29static struct idxd_cdev_context ictx[IDXD_TYPE_MAX] = {
30 { .name = "dsa" },
31};
32
33struct idxd_user_context {
34 struct idxd_wq *wq;
35 struct task_struct *task;
36 unsigned int pasid;
35 unsigned int flags;
37 unsigned int flags;
38 struct iommu_sva *sva;
36};
37
38enum idxd_cdev_cleanup {
39 CDEV_NORMAL = 0,
40 CDEV_FAILED,
41};
42
43static void idxd_cdev_dev_release(struct device *dev)

--- 26 unchanged lines hidden (view full) ---

70
71static int idxd_cdev_open(struct inode *inode, struct file *filp)
72{
73 struct idxd_user_context *ctx;
74 struct idxd_device *idxd;
75 struct idxd_wq *wq;
76 struct device *dev;
77 int rc = 0;
39};
40
41enum idxd_cdev_cleanup {
42 CDEV_NORMAL = 0,
43 CDEV_FAILED,
44};
45
46static void idxd_cdev_dev_release(struct device *dev)

--- 26 unchanged lines hidden (view full) ---

73
74static int idxd_cdev_open(struct inode *inode, struct file *filp)
75{
76 struct idxd_user_context *ctx;
77 struct idxd_device *idxd;
78 struct idxd_wq *wq;
79 struct device *dev;
80 int rc = 0;
81 struct iommu_sva *sva;
82 unsigned int pasid;
78
79 wq = inode_wq(inode);
80 idxd = wq->idxd;
81 dev = &idxd->pdev->dev;
82
83 dev_dbg(dev, "%s called: %d\n", __func__, idxd_wq_refcount(wq));
84
85 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);

--- 4 unchanged lines hidden (view full) ---

90
91 if (idxd_wq_refcount(wq) > 0 && wq_dedicated(wq)) {
92 rc = -EBUSY;
93 goto failed;
94 }
95
96 ctx->wq = wq;
97 filp->private_data = ctx;
83
84 wq = inode_wq(inode);
85 idxd = wq->idxd;
86 dev = &idxd->pdev->dev;
87
88 dev_dbg(dev, "%s called: %d\n", __func__, idxd_wq_refcount(wq));
89
90 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);

--- 4 unchanged lines hidden (view full) ---

95
96 if (idxd_wq_refcount(wq) > 0 && wq_dedicated(wq)) {
97 rc = -EBUSY;
98 goto failed;
99 }
100
101 ctx->wq = wq;
102 filp->private_data = ctx;
103
104 if (device_pasid_enabled(idxd)) {
105 sva = iommu_sva_bind_device(dev, current->mm, NULL);
106 if (IS_ERR(sva)) {
107 rc = PTR_ERR(sva);
108 dev_err(dev, "pasid allocation failed: %d\n", rc);
109 goto failed;
110 }
111
112 pasid = iommu_sva_get_pasid(sva);
113 if (pasid == IOMMU_PASID_INVALID) {
114 iommu_sva_unbind_device(sva);
115 goto failed;
116 }
117
118 ctx->sva = sva;
119 ctx->pasid = pasid;
120
121 if (wq_dedicated(wq)) {
122 rc = idxd_wq_set_pasid(wq, pasid);
123 if (rc < 0) {
124 iommu_sva_unbind_device(sva);
125 dev_err(dev, "wq set pasid failed: %d\n", rc);
126 goto failed;
127 }
128 }
129 }
130
98 idxd_wq_get(wq);
99 mutex_unlock(&wq->wq_lock);
100 return 0;
101
102 failed:
103 mutex_unlock(&wq->wq_lock);
104 kfree(ctx);
105 return rc;
106}
107
108static int idxd_cdev_release(struct inode *node, struct file *filep)
109{
110 struct idxd_user_context *ctx = filep->private_data;
111 struct idxd_wq *wq = ctx->wq;
112 struct idxd_device *idxd = wq->idxd;
113 struct device *dev = &idxd->pdev->dev;
131 idxd_wq_get(wq);
132 mutex_unlock(&wq->wq_lock);
133 return 0;
134
135 failed:
136 mutex_unlock(&wq->wq_lock);
137 kfree(ctx);
138 return rc;
139}
140
141static int idxd_cdev_release(struct inode *node, struct file *filep)
142{
143 struct idxd_user_context *ctx = filep->private_data;
144 struct idxd_wq *wq = ctx->wq;
145 struct idxd_device *idxd = wq->idxd;
146 struct device *dev = &idxd->pdev->dev;
147 int rc;
114
115 dev_dbg(dev, "%s called\n", __func__);
116 filep->private_data = NULL;
117
118 /* Wait for in-flight operations to complete. */
148
149 dev_dbg(dev, "%s called\n", __func__);
150 filep->private_data = NULL;
151
152 /* Wait for in-flight operations to complete. */
119 idxd_wq_drain(wq);
153 if (wq_shared(wq)) {
154 idxd_device_drain_pasid(idxd, ctx->pasid);
155 } else {
156 if (device_pasid_enabled(idxd)) {
157 /* The wq disable in the disable pasid function will drain the wq */
158 rc = idxd_wq_disable_pasid(wq);
159 if (rc < 0)
160 dev_err(dev, "wq disable pasid failed.\n");
161 } else {
162 idxd_wq_drain(wq);
163 }
164 }
120
165
166 if (ctx->sva)
167 iommu_sva_unbind_device(ctx->sva);
121 kfree(ctx);
122 mutex_lock(&wq->wq_lock);
123 idxd_wq_put(wq);
124 mutex_unlock(&wq->wq_lock);
125 return 0;
126}
127
128static int check_vma(struct idxd_wq *wq, struct vm_area_struct *vma,

--- 190 unchanged lines hidden ---
168 kfree(ctx);
169 mutex_lock(&wq->wq_lock);
170 idxd_wq_put(wq);
171 mutex_unlock(&wq->wq_lock);
172 return 0;
173}
174
175static int check_vma(struct idxd_wq *wq, struct vm_area_struct *vma,

--- 190 unchanged lines hidden ---