diff options
Diffstat (limited to 'drivers/misc/thinkpad_acpi.c')
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 98 |
1 files changed, 70 insertions, 28 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 44aa8c92f91f..99500af651c1 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -717,9 +717,19 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm) | |||
717 | printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); | 717 | printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); |
718 | printk(IBM_INFO "%s\n", IBM_URL); | 718 | printk(IBM_INFO "%s\n", IBM_URL); |
719 | 719 | ||
720 | if (ibm_thinkpad_ec_found) | 720 | printk(IBM_INFO "ThinkPad BIOS %s, EC %s\n", |
721 | printk(IBM_INFO "ThinkPad EC firmware %s\n", | 721 | (thinkpad_id.bios_version_str) ? |
722 | ibm_thinkpad_ec_found); | 722 | thinkpad_id.bios_version_str : "unknown", |
723 | (thinkpad_id.ec_version_str) ? | ||
724 | thinkpad_id.ec_version_str : "unknown"); | ||
725 | |||
726 | if (thinkpad_id.vendor && thinkpad_id.model_str) | ||
727 | printk(IBM_INFO "%s %s\n", | ||
728 | (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ? | ||
729 | "IBM" : ((thinkpad_id.vendor == | ||
730 | PCI_VENDOR_ID_LENOVO) ? | ||
731 | "Lenovo" : "Unknown vendor"), | ||
732 | thinkpad_id.model_str); | ||
723 | 733 | ||
724 | return 0; | 734 | return 0; |
725 | } | 735 | } |
@@ -2648,7 +2658,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm) | |||
2648 | 2658 | ||
2649 | acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); | 2659 | acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); |
2650 | 2660 | ||
2651 | if (ibm_thinkpad_ec_found && experimental) { | 2661 | if (thinkpad_id.ec_model && experimental) { |
2652 | /* | 2662 | /* |
2653 | * Direct EC access mode: sensors at registers | 2663 | * Direct EC access mode: sensors at registers |
2654 | * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for | 2664 | * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for |
@@ -3532,20 +3542,19 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
3532 | * Enable for TP-1Y (T43), TP-78 (R51e), | 3542 | * Enable for TP-1Y (T43), TP-78 (R51e), |
3533 | * TP-76 (R52), TP-70 (T43, R52), which are known | 3543 | * TP-76 (R52), TP-70 (T43, R52), which are known |
3534 | * to be buggy. */ | 3544 | * to be buggy. */ |
3535 | if (fan_control_initial_status == 0x07 && | 3545 | if (fan_control_initial_status == 0x07) { |
3536 | ibm_thinkpad_ec_found && | 3546 | switch (thinkpad_id.ec_model) { |
3537 | ((ibm_thinkpad_ec_found[0] == '1' && | 3547 | case 0x5931: /* TP-1Y */ |
3538 | ibm_thinkpad_ec_found[1] == 'Y') || | 3548 | case 0x3837: /* TP-78 */ |
3539 | (ibm_thinkpad_ec_found[0] == '7' && | 3549 | case 0x3637: /* TP-76 */ |
3540 | (ibm_thinkpad_ec_found[1] == '6' || | 3550 | case 0x3037: /* TP-70 */ |
3541 | ibm_thinkpad_ec_found[1] == '8' || | 3551 | printk(IBM_NOTICE |
3542 | ibm_thinkpad_ec_found[1] == '0')) | 3552 | "fan_init: initial fan status is " |
3543 | )) { | 3553 | "unknown, assuming it is in auto " |
3544 | printk(IBM_NOTICE | 3554 | "mode\n"); |
3545 | "fan_init: initial fan status is " | 3555 | tp_features.fan_ctrl_status_undef = 1; |
3546 | "unknown, assuming it is in auto " | 3556 | ;; |
3547 | "mode\n"); | 3557 | } |
3548 | tp_features.fan_ctrl_status_undef = 1; | ||
3549 | } | 3558 | } |
3550 | } else { | 3559 | } else { |
3551 | printk(IBM_ERR | 3560 | printk(IBM_ERR |
@@ -4279,13 +4288,30 @@ static void ibm_exit(struct ibm_struct *ibm) | |||
4279 | 4288 | ||
4280 | /* Probing */ | 4289 | /* Probing */ |
4281 | 4290 | ||
4282 | static char *ibm_thinkpad_ec_found; | 4291 | static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) |
4283 | |||
4284 | static char* __init check_dmi_for_ec(void) | ||
4285 | { | 4292 | { |
4286 | struct dmi_device *dev = NULL; | 4293 | struct dmi_device *dev = NULL; |
4287 | char ec_fw_string[18]; | 4294 | char ec_fw_string[18]; |
4288 | 4295 | ||
4296 | if (!tp) | ||
4297 | return; | ||
4298 | |||
4299 | memset(tp, 0, sizeof(*tp)); | ||
4300 | |||
4301 | if (dmi_name_in_vendors("IBM")) | ||
4302 | tp->vendor = PCI_VENDOR_ID_IBM; | ||
4303 | else if (dmi_name_in_vendors("LENOVO")) | ||
4304 | tp->vendor = PCI_VENDOR_ID_LENOVO; | ||
4305 | else | ||
4306 | return; | ||
4307 | |||
4308 | tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION), | ||
4309 | GFP_KERNEL); | ||
4310 | if (!tp->bios_version_str) | ||
4311 | return; | ||
4312 | tp->bios_model = tp->bios_version_str[0] | ||
4313 | | (tp->bios_version_str[1] << 8); | ||
4314 | |||
4289 | /* | 4315 | /* |
4290 | * ThinkPad T23 or newer, A31 or newer, R50e or newer, | 4316 | * ThinkPad T23 or newer, A31 or newer, R50e or newer, |
4291 | * X32 or newer, all Z series; Some models must have an | 4317 | * X32 or newer, all Z series; Some models must have an |
@@ -4299,10 +4325,20 @@ static char* __init check_dmi_for_ec(void) | |||
4299 | ec_fw_string) == 1) { | 4325 | ec_fw_string) == 1) { |
4300 | ec_fw_string[sizeof(ec_fw_string) - 1] = 0; | 4326 | ec_fw_string[sizeof(ec_fw_string) - 1] = 0; |
4301 | ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; | 4327 | ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; |
4302 | return kstrdup(ec_fw_string, GFP_KERNEL); | 4328 | |
4329 | tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); | ||
4330 | tp->ec_model = ec_fw_string[0] | ||
4331 | | (ec_fw_string[1] << 8); | ||
4332 | break; | ||
4303 | } | 4333 | } |
4304 | } | 4334 | } |
4305 | return NULL; | 4335 | |
4336 | tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION), | ||
4337 | GFP_KERNEL); | ||
4338 | if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) { | ||
4339 | kfree(tp->model_str); | ||
4340 | tp->model_str = NULL; | ||
4341 | } | ||
4306 | } | 4342 | } |
4307 | 4343 | ||
4308 | static int __init probe_for_thinkpad(void) | 4344 | static int __init probe_for_thinkpad(void) |
@@ -4316,7 +4352,7 @@ static int __init probe_for_thinkpad(void) | |||
4316 | * Non-ancient models have better DMI tagging, but very old models | 4352 | * Non-ancient models have better DMI tagging, but very old models |
4317 | * don't. | 4353 | * don't. |
4318 | */ | 4354 | */ |
4319 | is_thinkpad = dmi_name_in_vendors("ThinkPad"); | 4355 | is_thinkpad = (thinkpad_id.model_str != NULL); |
4320 | 4356 | ||
4321 | /* ec is required because many other handles are relative to it */ | 4357 | /* ec is required because many other handles are relative to it */ |
4322 | IBM_ACPIHANDLE_INIT(ec); | 4358 | IBM_ACPIHANDLE_INIT(ec); |
@@ -4332,7 +4368,7 @@ static int __init probe_for_thinkpad(void) | |||
4332 | * false positives a damn great deal | 4368 | * false positives a damn great deal |
4333 | */ | 4369 | */ |
4334 | if (!is_thinkpad) | 4370 | if (!is_thinkpad) |
4335 | is_thinkpad = dmi_name_in_vendors("IBM"); | 4371 | is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM); |
4336 | 4372 | ||
4337 | if (!is_thinkpad && !force_load) | 4373 | if (!is_thinkpad && !force_load) |
4338 | return -ENODEV; | 4374 | return -ENODEV; |
@@ -4475,12 +4511,16 @@ static int __init thinkpad_acpi_module_init(void) | |||
4475 | int ret, i; | 4511 | int ret, i; |
4476 | 4512 | ||
4477 | /* Driver-level probe */ | 4513 | /* Driver-level probe */ |
4514 | |||
4515 | get_thinkpad_model_data(&thinkpad_id); | ||
4478 | ret = probe_for_thinkpad(); | 4516 | ret = probe_for_thinkpad(); |
4479 | if (ret) | 4517 | if (ret) { |
4518 | thinkpad_acpi_module_exit(); | ||
4480 | return ret; | 4519 | return ret; |
4520 | } | ||
4481 | 4521 | ||
4482 | /* Driver initialization */ | 4522 | /* Driver initialization */ |
4483 | ibm_thinkpad_ec_found = check_dmi_for_ec(); | 4523 | |
4484 | IBM_ACPIHANDLE_INIT(ecrd); | 4524 | IBM_ACPIHANDLE_INIT(ecrd); |
4485 | IBM_ACPIHANDLE_INIT(ecwr); | 4525 | IBM_ACPIHANDLE_INIT(ecwr); |
4486 | 4526 | ||
@@ -4590,7 +4630,9 @@ static void thinkpad_acpi_module_exit(void) | |||
4590 | if (proc_dir) | 4630 | if (proc_dir) |
4591 | remove_proc_entry(IBM_PROC_DIR, acpi_root_dir); | 4631 | remove_proc_entry(IBM_PROC_DIR, acpi_root_dir); |
4592 | 4632 | ||
4593 | kfree(ibm_thinkpad_ec_found); | 4633 | kfree(thinkpad_id.bios_version_str); |
4634 | kfree(thinkpad_id.ec_version_str); | ||
4635 | kfree(thinkpad_id.model_str); | ||
4594 | } | 4636 | } |
4595 | 4637 | ||
4596 | module_init(thinkpad_acpi_module_init); | 4638 | module_init(thinkpad_acpi_module_init); |