File lm_sensors-r5905-fix-coretemp-detection.patch of Package sensors

Upstream changeset: r5905
Implement universal detection for Intel digital thermal sensors. This
relies on a flag returned by the cpuid instruction, as the coretemp
driver itself does since kernel 2.6.35.

---
 prog/detect/sensors-detect |   68 +++++++++++++++++++++++++++------------------
 1 file changed, 42 insertions(+), 26 deletions(-)

--- lm_sensors-3.2.0.orig/prog/detect/sensors-detect
+++ lm_sensors-3.2.0/prog/detect/sensors-detect
@@ -23,7 +23,7 @@
 require 5.004;
 
 use strict;
-use Fcntl;
+use Fcntl qw(:DEFAULT :seek);
 use File::Basename;
 
 # We will call modprobe, which typically lives in either /sbin,
@@ -2025,13 +2025,9 @@ use vars qw(@cpu_ids);
 		driver => "k10temp",
 		detect => \&fam11h_pci_detect,
 	}, {
-		name => "Intel Core family thermal sensor",
+		name => "Intel digital thermal sensor",
 		driver => "coretemp",
-		detect => sub { coretemp_detect(0); },
-	}, {
-		name => "Intel Atom thermal sensor",
-		driver => "coretemp",
-		detect => sub { coretemp_detect(1); },
+		detect => \&coretemp_detect,
 	}, {
 		name => "Intel AMB FB-DIMM thermal sensor",
 		driver => "i5k_amb",
@@ -2296,10 +2292,10 @@ sub initialize_cpu_list
 	while (<INPUTFILE>) {
 		if (m/^processor\s*:\s*(\d+)/) {
 			push @cpu, $entry if scalar keys(%{$entry}); # Previous entry
-			$entry = {}; # New entry
+			$entry = { nr => $1 }; # New entry
 			next;
 		}
-		if (m/^(vendor_id|cpu family|model|model name|stepping)\s*:\s*(.+)$/) {
+		if (m/^(vendor_id|cpu family|model|model name|stepping|cpuid level)\s*:\s*(.+)$/) {
 			my $k = $1;
 			my $v = $2;
 			$v =~ s/\s+/ /g;	# Merge multiple spaces
@@ -2468,6 +2464,15 @@ sub load_module
 	$modules_list{$normalized} = 1;
 }
 
+# udev may take some time to create device nodes when loading modules
+sub udev_settle
+{
+	if (!(-x "/sbin/udevadm" && system("/sbin/udevadm settle") == 0)
+	 && !(-x "/sbin/udevsettle" && system("/sbin/udevsettle") == 0)) {
+		sleep(1);
+	}
+}
+
 sub initialize_modules_supported
 {
 	foreach my $chip (@chip_ids) {
@@ -5757,23 +5762,33 @@ sub intel_amb_detect
 	return;
 }
 
+sub cpuid
+{
+	my ($cpu_nr, $eax) = @_;
+
+	sysopen(CPUID, "/dev/cpu/$cpu_nr/cpuid", O_RDONLY) or return;
+	binmode CPUID;
+	sysseek(CPUID, $eax, SEEK_SET)
+		or die "Cannot seek /dev/cpu/$cpu_nr/cpuid";
+	sysread(CPUID, my $data, 16)
+		or die "Cannot read /dev/cpu/$cpu_nr/cpuid";
+	close CPUID;
+
+	return unpack("L4", $data);
+}
+
 sub coretemp_detect
 {
-	my $chip = shift;
 	my $probecpu;
 
 	foreach $probecpu (@cpu) {
 		next unless $probecpu->{vendor_id} eq 'GenuineIntel' &&
-			    $probecpu->{'cpu family'} == 6;
-		return 9 if $chip == 0 &&
-			($probecpu->{model} == 14 ||	# Pentium M DC
-			 $probecpu->{model} == 15 ||	# Core 2 DC 65nm
-			 $probecpu->{model} == 0x16 ||	# Core 2 SC 65nm
-			 $probecpu->{model} == 0x17 ||	# Penryn 45nm
-			 $probecpu->{model} == 0x1a ||	# Nehalem
-			 $probecpu->{model} == 0x1e);	# Lynnfield
-		return 9 if $chip == 1 &&
-			($probecpu->{model} == 0x1c);	# Atom
+			    $probecpu->{'cpuid level'} >= 6;
+
+		# Now we check for the DTS flag
+		my @regs = cpuid($probecpu->{nr}, 6);
+		return unless @regs == 4;
+		return 9 if ($regs[0] & (1 << 0));	# eax, bit 0
 	}
 	return;
 }
@@ -6137,6 +6152,12 @@ sub main
 	print "Some south bridges, CPUs or memory controllers contain embedded sensors.\n".
 	      "Do you want to scan for them? This is totally safe. (YES/no): ";
 	unless (<STDIN> =~ /^\s*n/i) {
+		# Load the cpuid driver if needed
+		unless (-e "/dev/cpu/$cpu[0]->{nr}/cpuid") {
+			load_module("cpuid");
+			udev_settle();
+		}
+
 		$| = 1;
 		foreach my $entry (@cpu_ids) {
 			scan_cpu($entry);
@@ -6212,12 +6233,7 @@ sub main
 		$by_default = 1 if dmi_match('board_vendor', 'asustek', 'tyan',
 					     'supermicro');
 
-		# udev may take some time to create the device node
-		if (!(-x "/sbin/udevadm" && system("/sbin/udevadm settle") == 0)
-		 && !(-x "/sbin/udevsettle" && system("/sbin/udevsettle") == 0)) {
-			sleep(1);
-		}
-
+		udev_settle();
 		for (my $dev_nr = 0; $dev_nr < @i2c_adapters; $dev_nr++) {
 			next unless exists $i2c_adapters[$dev_nr];
 			scan_i2c_adapter($dev_nr, $by_default);
openSUSE Build Service is sponsored by