1010 */
1111
1212#include <linux/vfio.h>
13- #include <linux/mdev.h>
13+
14+ #include <asm/isc.h>
1415
1516#include "ioasm.h"
1617#include "vfio_ccw_private.h"
@@ -161,15 +162,22 @@ static void fsm_notoper(struct vfio_ccw_private *private,
161162{
162163 struct subchannel * sch = private -> sch ;
163164
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 );
166171
167172 /*
168173 * TODO:
169174 * Probably we should send the machine check to the guest.
170175 */
171176 css_sched_sch_todo (sch , SCH_TODO_UNREG );
172177 private -> state = VFIO_CCW_STATE_NOT_OPER ;
178+
179+ /* This is usually handled during CLOSE event */
180+ cp_free (& private -> cp );
173181}
174182
175183/*
@@ -242,7 +250,6 @@ static void fsm_io_request(struct vfio_ccw_private *private,
242250 union orb * orb ;
243251 union scsw * scsw = & private -> scsw ;
244252 struct ccw_io_region * io_region = private -> io_region ;
245- struct mdev_device * mdev = private -> mdev ;
246253 char * errstr = "request" ;
247254 struct subchannel_id schid = get_schid (private );
248255
@@ -256,17 +263,17 @@ static void fsm_io_request(struct vfio_ccw_private *private,
256263 if (orb -> tm .b ) {
257264 io_region -> ret_code = - EOPNOTSUPP ;
258265 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 ,
261268 schid .ssid , schid .sch_no );
262269 errstr = "transport mode" ;
263270 goto err_out ;
264271 }
265272 io_region -> ret_code = cp_init (& private -> cp , orb );
266273 if (io_region -> ret_code ) {
267274 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 ,
270277 schid .ssid , schid .sch_no ,
271278 io_region -> ret_code );
272279 errstr = "cp init" ;
@@ -276,8 +283,8 @@ static void fsm_io_request(struct vfio_ccw_private *private,
276283 io_region -> ret_code = cp_prefetch (& private -> cp );
277284 if (io_region -> ret_code ) {
278285 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 ,
281288 schid .ssid , schid .sch_no ,
282289 io_region -> ret_code );
283290 errstr = "cp prefetch" ;
@@ -289,8 +296,8 @@ static void fsm_io_request(struct vfio_ccw_private *private,
289296 io_region -> ret_code = fsm_io_helper (private );
290297 if (io_region -> ret_code ) {
291298 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 ,
294301 schid .ssid , schid .sch_no ,
295302 io_region -> ret_code );
296303 errstr = "cp fsm_io_helper" ;
@@ -300,16 +307,16 @@ static void fsm_io_request(struct vfio_ccw_private *private,
300307 return ;
301308 } else if (scsw -> cmd .fctl & SCSW_FCTL_HALT_FUNC ) {
302309 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 ,
305312 schid .ssid , schid .sch_no );
306313 /* halt is handled via the async cmd region */
307314 io_region -> ret_code = - EOPNOTSUPP ;
308315 goto err_out ;
309316 } else if (scsw -> cmd .fctl & SCSW_FCTL_CLEAR_FUNC ) {
310317 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 ,
313320 schid .ssid , schid .sch_no );
314321 /* clear is handled via the async cmd region */
315322 io_region -> ret_code = - EOPNOTSUPP ;
@@ -366,6 +373,54 @@ static void fsm_irq(struct vfio_ccw_private *private,
366373 complete (private -> completion );
367374}
368375
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+
369424/*
370425 * Device statemachine
371426 */
@@ -375,29 +430,39 @@ fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS] = {
375430 [VFIO_CCW_EVENT_IO_REQ ] = fsm_io_error ,
376431 [VFIO_CCW_EVENT_ASYNC_REQ ] = fsm_async_error ,
377432 [VFIO_CCW_EVENT_INTERRUPT ] = fsm_disabled_irq ,
433+ [VFIO_CCW_EVENT_OPEN ] = fsm_nop ,
434+ [VFIO_CCW_EVENT_CLOSE ] = fsm_nop ,
378435 },
379436 [VFIO_CCW_STATE_STANDBY ] = {
380437 [VFIO_CCW_EVENT_NOT_OPER ] = fsm_notoper ,
381438 [VFIO_CCW_EVENT_IO_REQ ] = fsm_io_error ,
382439 [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 ,
384443 },
385444 [VFIO_CCW_STATE_IDLE ] = {
386445 [VFIO_CCW_EVENT_NOT_OPER ] = fsm_notoper ,
387446 [VFIO_CCW_EVENT_IO_REQ ] = fsm_io_request ,
388447 [VFIO_CCW_EVENT_ASYNC_REQ ] = fsm_async_request ,
389448 [VFIO_CCW_EVENT_INTERRUPT ] = fsm_irq ,
449+ [VFIO_CCW_EVENT_OPEN ] = fsm_notoper ,
450+ [VFIO_CCW_EVENT_CLOSE ] = fsm_close ,
390451 },
391452 [VFIO_CCW_STATE_CP_PROCESSING ] = {
392453 [VFIO_CCW_EVENT_NOT_OPER ] = fsm_notoper ,
393454 [VFIO_CCW_EVENT_IO_REQ ] = fsm_io_retry ,
394455 [VFIO_CCW_EVENT_ASYNC_REQ ] = fsm_async_retry ,
395456 [VFIO_CCW_EVENT_INTERRUPT ] = fsm_irq ,
457+ [VFIO_CCW_EVENT_OPEN ] = fsm_notoper ,
458+ [VFIO_CCW_EVENT_CLOSE ] = fsm_close ,
396459 },
397460 [VFIO_CCW_STATE_CP_PENDING ] = {
398461 [VFIO_CCW_EVENT_NOT_OPER ] = fsm_notoper ,
399462 [VFIO_CCW_EVENT_IO_REQ ] = fsm_io_busy ,
400463 [VFIO_CCW_EVENT_ASYNC_REQ ] = fsm_async_request ,
401464 [VFIO_CCW_EVENT_INTERRUPT ] = fsm_irq ,
465+ [VFIO_CCW_EVENT_OPEN ] = fsm_notoper ,
466+ [VFIO_CCW_EVENT_CLOSE ] = fsm_close ,
402467 },
403468};
0 commit comments