vfio/ccw: Create an OPEN FSM Event
authorEric Farman <farman@linux.ibm.com>
Thu, 7 Jul 2022 13:57:34 +0000 (15:57 +0200)
committerAlex Williamson <alex.williamson@redhat.com>
Thu, 7 Jul 2022 20:06:12 +0000 (14:06 -0600)
Move the process of enabling a subchannel for use by vfio-ccw
into the FSM, such that it can manage the sequence of lifecycle
events for the device.

That is, if the FSM state is NOT_OPER(erational), then do the work
that would enable the subchannel and move the FSM to STANDBY state.
An attempt to perform this event again from any of the other operating
states (IDLE, CP_PROCESSING, CP_PENDING) will convert the device back
to NOT_OPER so the configuration process can be started again.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
Link: https://lore.kernel.org/r/20220707135737.720765-9-farman@linux.ibm.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
drivers/s390/cio/vfio_ccw_drv.c
drivers/s390/cio/vfio_ccw_fsm.c
drivers/s390/cio/vfio_ccw_private.h

index fe87a2652a2225f1ea649686ddac4ccc9417e75f..7d9189640da3aa858c5ddc3cb91382adc7075196 100644 (file)
@@ -231,15 +231,10 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
 
        dev_set_drvdata(&sch->dev, private);
 
-       spin_lock_irq(sch->lock);
-       sch->isc = VFIO_CCW_ISC;
-       ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
-       spin_unlock_irq(sch->lock);
-       if (ret)
+       vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_OPEN);
+       if (private->state == VFIO_CCW_STATE_NOT_OPER)
                goto out_free;
 
-       private->state = VFIO_CCW_STATE_STANDBY;
-
        ret = mdev_register_device(&sch->dev, &vfio_ccw_mdev_driver);
        if (ret)
                goto out_disable;
index 88e529a2e184820326f19e8135d78f57d5d69d6e..2811b20404909960fa5ea669c26da8384b7ac298 100644 (file)
@@ -11,6 +11,8 @@
 
 #include <linux/vfio.h>
 
+#include <asm/isc.h>
+
 #include "ioasm.h"
 #include "vfio_ccw_private.h"
 
@@ -368,6 +370,20 @@ static void fsm_irq(struct vfio_ccw_private *private,
                complete(private->completion);
 }
 
+static void fsm_open(struct vfio_ccw_private *private,
+                    enum vfio_ccw_event event)
+{
+       struct subchannel *sch = private->sch;
+       int ret;
+
+       spin_lock_irq(sch->lock);
+       sch->isc = VFIO_CCW_ISC;
+       ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
+       if (!ret)
+               private->state = VFIO_CCW_STATE_STANDBY;
+       spin_unlock_irq(sch->lock);
+}
+
 /*
  * Device statemachine
  */
@@ -377,29 +393,34 @@ fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS] = {
                [VFIO_CCW_EVENT_IO_REQ]         = fsm_io_error,
                [VFIO_CCW_EVENT_ASYNC_REQ]      = fsm_async_error,
                [VFIO_CCW_EVENT_INTERRUPT]      = fsm_disabled_irq,
+               [VFIO_CCW_EVENT_OPEN]           = fsm_open,
        },
        [VFIO_CCW_STATE_STANDBY] = {
                [VFIO_CCW_EVENT_NOT_OPER]       = fsm_notoper,
                [VFIO_CCW_EVENT_IO_REQ]         = fsm_io_error,
                [VFIO_CCW_EVENT_ASYNC_REQ]      = fsm_async_error,
                [VFIO_CCW_EVENT_INTERRUPT]      = fsm_irq,
+               [VFIO_CCW_EVENT_OPEN]           = fsm_notoper,
        },
        [VFIO_CCW_STATE_IDLE] = {
                [VFIO_CCW_EVENT_NOT_OPER]       = fsm_notoper,
                [VFIO_CCW_EVENT_IO_REQ]         = fsm_io_request,
                [VFIO_CCW_EVENT_ASYNC_REQ]      = fsm_async_request,
                [VFIO_CCW_EVENT_INTERRUPT]      = fsm_irq,
+               [VFIO_CCW_EVENT_OPEN]           = fsm_notoper,
        },
        [VFIO_CCW_STATE_CP_PROCESSING] = {
                [VFIO_CCW_EVENT_NOT_OPER]       = fsm_notoper,
                [VFIO_CCW_EVENT_IO_REQ]         = fsm_io_retry,
                [VFIO_CCW_EVENT_ASYNC_REQ]      = fsm_async_retry,
                [VFIO_CCW_EVENT_INTERRUPT]      = fsm_irq,
+               [VFIO_CCW_EVENT_OPEN]           = fsm_notoper,
        },
        [VFIO_CCW_STATE_CP_PENDING] = {
                [VFIO_CCW_EVENT_NOT_OPER]       = fsm_notoper,
                [VFIO_CCW_EVENT_IO_REQ]         = fsm_io_busy,
                [VFIO_CCW_EVENT_ASYNC_REQ]      = fsm_async_request,
                [VFIO_CCW_EVENT_INTERRUPT]      = fsm_irq,
+               [VFIO_CCW_EVENT_OPEN]           = fsm_notoper,
        },
 };
index a2584c130e79d21693c9b3943244668d32905ff4..93e136ba369b6be8aac3a27402a1d4090cb83897 100644 (file)
@@ -142,6 +142,7 @@ enum vfio_ccw_event {
        VFIO_CCW_EVENT_IO_REQ,
        VFIO_CCW_EVENT_INTERRUPT,
        VFIO_CCW_EVENT_ASYNC_REQ,
+       VFIO_CCW_EVENT_OPEN,
        /* last element! */
        NR_VFIO_CCW_EVENTS
 };