summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoan Lledó <jlledom@member.fsf.org>2019-11-24 11:17:30 +0100
committerJoan Lledó <jlledom@member.fsf.org>2019-12-27 10:40:12 +0100
commit73901e7f7c03a5cdea317fd3d36feb978ef34a02 (patch)
tree1e1813ab51f43c53808f4725d89821741f069e6a /src
parentfbd1f0fe79ba25b72635f8e36a6c33d7e0ca19f6 (diff)
Hurd: avoid using the deprecated RPC pci_get_ndevs()
Diffstat (limited to 'src')
-rw-r--r--src/hurd_pci.c153
1 files changed, 91 insertions, 62 deletions
diff --git a/src/hurd_pci.c b/src/hurd_pci.c
index 28bef16..26505f3 100644
--- a/src/hurd_pci.c
+++ b/src/hurd_pci.c
@@ -304,8 +304,8 @@ pci_device_hurd_destroy(struct pci_device *dev)
/* Walk through the FS tree to see what is allowed for us */
static int
-enum_devices(const char *parent, struct pci_device_private **device,
- int domain, int bus, int dev, int func, tree_level lev)
+enum_devices(const char *parent, int domain,
+ int bus, int dev, int func, tree_level lev)
{
int err, ret;
DIR *dir;
@@ -315,6 +315,7 @@ enum_devices(const char *parent, struct pci_device_private **device,
uint32_t reg;
size_t toread;
mach_port_t device_port;
+ struct pci_device_private *d, *devices;
dir = opendir(parent);
if (!dir)
@@ -329,8 +330,10 @@ enum_devices(const char *parent, struct pci_device_private **device,
errno = 0;
ret = strtol(entry->d_name, 0, 16);
- if (errno)
+ if (errno) {
+ closedir(dir);
return errno;
+ }
/*
* We found a valid directory.
@@ -350,14 +353,18 @@ enum_devices(const char *parent, struct pci_device_private **device,
func = ret;
break;
default:
+ if (closedir(dir) < 0)
+ return errno;
return -1;
}
- err = enum_devices(path, device, domain, bus, dev, func, lev+1);
- if (err == EPERM)
- continue;
- }
- else {
+ err = enum_devices(path, domain, bus, dev, func, lev+1);
+ if (err && err != EPERM && err != EACCES) {
+ if (closedir(dir) < 0)
+ return errno;
+ return err;
+ }
+ } else {
if (strncmp(entry->d_name, FILE_CONFIG_NAME, NAME_MAX))
/* We are looking for the config file */
continue;
@@ -367,52 +374,87 @@ enum_devices(const char *parent, struct pci_device_private **device,
_SERVERS_BUS_PCI, domain, bus, dev, func,
entry->d_name);
device_port = file_name_lookup(server, 0, 0);
- if (device_port == MACH_PORT_NULL)
+ if (device_port == MACH_PORT_NULL) {
+ closedir(dir);
return errno;
+ }
toread = sizeof(reg);
err = pciclient_cfg_read(device_port, PCI_VENDOR_ID, (char*)&reg,
&toread);
- if (err)
+ if (err) {
+ if (closedir(dir) < 0)
+ return errno;
return err;
- if (toread != sizeof(reg))
+ }
+ if (toread != sizeof(reg)) {
+ if (closedir(dir) < 0)
+ return errno;
return -1;
+ }
- (*device)->base.domain = domain;
- (*device)->base.bus = bus;
- (*device)->base.dev = dev;
- (*device)->base.func = func;
- (*device)->base.vendor_id = PCI_VENDOR(reg);
- (*device)->base.device_id = PCI_DEVICE(reg);
+ 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;
+ }
+
+ d = devices + pci_sys->num_devices;
+ memset(d, 0, sizeof(struct pci_device_private));
+
+ d->base.domain = domain;
+ d->base.bus = bus;
+ d->base.dev = dev;
+ d->base.func = func;
+ d->base.vendor_id = PCI_VENDOR(reg);
+ d->base.device_id = PCI_DEVICE(reg);
toread = sizeof(reg);
err = pciclient_cfg_read(device_port, PCI_CLASS, (char*)&reg,
&toread);
- if (err)
+ if (err) {
+ if (closedir(dir) < 0)
+ return errno;
return err;
- if (toread != sizeof(reg))
+ }
+ if (toread != sizeof(reg)) {
+ if (closedir(dir) < 0)
+ return errno;
return -1;
+ }
- (*device)->base.device_class = reg >> 8;
- (*device)->base.revision = reg & 0xFF;
+ d->base.device_class = reg >> 8;
+ d->base.revision = reg & 0xFF;
toread = sizeof(reg);
err = pciclient_cfg_read(device_port, PCI_SUB_VENDOR_ID,
(char*)&reg, &toread);
- if (err)
+ if (err) {
+ if (closedir(dir) < 0)
+ return errno;
return err;
- if (toread != sizeof(reg))
+ }
+ if (toread != sizeof(reg)) {
+ if (closedir(dir) < 0)
+ return errno;
return -1;
+ }
- (*device)->base.subvendor_id = PCI_VENDOR(reg);
- (*device)->base.subdevice_id = PCI_DEVICE(reg);
+ d->base.subvendor_id = PCI_VENDOR(reg);
+ d->base.subdevice_id = PCI_DEVICE(reg);
- (*device)->device_port = device_port;
+ d->device_port = device_port;
- (*device)++;
+ pci_sys->devices = devices;
+ pci_sys->num_devices++;
}
}
+ if (closedir(dir) < 0)
+ return errno;
+
return 0;
}
@@ -438,20 +480,28 @@ static const struct pci_system_methods hurd_pci_methods = {
.unmap_legacy = pci_device_x86_unmap_legacy,
};
+/* Get the name of the server using libpciaccess if any */
+extern char *netfs_server_name;
+#pragma weak netfs_server_name
+
_pci_hidden int
pci_system_hurd_create(void)
{
- struct pci_device_private *device;
int err;
struct pci_system_hurd *pci_sys_hurd;
- size_t ndevs;
- mach_port_t pci_server_port;
- /* If we can open pci cfg io ports on hurd,
- * we are the arbiter, therefore try x86 method first */
- err = pci_system_x86_create();
- if (!err)
- return 0;
+ if (&netfs_server_name && netfs_server_name
+ && !strcmp(netfs_server_name, "pci-arbiter")) {
+ /* We are a PCI arbiter, try the x86 way */
+ err = pci_system_x86_create();
+ if (!err)
+ return 0;
+ }
+
+ /*
+ * From this point on, we are either a client or a nested arbiter.
+ * Both will connect to a master arbiter.
+ */
pci_sys_hurd = calloc(1, sizeof(struct pci_system_hurd));
if (pci_sys_hurd == NULL) {
@@ -462,35 +512,14 @@ pci_system_hurd_create(void)
pci_sys->methods = &hurd_pci_methods;
- pci_server_port = file_name_lookup(_SERVERS_BUS_PCI, 0, 0);
- if (!pci_server_port) {
- /* Fall back to x86 access method */
- return pci_system_x86_create();
- }
-
- /* The server gives us the number of available devices for us */
- err = pci_get_ndevs (pci_server_port, &ndevs);
+ pci_sys->num_devices = 0;
+ err = enum_devices(_SERVERS_BUS_PCI, -1, -1, -1, -1, LEVEL_DOMAIN);
if (err) {
- mach_port_deallocate (mach_task_self (), pci_server_port);
- /* Fall back to x86 access method */
- return pci_system_x86_create();
+ /* 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;
}
- mach_port_deallocate (mach_task_self (), pci_server_port);
-
- pci_sys->num_devices = ndevs;
- pci_sys->devices = calloc(ndevs, sizeof(struct pci_device_private));
- if (pci_sys->devices == NULL) {
- x86_disable_io();
- free(pci_sys_hurd);
- pci_sys = NULL;
- return ENOMEM;
- }
-
- device = pci_sys->devices;
- err = enum_devices(_SERVERS_BUS_PCI, &device, -1, -1, -1, -1,
- LEVEL_DOMAIN);
- if (err)
- return pci_system_x86_create();
return 0;
}