libnvidia-container-1.12.0 added.
This commit is contained in:
parent
3d1e2eccad
commit
6f9c880ac1
|
@ -267,6 +267,7 @@ sys-libs/compiler-rt-sanitizers ~amd64
|
||||||
<sys-libs/glibc-2.35 ~amd64
|
<sys-libs/glibc-2.35 ~amd64
|
||||||
<sys-libs/ldb-1.7 ~amd64
|
<sys-libs/ldb-1.7 ~amd64
|
||||||
sys-libs/libomp ~amd64
|
sys-libs/libomp ~amd64
|
||||||
|
sys-libs/libnvidia-container ~amd64
|
||||||
sys-libs/libudev-compat ~amd64
|
sys-libs/libudev-compat ~amd64
|
||||||
<sys-libs/talloc-2.5 ~amd64
|
<sys-libs/talloc-2.5 ~amd64
|
||||||
<sys-libs/tdb-1.5 ~amd64
|
<sys-libs/tdb-1.5 ~amd64
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
DIST libnvidia-container-1.12.0.tar.gz 1397606 SHA256 29aee3f805a1d0fed0025ddc992a67e2181c001f60f9fe198aebe6f0455ee85b SHA512 fbd8beeaedea61ca57b52da7e832ad9e2c52edd20ddf0ad23e17c91b414e364fa79b5af43892369d6ff0860c66f741962f4a5ce847ee008b5017ad360ed15128 WHIRLPOOL dc41a8e83bed148e92f5a0efd02c787d130d2f28380f39bf0095b30bc13c9b8f494824261cd1e2857266234c4bf4dd32f37c3e8d49721a9c13409317a299033d
|
|
@ -0,0 +1,119 @@
|
||||||
|
diff --git a/src/pci-enum.h b/src/pci-enum.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..73b8497
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/pci-enum.h
|
||||||
|
@@ -0,0 +1,112 @@
|
||||||
|
+/*
|
||||||
|
+ * (C) Copyright IBM Corporation 2006
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti
|
||||||
|
+ *
|
||||||
|
+ * Copyright 2009 Red Hat, Inc.
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 2014 NVIDIA Corporation
|
||||||
|
+ *
|
||||||
|
+ * All Rights Reserved.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
+ * of this software and associated documentation files (the "Software"), to deal
|
||||||
|
+ * in the Software without restriction, including without limitation the rights
|
||||||
|
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
+ * copies of the Software, and to permit persons to whom the Software is
|
||||||
|
+ * furnished to do so, subject to the following conditions:
|
||||||
|
+ *
|
||||||
|
+ * The above copyright notice and this permission notice shall be included in
|
||||||
|
+ * all copies or substantial portions of the Software.
|
||||||
|
+ *
|
||||||
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
+ * THE SOFTWARE.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * pci-enum.h
|
||||||
|
+ *
|
||||||
|
+ * Based on libpciaccess/include/pciaccess.h from libpciaccess-0.12.1, which
|
||||||
|
+ * can be found here:
|
||||||
|
+ *
|
||||||
|
+ * http://cgit.freedesktop.org/xorg/lib/libpciaccess
|
||||||
|
+ *
|
||||||
|
+ * Original authors: Ian Romanick <idr@us.ibm.com>, Paulo R. Zanoni,
|
||||||
|
+ * Tiago Vignatti
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef PCI_ENUM_H
|
||||||
|
+#define PCI_ENUM_H
|
||||||
|
+
|
||||||
|
+#include <inttypes.h>
|
||||||
|
+
|
||||||
|
+struct pci_id_match;
|
||||||
|
+
|
||||||
|
+#ifdef __cplusplus
|
||||||
|
+extern "C" {
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+int pci_enum_match_id(struct pci_id_match *);
|
||||||
|
+
|
||||||
|
+#ifdef __cplusplus
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#define PCI_MATCH_ANY (~0U)
|
||||||
|
+
|
||||||
|
+#define PCI_BASE_CLASS_MASK 0xff00
|
||||||
|
+#define PCI_SUB_CLASS_MASK 0x00ff
|
||||||
|
+#define PCI_FULL_CLASS_MASK PCI_BASE_CLASS_MASK | PCI_SUB_CLASS_MASK
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Compare two PCI ID values (either vendor or device). This is used
|
||||||
|
+ * internally to compare the fields of pci_id_match to the fields of
|
||||||
|
+ * pci_device.
|
||||||
|
+ */
|
||||||
|
+#define PCI_ID_COMPARE(a, b) \
|
||||||
|
+ (((a) == PCI_MATCH_ANY) || ((a) == (b)))
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ */
|
||||||
|
+struct pci_id_match {
|
||||||
|
+ /**
|
||||||
|
+ * Device/vendor matching controls
|
||||||
|
+ *
|
||||||
|
+ * Control the search based on the device, vendor, subdevice, or subvendor
|
||||||
|
+ * IDs. Setting any of these fields to PCI_MATCH_ANY will cause the field
|
||||||
|
+ * to not be used in the comparison.
|
||||||
|
+ */
|
||||||
|
+ /*@{*/
|
||||||
|
+ uint32_t vendor_id;
|
||||||
|
+ uint32_t device_id;
|
||||||
|
+ uint32_t subvendor_id;
|
||||||
|
+ uint32_t subdevice_id;
|
||||||
|
+ /*@}*/
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Device class matching controls
|
||||||
|
+ *
|
||||||
|
+ * Device's class and subclass. The class is at bits [15:8], subclass is at
|
||||||
|
+ * bits [7:0].
|
||||||
|
+ */
|
||||||
|
+ /*@{*/
|
||||||
|
+ uint16_t device_class;
|
||||||
|
+ uint16_t device_class_mask;
|
||||||
|
+ /*@}*/
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Match results
|
||||||
|
+ *
|
||||||
|
+ * Specifies the number of devices found that match this criteria.
|
||||||
|
+ */
|
||||||
|
+ /*@{*/
|
||||||
|
+ uint16_t num_matches;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#endif /* PCI_ENUM_H */
|
||||||
|
\ No newline at end of file
|
|
@ -0,0 +1,536 @@
|
||||||
|
diff --git a/src/pci-sysfs.c b/src/pci-sysfs.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..210bf40
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/pci-sysfs.c
|
||||||
|
@@ -0,0 +1,529 @@
|
||||||
|
+/*
|
||||||
|
+ * (C) Copyright IBM Corporation 2006
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 2014-2018 NVIDIA Corporation
|
||||||
|
+ *
|
||||||
|
+ * All Rights Reserved.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
+ * of this software and associated documentation files (the "Software"), to deal
|
||||||
|
+ * in the Software without restriction, including without limitation the rights
|
||||||
|
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
+ * copies of the Software, and to permit persons to whom the Software is
|
||||||
|
+ * furnished to do so, subject to the following conditions:
|
||||||
|
+ *
|
||||||
|
+ * The above copyright notice and this permission notice shall be included in
|
||||||
|
+ * all copies or substantial portions of the Software.
|
||||||
|
+ *
|
||||||
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
+ * THE SOFTWARE.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * pcienum-sysfs.c
|
||||||
|
+ *
|
||||||
|
+ * Based on libpciaccess/src/linux_sysfs.c from libpciaccess-0.12.1, which was
|
||||||
|
+ * found here:
|
||||||
|
+ *
|
||||||
|
+ * http://cgit.freedesktop.org/xorg/lib/libpciaccess
|
||||||
|
+ *
|
||||||
|
+ * Access PCI subsystem using Linux's sysfs interface. This interface is
|
||||||
|
+ * available starting somewhere in the late 2.5.x kernel phase, and is the
|
||||||
|
+ * preferred method on all 2.6.x kernels.
|
||||||
|
+ *
|
||||||
|
+ * Original author: Ian Romanick <idr@us.ibm.com>
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#if defined(NV_LINUX)
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <fcntl.h>
|
||||||
|
+#include <sys/mman.h>
|
||||||
|
+#include <dirent.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <sys/time.h>
|
||||||
|
+#include <time.h>
|
||||||
|
+#include <limits.h>
|
||||||
|
+
|
||||||
|
+#include "pci-enum.h"
|
||||||
|
+#include "pci-sysfs.h"
|
||||||
|
+
|
||||||
|
+#define SYS_BUS_PCI "/sys/bus/pci/"
|
||||||
|
+#define SYS_BUS_PCI_DEVICES SYS_BUS_PCI "devices"
|
||||||
|
+#define SYS_BUS_PCI_RESCAN SYS_BUS_PCI "rescan"
|
||||||
|
+#define PCI_DBDF_FORMAT "%04x:%02x:%02x.%1u"
|
||||||
|
+#define SYSFS_PCI_BRIDGE_RESCAN_FMT SYS_BUS_PCI_DEVICES "/" PCI_DBDF_FORMAT "/rescan"
|
||||||
|
+#define SYSFS_RESCAN_STRING "1\n"
|
||||||
|
+#define SYSFS_RESCAN_STRING_SIZE 2
|
||||||
|
+#define PCI_CAP_TTL_MAX 20
|
||||||
|
+#define SYSFS_PATH_SIZE 256
|
||||||
|
+
|
||||||
|
+#define BAIL_ON_IO_ERR(buf, err, cnt, action) \
|
||||||
|
+do { \
|
||||||
|
+ if (((err) != 0) || ((cnt) < sizeof(buf))) \
|
||||||
|
+ { \
|
||||||
|
+ (err) = ((err) == 0) ? EIO : (err); \
|
||||||
|
+ action; \
|
||||||
|
+ } \
|
||||||
|
+} while (0)
|
||||||
|
+
|
||||||
|
+static int pci_sysfs_read_cfg(uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, void *,
|
||||||
|
+ uint16_t size, uint16_t *);
|
||||||
|
+
|
||||||
|
+static int find_matches(struct pci_id_match *match);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Attempt to access PCI subsystem using Linux's sysfs interface to enumerate
|
||||||
|
+ * the matched devices.
|
||||||
|
+ */
|
||||||
|
+int
|
||||||
|
+pci_enum_match_id(struct pci_id_match *match)
|
||||||
|
+{
|
||||||
|
+ int err = 0;
|
||||||
|
+ struct stat st;
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If the directory "/sys/bus/pci/devices" exists, then the PCI subsystem
|
||||||
|
+ * can be accessed using this interface.
|
||||||
|
+ */
|
||||||
|
+ match->num_matches = 0;
|
||||||
|
+ if (stat(SYS_BUS_PCI_DEVICES, &st) == 0)
|
||||||
|
+ {
|
||||||
|
+ err = find_matches(match);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ err = errno;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * The sysfs lookup method uses the directory entries in /sys/bus/pci/devices
|
||||||
|
+ * to enumerate all PCI devices, and then uses a file in each that is mapped to
|
||||||
|
+ * the device's PCI config space to extract the data to match against.
|
||||||
|
+ */
|
||||||
|
+static int
|
||||||
|
+find_matches(struct pci_id_match *match)
|
||||||
|
+{
|
||||||
|
+ struct dirent *d;
|
||||||
|
+ DIR *sysfs_pci_dir;
|
||||||
|
+ int err = 0;
|
||||||
|
+
|
||||||
|
+ sysfs_pci_dir = opendir(SYS_BUS_PCI_DEVICES);
|
||||||
|
+ if (sysfs_pci_dir == NULL)
|
||||||
|
+ {
|
||||||
|
+ return errno;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while ((d = readdir(sysfs_pci_dir)) != NULL)
|
||||||
|
+ {
|
||||||
|
+ uint8_t config[48];
|
||||||
|
+ uint16_t bytes;
|
||||||
|
+ unsigned dom, bus, dev, func;
|
||||||
|
+ uint16_t vendor_id, device_id, subvendor_id, subdevice_id;
|
||||||
|
+ uint16_t device_class;
|
||||||
|
+
|
||||||
|
+ /* Ignore the . and .. dirents */
|
||||||
|
+ if ((strcmp(d->d_name, ".") == 0) || (strcmp(d->d_name, "..") == 0))
|
||||||
|
+ {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sscanf(d->d_name, PCI_DBDF_FORMAT,
|
||||||
|
+ & dom, & bus, & dev, & func);
|
||||||
|
+
|
||||||
|
+ err = pci_sysfs_read_cfg(dom, bus, dev, func, 0, config, 48, & bytes);
|
||||||
|
+ if ((bytes == 48) && !err)
|
||||||
|
+ {
|
||||||
|
+ vendor_id = (uint16_t)config[0] + ((uint16_t)config[1] << 8);
|
||||||
|
+ device_id = (uint16_t)config[2] + ((uint16_t)config[3] << 8);
|
||||||
|
+ device_class = (uint16_t)config[10] +
|
||||||
|
+ ((uint16_t)config[11] << 8);
|
||||||
|
+ subvendor_id = (uint16_t)config[44] +
|
||||||
|
+ ((uint16_t)config[45] << 8);
|
||||||
|
+ subdevice_id = (uint16_t)config[46] +
|
||||||
|
+ ((uint16_t)config[47] << 8);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * This logic, originally in common_iterator.c, will tell if
|
||||||
|
+ * this device is a match for the search criteria.
|
||||||
|
+ */
|
||||||
|
+ if (PCI_ID_COMPARE(match->vendor_id, vendor_id) &&
|
||||||
|
+ PCI_ID_COMPARE(match->device_id, device_id) &&
|
||||||
|
+ PCI_ID_COMPARE(match->subvendor_id, subvendor_id) &&
|
||||||
|
+ PCI_ID_COMPARE(match->subdevice_id, subdevice_id) &&
|
||||||
|
+ ((device_class & match->device_class_mask) ==
|
||||||
|
+ match->device_class))
|
||||||
|
+ {
|
||||||
|
+ match->num_matches++;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (err)
|
||||||
|
+ {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ closedir(sysfs_pci_dir);
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+pci_sysfs_read_cfg(uint16_t domain, uint16_t bus, uint16_t device,
|
||||||
|
+ uint16_t function, uint16_t off, void *data,
|
||||||
|
+ uint16_t size, uint16_t *bytes_read)
|
||||||
|
+{
|
||||||
|
+ char name[SYSFS_PATH_SIZE];
|
||||||
|
+ uint16_t temp_size = size;
|
||||||
|
+ int err = 0;
|
||||||
|
+ int fd;
|
||||||
|
+ char *data_bytes = data;
|
||||||
|
+
|
||||||
|
+ if (bytes_read != NULL)
|
||||||
|
+ {
|
||||||
|
+ *bytes_read = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Each device has a directory under sysfs. Within that directory there
|
||||||
|
+ * is a file named "config". This file used to access the PCI config
|
||||||
|
+ * space. It is used here to obtain most of the information about the
|
||||||
|
+ * device.
|
||||||
|
+ */
|
||||||
|
+ snprintf(name, SYSFS_PATH_SIZE - 1, "%s/" PCI_DBDF_FORMAT "/config",
|
||||||
|
+ SYS_BUS_PCI_DEVICES, domain, bus, device, function);
|
||||||
|
+
|
||||||
|
+ fd = open(name, O_RDONLY);
|
||||||
|
+ if (fd < 0)
|
||||||
|
+ {
|
||||||
|
+ return errno;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (off != 0)
|
||||||
|
+ {
|
||||||
|
+ if (lseek(fd, (off_t) off, SEEK_SET) < 0)
|
||||||
|
+ {
|
||||||
|
+ close(fd);
|
||||||
|
+ return errno;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while (temp_size > 0)
|
||||||
|
+ {
|
||||||
|
+ const ssize_t bytes = read(fd, data_bytes, temp_size);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If zero bytes were read, then we assume it's the end of the
|
||||||
|
+ * config file.
|
||||||
|
+ */
|
||||||
|
+ if (bytes <= 0)
|
||||||
|
+ {
|
||||||
|
+ err = errno;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ temp_size -= bytes;
|
||||||
|
+ data_bytes += bytes;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (bytes_read != NULL)
|
||||||
|
+ {
|
||||||
|
+ *bytes_read = size - temp_size;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ close(fd);
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+pci_sysfs_write_cfg(uint16_t domain, uint16_t bus, uint16_t device,
|
||||||
|
+ uint16_t function, uint16_t off, void *data,
|
||||||
|
+ uint16_t size, uint16_t *bytes_written)
|
||||||
|
+{
|
||||||
|
+ char name[SYSFS_PATH_SIZE];
|
||||||
|
+ uint16_t temp_size = size;
|
||||||
|
+ int err = 0;
|
||||||
|
+ int fd;
|
||||||
|
+ char *data_bytes = data;
|
||||||
|
+
|
||||||
|
+ if (bytes_written != NULL)
|
||||||
|
+ {
|
||||||
|
+ *bytes_written = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Each device has a directory under sysfs. Within that directory there
|
||||||
|
+ * is a file named "config". This file used to access the PCI config
|
||||||
|
+ * space.
|
||||||
|
+ */
|
||||||
|
+ snprintf(name, SYSFS_PATH_SIZE - 1, "%s/" PCI_DBDF_FORMAT "/config",
|
||||||
|
+ SYS_BUS_PCI_DEVICES, domain, bus, device, function);
|
||||||
|
+
|
||||||
|
+ fd = open(name, O_WRONLY);
|
||||||
|
+ if (fd < 0)
|
||||||
|
+ {
|
||||||
|
+ return errno;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (off != 0)
|
||||||
|
+ {
|
||||||
|
+ if (lseek(fd, (off_t) off, SEEK_SET) < 0)
|
||||||
|
+ {
|
||||||
|
+ close(fd);
|
||||||
|
+ return errno;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while (temp_size > 0)
|
||||||
|
+ {
|
||||||
|
+ const ssize_t bytes = write(fd, data_bytes, temp_size);
|
||||||
|
+
|
||||||
|
+ if (bytes < 0)
|
||||||
|
+ {
|
||||||
|
+ err = errno;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ /*
|
||||||
|
+ * If zero bytes were written, then we assume it's the end of the
|
||||||
|
+ * config file.
|
||||||
|
+ */
|
||||||
|
+ if (bytes == 0)
|
||||||
|
+ {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ temp_size -= bytes;
|
||||||
|
+ data_bytes += bytes;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (bytes_written != NULL)
|
||||||
|
+ {
|
||||||
|
+ *bytes_written = size - temp_size;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ close(fd);
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+pci_rescan(uint16_t domain, uint8_t bus, uint8_t slot, uint8_t function)
|
||||||
|
+{
|
||||||
|
+ char const *node;
|
||||||
|
+ char node_buf[SYSFS_PATH_SIZE];
|
||||||
|
+ int node_fd;
|
||||||
|
+ ssize_t cnt;
|
||||||
|
+
|
||||||
|
+ if ((domain | bus | slot | function) == 0)
|
||||||
|
+ {
|
||||||
|
+ /* rescan the entire PCI tree */
|
||||||
|
+ node = SYS_BUS_PCI_RESCAN;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ snprintf(node_buf, sizeof(node_buf) - 1, SYSFS_PCI_BRIDGE_RESCAN_FMT,
|
||||||
|
+ domain, bus, slot, function);
|
||||||
|
+ node = node_buf;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ node_fd = open(node, O_WRONLY);
|
||||||
|
+
|
||||||
|
+ if (node_fd < 0)
|
||||||
|
+ {
|
||||||
|
+ return errno;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ cnt = write(node_fd, SYSFS_RESCAN_STRING, SYSFS_RESCAN_STRING_SIZE);
|
||||||
|
+
|
||||||
|
+ close(node_fd);
|
||||||
|
+
|
||||||
|
+ return cnt == SYSFS_RESCAN_STRING_SIZE ? 0 : EIO;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+pci_find_parent_bridge(pci_info_t *p_gpu_info, pci_info_t *p_bridge_info)
|
||||||
|
+{
|
||||||
|
+ char gpu_path[SYSFS_PATH_SIZE];
|
||||||
|
+ char bridge_path[PATH_MAX];
|
||||||
|
+ char *p_node;
|
||||||
|
+
|
||||||
|
+ snprintf(gpu_path, SYSFS_PATH_SIZE - 1, "%s/" PCI_DBDF_FORMAT "/..", SYS_BUS_PCI_DEVICES,
|
||||||
|
+ p_gpu_info->domain, p_gpu_info->bus,
|
||||||
|
+ p_gpu_info->dev, p_gpu_info->ftn);
|
||||||
|
+
|
||||||
|
+ if (realpath(gpu_path, bridge_path) == NULL)
|
||||||
|
+ {
|
||||||
|
+ return errno;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ p_node = strrchr(bridge_path, '/');
|
||||||
|
+
|
||||||
|
+ if (p_node == NULL)
|
||||||
|
+ {
|
||||||
|
+ return ENOENT;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ++p_node;
|
||||||
|
+
|
||||||
|
+ if (sscanf(p_node, PCI_DBDF_FORMAT,
|
||||||
|
+ &p_bridge_info->domain, &p_bridge_info->bus,
|
||||||
|
+ &p_bridge_info->dev, &p_bridge_info->ftn) != 4)
|
||||||
|
+ {
|
||||||
|
+ return ENOENT;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+pci_find_pcie_caps(uint16_t domain, uint8_t bus, uint8_t device, uint8_t ftn, uint8_t *p_caps)
|
||||||
|
+{
|
||||||
|
+ unsigned ttl;
|
||||||
|
+ uint8_t off;
|
||||||
|
+ uint8_t cap_id;
|
||||||
|
+ int err = ENXIO;
|
||||||
|
+ uint16_t cnt;
|
||||||
|
+
|
||||||
|
+ for (off = PCI_CAPABILITY_LIST, ttl = PCI_CAP_TTL_MAX; ttl; --ttl)
|
||||||
|
+ {
|
||||||
|
+ err = pci_sysfs_read_cfg(domain, bus, device, ftn, off,
|
||||||
|
+ &off, sizeof(off), &cnt);
|
||||||
|
+ BAIL_ON_IO_ERR(off, err, cnt, break);
|
||||||
|
+
|
||||||
|
+ /* Capabilities must reside above the std config header */
|
||||||
|
+ if ((off < PCI_STD_HEADER_SIZEOF) || (off == 0xff))
|
||||||
|
+ {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Clear the reserved bits */
|
||||||
|
+ off &= ~3;
|
||||||
|
+
|
||||||
|
+ err = pci_sysfs_read_cfg(domain, bus, device, ftn, off + PCI_CAP_LIST_ID,
|
||||||
|
+ &cap_id, sizeof(cap_id), &cnt);
|
||||||
|
+ BAIL_ON_IO_ERR(cap_id, err, cnt, break);
|
||||||
|
+
|
||||||
|
+ if (cap_id == PCI_CAP_ID_EXP)
|
||||||
|
+ {
|
||||||
|
+ goto found;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (cap_id == 0xff)
|
||||||
|
+ {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ off += PCI_CAP_LIST_NEXT;
|
||||||
|
+ }
|
||||||
|
+ return err;
|
||||||
|
+found:
|
||||||
|
+ *p_caps = off;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+pci_bridge_link_set_enable(uint16_t domain, uint8_t bus, uint8_t device, uint8_t ftn, int enable)
|
||||||
|
+{
|
||||||
|
+ uint8_t pcie_caps = 0;
|
||||||
|
+ uint16_t reg;
|
||||||
|
+ uint32_t cap_reg;
|
||||||
|
+ uint16_t cnt;
|
||||||
|
+ int err;
|
||||||
|
+ struct timeval start;
|
||||||
|
+ struct timeval curr;
|
||||||
|
+ struct timeval diff;
|
||||||
|
+ struct timespec delay = {0, PCI_LINK_DELAY_NS};
|
||||||
|
+ struct timespec dlllar_disable_delay = {0, PCI_LINK_DLLLAR_DISABLE_DELAY_NS};
|
||||||
|
+
|
||||||
|
+ err = pci_find_pcie_caps(domain, bus, device, ftn, &pcie_caps);
|
||||||
|
+
|
||||||
|
+ if (err != 0)
|
||||||
|
+ {
|
||||||
|
+ return err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ err = pci_sysfs_read_cfg(domain, bus, device, ftn, pcie_caps + PCI_EXP_LNKCTL,
|
||||||
|
+ ®, sizeof(reg), &cnt);
|
||||||
|
+ BAIL_ON_IO_ERR(reg, err, cnt, return err);
|
||||||
|
+
|
||||||
|
+ if (enable)
|
||||||
|
+ {
|
||||||
|
+ reg &= ~PCI_EXP_LNKCTL_LD;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ reg |= PCI_EXP_LNKCTL_LD;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ err = pci_sysfs_write_cfg(domain, bus, device, ftn, pcie_caps + PCI_EXP_LNKCTL,
|
||||||
|
+ ®, sizeof(reg), &cnt);
|
||||||
|
+ BAIL_ON_IO_ERR(reg, err, cnt, return err);
|
||||||
|
+
|
||||||
|
+ if (enable)
|
||||||
|
+ {
|
||||||
|
+ /*
|
||||||
|
+ * Data Link Layer Link Active Reporting must be capable for
|
||||||
|
+ * zero power capable downstream port. But old controller might
|
||||||
|
+ * not implement it. In this case, we wait for 30 ms.
|
||||||
|
+ */
|
||||||
|
+ err = pci_sysfs_read_cfg(domain, bus, device, ftn, pcie_caps + PCI_EXP_LNKCAP,
|
||||||
|
+ &cap_reg, sizeof(cap_reg), &cnt);
|
||||||
|
+ BAIL_ON_IO_ERR(cap_reg, err, cnt, return err);
|
||||||
|
+
|
||||||
|
+ if (cap_reg & PCI_EXP_LNKCAP_DLLLARC)
|
||||||
|
+ {
|
||||||
|
+ /* wait for the link to go up and then sleep for 100 ms */
|
||||||
|
+
|
||||||
|
+ gettimeofday(&start, NULL);
|
||||||
|
+
|
||||||
|
+ for (;;)
|
||||||
|
+ {
|
||||||
|
+ err = pci_sysfs_read_cfg(domain, bus, device, ftn, pcie_caps + PCI_EXP_LNKSTA,
|
||||||
|
+ ®, sizeof(reg), &cnt);
|
||||||
|
+ BAIL_ON_IO_ERR(reg, err, cnt, return err);
|
||||||
|
+
|
||||||
|
+ if ((reg & PCI_EXP_LNKSTA_DLLLA) != 0)
|
||||||
|
+ {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ gettimeofday(&curr, NULL);
|
||||||
|
+ timersub(&curr, &start, &diff);
|
||||||
|
+
|
||||||
|
+ if ((diff.tv_sec > 0) || (diff.tv_usec >= PCI_LINK_WAIT_US))
|
||||||
|
+ {
|
||||||
|
+ return ETIME;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ /*
|
||||||
|
+ * Measured the time on DGX1 for link to become established in a bridge,
|
||||||
|
+ * where the DLLLA reporting is supported and its approximately ~9ms,
|
||||||
|
+ * so wait for 30ms where DLLLA reporting is not supported.
|
||||||
|
+ */
|
||||||
|
+ PCI_NANOSLEEP(&dlllar_disable_delay, NULL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ PCI_NANOSLEEP(&delay, NULL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif /* defined(NV_LINUX) */
|
||||||
|
\ No newline at end of file
|
|
@ -0,0 +1,92 @@
|
||||||
|
diff --git a/src/pci-sysfs.h b/src/pci-sysfs.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..1fc695b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/pci-sysfs.h
|
||||||
|
@@ -0,0 +1,85 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2016-2018, NVIDIA CORPORATION.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person
|
||||||
|
+ * obtaining a copy of this software and associated documentation
|
||||||
|
+ * files (the "Software"), to deal in the Software without
|
||||||
|
+ * restriction, including without limitation the rights to use, copy,
|
||||||
|
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
+ * of the Software, and to permit persons to whom the Software is
|
||||||
|
+ * furnished to do so, subject to the following conditions:
|
||||||
|
+ *
|
||||||
|
+ * The above copyright notice and this permission notice shall be
|
||||||
|
+ * included in all copies or substantial portions of the Software.
|
||||||
|
+ *
|
||||||
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
+ * SOFTWARE.
|
||||||
|
+ *
|
||||||
|
+ * This file provides utility functions on Linux for interfacing
|
||||||
|
+ * with the sysfs/PCI kernel facility.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef __PCI_SYSFS_H__
|
||||||
|
+#define __PCI_SYSFS_H__
|
||||||
|
+
|
||||||
|
+#if defined(NV_LINUX)
|
||||||
|
+
|
||||||
|
+#include <linux/pci.h>
|
||||||
|
+
|
||||||
|
+#if !defined(PCI_STD_HEADER_SIZEOF)
|
||||||
|
+#define PCI_STD_HEADER_SIZEOF 64
|
||||||
|
+#endif
|
||||||
|
+#if !defined(PCI_CAP_ID_EXP)
|
||||||
|
+#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
|
||||||
|
+#endif
|
||||||
|
+#if !defined(PCI_EXP_LNKCAP)
|
||||||
|
+#define PCI_EXP_LNKCAP 12 /* Link Capabilities */
|
||||||
|
+#endif
|
||||||
|
+#if !defined(PCI_EXP_LNKCAP_DLLLARC)
|
||||||
|
+#define PCI_EXP_LNKCAP_DLLLARC 0x00100000 /* Data Link Layer Link Active Reporting Capable */
|
||||||
|
+#endif
|
||||||
|
+#if !defined(PCI_EXP_LNKCTL)
|
||||||
|
+#define PCI_EXP_LNKCTL 16 /* Link Control */
|
||||||
|
+#endif
|
||||||
|
+#if !defined(PCI_EXP_LNKCTL_LD)
|
||||||
|
+#define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */
|
||||||
|
+#endif
|
||||||
|
+#if !defined(PCI_EXP_LNKSTA)
|
||||||
|
+#define PCI_EXP_LNKSTA 18 /* Link Status */
|
||||||
|
+#endif
|
||||||
|
+#if !defined(PCI_EXP_LNKSTA_DLLLA)
|
||||||
|
+#define PCI_EXP_LNKSTA_DLLLA 0x2000 /* Data Link Layer Link Active */
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#define PCI_LINK_WAIT_US 200000 /* 200 ms, must be less than 1000000 (1s) */
|
||||||
|
+#define PCI_LINK_DELAY_NS 100000000 /* 100 ms */
|
||||||
|
+#define PCI_LINK_DLLLAR_DISABLE_DELAY_NS 30000000 /* 30ms */
|
||||||
|
+
|
||||||
|
+#if (_POSIX_C_SOURCE >= 199309L)
|
||||||
|
+#define PCI_NANOSLEEP(ts, rem) nanosleep(ts, rem)
|
||||||
|
+#elif !(_POSIX_C_SOURCE >= 200809L)
|
||||||
|
+#define PCI_NANOSLEEP(ts, rem) usleep((ts)->tv_sec * 1000000 + ((ts)->tv_nsec + 999) / 1000)
|
||||||
|
+#else
|
||||||
|
+#define PCI_NANOSLEEP(ts, rem) sleep((ts)->tv_sec + ((ts)->tv_nsec + 999999999) / 1000000000)
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+typedef struct {
|
||||||
|
+ unsigned domain;
|
||||||
|
+ unsigned bus;
|
||||||
|
+ unsigned dev;
|
||||||
|
+ unsigned ftn;
|
||||||
|
+} pci_info_t;
|
||||||
|
+
|
||||||
|
+int pci_rescan(uint16_t domain, uint8_t bus, uint8_t slot, uint8_t function);
|
||||||
|
+int pci_find_parent_bridge(pci_info_t *p_gpu_info, pci_info_t *p_bridge_info);
|
||||||
|
+int pci_bridge_link_set_enable(uint16_t domain, uint8_t bus, uint8_t device, uint8_t ftn, int enable);
|
||||||
|
+
|
||||||
|
+#endif /* NV_LINUX */
|
||||||
|
+
|
||||||
|
+#endif /* __PCI_SYSFS_H__ */
|
||||||
|
\ No newline at end of file
|
|
@ -0,0 +1,801 @@
|
||||||
|
diff --git a/src/nvidia-modprobe-utils.c b/src/nvidia-modprobe-utils.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..0f97cf9
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/nvidia-modprobe-utils.c
|
||||||
|
@@ -0,0 +1,794 @@
|
||||||
|
+
|
||||||
|
+#if defined(NV_LINUX)
|
||||||
|
+
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <sys/wait.h>
|
||||||
|
+#include <fcntl.h>
|
||||||
|
+
|
||||||
|
+#include "nvidia-modprobe-utils.h"
|
||||||
|
+#include "pci-enum.h"
|
||||||
|
+
|
||||||
|
+#define NV_PROC_MODPROBE_PATH "/proc/sys/kernel/modprobe"
|
||||||
|
+#define NV_PROC_MODULES_PATH "/proc/modules"
|
||||||
|
+#define NV_PROC_DEVICES_PATH "/proc/devices"
|
||||||
|
+
|
||||||
|
+#define NV_PROC_MODPROBE_PATH_MAX 1024
|
||||||
|
+#define NV_MAX_MODULE_NAME_SIZE 16
|
||||||
|
+#define NV_MAX_PROC_REGISTRY_PATH_SIZE NV_MAX_CHARACTER_DEVICE_FILE_STRLEN
|
||||||
|
+#define NV_MAX_LINE_LENGTH 256
|
||||||
|
+
|
||||||
|
+#define NV_NVIDIA_MODULE_NAME "nvidia"
|
||||||
|
+#define NV_PROC_REGISTRY_PATH "/proc/driver/nvidia/params"
|
||||||
|
+
|
||||||
|
+#define NV_NMODULE_NVIDIA_MODULE_NAME "nvidia%d"
|
||||||
|
+#define NV_NMODULE_PROC_REGISTRY_PATH "/proc/driver/nvidia/%d/params"
|
||||||
|
+
|
||||||
|
+#define NV_UVM_MODULE_NAME "nvidia-uvm"
|
||||||
|
+#define NV_UVM_DEVICE_NAME "/dev/nvidia-uvm"
|
||||||
|
+#define NV_UVM_TOOLS_DEVICE_NAME "/dev/nvidia-uvm-tools"
|
||||||
|
+
|
||||||
|
+#define NV_MODESET_MODULE_NAME "nvidia-modeset"
|
||||||
|
+
|
||||||
|
+#define NV_VGPU_VFIO_MODULE_NAME "nvidia-vgpu-vfio"
|
||||||
|
+
|
||||||
|
+#define NV_NVLINK_MODULE_NAME "nvidia-nvlink"
|
||||||
|
+#define NV_NVLINK_PROC_PERM_PATH "/proc/driver/nvidia-nvlink/permissions"
|
||||||
|
+
|
||||||
|
+#define NV_DEVICE_FILE_MODE_MASK (S_IRWXU|S_IRWXG|S_IRWXO)
|
||||||
|
+#define NV_DEVICE_FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
|
||||||
|
+#define NV_DEVICE_FILE_UID 0
|
||||||
|
+#define NV_DEVICE_FILE_GID 0
|
||||||
|
+
|
||||||
|
+#define NV_MAKE_DEVICE(x,y) ((dev_t)((x) << 8 | (y)))
|
||||||
|
+
|
||||||
|
+#define NV_MAJOR_DEVICE_NUMBER 195
|
||||||
|
+
|
||||||
|
+#define NV_PCI_VENDOR_ID 0x10DE
|
||||||
|
+
|
||||||
|
+#define NV_MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Construct the nvidia kernel module name based on the input
|
||||||
|
+ * module instance provided. If an error occurs, the null
|
||||||
|
+ * terminator will be written to nv_module_name[0].
|
||||||
|
+ */
|
||||||
|
+static __inline__ void assign_nvidia_kernel_module_name
|
||||||
|
+(
|
||||||
|
+ char nv_module_name[NV_MAX_MODULE_NAME_SIZE],
|
||||||
|
+ int module_instance
|
||||||
|
+)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if (is_multi_module(module_instance))
|
||||||
|
+ {
|
||||||
|
+ ret = snprintf(nv_module_name, NV_MAX_MODULE_NAME_SIZE,
|
||||||
|
+ NV_NMODULE_NVIDIA_MODULE_NAME, module_instance);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ ret = snprintf(nv_module_name, NV_MAX_MODULE_NAME_SIZE,
|
||||||
|
+ NV_NVIDIA_MODULE_NAME);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ret <= 0)
|
||||||
|
+ {
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ nv_module_name[NV_MAX_MODULE_NAME_SIZE - 1] = '\0';
|
||||||
|
+
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+fail:
|
||||||
|
+
|
||||||
|
+ nv_module_name[0] = '\0';
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Construct the proc registry path name based on the input
|
||||||
|
+ * module instance provided. If an error occurs, the null
|
||||||
|
+ * terminator will be written to proc_path[0].
|
||||||
|
+ */
|
||||||
|
+static __inline__ void assign_proc_registry_path
|
||||||
|
+(
|
||||||
|
+ char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE],
|
||||||
|
+ int module_instance
|
||||||
|
+)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if (is_multi_module(module_instance))
|
||||||
|
+ {
|
||||||
|
+ ret = snprintf(proc_path, NV_MAX_PROC_REGISTRY_PATH_SIZE,
|
||||||
|
+ NV_NMODULE_PROC_REGISTRY_PATH, module_instance);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ ret = snprintf(proc_path, NV_MAX_PROC_REGISTRY_PATH_SIZE,
|
||||||
|
+ NV_PROC_REGISTRY_PATH);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ret <= 0)
|
||||||
|
+ {
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE - 1] = '\0';
|
||||||
|
+
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+fail:
|
||||||
|
+
|
||||||
|
+ proc_path[0] = '\0';
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Just like strcmp(3), except that differences between '-' and '_' are
|
||||||
|
+ * ignored. This is useful for comparing module names, where '-' and '_'
|
||||||
|
+ * are supposed to be treated interchangeably.
|
||||||
|
+ */
|
||||||
|
+static int modcmp(const char *a, const char *b)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ /* Walk both strings and compare each character */
|
||||||
|
+ for (i = 0; a[i] && b[i]; i++)
|
||||||
|
+ {
|
||||||
|
+ if (a[i] != b[i])
|
||||||
|
+ {
|
||||||
|
+ /* ignore differences between '-' and '_' */
|
||||||
|
+ if (((a[i] == '-') || (a[i] == '_')) &&
|
||||||
|
+ ((b[i] == '-') || (b[i] == '_')))
|
||||||
|
+ {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If the strings are of unequal length, only one of a[i] or b[i] == '\0'.
|
||||||
|
+ * If they are the same length, both will be '\0', and the strings match.
|
||||||
|
+ */
|
||||||
|
+ return a[i] - b[i];
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Check whether the specified module is loaded by reading
|
||||||
|
+ * NV_PROC_MODULES_PATH; returns 1 if the kernel module is loaded.
|
||||||
|
+ * Otherwise, it returns 0.
|
||||||
|
+ */
|
||||||
|
+static int is_kernel_module_loaded(const char *nv_module_name)
|
||||||
|
+{
|
||||||
|
+ FILE *fp;
|
||||||
|
+ char module_name[NV_MAX_MODULE_NAME_SIZE];
|
||||||
|
+ int module_loaded = 0;
|
||||||
|
+
|
||||||
|
+ fp = fopen(NV_PROC_MODULES_PATH, "r");
|
||||||
|
+
|
||||||
|
+ if (fp == NULL)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while (fscanf(fp, "%15s%*[^\n]\n", module_name) == 1)
|
||||||
|
+ {
|
||||||
|
+ module_name[15] = '\0';
|
||||||
|
+ if (modcmp(module_name, nv_module_name) == 0)
|
||||||
|
+ {
|
||||||
|
+ module_loaded = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fclose(fp);
|
||||||
|
+
|
||||||
|
+ return module_loaded;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Attempt to redirect STDOUT and STDERR to /dev/null.
|
||||||
|
+ *
|
||||||
|
+ * This is only for the cosmetics of silencing warnings, so do not
|
||||||
|
+ * treat any errors here as fatal.
|
||||||
|
+ */
|
||||||
|
+static void silence_current_process(void)
|
||||||
|
+{
|
||||||
|
+ int dev_null_fd = open("/dev/null", O_RDWR);
|
||||||
|
+ if (dev_null_fd < 0)
|
||||||
|
+ {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dup2(dev_null_fd, STDOUT_FILENO);
|
||||||
|
+ dup2(dev_null_fd, STDERR_FILENO);
|
||||||
|
+ close(dev_null_fd);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Attempt to load a kernel module; returns 1 if kernel module is
|
||||||
|
+ * successfully loaded. Returns 0 if the kernel module could not be
|
||||||
|
+ * loaded.
|
||||||
|
+ *
|
||||||
|
+ * If any error is encountered and print_errors is non-0, then print the
|
||||||
|
+ * error to stderr.
|
||||||
|
+ */
|
||||||
|
+static int modprobe_helper(const int print_errors, const char *module_name)
|
||||||
|
+{
|
||||||
|
+ char modprobe_path[NV_PROC_MODPROBE_PATH_MAX];
|
||||||
|
+ int status = 1;
|
||||||
|
+ struct stat file_status;
|
||||||
|
+ pid_t pid;
|
||||||
|
+ const char *envp[] = { "PATH=/sbin", NULL };
|
||||||
|
+ FILE *fp;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Use PCI_BASE_CLASS_MASK to cover both types of DISPLAY controllers that
|
||||||
|
+ * NVIDIA ships (VGA = 0x300 and 3D = 0x302).
|
||||||
|
+ */
|
||||||
|
+ struct pci_id_match id_match = {
|
||||||
|
+ NV_PCI_VENDOR_ID, /* Vendor ID = 0x10DE */
|
||||||
|
+ PCI_MATCH_ANY, /* Device ID = any */
|
||||||
|
+ PCI_MATCH_ANY, /* Subvendor ID = any */
|
||||||
|
+ PCI_MATCH_ANY, /* Subdevice ID = any */
|
||||||
|
+ 0x0300, /* Device Class = PCI_BASE_CLASS_DISPLAY */
|
||||||
|
+ PCI_BASE_CLASS_MASK, /* Display Mask = base class only */
|
||||||
|
+ 0 /* Initial number of matches */
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ modprobe_path[0] = '\0';
|
||||||
|
+
|
||||||
|
+ if (module_name == NULL || module_name[0] == '\0') {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* If the kernel module is already loaded, nothing more to do: success. */
|
||||||
|
+
|
||||||
|
+ if (is_kernel_module_loaded(module_name))
|
||||||
|
+ {
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Before attempting to load the module, look for any NVIDIA PCI devices.
|
||||||
|
+ * If none exist, exit instead of attempting the modprobe, because doing so
|
||||||
|
+ * would issue error messages that are really irrelevant if there are no
|
||||||
|
+ * NVIDIA PCI devices present.
|
||||||
|
+ *
|
||||||
|
+ * If our check fails, for whatever reason, continue with the modprobe just
|
||||||
|
+ * in case.
|
||||||
|
+ */
|
||||||
|
+ status = pci_enum_match_id(&id_match);
|
||||||
|
+ if (status == 0 && id_match.num_matches == 0)
|
||||||
|
+ {
|
||||||
|
+ if (print_errors)
|
||||||
|
+ {
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ "NVIDIA: no NVIDIA devices found\n");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Only attempt to load the kernel module if root. */
|
||||||
|
+
|
||||||
|
+ if (geteuid() != 0)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Attempt to read the full path to the modprobe executable from /proc. */
|
||||||
|
+
|
||||||
|
+ fp = fopen(NV_PROC_MODPROBE_PATH, "r");
|
||||||
|
+ if (fp != NULL)
|
||||||
|
+ {
|
||||||
|
+ char *str;
|
||||||
|
+ size_t n;
|
||||||
|
+
|
||||||
|
+ n = fread(modprobe_path, 1, sizeof(modprobe_path), fp);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Null terminate the string, but make sure 'n' is in the range
|
||||||
|
+ * [0, sizeof(modprobe_path)-1].
|
||||||
|
+ */
|
||||||
|
+ n = NV_MIN(n, sizeof(modprobe_path) - 1);
|
||||||
|
+ modprobe_path[n] = '\0';
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If str was longer than a line, we might still have a
|
||||||
|
+ * newline in modprobe_path: if so, overwrite it with the nul
|
||||||
|
+ * terminator.
|
||||||
|
+ */
|
||||||
|
+ str = strchr(modprobe_path, '\n');
|
||||||
|
+ if (str != NULL)
|
||||||
|
+ {
|
||||||
|
+ *str = '\0';
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fclose(fp);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* If we couldn't read it from /proc, pick a reasonable default. */
|
||||||
|
+
|
||||||
|
+ if (modprobe_path[0] == '\0')
|
||||||
|
+ {
|
||||||
|
+ sprintf(modprobe_path, "/sbin/modprobe");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Do not attempt to exec(3) modprobe if it does not exist. */
|
||||||
|
+
|
||||||
|
+ if (stat(modprobe_path, &file_status) != 0 ||
|
||||||
|
+ !S_ISREG(file_status.st_mode) ||
|
||||||
|
+ (file_status.st_mode & S_IXUSR) != S_IXUSR)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Fork and exec modprobe from the child process. */
|
||||||
|
+
|
||||||
|
+ switch (pid = fork())
|
||||||
|
+ {
|
||||||
|
+ case 0:
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * modprobe might complain in expected scenarios. E.g.,
|
||||||
|
+ * `modprobe nvidia` on a Tegra system with dGPU where no nvidia.ko is
|
||||||
|
+ * present will complain:
|
||||||
|
+ *
|
||||||
|
+ * "modprobe: FATAL: Module nvidia not found."
|
||||||
|
+ *
|
||||||
|
+ * Silence the current process to avoid such unwanted messages.
|
||||||
|
+ */
|
||||||
|
+ silence_current_process();
|
||||||
|
+
|
||||||
|
+ execle(modprobe_path, "modprobe",
|
||||||
|
+ module_name, NULL, envp);
|
||||||
|
+
|
||||||
|
+ /* If execl(3) returned, then an error has occurred. */
|
||||||
|
+
|
||||||
|
+ if (print_errors)
|
||||||
|
+ {
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ "NVIDIA: failed to execute `%s`: %s.\n",
|
||||||
|
+ modprobe_path, strerror(errno));
|
||||||
|
+ }
|
||||||
|
+ exit(1);
|
||||||
|
+
|
||||||
|
+ case -1:
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ if (waitpid(pid, &status, 0) < 0)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
|
||||||
|
+ {
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Attempt to load an NVIDIA kernel module
|
||||||
|
+ */
|
||||||
|
+int nvidia_modprobe(const int print_errors, int module_instance)
|
||||||
|
+{
|
||||||
|
+ char nv_module_name[NV_MAX_MODULE_NAME_SIZE];
|
||||||
|
+
|
||||||
|
+ assign_nvidia_kernel_module_name(nv_module_name, module_instance);
|
||||||
|
+
|
||||||
|
+ return modprobe_helper(print_errors, nv_module_name);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Determine the requested device file parameters: allow users to
|
||||||
|
+ * override the default UID/GID and/or mode of the NVIDIA device
|
||||||
|
+ * files, or even whether device file modification should be allowed;
|
||||||
|
+ * the attributes are managed globally, and can be adjusted via the
|
||||||
|
+ * appropriate kernel module parameters.
|
||||||
|
+ */
|
||||||
|
+static void init_device_file_parameters(uid_t *uid, gid_t *gid, mode_t *mode,
|
||||||
|
+ int *modify, const char *proc_path)
|
||||||
|
+{
|
||||||
|
+ FILE *fp;
|
||||||
|
+ char name[32];
|
||||||
|
+ unsigned int value;
|
||||||
|
+
|
||||||
|
+ *mode = NV_DEVICE_FILE_MODE;
|
||||||
|
+ *uid = NV_DEVICE_FILE_UID;
|
||||||
|
+ *gid = NV_DEVICE_FILE_GID;
|
||||||
|
+ *modify = 1;
|
||||||
|
+
|
||||||
|
+ if (proc_path == NULL || proc_path[0] == '\0')
|
||||||
|
+ {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fp = fopen(proc_path, "r");
|
||||||
|
+
|
||||||
|
+ if (fp == NULL)
|
||||||
|
+ {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while (fscanf(fp, "%31[^:]: %u\n", name, &value) == 2)
|
||||||
|
+ {
|
||||||
|
+ name[31] = '\0';
|
||||||
|
+ if (strcmp(name, "DeviceFileUID") == 0)
|
||||||
|
+ {
|
||||||
|
+ *uid = value;
|
||||||
|
+ }
|
||||||
|
+ if (strcmp(name, "DeviceFileGID") == 0)
|
||||||
|
+ {
|
||||||
|
+ *gid = value;
|
||||||
|
+ }
|
||||||
|
+ if (strcmp(name, "DeviceFileMode") == 0)
|
||||||
|
+ {
|
||||||
|
+ *mode = value;
|
||||||
|
+ }
|
||||||
|
+ if (strcmp(name, "ModifyDeviceFiles") == 0)
|
||||||
|
+ {
|
||||||
|
+ *modify = value;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fclose(fp);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * A helper to query device file states.
|
||||||
|
+ */
|
||||||
|
+static int get_file_state_helper(
|
||||||
|
+ const char *path,
|
||||||
|
+ int major,
|
||||||
|
+ int minor,
|
||||||
|
+ const char *proc_path,
|
||||||
|
+ uid_t uid,
|
||||||
|
+ gid_t gid,
|
||||||
|
+ mode_t mode)
|
||||||
|
+{
|
||||||
|
+ dev_t dev = NV_MAKE_DEVICE(major, minor);
|
||||||
|
+ struct stat stat_buf;
|
||||||
|
+ int ret;
|
||||||
|
+ int state = 0;
|
||||||
|
+
|
||||||
|
+ ret = stat(path, &stat_buf);
|
||||||
|
+ if (ret == 0)
|
||||||
|
+ {
|
||||||
|
+ nvidia_update_file_state(&state, NvDeviceFileStateFileExists);
|
||||||
|
+
|
||||||
|
+ if (S_ISCHR(stat_buf.st_mode) && (stat_buf.st_rdev == dev))
|
||||||
|
+ {
|
||||||
|
+ nvidia_update_file_state(&state, NvDeviceFileStateChrDevOk);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (((stat_buf.st_mode & NV_DEVICE_FILE_MODE_MASK) == mode) &&
|
||||||
|
+ (stat_buf.st_uid == uid) &&
|
||||||
|
+ (stat_buf.st_gid == gid))
|
||||||
|
+ {
|
||||||
|
+ nvidia_update_file_state(&state, NvDeviceFileStatePermissionsOk);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return state;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int nvidia_get_file_state(int minor, int module_instance)
|
||||||
|
+{
|
||||||
|
+ char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
|
||||||
|
+ char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
|
||||||
|
+ mode_t mode;
|
||||||
|
+ uid_t uid;
|
||||||
|
+ gid_t gid;
|
||||||
|
+ int modification_allowed;
|
||||||
|
+ int state = 0;
|
||||||
|
+
|
||||||
|
+ assign_device_file_name(path, minor, module_instance);
|
||||||
|
+ assign_proc_registry_path(proc_path, module_instance);
|
||||||
|
+
|
||||||
|
+ init_device_file_parameters(&uid, &gid, &mode, &modification_allowed,
|
||||||
|
+ proc_path);
|
||||||
|
+
|
||||||
|
+ state = get_file_state_helper(path, NV_MAJOR_DEVICE_NUMBER, minor,
|
||||||
|
+ proc_path, uid, gid, mode);
|
||||||
|
+
|
||||||
|
+ return state;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Attempt to create the specified device file with the specified major
|
||||||
|
+ * and minor number. If proc_path is specified, scan it for custom file
|
||||||
|
+ * permissions. Returns 1 if the file is successfully created; returns 0
|
||||||
|
+ * if the file could not be created.
|
||||||
|
+ */
|
||||||
|
+int mknod_helper(int major, int minor, const char *path,
|
||||||
|
+ const char *proc_path)
|
||||||
|
+{
|
||||||
|
+ dev_t dev = NV_MAKE_DEVICE(major, minor);
|
||||||
|
+ mode_t mode;
|
||||||
|
+ uid_t uid;
|
||||||
|
+ gid_t gid;
|
||||||
|
+ int modification_allowed;
|
||||||
|
+ int ret;
|
||||||
|
+ int state;
|
||||||
|
+ int do_mknod;
|
||||||
|
+
|
||||||
|
+ if (path == NULL || path[0] == '\0')
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ init_device_file_parameters(&uid, &gid, &mode, &modification_allowed,
|
||||||
|
+ proc_path);
|
||||||
|
+
|
||||||
|
+ /* If device file modification is not allowed, nothing to do: success. */
|
||||||
|
+
|
||||||
|
+ if (modification_allowed != 1)
|
||||||
|
+ {
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ state = get_file_state_helper(path, major, minor,
|
||||||
|
+ proc_path, uid, gid, mode);
|
||||||
|
+
|
||||||
|
+ if (nvidia_test_file_state(state, NvDeviceFileStateFileExists) &&
|
||||||
|
+ nvidia_test_file_state(state, NvDeviceFileStateChrDevOk) &&
|
||||||
|
+ nvidia_test_file_state(state, NvDeviceFileStatePermissionsOk))
|
||||||
|
+ {
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* If the stat(2) above failed, we need to create the device file. */
|
||||||
|
+
|
||||||
|
+ do_mknod = 0;
|
||||||
|
+
|
||||||
|
+ if (!nvidia_test_file_state(state, NvDeviceFileStateFileExists))
|
||||||
|
+ {
|
||||||
|
+ do_mknod = 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If the file exists but the file is either not a character device or has
|
||||||
|
+ * the wrong major/minor character device number, then we need to delete it
|
||||||
|
+ * and recreate it.
|
||||||
|
+ */
|
||||||
|
+ if (!do_mknod &&
|
||||||
|
+ !nvidia_test_file_state(state, NvDeviceFileStateChrDevOk))
|
||||||
|
+ {
|
||||||
|
+ ret = remove(path);
|
||||||
|
+ if (ret != 0)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ do_mknod = 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (do_mknod)
|
||||||
|
+ {
|
||||||
|
+ ret = mknod(path, S_IFCHR | mode, dev);
|
||||||
|
+ if (ret != 0)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Make sure the permissions and ownership are set correctly; if
|
||||||
|
+ * we created the device above and either of the below fails, then
|
||||||
|
+ * also delete the device file.
|
||||||
|
+ */
|
||||||
|
+ if ((chmod(path, mode) != 0) ||
|
||||||
|
+ (chown(path, uid, gid) != 0))
|
||||||
|
+ {
|
||||||
|
+ if (do_mknod)
|
||||||
|
+ {
|
||||||
|
+ remove(path);
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Attempt to create a device file with the specified minor number for
|
||||||
|
+ * the specified NVIDIA module instance.
|
||||||
|
+ */
|
||||||
|
+int nvidia_mknod(int minor, int module_instance)
|
||||||
|
+{
|
||||||
|
+ char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
|
||||||
|
+ char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
|
||||||
|
+
|
||||||
|
+ assign_device_file_name(path, minor, module_instance);
|
||||||
|
+ assign_proc_registry_path(proc_path, module_instance);
|
||||||
|
+
|
||||||
|
+ return mknod_helper(NV_MAJOR_DEVICE_NUMBER, minor, path, proc_path);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Scan NV_PROC_DEVICES_PATH to find the major number of the character
|
||||||
|
+ * device with the specified name. Returns the major number on success,
|
||||||
|
+ * or -1 on failure.
|
||||||
|
+ */
|
||||||
|
+int get_chardev_major(const char *name)
|
||||||
|
+{
|
||||||
|
+ int ret = -1;
|
||||||
|
+ char line[NV_MAX_LINE_LENGTH];
|
||||||
|
+ FILE *fp;
|
||||||
|
+
|
||||||
|
+ line[NV_MAX_LINE_LENGTH - 1] = '\0';
|
||||||
|
+
|
||||||
|
+ fp = fopen(NV_PROC_DEVICES_PATH, "r");
|
||||||
|
+ if (!fp)
|
||||||
|
+ {
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Find the beginning of the 'Character devices:' section */
|
||||||
|
+
|
||||||
|
+ while (fgets(line, NV_MAX_LINE_LENGTH - 1, fp))
|
||||||
|
+ {
|
||||||
|
+ if (strcmp(line, "Character devices:\n") == 0)
|
||||||
|
+ {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ferror(fp)) {
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Search for the given module name */
|
||||||
|
+
|
||||||
|
+ while (fgets(line, NV_MAX_LINE_LENGTH - 1, fp))
|
||||||
|
+ {
|
||||||
|
+ char *found;
|
||||||
|
+
|
||||||
|
+ if (strcmp(line, "\n") == 0 )
|
||||||
|
+ {
|
||||||
|
+ /* we've reached the end of the 'Character devices:' section */
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ found = strstr(line, name);
|
||||||
|
+
|
||||||
|
+ /* Check for a newline to avoid partial matches */
|
||||||
|
+
|
||||||
|
+ if (found && found[strlen(name)] == '\n')
|
||||||
|
+ {
|
||||||
|
+ int major;
|
||||||
|
+
|
||||||
|
+ /* Read the device major number */
|
||||||
|
+
|
||||||
|
+ if (sscanf(line, " %d %*s", &major) == 1)
|
||||||
|
+ {
|
||||||
|
+ ret = major;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+done:
|
||||||
|
+
|
||||||
|
+ if (fp)
|
||||||
|
+ {
|
||||||
|
+ fclose(fp);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Attempt to create the NVIDIA Unified Memory device file
|
||||||
|
+ */
|
||||||
|
+int nvidia_uvm_mknod(int base_minor)
|
||||||
|
+{
|
||||||
|
+ int major = get_chardev_major(NV_UVM_MODULE_NAME);
|
||||||
|
+
|
||||||
|
+ if (major < 0)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return mknod_helper(major, base_minor, NV_UVM_DEVICE_NAME, NULL) &&
|
||||||
|
+ mknod_helper(major, base_minor + 1, NV_UVM_TOOLS_DEVICE_NAME, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Attempt to load the NVIDIA Unified Memory kernel module
|
||||||
|
+ */
|
||||||
|
+int nvidia_uvm_modprobe(void)
|
||||||
|
+{
|
||||||
|
+ return modprobe_helper(0, NV_UVM_MODULE_NAME);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Attempt to load the NVIDIA modeset driver.
|
||||||
|
+ */
|
||||||
|
+int nvidia_modeset_modprobe(void)
|
||||||
|
+{
|
||||||
|
+ return modprobe_helper(0, NV_MODESET_MODULE_NAME);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Attempt to create the NVIDIA modeset driver device file.
|
||||||
|
+ */
|
||||||
|
+int nvidia_modeset_mknod(void)
|
||||||
|
+{
|
||||||
|
+ char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
|
||||||
|
+
|
||||||
|
+ assign_proc_registry_path(proc_path, NV_MODULE_INSTANCE_NONE);
|
||||||
|
+
|
||||||
|
+ return mknod_helper(NV_MAJOR_DEVICE_NUMBER,
|
||||||
|
+ NV_MODESET_MINOR_DEVICE_NUM,
|
||||||
|
+ NV_MODESET_DEVICE_NAME, proc_path);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Attempt to create the NVIDIA NVLink driver device file.
|
||||||
|
+ */
|
||||||
|
+int nvidia_nvlink_mknod(void)
|
||||||
|
+{
|
||||||
|
+ int major = get_chardev_major(NV_NVLINK_MODULE_NAME);
|
||||||
|
+
|
||||||
|
+ if (major < 0)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return mknod_helper(major,
|
||||||
|
+ 0,
|
||||||
|
+ NV_NVLINK_DEVICE_NAME,
|
||||||
|
+ NV_NVLINK_PROC_PERM_PATH);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int nvidia_vgpu_vfio_mknod(int minor_num)
|
||||||
|
+{
|
||||||
|
+ int major = get_chardev_major(NV_VGPU_VFIO_MODULE_NAME);
|
||||||
|
+ char vgpu_dev_name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
|
||||||
|
+ char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
|
||||||
|
+
|
||||||
|
+ if (major < 0)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ assign_proc_registry_path(proc_path, NV_MODULE_INSTANCE_NONE);
|
||||||
|
+
|
||||||
|
+ snprintf(vgpu_dev_name, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
+ NV_VGPU_VFIO_DEVICE_NAME, minor_num);
|
||||||
|
+
|
||||||
|
+ vgpu_dev_name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN - 1] = '\0';
|
||||||
|
+
|
||||||
|
+ return mknod_helper(major, minor_num, vgpu_dev_name, proc_path);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif /* NV_LINUX */
|
||||||
|
\ No newline at end of file
|
|
@ -0,0 +1,164 @@
|
||||||
|
diff --git a/src/nvidia-modprobe-utils.h b/src/nvidia-modprobe-utils.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..e06b4a4
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/nvidia-modprobe-utils.h
|
||||||
|
@@ -0,0 +1,157 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2013, NVIDIA CORPORATION.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person
|
||||||
|
+ * obtaining a copy of this software and associated documentation
|
||||||
|
+ * files (the "Software"), to deal in the Software without
|
||||||
|
+ * restriction, including without limitation the rights to use, copy,
|
||||||
|
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
+ * of the Software, and to permit persons to whom the Software is
|
||||||
|
+ * furnished to do so, subject to the following conditions:
|
||||||
|
+ *
|
||||||
|
+ * The above copyright notice and this permission notice shall be
|
||||||
|
+ * included in all copies or substantial portions of the Software.
|
||||||
|
+ *
|
||||||
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
+ * SOFTWARE.
|
||||||
|
+ *
|
||||||
|
+ * This file provides utility functions on Linux for loading the
|
||||||
|
+ * NVIDIA kernel module and creating NVIDIA device files.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef __NVIDIA_MODPROBE_UTILS_H__
|
||||||
|
+#define __NVIDIA_MODPROBE_UTILS_H__
|
||||||
|
+
|
||||||
|
+#include <stdio.h>
|
||||||
|
+
|
||||||
|
+#define NV_MAX_CHARACTER_DEVICE_FILE_STRLEN 128
|
||||||
|
+#define NV_MODULE_INSTANCE_NONE -1
|
||||||
|
+#define NV_MODULE_INSTANCE_ZERO 0
|
||||||
|
+#define NV_MAX_MODULE_INSTANCES 8
|
||||||
|
+#define NV_CTL_DEVICE_NUM 255
|
||||||
|
+#define NV_MODESET_MINOR_DEVICE_NUM 254
|
||||||
|
+
|
||||||
|
+#define NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX NV_CTL_DEVICE_NUM
|
||||||
|
+
|
||||||
|
+#define NV_DEVICE_FILE_PATH "/dev/nvidia%d"
|
||||||
|
+#define NV_CTRL_DEVICE_FILE_PATH "/dev/nvidiactl"
|
||||||
|
+#define NV_MODESET_DEVICE_NAME "/dev/nvidia-modeset"
|
||||||
|
+#define NV_VGPU_VFIO_DEVICE_NAME "/dev/nvidia-vgpu%d"
|
||||||
|
+#define NV_NVLINK_DEVICE_NAME "/dev/nvidia-nvlink"
|
||||||
|
+
|
||||||
|
+#define NV_NMODULE_CTRL_DEVICE_FILE_PATH "/dev/nvidiactl%d"
|
||||||
|
+
|
||||||
|
+#define NV_FRONTEND_CONTROL_DEVICE_MINOR_MIN \
|
||||||
|
+ (NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX - \
|
||||||
|
+ NV_MAX_MODULE_INSTANCES)
|
||||||
|
+
|
||||||
|
+#define NV_FRONTEND_IS_CONTROL_DEVICE(x) \
|
||||||
|
+ ((x <= NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX) && \
|
||||||
|
+ (x > NV_FRONTEND_CONTROL_DEVICE_MINOR_MIN))
|
||||||
|
+
|
||||||
|
+#if defined(NV_LINUX)
|
||||||
|
+
|
||||||
|
+typedef enum
|
||||||
|
+{
|
||||||
|
+ NvDeviceFileStateFileExists = 0,
|
||||||
|
+ NvDeviceFileStateChrDevOk,
|
||||||
|
+ NvDeviceFileStatePermissionsOk
|
||||||
|
+} NvDeviceFileState;
|
||||||
|
+
|
||||||
|
+static __inline__ void nvidia_update_file_state(int *state,
|
||||||
|
+ NvDeviceFileState value)
|
||||||
|
+{
|
||||||
|
+ *state |= (1 << value);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static __inline__ int nvidia_test_file_state(int state,
|
||||||
|
+ NvDeviceFileState value)
|
||||||
|
+{
|
||||||
|
+ return !!(state & (1 << value));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int nvidia_get_file_state(int minor, int module_instance);
|
||||||
|
+int nvidia_modprobe(const int print_errors, int module_instance);
|
||||||
|
+int nvidia_mknod(int minor, int module_instance);
|
||||||
|
+int nvidia_uvm_modprobe(void);
|
||||||
|
+int nvidia_uvm_mknod(int base_minor);
|
||||||
|
+int nvidia_modeset_modprobe(void);
|
||||||
|
+int nvidia_modeset_mknod(void);
|
||||||
|
+int nvidia_vgpu_vfio_mknod(int minor_num);
|
||||||
|
+int nvidia_nvlink_mknod(void);
|
||||||
|
+
|
||||||
|
+int mknod_helper(int major, int minor, const char *path, const char *proc_path);
|
||||||
|
+int get_chardev_major(const char *name);
|
||||||
|
+
|
||||||
|
+#endif /* NV_LINUX */
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Detect use of multiple kernel module instances. Use a single
|
||||||
|
+ * module instance unless instance != NV_MODULE_INSTANCE_NONE
|
||||||
|
+ */
|
||||||
|
+static __inline__ int is_multi_module(int module_instance)
|
||||||
|
+{
|
||||||
|
+ return (module_instance != NV_MODULE_INSTANCE_NONE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Construct the device file name, based on 'minor'. If an error
|
||||||
|
+ * occurs, the nul terminator will be written to name[0].
|
||||||
|
+ */
|
||||||
|
+static __inline__ void assign_device_file_name
|
||||||
|
+(
|
||||||
|
+ char name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN],
|
||||||
|
+ int minor,
|
||||||
|
+ int module_instance
|
||||||
|
+)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if ((minor < 0) || (minor > NV_CTL_DEVICE_NUM))
|
||||||
|
+ {
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!is_multi_module(module_instance) && minor == NV_CTL_DEVICE_NUM)
|
||||||
|
+ {
|
||||||
|
+ ret = snprintf(name,
|
||||||
|
+ NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
+ NV_CTRL_DEVICE_FILE_PATH);
|
||||||
|
+ }
|
||||||
|
+ else if (is_multi_module(module_instance) &&
|
||||||
|
+ NV_FRONTEND_IS_CONTROL_DEVICE(minor))
|
||||||
|
+ {
|
||||||
|
+ ret = snprintf(name,
|
||||||
|
+ NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
+ NV_NMODULE_CTRL_DEVICE_FILE_PATH,
|
||||||
|
+ module_instance);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ ret = snprintf(name,
|
||||||
|
+ NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
+ NV_DEVICE_FILE_PATH, minor);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ret <= 0)
|
||||||
|
+ {
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN - 1] = '\0';
|
||||||
|
+
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+fail:
|
||||||
|
+
|
||||||
|
+ name[0] = '\0';
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif /* __NVIDIA_MODPROBE_UTILS_H__ */
|
||||||
|
\ No newline at end of file
|
|
@ -0,0 +1,13 @@
|
||||||
|
diff --git a/mk/common.mk b/mk/common.mk
|
||||||
|
index bded646..572adfc 100644
|
||||||
|
--- a/mk/common.mk
|
||||||
|
+++ b/mk/common.mk
|
||||||
|
@@ -21,7 +21,7 @@ DOCKER ?= docker
|
||||||
|
UID := $(shell id -u)
|
||||||
|
GID := $(shell id -g)
|
||||||
|
DATE := $(shell date -u --iso-8601=minutes)
|
||||||
|
-REVISION := $(shell git rev-parse HEAD)
|
||||||
|
+REVISION := 61f82bf25f0b3afaa75c6df8a0a6551ecfdf81f4
|
||||||
|
COMPILER := $(realpath $(shell which $(CC)))
|
||||||
|
PLATFORM ?= $(shell uname -m)
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 0070ada..8643de0 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -4,21 +4,21 @@
|
||||||
|
|
||||||
|
.PHONY: all tools shared static deps install uninstall dist depsclean mostlyclean clean distclean
|
||||||
|
.DEFAULT_GOAL := all
|
||||||
|
-
|
||||||
|
+STRIP := @echo skipping: strip
|
||||||
|
##### Global variables #####
|
||||||
|
|
||||||
|
-WITH_LIBELF ?= no
|
||||||
|
-WITH_TIRPC ?= no
|
||||||
|
+WITH_LIBELF ?= yes
|
||||||
|
+WITH_TIRPC ?= yes
|
||||||
|
WITH_SECCOMP ?= yes
|
||||||
|
|
||||||
|
##### Global definitions #####
|
||||||
|
|
||||||
|
-export prefix = /usr/local
|
||||||
|
+export prefix = /usr
|
||||||
|
export exec_prefix = $(prefix)
|
||||||
|
export bindir = $(exec_prefix)/bin
|
||||||
|
-export libdir = $(exec_prefix)/lib
|
||||||
|
+export libdir = $(exec_prefix)/lib64
|
||||||
|
export docdir = $(prefix)/share/doc
|
||||||
|
-export libdbgdir = $(prefix)/lib/debug$(libdir)
|
||||||
|
+export libdbgdir = $(prefix)/lib64/debug$(libdir)
|
||||||
|
export includedir = $(prefix)/include
|
||||||
|
export pkgconfdir = $(libdir)/pkgconfig
|
||||||
|
|
||||||
|
@@ -51,6 +51,8 @@ LIB_SRCS := $(SRCS_DIR)/driver.c \
|
||||||
|
$(SRCS_DIR)/error_generic.c \
|
||||||
|
$(SRCS_DIR)/error.c \
|
||||||
|
$(SRCS_DIR)/ldcache.c \
|
||||||
|
+ $(SRCS_DIR)/pci-sysfs.c \
|
||||||
|
+ $(SRCS_DIR)/nvidia-modprobe-utils.c \
|
||||||
|
$(SRCS_DIR)/nvc.c \
|
||||||
|
$(SRCS_DIR)/nvc_ldcache.c \
|
||||||
|
$(SRCS_DIR)/nvc_info.c \
|
||||||
|
@@ -112,7 +114,7 @@ CFLAGS := -std=gnu11 -O2 -g -fdata-sections -ffunction-sections -fstack-protec
|
||||||
|
-Wall -Wextra -Wcast-align -Wpointer-arith -Wmissing-prototypes -Wnonnull \
|
||||||
|
-Wwrite-strings -Wlogical-op -Wformat=2 -Wmissing-format-attribute -Winit-self -Wshadow \
|
||||||
|
-Wstrict-prototypes -Wunreachable-code -Wconversion -Wsign-conversion \
|
||||||
|
- -Wno-unknown-warning-option -Wno-format-extra-args -Wno-gnu-alignof-expression $(CFLAGS)
|
||||||
|
+ -Wno-unknown-warning-option -Wno-format-extra-args -Wno-gnu-alignof-expression -I/usr/include/tirpc $(CFLAGS)
|
||||||
|
LDFLAGS := -Wl,-zrelro -Wl,-znow -Wl,-zdefs -Wl,--gc-sections $(LDFLAGS)
|
||||||
|
LDLIBS := $(LDLIBS)
|
||||||
|
|
||||||
|
@@ -120,8 +122,8 @@ LDLIBS := $(LDLIBS)
|
||||||
|
LIB_CPPFLAGS = -DNV_LINUX -isystem $(DEPS_DIR)$(includedir) -include $(BUILD_DEFS)
|
||||||
|
LIB_CFLAGS = -fPIC
|
||||||
|
LIB_LDFLAGS = -L$(DEPS_DIR)$(libdir) -shared -Wl,-soname=$(LIB_SONAME)
|
||||||
|
-LIB_LDLIBS_STATIC = -l:libnvidia-modprobe-utils.a
|
||||||
|
-LIB_LDLIBS_SHARED = -ldl -lcap
|
||||||
|
+# LIB_LDLIBS_STATIC = -l:libnvidia-modprobe-utils.a
|
||||||
|
+LIB_LDLIBS_SHARED = -ldl -lcap -ltirpc
|
||||||
|
ifeq ($(WITH_LIBELF), yes)
|
||||||
|
LIB_CPPFLAGS += -DWITH_LIBELF
|
||||||
|
LIB_LDLIBS_SHARED += -lelf
|
||||||
|
@@ -130,7 +132,7 @@ LIB_LDLIBS_STATIC += -l:libelf.a
|
||||||
|
endif
|
||||||
|
ifeq ($(WITH_TIRPC), yes)
|
||||||
|
LIB_CPPFLAGS += -isystem $(DEPS_DIR)$(includedir)/tirpc -DWITH_TIRPC
|
||||||
|
-LIB_LDLIBS_STATIC += -l:libtirpc.a
|
||||||
|
+# LIB_LDLIBS_STATIC += -l:libtirpc.a
|
||||||
|
LIB_LDLIBS_SHARED += -lpthread
|
||||||
|
endif
|
||||||
|
ifeq ($(WITH_SECCOMP), yes)
|
||||||
|
@@ -145,7 +147,7 @@ LIB_LDLIBS_SHARED += $(LDLIBS)
|
||||||
|
LIB_LDLIBS = $(LIB_LDLIBS_STATIC) $(LIB_LDLIBS_SHARED)
|
||||||
|
|
||||||
|
# Binary flags (recursively expanded to handle target-specific flags)
|
||||||
|
-BIN_CPPFLAGS = -include $(BUILD_DEFS) $(CPPFLAGS)
|
||||||
|
+BIN_CPPFLAGS = -include $(BUILD_DEFS) $(CPPFLAGS) -DWITH_TIRPC
|
||||||
|
BIN_CFLAGS = -I$(SRCS_DIR) -fPIE -flto $(CFLAGS)
|
||||||
|
BIN_LDFLAGS = -L. -pie $(LDFLAGS) -Wl,-rpath='$$ORIGIN/../$$LIB'
|
||||||
|
BIN_LDLIBS = -l:$(LIB_SHARED) -lcap $(LDLIBS)
|
||||||
|
@@ -219,12 +221,12 @@ static: $(LIB_STATIC)($(LIB_STATIC_OBJ))
|
||||||
|
deps: export DESTDIR:=$(DEPS_DIR)
|
||||||
|
deps: $(LIB_RPC_SRCS) $(BUILD_DEFS)
|
||||||
|
$(MKDIR) -p $(DEPS_DIR)
|
||||||
|
- $(MAKE) -f $(MAKE_DIR)/nvidia-modprobe.mk install
|
||||||
|
+ # $(MAKE) -f $(MAKE_DIR)/nvidia-modprobe.mk install
|
||||||
|
ifeq ($(WITH_LIBELF), no)
|
||||||
|
- $(MAKE) -f $(MAKE_DIR)/elftoolchain.mk install
|
||||||
|
+ # $(MAKE) -f $(MAKE_DIR)/elftoolchain.mk install
|
||||||
|
endif
|
||||||
|
ifeq ($(WITH_TIRPC), yes)
|
||||||
|
- $(MAKE) -f $(MAKE_DIR)/libtirpc.mk install
|
||||||
|
+ # $(MAKE) -f $(MAKE_DIR)/libtirpc.mk install
|
||||||
|
endif
|
||||||
|
|
||||||
|
install: all
|
||||||
|
@@ -237,7 +239,7 @@ install: all
|
||||||
|
$(LN) -sf $(LIB_SONAME) $(DESTDIR)$(libdir)/$(LIB_SYMLINK)
|
||||||
|
$(LDCONFIG) -n $(DESTDIR)$(libdir)
|
||||||
|
# Install debugging symbols
|
||||||
|
- $(INSTALL) -m 644 $(DEBUG_DIR)/$(LIB_SONAME) $(DESTDIR)$(libdbgdir)
|
||||||
|
+ # $(INSTALL) -m 644 $(DEBUG_DIR)/$(LIB_SONAME) $(DESTDIR)$(libdbgdir)
|
||||||
|
# Install configuration files
|
||||||
|
$(MAKE_DIR)/$(LIB_PKGCFG).in "$(strip $(VERSION))" "$(strip $(LIB_LDLIBS_SHARED))" > $(DESTDIR)$(pkgconfdir)/$(LIB_PKGCFG)
|
||||||
|
# Install binary files
|
|
@ -0,0 +1,15 @@
|
||||||
|
diff --git a/src/nvc.c b/src/nvc.c
|
||||||
|
index 0a5ec79..172f906 100644
|
||||||
|
--- a/src/nvc.c
|
||||||
|
+++ b/src/nvc.c
|
||||||
|
@@ -14,8 +14,8 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
-#include <pci-enum.h>
|
||||||
|
-#include <nvidia-modprobe-utils.h>
|
||||||
|
+#include "pci-enum.h"
|
||||||
|
+#include "nvidia-modprobe-utils.h"
|
||||||
|
|
||||||
|
#include "nvc_internal.h"
|
||||||
|
|
|
@ -0,0 +1,567 @@
|
||||||
|
--- a/src/nvidia-modprobe-utils.c 2020-09-18 18:11:57.042187266 +0800
|
||||||
|
+++ b/src/nvidia-modprobe-utils.c 2020-09-18 18:25:49.318472815 +0800
|
||||||
|
@@ -1,3 +1,29 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2013, NVIDIA CORPORATION.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person
|
||||||
|
+ * obtaining a copy of this software and associated documentation
|
||||||
|
+ * files (the "Software"), to deal in the Software without
|
||||||
|
+ * restriction, including without limitation the rights to use, copy,
|
||||||
|
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
+ * of the Software, and to permit persons to whom the Software is
|
||||||
|
+ * furnished to do so, subject to the following conditions:
|
||||||
|
+ *
|
||||||
|
+ * The above copyright notice and this permission notice shall be
|
||||||
|
+ * included in all copies or substantial portions of the Software.
|
||||||
|
+ *
|
||||||
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
+ * SOFTWARE.
|
||||||
|
+ *
|
||||||
|
+ * This file provides utility functions on Linux for loading the
|
||||||
|
+ * NVIDIA kernel module and creating NVIDIA device files.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
#if defined(NV_LINUX)
|
||||||
|
|
||||||
|
@@ -27,9 +53,6 @@
|
||||||
|
#define NV_NVIDIA_MODULE_NAME "nvidia"
|
||||||
|
#define NV_PROC_REGISTRY_PATH "/proc/driver/nvidia/params"
|
||||||
|
|
||||||
|
-#define NV_NMODULE_NVIDIA_MODULE_NAME "nvidia%d"
|
||||||
|
-#define NV_NMODULE_PROC_REGISTRY_PATH "/proc/driver/nvidia/%d/params"
|
||||||
|
-
|
||||||
|
#define NV_UVM_MODULE_NAME "nvidia-uvm"
|
||||||
|
#define NV_UVM_DEVICE_NAME "/dev/nvidia-uvm"
|
||||||
|
#define NV_UVM_TOOLS_DEVICE_NAME "/dev/nvidia-uvm-tools"
|
||||||
|
@@ -41,12 +64,16 @@
|
||||||
|
#define NV_NVLINK_MODULE_NAME "nvidia-nvlink"
|
||||||
|
#define NV_NVLINK_PROC_PERM_PATH "/proc/driver/nvidia-nvlink/permissions"
|
||||||
|
|
||||||
|
+#define NV_NVSWITCH_MODULE_NAME "nvidia-nvswitch"
|
||||||
|
+#define NV_NVSWITCH_PROC_PERM_PATH "/proc/driver/nvidia-nvswitch/permissions"
|
||||||
|
+
|
||||||
|
#define NV_DEVICE_FILE_MODE_MASK (S_IRWXU|S_IRWXG|S_IRWXO)
|
||||||
|
#define NV_DEVICE_FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
|
||||||
|
#define NV_DEVICE_FILE_UID 0
|
||||||
|
#define NV_DEVICE_FILE_GID 0
|
||||||
|
|
||||||
|
-#define NV_MAKE_DEVICE(x,y) ((dev_t)((x) << 8 | (y)))
|
||||||
|
+#define NV_MAKE_DEVICE(major, minor) \
|
||||||
|
+ ((dev_t)((minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12)))
|
||||||
|
|
||||||
|
#define NV_MAJOR_DEVICE_NUMBER 195
|
||||||
|
|
||||||
|
@@ -55,84 +82,6 @@
|
||||||
|
#define NV_MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * Construct the nvidia kernel module name based on the input
|
||||||
|
- * module instance provided. If an error occurs, the null
|
||||||
|
- * terminator will be written to nv_module_name[0].
|
||||||
|
- */
|
||||||
|
-static __inline__ void assign_nvidia_kernel_module_name
|
||||||
|
-(
|
||||||
|
- char nv_module_name[NV_MAX_MODULE_NAME_SIZE],
|
||||||
|
- int module_instance
|
||||||
|
-)
|
||||||
|
-{
|
||||||
|
- int ret;
|
||||||
|
-
|
||||||
|
- if (is_multi_module(module_instance))
|
||||||
|
- {
|
||||||
|
- ret = snprintf(nv_module_name, NV_MAX_MODULE_NAME_SIZE,
|
||||||
|
- NV_NMODULE_NVIDIA_MODULE_NAME, module_instance);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- ret = snprintf(nv_module_name, NV_MAX_MODULE_NAME_SIZE,
|
||||||
|
- NV_NVIDIA_MODULE_NAME);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (ret <= 0)
|
||||||
|
- {
|
||||||
|
- goto fail;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- nv_module_name[NV_MAX_MODULE_NAME_SIZE - 1] = '\0';
|
||||||
|
-
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
-fail:
|
||||||
|
-
|
||||||
|
- nv_module_name[0] = '\0';
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/*
|
||||||
|
- * Construct the proc registry path name based on the input
|
||||||
|
- * module instance provided. If an error occurs, the null
|
||||||
|
- * terminator will be written to proc_path[0].
|
||||||
|
- */
|
||||||
|
-static __inline__ void assign_proc_registry_path
|
||||||
|
-(
|
||||||
|
- char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE],
|
||||||
|
- int module_instance
|
||||||
|
-)
|
||||||
|
-{
|
||||||
|
- int ret;
|
||||||
|
-
|
||||||
|
- if (is_multi_module(module_instance))
|
||||||
|
- {
|
||||||
|
- ret = snprintf(proc_path, NV_MAX_PROC_REGISTRY_PATH_SIZE,
|
||||||
|
- NV_NMODULE_PROC_REGISTRY_PATH, module_instance);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- ret = snprintf(proc_path, NV_MAX_PROC_REGISTRY_PATH_SIZE,
|
||||||
|
- NV_PROC_REGISTRY_PATH);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (ret <= 0)
|
||||||
|
- {
|
||||||
|
- goto fail;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE - 1] = '\0';
|
||||||
|
-
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
-fail:
|
||||||
|
-
|
||||||
|
- proc_path[0] = '\0';
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/*
|
||||||
|
* Just like strcmp(3), except that differences between '-' and '_' are
|
||||||
|
* ignored. This is useful for comparing module names, where '-' and '_'
|
||||||
|
* are supposed to be treated interchangeably.
|
||||||
|
@@ -370,18 +319,20 @@
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
- if (waitpid(pid, &status, 0) < 0)
|
||||||
|
- {
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
- if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
|
||||||
|
- {
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
+ /*
|
||||||
|
+ * waitpid(2) is not always guaranteed to return success even if
|
||||||
|
+ * the child terminated normally. For example, if the process
|
||||||
|
+ * explicitly configured the handling of the SIGCHLD signal
|
||||||
|
+ * to SIG_IGN, then waitpid(2) will instead block until all
|
||||||
|
+ * children terminate and return the error ECHILD, regardless
|
||||||
|
+ * of the child's exit codes.
|
||||||
|
+ *
|
||||||
|
+ * Hence, ignore waitpid(2) error codes and instead check
|
||||||
|
+ * whether the desired kernel module is loaded.
|
||||||
|
+ */
|
||||||
|
+ waitpid(pid, NULL, 0);
|
||||||
|
+
|
||||||
|
+ return is_kernel_module_loaded(module_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
@@ -391,13 +342,9 @@
|
||||||
|
/*
|
||||||
|
* Attempt to load an NVIDIA kernel module
|
||||||
|
*/
|
||||||
|
-int nvidia_modprobe(const int print_errors, int module_instance)
|
||||||
|
+int nvidia_modprobe(const int print_errors)
|
||||||
|
{
|
||||||
|
- char nv_module_name[NV_MAX_MODULE_NAME_SIZE];
|
||||||
|
-
|
||||||
|
- assign_nvidia_kernel_module_name(nv_module_name, module_instance);
|
||||||
|
-
|
||||||
|
- return modprobe_helper(print_errors, nv_module_name);
|
||||||
|
+ return modprobe_helper(print_errors, NV_NVIDIA_MODULE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -447,7 +394,8 @@
|
||||||
|
{
|
||||||
|
*mode = value;
|
||||||
|
}
|
||||||
|
- if (strcmp(name, "ModifyDeviceFiles") == 0)
|
||||||
|
+ if ((strcmp(name, "ModifyDeviceFiles") == 0) ||
|
||||||
|
+ (strcmp(name, "DeviceFileModify") == 0))
|
||||||
|
{
|
||||||
|
*modify = value;
|
||||||
|
}
|
||||||
|
@@ -456,7 +404,7 @@
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
-/*
|
||||||
|
+/*
|
||||||
|
* A helper to query device file states.
|
||||||
|
*/
|
||||||
|
static int get_file_state_helper(
|
||||||
|
@@ -494,24 +442,22 @@
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int nvidia_get_file_state(int minor, int module_instance)
|
||||||
|
+int nvidia_get_file_state(int minor)
|
||||||
|
{
|
||||||
|
char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
|
||||||
|
- char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
|
||||||
|
mode_t mode;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
int modification_allowed;
|
||||||
|
int state = 0;
|
||||||
|
|
||||||
|
- assign_device_file_name(path, minor, module_instance);
|
||||||
|
- assign_proc_registry_path(proc_path, module_instance);
|
||||||
|
+ assign_device_file_name(path, minor);
|
||||||
|
|
||||||
|
init_device_file_parameters(&uid, &gid, &mode, &modification_allowed,
|
||||||
|
- proc_path);
|
||||||
|
+ NV_PROC_REGISTRY_PATH);
|
||||||
|
|
||||||
|
state = get_file_state_helper(path, NV_MAJOR_DEVICE_NUMBER, minor,
|
||||||
|
- proc_path, uid, gid, mode);
|
||||||
|
+ NV_PROC_REGISTRY_PATH, uid, gid, mode);
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
@@ -522,8 +468,8 @@
|
||||||
|
* permissions. Returns 1 if the file is successfully created; returns 0
|
||||||
|
* if the file could not be created.
|
||||||
|
*/
|
||||||
|
-int mknod_helper(int major, int minor, const char *path,
|
||||||
|
- const char *proc_path)
|
||||||
|
+static int mknod_helper(int major, int minor, const char *path,
|
||||||
|
+ const char *proc_path)
|
||||||
|
{
|
||||||
|
dev_t dev = NV_MAKE_DEVICE(major, minor);
|
||||||
|
mode_t mode;
|
||||||
|
@@ -616,15 +562,13 @@
|
||||||
|
* Attempt to create a device file with the specified minor number for
|
||||||
|
* the specified NVIDIA module instance.
|
||||||
|
*/
|
||||||
|
-int nvidia_mknod(int minor, int module_instance)
|
||||||
|
+int nvidia_mknod(int minor)
|
||||||
|
{
|
||||||
|
char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
|
||||||
|
- char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
|
||||||
|
|
||||||
|
- assign_device_file_name(path, minor, module_instance);
|
||||||
|
- assign_proc_registry_path(proc_path, module_instance);
|
||||||
|
+ assign_device_file_name(path, minor);
|
||||||
|
|
||||||
|
- return mknod_helper(NV_MAJOR_DEVICE_NUMBER, minor, path, proc_path);
|
||||||
|
+ return mknod_helper(NV_MAJOR_DEVICE_NUMBER, minor, path, NV_PROC_REGISTRY_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -633,7 +577,7 @@
|
||||||
|
* device with the specified name. Returns the major number on success,
|
||||||
|
* or -1 on failure.
|
||||||
|
*/
|
||||||
|
-int get_chardev_major(const char *name)
|
||||||
|
+int nvidia_get_chardev_major(const char *name)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
char line[NV_MAX_LINE_LENGTH];
|
||||||
|
@@ -702,13 +646,86 @@
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+int nvidia_nvlink_get_file_state(void)
|
||||||
|
+{
|
||||||
|
+ char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
|
||||||
|
+ mode_t mode;
|
||||||
|
+ uid_t uid;
|
||||||
|
+ gid_t gid;
|
||||||
|
+ int modification_allowed;
|
||||||
|
+ int ret;
|
||||||
|
+ int major = nvidia_get_chardev_major(NV_NVLINK_MODULE_NAME);
|
||||||
|
+
|
||||||
|
+ if (major < 0)
|
||||||
|
+ {
|
||||||
|
+ path[0] = '\0';
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = snprintf(path, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
+ NV_NVLINK_DEVICE_NAME);
|
||||||
|
+
|
||||||
|
+ if (ret < 0 || ret >= NV_MAX_CHARACTER_DEVICE_FILE_STRLEN)
|
||||||
|
+ {
|
||||||
|
+ path[0] = '\0';
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+done:
|
||||||
|
+
|
||||||
|
+ init_device_file_parameters(&uid, &gid, &mode, &modification_allowed,
|
||||||
|
+ NV_NVLINK_PROC_PERM_PATH);
|
||||||
|
+
|
||||||
|
+ return get_file_state_helper(path, major, 0,
|
||||||
|
+ NV_NVLINK_PROC_PERM_PATH, uid, gid, mode);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int nvidia_nvswitch_get_file_state(int minor)
|
||||||
|
+{
|
||||||
|
+ char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
|
||||||
|
+ mode_t mode;
|
||||||
|
+ uid_t uid;
|
||||||
|
+ gid_t gid;
|
||||||
|
+ int modification_allowed;
|
||||||
|
+ int ret;
|
||||||
|
+ int major = nvidia_get_chardev_major(NV_NVSWITCH_MODULE_NAME);
|
||||||
|
+
|
||||||
|
+ if ((major < 0) || (minor < 0) || (minor > NV_NVSWITCH_CTL_MINOR))
|
||||||
|
+ {
|
||||||
|
+ path[0] = '\0';
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (minor == NV_NVSWITCH_CTL_MINOR)
|
||||||
|
+ {
|
||||||
|
+ ret = snprintf(path, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
+ NV_NVSWITCH_CTL_NAME);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ ret = snprintf(path, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
+ NV_NVSWITCH_DEVICE_NAME, minor);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ret < 0 || ret >= NV_MAX_CHARACTER_DEVICE_FILE_STRLEN)
|
||||||
|
+ {
|
||||||
|
+ path[0] = '\0';
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+done:
|
||||||
|
+
|
||||||
|
+ init_device_file_parameters(&uid, &gid, &mode, &modification_allowed,
|
||||||
|
+ NV_NVSWITCH_PROC_PERM_PATH);
|
||||||
|
+
|
||||||
|
+ return get_file_state_helper(path, major, minor,
|
||||||
|
+ NV_NVSWITCH_PROC_PERM_PATH, uid, gid, mode);
|
||||||
|
+}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt to create the NVIDIA Unified Memory device file
|
||||||
|
*/
|
||||||
|
int nvidia_uvm_mknod(int base_minor)
|
||||||
|
{
|
||||||
|
- int major = get_chardev_major(NV_UVM_MODULE_NAME);
|
||||||
|
+ int major = nvidia_get_chardev_major(NV_UVM_MODULE_NAME);
|
||||||
|
|
||||||
|
if (major < 0)
|
||||||
|
{
|
||||||
|
@@ -743,13 +760,9 @@
|
||||||
|
*/
|
||||||
|
int nvidia_modeset_mknod(void)
|
||||||
|
{
|
||||||
|
- char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
|
||||||
|
-
|
||||||
|
- assign_proc_registry_path(proc_path, NV_MODULE_INSTANCE_NONE);
|
||||||
|
-
|
||||||
|
return mknod_helper(NV_MAJOR_DEVICE_NUMBER,
|
||||||
|
NV_MODESET_MINOR_DEVICE_NUM,
|
||||||
|
- NV_MODESET_DEVICE_NAME, proc_path);
|
||||||
|
+ NV_MODESET_DEVICE_NAME, NV_PROC_REGISTRY_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -757,7 +770,7 @@
|
||||||
|
*/
|
||||||
|
int nvidia_nvlink_mknod(void)
|
||||||
|
{
|
||||||
|
- int major = get_chardev_major(NV_NVLINK_MODULE_NAME);
|
||||||
|
+ int major = nvidia_get_chardev_major(NV_NVLINK_MODULE_NAME);
|
||||||
|
|
||||||
|
if (major < 0)
|
||||||
|
{
|
||||||
|
@@ -770,25 +783,164 @@
|
||||||
|
NV_NVLINK_PROC_PERM_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Attempt to create the NVIDIA NVSwitch driver device files.
|
||||||
|
+ */
|
||||||
|
+int nvidia_nvswitch_mknod(int minor)
|
||||||
|
+{
|
||||||
|
+ int major = 0;
|
||||||
|
+ char name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ major = nvidia_get_chardev_major(NV_NVSWITCH_MODULE_NAME);
|
||||||
|
+
|
||||||
|
+ if (major < 0)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (minor == NV_NVSWITCH_CTL_MINOR)
|
||||||
|
+ {
|
||||||
|
+ ret = snprintf(name, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
+ NV_NVSWITCH_CTL_NAME);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ ret = snprintf(name, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
+ NV_NVSWITCH_DEVICE_NAME, minor);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ret < 0 || ret >= NV_MAX_CHARACTER_DEVICE_FILE_STRLEN)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return mknod_helper(major, minor, name, NV_NVSWITCH_PROC_PERM_PATH);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int nvidia_vgpu_vfio_mknod(int minor_num)
|
||||||
|
{
|
||||||
|
- int major = get_chardev_major(NV_VGPU_VFIO_MODULE_NAME);
|
||||||
|
+ int major = nvidia_get_chardev_major(NV_VGPU_VFIO_MODULE_NAME);
|
||||||
|
char vgpu_dev_name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
|
||||||
|
- char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
|
||||||
|
+ int ret;
|
||||||
|
|
||||||
|
if (major < 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- assign_proc_registry_path(proc_path, NV_MODULE_INSTANCE_NONE);
|
||||||
|
-
|
||||||
|
- snprintf(vgpu_dev_name, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
- NV_VGPU_VFIO_DEVICE_NAME, minor_num);
|
||||||
|
+ ret = snprintf(vgpu_dev_name, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
+ NV_VGPU_VFIO_DEVICE_NAME, minor_num);
|
||||||
|
+ if (ret <= 0)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
vgpu_dev_name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN - 1] = '\0';
|
||||||
|
|
||||||
|
- return mknod_helper(major, minor_num, vgpu_dev_name, proc_path);
|
||||||
|
+ return mknod_helper(major, minor_num, vgpu_dev_name, NV_PROC_REGISTRY_PATH);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int nvidia_cap_get_device_file_attrs(const char* cap_file_path,
|
||||||
|
+ int *major,
|
||||||
|
+ int *minor,
|
||||||
|
+ char *name)
|
||||||
|
+{
|
||||||
|
+ char field[32];
|
||||||
|
+ FILE *fp;
|
||||||
|
+ int value;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ *major = nvidia_get_chardev_major(NV_CAPS_MODULE_NAME);
|
||||||
|
+
|
||||||
|
+ if (*major < 0)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fp = fopen(cap_file_path, "r");
|
||||||
|
+
|
||||||
|
+ if (fp == NULL)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ *minor = -1;
|
||||||
|
+
|
||||||
|
+ while (fscanf(fp, "%31[^:]: %d\n", field, &value) == 2)
|
||||||
|
+ {
|
||||||
|
+ field[31] = '\0';
|
||||||
|
+ if (strcmp(field, "DeviceFileMinor") == 0)
|
||||||
|
+ {
|
||||||
|
+ *minor = value;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fclose(fp);
|
||||||
|
+
|
||||||
|
+ if (*minor < 0)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = snprintf(name, NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
+ NV_CAP_DEVICE_NAME, *minor);
|
||||||
|
+
|
||||||
|
+ if (ret < 0 || ret >= NV_MAX_CHARACTER_DEVICE_FILE_STRLEN)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Attempt to create the NVIDIA capability device files.
|
||||||
|
+ */
|
||||||
|
+int nvidia_cap_mknod(const char* cap_file_path, int *minor)
|
||||||
|
+{
|
||||||
|
+ int major;
|
||||||
|
+ char name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = nvidia_cap_get_device_file_attrs(cap_file_path, &major, minor, name);
|
||||||
|
+ if (ret == 0)
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = mkdir("/dev/"NV_CAPS_MODULE_NAME, 0755);
|
||||||
|
+ if ((ret != 0) && (errno != EEXIST))
|
||||||
|
+ {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return mknod_helper(major, *minor, name, cap_file_path);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int nvidia_cap_get_file_state(const char* cap_file_path)
|
||||||
|
+{
|
||||||
|
+ char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
|
||||||
|
+ mode_t mode;
|
||||||
|
+ uid_t uid;
|
||||||
|
+ gid_t gid;
|
||||||
|
+ int modification_allowed;
|
||||||
|
+ int ret;
|
||||||
|
+ int major;
|
||||||
|
+ int minor;
|
||||||
|
+
|
||||||
|
+ ret = nvidia_cap_get_device_file_attrs(cap_file_path, &major, &minor, path);
|
||||||
|
+ if (ret == 0)
|
||||||
|
+ {
|
||||||
|
+ path[0] = '\0';
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ init_device_file_parameters(&uid, &gid, &mode, &modification_allowed,
|
||||||
|
+ cap_file_path);
|
||||||
|
+
|
||||||
|
+ return get_file_state_helper(path, major, minor,
|
||||||
|
+ cap_file_path, uid, gid, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
-#endif /* NV_LINUX */
|
||||||
|
\ No newline at end of file
|
||||||
|
+#endif /* NV_LINUX */
|
|
@ -0,0 +1,118 @@
|
||||||
|
--- a/src/nvidia-modprobe-utils.h 2020-09-18 18:11:57.046187358 +0800
|
||||||
|
+++ b/src/nvidia-modprobe-utils.h 2020-09-18 23:35:14.062948666 +0800
|
||||||
|
@@ -31,29 +31,20 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define NV_MAX_CHARACTER_DEVICE_FILE_STRLEN 128
|
||||||
|
-#define NV_MODULE_INSTANCE_NONE -1
|
||||||
|
-#define NV_MODULE_INSTANCE_ZERO 0
|
||||||
|
-#define NV_MAX_MODULE_INSTANCES 8
|
||||||
|
#define NV_CTL_DEVICE_NUM 255
|
||||||
|
#define NV_MODESET_MINOR_DEVICE_NUM 254
|
||||||
|
-
|
||||||
|
-#define NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX NV_CTL_DEVICE_NUM
|
||||||
|
+#define NV_NVSWITCH_CTL_MINOR 255
|
||||||
|
|
||||||
|
#define NV_DEVICE_FILE_PATH "/dev/nvidia%d"
|
||||||
|
#define NV_CTRL_DEVICE_FILE_PATH "/dev/nvidiactl"
|
||||||
|
#define NV_MODESET_DEVICE_NAME "/dev/nvidia-modeset"
|
||||||
|
#define NV_VGPU_VFIO_DEVICE_NAME "/dev/nvidia-vgpu%d"
|
||||||
|
#define NV_NVLINK_DEVICE_NAME "/dev/nvidia-nvlink"
|
||||||
|
+#define NV_NVSWITCH_CTL_NAME "/dev/nvidia-nvswitchctl"
|
||||||
|
+#define NV_NVSWITCH_DEVICE_NAME "/dev/nvidia-nvswitch%d"
|
||||||
|
|
||||||
|
-#define NV_NMODULE_CTRL_DEVICE_FILE_PATH "/dev/nvidiactl%d"
|
||||||
|
-
|
||||||
|
-#define NV_FRONTEND_CONTROL_DEVICE_MINOR_MIN \
|
||||||
|
- (NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX - \
|
||||||
|
- NV_MAX_MODULE_INSTANCES)
|
||||||
|
-
|
||||||
|
-#define NV_FRONTEND_IS_CONTROL_DEVICE(x) \
|
||||||
|
- ((x <= NV_FRONTEND_CONTROL_DEVICE_MINOR_MAX) && \
|
||||||
|
- (x > NV_FRONTEND_CONTROL_DEVICE_MINOR_MIN))
|
||||||
|
+#define NV_CAPS_MODULE_NAME "nvidia-caps"
|
||||||
|
+#define NV_CAP_DEVICE_NAME "/dev/" NV_CAPS_MODULE_NAME "/nvidia-cap%d"
|
||||||
|
|
||||||
|
#if defined(NV_LINUX)
|
||||||
|
|
||||||
|
@@ -76,40 +67,33 @@
|
||||||
|
return !!(state & (1 << value));
|
||||||
|
}
|
||||||
|
|
||||||
|
-int nvidia_get_file_state(int minor, int module_instance);
|
||||||
|
-int nvidia_modprobe(const int print_errors, int module_instance);
|
||||||
|
-int nvidia_mknod(int minor, int module_instance);
|
||||||
|
+int nvidia_get_file_state(int minor);
|
||||||
|
+int nvidia_modprobe(const int print_errors);
|
||||||
|
+int nvidia_mknod(int minor);
|
||||||
|
int nvidia_uvm_modprobe(void);
|
||||||
|
int nvidia_uvm_mknod(int base_minor);
|
||||||
|
int nvidia_modeset_modprobe(void);
|
||||||
|
int nvidia_modeset_mknod(void);
|
||||||
|
int nvidia_vgpu_vfio_mknod(int minor_num);
|
||||||
|
int nvidia_nvlink_mknod(void);
|
||||||
|
-
|
||||||
|
-int mknod_helper(int major, int minor, const char *path, const char *proc_path);
|
||||||
|
-int get_chardev_major(const char *name);
|
||||||
|
+int nvidia_nvlink_get_file_state(void);
|
||||||
|
+int nvidia_nvswitch_mknod(int minor);
|
||||||
|
+int nvidia_nvswitch_get_file_state(int minor);
|
||||||
|
+int nvidia_cap_mknod(const char* cap_file_path, int *minor);
|
||||||
|
+int nvidia_cap_get_file_state(const char* cap_file_path);
|
||||||
|
+int nvidia_cap_get_device_file_attrs(const char* cap_file_path, int *major, int *minor, char *name);
|
||||||
|
+int nvidia_get_chardev_major(const char *name);
|
||||||
|
|
||||||
|
#endif /* NV_LINUX */
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * Detect use of multiple kernel module instances. Use a single
|
||||||
|
- * module instance unless instance != NV_MODULE_INSTANCE_NONE
|
||||||
|
- */
|
||||||
|
-static __inline__ int is_multi_module(int module_instance)
|
||||||
|
-{
|
||||||
|
- return (module_instance != NV_MODULE_INSTANCE_NONE);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/*
|
||||||
|
* Construct the device file name, based on 'minor'. If an error
|
||||||
|
* occurs, the nul terminator will be written to name[0].
|
||||||
|
*/
|
||||||
|
static __inline__ void assign_device_file_name
|
||||||
|
(
|
||||||
|
char name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN],
|
||||||
|
- int minor,
|
||||||
|
- int module_instance
|
||||||
|
+ int minor
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
@@ -119,20 +102,12 @@
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (!is_multi_module(module_instance) && minor == NV_CTL_DEVICE_NUM)
|
||||||
|
+ if (minor == NV_CTL_DEVICE_NUM)
|
||||||
|
{
|
||||||
|
ret = snprintf(name,
|
||||||
|
NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
NV_CTRL_DEVICE_FILE_PATH);
|
||||||
|
}
|
||||||
|
- else if (is_multi_module(module_instance) &&
|
||||||
|
- NV_FRONTEND_IS_CONTROL_DEVICE(minor))
|
||||||
|
- {
|
||||||
|
- ret = snprintf(name,
|
||||||
|
- NV_MAX_CHARACTER_DEVICE_FILE_STRLEN,
|
||||||
|
- NV_NMODULE_CTRL_DEVICE_FILE_PATH,
|
||||||
|
- module_instance);
|
||||||
|
- }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = snprintf(name,
|
||||||
|
@@ -154,4 +129,4 @@
|
||||||
|
name[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
-#endif /* __NVIDIA_MODPROBE_UTILS_H__ */
|
||||||
|
\ No newline at end of file
|
||||||
|
+#endif /* __NVIDIA_MODPROBE_UTILS_H__ */
|
|
@ -0,0 +1,11 @@
|
||||||
|
--- a/src/nvc_info.c 2020-09-16 20:30:14.000000000 +0800
|
||||||
|
+++ b/src/nvc_info.c 2020-09-18 18:06:55.562176348 +0800
|
||||||
|
@@ -6,7 +6,7 @@
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
-#include <nvidia-modprobe-utils.h>
|
||||||
|
+#include "nvidia-modprobe-utils.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
|
@ -0,0 +1,11 @@
|
||||||
|
--- a/src/nvc_mount.c 2020-09-16 20:30:14.000000000 +0800
|
||||||
|
+++ b/src/nvc_mount.c 2020-09-18 18:00:17.984906768 +0800
|
||||||
|
@@ -10,7 +10,7 @@
|
||||||
|
#include <libgen.h>
|
||||||
|
#undef basename /* Use the GNU version of basename. */
|
||||||
|
#include <limits.h>
|
||||||
|
-#include <nvidia-modprobe-utils.h>
|
||||||
|
+#include "nvidia-modprobe-utils.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sched.h>
|
|
@ -0,0 +1,13 @@
|
||||||
|
diff --git a/mk/common.mk b/mk/common.mk
|
||||||
|
index bded646..572adfc 100644
|
||||||
|
--- a/mk/common.mk
|
||||||
|
+++ b/mk/common.mk
|
||||||
|
@@ -26,7 +26,7 @@
|
||||||
|
else
|
||||||
|
DATE := $(shell date -u --iso-8601=minutes)
|
||||||
|
endif
|
||||||
|
-REVISION ?= $(shell git rev-parse HEAD)
|
||||||
|
+REVISION ?= 0b7fa90ce0721b010a5e80ecf53ceb43280a33b4
|
||||||
|
COMPILER := $(realpath $(shell which $(CC)))
|
||||||
|
PLATFORM ?= $(shell uname -m)
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 0070ada..8643de0 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -14,22 +14,22 @@
|
||||||
|
|
||||||
|
.PHONY: all tools shared static deps install uninstall dist depsclean mostlyclean clean distclean
|
||||||
|
.DEFAULT_GOAL := all
|
||||||
|
-
|
||||||
|
+STRIP := @echo skipping: strip
|
||||||
|
##### Global variables #####
|
||||||
|
|
||||||
|
-WITH_NVCGO ?= yes
|
||||||
|
-WITH_LIBELF ?= no
|
||||||
|
-WITH_TIRPC ?= no
|
||||||
|
+WITH_NVCGO ?= yes
|
||||||
|
+WITH_LIBELF ?= yes
|
||||||
|
+WITH_TIRPC ?= yes
|
||||||
|
WITH_SECCOMP ?= yes
|
||||||
|
|
||||||
|
##### Global definitions #####
|
||||||
|
|
||||||
|
-export prefix = /usr/local
|
||||||
|
+export prefix = /usr
|
||||||
|
export exec_prefix = $(prefix)
|
||||||
|
export bindir = $(exec_prefix)/bin
|
||||||
|
-export libdir = $(exec_prefix)/lib
|
||||||
|
+export libdir = $(exec_prefix)/lib64
|
||||||
|
export docdir = $(prefix)/share/doc
|
||||||
|
-export libdbgdir = $(prefix)/lib/debug$(libdir)
|
||||||
|
+export libdbgdir = $(prefix)/lib64/debug$(libdir)
|
||||||
|
export includedir = $(prefix)/include
|
||||||
|
export pkgconfdir = $(libdir)/pkgconfig
|
||||||
|
|
||||||
|
@@ -62,6 +62,8 @@
|
||||||
|
$(SRCS_DIR)/error_generic.c \
|
||||||
|
$(SRCS_DIR)/error.c \
|
||||||
|
$(SRCS_DIR)/ldcache.c \
|
||||||
|
+ $(SRCS_DIR)/pci-sysfs.c \
|
||||||
|
+ $(SRCS_DIR)/nvidia-modprobe-utils.c \
|
||||||
|
$(SRCS_DIR)/nvc.c \
|
||||||
|
$(SRCS_DIR)/nvc_ldcache.c \
|
||||||
|
$(SRCS_DIR)/nvc_info.c \
|
||||||
|
@@ -144,7 +146,7 @@
|
||||||
|
-Wall -Wextra -Wcast-align -Wpointer-arith -Wmissing-prototypes -Wnonnull \
|
||||||
|
-Wwrite-strings -Wlogical-op -Wformat=2 -Wmissing-format-attribute -Winit-self -Wshadow \
|
||||||
|
-Wstrict-prototypes -Wunreachable-code -Wconversion -Wsign-conversion \
|
||||||
|
- -Wno-unknown-warning-option -Wno-format-extra-args -Wno-gnu-alignof-expression $(CFLAGS)
|
||||||
|
+ -Wno-unknown-warning-option -Wno-format-extra-args -Wno-gnu-alignof-expression -I/usr/include/tirpc $(CFLAGS)
|
||||||
|
LDFLAGS := -Wl,-zrelro -Wl,-znow -Wl,-zdefs -Wl,--gc-sections $(LDFLAGS)
|
||||||
|
LDLIBS := $(LDLIBS)
|
||||||
|
|
||||||
|
@@ -152,8 +154,8 @@
|
||||||
|
LIB_CPPFLAGS = -DNV_LINUX -isystem $(DEPS_DIR)$(includedir) -include $(BUILD_DEFS)
|
||||||
|
LIB_CFLAGS = -fPIC
|
||||||
|
LIB_LDFLAGS = -L$(DEPS_DIR)$(libdir) -shared -Wl,-soname=$(LIB_SONAME)
|
||||||
|
-LIB_LDLIBS_STATIC = -l:libnvidia-modprobe-utils.a
|
||||||
|
-LIB_LDLIBS_SHARED = -ldl -lcap
|
||||||
|
+# LIB_LDLIBS_STATIC = -l:libnvidia-modprobe-utils.a
|
||||||
|
+LIB_LDLIBS_SHARED = -ldl -lcap -ltirpc
|
||||||
|
ifeq ($(WITH_NVCGO), yes)
|
||||||
|
LIB_CPPFLAGS += -DWITH_NVCGO
|
||||||
|
LIB_LDLIBS_SHARED += -lpthread
|
||||||
|
@@ -166,7 +168,7 @@
|
||||||
|
endif
|
||||||
|
ifeq ($(WITH_TIRPC), yes)
|
||||||
|
LIB_CPPFLAGS += -isystem $(DEPS_DIR)$(includedir)/tirpc -DWITH_TIRPC
|
||||||
|
-LIB_LDLIBS_STATIC += -l:libtirpc.a
|
||||||
|
+# LIB_LDLIBS_STATIC += -l:libtirpc.a
|
||||||
|
LIB_LDLIBS_SHARED += -lpthread
|
||||||
|
endif
|
||||||
|
ifeq ($(WITH_SECCOMP), yes)
|
||||||
|
@@ -181,7 +183,7 @@
|
||||||
|
LIB_LDLIBS = $(LIB_LDLIBS_STATIC) $(LIB_LDLIBS_SHARED)
|
||||||
|
|
||||||
|
# Binary flags (recursively expanded to handle target-specific flags)
|
||||||
|
-BIN_CPPFLAGS = -include $(BUILD_DEFS) $(CPPFLAGS)
|
||||||
|
+BIN_CPPFLAGS = -include $(BUILD_DEFS) $(CPPFLAGS) -DWITH_TIRPC
|
||||||
|
BIN_CFLAGS = -I$(SRCS_DIR) -fPIE -flto $(CFLAGS)
|
||||||
|
BIN_LDFLAGS = -L. -pie $(LDFLAGS) -Wl,-rpath='$$ORIGIN/../$$LIB'
|
||||||
|
BIN_LDLIBS = -l:$(LIB_SHARED) -ldl -lcap $(LDLIBS)
|
||||||
|
@@ -258,15 +260,15 @@
|
||||||
|
|
||||||
|
deps: $(LIB_RPC_SRCS) $(BUILD_DEFS)
|
||||||
|
$(MKDIR) -p $(DEPS_DIR)
|
||||||
|
- $(MAKE) -f $(MAKE_DIR)/nvidia-modprobe.mk DESTDIR=$(DEPS_DIR) install
|
||||||
|
+ # $(MAKE) -f $(MAKE_DIR)/nvidia-modprobe.mk DESTDIR=$(DEPS_DIR) install
|
||||||
|
ifeq ($(WITH_NVCGO), yes)
|
||||||
|
$(MAKE) -f $(MAKE_DIR)/nvcgo.mk DESTDIR=$(DEPS_DIR) MAJOR=$(MAJOR) VERSION=$(VERSION) LIB_NAME=$(LIBGO_NAME) install
|
||||||
|
endif
|
||||||
|
ifeq ($(WITH_LIBELF), no)
|
||||||
|
- $(MAKE) -f $(MAKE_DIR)/elftoolchain.mk DESTDIR=$(DEPS_DIR) install
|
||||||
|
+ # $(MAKE) -f $(MAKE_DIR)/elftoolchain.mk DESTDIR=$(DEPS_DIR) install
|
||||||
|
endif
|
||||||
|
ifeq ($(WITH_TIRPC), yes)
|
||||||
|
- $(MAKE) -f $(MAKE_DIR)/libtirpc.mk DESTDIR=$(DEPS_DIR) install
|
||||||
|
+ # $(MAKE) -f $(MAKE_DIR)/libtirpc.mk DESTDIR=$(DEPS_DIR) install
|
||||||
|
endif
|
||||||
|
|
||||||
|
install: all
|
||||||
|
@@ -283,7 +285,7 @@
|
||||||
|
endif
|
||||||
|
$(LDCONFIG) -n $(DESTDIR)$(libdir)
|
||||||
|
# Install debugging symbols
|
||||||
|
- $(INSTALL) -m 644 $(DEBUG_DIR)/$(LIB_SONAME) $(DESTDIR)$(libdbgdir)
|
||||||
|
+ # $(INSTALL) -m 644 $(DEBUG_DIR)/$(LIB_SONAME) $(DESTDIR)$(libdbgdir)
|
||||||
|
# Install configuration files
|
||||||
|
$(MAKE_DIR)/$(LIB_PKGCFG).in "$(strip $(VERSION))" "$(strip $(LIB_LDLIBS_SHARED))" > $(DESTDIR)$(pkgconfdir)/$(LIB_PKGCFG)
|
||||||
|
# Install binary files
|
|
@ -0,0 +1,13 @@
|
||||||
|
diff --git a/mk/nvcgo.mk b/mk/nvcgo.mk
|
||||||
|
index 0070ada..8643de0 100644
|
||||||
|
--- a/mk/nvcgo.mk
|
||||||
|
+++ b/mk/nvcgo.mk
|
||||||
|
@@ -26,7 +26,8 @@
|
||||||
|
|
||||||
|
build:
|
||||||
|
$(RM) -rf $(SRCS_DIR)
|
||||||
|
- $(CP) -R $(CURDIR)/src/$(PREFIX) $(SRCS_DIR)
|
||||||
|
+ mkdir -p $(SRCS_DIR)
|
||||||
|
+ $(CP) -r $(CURDIR)/src/$(PREFIX)/. $(SRCS_DIR)
|
||||||
|
$(MAKE) -C $(SRCS_DIR) VERSION=$(VERSION) clean
|
||||||
|
$(MAKE) -C $(SRCS_DIR) VERSION=$(VERSION) build
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Copyright 1999-2023 Gentoo Authors
|
||||||
|
# Distributed under the terms of the GNU General Public License v2
|
||||||
|
|
||||||
|
EAPI=8
|
||||||
|
|
||||||
|
DESCRIPTION="NVIDIA container runtime library"
|
||||||
|
HOMEPAGE="https://github.com/NVIDIA/libnvidia-container"
|
||||||
|
|
||||||
|
if [[ "${PV}" == "9999" ]] ; then
|
||||||
|
inherit git-r3
|
||||||
|
EGIT_REPO_URI="https://github.com/NVIDIA/${PN}.git"
|
||||||
|
else
|
||||||
|
SRC_URI="
|
||||||
|
https://github.com/NVIDIA/${PN}/archive/v${PV/_rc/-rc.}.tar.gz -> ${P}.tar.gz
|
||||||
|
"
|
||||||
|
S="${WORKDIR}/${PN}-${PV/_rc/-rc.}"
|
||||||
|
KEYWORDS="~amd64"
|
||||||
|
fi
|
||||||
|
|
||||||
|
LICENSE="Apache-2.0"
|
||||||
|
SLOT="0"
|
||||||
|
|
||||||
|
IUSE=""
|
||||||
|
|
||||||
|
RDEPEND="
|
||||||
|
net-libs/libtirpc
|
||||||
|
sys-libs/libcap
|
||||||
|
sys-libs/libseccomp
|
||||||
|
x11-drivers/nvidia-drivers
|
||||||
|
"
|
||||||
|
|
||||||
|
DEPEND="${RDEPEND}"
|
||||||
|
|
||||||
|
BDEPEND="
|
||||||
|
net-libs/rpcsvc-proto
|
||||||
|
sys-apps/lsb-release
|
||||||
|
sys-devel/bmake
|
||||||
|
virtual/pkgconfig
|
||||||
|
"
|
||||||
|
|
||||||
|
PATCHES=(
|
||||||
|
"${FILESDIR}"/${PN}-1.1.1-add-enum-h.patch
|
||||||
|
"${FILESDIR}"/${PN}-1.1.1-add-sysfs-c.patch
|
||||||
|
"${FILESDIR}"/${PN}-1.1.1-add-sysfs-h.patch
|
||||||
|
"${FILESDIR}"/${PN}-1.1.1-add-utils-c.patch
|
||||||
|
"${FILESDIR}"/${PN}-1.1.1-add-utils-h.patch
|
||||||
|
"${FILESDIR}"/${PN}-1.7.0-fix-git.patch
|
||||||
|
"${FILESDIR}"/${PN}-1.8.0-fix-makefile.patch
|
||||||
|
"${FILESDIR}"/${PN}-1.1.1-fix-nvc.patch
|
||||||
|
"${FILESDIR}"/${PN}-1.3.0-fix-nvc-info.patch
|
||||||
|
"${FILESDIR}"/${PN}-1.3.0-fix-nvc-mount.patch
|
||||||
|
"${FILESDIR}"/${PN}-1.3.0-fix-modprobe-utils-c.patch
|
||||||
|
"${FILESDIR}"/${PN}-1.3.0-fix-modprobe-utils-h.patch
|
||||||
|
"${FILESDIR}"/${PN}-1.8.0-fix-nvcgomk.patch
|
||||||
|
)
|
Loading…
Reference in New Issue