diff options
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | common-utils/msg.c | 2 | ||||
-rw-r--r-- | common-utils/nvgetopt.c | 2 | ||||
-rw-r--r-- | common-utils/nvpci-utils.c | 65 | ||||
-rw-r--r-- | common-utils/nvpci-utils.h | 33 | ||||
-rw-r--r-- | common-utils/src.mk | 13 | ||||
-rw-r--r-- | extract_edids.c | 6 | ||||
-rw-r--r-- | make_usable.c | 52 | ||||
-rw-r--r-- | multiple_screens.c | 6 | ||||
-rw-r--r-- | nvidia-xconfig.c | 2 | ||||
-rw-r--r-- | nvidia-xconfig.h | 1 | ||||
-rw-r--r-- | query_gpu_info.c | 11 | ||||
-rw-r--r-- | util.c | 31 | ||||
-rw-r--r-- | utils.mk | 3 | ||||
-rw-r--r-- | version.mk | 2 |
15 files changed, 201 insertions, 38 deletions
@@ -25,6 +25,7 @@ # include common variables and functions ############################################################################## +COMMON_UTILS_PCIACCESS = 1 include utils.mk @@ -87,14 +88,14 @@ common_cflags += -DPROGRAM_NAME=\"nvidia-xconfig\" CFLAGS += $(common_cflags) HOST_CFLAGS += $(common_cflags) -LIBS += -lm +LIBS += -lm -lpciaccess ifneq ($(TARGET_OS),FreeBSD) LIBS += -ldl endif ifeq ($(TARGET_OS),SunOS) - LIBS += -lscf + LIBS += -lscf -ldevinfo endif @@ -119,7 +120,10 @@ MANPAGE_install: $(MANPAGE) $(eval $(call DEBUG_INFO_RULES, $(NVIDIA_XCONFIG))) $(NVIDIA_XCONFIG).unstripped: $(OBJS) $(call quiet_cmd,LINK) $(CFLAGS) $(LDFLAGS) $(BIN_LDFLAGS) \ - -o $@ $(OBJS) $(LIBS) + $(PCIACCESS_LDFLAGS) -o $@ $(OBJS) $(LIBS) + +# make_usable.c includes pciaccess.h +$(call BUILD_OBJECT_LIST,make_usable.c): CFLAGS += $(PCIACCESS_CFLAGS) # define the rule to build each object file $(foreach src, $(SRC), $(eval $(call DEFINE_OBJECT_RULE,TARGET,$(src)))) diff --git a/common-utils/msg.c b/common-utils/msg.c index 8a78530..70772a2 100644 --- a/common-utils/msg.c +++ b/common-utils/msg.c @@ -113,7 +113,7 @@ do { \ NV_VSNPRINTF(buf, fmt); \ format(stream, prefix, buf, whitespace); \ free (buf); \ -} while(0) +} while (0) /* diff --git a/common-utils/nvgetopt.c b/common-utils/nvgetopt.c index 286aee8..5ae3a14 100644 --- a/common-utils/nvgetopt.c +++ b/common-utils/nvgetopt.c @@ -189,7 +189,7 @@ int nvgetopt(int argc, if (a[0] == '-') a++; if (a[0] == '+') a++; - while(a[0]) { a[0] = a[1]; a++; } + while (a[0]) { a[0] = a[1]; a++; } /* * decrement argv_index so that we process this diff --git a/common-utils/nvpci-utils.c b/common-utils/nvpci-utils.c new file mode 100644 index 0000000..62946d2 --- /dev/null +++ b/common-utils/nvpci-utils.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 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. + */ + +#include "nvpci-utils.h" + +/* + * libpciaccess stores the device class in bits 16-23, subclass in 8-15, and + * interface in bits 0-7 of dev->device_class. We care only about the class + * and subclass. + */ +const uint32_t PCI_CLASS_DISPLAY_VGA = 0x30000; +const uint32_t PCI_CLASS_SUBCLASS_MASK = 0xffff00; + +/* + * nvpci_find_gpu_by_vendor() - use libpciaccess to find all VGA and 3D PCI + * devices matching the passed-in vendor_id (which may be set to PCI_MATCH_ANY). + * The caller is responsible for calling pci_system_init() before using this + * function, and pci_system_cleanup() when libpciaccess is no longer needed. + */ +struct pci_device_iterator *nvpci_find_gpu_by_vendor(uint32_t vendor_id) +{ + const struct pci_id_match match = { + .vendor_id = vendor_id, + .device_id = PCI_MATCH_ANY, + .subvendor_id = PCI_MATCH_ANY, + .subdevice_id = PCI_MATCH_ANY, + .device_class = PCI_CLASS_DISPLAY_VGA, + /* + * Ignore bit 1 of the subclass, to allow both 0x30000 (VGA controller) + * and 0x30200 (3D controller). + */ + .device_class_mask = PCI_CLASS_SUBCLASS_MASK & ~0x200, + }; + + return pci_id_match_iterator_create(&match); +} + +/* + * nvpci_dev_is_vga() - test whether the passed-in struct pci_device* has the + * VGA device class 0x0300 (and not 3D class 0x0302). + */ +int nvpci_dev_is_vga(struct pci_device *dev) +{ + return (dev->device_class & PCI_CLASS_SUBCLASS_MASK) == + PCI_CLASS_DISPLAY_VGA; +} diff --git a/common-utils/nvpci-utils.h b/common-utils/nvpci-utils.h new file mode 100644 index 0000000..9813e90 --- /dev/null +++ b/common-utils/nvpci-utils.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 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. + */ + +#ifndef __NVPCI_UTILS_H__ +#define __NVPCI_UTILS_H__ + +#include <pciaccess.h> + +#define NV_PCI_VENDOR_ID 0x10de + +struct pci_device_iterator *nvpci_find_gpu_by_vendor(uint32_t vendor_id); +int nvpci_dev_is_vga(struct pci_device *dev); + +#endif /* __NVPCI_UTILS_H__ */ diff --git a/common-utils/src.mk b/common-utils/src.mk index 6dbed7a..bb1e1d3 100644 --- a/common-utils/src.mk +++ b/common-utils/src.mk @@ -1,5 +1,8 @@ # makefile fragment included by nvidia-xconfig, nvidia-settings, and nvidia-installer +# the including makefile should set this if the relevant program uses pciaccess +COMMON_UTILS_PCIACCESS ?= + COMMON_UTILS_SRC += nvgetopt.c COMMON_UTILS_SRC += common-utils.c COMMON_UTILS_SRC += msg.c @@ -9,6 +12,16 @@ COMMON_UTILS_EXTRA_DIST += common-utils.h COMMON_UTILS_EXTRA_DIST += msg.h COMMON_UTILS_EXTRA_DIST += src.mk +# only build nvpci-utils.c for programs that actually use libpciaccess, to +# prevent other programs from needing to set the right CFLAGS/LDFLAGS for code +# they won't use. Otherwise, just package it in the source tarball. +ifneq ($(COMMON_UTILS_PCIACCESS),) + COMMON_UTILS_SRC += nvpci-utils.c +else + COMMON_UTILS_EXTRA_DIST += nvpci-utils.c +endif +COMMON_UTILS_EXTRA_DIST += nvpci-utils.h + # gen-manpage-opts-helper.c is listed in EXTRA_DIST, rather than SRC, # because it is not compiled into the utilities themselves, but used # when building the utility's gen-manpage-opts diff --git a/extract_edids.c b/extract_edids.c index 8e2d10e..0dac31a 100644 --- a/extract_edids.c +++ b/extract_edids.c @@ -249,7 +249,7 @@ int extract_edids(Options *op) /* scan through the whole file, and build a list of pEdids */ - while(1) { + while (1) { if (fileType == LOG_FILE) { @@ -485,7 +485,7 @@ static int readEdidDataforLogFile(FilePtr pFile, EdidPtr pEdid) state = STATE_LOOKING_FOR_TOP_NIBBLE; k = 0; - while(1) { + while (1) { c = pFile->current[0]; @@ -673,7 +673,7 @@ static int readEdidDataforTextFile(FilePtr pFile, EdidPtr pEdid) state = STATE_LOOKING_FOR_TOP_NIBBLE; k = 0; - while(1) { + while (1) { c = pFile->current[0]; diff --git a/make_usable.c b/make_usable.c index 34fadd5..27bd307 100644 --- a/make_usable.c +++ b/make_usable.c @@ -29,6 +29,7 @@ #include "xf86Parser.h" #include "configProcs.h" #include "msg.h" +#include "nvpci-utils.h" static void ensure_module_loaded(XConfigPtr config, char *name); @@ -238,6 +239,32 @@ int update_server_flags(Options *op, XConfigPtr config) +static int count_non_nv_gpus(void) +{ + struct pci_device_iterator *iter; + struct pci_device *dev; + int count = 0; + + if (pci_system_init()) { + return -1; + } + + iter = nvpci_find_gpu_by_vendor(PCI_MATCH_ANY); + + for (dev = pci_device_next(iter); dev; dev = pci_device_next(iter)) { + if (dev->vendor_id != NV_PCI_VENDOR_ID) { + count++; + } + } + + pci_system_cleanup(); + + return count; +} + + + + /* * update_device() - update the device; there is a lot of information * in the device that is not relevant to the NVIDIA X driver. In @@ -254,7 +281,6 @@ static int update_device(Options *op, XConfigPtr config, XConfigDevicePtr device size_t index_id; XConfigDevicePtr next; XConfigOptionPtr options; - DevicesPtr pDevices; next = device->next; options = device->options; @@ -285,25 +311,15 @@ static int update_device(Options *op, XConfigPtr config, XConfigDevicePtr device * 3. If we want to write busid with option --busid * 4. If we want to preserve existing bus id * 5. If there are multiple screens + * 6. If the system has any non-NVIDIA GPUs */ if (GET_BOOL_OPTION(op->boolean_option_values, ENABLE_PRIME_OPTION) && op->busid == NULL) { - pDevices = find_devices(op); - if (!pDevices || pDevices->nDevices < 1) { - nv_error_msg("Unable to find any GPUs in the system."); - return FALSE; - } - if (device->index_id >= pDevices->nDevices) { - nv_error_msg("Invalid GPU index value."); + device->busid = nv_format_busid(op, device->index_id); + if (device->busid == NULL) { return FALSE; - } - device->busid = nvalloc(32); - - xconfigFormatPciBusString(device->busid, 32, - pDevices->devices[device->index_id].dev.domain, - pDevices->devices[device->index_id].dev.bus, - pDevices->devices[device->index_id].dev.slot, 0); + } } else if (op->busid == NV_DISABLE_STRING_OPTION) { device->busid = NULL; } else if (op->busid) { @@ -317,7 +333,13 @@ static int update_device(Options *op, XConfigPtr config, XConfigDevicePtr device device->busid = NULL; } } else if (config->screens->next) { + /* enable_separate_x_screens() already generated a busid string */ device->busid = busid; + } else if (count_non_nv_gpus() > 0) { + device->busid = nv_format_busid(op, device->index_id); + if (device->busid == NULL) { + return FALSE; + } } device->chipid = -1; diff --git a/multiple_screens.c b/multiple_screens.c index bfa9b23..6f0fded 100644 --- a/multiple_screens.c +++ b/multiple_screens.c @@ -638,11 +638,7 @@ static int enable_separate_x_screens(Options *op, XConfigPtr config, continue; } - screenlist[i]->device->busid = nvalloc(32); - xconfigFormatPciBusString(screenlist[i]->device->busid, 32, - pDevices->devices[i].dev.domain, - pDevices->devices[i].dev.bus, - pDevices->devices[i].dev.slot, 0); + screenlist[i]->device->busid = nv_format_busid(op, i); screenlist[i]->device->board = nvstrdup(pDevices->devices[i].name); } diff --git a/nvidia-xconfig.c b/nvidia-xconfig.c index 3144771..40ca027 100644 --- a/nvidia-xconfig.c +++ b/nvidia-xconfig.c @@ -906,7 +906,7 @@ static int write_xconfig(Options *op, XConfigPtr config, int first_touch) * to the default depth of the first screen */ if (op->disable_scf == FALSE) { - if(!update_scf_depth(config->screens[0].defaultdepth)) { + if (!update_scf_depth(config->screens[0].defaultdepth)) { goto done; } } diff --git a/nvidia-xconfig.h b/nvidia-xconfig.h index 2d345e6..be7d13c 100644 --- a/nvidia-xconfig.h +++ b/nvidia-xconfig.h @@ -200,6 +200,7 @@ typedef struct { /* util.c */ int copy_file(const char *srcfile, const char *dstfile, mode_t mode); +char *nv_format_busid(Options *op, int index); /* make_usable.c */ diff --git a/query_gpu_info.c b/query_gpu_info.c index 01e6152..2b753c6 100644 --- a/query_gpu_info.c +++ b/query_gpu_info.c @@ -27,8 +27,6 @@ static char *display_device_mask_to_display_device_name(unsigned int mask); -#define BUS_ID_STRING_LENGTH 32 - /* * query_gpu_info() - query information about the GPU, and print it @@ -40,7 +38,7 @@ int query_gpu_info(Options *op) DevicesPtr pDevices; DisplayDevicePtr pDisplayDevice; int i, j; - char *name, busid[BUS_ID_STRING_LENGTH]; + char *name, *busid; /* query the GPU information */ @@ -62,12 +60,9 @@ int query_gpu_info(Options *op) nv_info_msg(TAB, "Name : %s", pDevices->devices[i].name); nv_info_msg(TAB, "UUID : %s", pDevices->devices[i].uuid); - memset(busid, 0, BUS_ID_STRING_LENGTH); - xconfigFormatPciBusString(busid, BUS_ID_STRING_LENGTH, - pDevices->devices[i].dev.domain, - pDevices->devices[i].dev.bus, - pDevices->devices[i].dev.slot, 0); + busid = nv_format_busid(op, i); nv_info_msg(TAB, "PCI BusID : %s", busid); + nvfree(busid); nv_info_msg(NULL, ""); nv_info_msg(TAB, "Number of Display Devices: %d", @@ -171,3 +171,34 @@ void xconfigPrint(MsgType t, const char *msg) if (newline) nv_info_msg_to_file(stream, NULL, ""); } /* xconfigPrint */ + +/* a round number longer than "PCI:bus@domain:slot:function" */ +#define BUS_ID_STRING_LENGTH 32 + +/* + * nv_format_busid() - returns a newly allocated formatted string with the PCI + * Bus ID of the device with the given index, or NULL on failure. + */ +char *nv_format_busid(Options *op, int index) +{ + char buf[BUS_ID_STRING_LENGTH]; + DevicesPtr pDevices; + NvCfgPciDevice *dev; + + pDevices = find_devices(op); + if (!pDevices || pDevices->nDevices < 1) { + nv_error_msg("Unable to find any GPUs in the system."); + return NULL; + } + if (index >= pDevices->nDevices) { + nv_error_msg("Invalid GPU index value."); + return NULL; + } + + dev = &pDevices->devices[index].dev; + + xconfigFormatPciBusString(buf, sizeof(buf), + dev->domain, dev->bus, dev->slot, 0); + + return nvstrdup(buf); +} @@ -186,6 +186,8 @@ NV_QUIET_COMMAND_REMOVED_TARGET_PREFIX ?= NV_GENERATED_HEADERS ?= +PCIACCESS_CFLAGS ?= +PCIACCESS_LDFLAGS ?= ############################################################################## # This makefile uses the $(eval) builtin function, which was added in @@ -380,6 +382,7 @@ BUILD_OBJECT_LIST_WITH_DIR = \ BUILD_OBJECT_LIST = \ $(call BUILD_OBJECT_LIST_WITH_DIR,$(1),$(OUTPUTDIR)) +$(call BUILD_OBJECT_LIST,nvpci-utils.c): CFLAGS += $(PCIACCESS_CFLAGS) ############################################################################## # function to generate a list of dependency files from their @@ -1,4 +1,4 @@ -NVIDIA_VERSION = 495.46 +NVIDIA_VERSION = 510.39.01 # This file. VERSION_MK_FILE := $(lastword $(MAKEFILE_LIST)) |