Skip to content

Commit 9e6f07c

Browse files
efarmanAlex Williamson
authored andcommitted
vfio/ccw: create a parent struct
Move the stuff associated with the mdev parent (and thus the subchannel struct) into its own struct, and leave the rest in the existing private structure. The subchannel will point to the parent, and the parent will point to the private, for the areas where one or both are needed. Further separation of these structs will follow. Signed-off-by: Eric Farman <farman@linux.ibm.com> Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com> Link: https://lore.kernel.org/r/20221104142007.1314999-2-farman@linux.ibm.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
1 parent f38044e commit 9e6f07c

File tree

3 files changed

+101
-25
lines changed

3 files changed

+101
-25
lines changed

drivers/s390/cio/vfio_ccw_drv.c

Lines changed: 80 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,19 @@ debug_info_t *vfio_ccw_debug_trace_id;
3636
*/
3737
int vfio_ccw_sch_quiesce(struct subchannel *sch)
3838
{
39-
struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
39+
struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev);
40+
struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev);
4041
DECLARE_COMPLETION_ONSTACK(completion);
4142
int iretry, ret = 0;
4243

44+
/*
45+
* Probably an impossible situation, after being called through
46+
* FSM callbacks. But in the event it did, register a warning
47+
* and return as if things were fine.
48+
*/
49+
if (WARN_ON(!private))
50+
return 0;
51+
4352
iretry = 255;
4453
do {
4554

@@ -121,7 +130,23 @@ static void vfio_ccw_crw_todo(struct work_struct *work)
121130
*/
122131
static void vfio_ccw_sch_irq(struct subchannel *sch)
123132
{
124-
struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
133+
struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev);
134+
struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev);
135+
136+
/*
137+
* The subchannel should still be disabled at this point,
138+
* so an interrupt would be quite surprising. As with an
139+
* interrupt while the FSM is closed, let's attempt to
140+
* disable the subchannel again.
141+
*/
142+
if (!private) {
143+
VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: unexpected interrupt\n",
144+
sch->schid.cssid, sch->schid.ssid,
145+
sch->schid.sch_no);
146+
147+
cio_disable_subchannel(sch);
148+
return;
149+
}
125150

126151
inc_irq_stat(IRQIO_CIO);
127152
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT);
@@ -201,10 +226,19 @@ static void vfio_ccw_free_private(struct vfio_ccw_private *private)
201226
mutex_destroy(&private->io_mutex);
202227
kfree(private);
203228
}
229+
230+
static void vfio_ccw_free_parent(struct device *dev)
231+
{
232+
struct vfio_ccw_parent *parent = container_of(dev, struct vfio_ccw_parent, dev);
233+
234+
kfree(parent);
235+
}
236+
204237
static int vfio_ccw_sch_probe(struct subchannel *sch)
205238
{
206239
struct pmcw *pmcw = &sch->schib.pmcw;
207240
struct vfio_ccw_private *private;
241+
struct vfio_ccw_parent *parent;
208242
int ret = -ENOMEM;
209243

210244
if (pmcw->qf) {
@@ -213,38 +247,58 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
213247
return -ENODEV;
214248
}
215249

250+
parent = kzalloc(sizeof(*parent), GFP_KERNEL);
251+
if (!parent)
252+
return -ENOMEM;
253+
254+
dev_set_name(&parent->dev, "parent");
255+
parent->dev.parent = &sch->dev;
256+
parent->dev.release = &vfio_ccw_free_parent;
257+
ret = device_register(&parent->dev);
258+
if (ret)
259+
goto out_free;
260+
216261
private = vfio_ccw_alloc_private(sch);
217-
if (IS_ERR(private))
262+
if (IS_ERR(private)) {
263+
device_unregister(&parent->dev);
218264
return PTR_ERR(private);
265+
}
219266

220-
dev_set_drvdata(&sch->dev, private);
267+
dev_set_drvdata(&sch->dev, parent);
268+
dev_set_drvdata(&parent->dev, private);
221269

222-
private->mdev_type.sysfs_name = "io";
223-
private->mdev_type.pretty_name = "I/O subchannel (Non-QDIO)";
224-
private->mdev_types[0] = &private->mdev_type;
225-
ret = mdev_register_parent(&private->parent, &sch->dev,
270+
parent->mdev_type.sysfs_name = "io";
271+
parent->mdev_type.pretty_name = "I/O subchannel (Non-QDIO)";
272+
parent->mdev_types[0] = &parent->mdev_type;
273+
ret = mdev_register_parent(&parent->parent, &sch->dev,
226274
&vfio_ccw_mdev_driver,
227-
private->mdev_types, 1);
275+
parent->mdev_types, 1);
228276
if (ret)
229-
goto out_free;
277+
goto out_unreg;
230278

231279
VFIO_CCW_MSG_EVENT(4, "bound to subchannel %x.%x.%04x\n",
232280
sch->schid.cssid, sch->schid.ssid,
233281
sch->schid.sch_no);
234282
return 0;
235283

284+
out_unreg:
285+
device_unregister(&parent->dev);
236286
out_free:
287+
dev_set_drvdata(&parent->dev, NULL);
237288
dev_set_drvdata(&sch->dev, NULL);
238-
vfio_ccw_free_private(private);
289+
if (private)
290+
vfio_ccw_free_private(private);
239291
return ret;
240292
}
241293

242294
static void vfio_ccw_sch_remove(struct subchannel *sch)
243295
{
244-
struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
296+
struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev);
297+
struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev);
245298

246-
mdev_unregister_parent(&private->parent);
299+
mdev_unregister_parent(&parent->parent);
247300

301+
device_unregister(&parent->dev);
248302
dev_set_drvdata(&sch->dev, NULL);
249303

250304
vfio_ccw_free_private(private);
@@ -256,7 +310,11 @@ static void vfio_ccw_sch_remove(struct subchannel *sch)
256310

257311
static void vfio_ccw_sch_shutdown(struct subchannel *sch)
258312
{
259-
struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
313+
struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev);
314+
struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev);
315+
316+
if (WARN_ON(!private))
317+
return;
260318

261319
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_CLOSE);
262320
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
@@ -274,7 +332,8 @@ static void vfio_ccw_sch_shutdown(struct subchannel *sch)
274332
*/
275333
static int vfio_ccw_sch_event(struct subchannel *sch, int process)
276334
{
277-
struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
335+
struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev);
336+
struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev);
278337
unsigned long flags;
279338
int rc = -EAGAIN;
280339

@@ -287,8 +346,10 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process)
287346

288347
rc = 0;
289348

290-
if (cio_update_schib(sch))
291-
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
349+
if (cio_update_schib(sch)) {
350+
if (private)
351+
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
352+
}
292353

293354
out_unlock:
294355
spin_unlock_irqrestore(sch->lock, flags);
@@ -326,7 +387,8 @@ static void vfio_ccw_queue_crw(struct vfio_ccw_private *private,
326387
static int vfio_ccw_chp_event(struct subchannel *sch,
327388
struct chp_link *link, int event)
328389
{
329-
struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
390+
struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev);
391+
struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev);
330392
int mask = chp_ssd_get_mask(&sch->ssd_info, link);
331393
int retry = 255;
332394

drivers/s390/cio/vfio_ccw_ops.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
5555

5656
static int vfio_ccw_mdev_probe(struct mdev_device *mdev)
5757
{
58-
struct vfio_ccw_private *private = dev_get_drvdata(mdev->dev.parent);
58+
struct subchannel *sch = to_subchannel(mdev->dev.parent);
59+
struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev);
60+
struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev);
5961
int ret;
6062

6163
if (private->state == VFIO_CCW_STATE_NOT_OPER)
@@ -100,7 +102,9 @@ static void vfio_ccw_mdev_release_dev(struct vfio_device *vdev)
100102

101103
static void vfio_ccw_mdev_remove(struct mdev_device *mdev)
102104
{
103-
struct vfio_ccw_private *private = dev_get_drvdata(mdev->dev.parent);
105+
struct subchannel *sch = to_subchannel(mdev->dev.parent);
106+
struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev);
107+
struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev);
104108

105109
VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: remove\n",
106110
private->sch->schid.cssid,

drivers/s390/cio/vfio_ccw_private.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,21 @@ struct vfio_ccw_crw {
6767
struct crw crw;
6868
};
6969

70+
/**
71+
* struct vfio_ccw_parent
72+
*
73+
* @dev: embedded device struct
74+
* @parent: parent data structures for mdevs created
75+
* @mdev_type(s): identifying information for mdevs created
76+
*/
77+
struct vfio_ccw_parent {
78+
struct device dev;
79+
80+
struct mdev_parent parent;
81+
struct mdev_type mdev_type;
82+
struct mdev_type *mdev_types[1];
83+
};
84+
7085
/**
7186
* struct vfio_ccw_private
7287
* @vdev: Embedded VFIO device
@@ -89,7 +104,6 @@ struct vfio_ccw_crw {
89104
* @io_work: work for deferral process of I/O handling
90105
* @crw_work: work for deferral process of CRW handling
91106
* @release_comp: synchronization helper for vfio device release
92-
* @parent: parent data structures for mdevs created
93107
*/
94108
struct vfio_ccw_private {
95109
struct vfio_device vdev;
@@ -116,10 +130,6 @@ struct vfio_ccw_private {
116130
struct work_struct crw_work;
117131

118132
struct completion release_comp;
119-
120-
struct mdev_parent parent;
121-
struct mdev_type mdev_type;
122-
struct mdev_type *mdev_types[1];
123133
} __aligned(8);
124134

125135
int vfio_ccw_sch_quiesce(struct subchannel *sch);

0 commit comments

Comments
 (0)