aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorAlan Jenkins <alan-jenkins@tuffmail.co.uk>2010-01-06 16:07:37 -0500
committerLen Brown <len.brown@intel.com>2010-01-16 01:49:13 -0500
commitda8ba01deb98f3dc0558b1f5a37e64f40bba7904 (patch)
tree25db93089a0ef7c22d764b88f8a47514155f8bc3 /drivers/platform
parent61c39bb354a1f791ba6f562b766a72e508a036ee (diff)
eeepc-laptop: disable cpu speed control on EeePC 701
The EeePC 4G ("701") implements CFVS, but it is not supported by the pre-installed OS, and the original option to change it in the BIOS setup screen was removed in later versions. Judging by the lack of "Super Hybrid Engine" on Asus product pages, this applies to all "701" models (4G/4G Surf/2G Surf). So Asus made a deliberate decision not to support it on this model. We have several reports that using it can cause the system to hang [1]. That said, it does not happen all the time. Some users do not experience it at all (and apparently wish to continue "right-clocking"). Check for the EeePC 701 using DMI. If met, then disable writes to the "cpufv" sysfs attribute and log an explanatory message. Add a "cpufv_disabled" attribute which allow users to override this policy. Writing to this attribute will log a second message. The sysfs attribute is more useful than a module option, because it makes it easier for userspace scripts to provide consistent behaviour (according to user configuration), regardless of whether the kernel includes this change. [1] <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=559578> Signed-off-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk> Signed-off-by: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/eeepc-laptop.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 5838c69b2fb3..e954f2af5724 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -35,6 +35,7 @@
35#include <linux/pci.h> 35#include <linux/pci.h>
36#include <linux/pci_hotplug.h> 36#include <linux/pci_hotplug.h>
37#include <linux/leds.h> 37#include <linux/leds.h>
38#include <linux/dmi.h>
38 39
39#define EEEPC_LAPTOP_VERSION "0.1" 40#define EEEPC_LAPTOP_VERSION "0.1"
40#define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver" 41#define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver"
@@ -159,6 +160,7 @@ struct eeepc_laptop {
159 acpi_handle handle; /* the handle of the acpi device */ 160 acpi_handle handle; /* the handle of the acpi device */
160 u32 cm_supported; /* the control methods supported 161 u32 cm_supported; /* the control methods supported
161 by this BIOS */ 162 by this BIOS */
163 bool cpufv_disabled;
162 u16 event_count[128]; /* count for each event */ 164 u16 event_count[128]; /* count for each event */
163 165
164 struct platform_device *platform_device; 166 struct platform_device *platform_device;
@@ -378,6 +380,8 @@ static ssize_t store_cpufv(struct device *dev,
378 struct eeepc_cpufv c; 380 struct eeepc_cpufv c;
379 int rv, value; 381 int rv, value;
380 382
383 if (eeepc->cpufv_disabled)
384 return -EPERM;
381 if (get_cpufv(eeepc, &c)) 385 if (get_cpufv(eeepc, &c))
382 return -ENODEV; 386 return -ENODEV;
383 rv = parse_arg(buf, count, &value); 387 rv = parse_arg(buf, count, &value);
@@ -389,6 +393,41 @@ static ssize_t store_cpufv(struct device *dev,
389 return rv; 393 return rv;
390} 394}
391 395
396static ssize_t show_cpufv_disabled(struct device *dev,
397 struct device_attribute *attr,
398 char *buf)
399{
400 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
401
402 return sprintf(buf, "%d\n", eeepc->cpufv_disabled);
403}
404
405static ssize_t store_cpufv_disabled(struct device *dev,
406 struct device_attribute *attr,
407 const char *buf, size_t count)
408{
409 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
410 int rv, value;
411
412 rv = parse_arg(buf, count, &value);
413 if (rv < 0)
414 return rv;
415
416 switch (value) {
417 case 0:
418 if (eeepc->cpufv_disabled)
419 pr_warning("cpufv enabled (not officially supported "
420 "on this model)\n");
421 eeepc->cpufv_disabled = false;
422 return rv;
423 case 1:
424 return -EPERM;
425 default:
426 return -EINVAL;
427 }
428}
429
430
392static struct device_attribute dev_attr_cpufv = { 431static struct device_attribute dev_attr_cpufv = {
393 .attr = { 432 .attr = {
394 .name = "cpufv", 433 .name = "cpufv",
@@ -404,12 +443,22 @@ static struct device_attribute dev_attr_available_cpufv = {
404 .show = show_available_cpufv 443 .show = show_available_cpufv
405}; 444};
406 445
446static struct device_attribute dev_attr_cpufv_disabled = {
447 .attr = {
448 .name = "cpufv_disabled",
449 .mode = 0644 },
450 .show = show_cpufv_disabled,
451 .store = store_cpufv_disabled
452};
453
454
407static struct attribute *platform_attributes[] = { 455static struct attribute *platform_attributes[] = {
408 &dev_attr_camera.attr, 456 &dev_attr_camera.attr,
409 &dev_attr_cardr.attr, 457 &dev_attr_cardr.attr,
410 &dev_attr_disp.attr, 458 &dev_attr_disp.attr,
411 &dev_attr_cpufv.attr, 459 &dev_attr_cpufv.attr,
412 &dev_attr_available_cpufv.attr, 460 &dev_attr_available_cpufv.attr,
461 &dev_attr_cpufv_disabled.attr,
413 NULL 462 NULL
414}; 463};
415 464
@@ -1261,6 +1310,42 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
1261 } 1310 }
1262} 1311}
1263 1312
1313static void eeepc_dmi_check(struct eeepc_laptop *eeepc)
1314{
1315 const char *model;
1316
1317 /*
1318 * Blacklist for setting cpufv (cpu speed).
1319 *
1320 * EeePC 4G ("701") implements CFVS, but it is not supported
1321 * by the pre-installed OS, and the original option to change it
1322 * in the BIOS setup screen was removed in later versions.
1323 *
1324 * Judging by the lack of "Super Hybrid Engine" on Asus product pages,
1325 * this applies to all "701" models (4G/4G Surf/2G Surf).
1326 *
1327 * So Asus made a deliberate decision not to support it on this model.
1328 * We have several reports that using it can cause the system to hang
1329 *
1330 * The hang has also been reported on a "702" (Model name "8G"?).
1331 *
1332 * We avoid dmi_check_system() / dmi_match(), because they use
1333 * substring matching. We don't want to affect the "701SD"
1334 * and "701SDX" models, because they do support S.H.E.
1335 */
1336
1337 model = dmi_get_system_info(DMI_PRODUCT_NAME);
1338 if (!model)
1339 return;
1340
1341 if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) {
1342 eeepc->cpufv_disabled = true;
1343 pr_info("model %s does not officially support setting cpu "
1344 "speed\n", model);
1345 pr_info("cpufv disabled to avoid instability\n");
1346 }
1347}
1348
1264static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name) 1349static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
1265{ 1350{
1266 int dummy; 1351 int dummy;
@@ -1342,6 +1427,8 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device)
1342 strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); 1427 strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
1343 device->driver_data = eeepc; 1428 device->driver_data = eeepc;
1344 1429
1430 eeepc_dmi_check(eeepc);
1431
1345 result = eeepc_acpi_init(eeepc, device); 1432 result = eeepc_acpi_init(eeepc, device);
1346 if (result) 1433 if (result)
1347 goto fail_platform; 1434 goto fail_platform;