10
10
*/
11
11
12
12
#include <linux/vfio.h>
13
- #include <linux/mdev.h>
13
+
14
+ #include <asm/isc.h>
14
15
15
16
#include "ioasm.h"
16
17
#include "vfio_ccw_private.h"
@@ -161,15 +162,22 @@ static void fsm_notoper(struct vfio_ccw_private *private,
161
162
{
162
163
struct subchannel * sch = private -> sch ;
163
164
164
- VFIO_CCW_TRACE_EVENT (2 , "notoper" );
165
- VFIO_CCW_TRACE_EVENT (2 , dev_name (& sch -> dev ));
165
+ VFIO_CCW_MSG_EVENT (2 , "sch %x.%x.%04x: notoper event %x state %x\n" ,
166
+ sch -> schid .cssid ,
167
+ sch -> schid .ssid ,
168
+ sch -> schid .sch_no ,
169
+ event ,
170
+ private -> state );
166
171
167
172
/*
168
173
* TODO:
169
174
* Probably we should send the machine check to the guest.
170
175
*/
171
176
css_sched_sch_todo (sch , SCH_TODO_UNREG );
172
177
private -> state = VFIO_CCW_STATE_NOT_OPER ;
178
+
179
+ /* This is usually handled during CLOSE event */
180
+ cp_free (& private -> cp );
173
181
}
174
182
175
183
/*
@@ -242,7 +250,6 @@ static void fsm_io_request(struct vfio_ccw_private *private,
242
250
union orb * orb ;
243
251
union scsw * scsw = & private -> scsw ;
244
252
struct ccw_io_region * io_region = private -> io_region ;
245
- struct mdev_device * mdev = private -> mdev ;
246
253
char * errstr = "request" ;
247
254
struct subchannel_id schid = get_schid (private );
248
255
@@ -256,17 +263,17 @@ static void fsm_io_request(struct vfio_ccw_private *private,
256
263
if (orb -> tm .b ) {
257
264
io_region -> ret_code = - EOPNOTSUPP ;
258
265
VFIO_CCW_MSG_EVENT (2 ,
259
- "%pUl ( %x.%x.%04x) : transport mode\n" ,
260
- mdev_uuid ( mdev ), schid .cssid ,
266
+ "sch %x.%x.%04x: transport mode\n" ,
267
+ schid .cssid ,
261
268
schid .ssid , schid .sch_no );
262
269
errstr = "transport mode" ;
263
270
goto err_out ;
264
271
}
265
272
io_region -> ret_code = cp_init (& private -> cp , orb );
266
273
if (io_region -> ret_code ) {
267
274
VFIO_CCW_MSG_EVENT (2 ,
268
- "%pUl ( %x.%x.%04x) : cp_init=%d\n" ,
269
- mdev_uuid ( mdev ), schid .cssid ,
275
+ "sch %x.%x.%04x: cp_init=%d\n" ,
276
+ schid .cssid ,
270
277
schid .ssid , schid .sch_no ,
271
278
io_region -> ret_code );
272
279
errstr = "cp init" ;
@@ -276,8 +283,8 @@ static void fsm_io_request(struct vfio_ccw_private *private,
276
283
io_region -> ret_code = cp_prefetch (& private -> cp );
277
284
if (io_region -> ret_code ) {
278
285
VFIO_CCW_MSG_EVENT (2 ,
279
- "%pUl ( %x.%x.%04x) : cp_prefetch=%d\n" ,
280
- mdev_uuid ( mdev ), schid .cssid ,
286
+ "sch %x.%x.%04x: cp_prefetch=%d\n" ,
287
+ schid .cssid ,
281
288
schid .ssid , schid .sch_no ,
282
289
io_region -> ret_code );
283
290
errstr = "cp prefetch" ;
@@ -289,8 +296,8 @@ static void fsm_io_request(struct vfio_ccw_private *private,
289
296
io_region -> ret_code = fsm_io_helper (private );
290
297
if (io_region -> ret_code ) {
291
298
VFIO_CCW_MSG_EVENT (2 ,
292
- "%pUl ( %x.%x.%04x) : fsm_io_helper=%d\n" ,
293
- mdev_uuid ( mdev ), schid .cssid ,
299
+ "sch %x.%x.%04x: fsm_io_helper=%d\n" ,
300
+ schid .cssid ,
294
301
schid .ssid , schid .sch_no ,
295
302
io_region -> ret_code );
296
303
errstr = "cp fsm_io_helper" ;
@@ -300,16 +307,16 @@ static void fsm_io_request(struct vfio_ccw_private *private,
300
307
return ;
301
308
} else if (scsw -> cmd .fctl & SCSW_FCTL_HALT_FUNC ) {
302
309
VFIO_CCW_MSG_EVENT (2 ,
303
- "%pUl ( %x.%x.%04x) : halt on io_region\n" ,
304
- mdev_uuid ( mdev ), schid .cssid ,
310
+ "sch %x.%x.%04x: halt on io_region\n" ,
311
+ schid .cssid ,
305
312
schid .ssid , schid .sch_no );
306
313
/* halt is handled via the async cmd region */
307
314
io_region -> ret_code = - EOPNOTSUPP ;
308
315
goto err_out ;
309
316
} else if (scsw -> cmd .fctl & SCSW_FCTL_CLEAR_FUNC ) {
310
317
VFIO_CCW_MSG_EVENT (2 ,
311
- "%pUl ( %x.%x.%04x) : clear on io_region\n" ,
312
- mdev_uuid ( mdev ), schid .cssid ,
318
+ "sch %x.%x.%04x: clear on io_region\n" ,
319
+ schid .cssid ,
313
320
schid .ssid , schid .sch_no );
314
321
/* clear is handled via the async cmd region */
315
322
io_region -> ret_code = - EOPNOTSUPP ;
@@ -366,6 +373,54 @@ static void fsm_irq(struct vfio_ccw_private *private,
366
373
complete (private -> completion );
367
374
}
368
375
376
+ static void fsm_open (struct vfio_ccw_private * private ,
377
+ enum vfio_ccw_event event )
378
+ {
379
+ struct subchannel * sch = private -> sch ;
380
+ int ret ;
381
+
382
+ spin_lock_irq (sch -> lock );
383
+ sch -> isc = VFIO_CCW_ISC ;
384
+ ret = cio_enable_subchannel (sch , (u32 )(unsigned long )sch );
385
+ if (ret )
386
+ goto err_unlock ;
387
+
388
+ private -> state = VFIO_CCW_STATE_IDLE ;
389
+ spin_unlock_irq (sch -> lock );
390
+ return ;
391
+
392
+ err_unlock :
393
+ spin_unlock_irq (sch -> lock );
394
+ vfio_ccw_fsm_event (private , VFIO_CCW_EVENT_NOT_OPER );
395
+ }
396
+
397
+ static void fsm_close (struct vfio_ccw_private * private ,
398
+ enum vfio_ccw_event event )
399
+ {
400
+ struct subchannel * sch = private -> sch ;
401
+ int ret ;
402
+
403
+ spin_lock_irq (sch -> lock );
404
+
405
+ if (!sch -> schib .pmcw .ena )
406
+ goto err_unlock ;
407
+
408
+ ret = cio_disable_subchannel (sch );
409
+ if (ret == - EBUSY )
410
+ vfio_ccw_sch_quiesce (sch );
411
+ if (ret )
412
+ goto err_unlock ;
413
+
414
+ private -> state = VFIO_CCW_STATE_STANDBY ;
415
+ spin_unlock_irq (sch -> lock );
416
+ cp_free (& private -> cp );
417
+ return ;
418
+
419
+ err_unlock :
420
+ spin_unlock_irq (sch -> lock );
421
+ vfio_ccw_fsm_event (private , VFIO_CCW_EVENT_NOT_OPER );
422
+ }
423
+
369
424
/*
370
425
* Device statemachine
371
426
*/
@@ -375,29 +430,39 @@ fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS] = {
375
430
[VFIO_CCW_EVENT_IO_REQ ] = fsm_io_error ,
376
431
[VFIO_CCW_EVENT_ASYNC_REQ ] = fsm_async_error ,
377
432
[VFIO_CCW_EVENT_INTERRUPT ] = fsm_disabled_irq ,
433
+ [VFIO_CCW_EVENT_OPEN ] = fsm_nop ,
434
+ [VFIO_CCW_EVENT_CLOSE ] = fsm_nop ,
378
435
},
379
436
[VFIO_CCW_STATE_STANDBY ] = {
380
437
[VFIO_CCW_EVENT_NOT_OPER ] = fsm_notoper ,
381
438
[VFIO_CCW_EVENT_IO_REQ ] = fsm_io_error ,
382
439
[VFIO_CCW_EVENT_ASYNC_REQ ] = fsm_async_error ,
383
- [VFIO_CCW_EVENT_INTERRUPT ] = fsm_irq ,
440
+ [VFIO_CCW_EVENT_INTERRUPT ] = fsm_disabled_irq ,
441
+ [VFIO_CCW_EVENT_OPEN ] = fsm_open ,
442
+ [VFIO_CCW_EVENT_CLOSE ] = fsm_notoper ,
384
443
},
385
444
[VFIO_CCW_STATE_IDLE ] = {
386
445
[VFIO_CCW_EVENT_NOT_OPER ] = fsm_notoper ,
387
446
[VFIO_CCW_EVENT_IO_REQ ] = fsm_io_request ,
388
447
[VFIO_CCW_EVENT_ASYNC_REQ ] = fsm_async_request ,
389
448
[VFIO_CCW_EVENT_INTERRUPT ] = fsm_irq ,
449
+ [VFIO_CCW_EVENT_OPEN ] = fsm_notoper ,
450
+ [VFIO_CCW_EVENT_CLOSE ] = fsm_close ,
390
451
},
391
452
[VFIO_CCW_STATE_CP_PROCESSING ] = {
392
453
[VFIO_CCW_EVENT_NOT_OPER ] = fsm_notoper ,
393
454
[VFIO_CCW_EVENT_IO_REQ ] = fsm_io_retry ,
394
455
[VFIO_CCW_EVENT_ASYNC_REQ ] = fsm_async_retry ,
395
456
[VFIO_CCW_EVENT_INTERRUPT ] = fsm_irq ,
457
+ [VFIO_CCW_EVENT_OPEN ] = fsm_notoper ,
458
+ [VFIO_CCW_EVENT_CLOSE ] = fsm_close ,
396
459
},
397
460
[VFIO_CCW_STATE_CP_PENDING ] = {
398
461
[VFIO_CCW_EVENT_NOT_OPER ] = fsm_notoper ,
399
462
[VFIO_CCW_EVENT_IO_REQ ] = fsm_io_busy ,
400
463
[VFIO_CCW_EVENT_ASYNC_REQ ] = fsm_async_request ,
401
464
[VFIO_CCW_EVENT_INTERRUPT ] = fsm_irq ,
465
+ [VFIO_CCW_EVENT_OPEN ] = fsm_notoper ,
466
+ [VFIO_CCW_EVENT_CLOSE ] = fsm_close ,
402
467
},
403
468
};
0 commit comments