X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=drivers%2Fhwmon%2Fcoretemp.c;h=bbb0b0d463f7e0c7cf489a3b30ff2057563d1749;hb=69e1ded651ee31c8a570d58647902a55806d0db8;hp=9425098928957350abda4a9bdf280a819fee15eb;hpb=ef64cf9d06049e4e9df661f3be60b217e476bee1;p=cascardo%2Flinux.git diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 942509892895..bbb0b0d463f7 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -176,20 +177,33 @@ static ssize_t show_temp(struct device *dev, /* Check whether the time interval has elapsed */ if (!tdata->valid || time_after(jiffies, tdata->last_updated + HZ)) { rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); - tdata->valid = 0; - /* Check whether the data is valid */ - if (eax & 0x80000000) { - tdata->temp = tdata->tjmax - - ((eax >> 16) & 0x7f) * 1000; - tdata->valid = 1; - } + /* + * Ignore the valid bit. In all observed cases the register + * value is either low or zero if the valid bit is 0. + * Return it instead of reporting an error which doesn't + * really help at all. + */ + tdata->temp = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000; + tdata->valid = 1; tdata->last_updated = jiffies; } mutex_unlock(&tdata->update_lock); - return tdata->valid ? sprintf(buf, "%d\n", tdata->temp) : -EAGAIN; + return sprintf(buf, "%d\n", tdata->temp); } +struct tjmax_pci { + unsigned int device; + int tjmax; +}; + +static const struct tjmax_pci tjmax_pci_table[] = { + { 0x0708, 110000 }, /* CE41x0 (Sodaville ) */ + { 0x0c72, 102000 }, /* Atom S1240 (Centerton) */ + { 0x0c73, 95000 }, /* Atom S1220 (Centerton) */ + { 0x0c75, 95000 }, /* Atom S1260 (Centerton) */ +}; + struct tjmax { char const *id; int tjmax; @@ -198,9 +212,6 @@ struct tjmax { static const struct tjmax tjmax_table[] = { { "CPU 230", 100000 }, /* Model 0x1c, stepping 2 */ { "CPU 330", 125000 }, /* Model 0x1c, stepping 2 */ - { "CPU CE4110", 110000 }, /* Model 0x1c, stepping 10 Sodaville */ - { "CPU CE4150", 110000 }, /* Model 0x1c, stepping 10 */ - { "CPU CE4170", 110000 }, /* Model 0x1c, stepping 10 */ }; struct tjmax_model { @@ -222,8 +233,11 @@ static const struct tjmax_model tjmax_model_table[] = { * is undetectable by software */ { 0x27, ANY, 90000 }, /* Atom Medfield (Z2460) */ - { 0x35, ANY, 90000 }, /* Atom Clover Trail/Cloverview (Z2760) */ - { 0x36, ANY, 100000 }, /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) */ + { 0x35, ANY, 90000 }, /* Atom Clover Trail/Cloverview (Z27x0) */ + { 0x36, ANY, 100000 }, /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) + * Also matches S12x0 (stepping 9), covered by + * PCI table + */ }; static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) @@ -236,8 +250,20 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) int err; u32 eax, edx; int i; + struct pci_dev *host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)); + + /* + * Explicit tjmax table entries override heuristics. + * First try PCI host bridge IDs, followed by model ID strings + * and model/stepping information. + */ + if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL) { + for (i = 0; i < ARRAY_SIZE(tjmax_pci_table); i++) { + if (host_bridge->device == tjmax_pci_table[i].device) + return tjmax_pci_table[i].tjmax; + } + } - /* explicit tjmax table entries override heuristics */ for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) { if (strstr(c->x86_model_id, tjmax_table[i].id)) return tjmax_table[i].tjmax; @@ -343,12 +369,12 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) if (cpu_has_tjmax(c)) dev_warn(dev, "Unable to read TjMax from CPU %u\n", id); } else { - val = (eax >> 16) & 0xff; + val = (eax >> 16) & 0x7f; /* * If the TjMax is not plausible, an assumption * will be used */ - if (val) { + if (val >= 85) { dev_dbg(dev, "TjMax is %d degrees C\n", val); return val * 1000; }