提交 b0ffd938 编写于 作者: B Bjoern Walk 提交者: John Ferlan

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: NBoris Fiuczynski <fiuczy@linux.vnet.ibm.com>
Signed-off-by: NBjoern Walk <bwalk@linux.vnet.ibm.com>
上级 a9b98ecf
...@@ -318,6 +318,37 @@ ...@@ -318,6 +318,37 @@
</data> </data>
</define> </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"> <define name="cpuset">
<data type="string"> <data type="string">
<param name="pattern">([0-9]+(-[0-9]+)?|\^[0-9]+)(,([0-9]+(-[0-9]+)?|\^[0-9]+))*</param> <param name="pattern">([0-9]+(-[0-9]+)?|\^[0-9]+)(,([0-9]+(-[0-9]+)?|\^[0-9]+))*</param>
......
...@@ -5775,36 +5775,6 @@ ...@@ -5775,36 +5775,6 @@
</element> </element>
<empty/> <empty/>
</define> </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"> <define name="panic">
<element name="panic"> <element name="panic">
<optional> <optional>
......
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
<ref name="capstorage"/> <ref name="capstorage"/>
<ref name="capdrm"/> <ref name="capdrm"/>
<ref name="capmdev"/> <ref name="capmdev"/>
<ref name="capccwdev"/>
</choice> </choice>
</element> </element>
</define> </define>
...@@ -597,6 +598,21 @@ ...@@ -597,6 +598,21 @@
</element> </element>
</define> </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'> <define name='address'>
<element name='address'> <element name='address'>
<attribute name='domain'><ref name='hexuint'/></attribute> <attribute name='domain'><ref name='hexuint'/></attribute>
......
...@@ -62,7 +62,8 @@ VIR_ENUM_IMPL(virNodeDevCap, VIR_NODE_DEV_CAP_LAST, ...@@ -62,7 +62,8 @@ VIR_ENUM_IMPL(virNodeDevCap, VIR_NODE_DEV_CAP_LAST,
"scsi_generic", "scsi_generic",
"drm", "drm",
"mdev_types", "mdev_types",
"mdev") "mdev",
"ccw")
VIR_ENUM_IMPL(virNodeDevNetCap, VIR_NODE_DEV_CAP_NET_LAST, VIR_ENUM_IMPL(virNodeDevNetCap, VIR_NODE_DEV_CAP_NET_LAST,
"80203", "80203",
...@@ -581,6 +582,14 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def) ...@@ -581,6 +582,14 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def)
virBufferAsprintf(&buf, "<iommuGroup number='%u'/>\n", virBufferAsprintf(&buf, "<iommuGroup number='%u'/>\n",
data->mdev.iommuGroupNumber); data->mdev.iommuGroupNumber);
break; 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_MDEV_TYPES:
case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_FC_HOST:
case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_VPORTS:
...@@ -717,6 +726,66 @@ virNodeDevCapDRMParseXML(xmlXPathContextPtr ctxt, ...@@ -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 static int
virNodeDevCapStorageParseXML(xmlXPathContextPtr ctxt, virNodeDevCapStorageParseXML(xmlXPathContextPtr ctxt,
virNodeDeviceDefPtr def, virNodeDeviceDefPtr def,
...@@ -1754,6 +1823,9 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt, ...@@ -1754,6 +1823,9 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
case VIR_NODE_DEV_CAP_MDEV: case VIR_NODE_DEV_CAP_MDEV:
ret = virNodeDevCapMdevParseXML(ctxt, def, node, &caps->data.mdev); ret = virNodeDevCapMdevParseXML(ctxt, def, node, &caps->data.mdev);
break; 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_MDEV_TYPES:
case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_FC_HOST:
case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_VPORTS:
...@@ -2083,6 +2155,7 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps) ...@@ -2083,6 +2155,7 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
case VIR_NODE_DEV_CAP_DRM: case VIR_NODE_DEV_CAP_DRM:
case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_FC_HOST:
case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_VPORTS:
case VIR_NODE_DEV_CAP_CCW_DEV:
case VIR_NODE_DEV_CAP_LAST: case VIR_NODE_DEV_CAP_LAST:
/* This case is here to shutup the compiler */ /* This case is here to shutup the compiler */
break; break;
......
...@@ -66,6 +66,7 @@ typedef enum { ...@@ -66,6 +66,7 @@ typedef enum {
VIR_NODE_DEV_CAP_DRM, /* DRM device */ VIR_NODE_DEV_CAP_DRM, /* DRM device */
VIR_NODE_DEV_CAP_MDEV_TYPES, /* Device capable of mediated devices */ VIR_NODE_DEV_CAP_MDEV_TYPES, /* Device capable of mediated devices */
VIR_NODE_DEV_CAP_MDEV, /* Mediated device */ VIR_NODE_DEV_CAP_MDEV, /* Mediated device */
VIR_NODE_DEV_CAP_CCW_DEV, /* s390 CCW device */
VIR_NODE_DEV_CAP_LAST VIR_NODE_DEV_CAP_LAST
} virNodeDevCapType; } virNodeDevCapType;
...@@ -267,6 +268,14 @@ struct _virNodeDevCapDRM { ...@@ -267,6 +268,14 @@ struct _virNodeDevCapDRM {
virNodeDevDRMType type; 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 struct _virNodeDevCapData virNodeDevCapData;
typedef virNodeDevCapData *virNodeDevCapDataPtr; typedef virNodeDevCapData *virNodeDevCapDataPtr;
struct _virNodeDevCapData { struct _virNodeDevCapData {
...@@ -284,6 +293,7 @@ struct _virNodeDevCapData { ...@@ -284,6 +293,7 @@ struct _virNodeDevCapData {
virNodeDevCapSCSIGeneric sg; virNodeDevCapSCSIGeneric sg;
virNodeDevCapDRM drm; virNodeDevCapDRM drm;
virNodeDevCapMdev mdev; virNodeDevCapMdev mdev;
virNodeDevCapCCW ccw_dev;
}; };
}; };
......
...@@ -84,6 +84,7 @@ static int update_caps(virNodeDeviceObjPtr dev) ...@@ -84,6 +84,7 @@ static int update_caps(virNodeDeviceObjPtr dev)
case VIR_NODE_DEV_CAP_SCSI_GENERIC: case VIR_NODE_DEV_CAP_SCSI_GENERIC:
case VIR_NODE_DEV_CAP_MDEV_TYPES: case VIR_NODE_DEV_CAP_MDEV_TYPES:
case VIR_NODE_DEV_CAP_MDEV: case VIR_NODE_DEV_CAP_MDEV:
case VIR_NODE_DEV_CAP_CCW_DEV:
case VIR_NODE_DEV_CAP_LAST: case VIR_NODE_DEV_CAP_LAST:
break; break;
} }
......
...@@ -1104,6 +1104,36 @@ udevProcessMediatedDevice(struct udev_device *dev, ...@@ -1104,6 +1104,36 @@ udevProcessMediatedDevice(struct udev_device *dev,
return ret; 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 static int
udevGetDeviceNodes(struct udev_device *device, udevGetDeviceNodes(struct udev_device *device,
virNodeDeviceDefPtr def) virNodeDeviceDefPtr def)
...@@ -1172,8 +1202,8 @@ udevGetDeviceType(struct udev_device *device, ...@@ -1172,8 +1202,8 @@ udevGetDeviceType(struct udev_device *device,
if (udevHasDeviceProperty(device, "INTERFACE")) if (udevHasDeviceProperty(device, "INTERFACE"))
*type = VIR_NODE_DEV_CAP_NET; *type = VIR_NODE_DEV_CAP_NET;
/* Neither SCSI generic devices nor mediated devices set DEVTYPE /* The following devices do not set the DEVTYPE property, therefore
* property, therefore we need to rely on the SUBSYSTEM property */ * we need to rely on the SUBSYSTEM property */
if (udevGetStringProperty(device, "SUBSYSTEM", &subsystem) < 0) if (udevGetStringProperty(device, "SUBSYSTEM", &subsystem) < 0)
return -1; return -1;
...@@ -1181,6 +1211,8 @@ udevGetDeviceType(struct udev_device *device, ...@@ -1181,6 +1211,8 @@ udevGetDeviceType(struct udev_device *device,
*type = VIR_NODE_DEV_CAP_SCSI_GENERIC; *type = VIR_NODE_DEV_CAP_SCSI_GENERIC;
else if (STREQ_NULLABLE(subsystem, "mdev")) else if (STREQ_NULLABLE(subsystem, "mdev"))
*type = VIR_NODE_DEV_CAP_MDEV; *type = VIR_NODE_DEV_CAP_MDEV;
else if (STREQ_NULLABLE(subsystem, "ccw"))
*type = VIR_NODE_DEV_CAP_CCW_DEV;
VIR_FREE(subsystem); VIR_FREE(subsystem);
} }
...@@ -1222,6 +1254,8 @@ static int udevGetDeviceDetails(struct udev_device *device, ...@@ -1222,6 +1254,8 @@ static int udevGetDeviceDetails(struct udev_device *device,
return udevProcessDRMDevice(device, def); return udevProcessDRMDevice(device, def);
case VIR_NODE_DEV_CAP_MDEV: case VIR_NODE_DEV_CAP_MDEV:
return udevProcessMediatedDevice(device, def); 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_MDEV_TYPES:
case VIR_NODE_DEV_CAP_SYSTEM: case VIR_NODE_DEV_CAP_SYSTEM:
case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_FC_HOST:
......
<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>
<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) ...@@ -103,6 +103,7 @@ mymain(void)
DO_TEST("drm_renderD129"); DO_TEST("drm_renderD129");
DO_TEST("pci_0000_02_10_7_mdev_types"); DO_TEST("pci_0000_02_10_7_mdev_types");
DO_TEST("mdev_3627463d_b7f0_4fea_b468_f1da537d301b"); DO_TEST("mdev_3627463d_b7f0_4fea_b468_f1da537d301b");
DO_TEST("ccw_0_0_ffff");
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
} }
......
...@@ -460,6 +460,8 @@ cmdNodeListDevices(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) ...@@ -460,6 +460,8 @@ cmdNodeListDevices(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
case VIR_NODE_DEV_CAP_MDEV: case VIR_NODE_DEV_CAP_MDEV:
flags |= VIR_CONNECT_LIST_NODE_DEVICES_CAP_MDEV; flags |= VIR_CONNECT_LIST_NODE_DEVICES_CAP_MDEV;
break; break;
case VIR_NODE_DEV_CAP_CCW_DEV:
/* enable next patch */
case VIR_NODE_DEV_CAP_LAST: case VIR_NODE_DEV_CAP_LAST:
break; break;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册