bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH libpciaccess] hurd: device_open the pre-existing pci server


From: Damien Zammit
Subject: [PATCH libpciaccess] hurd: device_open the pre-existing pci server
Date: Sat, 6 Mar 2021 15:00:00 +1100

This is a cleaned up version of my previous patch.
It fixes a bug by sorting the device array by B/D/F for all backends.
(It assumes only domain 0000 exists and I think that assumption is also made 
elsewhere).

---
 src/common_init.c |  37 ++++++++++++++++
 src/hurd_pci.c    | 108 +++++++++++++++++++++++++++-------------------
 2 files changed, 101 insertions(+), 44 deletions(-)

diff --git a/src/common_init.c b/src/common_init.c
index 1940cff..14f0c6b 100644
--- a/src/common_init.c
+++ b/src/common_init.c
@@ -40,6 +40,40 @@
 
 _pci_hidden struct pci_system * pci_sys;
 
+static int
+sort_devices(void)
+{
+    int bus, dev, func;
+    struct pci_device_private *sorted;
+    struct pci_device_private *device;
+    struct pci_device_private *tmpdev;
+
+    sorted = calloc(pci_sys->num_devices, sizeof(struct pci_device_private));
+    if (!sorted) {
+        return ENOMEM;
+    }
+
+    tmpdev = sorted;
+
+    for (bus = 0; bus < 256; bus++) {
+        for (dev = 0; dev < 32; dev++) {
+            for (func = 0; func < 8; func++) {
+                device = (struct pci_device_private *)
+                         pci_device_find_by_slot(0, bus, dev, func);
+                if (device) {
+                    *tmpdev = *device;
+                    tmpdev++;
+                }
+            }
+        }
+    }
+    if (pci_sys->devices) {
+        free(pci_sys->devices);
+        pci_sys->devices = sorted;
+    }
+    return 0;
+}
+
 /**
  * Initialize the PCI subsystem for access.
  *
@@ -72,6 +106,9 @@ pci_system_init( void )
 #else
 # error "Unsupported OS"
 #endif
+    if (!err) {
+        err = sort_devices();
+    }
 
     return err;
 }
diff --git a/src/hurd_pci.c b/src/hurd_pci.c
index ada7af8..ad6883a 100644
--- a/src/hurd_pci.c
+++ b/src/hurd_pci.c
@@ -33,9 +33,12 @@
 #include <sys/mman.h>
 #include <string.h>
 #include <strings.h>
+#include <mach.h>
 #include <hurd.h>
 #include <hurd/pci.h>
 #include <hurd/paths.h>
+#include <hurd/fs.h>
+#include <device/device.h>
 
 #include "x86_pci.h"
 #include "pciaccess.h"
@@ -302,26 +305,52 @@ pci_device_hurd_destroy(struct pci_device *dev)
     mach_port_deallocate (mach_task_self (), d->device_port);
 }
 
+static struct dirent *
+simple_readdir(mach_port_t port, uint32_t *first_entry)
+{
+    struct dirent *e;
+    char *data;
+    int nentries = 0;
+    vm_size_t size;
+
+    dir_readdir (port, &data, &size, *first_entry, 1, 0, &nentries);
+
+    if (nentries == 0) {
+       return NULL;
+    }
+
+    *first_entry = *first_entry + 1;
+    e = (struct dirent *)(data+4);
+    return e;
+}
+
 /* Walk through the FS tree to see what is allowed for us */
 static int
-enum_devices(const char *parent, int domain,
-    int bus, int dev, int func, tree_level lev)
+enum_devices(mach_port_t pci_port, mach_port_t cwd_port, const char *parent, 
int domain,
+             int bus, int dev, int func, tree_level lev)
 {
     int err, ret;
-    DIR *dir;
-    struct dirent *entry;
+    struct dirent *entry = NULL;
     char path[NAME_MAX];
     char server[NAME_MAX];
-    uint32_t reg;
+    uint32_t reg, count = 0;
     size_t toread;
     mach_port_t device_port;
     struct pci_device_private *d, *devices;
 
-    dir = opendir(parent);
-    if (!dir)
-        return errno;
+    if (pci_port == MACH_PORT_NULL) {
+        return EGRATUITOUS;
+    } else {
+        if (lev > LEVEL_FUNC + 1) {
+            return 0;
+        }
+        cwd_port = file_name_lookup_under (pci_port, parent, O_DIRECTORY | 
O_RDWR | O_EXEC, 0);
+        if (cwd_port == MACH_PORT_NULL) {
+            return 0;
+        }
+    }
 
-    while ((entry = readdir(dir)) != 0) {
+    while ((entry = simple_readdir(cwd_port, &count)) != NULL) {
         snprintf(path, NAME_MAX, "%s/%s", parent, entry->d_name);
         if (entry->d_type == DT_DIR) {
             if (!strncmp(entry->d_name, ".", NAME_MAX)
@@ -331,7 +360,6 @@ enum_devices(const char *parent, int domain,
             errno = 0;
             ret = strtol(entry->d_name, 0, 16);
             if (errno) {
-                closedir(dir);
                 return errno;
             }
 
@@ -353,16 +381,12 @@ enum_devices(const char *parent, int domain,
                 func = ret;
                 break;
             default:
-                if (closedir(dir) < 0)
-                    return errno;
-                return -1;
+                return 0;
             }
 
-            err = enum_devices(path, domain, bus, dev, func, lev+1);
+            err = enum_devices(pci_port, cwd_port, path, domain, bus, dev, 
func, lev+1);
             if (err && err != EPERM && err != EACCES) {
-                if (closedir(dir) < 0)
-                    return errno;
-                return err;
+                return 0;
             }
         } else {
             if (strncmp(entry->d_name, FILE_CONFIG_NAME, NAME_MAX))
@@ -370,34 +394,27 @@ enum_devices(const char *parent, int domain,
                 continue;
 
             /* We found an available virtual device, add it to our list */
-            snprintf(server, NAME_MAX, "%s/%04x/%02x/%02x/%01u/%s",
-                     _SERVERS_BUS_PCI, domain, bus, dev, func,
+            snprintf(server, NAME_MAX, "./%04x/%02x/%02x/%01u/%s",
+                     domain, bus, dev, func,
                      entry->d_name);
-            device_port = file_name_lookup(server, 0, 0);
+            device_port = file_name_lookup_under(pci_port, server, O_RDWR, 0);
             if (device_port == MACH_PORT_NULL) {
-                closedir(dir);
-                return errno;
+                return 0;
             }
 
             toread = sizeof(reg);
             err = pciclient_cfg_read(device_port, PCI_VENDOR_ID, (char*)&reg,
                                      &toread);
             if (err) {
-                if (closedir(dir) < 0)
-                    return errno;
                 return err;
             }
             if (toread != sizeof(reg)) {
-                if (closedir(dir) < 0)
-                    return errno;
                 return -1;
             }
 
             devices = realloc(pci_sys->devices, (pci_sys->num_devices + 1)
                               * sizeof(struct pci_device_private));
             if (!devices) {
-                if (closedir(dir) < 0)
-                    return errno;
                 return ENOMEM;
             }
 
@@ -415,13 +432,9 @@ enum_devices(const char *parent, int domain,
             err = pciclient_cfg_read(device_port, PCI_CLASS, (char*)&reg,
                                      &toread);
             if (err) {
-                if (closedir(dir) < 0)
-                    return errno;
                 return err;
             }
             if (toread != sizeof(reg)) {
-                if (closedir(dir) < 0)
-                    return errno;
                 return -1;
             }
 
@@ -432,13 +445,9 @@ enum_devices(const char *parent, int domain,
             err = pciclient_cfg_read(device_port, PCI_SUB_VENDOR_ID,
                                      (char*)&reg, &toread);
             if (err) {
-                if (closedir(dir) < 0)
-                    return errno;
                 return err;
             }
             if (toread != sizeof(reg)) {
-                if (closedir(dir) < 0)
-                    return errno;
                 return -1;
             }
 
@@ -452,9 +461,6 @@ enum_devices(const char *parent, int domain,
         }
     }
 
-    if (closedir(dir) < 0)
-        return errno;
-
     return 0;
 }
 
@@ -489,6 +495,8 @@ pci_system_hurd_create(void)
 {
     int err;
     struct pci_system_hurd *pci_sys_hurd;
+    mach_port_t device_master;
+    mach_port_t root, pci_server_port = MACH_PORT_NULL;
 
     if (&netfs_server_name && netfs_server_name
         && !strcmp(netfs_server_name, "pci-arbiter")) {
@@ -513,12 +521,24 @@ pci_system_hurd_create(void)
     pci_sys->methods = &hurd_pci_methods;
 
     pci_sys->num_devices = 0;
-    err = enum_devices(_SERVERS_BUS_PCI, -1, -1, -1, -1, LEVEL_DOMAIN);
+
+    if (! (err = get_privileged_ports (NULL, &device_master)) && 
(device_master != MACH_PORT_NULL)) {
+        err = device_open (device_master, D_READ|D_WRITE, "pci", 
&pci_server_port);
+        if (err) {
+            pci_system_cleanup();
+            return err;
+        }
+        root = file_name_lookup_under (pci_server_port, ".", O_DIRECTORY | 
O_RDWR | O_EXEC, 0);
+        if (!root) {
+            pci_system_cleanup();
+            return errno;
+        }
+        err = enum_devices(pci_server_port, root, ".", -1, -1, -1, -1, 
LEVEL_DOMAIN);
+    }
+
     if (err) {
-      /* There was an error, but we don't know which devices have been
-       * initialized correctly, so call cleanup to free whatever is allocated 
*/
-      pci_system_cleanup();
-      return err;
+        pci_system_cleanup();
+        return err;
     }
 
     return 0;
-- 
2.30.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]