Skip to content

Commit e6fd6d7

Browse files
davejiangvinodkoul
authored andcommitted
dmaengine: idxd: add a device to represent the file opened
Embed a struct device for the user file context in order to export sysfs attributes related with the opened file. Tie the lifetime of the file context to the device. The sysfs entry will be added under the char device. Tested-by: Tony Zhu <[email protected]> Signed-off-by: Dave Jiang <[email protected]> Co-developed-by: Fenghua Yu <[email protected]> Signed-off-by: Fenghua Yu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent fecae13 commit e6fd6d7

File tree

2 files changed

+97
-24
lines changed

2 files changed

+97
-24
lines changed

drivers/dma/idxd/cdev.c

Lines changed: 95 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ struct idxd_cdev_context {
2323
struct ida minor_ida;
2424
};
2525

26+
/*
27+
* Since user file names are global in DSA devices, define their ida's as
28+
* global to avoid conflict file names.
29+
*/
30+
static DEFINE_IDA(file_ida);
31+
static DEFINE_MUTEX(ida_lock);
32+
2633
/*
2734
* ictx is an array based off of accelerator types. enum idxd_type
2835
* is used as index
@@ -39,7 +46,60 @@ struct idxd_user_context {
3946
struct mm_struct *mm;
4047
unsigned int flags;
4148
struct iommu_sva *sva;
49+
struct idxd_dev idxd_dev;
4250
u64 counters[COUNTER_MAX];
51+
int id;
52+
};
53+
54+
static void idxd_cdev_evl_drain_pasid(struct idxd_wq *wq, u32 pasid);
55+
static void idxd_xa_pasid_remove(struct idxd_user_context *ctx);
56+
57+
static inline struct idxd_user_context *dev_to_uctx(struct device *dev)
58+
{
59+
struct idxd_dev *idxd_dev = confdev_to_idxd_dev(dev);
60+
61+
return container_of(idxd_dev, struct idxd_user_context, idxd_dev);
62+
}
63+
64+
static void idxd_file_dev_release(struct device *dev)
65+
{
66+
struct idxd_user_context *ctx = dev_to_uctx(dev);
67+
struct idxd_wq *wq = ctx->wq;
68+
struct idxd_device *idxd = wq->idxd;
69+
int rc;
70+
71+
mutex_lock(&ida_lock);
72+
ida_free(&file_ida, ctx->id);
73+
mutex_unlock(&ida_lock);
74+
75+
/* Wait for in-flight operations to complete. */
76+
if (wq_shared(wq)) {
77+
idxd_device_drain_pasid(idxd, ctx->pasid);
78+
} else {
79+
if (device_user_pasid_enabled(idxd)) {
80+
/* The wq disable in the disable pasid function will drain the wq */
81+
rc = idxd_wq_disable_pasid(wq);
82+
if (rc < 0)
83+
dev_err(dev, "wq disable pasid failed.\n");
84+
} else {
85+
idxd_wq_drain(wq);
86+
}
87+
}
88+
89+
if (ctx->sva) {
90+
idxd_cdev_evl_drain_pasid(wq, ctx->pasid);
91+
iommu_sva_unbind_device(ctx->sva);
92+
idxd_xa_pasid_remove(ctx);
93+
}
94+
kfree(ctx);
95+
mutex_lock(&wq->wq_lock);
96+
idxd_wq_put(wq);
97+
mutex_unlock(&wq->wq_lock);
98+
}
99+
100+
static struct device_type idxd_cdev_file_type = {
101+
.name = "idxd_file",
102+
.release = idxd_file_dev_release,
43103
};
44104

45105
static void idxd_cdev_dev_release(struct device *dev)
@@ -107,10 +167,11 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
107167
struct idxd_user_context *ctx;
108168
struct idxd_device *idxd;
109169
struct idxd_wq *wq;
110-
struct device *dev;
170+
struct device *dev, *fdev;
111171
int rc = 0;
112172
struct iommu_sva *sva;
113173
unsigned int pasid;
174+
struct idxd_cdev *idxd_cdev;
114175

115176
wq = inode_wq(inode);
116177
idxd = wq->idxd;
@@ -166,10 +227,41 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
166227
}
167228
}
168229

230+
idxd_cdev = wq->idxd_cdev;
231+
mutex_lock(&ida_lock);
232+
ctx->id = ida_alloc(&file_ida, GFP_KERNEL);
233+
mutex_unlock(&ida_lock);
234+
if (ctx->id < 0) {
235+
dev_warn(dev, "ida alloc failure\n");
236+
goto failed_ida;
237+
}
238+
ctx->idxd_dev.type = IDXD_DEV_CDEV_FILE;
239+
fdev = user_ctx_dev(ctx);
240+
device_initialize(fdev);
241+
fdev->parent = cdev_dev(idxd_cdev);
242+
fdev->bus = &dsa_bus_type;
243+
fdev->type = &idxd_cdev_file_type;
244+
245+
rc = dev_set_name(fdev, "file%d", ctx->id);
246+
if (rc < 0) {
247+
dev_warn(dev, "set name failure\n");
248+
goto failed_dev_name;
249+
}
250+
251+
rc = device_add(fdev);
252+
if (rc < 0) {
253+
dev_warn(dev, "file device add failure\n");
254+
goto failed_dev_add;
255+
}
256+
169257
idxd_wq_get(wq);
170258
mutex_unlock(&wq->wq_lock);
171259
return 0;
172260

261+
failed_dev_add:
262+
failed_dev_name:
263+
put_device(fdev);
264+
failed_ida:
173265
failed_set_pasid:
174266
if (device_user_pasid_enabled(idxd))
175267
idxd_xa_pasid_remove(ctx);
@@ -217,34 +309,12 @@ static int idxd_cdev_release(struct inode *node, struct file *filep)
217309
struct idxd_wq *wq = ctx->wq;
218310
struct idxd_device *idxd = wq->idxd;
219311
struct device *dev = &idxd->pdev->dev;
220-
int rc;
221312

222313
dev_dbg(dev, "%s called\n", __func__);
223314
filep->private_data = NULL;
224315

225-
/* Wait for in-flight operations to complete. */
226-
if (wq_shared(wq)) {
227-
idxd_device_drain_pasid(idxd, ctx->pasid);
228-
} else {
229-
if (device_user_pasid_enabled(idxd)) {
230-
/* The wq disable in the disable pasid function will drain the wq */
231-
rc = idxd_wq_disable_pasid(wq);
232-
if (rc < 0)
233-
dev_err(dev, "wq disable pasid failed.\n");
234-
} else {
235-
idxd_wq_drain(wq);
236-
}
237-
}
316+
device_unregister(user_ctx_dev(ctx));
238317

239-
if (ctx->sva) {
240-
idxd_cdev_evl_drain_pasid(wq, ctx->pasid);
241-
iommu_sva_unbind_device(ctx->sva);
242-
idxd_xa_pasid_remove(ctx);
243-
}
244-
kfree(ctx);
245-
mutex_lock(&wq->wq_lock);
246-
idxd_wq_put(wq);
247-
mutex_unlock(&wq->wq_lock);
248318
return 0;
249319
}
250320

@@ -375,6 +445,7 @@ void idxd_wq_del_cdev(struct idxd_wq *wq)
375445
struct idxd_cdev *idxd_cdev;
376446

377447
idxd_cdev = wq->idxd_cdev;
448+
ida_destroy(&file_ida);
378449
wq->idxd_cdev = NULL;
379450
cdev_device_del(&idxd_cdev->cdev, cdev_dev(idxd_cdev));
380451
put_device(cdev_dev(idxd_cdev));

drivers/dma/idxd/idxd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ enum idxd_dev_type {
3232
IDXD_DEV_GROUP,
3333
IDXD_DEV_ENGINE,
3434
IDXD_DEV_CDEV,
35+
IDXD_DEV_CDEV_FILE,
3536
IDXD_DEV_MAX_TYPE,
3637
};
3738

@@ -405,6 +406,7 @@ enum idxd_completion_status {
405406
#define engine_confdev(engine) &engine->idxd_dev.conf_dev
406407
#define group_confdev(group) &group->idxd_dev.conf_dev
407408
#define cdev_dev(cdev) &cdev->idxd_dev.conf_dev
409+
#define user_ctx_dev(ctx) (&(ctx)->idxd_dev.conf_dev)
408410

409411
#define confdev_to_idxd_dev(dev) container_of(dev, struct idxd_dev, conf_dev)
410412
#define idxd_dev_to_idxd(idxd_dev) container_of(idxd_dev, struct idxd_device, idxd_dev)

0 commit comments

Comments
 (0)