11dcac3e1SXiao Feng Ren /* 21dcac3e1SXiao Feng Ren * vfio based subchannel assignment support 31dcac3e1SXiao Feng Ren * 41dcac3e1SXiao Feng Ren * Copyright 2017 IBM Corp. 51dcac3e1SXiao Feng Ren * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> 61dcac3e1SXiao Feng Ren * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com> 71dcac3e1SXiao Feng Ren * Pierre Morel <pmorel@linux.vnet.ibm.com> 81dcac3e1SXiao Feng Ren * 91dcac3e1SXiao Feng Ren * This work is licensed under the terms of the GNU GPL, version 2 or(at 101dcac3e1SXiao Feng Ren * your option) any version. See the COPYING file in the top-level 111dcac3e1SXiao Feng Ren * directory. 121dcac3e1SXiao Feng Ren */ 131dcac3e1SXiao Feng Ren 141dcac3e1SXiao Feng Ren #include <linux/vfio.h> 15c14e706cSDong Jia Shi #include <linux/vfio_ccw.h> 161dcac3e1SXiao Feng Ren #include <sys/ioctl.h> 171dcac3e1SXiao Feng Ren 181dcac3e1SXiao Feng Ren #include "qemu/osdep.h" 191dcac3e1SXiao Feng Ren #include "qapi/error.h" 201dcac3e1SXiao Feng Ren #include "hw/sysbus.h" 211dcac3e1SXiao Feng Ren #include "hw/vfio/vfio.h" 221dcac3e1SXiao Feng Ren #include "hw/vfio/vfio-common.h" 231dcac3e1SXiao Feng Ren #include "hw/s390x/s390-ccw.h" 241dcac3e1SXiao Feng Ren #include "hw/s390x/ccw-device.h" 25*4886b3e9SDong Jia Shi #include "qemu/error-report.h" 261dcac3e1SXiao Feng Ren 271dcac3e1SXiao Feng Ren #define TYPE_VFIO_CCW "vfio-ccw" 281dcac3e1SXiao Feng Ren typedef struct VFIOCCWDevice { 291dcac3e1SXiao Feng Ren S390CCWDevice cdev; 301dcac3e1SXiao Feng Ren VFIODevice vdev; 31c14e706cSDong Jia Shi uint64_t io_region_size; 32c14e706cSDong Jia Shi uint64_t io_region_offset; 33c14e706cSDong Jia Shi struct ccw_io_region *io_region; 34*4886b3e9SDong Jia Shi EventNotifier io_notifier; 351dcac3e1SXiao Feng Ren } VFIOCCWDevice; 361dcac3e1SXiao Feng Ren 371dcac3e1SXiao Feng Ren static void vfio_ccw_compute_needs_reset(VFIODevice *vdev) 381dcac3e1SXiao Feng Ren { 391dcac3e1SXiao Feng Ren vdev->needs_reset = false; 401dcac3e1SXiao Feng Ren } 411dcac3e1SXiao Feng Ren 421dcac3e1SXiao Feng Ren /* 431dcac3e1SXiao Feng Ren * We don't need vfio_hot_reset_multi and vfio_eoi operations for 441dcac3e1SXiao Feng Ren * vfio_ccw device now. 451dcac3e1SXiao Feng Ren */ 461dcac3e1SXiao Feng Ren struct VFIODeviceOps vfio_ccw_ops = { 471dcac3e1SXiao Feng Ren .vfio_compute_needs_reset = vfio_ccw_compute_needs_reset, 481dcac3e1SXiao Feng Ren }; 491dcac3e1SXiao Feng Ren 501dcac3e1SXiao Feng Ren static void vfio_ccw_reset(DeviceState *dev) 511dcac3e1SXiao Feng Ren { 521dcac3e1SXiao Feng Ren CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev); 531dcac3e1SXiao Feng Ren S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev); 541dcac3e1SXiao Feng Ren VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); 551dcac3e1SXiao Feng Ren 561dcac3e1SXiao Feng Ren ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET); 571dcac3e1SXiao Feng Ren } 581dcac3e1SXiao Feng Ren 59*4886b3e9SDong Jia Shi static void vfio_ccw_io_notifier_handler(void *opaque) 60*4886b3e9SDong Jia Shi { 61*4886b3e9SDong Jia Shi VFIOCCWDevice *vcdev = opaque; 62*4886b3e9SDong Jia Shi 63*4886b3e9SDong Jia Shi if (!event_notifier_test_and_clear(&vcdev->io_notifier)) { 64*4886b3e9SDong Jia Shi return; 65*4886b3e9SDong Jia Shi } 66*4886b3e9SDong Jia Shi } 67*4886b3e9SDong Jia Shi 68*4886b3e9SDong Jia Shi static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp) 69*4886b3e9SDong Jia Shi { 70*4886b3e9SDong Jia Shi VFIODevice *vdev = &vcdev->vdev; 71*4886b3e9SDong Jia Shi struct vfio_irq_info *irq_info; 72*4886b3e9SDong Jia Shi struct vfio_irq_set *irq_set; 73*4886b3e9SDong Jia Shi size_t argsz; 74*4886b3e9SDong Jia Shi int32_t *pfd; 75*4886b3e9SDong Jia Shi 76*4886b3e9SDong Jia Shi if (vdev->num_irqs < VFIO_CCW_IO_IRQ_INDEX + 1) { 77*4886b3e9SDong Jia Shi error_setg(errp, "vfio: unexpected number of io irqs %u", 78*4886b3e9SDong Jia Shi vdev->num_irqs); 79*4886b3e9SDong Jia Shi return; 80*4886b3e9SDong Jia Shi } 81*4886b3e9SDong Jia Shi 82*4886b3e9SDong Jia Shi argsz = sizeof(*irq_set); 83*4886b3e9SDong Jia Shi irq_info = g_malloc0(argsz); 84*4886b3e9SDong Jia Shi irq_info->index = VFIO_CCW_IO_IRQ_INDEX; 85*4886b3e9SDong Jia Shi irq_info->argsz = argsz; 86*4886b3e9SDong Jia Shi if (ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, 87*4886b3e9SDong Jia Shi irq_info) < 0 || irq_info->count < 1) { 88*4886b3e9SDong Jia Shi error_setg_errno(errp, errno, "vfio: Error getting irq info"); 89*4886b3e9SDong Jia Shi goto out_free_info; 90*4886b3e9SDong Jia Shi } 91*4886b3e9SDong Jia Shi 92*4886b3e9SDong Jia Shi if (event_notifier_init(&vcdev->io_notifier, 0)) { 93*4886b3e9SDong Jia Shi error_setg_errno(errp, errno, 94*4886b3e9SDong Jia Shi "vfio: Unable to init event notifier for IO"); 95*4886b3e9SDong Jia Shi goto out_free_info; 96*4886b3e9SDong Jia Shi } 97*4886b3e9SDong Jia Shi 98*4886b3e9SDong Jia Shi argsz = sizeof(*irq_set) + sizeof(*pfd); 99*4886b3e9SDong Jia Shi irq_set = g_malloc0(argsz); 100*4886b3e9SDong Jia Shi irq_set->argsz = argsz; 101*4886b3e9SDong Jia Shi irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | 102*4886b3e9SDong Jia Shi VFIO_IRQ_SET_ACTION_TRIGGER; 103*4886b3e9SDong Jia Shi irq_set->index = VFIO_CCW_IO_IRQ_INDEX; 104*4886b3e9SDong Jia Shi irq_set->start = 0; 105*4886b3e9SDong Jia Shi irq_set->count = 1; 106*4886b3e9SDong Jia Shi pfd = (int32_t *) &irq_set->data; 107*4886b3e9SDong Jia Shi 108*4886b3e9SDong Jia Shi *pfd = event_notifier_get_fd(&vcdev->io_notifier); 109*4886b3e9SDong Jia Shi qemu_set_fd_handler(*pfd, vfio_ccw_io_notifier_handler, NULL, vcdev); 110*4886b3e9SDong Jia Shi if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) { 111*4886b3e9SDong Jia Shi error_setg(errp, "vfio: Failed to set up io notification"); 112*4886b3e9SDong Jia Shi qemu_set_fd_handler(*pfd, NULL, NULL, vcdev); 113*4886b3e9SDong Jia Shi event_notifier_cleanup(&vcdev->io_notifier); 114*4886b3e9SDong Jia Shi } 115*4886b3e9SDong Jia Shi 116*4886b3e9SDong Jia Shi g_free(irq_set); 117*4886b3e9SDong Jia Shi 118*4886b3e9SDong Jia Shi out_free_info: 119*4886b3e9SDong Jia Shi g_free(irq_info); 120*4886b3e9SDong Jia Shi } 121*4886b3e9SDong Jia Shi 122*4886b3e9SDong Jia Shi static void vfio_ccw_unregister_io_notifier(VFIOCCWDevice *vcdev) 123*4886b3e9SDong Jia Shi { 124*4886b3e9SDong Jia Shi struct vfio_irq_set *irq_set; 125*4886b3e9SDong Jia Shi size_t argsz; 126*4886b3e9SDong Jia Shi int32_t *pfd; 127*4886b3e9SDong Jia Shi 128*4886b3e9SDong Jia Shi argsz = sizeof(*irq_set) + sizeof(*pfd); 129*4886b3e9SDong Jia Shi irq_set = g_malloc0(argsz); 130*4886b3e9SDong Jia Shi irq_set->argsz = argsz; 131*4886b3e9SDong Jia Shi irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | 132*4886b3e9SDong Jia Shi VFIO_IRQ_SET_ACTION_TRIGGER; 133*4886b3e9SDong Jia Shi irq_set->index = VFIO_CCW_IO_IRQ_INDEX; 134*4886b3e9SDong Jia Shi irq_set->start = 0; 135*4886b3e9SDong Jia Shi irq_set->count = 1; 136*4886b3e9SDong Jia Shi pfd = (int32_t *) &irq_set->data; 137*4886b3e9SDong Jia Shi *pfd = -1; 138*4886b3e9SDong Jia Shi 139*4886b3e9SDong Jia Shi if (ioctl(vcdev->vdev.fd, VFIO_DEVICE_SET_IRQS, irq_set)) { 140*4886b3e9SDong Jia Shi error_report("vfio: Failed to de-assign device io fd: %m"); 141*4886b3e9SDong Jia Shi } 142*4886b3e9SDong Jia Shi 143*4886b3e9SDong Jia Shi qemu_set_fd_handler(event_notifier_get_fd(&vcdev->io_notifier), 144*4886b3e9SDong Jia Shi NULL, NULL, vcdev); 145*4886b3e9SDong Jia Shi event_notifier_cleanup(&vcdev->io_notifier); 146*4886b3e9SDong Jia Shi 147*4886b3e9SDong Jia Shi g_free(irq_set); 148*4886b3e9SDong Jia Shi } 149*4886b3e9SDong Jia Shi 150c14e706cSDong Jia Shi static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp) 151c14e706cSDong Jia Shi { 152c14e706cSDong Jia Shi VFIODevice *vdev = &vcdev->vdev; 153c14e706cSDong Jia Shi struct vfio_region_info *info; 154c14e706cSDong Jia Shi int ret; 155c14e706cSDong Jia Shi 156c14e706cSDong Jia Shi /* Sanity check device */ 157c14e706cSDong Jia Shi if (!(vdev->flags & VFIO_DEVICE_FLAGS_CCW)) { 158c14e706cSDong Jia Shi error_setg(errp, "vfio: Um, this isn't a vfio-ccw device"); 159c14e706cSDong Jia Shi return; 160c14e706cSDong Jia Shi } 161c14e706cSDong Jia Shi 162c14e706cSDong Jia Shi if (vdev->num_regions < VFIO_CCW_CONFIG_REGION_INDEX + 1) { 163c14e706cSDong Jia Shi error_setg(errp, "vfio: Unexpected number of the I/O region %u", 164c14e706cSDong Jia Shi vdev->num_regions); 165c14e706cSDong Jia Shi return; 166c14e706cSDong Jia Shi } 167c14e706cSDong Jia Shi 168c14e706cSDong Jia Shi ret = vfio_get_region_info(vdev, VFIO_CCW_CONFIG_REGION_INDEX, &info); 169c14e706cSDong Jia Shi if (ret) { 170c14e706cSDong Jia Shi error_setg_errno(errp, -ret, "vfio: Error getting config info"); 171c14e706cSDong Jia Shi return; 172c14e706cSDong Jia Shi } 173c14e706cSDong Jia Shi 174c14e706cSDong Jia Shi vcdev->io_region_size = info->size; 175c14e706cSDong Jia Shi if (sizeof(*vcdev->io_region) != vcdev->io_region_size) { 176c14e706cSDong Jia Shi error_setg(errp, "vfio: Unexpected size of the I/O region"); 177c14e706cSDong Jia Shi g_free(info); 178c14e706cSDong Jia Shi return; 179c14e706cSDong Jia Shi } 180c14e706cSDong Jia Shi 181c14e706cSDong Jia Shi vcdev->io_region_offset = info->offset; 182c14e706cSDong Jia Shi vcdev->io_region = g_malloc0(info->size); 183c14e706cSDong Jia Shi 184c14e706cSDong Jia Shi g_free(info); 185c14e706cSDong Jia Shi } 186c14e706cSDong Jia Shi 187c14e706cSDong Jia Shi static void vfio_ccw_put_region(VFIOCCWDevice *vcdev) 188c14e706cSDong Jia Shi { 189c14e706cSDong Jia Shi g_free(vcdev->io_region); 190c14e706cSDong Jia Shi } 191c14e706cSDong Jia Shi 1921dcac3e1SXiao Feng Ren static void vfio_put_device(VFIOCCWDevice *vcdev) 1931dcac3e1SXiao Feng Ren { 1941dcac3e1SXiao Feng Ren g_free(vcdev->vdev.name); 1951dcac3e1SXiao Feng Ren vfio_put_base_device(&vcdev->vdev); 1961dcac3e1SXiao Feng Ren } 1971dcac3e1SXiao Feng Ren 1981dcac3e1SXiao Feng Ren static VFIOGroup *vfio_ccw_get_group(S390CCWDevice *cdev, Error **errp) 1991dcac3e1SXiao Feng Ren { 2001dcac3e1SXiao Feng Ren char *tmp, group_path[PATH_MAX]; 2011dcac3e1SXiao Feng Ren ssize_t len; 2021dcac3e1SXiao Feng Ren int groupid; 2031dcac3e1SXiao Feng Ren 2041dcac3e1SXiao Feng Ren tmp = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/%s/iommu_group", 2051dcac3e1SXiao Feng Ren cdev->hostid.cssid, cdev->hostid.ssid, 2061dcac3e1SXiao Feng Ren cdev->hostid.devid, cdev->mdevid); 2071dcac3e1SXiao Feng Ren len = readlink(tmp, group_path, sizeof(group_path)); 2081dcac3e1SXiao Feng Ren g_free(tmp); 2091dcac3e1SXiao Feng Ren 2101dcac3e1SXiao Feng Ren if (len <= 0 || len >= sizeof(group_path)) { 2111dcac3e1SXiao Feng Ren error_setg(errp, "vfio: no iommu_group found"); 2121dcac3e1SXiao Feng Ren return NULL; 2131dcac3e1SXiao Feng Ren } 2141dcac3e1SXiao Feng Ren 2151dcac3e1SXiao Feng Ren group_path[len] = 0; 2161dcac3e1SXiao Feng Ren 2171dcac3e1SXiao Feng Ren if (sscanf(basename(group_path), "%d", &groupid) != 1) { 2181dcac3e1SXiao Feng Ren error_setg(errp, "vfio: failed to read %s", group_path); 2191dcac3e1SXiao Feng Ren return NULL; 2201dcac3e1SXiao Feng Ren } 2211dcac3e1SXiao Feng Ren 2221dcac3e1SXiao Feng Ren return vfio_get_group(groupid, &address_space_memory, errp); 2231dcac3e1SXiao Feng Ren } 2241dcac3e1SXiao Feng Ren 2251dcac3e1SXiao Feng Ren static void vfio_ccw_realize(DeviceState *dev, Error **errp) 2261dcac3e1SXiao Feng Ren { 2271dcac3e1SXiao Feng Ren VFIODevice *vbasedev; 2281dcac3e1SXiao Feng Ren VFIOGroup *group; 2291dcac3e1SXiao Feng Ren CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev); 2301dcac3e1SXiao Feng Ren S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev); 2311dcac3e1SXiao Feng Ren VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); 2321dcac3e1SXiao Feng Ren S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); 2331dcac3e1SXiao Feng Ren Error *err = NULL; 2341dcac3e1SXiao Feng Ren 2351dcac3e1SXiao Feng Ren /* Call the class init function for subchannel. */ 2361dcac3e1SXiao Feng Ren if (cdc->realize) { 2371dcac3e1SXiao Feng Ren cdc->realize(cdev, vcdev->vdev.sysfsdev, &err); 2381dcac3e1SXiao Feng Ren if (err) { 2391dcac3e1SXiao Feng Ren goto out_err_propagate; 2401dcac3e1SXiao Feng Ren } 2411dcac3e1SXiao Feng Ren } 2421dcac3e1SXiao Feng Ren 2431dcac3e1SXiao Feng Ren group = vfio_ccw_get_group(cdev, &err); 2441dcac3e1SXiao Feng Ren if (!group) { 2451dcac3e1SXiao Feng Ren goto out_group_err; 2461dcac3e1SXiao Feng Ren } 2471dcac3e1SXiao Feng Ren 2481dcac3e1SXiao Feng Ren vcdev->vdev.ops = &vfio_ccw_ops; 2491dcac3e1SXiao Feng Ren vcdev->vdev.type = VFIO_DEVICE_TYPE_CCW; 2501dcac3e1SXiao Feng Ren vcdev->vdev.name = g_strdup_printf("%x.%x.%04x", cdev->hostid.cssid, 2511dcac3e1SXiao Feng Ren cdev->hostid.ssid, cdev->hostid.devid); 2521dcac3e1SXiao Feng Ren QLIST_FOREACH(vbasedev, &group->device_list, next) { 2531dcac3e1SXiao Feng Ren if (strcmp(vbasedev->name, vcdev->vdev.name) == 0) { 2541dcac3e1SXiao Feng Ren error_setg(&err, "vfio: subchannel %s has already been attached", 2551dcac3e1SXiao Feng Ren vcdev->vdev.name); 2561dcac3e1SXiao Feng Ren goto out_device_err; 2571dcac3e1SXiao Feng Ren } 2581dcac3e1SXiao Feng Ren } 2591dcac3e1SXiao Feng Ren 2601dcac3e1SXiao Feng Ren if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, &err)) { 2611dcac3e1SXiao Feng Ren goto out_device_err; 2621dcac3e1SXiao Feng Ren } 2631dcac3e1SXiao Feng Ren 264c14e706cSDong Jia Shi vfio_ccw_get_region(vcdev, &err); 265c14e706cSDong Jia Shi if (err) { 266c14e706cSDong Jia Shi goto out_region_err; 267c14e706cSDong Jia Shi } 268c14e706cSDong Jia Shi 269*4886b3e9SDong Jia Shi vfio_ccw_register_io_notifier(vcdev, &err); 270*4886b3e9SDong Jia Shi if (err) { 271*4886b3e9SDong Jia Shi goto out_notifier_err; 272*4886b3e9SDong Jia Shi } 273*4886b3e9SDong Jia Shi 2741dcac3e1SXiao Feng Ren return; 2751dcac3e1SXiao Feng Ren 276*4886b3e9SDong Jia Shi out_notifier_err: 277*4886b3e9SDong Jia Shi vfio_ccw_put_region(vcdev); 278c14e706cSDong Jia Shi out_region_err: 279c14e706cSDong Jia Shi vfio_put_device(vcdev); 2801dcac3e1SXiao Feng Ren out_device_err: 2811dcac3e1SXiao Feng Ren vfio_put_group(group); 2821dcac3e1SXiao Feng Ren out_group_err: 2831dcac3e1SXiao Feng Ren if (cdc->unrealize) { 2841dcac3e1SXiao Feng Ren cdc->unrealize(cdev, NULL); 2851dcac3e1SXiao Feng Ren } 2861dcac3e1SXiao Feng Ren out_err_propagate: 2871dcac3e1SXiao Feng Ren error_propagate(errp, err); 2881dcac3e1SXiao Feng Ren } 2891dcac3e1SXiao Feng Ren 2901dcac3e1SXiao Feng Ren static void vfio_ccw_unrealize(DeviceState *dev, Error **errp) 2911dcac3e1SXiao Feng Ren { 2921dcac3e1SXiao Feng Ren CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev); 2931dcac3e1SXiao Feng Ren S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev); 2941dcac3e1SXiao Feng Ren VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev); 2951dcac3e1SXiao Feng Ren S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); 2961dcac3e1SXiao Feng Ren VFIOGroup *group = vcdev->vdev.group; 2971dcac3e1SXiao Feng Ren 298*4886b3e9SDong Jia Shi vfio_ccw_unregister_io_notifier(vcdev); 299c14e706cSDong Jia Shi vfio_ccw_put_region(vcdev); 3001dcac3e1SXiao Feng Ren vfio_put_device(vcdev); 3011dcac3e1SXiao Feng Ren vfio_put_group(group); 3021dcac3e1SXiao Feng Ren 3031dcac3e1SXiao Feng Ren if (cdc->unrealize) { 3041dcac3e1SXiao Feng Ren cdc->unrealize(cdev, errp); 3051dcac3e1SXiao Feng Ren } 3061dcac3e1SXiao Feng Ren } 3071dcac3e1SXiao Feng Ren 3081dcac3e1SXiao Feng Ren static Property vfio_ccw_properties[] = { 3091dcac3e1SXiao Feng Ren DEFINE_PROP_STRING("sysfsdev", VFIOCCWDevice, vdev.sysfsdev), 3101dcac3e1SXiao Feng Ren DEFINE_PROP_END_OF_LIST(), 3111dcac3e1SXiao Feng Ren }; 3121dcac3e1SXiao Feng Ren 3131dcac3e1SXiao Feng Ren static const VMStateDescription vfio_ccw_vmstate = { 3141dcac3e1SXiao Feng Ren .name = TYPE_VFIO_CCW, 3151dcac3e1SXiao Feng Ren .unmigratable = 1, 3161dcac3e1SXiao Feng Ren }; 3171dcac3e1SXiao Feng Ren 3181dcac3e1SXiao Feng Ren static void vfio_ccw_class_init(ObjectClass *klass, void *data) 3191dcac3e1SXiao Feng Ren { 3201dcac3e1SXiao Feng Ren DeviceClass *dc = DEVICE_CLASS(klass); 3211dcac3e1SXiao Feng Ren 3221dcac3e1SXiao Feng Ren dc->props = vfio_ccw_properties; 3231dcac3e1SXiao Feng Ren dc->vmsd = &vfio_ccw_vmstate; 3241dcac3e1SXiao Feng Ren dc->desc = "VFIO-based subchannel assignment"; 3251dcac3e1SXiao Feng Ren dc->realize = vfio_ccw_realize; 3261dcac3e1SXiao Feng Ren dc->unrealize = vfio_ccw_unrealize; 3271dcac3e1SXiao Feng Ren dc->reset = vfio_ccw_reset; 3281dcac3e1SXiao Feng Ren } 3291dcac3e1SXiao Feng Ren 3301dcac3e1SXiao Feng Ren static const TypeInfo vfio_ccw_info = { 3311dcac3e1SXiao Feng Ren .name = TYPE_VFIO_CCW, 3321dcac3e1SXiao Feng Ren .parent = TYPE_S390_CCW, 3331dcac3e1SXiao Feng Ren .instance_size = sizeof(VFIOCCWDevice), 3341dcac3e1SXiao Feng Ren .class_init = vfio_ccw_class_init, 3351dcac3e1SXiao Feng Ren }; 3361dcac3e1SXiao Feng Ren 3371dcac3e1SXiao Feng Ren static void register_vfio_ccw_type(void) 3381dcac3e1SXiao Feng Ren { 3391dcac3e1SXiao Feng Ren type_register_static(&vfio_ccw_info); 3401dcac3e1SXiao Feng Ren } 3411dcac3e1SXiao Feng Ren 3421dcac3e1SXiao Feng Ren type_init(register_vfio_ccw_type) 343