diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index cc560e66f28e6e210552edabd0779fc8fda4787b..1ea667cdf6f3323ba889b768e9ea28e8929df94f 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -318,6 +318,37 @@ + + + + 0x[0-9a-eA-E][0-9a-fA-F]? + + + 0x[fF][0-9a-eA-E]? + + + 0 + 254 + + + + + + (0x)?[0-3] + + + + + + 0x[0-9a-fA-F]{1,4} + + + 0 + 65535 + + + + ([0-9]+(-[0-9]+)?|\^[0-9]+)(,([0-9]+(-[0-9]+)?|\^[0-9]+))* diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 144c28159611fac3c83fdb4226fa6b64ffb46b5f..4d9f8d1a25ab1372f025d6a75854db8f878fb61b 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -5775,36 +5775,6 @@ - - - - 0x[0-9a-eA-E][0-9a-fA-F]? - - - 0x[fF][0-9a-eA-E]? - - - 0 - 254 - - - - - - (0x)?[0-3] - - - - - - 0x[0-9a-fA-F]{1,4} - - - 0 - 65535 - - - diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng index 924f73861b83d61e831d8065804e3cf1f12bf66d..87bfb0c2865c738ac7b72ca09d38b0d31c5eb8c3 100644 --- a/docs/schemas/nodedev.rng +++ b/docs/schemas/nodedev.rng @@ -84,6 +84,7 @@ + @@ -597,6 +598,21 @@ + + + ccw + + + + + + + + + + + + diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 722a4a5a00b775e84c0a9d71f9848de9db460c16..22c06f86979b2624ef5d4758c1435f6f322aae5b 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -62,7 +62,8 @@ VIR_ENUM_IMPL(virNodeDevCap, VIR_NODE_DEV_CAP_LAST, "scsi_generic", "drm", "mdev_types", - "mdev") + "mdev", + "ccw") VIR_ENUM_IMPL(virNodeDevNetCap, VIR_NODE_DEV_CAP_NET_LAST, "80203", @@ -581,6 +582,14 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def) virBufferAsprintf(&buf, "\n", data->mdev.iommuGroupNumber); break; + case VIR_NODE_DEV_CAP_CCW_DEV: + virBufferAsprintf(&buf, "0x%x\n", + data->ccw_dev.cssid); + virBufferAsprintf(&buf, "0x%x\n", + data->ccw_dev.ssid); + virBufferAsprintf(&buf, "0x%04x\n", + data->ccw_dev.devno); + break; case VIR_NODE_DEV_CAP_MDEV_TYPES: case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: @@ -717,6 +726,66 @@ virNodeDevCapDRMParseXML(xmlXPathContextPtr ctxt, } +static int +virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt, + virNodeDeviceDefPtr def, + xmlNodePtr node, + virNodeDevCapCCWPtr ccw_dev) +{ + xmlNodePtr orignode; + int ret = -1; + char *cssid = NULL, *ssid = NULL, *devno = NULL; + + orignode = ctxt->node; + ctxt->node = node; + + if (!(cssid = virXPathString("string(./cssid[1])", ctxt))) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("missing cssid value for '%s'"), def->name); + goto out; + } + + if (virStrToLong_uip(cssid, NULL, 0, &ccw_dev->cssid) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("invalid cssid value '%s' for '%s'"), + cssid, def->name); + goto out; + } + + if (!(ssid = virXPathString("string(./ssid[1])", ctxt))) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("missing ssid value for '%s'"), def->name); + goto out; + } + + if (virStrToLong_uip(ssid, NULL, 0, &ccw_dev->ssid) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("invalid ssid value '%s' for '%s'"), + cssid, def->name); + goto out; + } + + if (!(devno = virXPathString("string(./devno[1])", ctxt))) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("missing devno value for '%s'"), def->name); + goto out; + } + + if (virStrToLong_uip(devno, NULL, 16, &ccw_dev->devno) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("invalid devno value '%s' for '%s'"), + devno, def->name); + goto out; + } + + ret = 0; + + out: + ctxt->node = orignode; + return ret; +} + + static int virNodeDevCapStorageParseXML(xmlXPathContextPtr ctxt, virNodeDeviceDefPtr def, @@ -1754,6 +1823,9 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt, case VIR_NODE_DEV_CAP_MDEV: ret = virNodeDevCapMdevParseXML(ctxt, def, node, &caps->data.mdev); break; + case VIR_NODE_DEV_CAP_CCW_DEV: + ret = virNodeDevCapCCWParseXML(ctxt, def, node, &caps->data.ccw_dev); + break; case VIR_NODE_DEV_CAP_MDEV_TYPES: case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: @@ -2083,6 +2155,7 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps) case VIR_NODE_DEV_CAP_DRM: case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: + case VIR_NODE_DEV_CAP_CCW_DEV: case VIR_NODE_DEV_CAP_LAST: /* This case is here to shutup the compiler */ break; diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index 5743f9d3e2d04e3f008aa9e6fe31361898433dc9..bf9d5fce56eda9f7406dee42916bebd26731b20e 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -66,6 +66,7 @@ typedef enum { VIR_NODE_DEV_CAP_DRM, /* DRM device */ VIR_NODE_DEV_CAP_MDEV_TYPES, /* Device capable of mediated devices */ VIR_NODE_DEV_CAP_MDEV, /* Mediated device */ + VIR_NODE_DEV_CAP_CCW_DEV, /* s390 CCW device */ VIR_NODE_DEV_CAP_LAST } virNodeDevCapType; @@ -267,6 +268,14 @@ struct _virNodeDevCapDRM { virNodeDevDRMType type; }; +typedef struct _virNodeDevCapCCW virNodeDevCapCCW; +typedef virNodeDevCapCCW *virNodeDevCapCCWPtr; +struct _virNodeDevCapCCW { + unsigned int cssid; + unsigned int ssid; + unsigned int devno; +}; + typedef struct _virNodeDevCapData virNodeDevCapData; typedef virNodeDevCapData *virNodeDevCapDataPtr; struct _virNodeDevCapData { @@ -284,6 +293,7 @@ struct _virNodeDevCapData { virNodeDevCapSCSIGeneric sg; virNodeDevCapDRM drm; virNodeDevCapMdev mdev; + virNodeDevCapCCW ccw_dev; }; }; diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c index dfce17ce7157b55d43bd734065b94d4b5797b7be..66faf2b4fcf96798b98794032fdb262ec9c0a425 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -84,6 +84,7 @@ static int update_caps(virNodeDeviceObjPtr dev) case VIR_NODE_DEV_CAP_SCSI_GENERIC: case VIR_NODE_DEV_CAP_MDEV_TYPES: case VIR_NODE_DEV_CAP_MDEV: + case VIR_NODE_DEV_CAP_CCW_DEV: case VIR_NODE_DEV_CAP_LAST: break; } diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index 4ecb0b18fefce0b1ab0d0414ffba37ea2ecafbf8..cc854b53802f293e7c050d4b1811b81a4c78981a 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -1104,6 +1104,36 @@ udevProcessMediatedDevice(struct udev_device *dev, return ret; } + +static int +udevProcessCCW(struct udev_device *device, + virNodeDeviceDefPtr def) +{ + int online; + char *p; + virNodeDevCapDataPtr data = &def->caps->data; + + /* process only online devices to keep the list sane */ + if (udevGetIntSysfsAttr(device, "online", &online, 0) < 0 || online != 1) + return -1; + + if ((p = strrchr(def->sysfs_path, '/')) == NULL || + virStrToLong_ui(p + 1, &p, 16, &data->ccw_dev.cssid) < 0 || p == NULL || + virStrToLong_ui(p + 1, &p, 16, &data->ccw_dev.ssid) < 0 || p == NULL || + virStrToLong_ui(p + 1, &p, 16, &data->ccw_dev.devno) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to parse the CCW address from sysfs path: '%s'"), + def->sysfs_path); + return -1; + } + + if (udevGenerateDeviceName(device, def, NULL) != 0) + return -1; + + return 0; +} + + static int udevGetDeviceNodes(struct udev_device *device, virNodeDeviceDefPtr def) @@ -1172,8 +1202,8 @@ udevGetDeviceType(struct udev_device *device, if (udevHasDeviceProperty(device, "INTERFACE")) *type = VIR_NODE_DEV_CAP_NET; - /* Neither SCSI generic devices nor mediated devices set DEVTYPE - * property, therefore we need to rely on the SUBSYSTEM property */ + /* The following devices do not set the DEVTYPE property, therefore + * we need to rely on the SUBSYSTEM property */ if (udevGetStringProperty(device, "SUBSYSTEM", &subsystem) < 0) return -1; @@ -1181,6 +1211,8 @@ udevGetDeviceType(struct udev_device *device, *type = VIR_NODE_DEV_CAP_SCSI_GENERIC; else if (STREQ_NULLABLE(subsystem, "mdev")) *type = VIR_NODE_DEV_CAP_MDEV; + else if (STREQ_NULLABLE(subsystem, "ccw")) + *type = VIR_NODE_DEV_CAP_CCW_DEV; VIR_FREE(subsystem); } @@ -1222,6 +1254,8 @@ static int udevGetDeviceDetails(struct udev_device *device, return udevProcessDRMDevice(device, def); case VIR_NODE_DEV_CAP_MDEV: return udevProcessMediatedDevice(device, def); + case VIR_NODE_DEV_CAP_CCW_DEV: + return udevProcessCCW(device, def); case VIR_NODE_DEV_CAP_MDEV_TYPES: case VIR_NODE_DEV_CAP_SYSTEM: case VIR_NODE_DEV_CAP_FC_HOST: diff --git a/tests/nodedevschemadata/ccw_0_0_10000-invalid.xml b/tests/nodedevschemadata/ccw_0_0_10000-invalid.xml new file mode 100644 index 0000000000000000000000000000000000000000..d840555c09b6f86efc27231df6bb2aca53d8e1bd --- /dev/null +++ b/tests/nodedevschemadata/ccw_0_0_10000-invalid.xml @@ -0,0 +1,10 @@ + + ccw_0_0_10000 + /sys/devices/css0/0.0.0000/0.0.10000 + computer + + 0x0 + 0x0 + 0x10000 + + diff --git a/tests/nodedevschemadata/ccw_0_0_ffff.xml b/tests/nodedevschemadata/ccw_0_0_ffff.xml new file mode 100644 index 0000000000000000000000000000000000000000..5ecd0b0aae57f82c058e6a565bb63403e0c5157d --- /dev/null +++ b/tests/nodedevschemadata/ccw_0_0_ffff.xml @@ -0,0 +1,10 @@ + + ccw_0_0_ffff + /sys/devices/css0/0.0.0000/0.0.ffff + computer + + 0x0 + 0x0 + 0xffff + + diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c index a2aad518d339d75532109c2c6963196c6a4f9b85..805deef269511c06a1272c305a4e95f1d471c9bc 100644 --- a/tests/nodedevxml2xmltest.c +++ b/tests/nodedevxml2xmltest.c @@ -103,6 +103,7 @@ mymain(void) DO_TEST("drm_renderD129"); DO_TEST("pci_0000_02_10_7_mdev_types"); DO_TEST("mdev_3627463d_b7f0_4fea_b468_f1da537d301b"); + DO_TEST("ccw_0_0_ffff"); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c index ad96dda1f9f9f74cfdbac92f7b205d6351718586..1822d3dce3954d1cde21ace580e6091ab6e27955 100644 --- a/tools/virsh-nodedev.c +++ b/tools/virsh-nodedev.c @@ -460,6 +460,8 @@ cmdNodeListDevices(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) case VIR_NODE_DEV_CAP_MDEV: flags |= VIR_CONNECT_LIST_NODE_DEVICES_CAP_MDEV; break; + case VIR_NODE_DEV_CAP_CCW_DEV: + /* enable next patch */ case VIR_NODE_DEV_CAP_LAST: break; }