mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
node_device: detect CCW devices
Make CCW devices available to the node_device driver. The devices are already seen by udev so let's implement necessary code for detecting them properly. Topologically, CCW devices are similar to PCI devices, e.g.: +- ccw_0_0_1a2b | +- scsi_host0 | +- scsi_target0_0_0 | +- scsi_0_0_0_0 Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com> Signed-off-by: Bjoern Walk <bwalk@linux.vnet.ibm.com>
This commit is contained in:
parent
a9b98ecf4e
commit
b0ffd938d4
@ -318,6 +318,37 @@
|
||||
</data>
|
||||
</define>
|
||||
|
||||
<define name="ccwCssidRange">
|
||||
<choice>
|
||||
<data type="string">
|
||||
<param name="pattern">0x[0-9a-eA-E][0-9a-fA-F]?</param>
|
||||
</data>
|
||||
<data type="string">
|
||||
<param name="pattern">0x[fF][0-9a-eA-E]?</param>
|
||||
</data>
|
||||
<data type="int">
|
||||
<param name="minInclusive">0</param>
|
||||
<param name="maxInclusive">254</param>
|
||||
</data>
|
||||
</choice>
|
||||
</define>
|
||||
<define name="ccwSsidRange">
|
||||
<data type="string">
|
||||
<param name="pattern">(0x)?[0-3]</param>
|
||||
</data>
|
||||
</define>
|
||||
<define name="ccwDevnoRange">
|
||||
<choice>
|
||||
<data type="string">
|
||||
<param name="pattern">0x[0-9a-fA-F]{1,4}</param>
|
||||
</data>
|
||||
<data type="int">
|
||||
<param name="minInclusive">0</param>
|
||||
<param name="maxInclusive">65535</param>
|
||||
</data>
|
||||
</choice>
|
||||
</define>
|
||||
|
||||
<define name="cpuset">
|
||||
<data type="string">
|
||||
<param name="pattern">([0-9]+(-[0-9]+)?|\^[0-9]+)(,([0-9]+(-[0-9]+)?|\^[0-9]+))*</param>
|
||||
|
@ -5775,36 +5775,6 @@
|
||||
</element>
|
||||
<empty/>
|
||||
</define>
|
||||
<define name="ccwCssidRange">
|
||||
<choice>
|
||||
<data type="string">
|
||||
<param name="pattern">0x[0-9a-eA-E][0-9a-fA-F]?</param>
|
||||
</data>
|
||||
<data type="string">
|
||||
<param name="pattern">0x[fF][0-9a-eA-E]?</param>
|
||||
</data>
|
||||
<data type="int">
|
||||
<param name="minInclusive">0</param>
|
||||
<param name="maxInclusive">254</param>
|
||||
</data>
|
||||
</choice>
|
||||
</define>
|
||||
<define name="ccwSsidRange">
|
||||
<data type="string">
|
||||
<param name="pattern">(0x)?[0-3]</param>
|
||||
</data>
|
||||
</define>
|
||||
<define name="ccwDevnoRange">
|
||||
<choice>
|
||||
<data type="string">
|
||||
<param name="pattern">0x[0-9a-fA-F]{1,4}</param>
|
||||
</data>
|
||||
<data type="int">
|
||||
<param name="minInclusive">0</param>
|
||||
<param name="maxInclusive">65535</param>
|
||||
</data>
|
||||
</choice>
|
||||
</define>
|
||||
<define name="panic">
|
||||
<element name="panic">
|
||||
<optional>
|
||||
|
@ -84,6 +84,7 @@
|
||||
<ref name="capstorage"/>
|
||||
<ref name="capdrm"/>
|
||||
<ref name="capmdev"/>
|
||||
<ref name="capccwdev"/>
|
||||
</choice>
|
||||
</element>
|
||||
</define>
|
||||
@ -597,6 +598,21 @@
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name='capccwdev'>
|
||||
<attribute name='type'>
|
||||
<value>ccw</value>
|
||||
</attribute>
|
||||
<element name='cssid'>
|
||||
<ref name='ccwCssidRange'/>
|
||||
</element>
|
||||
<element name='ssid'>
|
||||
<ref name='ccwSsidRange'/>
|
||||
</element>
|
||||
<element name='devno'>
|
||||
<ref name='ccwDevnoRange'/>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name='address'>
|
||||
<element name='address'>
|
||||
<attribute name='domain'><ref name='hexuint'/></attribute>
|
||||
|
@ -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, "<iommuGroup number='%u'/>\n",
|
||||
data->mdev.iommuGroupNumber);
|
||||
break;
|
||||
case VIR_NODE_DEV_CAP_CCW_DEV:
|
||||
virBufferAsprintf(&buf, "<cssid>0x%x</cssid>\n",
|
||||
data->ccw_dev.cssid);
|
||||
virBufferAsprintf(&buf, "<ssid>0x%x</ssid>\n",
|
||||
data->ccw_dev.ssid);
|
||||
virBufferAsprintf(&buf, "<devno>0x%04x</devno>\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;
|
||||
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
10
tests/nodedevschemadata/ccw_0_0_10000-invalid.xml
Normal file
10
tests/nodedevschemadata/ccw_0_0_10000-invalid.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<device>
|
||||
<name>ccw_0_0_10000</name>
|
||||
<path>/sys/devices/css0/0.0.0000/0.0.10000</path>
|
||||
<parent>computer</parent>
|
||||
<capability type='ccw'>
|
||||
<cssid>0x0</cssid>
|
||||
<ssid>0x0</ssid>
|
||||
<devno>0x10000</devno>
|
||||
</capability>
|
||||
</device>
|
10
tests/nodedevschemadata/ccw_0_0_ffff.xml
Normal file
10
tests/nodedevschemadata/ccw_0_0_ffff.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<device>
|
||||
<name>ccw_0_0_ffff</name>
|
||||
<path>/sys/devices/css0/0.0.0000/0.0.ffff</path>
|
||||
<parent>computer</parent>
|
||||
<capability type='ccw'>
|
||||
<cssid>0x0</cssid>
|
||||
<ssid>0x0</ssid>
|
||||
<devno>0xffff</devno>
|
||||
</capability>
|
||||
</device>
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user