From d6ee660f9d3fac5f96f1d55247ff7c6e5ffb52c4 Mon Sep 17 00:00:00 2001 From: Fierelier Date: Tue, 12 Dec 2023 06:44:09 +0100 Subject: [PATCH] Initial commit --- LICENSE | 9 +++++++ cmd/eject | 64 ++++++++++++++++++++++++++++++++++++++++++++ cmd/get_egpu_process | 27 +++++++++++++++++++ cmd/get_process_tty | 6 +++++ egpu-tk | 7 +++++ env | 9 +++++++ readme.txt | 10 +++++++ xorg-egpu-only.conf | 10 +++++++ xorg-igpu-only.conf | 10 +++++++ 9 files changed, 152 insertions(+) create mode 100644 LICENSE create mode 100644 cmd/eject create mode 100644 cmd/get_egpu_process create mode 100644 cmd/get_process_tty create mode 100755 egpu-tk create mode 100644 env create mode 100644 readme.txt create mode 100644 xorg-egpu-only.conf create mode 100644 xorg-igpu-only.conf diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..67fe97b --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2023 + +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. diff --git a/cmd/eject b/cmd/eject new file mode 100644 index 0000000..19ec063 --- /dev/null +++ b/cmd/eject @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +echo "Terminating eGPU Xorg servers..." +while true; do + EGPU_PROC="$("$APP_CMD" get_egpu_process)" + if [ "$EGPU_PROC" = "" ]; then # No eGPU process + break + fi + + echo "* $EGPU_PROC" + kill -n 15 "$EGPU_PROC" + if ! [ "$?" = "0" ]; then + echo "Process couldn't be terminated." + exit 1 + fi + + while true; do # Wait for process to close + if ! [ -d "/proc/$EGPU_PROC" ]; then + break + fi + sleep 1 + done +done + +echo "Unbinding eGPU from its drivers..." +for DEV_ID in "${EGPU_IDS[@]}"; do + DEV_PTH="/sys/bus/pci/devices/0000:$DEV_ID" + if ! [ -d "$DEV_PTH" ]; then # Device is already removed + continue + fi + + DEV_DRV_SRC="/sys/bus/pci/devices/0000:$DEV_ID/driver" + while true; do + DEV_DRV="$(readlink -f "$DEV_DRV_SRC")" + if ! [ -f "$DEV_DRV/unbind" ]; then # No driver is loaded + break + fi + echo "* ${DEV_ID}: $(basename "$DEV_DRV")" + echo "0000:$DEV_ID" > "$DEV_DRV/unbind" + while true; do # Wait for device to be unbound + if ! [ "$DEV_DRV" = "$(readlink -f "$DEV_DRV_SRC")" ]; then + break + fi + sleep 1 + done + done +done + +echo "Removing eGPU devices from PCI bus..." +for DEV_ID in "${EGPU_IDS[@]}"; do + DEV_PTH="/sys/bus/pci/devices/0000:$DEV_ID" + if ! [ -d "$DEV_PTH" ]; then # Device is already removed + continue + fi + + echo "* ${DEV_ID}" + echo "1" > "$DEV_PTH/remove" + while true; do + if ! [ -d "$DEV_PTH" ]; then + break + fi + sleep 1 + done +done +echo "Done." diff --git a/cmd/get_egpu_process b/cmd/get_egpu_process new file mode 100644 index 0000000..23ee0c1 --- /dev/null +++ b/cmd/get_egpu_process @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +for proc in "/proc"/*; do + first_arg=1 + xfconf=0 + while IFS= read -r -d '' proc_arg; do + if [ "$first_arg" = "1" ]; then + if ! [[ "$proc_arg" == *"Xorg" ]]; then + break + fi + first_arg=0 + continue + fi + + if [ "$xfconf" = "1" ]; then + if ! [ "$proc_arg" == "$IGPU_XORG_CONFIG" ]; then + echo "$(basename "$proc")" + exit 0 + fi + break + fi + + if [ "$proc_arg" = "-config" ]; then + xfconf=1 + fi + done < <(cat "$proc/cmdline" 2>/dev/null) +done +exit 0 diff --git a/cmd/get_process_tty b/cmd/get_process_tty new file mode 100644 index 0000000..1962d30 --- /dev/null +++ b/cmd/get_process_tty @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +while IFS= read -r -d '' proc_arg; do + if [[ "$proc_arg" == "vt"* ]]; then + echo "${proc_arg:2}" + fi +done < <(cat "/proc/$1/cmdline" 2>/dev/null) diff --git a/egpu-tk b/egpu-tk new file mode 100755 index 0000000..520c15c --- /dev/null +++ b/egpu-tk @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +APP_CMD="$(realpath "$BASH_SOURCE")" +APP_DIR="$(dirname "$APP_CMD")" +APP_ARGS=("${@}") +unset "APP_ARGS[0]" +source "$APP_DIR/env" +source "$APP_DIR/cmd/$1" "${APP_ARGS[@]}" diff --git a/env b/env new file mode 100644 index 0000000..be9869a --- /dev/null +++ b/env @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# IGPU info +IGPU_ID="00:02.0" # The PCI ID of the device +IGPU_XORG_CONFIG="xorg-igpu-only.conf" # The Xorg conf you use to boot a desktop on the device + +# EGPU info +EGPU_ID="05:00.0" # The PCI ID of the device +EGPU_IDS=("$EGPU_ID" "05:00.1") # Which devices to eject +EGPU_XORG_CONFIG="xorg-egpu-only.conf" # The Xorg conf you use to boot a desktop on the device diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..1914725 --- /dev/null +++ b/readme.txt @@ -0,0 +1,10 @@ +egpu-tk (External GPU Toolkit) + +A helper for managing eGPUs. This is meant to be used with 2 instances of X, both restricted to one of the GPUs. + +* Use lspci to see your devices +* Edit env appropriately +* Edit xorg-egpu-only.conf and xorg-igpu-only.conf appropriately. Put them into /etc/X11 +* Run "Xorg :1 -config xorg-igpu-only.conf vt7" for the iGPU +* Run "Xorg :2 -config xorg-igpu-only.conf vt8" for the dGPU +* To eject the dGPU, use "sudo ./egpu-tk eject" diff --git a/xorg-egpu-only.conf b/xorg-egpu-only.conf new file mode 100644 index 0000000..6e21c83 --- /dev/null +++ b/xorg-egpu-only.conf @@ -0,0 +1,10 @@ +Section "ServerFlags" + Option "AutoAddGPU" "off" +EndSection + +# GPU you want to use for display +Section "Device" + Identifier "AMD" + Driver "radeon" + BusID "PCI:5:0:0" +EndSection diff --git a/xorg-igpu-only.conf b/xorg-igpu-only.conf new file mode 100644 index 0000000..0e82c04 --- /dev/null +++ b/xorg-igpu-only.conf @@ -0,0 +1,10 @@ +Section "ServerFlags" + Option "AutoAddGPU" "off" +EndSection + +# GPU you want to use for display +Section "Device" + Identifier "Intel" + Driver "intel" + BusID "PCI:00:02:0" +EndSection