vfio-ccw: Register a chp_event callback for vfio-ccw
authorFarhan Ali <alifm@linux.ibm.com>
Tue, 5 May 2020 12:27:39 +0000 (14:27 +0200)
committerCornelia Huck <cohuck@redhat.com>
Tue, 2 Jun 2020 11:14:08 +0000 (13:14 +0200)
Register the chp_event callback to receive channel path related
events for the subchannels managed by vfio-ccw.

Signed-off-by: Farhan Ali <alifm@linux.ibm.com>
Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20200505122745.53208-3-farman@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
drivers/s390/cio/vfio_ccw_drv.c

index 8715c1c2f1e1cd4dae28df859175d0b52b06806c..fb1275a7d1f5c3b3f7250cf7f99d7470baa0e3cd 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <asm/isc.h>
 
+#include "chp.h"
 #include "ioasm.h"
 #include "css.h"
 #include "vfio_ccw_private.h"
@@ -262,6 +263,51 @@ out_unlock:
        return rc;
 }
 
+static int vfio_ccw_chp_event(struct subchannel *sch,
+                             struct chp_link *link, int event)
+{
+       struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
+       int mask = chp_ssd_get_mask(&sch->ssd_info, link);
+       int retry = 255;
+
+       if (!private || !mask)
+               return 0;
+
+       VFIO_CCW_MSG_EVENT(2, "%pUl (%x.%x.%04x): mask=0x%x event=%d\n",
+                          mdev_uuid(private->mdev), sch->schid.cssid,
+                          sch->schid.ssid, sch->schid.sch_no,
+                          mask, event);
+
+       if (cio_update_schib(sch))
+               return -ENODEV;
+
+       switch (event) {
+       case CHP_VARY_OFF:
+               /* Path logically turned off */
+               sch->opm &= ~mask;
+               sch->lpm &= ~mask;
+               if (sch->schib.pmcw.lpum & mask)
+                       cio_cancel_halt_clear(sch, &retry);
+               break;
+       case CHP_OFFLINE:
+               /* Path is gone */
+               if (sch->schib.pmcw.lpum & mask)
+                       cio_cancel_halt_clear(sch, &retry);
+               break;
+       case CHP_VARY_ON:
+               /* Path logically turned on */
+               sch->opm |= mask;
+               sch->lpm |= mask;
+               break;
+       case CHP_ONLINE:
+               /* Path became available */
+               sch->lpm |= mask & sch->opm;
+               break;
+       }
+
+       return 0;
+}
+
 static struct css_device_id vfio_ccw_sch_ids[] = {
        { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, },
        { /* end of list */ },
@@ -279,6 +325,7 @@ static struct css_driver vfio_ccw_sch_driver = {
        .remove = vfio_ccw_sch_remove,
        .shutdown = vfio_ccw_sch_shutdown,
        .sch_event = vfio_ccw_sch_event,
+       .chp_event = vfio_ccw_chp_event,
 };
 
 static int __init vfio_ccw_debug_init(void)