summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2010-07-29 14:56:40 -0700
committerAaron Plattner <aplattner@nvidia.com>2010-07-29 14:56:40 -0700
commit2afc0d0c29d810f8c96380acd9cff776302c308b (patch)
treea41a3b6f977659ca9af2e0e714eb23860a83a3bc
parent1033fdc743ea8a6502273f08e5ebd8a3a91548dc (diff)
256.44256.44
-rw-r--r--install-from-cwd.c4
-rw-r--r--kernel.c4
-rw-r--r--misc.c217
-rw-r--r--misc.h1
-rw-r--r--nvidia-installer.c1
-rw-r--r--nvidia-installer.h1
-rw-r--r--option_table.h4
-rw-r--r--version.mk2
8 files changed, 231 insertions, 3 deletions
diff --git a/install-from-cwd.c b/install-from-cwd.c
index 2af25f2..292d0a3 100644
--- a/install-from-cwd.c
+++ b/install-from-cwd.c
@@ -139,6 +139,10 @@ int install_from_cwd(Options *op)
}
ran_pre_install_hook = TRUE;
+ /* fail if the nouveau driver is currently in use */
+
+ if (!check_for_nouveau(op)) goto failed;
+
/* attempt to build a kernel module for the target kernel */
if (!op->no_kernel_module) {
diff --git a/kernel.c b/kernel.c
index 904a652..5b06253 100644
--- a/kernel.c
+++ b/kernel.c
@@ -746,8 +746,8 @@ int test_kernel_module(Options *op, Package *p)
"built against the wrong or improperly configured "
"kernel sources, with a version of gcc that differs "
"from the one used to build the target kernel, or "
- "if a driver such as rivafb/nvidiafb is present and "
- "prevents the NVIDIA kernel module from obtaining "
+ "if a driver such as rivafb, nvidiafb, or nouveau is present "
+ "and prevents the NVIDIA kernel module from obtaining "
"ownership of the NVIDIA graphics device(s), or "
"NVIDIA GPU installed in this system is not supported "
"by this NVIDIA Linux graphics driver release.\n\n"
diff --git a/misc.c b/misc.c
index 21c0a19..d613410 100644
--- a/misc.c
+++ b/misc.c
@@ -2410,3 +2410,220 @@ done:
nvfree(cmd);
return ret;
}
+
+
+
+/*
+ * Determine if the nouveau driver is currently in use. We do the
+ * equivalent of:
+ *
+ * ls -l /sys/bus/pci/devices/*\/driver | grep nouveau
+ *
+ * The directory structure under /sys/bus/pci/devices/ should contain
+ * a directory for each PCI device, and for those devices with a
+ * kernel driver there will be a "driver" symlink.
+ *
+ * This appears to be consistent with how libpciaccess works.
+ *
+ * Returns TRUE if nouveau is found; returns FALSE if not.
+ */
+
+#define SYSFS_DEVICES_PATH "/sys/bus/pci/devices"
+
+static int nouveau_is_present(void)
+{
+ DIR *dir;
+ struct dirent * ent;
+ int found = FALSE;
+
+ dir = opendir(SYSFS_DEVICES_PATH);
+
+ if (!dir) {
+ return FALSE;
+ }
+
+ while ((ent = readdir(dir)) != NULL) {
+
+ char driver_path[PATH_MAX];
+ char symlink_target[PATH_MAX];
+ char *name;
+ ssize_t ret;
+
+ if ((strcmp(ent->d_name, ".") == 0) ||
+ (strcmp(ent->d_name, "..") == 0)) {
+ continue;
+ }
+
+ snprintf(driver_path, PATH_MAX,
+ SYSFS_DEVICES_PATH "/%s/driver", ent->d_name);
+
+ driver_path[PATH_MAX - 1] = '\0';
+
+ ret = readlink(driver_path, symlink_target, PATH_MAX);
+ if (ret < 0) {
+ continue;
+ }
+
+ /* readlink(3) does not nul-terminate its returned string */
+
+ ret = NV_MIN(ret, PATH_MAX - 1);
+
+ symlink_target[ret] = '\0';
+
+ name = basename(symlink_target);
+
+ if (strcmp(name, "nouveau") == 0) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ closedir(dir);
+
+ return found;
+}
+
+
+
+/*
+ * Write a modprobe configuration fragment to disable loading of
+ * nouveau:
+ *
+ * if [ -d /etc/modprobe.d ]; then
+ * name=/etc/modprobe.d/nvidia-installer-nouveau-blacklist
+ * echo "# generated by nvidia-installer" > $name
+ * echo "blacklist nouveau" >> $name
+ * echo "options nouveau modeset=0" >> $name
+ * fi
+ *
+ * Returns TRUE if successful; returns FALSE if there was a failure.
+ */
+
+#define ETC_MODPROBE_D "/etc/modprobe.d"
+#define ETC_MODPROBE_D_FILE \
+ ETC_MODPROBE_D "/nvidia-installer-disable-nouveau.conf"
+
+/*
+ * this checksum is the result of compute_crc() for the file contents
+ * written in blacklist_nouveau()
+ */
+
+#define ETC_MODPROBE_D_FILE_CKSUM 3728279991U
+
+static int blacklist_nouveau(void)
+{
+ int ret;
+ struct stat stat_buf;
+ FILE *file;
+
+ ret = stat(ETC_MODPROBE_D, &stat_buf);
+
+ if (ret != 0) {
+ return FALSE;
+ }
+
+ file = fopen(ETC_MODPROBE_D_FILE, "w+");
+
+ if (!file) {
+ return FALSE;
+ }
+
+ fprintf(file, "# generated by nvidia-installer\n");
+ fprintf(file, "blacklist nouveau\n");
+ fprintf(file, "options nouveau modeset=0\n");
+
+ ret = fclose(file);
+
+ if (ret != 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+/*
+ * Check if the nouveau blacklist file is already present with the
+ * contents that we expect
+ */
+
+static int nouveau_blacklist_file_is_present(Options *op)
+{
+ if (access(ETC_MODPROBE_D_FILE, R_OK) != 0) {
+ return FALSE;
+ }
+
+ if (compute_crc(op, ETC_MODPROBE_D_FILE) != ETC_MODPROBE_D_FILE_CKSUM) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+/*
+ * Check if the nouveau kernel driver is in use. If it is, provide an
+ * appropriate error message and offer to try to disable nouveau.
+ *
+ * Returns FALSE if the nouveau kernel driver is in use (cause
+ * installation to abort); returns TRUE if the nouveau driver is not
+ * in use.
+ */
+
+int check_for_nouveau(Options *op)
+{
+ int ret;
+
+#define NOUVEAU_POINTER_MESSAGE \
+ "Please consult the NVIDIA driver README and your Linux " \
+ "distribution's documentation for details on how to correctly " \
+ "disable the Nouveau kernel driver."
+
+ if (op->no_nouveau_check) return TRUE;
+
+ if (!nouveau_is_present()) return TRUE;
+
+ ui_error(op, "The Nouveau kernel driver is currently in use "
+ "by your system. This driver is incompatible with the NVIDIA "
+ "driver, and must be disabled before proceeding. "
+ NOUVEAU_POINTER_MESSAGE);
+
+ if (nouveau_blacklist_file_is_present(op)) {
+ ui_warn(op, "The modprobe configuration file to disable Nouveau, "
+ ETC_MODPROBE_D_FILE ", is already present. Please be "
+ "sure you have rebooted your system since that file was "
+ "written. If you have rebooted, then Nouveau may be enabled "
+ "for other reasons, such as being included in the system "
+ "initial ramdisk or in your X configuration file. "
+ NOUVEAU_POINTER_MESSAGE);
+ return FALSE;
+ }
+
+ ret = ui_yes_no(op, FALSE, "For some distributions, Nouveau can be "
+ "disabled by adding a file in the modprobe configuration "
+ "directory. Would you like nvidia-installer to attempt "
+ "to create this modprobe file for you?");
+
+ if (ret) {
+ ret = blacklist_nouveau();
+
+ if (ret) {
+ ui_message(op, "The modprobe configuration file to disable "
+ "Nouveau, " ETC_MODPROBE_D_FILE ", has been written. "
+ "For some distributions, this may be sufficient to "
+ "disable Nouveau; other distributions may require "
+ "modification of the initial ramdisk. Please reboot "
+ "your system and attempt NVIDIA driver installation "
+ "again. Note if you later wish to reenable Nouveau, "
+ "you will need to delete the file "
+ ETC_MODPROBE_D_FILE ".");
+ } else {
+ ui_warn(op, "Unable to alter the nouveau modprobe configuration. "
+ NOUVEAU_POINTER_MESSAGE);
+ }
+ }
+
+ return FALSE;
+}
diff --git a/misc.h b/misc.h
index eda66e2..901e1ed 100644
--- a/misc.h
+++ b/misc.h
@@ -104,5 +104,6 @@ int check_for_modular_xorg(Options *op);
int check_for_nvidia_graphics_devices(Options *op, Package *p);
int run_nvidia_xconfig(Options *op);
int run_distro_hook(Options *op, const char *hook);
+int check_for_nouveau(Options *op);
#endif /* __NVIDIA_INSTALLER_MISC_H__ */
diff --git a/nvidia-installer.c b/nvidia-installer.c
index 48912f8..0269533 100644
--- a/nvidia-installer.c
+++ b/nvidia-installer.c
@@ -185,6 +185,7 @@ static void parse_commandline(int argc, char *argv[], Options *op)
op->silent = op->no_questions = op->accept_license = TRUE;
op->ui_str = "none";
break;
+ case 'z': op->no_nouveau_check = TRUE; break;
case 'k':
op->kernel_name = strval;
diff --git a/nvidia-installer.h b/nvidia-installer.h
index e1d7285..ed12589 100644
--- a/nvidia-installer.h
+++ b/nvidia-installer.h
@@ -141,6 +141,7 @@ typedef struct __options {
int no_x_check;
int no_nvidia_xconfig_question;
int run_distro_scripts;
+ int no_nouveau_check;
char *opengl_prefix;
char *opengl_libdir;
diff --git a/option_table.h b/option_table.h
index 7ad2e99..1d2a644 100644
--- a/option_table.h
+++ b/option_table.h
@@ -412,6 +412,10 @@ static const NVGetoptOption __options[] = {
"for distributing precompiled kernel interfaces in a local area "
"network." },
+ { "no-nouveau-check", 'z', 0,
+ "Normally, nvidia-installer aborts installation if the nouveau kernel "
+ "driver is in use. Use this option to disable this check." },
+
{ "run-nvidia-xconfig", 'X', 0,
"nvidia-installer can optionally invoke the nvidia-xconfig utility. "
"This will update the system X configuration file so that the NVIDIA X "
diff --git a/version.mk b/version.mk
index 9378557..00dde01 100644
--- a/version.mk
+++ b/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 256.38.02
+NVIDIA_VERSION = 256.44