Commit 7da52c0d authored by Aaron Plattner's avatar Aaron Plattner

331.13

parent 3bb6a19e
......@@ -235,6 +235,28 @@ char *nvasprintf(const char *fmt, ...)
} /* nvasprintf() */
/*
* nv_append_sprintf() - similar to glib's g_string_append_printf(), except
* instead of operating on a GString it operates on a (char **). Appends a
* formatted string to the end of the dynamically-allocated string pointed to by
* *buf (or the empty string if *buf is NULL), potentially reallocating the
* string in the process. This function only returns on succcess.
*/
void nv_append_sprintf(char **buf, const char *fmt, ...)
{
char *prefix, *suffix;
prefix = *buf;
NV_VSNPRINTF(suffix, fmt);
if (!prefix) {
*buf = suffix;
} else {
*buf = nvstrcat(prefix, suffix, NULL);
free(prefix);
free(suffix);
}
}
/*
......@@ -413,7 +435,7 @@ TextRows *nv_format_text_rows(const char *prefix,
}
}
/* look for any newline inbetween a and b, and move b to it */
/* look for any newline between a and b, and move b to it */
for (c = a; c < b; c++) if (*c == '\n') { b = c; break; }
......
......@@ -72,6 +72,7 @@ char *nvstrtolower(char *s);
char *nvstrtoupper(char *s);
char *nvstrchrnul(char *s, int c);
char *nvasprintf(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2);
void nv_append_sprintf(char **buf, const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3);
void nvfree(void *s);
char *tilde_expansion(const char *str);
......@@ -184,4 +185,20 @@ static NV_INLINE uint64_t nv_encode_version(unsigned int major,
#define NV_VERSION4(major, minor, micro, nano) \
nv_encode_version(major, minor, micro, nano)
/*
* Helper enum that can be used for boolean values that might or might not be
* set. Care should be taken to avoid simple boolean testing, as a value of
* NV_OPTIONAL_BOOL_DEFAULT would evaluate as true.
*
* The user is responsible for unconditionally initializing the default value of
* any such booleans to NV_OPTIONAL_BOOL_DEFAULT, before any code path that
* might optionally set their values is executed.
*/
typedef enum {
NV_OPTIONAL_BOOL_DEFAULT = -1,
NV_OPTIONAL_BOOL_FALSE = FALSE,
NV_OPTIONAL_BOOL_TRUE = TRUE
} NVOptionalBool;
#endif /* __COMMON_UTILS_H__ */
......@@ -89,7 +89,7 @@ static void print_option(const NVGetoptOption *o)
* '^' : toggles bold on and off
* '-' : is backslashified: "\-"
*
* Whitespace is omited when italics or bold is on
* Whitespace is omitted when italics or bold is on
*/
italics = 0;
......
......@@ -34,8 +34,8 @@
/*
* indicates that the option is a boolean value; the presence of the
* option will be interpretted as a TRUE value; if the option is
* prepended with '--no-', the option will be interpretted as a FALSE
* option will be interpreted as a TRUE value; if the option is
* prepended with '--no-', the option will be interpreted as a FALSE
* value. On success, nvgetopt will return the parsed boolean value
* through 'boolval'.
*/
......
......@@ -41,12 +41,17 @@
#define NV_PROC_MODPROBE_PATH "/proc/sys/kernel/modprobe"
#define NV_PROC_MODULES_PATH "/proc/modules"
#define NV_NVIDIA_MODULE_NAME "nvidia"
#define NV_PROC_MODPROBE_PATH_MAX 1024
#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_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_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
......@@ -56,15 +61,95 @@
#define NV_MAJOR_DEVICE_NUMBER 195
/*
* 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';
}
/*
* Check whether the NVIDIA kernel 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(void)
static int is_kernel_module_loaded(int module_instance)
{
FILE *fp;
char module_name[16];
char module_name[NV_MAX_MODULE_NAME_SIZE];
char nv_module_name[NV_MAX_MODULE_NAME_SIZE];
int module_loaded = 0;
fp = fopen(NV_PROC_MODULES_PATH, "r");
......@@ -73,11 +158,17 @@ static int is_kernel_module_loaded(void)
{
return 0;
}
assign_nvidia_kernel_module_name(nv_module_name, module_instance);
if (nv_module_name[0] == '\0')
{
return 0;
}
while (fscanf(fp, "%15s%*[^\n]\n", module_name) == 1)
{
module_name[15] = '\0';
if (strcmp(module_name, NV_NVIDIA_MODULE_NAME) == 0)
if (strcmp(module_name, nv_module_name) == 0)
{
module_loaded = 1;
break;
......@@ -98,9 +189,10 @@ static int is_kernel_module_loaded(void)
* If any error is encountered and print_errors is non-0, then print the
* error to stderr.
*/
int nvidia_modprobe(const int print_errors)
int nvidia_modprobe(const int print_errors, int module_instance)
{
char modprobe_path[NV_PROC_MODPROBE_PATH_MAX];
char nv_module_name[NV_MAX_MODULE_NAME_SIZE];
int status = 1;
pid_t pid;
const char *envp[] = { "PATH=/sbin", NULL };
......@@ -110,7 +202,7 @@ int nvidia_modprobe(const int print_errors)
/* If the kernel module is already loaded, nothing more to do: success. */
if (is_kernel_module_loaded())
if (is_kernel_module_loaded(module_instance))
{
return 1;
}
......@@ -157,6 +249,13 @@ int nvidia_modprobe(const int print_errors)
sprintf(modprobe_path, "/sbin/modprobe");
}
assign_nvidia_kernel_module_name(nv_module_name, module_instance);
if (nv_module_name[0] == '\0')
{
return 0;
}
/* Fork and exec modprobe from the child process. */
switch (pid = fork())
......@@ -164,7 +263,7 @@ int nvidia_modprobe(const int print_errors)
case 0:
execle(modprobe_path, "modprobe",
NV_NVIDIA_MODULE_NAME, NULL, envp);
nv_module_name, NULL, envp);
/* If execl(3) returned, then an error has occurred. */
......@@ -205,19 +304,27 @@ int nvidia_modprobe(const int print_errors)
* 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)
static void init_device_file_parameters(uid_t *uid, gid_t *gid, mode_t *mode,
int *modify, int module_instance)
{
FILE *fp;
char name[32];
unsigned int value;
char proc_path[NV_MAX_PROC_REGISTRY_PATH_SIZE];
*mode = NV_DEVICE_FILE_MODE;
*uid = NV_DEVICE_FILE_UID;
*gid = NV_DEVICE_FILE_GID;
*modify = 1;
fp = fopen(NV_PROC_REGISTRY_PATH, "r");
assign_proc_registry_path(proc_path, module_instance);
if (proc_path[0] == '\0')
{
return;
}
fp = fopen(proc_path, "r");
if (fp == NULL)
{
......@@ -254,7 +361,7 @@ static void init_device_file_parameters(uid_t *uid, gid_t *gid,
* number. Returns 1 if the file is successfully created; returns 0
* if the file could not be created.
*/
int nvidia_mknod(int minor)
int nvidia_mknod(int minor, int module_instance)
{
dev_t dev = NV_MAKE_DEVICE(NV_MAJOR_DEVICE_NUMBER, minor);
char path[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN];
......@@ -266,13 +373,14 @@ int nvidia_mknod(int minor)
struct stat stat_buf;
int do_mknod;
assign_device_file_name(path, minor);
assign_device_file_name(path, minor, module_instance);
if (path[0] == '\0')
{
return 0;
}
init_device_file_parameters(&uid, &gid, &mode, &modification_allowed);
init_device_file_parameters(&uid, &gid, &mode, &modification_allowed,
module_instance);
/* If device file modification is not allowed, nothing to do: success. */
......
......@@ -30,18 +30,45 @@
#include <stdio.h>
#define NV_CTL_DEVICE_NUM 255
#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_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_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)
int nvidia_modprobe(const int print_errors);
int nvidia_mknod(int minor);
int nvidia_modprobe(const int print_errors, int module_instance);
int nvidia_mknod(int minor, int module_instance);
#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].
......@@ -49,7 +76,8 @@ int nvidia_mknod(int minor);
static __inline__ void assign_device_file_name
(
char name[NV_MAX_CHARACTER_DEVICE_FILE_STRLEN],
int minor
int minor,
int module_instance
)
{
int ret;
......@@ -59,12 +87,20 @@ static __inline__ void assign_device_file_name
goto fail;
}
if (minor == NV_CTL_DEVICE_NUM)
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,
......
......@@ -22,6 +22,8 @@ nvidia\-modprobe \- Load the NVIDIA kernel module and create NVIDIA character de
.br
.BI "nvidia\-modprobe [" "options" "] \-\-create\-nvidia\-device\-file=" MINOR-NUMBER "
.br
.BI "nvidia\-modprobe [" "options" "] \-\-module\-instance=" MODULE-INSTANCE "
.br
.SH DESCRIPTION
The
......@@ -40,7 +42,11 @@ by hand: the NVIDIA user-space driver components will fork(2)/exec(3) it when ne
.PP
When run without any options,
.B nvidia\-modprobe
will load the NVIDIA kernel module and then exit. When the
will load the NVIDIA kernel module and then exit. When the
.B \-\-module\-instance
option is specified on systems with multiple NVIDIA kernel modules,
.B nvidia\-modprobe
will load the corresponding NVIDIA kernel module and then exit. When the
.B \-\-create\-nvidia\-device\-file
option is specified,
.B nvidia\-modprobe
......@@ -63,6 +69,9 @@ Run `/sbin/modprobe nvidia` and create
and
.I
/dev/nvidia1
.TP
.B nvidia\-modprobe -i 0
Run `/sbin/modprobe nvidia0`
.
.SH AUTHOR
......
......@@ -49,7 +49,7 @@ extern const char *pNV_ID;
static void print_version(void)
{
fmtout("");
fmtout(pNV_ID);
fmtout("%s", pNV_ID);
fmtout("");
fmtoutp(TAB, "Copyright (C) 2013 NVIDIA Corporation.");
fmtout("");
......@@ -70,8 +70,8 @@ static void print_summary(void)
static void print_help_helper(const char *name, const char *description)
{
fmtoutp(TAB, name);
fmtoutp(BIGTAB, description);
fmtoutp(TAB, "%s", name);
fmtoutp(BIGTAB, "%s", description);
fmtout("");
}
......@@ -94,6 +94,7 @@ int main(int argc, char *argv[])
int minors[64];
int num_minors = 0;
int i, ret = 1;
int module_instance = NV_MODULE_INSTANCE_NONE;
while (1)
{
......@@ -128,6 +129,19 @@ int main(int argc, char *argv[])
fmterr("Too many NVIDIA character device files requested.");
exit(1);
}
break;
case 'i':
if (intval < NV_MAX_MODULE_INSTANCES &&
intval >= NV_MODULE_INSTANCE_ZERO)
{
module_instance = intval;
}
else
{
fmterr("Module instance must be in the range from "
"0 to %d.\n", (NV_MAX_MODULE_INSTANCES-1));
exit(1);
}
break;
default:
fmterr("Invalid commandline, please run `%s --help` "
......@@ -138,7 +152,7 @@ int main(int argc, char *argv[])
/* Load the kernel module. */
ret = nvidia_modprobe(0);
ret = nvidia_modprobe(0, module_instance);
if (!ret)
{
goto done;
......@@ -148,7 +162,7 @@ int main(int argc, char *argv[])
for (i = 0; i < num_minors; i++)
{
ret = nvidia_mknod(minors[i]);
ret = nvidia_mknod(minors[i], module_instance);
if (!ret)
{
goto done;
......
......@@ -38,5 +38,13 @@ static const NVGetoptOption __options[] = {
"this option can be specified multiple times to create multiple "
"NVIDIA device files." },
{ "module-instance",
'i',
NVGETOPT_INTEGER_ARGUMENT | NVGETOPT_HELP_ALWAYS,
"MODULE-INSTANCE",
"Load the required NVIDIA kernel module that corresponds to the "
"specified &MODULE-INSTANCE& value. The value should be between "
"0 and 7." },
{ NULL, 0, 0, NULL, NULL },
};
......@@ -31,7 +31,7 @@ LD ?= ld
# only set these warnings and optimizations if CFLAGS is unset
CFLAGS ?= -Wall -O2
# always set these -f CFLAGS
CFLAGS += -fno-strict-aliasing -fno-omit-frame-pointer
CFLAGS += -fno-strict-aliasing -fno-omit-frame-pointer -Wformat=2
CC_ONLY_CFLAGS ?=
LDFLAGS ?=
BIN_LDFLAGS ?=
......
NVIDIA_VERSION = 325.15
NVIDIA_VERSION = 331.13
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment