[systemd-devel] [RFC][PATCH] udev: net_id - support multi-function, multi-port enpo* device names

Tom Gundersen teg at jklm.no
Wed Apr 1 07:52:47 PDT 2015


I'd argue that having firmware labels for such devices makes no sense, but they exist, so make sure
we handle them as best as we can.
---
 src/udev/udev-builtin-net_id.c | 64 ++++++++++++++++++++++++++++--------------
 1 file changed, 43 insertions(+), 21 deletions(-)

diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index 71f3a59..1a72190 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -35,7 +35,7 @@
  * Type of names:
  *   b<number>                             -- BCMA bus core number
  *   ccw<name>                             -- CCW bus group name
- *   o<index>                              -- on-board device index number
+ *   o<index>[f<function>][d<dev_port>]    -- on-board device index number
  *   s<slot>[f<function>][d<dev_port>]     -- hotplug slot index number
  *   x<MAC>                                -- MAC address
  *   [P<domain>]p<bus>s<slot>[f<function>][d<dev_port>]
@@ -126,11 +126,38 @@ struct netnames {
         char ccw_group[IFNAMSIZ];
 };
 
+/* read the 256 bytes PCI configuration space to check the multi-function bit */
+static bool is_pci_multifunction(struct udev_device *dev) {
+        _cleanup_fclose_ FILE *f = NULL;
+        const char *filename;
+        uint8_t config[64];
+
+        filename = strjoina(udev_device_get_syspath(dev), "/config");
+        f = fopen(filename, "re");
+        if (!f)
+                return false;
+        if (fread(&config, sizeof(config), 1, f) != 1)
+                return false;
+
+        /* bit 0-6 header type, bit 7 multi/single function device */
+        if ((config[PCI_HEADER_TYPE] & 0x80) != 0)
+                return true;
+
+        return false;
+}
+
 /* retrieve on-board index number and label from firmware */
 static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
+        unsigned func, dev_port = 0;
+        size_t l;
+        char *s;
+        const char *attr;
         const char *index;
         int idx;
 
+        if (sscanf(udev_device_get_sysname(names->pcidev), "%*x:%*x:%*x.%u", &func) != 1)
+                return -ENOENT;
+
         /* ACPI _DSM  -- device specific method for naming a PCI or PCI Express device */
         index = udev_device_get_sysattr_value(names->pcidev, "acpi_index");
         /* SMBIOS type 41 -- Onboard Devices Extended Information */
@@ -141,30 +168,25 @@ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) {
         idx = strtoul(index, NULL, 0);
         if (idx <= 0)
                 return -EINVAL;
-        snprintf(names->pci_onboard, sizeof(names->pci_onboard), "o%d", idx);
 
-        names->pci_onboard_label = udev_device_get_sysattr_value(names->pcidev, "label");
-        return 0;
-}
-
-/* read the 256 bytes PCI configuration space to check the multi-function bit */
-static bool is_pci_multifunction(struct udev_device *dev) {
-        _cleanup_fclose_ FILE *f = NULL;
-        const char *filename;
-        uint8_t config[64];
+        /* kernel provided multi-device index */
+        attr = udev_device_get_sysattr_value(dev, "dev_port");
+        if (attr)
+                dev_port = strtol(attr, NULL, 10);
 
-        filename = strjoina(udev_device_get_syspath(dev), "/config");
-        f = fopen(filename, "re");
-        if (!f)
-                return false;
-        if (fread(&config, sizeof(config), 1, f) != 1)
-                return false;
+        s = names->pci_onboard;
+        l = sizeof(names->pci_onboard);
+        l = strpcpyf(&s, l, "o%d", idx);
+        if (func > 0 || is_pci_multifunction(names->pcidev))
+                l = strpcpyf(&s, l, "f%d", func);
+        if (dev_port > 0)
+                l = strpcpyf(&s, l, "d%d", dev_port);
+        if (l == 0)
+                names->pci_onboard[0] = '\0';
 
-        /* bit 0-6 header type, bit 7 multi/single function device */
-        if ((config[PCI_HEADER_TYPE] & 0x80) != 0)
-                return true;
+        names->pci_onboard_label = udev_device_get_sysattr_value(names->pcidev, "label");
 
-        return false;
+        return 0;
 }
 
 static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
-- 
2.3.4



More information about the systemd-devel mailing list