All of lore.kernel.org
 help / color / mirror / Atom feed
* [Buildroot] [PATCH v3 1/5] package/nvidia-modprobe: new package
@ 2020-11-18  2:52 Christian Stewart
  2020-11-18  2:52 ` [Buildroot] [PATCH v3 2/5] package/linux4tegra: " Christian Stewart
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Christian Stewart @ 2020-11-18  2:52 UTC (permalink / raw)
  To: buildroot

nvidia-modprobe package adds a utility and headers for probing the NVIDIA
hardware at runtime.

https://github.com/NVIDIA/nvidia-modprobe

Signed-off-by: Christian Stewart <christian@paral.in>
---
 package/Config.in                            |  1 +
 package/nvidia-modprobe/Config.in            | 12 ++++++
 package/nvidia-modprobe/nvidia-modprobe.hash |  3 ++
 package/nvidia-modprobe/nvidia-modprobe.mk   | 45 ++++++++++++++++++++
 4 files changed, 61 insertions(+)
 create mode 100644 package/nvidia-modprobe/Config.in
 create mode 100644 package/nvidia-modprobe/nvidia-modprobe.hash
 create mode 100644 package/nvidia-modprobe/nvidia-modprobe.mk

diff --git a/package/Config.in b/package/Config.in
index 016a99ed1a..fa1b5d35e9 100644
--- a/package/Config.in
+++ b/package/Config.in
@@ -502,6 +502,7 @@ endmenu
 	source "package/nanocom/Config.in"
 	source "package/neard/Config.in"
 	source "package/nvidia-driver/Config.in"
+	source "package/nvidia-modprobe/Config.in"
 	source "package/nvme/Config.in"
 	source "package/ofono/Config.in"
 	source "package/on2-8170-modules/Config.in"
diff --git a/package/nvidia-modprobe/Config.in b/package/nvidia-modprobe/Config.in
new file mode 100644
index 0000000000..35953a33d4
--- /dev/null
+++ b/package/nvidia-modprobe/Config.in
@@ -0,0 +1,12 @@
+config BR2_PACKAGE_NVIDIA_MODPROBE
+	bool "nvidia-modprobe"
+	depends on BR2_TOOLCHAIN_HAS_THREADS
+	depends on BR2_TOOLCHAIN_USES_GLIBC
+	help
+	  nvidia-modprobe package adds a utility and headers for
+	  probing the NVIDIA hardware at runtime.
+
+	  https://github.com/NVIDIA/nvidia-modprobe
+
+comment "nvidia-modprobe needs a glibc toolchain w/ threads"
+	depends on !BR2_TOOLCHAIN_HAS_THREADS || !BR2_TOOLCHAN_USES_GLIBC
diff --git a/package/nvidia-modprobe/nvidia-modprobe.hash b/package/nvidia-modprobe/nvidia-modprobe.hash
new file mode 100644
index 0000000000..99908680f0
--- /dev/null
+++ b/package/nvidia-modprobe/nvidia-modprobe.hash
@@ -0,0 +1,3 @@
+# Locally computed:
+sha256 396b4102d3075a2dee3024652fae206a1b38ace54b8efb1e2c20757a11ec19f1  nvidia-modprobe-450.57.tar.gz
+sha256 8177f97513213526df2cf6184d8ff986c675afb514d4e68a404010521b880643  COPYING
diff --git a/package/nvidia-modprobe/nvidia-modprobe.mk b/package/nvidia-modprobe/nvidia-modprobe.mk
new file mode 100644
index 0000000000..7eeee6716c
--- /dev/null
+++ b/package/nvidia-modprobe/nvidia-modprobe.mk
@@ -0,0 +1,45 @@
+################################################################################
+#
+# nvidia-modprobe
+#
+################################################################################
+
+NVIDIA_MODPROBE_VERSION = 450.57
+NVIDIA_MODPROBE_SITE = $(call github,NVIDIA,nvidia-modprobe,$(NVIDIA_MODPROBE_VERSION))
+NVIDIA_MODPROBE_LICENSE = GPL-2
+NVIDIA_MODPROBE_LICENSE_FILES = COPYING
+
+NVIDIA_MODPROBE_DEPENDENCIES = host-pkgconf
+NVIDIA_MODPROBE_INSTALL_STAGING = YES
+
+define NVIDIA_MODPROBE_BUILD_CMDS
+	mkdir -p $(@D)/bin
+	$(TARGET_MAKE_ENV) $(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_LDFLAGS) \
+		-I $(@D)/common-utils -I $(@D)/modprobe-utils \
+		-o $(@D)/bin/nvidia-modprobe \
+		-DNV_LINUX=true -DPROGRAM_NAME=\"nvidia-modprobe\" \
+		-DNVIDIA_VERSION=\"$(NVIDIA_MODPROBE_VERSION)\" \
+		$(@D)/nvidia-modprobe.c $(@D)/modprobe-utils/nvidia-modprobe-utils.c \
+		$(@D)/modprobe-utils/pci-sysfs.c $(@D)/common-utils/common-utils.c \
+		$(@D)/common-utils/msg.c $(@D)/common-utils/nvgetopt.c
+endef
+
+define NVIDIA_MODPROBE_INSTALL_STAGING_CMDS
+	$(INSTALL) -D -m 644 $(@D)/modprobe-utils/nvidia-modprobe-utils.h \
+		$(STAGING_DIR)/usr/include/nvidia-modprobe-utils/nvidia-modprobe-utils.h
+	$(INSTALL) -D -m 644 $(@D)/modprobe-utils/pci-enum.h \
+		$(STAGING_DIR)/usr/include/nvidia-modprobe-utils/pci-enum.h
+	$(INSTALL) -D -m 644 $(@D)/common-utils/common-utils.h \
+		$(STAGING_DIR)/usr/include/nvidia-modprobe-utils/nvidia-common-utils.h
+	$(INSTALL) -D -m 644 $(@D)/common-utils/msg.h \
+		$(STAGING_DIR)/usr/include/nvidia-modprobe-utils/msg.h
+	$(INSTALL) -D -m 644 $(@D)/common-utils/nvgetopt.h \
+		$(STAGING_DIR)/usr/include/nvidia-modprobe-utils/nvgetopt.h
+endef
+
+define NVIDIA_MODPROBE_INSTALL_TARGET_CMDS
+	$(INSTALL) -m 0755 $(@D)/bin/nvidia-modprobe \
+		$(TARGET_DIR)/usr/bin/nvidia-modprobe
+endef
+
+$(eval $(generic-package))
-- 
2.29.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Buildroot] [PATCH v3 2/5] package/linux4tegra: new package
  2020-11-18  2:52 [Buildroot] [PATCH v3 1/5] package/nvidia-modprobe: new package Christian Stewart
@ 2020-11-18  2:52 ` Christian Stewart
  2020-11-18  2:52 ` [Buildroot] [PATCH v3 3/5] package/libnvidia-container: " Christian Stewart
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Christian Stewart @ 2020-11-18  2:52 UTC (permalink / raw)
  To: buildroot

NVIDIA Linux4Tegra utilities and binaries.

https://developer.nvidia.com/embedded/linux-tegra-archive

Signed-off-by: Christian Stewart <christian@paral.in>

v1 -> v2:

 - cjs: add license hashes

v2 -> v3:

 - cjs: fix broken LICENSE hash
 - cjs: add support for t210ref

Signed-off-by: Christian Stewart <christian@paral.in>
---
 package/Config.in                             |   1 +
 ...for-flashing-Buildroot-produced-disk.patch |  58 +++++++++
 package/linux4tegra/Config.in                 |  28 ++++
 package/linux4tegra/linux4tegra.hash          |  55 ++++++++
 package/linux4tegra/linux4tegra.mk            | 120 ++++++++++++++++++
 5 files changed, 262 insertions(+)
 create mode 100644 package/linux4tegra/0001-Adjust-flash.sh-for-flashing-Buildroot-produced-disk.patch
 create mode 100644 package/linux4tegra/Config.in
 create mode 100644 package/linux4tegra/linux4tegra.hash
 create mode 100644 package/linux4tegra/linux4tegra.mk

diff --git a/package/Config.in b/package/Config.in
index fa1b5d35e9..01072c3e45 100644
--- a/package/Config.in
+++ b/package/Config.in
@@ -482,6 +482,7 @@ endmenu
 	source "package/libuio/Config.in"
 	source "package/linux-backports/Config.in"
 	source "package/linux-serial-test/Config.in"
+	source "package/linux4tegra/Config.in"
 	source "package/linuxconsoletools/Config.in"
 	source "package/lirc-tools/Config.in"
 	source "package/lm-sensors/Config.in"
diff --git a/package/linux4tegra/0001-Adjust-flash.sh-for-flashing-Buildroot-produced-disk.patch b/package/linux4tegra/0001-Adjust-flash.sh-for-flashing-Buildroot-produced-disk.patch
new file mode 100644
index 0000000000..4ace27bddc
--- /dev/null
+++ b/package/linux4tegra/0001-Adjust-flash.sh-for-flashing-Buildroot-produced-disk.patch
@@ -0,0 +1,58 @@
+From fbd0d35995a23351d4b50ed0b814442a6873ded2 Mon Sep 17 00:00:00 2001
+From: Christian Stewart <christian@paral.in>
+Date: Fri, 17 Jul 2020 13:58:43 -0700
+Subject: [PATCH] Adjust flash.sh for flashing Buildroot-produced disk image
+
+Signed-off-by: Christian Stewart <christian@paral.in>
+---
+ flash.sh | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+diff --git a/flash.sh b/flash.sh
+index 38c0cbb..c27b41b 100755
+--- a/flash.sh
++++ b/flash.sh
+@@ -1339,9 +1339,10 @@ elif [ "${target_rootdev}" == "internal" ] || \
+ 		usage allunknown 1;
+ 	fi
+ 
+-	cmdline+="root=PARTUUID=${rootfsuuid} rw rootwait rootfstype=ext4 "
++	# cmdline+="root=PARTUUID=${rootfsuuid} rw rootwait rootfstype=ext4 "
++	cmdline+="root=/dev/${target_rootdev} rw rootwait"
+ else
+-	cmdline+="root=/dev/${target_rootdev} rw rootwait rootfstype=ext4 "
++	cmdline+="root=/dev/${target_rootdev} rw rootwait"
+ fi;
+ 
+ if [ "${CMDLINE_ADD}" != "" ]; then
+@@ -1512,11 +1513,7 @@ if [ "${write_image_name}" != "" ]; then
+ 	fi
+ fi
+ 
+-if [ "${INITRD_IN_BOOTIMG}" = "yes" ]; then
+-	ramdisk=initrd;
+-else
+-	ramdisk="/dev/null"
+-fi
++ramdisk="/dev/null"
+ echo -n "Making Boot image... ";
+ MKBOOTARG+="--kernel ${kernel_image} ";
+ MKBOOTARG+="--ramdisk ${ramdisk} ";
+@@ -1977,8 +1974,12 @@ if [ "${reuse_systemimg}" = "true" ] || [ "${skip_systemimg}" = "true" ]; then
+ elif [ "${rootdev_type}" = "internal" ]; then
+ 	APP_TAG+="-e s/APPFILE/${localsysfile}/ ";
+ 	if [ "${target_partname}" = "" -o "${target_partname}" = "APP" ]; then
+-		build_fsimg "$localsysfile" "$fillpat" \
+-		    "$rootfssize" "$rootfs_type" "$rootfs_dir" "$cmdline";
++    echo "Skipping image build and setting target_partfile to INITRD."
++    # target_partfile=${INITRD}
++    # cp ${INITRD} ./system.img
++    ln -fs ${INITRD} ./system.img
++		#build_fsimg "$localsysfile" "$fillpat" \
++		#    "$rootfssize" "$rootfs_type" "$rootfs_dir" "$cmdline";
+ 	fi;
+ elif [ "${rootdev_type}" = "network" -o "${rootdev_type}" = "external" ]; then
+ 	APP_TAG+="-e s/APPFILE/${localsysfile}/ ";
+-- 
+2.27.0
+
diff --git a/package/linux4tegra/Config.in b/package/linux4tegra/Config.in
new file mode 100644
index 0000000000..71f29494dc
--- /dev/null
+++ b/package/linux4tegra/Config.in
@@ -0,0 +1,28 @@
+config BR2_PACKAGE_LINUX4TEGRA
+	bool "linux4tegra"
+	help
+	  NVIDIA Linux4Tegra utilities and binaries.
+
+	  https://developer.nvidia.com/embedded/linux-tegra-archive
+
+if BR2_PACKAGE_LINUX4TEGRA
+
+choice
+	prompt "Platform"
+	default BR2_PACKAGE_LINUX4TEGRA_PLATFORM_T186REF
+	help
+	  Select the platform variant for linux4tegra.
+
+config BR2_PACKAGE_LINUX4TEGRA_PLATFORM_T186REF
+	bool "t186ref"
+	help
+	  Jetson AGX Xavier, Xavier NX, or TX2
+
+config BR2_PACKAGE_LINUX4TEGRA_PLATFORM_T210REF
+	bool "t210ref"
+	help
+	  Jetson Nano or Jetson TX1
+
+endchoice
+
+endif # if BR2_PACKAGE_LINUX4TEGRA
diff --git a/package/linux4tegra/linux4tegra.hash b/package/linux4tegra/linux4tegra.hash
new file mode 100644
index 0000000000..5e5f9b02c8
--- /dev/null
+++ b/package/linux4tegra/linux4tegra.hash
@@ -0,0 +1,55 @@
+# locally computed
+sha256	9a2d13b1f4b67fef97a428d54724b23e84e14636eedfa22f338c2d1ea62558e2  Tegra186_Linux_R32.4.3_aarch64.tbz2
+sha256	0c8590218be814eeec2a6f8b4fd01271893e4881ef2c66d130792c1d62737642  Tegra210_Linux_R32.4.3_aarch64.tbz2
+sha256	bd28b0c5aeeb00eb11d3ec6f6f3449d4b3a40100914258332734a53527997526  bootloader/LICENSE
+sha256	496f3bc5456694cce764d28a93565bb0d0967dbd95256759e4168a9587406949  bootloader/LICENSE.adsp
+sha256	d4885fa44934935d6a178c84a16aec49dae1bd4f41f14bbbd781bafcf704885f  bootloader/LICENSE.bpmp
+sha256	fd4513e2857a0d91c521dfbb924733563b55d5a2d42d4fb688d2506ed34df0c4  bootloader/LICENSE.bpmp_t194
+sha256	205a391eb9cfc69854cc0c3082de204d30124607cedecbdd3f47420b5f37f302  bootloader/LICENSE.camera-rtcpu
+sha256	3cc8cfbf77eb7f086d9b6f68de92251ebbcf13fd7a20fec2749cab30348bf9b1  bootloader/LICENSE.cboot
+sha256	3cc8cfbf77eb7f086d9b6f68de92251ebbcf13fd7a20fec2749cab30348bf9b1  bootloader/LICENSE.cboot_t194
+sha256	bd28b0c5aeeb00eb11d3ec6f6f3449d4b3a40100914258332734a53527997526  bootloader/LICENSE.chkbdinfo
+sha256	7bf7d9fae6472452d585ec38dd684daa86dc83638984d1cb14ee35239a868543  bootloader/LICENSE.mce_c10_prod_cr
+sha256	bd28b0c5aeeb00eb11d3ec6f6f3449d4b3a40100914258332734a53527997526  bootloader/LICENSE.mkbctpart
+sha256	9b0ccf575cfd9febc97b8f9967216f06341db2d44abc69df92c3127cc1a2608f  bootloader/LICENSE.mkbootimg
+sha256	bd28b0c5aeeb00eb11d3ec6f6f3449d4b3a40100914258332734a53527997526  bootloader/LICENSE.mkgpt
+sha256	cddaa9d5583a7705cd4734a6af4b421bca9016ba6af854c51efbfcbe19a4a893  bootloader/LICENSE.nv_smd_generator
+sha256	7b699cea50c65de6679ea0617e8276cf24a523d6068e2502e637fadf9bc49713  bootloader/LICENSE.spe.bin
+sha256	7b699cea50c65de6679ea0617e8276cf24a523d6068e2502e637fadf9bc49713  bootloader/LICENSE.spe_t194.bin
+sha256	0ef77b4d7ffb0195540e394863dd969594ba8e21cb4b810822b4d42c1ab8ef72  bootloader/LICENSE.tos-mon-only.img.arm-trusted-firmware
+sha256	0ef77b4d7ffb0195540e394863dd969594ba8e21cb4b810822b4d42c1ab8ef72  bootloader/LICENSE.tos-trusty.img.arm-trusted-firmware
+sha256	5a316570e2f1d43b09e51432e613c408b240d0ea0ce30134a7de16c25b832130  bootloader/LICENSE.tos-trusty.img.trusty
+sha256	0ef77b4d7ffb0195540e394863dd969594ba8e21cb4b810822b4d42c1ab8ef72  bootloader/LICENSE.tos-trusty_t194.img.arm-trusted-firmware
+sha256	5a316570e2f1d43b09e51432e613c408b240d0ea0ce30134a7de16c25b832130  bootloader/LICENSE.tos-trusty_t194.img.trusty
+sha256	bd28b0c5aeeb00eb11d3ec6f6f3449d4b3a40100914258332734a53527997526  nv_tegra/LICENSE
+sha256	bd28b0c5aeeb00eb11d3ec6f6f3449d4b3a40100914258332734a53527997526  nv_tegra/LICENSE
+sha256	a85e1af5d521f0d68aa08806292076bb9bda8a31a496f17063fafab121053e4d  nv_tegra/LICENSE.brcm_patchram_plus
+sha256	88e408dec7796e0440b0bf5131f88f0d97bc4014fc389562ec0d5cc7ed1c45ad  nv_tegra/LICENSE.l4t-usb-device-mode-filesystem.img
+sha256	1467d3bd35f6ad87ffb24c0e665c2d028dda6e943dff66b347f0051370dcf88d  nv_tegra/LICENSE.libnvargus
+sha256	7ea9279fe435e009307da026ea72a1f47ecbdeef3a6a7f6bb04a2dec7bbdfcd5  nv_tegra/LICENSE.libnvcam_imageencoder
+sha256	c19b803d92378a0acc9c7dc02e018022f821b8284a5d918e2628e6d1d9376245  nv_tegra/LICENSE.libnveventlib
+sha256	1f1bf0c752f072a447b1013fc9d76268ddf098c37ddc63988d60e4973cbee2f4  nv_tegra/LICENSE.libnvscf
+sha256	c19b803d92378a0acc9c7dc02e018022f821b8284a5d918e2628e6d1d9376245  nv_tegra/LICENSE.libnvtracebuf
+sha256	b4e0f72b067cd11afa0875d20144423a80b7293e4309cca43190cf8c1d4ba200  nv_tegra/LICENSE.libtegrav4l2
+sha256	8610954adbca6c6b85d8b1ae5613b44b0014e437d32fcad6683bb27541411686  nv_tegra/LICENSE.minigbm
+sha256	cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30  nv_tegra/LICENSE.nvbootctrl
+sha256	fa776c507a543cc43d9d66407cfe5d685f35207fd9631e7fd77ee4f42ef92be6  nv_tegra/LICENSE.nvdla
+sha256	8b6a8553e4a1668a6267b9789bd69ffe105bffd8f2af59e2fc74a5910bb159ab  nv_tegra/LICENSE.weston
+sha256	a34730970264d619f352598bf30295ad505a60fc3a493add8aa851645ce3ea47  nv_tegra/LICENSE.weston-data
+sha256	88e408dec7796e0440b0bf5131f88f0d97bc4014fc389562ec0d5cc7ed1c45ad  nv_tegra/nvidia_configs/opt/nvidia/l4t-usb-device-mode/LICENSE.filesystem.img
+sha256	a85e1af5d521f0d68aa08806292076bb9bda8a31a496f17063fafab121053e4d  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.brcm_patchram_plus
+sha256	89786bfd7060f6a60feae03257da6f3206b0f777352cf750c67b3b560dd087a5  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.cypress_wifibt
+sha256	1467d3bd35f6ad87ffb24c0e665c2d028dda6e943dff66b347f0051370dcf88d  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libnvargus
+sha256	7ea9279fe435e009307da026ea72a1f47ecbdeef3a6a7f6bb04a2dec7bbdfcd5  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libnvcam_imageencoder
+sha256	c19b803d92378a0acc9c7dc02e018022f821b8284a5d918e2628e6d1d9376245  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libnveventlib
+sha256	c19b803d92378a0acc9c7dc02e018022f821b8284a5d918e2628e6d1d9376245  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libnvtracebuf
+sha256	dee27dbeddf4f7d093df765624022e72fb28c818d60fa3fd9d1dd77b392e4d31  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libnvv4l2
+sha256	dee27dbeddf4f7d093df765624022e72fb28c818d60fa3fd9d1dd77b392e4d31  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libnvv4lconvert
+sha256	b4e0f72b067cd11afa0875d20144423a80b7293e4309cca43190cf8c1d4ba200  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libtegrav4l2
+sha256	fbef9c34b63148c0e670e6ac07705b25bebcc1f963b48bf7447ee61cfaadcc1e  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libvulkan1
+sha256	8610954adbca6c6b85d8b1ae5613b44b0014e437d32fcad6683bb27541411686  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.minigbm
+sha256	fa776c507a543cc43d9d66407cfe5d685f35207fd9631e7fd77ee4f42ef92be6  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.nvdla
+sha256	bd28b0c5aeeb00eb11d3ec6f6f3449d4b3a40100914258332734a53527997526  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.realtek_8822ce_wifibt
+sha256	f3f3ecff94537e7d5944fdbae7c6bd02d5eddca8fe1c29d8699ff2e54d26cebc  nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.tegra_sensors
+sha256	cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30  nv_tegra/nvidia_tools/usr/share/doc/nvidia-tegra/LICENSE.nvbootctrl
+sha256	5f28c11f8b1b3f97b9d42c74b85371ebf4127f241b799279bcecd69f7ee542dc  nv_tegra/nvidia_tools/usr/share/doc/nvidia-tegra/LICENSE.tipc_test
diff --git a/package/linux4tegra/linux4tegra.mk b/package/linux4tegra/linux4tegra.mk
new file mode 100644
index 0000000000..48061f4c98
--- /dev/null
+++ b/package/linux4tegra/linux4tegra.mk
@@ -0,0 +1,120 @@
+################################################################################
+#
+# linux4tegra
+#
+################################################################################
+
+LINUX4TEGRA_VERSION = 32.4.3
+
+ifeq ($(BR2_PACKAGE_LINUX4TEGRA_PLATFORM_T186REF),y)
+LINUX4TEGRA_SITE = https://developer.nvidia.com/embedded/L4T/r32_Release_v4.3/t186ref_release_aarch64
+LINUX4TEGRA_SOURCE = Tegra186_Linux_R$(LINUX4TEGRA_VERSION)_aarch64.tbz2
+else # ifeq ($(BR2_PACKAGE_LINUX4TEGRA_PLATFORM_T210REF),y)
+LINUX4TEGRA_SITE = https://developer.nvidia.com/embedded/L4T/r32_Release_v4.3/t210ref_release_aarch64
+LINUX4TEGRA_SOURCE = Tegra210_Linux_R$(LINUX4TEGRA_VERSION)_aarch64.tbz2
+endif
+
+LINUX4TEGRA_LICENSE = NVIDIA Software License, GPL-2.0, LGPL, Apache-2.0, MIT
+LINUX4TEGRA_LICENSE_FILES = \
+	bootloader/LICENSE \
+	bootloader/LICENSE.adsp \
+	bootloader/LICENSE.bpmp \
+	bootloader/LICENSE.bpmp_t194 \
+	bootloader/LICENSE.camera-rtcpu \
+	bootloader/LICENSE.cboot \
+	bootloader/LICENSE.cboot_t194 \
+	bootloader/LICENSE.chkbdinfo \
+	bootloader/LICENSE.mce_c10_prod_cr \
+	bootloader/LICENSE.mkbctpart \
+	bootloader/LICENSE.mkbootimg \
+	bootloader/LICENSE.mkgpt \
+	bootloader/LICENSE.nv_smd_generator \
+	bootloader/LICENSE.spe.bin \
+	bootloader/LICENSE.spe_t194.bin \
+	bootloader/LICENSE.tos-mon-only.img.arm-trusted-firmware \
+	bootloader/LICENSE.tos-trusty.img.arm-trusted-firmware \
+	bootloader/LICENSE.tos-trusty.img.trusty \
+	bootloader/LICENSE.tos-trusty_t194.img.arm-trusted-firmware \
+	bootloader/LICENSE.tos-trusty_t194.img.trusty \
+	nv_tegra/LICENSE \
+	nv_tegra/LICENSE \
+	nv_tegra/LICENSE.brcm_patchram_plus \
+	nv_tegra/LICENSE.l4t-usb-device-mode-filesystem.img \
+	nv_tegra/LICENSE.libnvargus \
+	nv_tegra/LICENSE.libnvcam_imageencoder \
+	nv_tegra/LICENSE.libnveventlib \
+	nv_tegra/LICENSE.libnvscf \
+	nv_tegra/LICENSE.libnvtracebuf \
+	nv_tegra/LICENSE.libtegrav4l2 \
+	nv_tegra/LICENSE.minigbm \
+	nv_tegra/LICENSE.nvbootctrl \
+	nv_tegra/LICENSE.nvdla \
+	nv_tegra/LICENSE.weston \
+	nv_tegra/LICENSE.weston-data \
+	nv_tegra/nvidia_configs/opt/nvidia/l4t-usb-device-mode/LICENSE.filesystem.img \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.brcm_patchram_plus \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.cypress_wifibt \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libnvargus \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libnvcam_imageencoder \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libnveventlib \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libnvtracebuf \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libnvv4l2 \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libnvv4lconvert \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libtegrav4l2 \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.libvulkan1 \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.minigbm \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.nvdla \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.realtek_8822ce_wifibt \
+	nv_tegra/nvidia_drivers/usr/share/doc/nvidia-tegra/LICENSE.tegra_sensors \
+	nv_tegra/nvidia_tools/usr/share/doc/nvidia-tegra/LICENSE.nvbootctrl \
+	nv_tegra/nvidia_tools/usr/share/doc/nvidia-tegra/LICENSE.tipc_test
+
+LINUX4TEGRA_INSTALL_IMAGES = YES
+
+define LINUX4TEGRA_EXTRACT_NVIDIA_DRIVERS
+	@mkdir -p $(@D)/nv_tegra/nvidia_drivers
+	$(call suitable-extractor,nvidia_drivers.tbz2) \
+		$(@D)/nv_tegra/nvidia_drivers.tbz2 | \
+		$(TAR) -C $(@D)/nv_tegra/nvidia_drivers $(TAR_OPTIONS) -
+endef
+
+LINUX4TEGRA_POST_EXTRACT_HOOKS += LINUX4TEGRA_EXTRACT_NVIDIA_DRIVERS
+
+define LINUX4TEGRA_EXTRACT_NVIDIA_CONFIGS
+	@mkdir -p $(@D)/nv_tegra/nvidia_configs
+	$(call suitable-extractor,config.tbz2) \
+		$(@D)/nv_tegra/config.tbz2 | \
+		$(TAR) -C $(@D)/nv_tegra/nvidia_configs $(TAR_OPTIONS) -
+endef
+
+LINUX4TEGRA_POST_EXTRACT_HOOKS += LINUX4TEGRA_EXTRACT_NVIDIA_CONFIGS
+
+define LINUX4TEGRA_EXTRACT_NVIDIA_TOOLS
+	@mkdir -p $(@D)/nv_tegra/nvidia_tools
+	$(call suitable-extractor,nv_tools.tbz2) \
+		$(@D)/nv_tegra/nv_tools.tbz2 | \
+		$(TAR) -C $(@D)/nv_tegra/nvidia_tools $(TAR_OPTIONS) -
+endef
+
+LINUX4TEGRA_POST_EXTRACT_HOOKS += LINUX4TEGRA_EXTRACT_NVIDIA_TOOLS
+
+# copy linux4tegra to the target dir
+define LINUX4TEGRA_INSTALL_IMAGES_CMDS
+	cp -r $(@D)/. $(BINARIES_DIR)/linux4tegra
+endef
+
+LINUX4TEGRA_RSYNC = \
+	rsync -a --ignore-times $(RSYNC_VCS_EXCLUSIONS) \
+		--chmod=u=rwX,go=rX --exclude .empty --exclude '*~' \
+		--keep-dirlinks --exclude=ld.so.conf.d
+
+define LINUX4TEGRA_INSTALL_TARGET_CMDS
+	# install nvidia_drivers
+	$(LINUX4TEGRA_RSYNC) $(@D)/nv_tegra/nvidia_drivers/ $(TARGET_DIR)/
+	# install nvidia_configs
+	$(LINUX4TEGRA_RSYNC) $(@D)/nv_tegra/nvidia_configs/ $(TARGET_DIR)/
+	# install nvidia_tools
+	$(LINUX4TEGRA_RSYNC) $(@D)/nv_tegra/nvidia_tools/ $(TARGET_DIR)/
+endef
+
+$(eval $(generic-package))
-- 
2.29.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Buildroot] [PATCH v3 3/5] package/libnvidia-container: new package
  2020-11-18  2:52 [Buildroot] [PATCH v3 1/5] package/nvidia-modprobe: new package Christian Stewart
  2020-11-18  2:52 ` [Buildroot] [PATCH v3 2/5] package/linux4tegra: " Christian Stewart
@ 2020-11-18  2:52 ` Christian Stewart
  2020-11-18  2:52 ` [Buildroot] [PATCH v3 4/5] board: add nvidia jetson tx2 support Christian Stewart
  2020-11-18  2:52 ` [Buildroot] [PATCH v3 5/5] board: add nvidia jetson nano support Christian Stewart
  3 siblings, 0 replies; 7+ messages in thread
From: Christian Stewart @ 2020-11-18  2:52 UTC (permalink / raw)
  To: buildroot

The libnvidia-container package adds a library and CLI for GPU-backed
containers, agnostic to container runtime.

https://github.com/NVIDIA/libnvidia-container

Signed-off-by: Christian Stewart <christian@paral.in>

v1 -> v2:

 - cjs: thanks Asaf thanks for review
 - cjs: remove extra include dirs
 - cjs: simplify configuration opts

v2 -> v3:

 - cjs: add fixup for go-module support

Signed-off-by: Christian Stewart <christian@paral.in>
---
 package/Config.in                             |    1 +
 ...d-fixes-from-vowstar-portage-overlay.patch | 1890 +++++++++++++++++
 ...ve-dependency-handling-from-Makefile.patch |  698 ++++++
 package/libnvidia-container/Config.in         |   18 +
 .../libnvidia-container.hash                  |    3 +
 .../libnvidia-container.mk                    |   44 +
 6 files changed, 2654 insertions(+)
 create mode 100644 package/libnvidia-container/0001-Build-fixes-from-vowstar-portage-overlay.patch
 create mode 100644 package/libnvidia-container/0002-Remove-dependency-handling-from-Makefile.patch
 create mode 100644 package/libnvidia-container/Config.in
 create mode 100644 package/libnvidia-container/libnvidia-container.hash
 create mode 100644 package/libnvidia-container/libnvidia-container.mk

diff --git a/package/Config.in b/package/Config.in
index 01072c3e45..ef01361fdb 100644
--- a/package/Config.in
+++ b/package/Config.in
@@ -1532,6 +1532,7 @@ menu "Hardware handling"
 	source "package/libllcp/Config.in"
 	source "package/libmbim/Config.in"
 	source "package/libnfc/Config.in"
+	source "package/libnvidia-container/Config.in"
 	source "package/libpciaccess/Config.in"
 	source "package/libphidget/Config.in"
 	source "package/libpri/Config.in"
diff --git a/package/libnvidia-container/0001-Build-fixes-from-vowstar-portage-overlay.patch b/package/libnvidia-container/0001-Build-fixes-from-vowstar-portage-overlay.patch
new file mode 100644
index 0000000000..7232e76d97
--- /dev/null
+++ b/package/libnvidia-container/0001-Build-fixes-from-vowstar-portage-overlay.patch
@@ -0,0 +1,1890 @@
+From bd633a208446c86e11097e3cd3b019a086738ae3 Mon Sep 17 00:00:00 2001
+From: Christian Stewart <christian@paral.in>
+Date: Sun, 19 Jul 2020 09:56:42 -0700
+Subject: [PATCH] Build fixes from vowstar portage overlay
+
+This commit brings in build fixes written by @vowstar in the overlay:
+
+https://github.com/vowstar/vowstar-overlay/tree/master/app-emulation/libnvidia-container/files
+
+Signed-off-by: Christian Stewart <christian@paral.in>
+---
+ Makefile                    |  30 +-
+ mk/Dockerfile.debian        |   1 -
+ mk/Dockerfile.ubuntu        |   1 -
+ mk/common.mk                |   2 +-
+ src/nvc.c                   |   4 +-
+ src/nvidia-modprobe-utils.c | 794 ++++++++++++++++++++++++++++++++++++
+ src/nvidia-modprobe-utils.h | 157 +++++++
+ src/pci-enum.h              | 112 +++++
+ src/pci-sysfs.c             | 529 ++++++++++++++++++++++++
+ src/pci-sysfs.h             |  85 ++++
+ 10 files changed, 1696 insertions(+), 19 deletions(-)
+ create mode 100644 src/nvidia-modprobe-utils.c
+ create mode 100644 src/nvidia-modprobe-utils.h
+ create mode 100644 src/pci-enum.h
+ create mode 100644 src/pci-sysfs.c
+ create mode 100644 src/pci-sysfs.h
+
+diff --git a/Makefile b/Makefile
+index c07863b..f1c56a9 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
+ 
+@@ -52,6 +52,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      \
+@@ -121,8 +123,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
+@@ -131,7 +133,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)
+@@ -146,7 +148,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)
+@@ -220,12 +222,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
+@@ -238,7 +240,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
+diff --git a/mk/Dockerfile.debian b/mk/Dockerfile.debian
+index 8e8a560..096e1d0 100644
+--- a/mk/Dockerfile.debian
++++ b/mk/Dockerfile.debian
+@@ -41,7 +41,6 @@ RUN make distclean && make -j"$(nproc)"
+ ENV DIST_DIR /dist
+ VOLUME $DIST_DIR
+ CMD bash -c " \
+-        export DISTRIB=$(lsb_release -c -s); \
+         export SECTION="" \
+         make dist; \
+         make deb; \
+diff --git a/mk/Dockerfile.ubuntu b/mk/Dockerfile.ubuntu
+index 8b8cea8..d1f64d0 100644
+--- a/mk/Dockerfile.ubuntu
++++ b/mk/Dockerfile.ubuntu
+@@ -40,7 +40,6 @@ RUN make distclean && make -j"$(nproc)"
+ ENV DIST_DIR /dist
+ VOLUME $DIST_DIR
+ CMD bash -c " \
+-        export DISTRIB=$(lsb_release -c -s); \
+         export SECTION="" \
+         make dist; \
+         make deb; \
+diff --git a/mk/common.mk b/mk/common.mk
+index 73bc27a..cdd93c9 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)
+ 
+diff --git a/src/nvc.c b/src/nvc.c
+index 35ad5be..f1d9b62 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"
+ 
+diff --git a/src/nvidia-modprobe-utils.c b/src/nvidia-modprobe-utils.c
+new file mode 100644
+index 0000000..d3f3233
+--- /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@end of file
+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
+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
+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,
++                            &reg, 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,
++                            &reg, 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,
++                                    &reg, 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
+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
+-- 
+2.27.0
+
diff --git a/package/libnvidia-container/0002-Remove-dependency-handling-from-Makefile.patch b/package/libnvidia-container/0002-Remove-dependency-handling-from-Makefile.patch
new file mode 100644
index 0000000000..d4ba9dfe80
--- /dev/null
+++ b/package/libnvidia-container/0002-Remove-dependency-handling-from-Makefile.patch
@@ -0,0 +1,698 @@
+From 6752d8d5e315eb3f061498a9c35558f90f9600e2 Mon Sep 17 00:00:00 2001
+From: Christian Stewart <christian@paral.in>
+Date: Sat, 18 Jul 2020 15:26:22 -0700
+Subject: [PATCH] Remove dependency handling from Makefile
+
+Buildroot will handle this for the makefile.
+
+Signed-off-by: Christian Stewart <christian@paral.in>
+---
+ Makefile                    |  54 +++------
+ mk/nvidia-modprobe.mk       |  55 ---------
+ src/nvc.c                   |   6 +-
+ src/nvidia-modprobe-utils.c | 225 ++++++++++++++++--------------------
+ src/nvidia-modprobe-utils.h |  53 ++-------
+ 5 files changed, 128 insertions(+), 265 deletions(-)
+ delete mode 100644 mk/nvidia-modprobe.mk
+
+diff --git a/Makefile b/Makefile
+index f1c56a9..80780d1 100644
+--- a/Makefile
++++ b/Makefile
+@@ -2,13 +2,13 @@
+ # Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
+ #
+ 
+-.PHONY: all tools shared static deps install uninstall dist depsclean mostlyclean clean distclean
++.PHONY: all tools shared static install uninstall dist mostlyclean clean distclean
+ .DEFAULT_GOAL := all
+-STRIP  := @echo skipping: strip
++
+ ##### Global variables #####
+ 
+-WITH_LIBELF  ?= yes
+-WITH_TIRPC   ?= yes
++WITH_LIBELF  ?= no
++WITH_TIRPC   ?= no
+ WITH_SECCOMP ?= yes
+ 
+ ##### Global definitions #####
+@@ -16,15 +16,14 @@ WITH_SECCOMP ?= yes
+ export prefix      = /usr
+ export exec_prefix = $(prefix)
+ export bindir      = $(exec_prefix)/bin
+-export libdir      = $(exec_prefix)/lib64
++export libdir      = $(exec_prefix)/lib
+ export docdir      = $(prefix)/share/doc
+-export libdbgdir   = $(prefix)/lib64/debug$(libdir)
++export libdbgdir   = $(prefix)/lib/debug$(libdir)
+ export includedir  = $(prefix)/include
+ export pkgconfdir  = $(libdir)/pkgconfig
+ 
+ export PKG_DIR     ?= $(CURDIR)/pkg
+ export SRCS_DIR    ?= $(CURDIR)/src
+-export DEPS_DIR    ?= $(CURDIR)/deps
+ export DIST_DIR    ?= $(CURDIR)/dist
+ export MAKE_DIR    ?= $(CURDIR)/mk
+ export DEBUG_DIR   ?= $(CURDIR)/.debug
+@@ -120,9 +119,9 @@ LDFLAGS  := -Wl,-zrelro -Wl,-znow -Wl,-zdefs -Wl,--gc-sections $(LDFLAGS)
+ LDLIBS   := $(LDLIBS)
+ 
+ # Library flags (recursively expanded to handle target-specific flags)
+-LIB_CPPFLAGS       = -DNV_LINUX -isystem $(DEPS_DIR)$(includedir) -include $(BUILD_DEFS)
++LIB_CPPFLAGS       = -DNV_LINUX -include $(BUILD_DEFS)
+ LIB_CFLAGS         = -fPIC
+-LIB_LDFLAGS        = -L$(DEPS_DIR)$(libdir) -shared -Wl,-soname=$(LIB_SONAME)
++LIB_LDFLAGS        = -shared -Wl,-soname=$(LIB_SONAME)
+ # LIB_LDLIBS_STATIC  = -l:libnvidia-modprobe-utils.a
+ LIB_LDLIBS_SHARED  = -ldl -lcap -ltirpc
+ ifeq ($(WITH_LIBELF), yes)
+@@ -132,7 +131,7 @@ else
+ LIB_LDLIBS_STATIC  += -l:libelf.a
+ endif
+ ifeq ($(WITH_TIRPC), yes)
+-LIB_CPPFLAGS       += -isystem $(DEPS_DIR)$(includedir)/tirpc -DWITH_TIRPC
++LIB_CPPFLAGS       += -DWITH_TIRPC
+ # LIB_LDLIBS_STATIC  += -l:libtirpc.a
+ LIB_LDLIBS_SHARED  += -lpthread
+ endif
+@@ -176,15 +175,15 @@ $(LIB_RPC_SRCS): $(LIB_RPC_SPEC)
+ 	$(RM) $@
+ 	cd $(dir $@) && $(RPCGEN) $(RPCGENFLAGS) -C -M -N -o $(notdir $@) $(LIB_RPC_SPEC)
+ 
+-$(LIB_OBJS): %.lo: %.c | deps
++$(LIB_OBJS): %.lo: %.c
+ 	$(CC) $(LIB_CFLAGS) $(LIB_CPPFLAGS) -MMD -MF $*.d -c $(OUTPUT_OPTION) $<
+ 
+-$(BIN_OBJS): %.o: %.c | shared
++$(BIN_OBJS): %.o: %.c
+ 	$(CC) $(BIN_CFLAGS) $(BIN_CPPFLAGS) -MMD -MF $*.d -c $(OUTPUT_OPTION) $<
+ 
+ -include $(DEPENDENCIES)
+ 
+-$(LIB_SHARED): $(LIB_OBJS)
++$(LIB_SHARED): $(BUILD_DEFS) $(SRCS_DIR)/driver_rpc.h $(LIB_OBJS)
+ 	$(MKDIR) -p $(DEBUG_DIR)
+ 	$(CC) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(LIB_LDFLAGS) $(OUTPUT_OPTION) $^ $(LIB_SCRIPT) $(LIB_LDLIBS)
+ 	$(OBJCPY) --only-keep-debug $@ $(LIB_SONAME)
+@@ -198,7 +197,7 @@ $(LIB_STATIC_OBJ): $(LIB_OBJS)
+ 	$(OBJCPY) --localize-hidden $@
+ 	$(STRIP) --strip-unneeded -R .comment $@
+ 
+-$(BIN_NAME): $(BIN_OBJS)
++$(BIN_NAME): $(BUILD_DEFS) $(SRCS_DIR)/driver_rpc.h $(LIB_SHARED) $(BIN_OBJS)
+ 	$(CC) $(BIN_CFLAGS) $(BIN_CPPFLAGS) $(BIN_LDFLAGS) $(OUTPUT_OPTION) $^ $(BIN_SCRIPT) $(BIN_LDLIBS)
+ 	$(STRIP) --strip-unneeded -R .comment $@
+ 
+@@ -219,17 +218,6 @@ shared: $(LIB_SHARED)
+ 
+ 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
+-ifeq ($(WITH_LIBELF), no)
+-	# $(MAKE) -f $(MAKE_DIR)/elftoolchain.mk install
+-endif
+-ifeq ($(WITH_TIRPC), yes)
+-	# $(MAKE) -f $(MAKE_DIR)/libtirpc.mk install
+-endif
+-
+ install: all
+ 	$(INSTALL) -d -m 755 $(addprefix $(DESTDIR),$(includedir) $(bindir) $(libdir) $(docdir) $(libdbgdir) $(pkgconfdir))
+ 	# Install header files
+@@ -237,8 +225,7 @@ install: all
+ 	# Install library files
+ 	$(INSTALL) -m 644 $(LIB_STATIC) $(DESTDIR)$(libdir)
+ 	$(INSTALL) -m 755 $(LIB_SHARED) $(DESTDIR)$(libdir)
+-	$(LN) -sf $(LIB_SONAME) $(DESTDIR)$(libdir)/$(LIB_SYMLINK)
+-	$(LDCONFIG) -n $(DESTDIR)$(libdir)
++	$(LN) -sf $(LIB_SHARED) $(DESTDIR)$(libdir)/$(LIB_SYMLINK)
+ 	# Install debugging symbols
+ 	# $(INSTALL) -m 644 $(DEBUG_DIR)/$(LIB_SONAME) $(DESTDIR)$(libdbgdir)
+ 	# Install configuration files
+@@ -268,23 +255,12 @@ dist: install
+ 	$(TAR) --numeric-owner --owner=0 --group=0 -C $(dir $(DESTDIR)) -caf $(DESTDIR)_$(ARCH).tar.xz $(notdir $(DESTDIR))
+ 	$(RM) -r $(DESTDIR)
+ 
+-depsclean:
+-	$(RM) $(BUILD_DEFS)
+-	-$(MAKE) -f $(MAKE_DIR)/nvidia-modprobe.mk clean
+-ifeq ($(WITH_LIBELF), no)
+-	-$(MAKE) -f $(MAKE_DIR)/elftoolchain.mk clean
+-endif
+-ifeq ($(WITH_TIRPC), yes)
+-	-$(MAKE) -f $(MAKE_DIR)/libtirpc.mk clean
+-endif
+-
+ mostlyclean:
+ 	$(RM) $(LIB_OBJS) $(LIB_STATIC_OBJ) $(BIN_OBJS) $(DEPENDENCIES)
+ 
+-clean: mostlyclean depsclean
++clean: mostlyclean
+ 
+ distclean: clean
+-	$(RM) -r $(DEPS_DIR) $(DIST_DIR) $(DEBUG_DIR)
+ 	$(RM) $(LIB_RPC_SRCS) $(LIB_STATIC) $(LIB_SHARED) $(BIN_NAME)
+ 
+ deb: DESTDIR:=$(DIST_DIR)/$(LIB_NAME)_$(VERSION)_$(ARCH)
+diff --git a/mk/nvidia-modprobe.mk b/mk/nvidia-modprobe.mk
+deleted file mode 100644
+index ad399de..0000000
+--- a/mk/nvidia-modprobe.mk
++++ /dev/null
+@@ -1,55 +0,0 @@
+-#
+-# Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
+-#
+-
+-include $(MAKE_DIR)/common.mk
+-
+-##### Source definitions #####
+-
+-VERSION        := 396.51
+-PREFIX         := nvidia-modprobe-$(VERSION)
+-URL            := https://github.com/NVIDIA/nvidia-modprobe/archive/$(VERSION).tar.gz
+-
+-SRCS_DIR       := $(DEPS_DIR)/src/$(PREFIX)
+-MODPROBE_UTILS := $(SRCS_DIR)/modprobe-utils
+-
+-LIB_STATIC     := $(MODPROBE_UTILS)/libnvidia-modprobe-utils.a
+-LIB_INCS       := $(MODPROBE_UTILS)/nvidia-modprobe-utils.h \
+-                  $(MODPROBE_UTILS)/pci-enum.h
+-LIB_SRCS       := $(MODPROBE_UTILS)/nvidia-modprobe-utils.c \
+-                  $(MODPROBE_UTILS)/pci-sysfs.c
+-
+-##### Flags definitions #####
+-
+-ARFLAGS  := -rU
+-CPPFLAGS := -D_FORTIFY_SOURCE=2 -DNV_LINUX
+-CFLAGS   := -O2 -g -fdata-sections -ffunction-sections -fstack-protector -fno-strict-aliasing -fPIC
+-
+-##### Private rules #####
+-
+-LIB_OBJS := $(LIB_SRCS:.c=.o)
+-
+-$(SRCS_DIR)/.download_stamp:
+-	$(MKDIR) -p $(SRCS_DIR)
+-	$(CURL) --progress-bar -fSL $(URL) | \
+-	$(TAR) -C $(SRCS_DIR) --strip-components=1 -xz $(PREFIX)/modprobe-utils
+-	@touch $@
+-
+-$(LIB_SRCS): $(SRCS_DIR)/.download_stamp
+-
+-##### Public rules #####
+-
+-.PHONY: all install clean
+-
+-all: $(LIB_STATIC)
+-
+-$(LIB_STATIC): $(LIB_OBJS)
+-	$(AR) rs $@ $^
+-
+-install: all
+-	$(INSTALL) -d -m 755 $(addprefix $(DESTDIR),$(includedir) $(libdir))
+-	$(INSTALL) -m 644 $(LIB_INCS) $(DESTDIR)$(includedir)
+-	$(INSTALL) -m 644 $(LIB_STATIC) $(DESTDIR)$(libdir)
+-
+-clean:
+-	$(RM) $(LIB_OBJS) $(LIB_STATIC)
+diff --git a/src/nvc.c b/src/nvc.c
+index f1d9b62..74ea61c 100644
+--- a/src/nvc.c
++++ b/src/nvc.c
+@@ -190,13 +190,13 @@ load_kernel_modules(struct error *err, const char *root)
+                 }
+ 
+                 log_info("loading kernel module nvidia");
+-                if (nvidia_modprobe(0, -1) == 0)
++                if (nvidia_modprobe(0) == 0)
+                         log_err("could not load kernel module nvidia");
+                 else {
+-                        if (nvidia_mknod(NV_CTL_DEVICE_MINOR, -1) == 0)
++                        if (nvidia_mknod(NV_CTL_DEVICE_MINOR) == 0)
+                                 log_err("could not create kernel module device node");
+                         for (int i = 0; i < (int)devs.num_matches; ++i) {
+-                                if (nvidia_mknod(i, -1) == 0)
++                                if (nvidia_mknod(i) == 0)
+                                         log_err("could not create kernel module device node");
+                         }
+                 }
+diff --git a/src/nvidia-modprobe-utils.c b/src/nvidia-modprobe-utils.c
+index d3f3233..fca21cf 100644
+--- a/src/nvidia-modprobe-utils.c
++++ b/src/nvidia-modprobe-utils.c
+@@ -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,6 +64,9 @@
+ #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
+@@ -54,84 +80,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 '_'
+@@ -370,18 +318,20 @@ static int modprobe_helper(const int print_errors, const char *module_name)
+             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 +341,9 @@ static int modprobe_helper(const int print_errors, const char *module_name)
+ /*
+  * 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);
+ }
+ 
+ 
+@@ -494,24 +440,22 @@ static int get_file_state_helper(
+     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 +466,8 @@ int nvidia_get_file_state(int minor, int module_instance)
+  * 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 +560,13 @@ int mknod_helper(int major, int minor, const char *path,
+  * 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 +575,7 @@ int nvidia_mknod(int minor, int module_instance)
+  * device with the specified name.  Returns the major number on success,
+  * or -1 on failure.
+  */
+-int get_chardev_major(const char *name)
++static int get_chardev_major(const char *name)
+ {
+     int ret = -1;
+     char line[NV_MAX_LINE_LENGTH];
+@@ -743,13 +685,9 @@ int nvidia_modeset_modprobe(void)
+  */
+ 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);
+ }
+ 
+ /*
+@@ -770,25 +708,62 @@ int nvidia_nvlink_mknod(void)
+                         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 = 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)
++    {
++        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);
+     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);
+ }
+ 
+-#endif /* NV_LINUX */
+\ No newline@end of file
++#endif /* NV_LINUX */
+diff --git a/src/nvidia-modprobe-utils.h b/src/nvidia-modprobe-utils.h
+index e06b4a4..5ab3355 100644
+--- a/src/nvidia-modprobe-utils.h
++++ b/src/nvidia-modprobe-utils.h
+@@ -31,29 +31,17 @@
+ #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_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_NVSWITCH_CTL_NAME "/dev/nvidia-nvswitchctl"
++#define NV_NVSWITCH_DEVICE_NAME "/dev/nvidia-nvswitch%d"
+ 
+ #if defined(NV_LINUX)
+ 
+@@ -76,31 +64,19 @@ static __inline__ int nvidia_test_file_state(int state,
+     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_nvswitch_mknod(int minor);
+ 
+ #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].
+@@ -108,8 +84,7 @@ static __inline__ int is_multi_module(int module_instance)
+ 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 +94,12 @@ static __inline__ void assign_device_file_name
+         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 +121,4 @@ fail:
+     name[0] = '\0';
+ }
+ 
+-#endif /* __NVIDIA_MODPROBE_UTILS_H__ */
+\ No newline@end of file
++#endif /* __NVIDIA_MODPROBE_UTILS_H__ */
+-- 
+2.27.0
+
diff --git a/package/libnvidia-container/Config.in b/package/libnvidia-container/Config.in
new file mode 100644
index 0000000000..7a452c3635
--- /dev/null
+++ b/package/libnvidia-container/Config.in
@@ -0,0 +1,18 @@
+config BR2_PACKAGE_LIBNVIDIA_CONTAINER
+	bool "libnvidia-container"
+	depends on BR2_SHARED_LIBS
+	depends on BR2_TOOLCHAIN_HAS_THREADS # tirpc
+	depends on BR2_TOOLCHAIN_USES_GLIBC # fexecve
+	select BR2_PACKAGE_ELFUTILS
+	select BR2_PACKAGE_LIBCAP
+	select BR2_PACKAGE_LIBTIRPC
+	select BR2_PACKAGE_NVIDIA_MODPROBE
+	help
+	  The libnvidia-container package adds a library and CLI for
+	  GPU-backed containers, agnostic to container runtime.
+
+	  https://github.com/NVIDIA/libnvidia-container
+
+comment "libnvidia-container needs a shared glibc toolchain w/ threads"
+	depends on !BR2_TOOLCHAIN_HAS_THREADS || !BR2_TOOLCHAN_USES_GLIBC || \
+		!BR2_SHARED_LIBS
diff --git a/package/libnvidia-container/libnvidia-container.hash b/package/libnvidia-container/libnvidia-container.hash
new file mode 100644
index 0000000000..d356eb2b1e
--- /dev/null
+++ b/package/libnvidia-container/libnvidia-container.hash
@@ -0,0 +1,3 @@
+# Locally computed:
+sha256 fd447629fd65d171b68edb62fa2e581c67fdb450ff540f486987ab826150d06e  libnvidia-container-1.2.0.tar.gz
+sha256 cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30  LICENSE
diff --git a/package/libnvidia-container/libnvidia-container.mk b/package/libnvidia-container/libnvidia-container.mk
new file mode 100644
index 0000000000..b040c0baaa
--- /dev/null
+++ b/package/libnvidia-container/libnvidia-container.mk
@@ -0,0 +1,44 @@
+################################################################################
+#
+# libnvidia-container
+#
+################################################################################
+
+LIBNVIDIA_CONTAINER_VERSION = 1.2.0
+LIBNVIDIA_CONTAINER_SITE = $(call github,NVIDIA,libnvidia-container,v$(LIBNVIDIA_CONTAINER_VERSION))
+LIBNVIDIA_CONTAINER_LICENSE = Apache-2.0
+LIBNVIDIA_CONTAINER_LICENSE_FILES = LICENSE
+
+LIBNVIDIA_CONTAINER_DEPENDENCIES = elfutils libcap libtirpc nvidia-modprobe \
+	host-pkgconf host-elfutils host-libcap
+
+LIBNVIDIA_CONTAINER_MAKE_OPTS = \
+	CFLAGS="$(TARGET_CFLAGS) -D_GNU_SOURCE" \
+	OBJCPY="$(TARGET_OBJCOPY)" \
+	RPCGEN="$(HOST_DIR)/bin/rpcgen" \
+	WITH_LIBELF=yes \
+	WITH_TIRPC=no
+
+ifeq ($(BR2_PACKAGE_LIBSECCOMP),y)
+LIBNVIDIA_CONTAINER_MAKE_OPTS += WITH_SECCOMP=yes
+LIBNVIDIA_CONTAINER_DEPENDENCIES += libseccomp
+else
+LIBNVIDIA_CONTAINER_MAKE_OPTS += WITH_SECCOMP=no
+endif
+
+define LIBNVIDIA_CONTAINER_BUILD_CMDS
+	$(TARGET_MAKE_ENV) $(MAKE) -C $(@D) \
+		$(TARGET_CONFIGURE_OPTS) \
+		$(LIBNVIDIA_CONTAINER_MAKE_OPTS) \
+		shared tools
+endef
+
+define LIBNVIDIA_CONTAINER_INSTALL_TARGET_CMDS
+	$(TARGET_MAKE_ENV) $(MAKE) -C $(@D) \
+		$(TARGET_CONFIGURE_OPTS) \
+		$(LIBNVIDIA_CONTAINER_MAKE_OPTS) \
+		DESTDIR="$(TARGET_DIR)" \
+		install
+endef
+
+$(eval $(generic-package))
-- 
2.29.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Buildroot] [PATCH v3 4/5] board: add nvidia jetson tx2 support
  2020-11-18  2:52 [Buildroot] [PATCH v3 1/5] package/nvidia-modprobe: new package Christian Stewart
  2020-11-18  2:52 ` [Buildroot] [PATCH v3 2/5] package/linux4tegra: " Christian Stewart
  2020-11-18  2:52 ` [Buildroot] [PATCH v3 3/5] package/libnvidia-container: " Christian Stewart
@ 2020-11-18  2:52 ` Christian Stewart
  2020-11-18 14:58   ` Romain Naour
  2020-11-18  2:52 ` [Buildroot] [PATCH v3 5/5] board: add nvidia jetson nano support Christian Stewart
  3 siblings, 1 reply; 7+ messages in thread
From: Christian Stewart @ 2020-11-18  2:52 UTC (permalink / raw)
  To: buildroot

Tested-by: Asaf Kahlon <asafka7@gmail.com>
Signed-off-by: Christian Stewart <christian@paral.in>
---
 board/jetson/tx2/readme.txt | 83 +++++++++++++++++++++++++++++++++++++
 board/jetsontx2             |  1 +
 configs/jetsontx2_defconfig | 55 ++++++++++++++++++++++++
 3 files changed, 139 insertions(+)
 create mode 100644 board/jetson/tx2/readme.txt
 create mode 120000 board/jetsontx2
 create mode 100644 configs/jetsontx2_defconfig

diff --git a/board/jetson/tx2/readme.txt b/board/jetson/tx2/readme.txt
new file mode 100644
index 0000000000..45fdb50a56
--- /dev/null
+++ b/board/jetson/tx2/readme.txt
@@ -0,0 +1,83 @@
+NVIDIA Jetson TX2
+
+Intro
+=====
+
+This configuration supports the Jetson TX2 devkit.
+
+Building
+========
+
+Configure Buildroot
+-------------------
+
+For Jetson TX2:
+
+  $ make jetsontx2_defconfig
+
+Build the rootfs
+----------------
+
+You may now build your rootfs with:
+
+  $ make
+
+
+Flashing
+========
+
+Once the build process is finished you will have the target binaries in the
+output/images directory, with a copy of linux4tegra.
+
+Flashing to the internal eMMC is done by booting to the official recovery mode,
+and flashing the system from there. The default factory-flashed TX2 is suitable.
+
+There are a lot of cases where the TX2 will not boot properly unless all of the
+peripherals are fully disconnected, power is disconnected, everything fully
+resets, and then the power is introduced back again.
+
+The recovery mode of the Jetson is used to flash. Entering recovery:
+
+ - Start with the machine powered off + fully unplugged.
+ - Plug in the device to power, and connect a HDMI display.
+ - Connect a micro-USB cable from the host PC to the target board.
+ - Power on the device by holding the start button until the red light is lit.
+ - Hold down the RST button and REC button simultaneously.
+ - Release the RST button while holding down the REC button.
+ - Wait a few seconds, then release the REC button.
+
+To flash over USB:
+
+```
+cd output/images/linux4tegra
+sudo bash ./flash.sh \
+     -I ../rootfs.ext2 \
+     -K ../Image \
+     -L ../u-boot-dtb.bin \
+     -C "ramdisk_size=100000 net.ifnames=0 elevator=deadline" \
+     -d ../tegra186-quill-p3310-1000-c03-00-base.dtb \
+     jetson-tx2-devkit mmcblk0p1
+```
+
+This will run the `flash.sh` script from L4T, and will setup the kernel, u-boot,
+persist + boot-up partition mmcblk0p1. This may overwrite your existing work so
+use it for initial setup only.
+
+Bootup Process
+==============
+
+The TX2 boots from the internal eMMC, at mmcblk0p1.
+
+A "secure boot" process is used, with multiple bootloaders:
+
+ - BootROM -> MB1 (TrustZone)
+ - MB2/BPMP -> (Non-Trustzone)
+ - Cboot (uses Little Kernel)
+ - Uboot
+ - Kernel
+ 
+Uboot is flashed to the mmcblk0p1 emmc partition.
+
+Cboot could be compiled from source, and the source is available from the
+official sources, however, we do not (yet) compile cboot.
+
diff --git a/board/jetsontx2 b/board/jetsontx2
new file mode 120000
index 0000000000..7404114cc3
--- /dev/null
+++ b/board/jetsontx2
@@ -0,0 +1 @@
+./jetson/tx2
\ No newline at end of file
diff --git a/configs/jetsontx2_defconfig b/configs/jetsontx2_defconfig
new file mode 100644
index 0000000000..c0eab3e50e
--- /dev/null
+++ b/configs/jetsontx2_defconfig
@@ -0,0 +1,55 @@
+BR2_aarch64=y
+BR2_cortex_a57=y
+
+# enable specific optimizations
+BR2_TARGET_OPTIMIZATION="-march=armv8-a+crypto -mcpu=cortex-a57+crypto"
+
+# Toolchain reference: docs.nvidia.com: "Jetson Linux Driver Package Toolchain"
+BR2_TOOLCHAIN_BUILDROOT_CXX=y
+BR2_BINUTILS_VERSION_2_32_X=y
+
+BR2_SYSTEM_DHCP="eth0"
+
+# Linux headers same as kernel, a 4.9 series
+BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_9=y
+BR2_KERNEL_HEADERS_AS_KERNEL=y
+
+BR2_LINUX_KERNEL=y
+BR2_LINUX_KERNEL_CUSTOM_TARBALL=y
+BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="$(call github,madisongh,linux-tegra-4.9,0be1a57448010ae60505acf4e2153638455cee7c)/linux-tegra-4.9.140-r1.tar.gz"
+BR2_LINUX_KERNEL_DEFCONFIG="tegra"
+
+# Build the DTB from the kernel sources
+BR2_LINUX_KERNEL_DTS_SUPPORT=y
+BR2_LINUX_KERNEL_INTREE_DTS_NAME="_ddot_/_ddot_/_ddot_/_ddot_/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-base"
+
+BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
+
+BR2_PACKAGE_LINUX4TEGRA=y
+BR2_PACKAGE_LINUX4TEGRA_PLATFORM_T186REF=y
+
+# TODO: NVIDIA_CONTAINER_TOOLKIT requires a go-module integration.
+# BR2_PACKAGE_NVIDIA_CONTAINER_TOOLKIT=y
+
+BR2_PACKAGE_LINUX_FIRMWARE=y
+BR2_PACKAGE_LINUX_FIRMWARE_RTL_88XX=y
+
+# Required tools to create the image
+BR2_PACKAGE_HOST_DOSFSTOOLS=y
+BR2_PACKAGE_HOST_JQ=y
+BR2_PACKAGE_HOST_PARTED=y
+
+# Filesystem / image
+BR2_TARGET_ROOTFS_EXT2=y
+BR2_TARGET_ROOTFS_EXT2_4=y
+BR2_TARGET_ROOTFS_EXT2_SIZE="1024M"
+# BR2_TARGET_ROOTFS_TAR is not set
+
+# Uboot
+BR2_TARGET_UBOOT=y
+BR2_TARGET_UBOOT_BOARD_DEFCONFIG="p2771-0000-500"
+BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y
+BR2_TARGET_UBOOT_CUSTOM_TARBALL=y
+BR2_TARGET_UBOOT_CUSTOM_TARBALL_LOCATION="$(call github,paralin,u-boot-tegra,e6da093be3cc593ef4294e1922b3391ede9c94da)/u-boot-tegra-l4t-r32.4-v2016.7.tar.gz"
+BR2_TARGET_UBOOT_FORMAT_DTB_BIN=y
+BR2_TARGET_UBOOT_NEEDS_DTC=y
-- 
2.29.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Buildroot] [PATCH v3 5/5] board: add nvidia jetson nano support
  2020-11-18  2:52 [Buildroot] [PATCH v3 1/5] package/nvidia-modprobe: new package Christian Stewart
                   ` (2 preceding siblings ...)
  2020-11-18  2:52 ` [Buildroot] [PATCH v3 4/5] board: add nvidia jetson tx2 support Christian Stewart
@ 2020-11-18  2:52 ` Christian Stewart
  3 siblings, 0 replies; 7+ messages in thread
From: Christian Stewart @ 2020-11-18  2:52 UTC (permalink / raw)
  To: buildroot

Signed-off-by: Christian Stewart <christian@paral.in>
---
 board/jetson/nano/format-sd.sh | 167 +++++++++++++++++++++++++++++++++
 board/jetson/nano/readme.txt   |  57 +++++++++++
 board/jetsonnano               |   1 +
 configs/jetsonnano_defconfig   |  55 +++++++++++
 4 files changed, 280 insertions(+)
 create mode 100644 board/jetson/nano/format-sd.sh
 create mode 100644 board/jetson/nano/readme.txt
 create mode 120000 board/jetsonnano
 create mode 100644 configs/jetsonnano_defconfig

diff --git a/board/jetson/nano/format-sd.sh b/board/jetson/nano/format-sd.sh
new file mode 100644
index 0000000000..1d3b6c442a
--- /dev/null
+++ b/board/jetson/nano/format-sd.sh
@@ -0,0 +1,167 @@
+#!/bin/bash
+set -eo pipefail
+
+# NOTE: The following copyright applies to linux4tegra and associated tools:
+
+# Copyright (c) 2019-2020, NVIDIA Corporation.  All Rights Reserved.
+#
+# NVIDIA Corporation and its licensors retain all intellectual property
+# and proprietary rights in and to this software, related documentation
+# and any modifications thereto.  Any use, reproduction, disclosure or
+# distribution of this software and related documentation without an express
+# license agreement from NVIDIA Corporation is strictly prohibited.
+
+if [ $EUID != 0 ]; then
+  echo "This script requires root."
+fi
+
+if [ -z "$NVIDIA_SD" ]; then
+    echo "Please set NVIDIA_SD and try again."
+    exit 1
+fi
+
+if [ ! -b "$NVIDIA_SD" ]; then
+    echo "$NVIDIA_SD is not a block device or doesn't exist."
+    exit 1
+fi
+
+IMAGES_DIR=$1
+if [ -z $IMAGES_DIR ]; then
+    echo "usage: $0 path/to/images/dir"
+    exit 1
+fi
+
+uimg_path=$IMAGES_DIR/Image
+if [ ! -f "$uimg_path" ]; then
+  echo "Image not found, make sure Buildroot is done compiling."
+  exit 1
+fi
+
+l4t_tools_path=$IMAGES_DIR/linux4tegra/tools
+if [ ! -d $l4t_tools_path ]; then
+    echo "linux4tegra tools not found, ensure buildroot is done compiling."
+    exit 1
+fi
+
+# jetson-nano
+boardid="3448"
+target="jetson-nano-qspi-sd"
+storage="sdcard"
+rev="300" # from 100, 200, 300
+chipid="0x21"
+
+l4t_dir=${IMAGES_DIR}/linux4tegra
+rootfs_img=$IMAGES_DIR/rootfs.ext2
+
+# TODO: dynamic rootfs size: the following /almost/ works:
+#rootfs_size=$(du -ms ${rootfs_img} | awk '{print $1}')
+#rootfs_size=$((rootfs_size + (rootfs_size / 10)))
+
+rootfs_size=2048
+
+echo "creating signed images"
+pushd ${l4t_dir}
+export BOARDID="${boardid}"
+export FAB="${rev}"
+
+${l4t_dir}/flash.sh \
+          --no-flash \
+          --sign \
+          --no-systemimg \
+          -x ${chipid} \
+          -B ${boardid} \
+          -S "${rootfs_size}MiB" \
+          -I $IMAGES_DIR/rootfs.ext2 \
+          -K $IMAGES_DIR/u-boot-dtb.bin \
+          -d $IMAGES_DIR/tegra210-p3448-0000-p3449-0000-b00.dtb \
+          "${target}" "mmcblk0p1"
+popd
+
+bootloader_dir=${l4t_dir}/bootloader
+if [ ! -f "${bootloader_dir}/flashcmd.txt" ]; then
+		echo "ERROR: ${bootloader_dir}/flashcmd.txt not found"
+		exit 1
+fi
+
+signed_image_dir=${bootloader_dir}/signed
+if [ ! -d "${signed_image_dir}" ]; then
+		echo "ERROR: ${signed_image_dir} not found"
+		exit 1
+fi
+
+chipid=$(sed -nr 's/.*chip ([^ ]*).*/\1/p' "${bootloader_dir}/flashcmd.txt")
+if [ "${chipid}" = "0x21" ]; then
+		signed_cfg="flash.xml"
+else
+		signed_cfg="flash.xml.tmp"
+fi
+
+if [ ! -f "${signed_image_dir}/${signed_cfg}" ]; then
+		echo "ERROR: ${signed_image_dir}/${signed_cfg} not found"
+		exit 1
+fi
+
+echo "create partitions"
+partitions=($(${l4t_tools_path}/nvptparser.py "${signed_image_dir}/${signed_cfg}" "${storage}"))
+part_type=8300 # Linux Filesystem
+
+sgdisk -og "${NVIDIA_SD}"
+for part in "${partitions[@]}"; do
+		eval "${part}"
+		if [ "${part_name}" = "master_boot_record" ]; then
+			  continue
+		fi
+		part_size=$((${part_size} / 512)) # convert to sectors
+		sgdisk -n "${part_num}":0:+"${part_size}" \
+			     -c "${part_num}":"${part_name}" \
+			     -t "${part_num}":"${part_type}" "${NVIDIA_SD}"
+done
+
+# prefer root partprobe
+PARTPROBE=partprobe
+if [ -f /usr/sbin/partprobe ]; then
+    PARTPROBE=/usr/sbin/partprobe
+fi
+
+$PARTPROBE ${NVIDIA_SD} || true
+sleep 1
+if $PARTPROBE ${NVIDIA_SD}; then
+    # wait for partitions to settle
+    sleep 1
+fi
+
+echo "write partitions"
+for part in "${partitions[@]}"; do
+		eval "${part}"
+		target_file=""
+		if [ "${part_name}" = "APP" ]; then
+			  target_file="${IMAGES_DIR}/rootfs.ext2" # Buildroot target system.
+		elif [ -e "${signed_image_dir}/${part_file}" ]; then
+			  target_file="${signed_image_dir}/${part_file}"
+		elif [ -e "${bootloader_dir}/${part_file}" ]; then
+			  target_file="${bootloader_dir}/${part_file}"
+		fi
+
+		echo "writing partition ${part_name}"
+		if [ "${part_name}" = "master_boot_record" ]; then
+			  echo "writing ${part_file}"
+			  dd conv=notrunc conv=fsync if="${signed_image_dir}/${part_file}" of="${NVIDIA_SD}" bs="${part_size}" count=1
+			  continue
+		fi
+
+		if [ "${target_file}" != "" ] && [ "${part_file}" != "" ]; then
+			  echo "writing ${target_file}"
+        target_part=${NVIDIA_SD}p${part_num}
+        if [ ! -b ${target_part} ]; then
+            target_part=${NVIDIA_SD}${part_num}
+        fi
+        if [ ! -b ${target_part} ]; then
+            echo "Partition block device ${target_part} or ${NVIDIA_SD}p${part_num} does not exist!"
+            exit 1
+        fi
+			  sudo dd conv=fsync if="${target_file}" of="${target_part}"
+		fi
+done
+
+echo "Successfully flashed $NVIDIA_SD"
+
diff --git a/board/jetson/nano/readme.txt b/board/jetson/nano/readme.txt
new file mode 100644
index 0000000000..8161c7e60f
--- /dev/null
+++ b/board/jetson/nano/readme.txt
@@ -0,0 +1,57 @@
+NVIDIA Jetson Nano
+
+Intro
+=====
+
+This configuration adds support for the Jetson Nano devkit.
+
+Building
+========
+
+Configure Buildroot
+-------------------
+
+For Jetson Nano:
+
+  $ make jetsonnano_defconfig
+
+Build the rootfs
+----------------
+
+You may now build your rootfs with:
+
+  $ make
+
+
+Flashing
+========
+
+Once the build process is finished you will have the target binaries in the
+output/images directory with a copy of linux4tegra.
+
+To format your SD card with the required partition layout, use the
+"format-sd.sh" script located under board/jetson/nano/format-sd.sh:
+
+  sudo \
+    NVIDIA_SD=/dev/sdX \
+    PATH=$(pwd)/output/host/sbin:$PATH \
+    bash board/jetson/nano/format-sd.sh ./output/images
+
+This will also flash the ext4 rootfs image to the SD card.
+
+Bootup Process
+==============
+
+The Jetson Nano can boot to a SD card.
+
+A "secure boot" process is used, with multiple bootloaders:
+
+ - BootROM -> MB1 (TrustZone)
+ - MB2/BPMP -> (Non-Trustzone)
+ - Cboot (uses Little Kernel)
+ - Uboot
+ - Kernel
+ 
+Cboot could be compiled from source, and the source is available from the
+official sources, however, we do not (yet) compile cboot.
+
diff --git a/board/jetsonnano b/board/jetsonnano
new file mode 120000
index 0000000000..808abfb405
--- /dev/null
+++ b/board/jetsonnano
@@ -0,0 +1 @@
+./jetson/nano
\ No newline at end of file
diff --git a/configs/jetsonnano_defconfig b/configs/jetsonnano_defconfig
new file mode 100644
index 0000000000..77600b8e98
--- /dev/null
+++ b/configs/jetsonnano_defconfig
@@ -0,0 +1,55 @@
+BR2_aarch64=y
+BR2_cortex_a57=y
+
+# enable specific optimizations
+BR2_TARGET_OPTIMIZATION="-march=armv8-a+crypto -mcpu=cortex-a57+crypto"
+
+# Toolchain reference: docs.nvidia.com: "Jetson Linux Driver Package Toolchain"
+BR2_TOOLCHAIN_BUILDROOT_CXX=y
+BR2_BINUTILS_VERSION_2_32_X=y
+
+BR2_SYSTEM_DHCP="eth0"
+
+# Linux headers same as kernel, a 4.9 series
+BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_9=y
+BR2_KERNEL_HEADERS_AS_KERNEL=y
+
+BR2_LINUX_KERNEL=y
+BR2_LINUX_KERNEL_CUSTOM_TARBALL=y
+BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="$(call github,madisongh,linux-tegra-4.9,0be1a57448010ae60505acf4e2153638455cee7c)/linux-tegra-4.9.140-r1.tar.gz"
+BR2_LINUX_KERNEL_DEFCONFIG="tegra"
+
+# Build the DTB from the kernel sources
+BR2_LINUX_KERNEL_DTS_SUPPORT=y
+BR2_LINUX_KERNEL_INTREE_DTS_NAME="_ddot_/_ddot_/_ddot_/_ddot_/nvidia/platform/t210/porg/kernel-dts/tegra210-p3448-0000-p3449-0000-a02 _ddot_/_ddot_/_ddot_/_ddot_/nvidia/platform/t210/porg/kernel-dts/tegra210-p3448-0000-p3449-0000-b00"
+
+BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
+
+BR2_PACKAGE_LINUX4TEGRA=y
+BR2_PACKAGE_LINUX4TEGRA_PLATFORM_T210REF=y
+
+# TODO: NVIDIA_CONTAINER_TOOLKIT requires a go-module integration.
+# BR2_PACKAGE_NVIDIA_CONTAINER_TOOLKIT=y
+
+BR2_PACKAGE_LINUX_FIRMWARE=y
+BR2_PACKAGE_LINUX_FIRMWARE_RTL_88XX=y
+
+# Required tools to create the image
+BR2_PACKAGE_HOST_DOSFSTOOLS=y
+BR2_PACKAGE_HOST_JQ=y
+BR2_PACKAGE_HOST_PARTED=y
+
+# Filesystem / image
+BR2_TARGET_ROOTFS_EXT2=y
+BR2_TARGET_ROOTFS_EXT2_4=y
+BR2_TARGET_ROOTFS_EXT2_SIZE="1024M"
+# BR2_TARGET_ROOTFS_TAR is not set
+
+# Uboot
+BR2_TARGET_UBOOT=y
+BR2_TARGET_UBOOT_BOARD_DEFCONFIG="p3450-porg"
+BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y
+BR2_TARGET_UBOOT_CUSTOM_TARBALL=y
+BR2_TARGET_UBOOT_CUSTOM_TARBALL_LOCATION="$(call github,paralin,u-boot-tegra,45dfa3dff43f880243a9fe68f3d911e99a240654)/u-boot-tegra-l4t-r32.4.2-v2016.07.tar.gz"
+BR2_TARGET_UBOOT_FORMAT_DTB_BIN=y
+BR2_TARGET_UBOOT_NEEDS_DTC=y
-- 
2.29.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Buildroot] [PATCH v3 4/5] board: add nvidia jetson tx2 support
  2020-11-18  2:52 ` [Buildroot] [PATCH v3 4/5] board: add nvidia jetson tx2 support Christian Stewart
@ 2020-11-18 14:58   ` Romain Naour
  2020-11-19  7:50     ` Christian Stewart
  0 siblings, 1 reply; 7+ messages in thread
From: Romain Naour @ 2020-11-18 14:58 UTC (permalink / raw)
  To: buildroot

Hello Christian,

Le 18/11/2020 ? 03:52, Christian Stewart a ?crit?:
> Tested-by: Asaf Kahlon <asafka7@gmail.com>
> Signed-off-by: Christian Stewart <christian@paral.in>
> ---
>  board/jetson/tx2/readme.txt | 83 +++++++++++++++++++++++++++++++++++++
>  board/jetsontx2             |  1 +
>  configs/jetsontx2_defconfig | 55 ++++++++++++++++++++++++
>  3 files changed, 139 insertions(+)
>  create mode 100644 board/jetson/tx2/readme.txt
>  create mode 120000 board/jetsontx2
>  create mode 100644 configs/jetsontx2_defconfig
> 

[...]

> diff --git a/configs/jetsontx2_defconfig b/configs/jetsontx2_defconfig
> new file mode 100644
> index 0000000000..c0eab3e50e
> --- /dev/null
> +++ b/configs/jetsontx2_defconfig
> @@ -0,0 +1,55 @@
> +BR2_aarch64=y
> +BR2_cortex_a57=y
> +
> +# enable specific optimizations
> +BR2_TARGET_OPTIMIZATION="-march=armv8-a+crypto -mcpu=cortex-a57+crypto"
> +
> +# Toolchain reference: docs.nvidia.com: "Jetson Linux Driver Package Toolchain"
> +BR2_TOOLCHAIN_BUILDROOT_CXX=y
> +BR2_BINUTILS_VERSION_2_32_X=y

AFAIK, the nvidia sdk requires a specific gcc version too. I'm not sure it can
build with GCC 9 or 10. Cuda libraries seems requires GCC 8.

> +
> +BR2_SYSTEM_DHCP="eth0"
> +
> +# Linux headers same as kernel, a 4.9 series
> +BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_9=y
> +BR2_KERNEL_HEADERS_AS_KERNEL=y
> +
> +BR2_LINUX_KERNEL=y
> +BR2_LINUX_KERNEL_CUSTOM_TARBALL=y
> +BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="$(call github,madisongh,linux-tegra-4.9,0be1a57448010ae60505acf4e2153638455cee7c)/linux-tegra-4.9.140-r1.tar.gz"
> +BR2_LINUX_KERNEL_DEFCONFIG="tegra"

The vanilla linux kernel doesn't even build with gcc 8, Matt Madison (the OE4T
maintainer) backported a lot of patches on the kernel 4.9.140 released by Nvidia
to fixes those issues.

Also this kernel include nvidia kernel stack, there is a hard dependency on the
linux4tegra version (32.4.3).

Best regards,
Romain

> +
> +# Build the DTB from the kernel sources
> +BR2_LINUX_KERNEL_DTS_SUPPORT=y
> +BR2_LINUX_KERNEL_INTREE_DTS_NAME="_ddot_/_ddot_/_ddot_/_ddot_/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-base"
> +
> +BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
> +
> +BR2_PACKAGE_LINUX4TEGRA=y
> +BR2_PACKAGE_LINUX4TEGRA_PLATFORM_T186REF=y
> +
> +# TODO: NVIDIA_CONTAINER_TOOLKIT requires a go-module integration.
> +# BR2_PACKAGE_NVIDIA_CONTAINER_TOOLKIT=y
> +
> +BR2_PACKAGE_LINUX_FIRMWARE=y
> +BR2_PACKAGE_LINUX_FIRMWARE_RTL_88XX=y
> +
> +# Required tools to create the image
> +BR2_PACKAGE_HOST_DOSFSTOOLS=y
> +BR2_PACKAGE_HOST_JQ=y
> +BR2_PACKAGE_HOST_PARTED=y
> +
> +# Filesystem / image
> +BR2_TARGET_ROOTFS_EXT2=y
> +BR2_TARGET_ROOTFS_EXT2_4=y
> +BR2_TARGET_ROOTFS_EXT2_SIZE="1024M"
> +# BR2_TARGET_ROOTFS_TAR is not set
> +
> +# Uboot
> +BR2_TARGET_UBOOT=y
> +BR2_TARGET_UBOOT_BOARD_DEFCONFIG="p2771-0000-500"
> +BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y
> +BR2_TARGET_UBOOT_CUSTOM_TARBALL=y
> +BR2_TARGET_UBOOT_CUSTOM_TARBALL_LOCATION="$(call github,paralin,u-boot-tegra,e6da093be3cc593ef4294e1922b3391ede9c94da)/u-boot-tegra-l4t-r32.4-v2016.7.tar.gz"
> +BR2_TARGET_UBOOT_FORMAT_DTB_BIN=y
> +BR2_TARGET_UBOOT_NEEDS_DTC=y
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Buildroot] [PATCH v3 4/5] board: add nvidia jetson tx2 support
  2020-11-18 14:58   ` Romain Naour
@ 2020-11-19  7:50     ` Christian Stewart
  0 siblings, 0 replies; 7+ messages in thread
From: Christian Stewart @ 2020-11-19  7:50 UTC (permalink / raw)
  To: buildroot

Romain,

On Wed, Nov 18, 2020 at 6:59 AM Romain Naour <romain.naour@smile.fr> wrote:

> > +# Toolchain reference: docs.nvidia.com: "Jetson Linux Driver Package Toolchain"
> > +BR2_TOOLCHAIN_BUILDROOT_CXX=y
> > +BR2_BINUTILS_VERSION_2_32_X=y
>
> AFAIK, the nvidia sdk requires a specific gcc version too. I'm not sure it can
> build with GCC 9 or 10. Cuda libraries seems requires GCC 8.

This has been tested under my Skiff project with the following:

BR2_TOOLCHAIN_BUILDROOT=y
BR2_TOOLCHAIN_BUILDROOT_CXX=y
BR2_TOOLCHAIN_BUILDROOT_GLIBC=y
BR2_TOOLCHAIN_BUILDROOT_WCHAR=y
BR2_TOOLCHAIN_BUILDROOT_LOCALE=y
BR2_BINUTILS_VERSION_2_32_X=y
BR2_GCC_VERSION_7_X=y
BR2_GCC_ENABLE_LTO=n
BR2_USE_MMU=y

I have submitted another series revision with the additional GCC
Version specifier.

Note: both the tx2 and nano have been tested and known to work well even w/ GPU.

> The vanilla linux kernel doesn't even build with gcc 8, Matt Madison (the OE4T
> maintainer) backported a lot of patches on the kernel 4.9.140 released by Nvidia
> to fixes those issues.

As noted above this has been tested against gcc 7, so I'm not sure
about > gcc 7.

> Also this kernel include nvidia kernel stack, there is a hard dependency on the
> linux4tegra version (32.4.3).

This series includes l4t 32.4.3.

Thanks for the review.

Best regards,
Christian Stewart

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-11-19  7:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-18  2:52 [Buildroot] [PATCH v3 1/5] package/nvidia-modprobe: new package Christian Stewart
2020-11-18  2:52 ` [Buildroot] [PATCH v3 2/5] package/linux4tegra: " Christian Stewart
2020-11-18  2:52 ` [Buildroot] [PATCH v3 3/5] package/libnvidia-container: " Christian Stewart
2020-11-18  2:52 ` [Buildroot] [PATCH v3 4/5] board: add nvidia jetson tx2 support Christian Stewart
2020-11-18 14:58   ` Romain Naour
2020-11-19  7:50     ` Christian Stewart
2020-11-18  2:52 ` [Buildroot] [PATCH v3 5/5] board: add nvidia jetson nano support Christian Stewart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.