Skip to content

Commit 3bf1311

Browse files
jgunthorpeawilliam
authored andcommitted
vfio/ccw: Convert to use vfio_register_emulated_iommu_dev()
This is a more complicated conversion because vfio_ccw is sharing the vfio_device between both the mdev_device, its vfio_device and the css_driver. The mdev is a singleton, and the reason for this sharing is so the extra css_driver function callbacks to be delivered to the vfio_device implementation. This keeps things as they are, with the css_driver allocating the singleton, not the mdev_driver. Embed the vfio_device in the vfio_ccw_private and instantiate it as a vfio_device when the mdev probes. The drvdata of both the css_device and the mdev_device point at the private, and container_of is used to get it back from the vfio_device. Reviewed-by: Eric Farman <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alex Williamson <[email protected]>
1 parent 39b6ee0 commit 3bf1311

File tree

3 files changed

+85
-48
lines changed

3 files changed

+85
-48
lines changed

drivers/s390/cio/vfio_ccw_drv.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ static int __init vfio_ccw_sch_init(void)
468468
vfio_ccw_work_q = create_singlethread_workqueue("vfio-ccw");
469469
if (!vfio_ccw_work_q) {
470470
ret = -ENOMEM;
471-
goto out_err;
471+
goto out_regions;
472472
}
473473

474474
vfio_ccw_io_region = kmem_cache_create_usercopy("vfio_ccw_io_region",
@@ -477,7 +477,7 @@ static int __init vfio_ccw_sch_init(void)
477477
sizeof(struct ccw_io_region), NULL);
478478
if (!vfio_ccw_io_region) {
479479
ret = -ENOMEM;
480-
goto out_err;
480+
goto out_regions;
481481
}
482482

483483
vfio_ccw_cmd_region = kmem_cache_create_usercopy("vfio_ccw_cmd_region",
@@ -486,7 +486,7 @@ static int __init vfio_ccw_sch_init(void)
486486
sizeof(struct ccw_cmd_region), NULL);
487487
if (!vfio_ccw_cmd_region) {
488488
ret = -ENOMEM;
489-
goto out_err;
489+
goto out_regions;
490490
}
491491

492492
vfio_ccw_schib_region = kmem_cache_create_usercopy("vfio_ccw_schib_region",
@@ -496,7 +496,7 @@ static int __init vfio_ccw_sch_init(void)
496496

497497
if (!vfio_ccw_schib_region) {
498498
ret = -ENOMEM;
499-
goto out_err;
499+
goto out_regions;
500500
}
501501

502502
vfio_ccw_crw_region = kmem_cache_create_usercopy("vfio_ccw_crw_region",
@@ -506,19 +506,25 @@ static int __init vfio_ccw_sch_init(void)
506506

507507
if (!vfio_ccw_crw_region) {
508508
ret = -ENOMEM;
509-
goto out_err;
509+
goto out_regions;
510510
}
511511

512+
ret = mdev_register_driver(&vfio_ccw_mdev_driver);
513+
if (ret)
514+
goto out_regions;
515+
512516
isc_register(VFIO_CCW_ISC);
513517
ret = css_driver_register(&vfio_ccw_sch_driver);
514518
if (ret) {
515519
isc_unregister(VFIO_CCW_ISC);
516-
goto out_err;
520+
goto out_driver;
517521
}
518522

519523
return ret;
520524

521-
out_err:
525+
out_driver:
526+
mdev_unregister_driver(&vfio_ccw_mdev_driver);
527+
out_regions:
522528
vfio_ccw_destroy_regions();
523529
destroy_workqueue(vfio_ccw_work_q);
524530
vfio_ccw_debug_exit();
@@ -528,6 +534,7 @@ static int __init vfio_ccw_sch_init(void)
528534
static void __exit vfio_ccw_sch_exit(void)
529535
{
530536
css_driver_unregister(&vfio_ccw_sch_driver);
537+
mdev_unregister_driver(&vfio_ccw_mdev_driver);
531538
isc_unregister(VFIO_CCW_ISC);
532539
vfio_ccw_destroy_regions();
533540
destroy_workqueue(vfio_ccw_work_q);

drivers/s390/cio/vfio_ccw_ops.c

Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
#include "vfio_ccw_private.h"
1919

20+
static const struct vfio_device_ops vfio_ccw_dev_ops;
21+
2022
static int vfio_ccw_mdev_reset(struct vfio_ccw_private *private)
2123
{
2224
struct subchannel *sch;
@@ -111,17 +113,21 @@ static struct attribute_group *mdev_type_groups[] = {
111113
NULL,
112114
};
113115

114-
static int vfio_ccw_mdev_create(struct mdev_device *mdev)
116+
static int vfio_ccw_mdev_probe(struct mdev_device *mdev)
115117
{
116-
struct vfio_ccw_private *private =
117-
dev_get_drvdata(mdev_parent_dev(mdev));
118+
struct vfio_ccw_private *private = dev_get_drvdata(mdev->dev.parent);
119+
int ret;
118120

119121
if (private->state == VFIO_CCW_STATE_NOT_OPER)
120122
return -ENODEV;
121123

122124
if (atomic_dec_if_positive(&private->avail) < 0)
123125
return -EPERM;
124126

127+
memset(&private->vdev, 0, sizeof(private->vdev));
128+
vfio_init_group_dev(&private->vdev, &mdev->dev,
129+
&vfio_ccw_dev_ops);
130+
125131
private->mdev = mdev;
126132
private->state = VFIO_CCW_STATE_IDLE;
127133

@@ -130,43 +136,54 @@ static int vfio_ccw_mdev_create(struct mdev_device *mdev)
130136
private->sch->schid.ssid,
131137
private->sch->schid.sch_no);
132138

139+
ret = vfio_register_emulated_iommu_dev(&private->vdev);
140+
if (ret)
141+
goto err_atomic;
142+
dev_set_drvdata(&mdev->dev, private);
133143
return 0;
144+
145+
err_atomic:
146+
vfio_uninit_group_dev(&private->vdev);
147+
atomic_inc(&private->avail);
148+
private->mdev = NULL;
149+
private->state = VFIO_CCW_STATE_IDLE;
150+
return ret;
134151
}
135152

136-
static int vfio_ccw_mdev_remove(struct mdev_device *mdev)
153+
static void vfio_ccw_mdev_remove(struct mdev_device *mdev)
137154
{
138-
struct vfio_ccw_private *private =
139-
dev_get_drvdata(mdev_parent_dev(mdev));
155+
struct vfio_ccw_private *private = dev_get_drvdata(mdev->dev.parent);
140156

141157
VFIO_CCW_MSG_EVENT(2, "mdev %pUl, sch %x.%x.%04x: remove\n",
142158
mdev_uuid(mdev), private->sch->schid.cssid,
143159
private->sch->schid.ssid,
144160
private->sch->schid.sch_no);
145161

162+
vfio_unregister_group_dev(&private->vdev);
163+
146164
if ((private->state != VFIO_CCW_STATE_NOT_OPER) &&
147165
(private->state != VFIO_CCW_STATE_STANDBY)) {
148166
if (!vfio_ccw_sch_quiesce(private->sch))
149167
private->state = VFIO_CCW_STATE_STANDBY;
150168
/* The state will be NOT_OPER on error. */
151169
}
152170

171+
vfio_uninit_group_dev(&private->vdev);
153172
cp_free(&private->cp);
154173
private->mdev = NULL;
155174
atomic_inc(&private->avail);
156-
157-
return 0;
158175
}
159176

160-
static int vfio_ccw_mdev_open_device(struct mdev_device *mdev)
177+
static int vfio_ccw_mdev_open_device(struct vfio_device *vdev)
161178
{
162179
struct vfio_ccw_private *private =
163-
dev_get_drvdata(mdev_parent_dev(mdev));
180+
container_of(vdev, struct vfio_ccw_private, vdev);
164181
unsigned long events = VFIO_IOMMU_NOTIFY_DMA_UNMAP;
165182
int ret;
166183

167184
private->nb.notifier_call = vfio_ccw_mdev_notifier;
168185

169-
ret = vfio_register_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,
186+
ret = vfio_register_notifier(vdev->dev, VFIO_IOMMU_NOTIFY,
170187
&events, &private->nb);
171188
if (ret)
172189
return ret;
@@ -187,15 +204,15 @@ static int vfio_ccw_mdev_open_device(struct mdev_device *mdev)
187204

188205
out_unregister:
189206
vfio_ccw_unregister_dev_regions(private);
190-
vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,
207+
vfio_unregister_notifier(vdev->dev, VFIO_IOMMU_NOTIFY,
191208
&private->nb);
192209
return ret;
193210
}
194211

195-
static void vfio_ccw_mdev_close_device(struct mdev_device *mdev)
212+
static void vfio_ccw_mdev_close_device(struct vfio_device *vdev)
196213
{
197214
struct vfio_ccw_private *private =
198-
dev_get_drvdata(mdev_parent_dev(mdev));
215+
container_of(vdev, struct vfio_ccw_private, vdev);
199216

200217
if ((private->state != VFIO_CCW_STATE_NOT_OPER) &&
201218
(private->state != VFIO_CCW_STATE_STANDBY)) {
@@ -206,8 +223,7 @@ static void vfio_ccw_mdev_close_device(struct mdev_device *mdev)
206223

207224
cp_free(&private->cp);
208225
vfio_ccw_unregister_dev_regions(private);
209-
vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,
210-
&private->nb);
226+
vfio_unregister_notifier(vdev->dev, VFIO_IOMMU_NOTIFY, &private->nb);
211227
}
212228

213229
static ssize_t vfio_ccw_mdev_read_io_region(struct vfio_ccw_private *private,
@@ -231,15 +247,14 @@ static ssize_t vfio_ccw_mdev_read_io_region(struct vfio_ccw_private *private,
231247
return ret;
232248
}
233249

234-
static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev,
250+
static ssize_t vfio_ccw_mdev_read(struct vfio_device *vdev,
235251
char __user *buf,
236252
size_t count,
237253
loff_t *ppos)
238254
{
255+
struct vfio_ccw_private *private =
256+
container_of(vdev, struct vfio_ccw_private, vdev);
239257
unsigned int index = VFIO_CCW_OFFSET_TO_INDEX(*ppos);
240-
struct vfio_ccw_private *private;
241-
242-
private = dev_get_drvdata(mdev_parent_dev(mdev));
243258

244259
if (index >= VFIO_CCW_NUM_REGIONS + private->num_regions)
245260
return -EINVAL;
@@ -284,15 +299,14 @@ static ssize_t vfio_ccw_mdev_write_io_region(struct vfio_ccw_private *private,
284299
return ret;
285300
}
286301

287-
static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev,
302+
static ssize_t vfio_ccw_mdev_write(struct vfio_device *vdev,
288303
const char __user *buf,
289304
size_t count,
290305
loff_t *ppos)
291306
{
307+
struct vfio_ccw_private *private =
308+
container_of(vdev, struct vfio_ccw_private, vdev);
292309
unsigned int index = VFIO_CCW_OFFSET_TO_INDEX(*ppos);
293-
struct vfio_ccw_private *private;
294-
295-
private = dev_get_drvdata(mdev_parent_dev(mdev));
296310

297311
if (index >= VFIO_CCW_NUM_REGIONS + private->num_regions)
298312
return -EINVAL;
@@ -510,12 +524,12 @@ void vfio_ccw_unregister_dev_regions(struct vfio_ccw_private *private)
510524
private->region = NULL;
511525
}
512526

513-
static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev,
527+
static ssize_t vfio_ccw_mdev_ioctl(struct vfio_device *vdev,
514528
unsigned int cmd,
515529
unsigned long arg)
516530
{
517531
struct vfio_ccw_private *private =
518-
dev_get_drvdata(mdev_parent_dev(mdev));
532+
container_of(vdev, struct vfio_ccw_private, vdev);
519533
int ret = 0;
520534
unsigned long minsz;
521535

@@ -606,37 +620,48 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev,
606620
}
607621

608622
/* Request removal of the device*/
609-
static void vfio_ccw_mdev_request(struct mdev_device *mdev, unsigned int count)
623+
static void vfio_ccw_mdev_request(struct vfio_device *vdev, unsigned int count)
610624
{
611-
struct vfio_ccw_private *private = dev_get_drvdata(mdev_parent_dev(mdev));
612-
613-
if (!private)
614-
return;
625+
struct vfio_ccw_private *private =
626+
container_of(vdev, struct vfio_ccw_private, vdev);
627+
struct device *dev = vdev->dev;
615628

616629
if (private->req_trigger) {
617630
if (!(count % 10))
618-
dev_notice_ratelimited(mdev_dev(private->mdev),
631+
dev_notice_ratelimited(dev,
619632
"Relaying device request to user (#%u)\n",
620633
count);
621634

622635
eventfd_signal(private->req_trigger, 1);
623636
} else if (count == 0) {
624-
dev_notice(mdev_dev(private->mdev),
637+
dev_notice(dev,
625638
"No device request channel registered, blocked until released by user\n");
626639
}
627640
}
628641

642+
static const struct vfio_device_ops vfio_ccw_dev_ops = {
643+
.open_device = vfio_ccw_mdev_open_device,
644+
.close_device = vfio_ccw_mdev_close_device,
645+
.read = vfio_ccw_mdev_read,
646+
.write = vfio_ccw_mdev_write,
647+
.ioctl = vfio_ccw_mdev_ioctl,
648+
.request = vfio_ccw_mdev_request,
649+
};
650+
651+
struct mdev_driver vfio_ccw_mdev_driver = {
652+
.driver = {
653+
.name = "vfio_ccw_mdev",
654+
.owner = THIS_MODULE,
655+
.mod_name = KBUILD_MODNAME,
656+
},
657+
.probe = vfio_ccw_mdev_probe,
658+
.remove = vfio_ccw_mdev_remove,
659+
};
660+
629661
static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
630662
.owner = THIS_MODULE,
663+
.device_driver = &vfio_ccw_mdev_driver,
631664
.supported_type_groups = mdev_type_groups,
632-
.create = vfio_ccw_mdev_create,
633-
.remove = vfio_ccw_mdev_remove,
634-
.open_device = vfio_ccw_mdev_open_device,
635-
.close_device = vfio_ccw_mdev_close_device,
636-
.read = vfio_ccw_mdev_read,
637-
.write = vfio_ccw_mdev_write,
638-
.ioctl = vfio_ccw_mdev_ioctl,
639-
.request = vfio_ccw_mdev_request,
640665
};
641666

642667
int vfio_ccw_mdev_reg(struct subchannel *sch)

drivers/s390/cio/vfio_ccw_private.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/eventfd.h>
1818
#include <linux/workqueue.h>
1919
#include <linux/vfio_ccw.h>
20+
#include <linux/vfio.h>
2021
#include <asm/crw.h>
2122
#include <asm/debug.h>
2223

@@ -67,6 +68,7 @@ struct vfio_ccw_crw {
6768

6869
/**
6970
* struct vfio_ccw_private
71+
* @vdev: Embedded VFIO device
7072
* @sch: pointer to the subchannel
7173
* @state: internal state of the device
7274
* @completion: synchronization helper of the I/O completion
@@ -90,6 +92,7 @@ struct vfio_ccw_crw {
9092
* @crw_work: work for deferral process of CRW handling
9193
*/
9294
struct vfio_ccw_private {
95+
struct vfio_device vdev;
9396
struct subchannel *sch;
9497
int state;
9598
struct completion *completion;
@@ -121,6 +124,8 @@ extern void vfio_ccw_mdev_unreg(struct subchannel *sch);
121124

122125
extern int vfio_ccw_sch_quiesce(struct subchannel *sch);
123126

127+
extern struct mdev_driver vfio_ccw_mdev_driver;
128+
124129
/*
125130
* States of the device statemachine.
126131
*/

0 commit comments

Comments
 (0)