Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86: (88 commits)
ips driver: make it less chatty
intel_scu_ipc: fix size field for intel_scu_ipc_command
intel_scu_ipc: return -EIO for error condition in busy_loop
intel_scu_ipc: fix data packing of PMIC command on Moorestown
Clean up command packing on MRST.
zero the stack buffer before giving random garbage to the SCU
Fix stack buffer size for IPC writev messages
intel_scu_ipc: Use the new cpu identification function
intel_scu_ipc: tidy up unused bits
Remove indirect read write api support.
intel_scu_ipc: Support Medfield processors
intel_scu_ipc: detect CPU type automatically
x86 plat: limit x86 platform driver menu to X86
acpi ec_sys: Be more cautious about ec write access
acpi ec: Fix possible double io port registration
hp-wmi: acpi_drivers.h is already included through acpi.h two lines below
hp-wmi: Fix mixing up of and/or directive
dell-laptop: make dell_laptop_i8042_filter() static
asus-laptop: fix asus_input_init error path
msi-wmi: make needlessly global symbols static
...

+3838 -751
+20
Documentation/ABI/testing/debugfs-ec
··· 1 + What: /sys/kernel/debug/ec/*/{gpe,use_global_lock,io} 2 + Date: July 2010 3 + Contact: Thomas Renninger <trenn@suse.de> 4 + Description: 5 + 6 + General information like which GPE is assigned to the EC and whether 7 + the global lock should get used. 8 + Knowing the EC GPE one can watch the amount of HW events related to 9 + the EC here (XY -> GPE number from /sys/kernel/debug/ec/*/gpe): 10 + /sys/firmware/acpi/interrupts/gpeXY 11 + 12 + The io file is binary and a userspace tool located here: 13 + ftp://ftp.suse.com/pub/people/trenn/sources/ec/ 14 + should get used to read out the 256 Embedded Controller registers 15 + or writing to them. 16 + 17 + CAUTION: Do not write to the Embedded Controller if you don't know 18 + what you are doing! Rebooting afterwards also is a good idea. 19 + This can influence the way your machine is cooled and fans may 20 + not get switched on again after you did a wrong write.
+9 -58
Documentation/laptops/thinkpad-acpi.txt
··· 960 960 subsystem, and follow all of the hwmon guidelines at 961 961 Documentation/hwmon. 962 962 963 + EXPERIMENTAL: Embedded controller register dump 964 + ----------------------------------------------- 963 965 964 - EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump 965 - ------------------------------------------------------------------------ 966 + This feature is not included in the thinkpad driver anymore. 967 + Instead the EC can be accessed through /sys/kernel/debug/ec with 968 + a userspace tool which can be found here: 969 + ftp://ftp.suse.com/pub/people/trenn/sources/ec 966 970 967 - This feature is marked EXPERIMENTAL because the implementation 968 - directly accesses hardware registers and may not work as expected. USE 969 - WITH CAUTION! To use this feature, you need to supply the 970 - experimental=1 parameter when loading the module. 971 - 972 - This feature dumps the values of 256 embedded controller 973 - registers. Values which have changed since the last time the registers 974 - were dumped are marked with a star: 975 - 976 - [root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump 977 - EC +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f 978 - EC 0x00: a7 47 87 01 fe 96 00 08 01 00 cb 00 00 00 40 00 979 - EC 0x10: 00 00 ff ff f4 3c 87 09 01 ff 42 01 ff ff 0d 00 980 - EC 0x20: 00 00 00 00 00 00 00 00 00 00 00 03 43 00 00 80 981 - EC 0x30: 01 07 1a 00 30 04 00 00 *85 00 00 10 00 50 00 00 982 - EC 0x40: 00 00 00 00 00 00 14 01 00 04 00 00 00 00 00 00 983 - EC 0x50: 00 c0 02 0d 00 01 01 02 02 03 03 03 03 *bc *02 *bc 984 - EC 0x60: *02 *bc *02 00 00 00 00 00 00 00 00 00 00 00 00 00 985 - EC 0x70: 00 00 00 00 00 12 30 40 *24 *26 *2c *27 *20 80 *1f 80 986 - EC 0x80: 00 00 00 06 *37 *0e 03 00 00 00 0e 07 00 00 00 00 987 - EC 0x90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 988 - EC 0xa0: *ff 09 ff 09 ff ff *64 00 *00 *00 *a2 41 *ff *ff *e0 00 989 - EC 0xb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 990 - EC 0xc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 991 - EC 0xd0: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 992 - EC 0xe0: 00 00 00 00 00 00 00 00 11 20 49 04 24 06 55 03 993 - EC 0xf0: 31 55 48 54 35 38 57 57 08 2f 45 73 07 65 6c 1a 994 - 995 - This feature can be used to determine the register holding the fan 971 + Use it to determine the register holding the fan 996 972 speed on some models. To do that, do the following: 997 - 998 973 - make sure the battery is fully charged 999 974 - make sure the fan is running 1000 - - run 'cat /proc/acpi/ibm/ecdump' several times, once per second or so 975 + - use above mentioned tool to read out the EC 1001 976 1002 - The first step makes sure various charging-related values don't 1003 - vary. The second ensures that the fan-related values do vary, since 1004 - the fan speed fluctuates a bit. The third will (hopefully) mark the 1005 - fan register with a star: 1006 - 1007 - [root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump 1008 - EC +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f 1009 - EC 0x00: a7 47 87 01 fe 96 00 08 01 00 cb 00 00 00 40 00 1010 - EC 0x10: 00 00 ff ff f4 3c 87 09 01 ff 42 01 ff ff 0d 00 1011 - EC 0x20: 00 00 00 00 00 00 00 00 00 00 00 03 43 00 00 80 1012 - EC 0x30: 01 07 1a 00 30 04 00 00 85 00 00 10 00 50 00 00 1013 - EC 0x40: 00 00 00 00 00 00 14 01 00 04 00 00 00 00 00 00 1014 - EC 0x50: 00 c0 02 0d 00 01 01 02 02 03 03 03 03 bc 02 bc 1015 - EC 0x60: 02 bc 02 00 00 00 00 00 00 00 00 00 00 00 00 00 1016 - EC 0x70: 00 00 00 00 00 12 30 40 24 27 2c 27 21 80 1f 80 1017 - EC 0x80: 00 00 00 06 *be 0d 03 00 00 00 0e 07 00 00 00 00 1018 - EC 0x90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1019 - EC 0xa0: ff 09 ff 09 ff ff 64 00 00 00 a2 41 ff ff e0 00 1020 - EC 0xb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1021 - EC 0xc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1022 - EC 0xd0: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1023 - EC 0xe0: 00 00 00 00 00 00 00 00 11 20 49 04 24 06 55 03 1024 - EC 0xf0: 31 55 48 54 35 38 57 57 08 2f 45 73 07 65 6c 1a 1025 - 1026 - Another set of values that varies often is the temperature 977 + Often fan and temperature values vary between 1027 978 readings. Since temperatures don't change vary fast, you can take 1028 979 several quick dumps to eliminate them. 1029 980
+6 -14
arch/x86/include/asm/intel_scu_ipc.h
··· 1 1 #ifndef _ASM_X86_INTEL_SCU_IPC_H_ 2 2 #define _ASM_X86_INTEL_SCU_IPC_H_ 3 3 4 + #define IPCMSG_VRTC 0xFA /* Set vRTC device */ 5 + 6 + /* Command id associated with message IPCMSG_VRTC */ 7 + #define IPC_CMD_VRTC_SETTIME 1 /* Set time */ 8 + #define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */ 9 + 4 10 /* Read single register */ 5 11 int intel_scu_ipc_ioread8(u16 addr, u8 *data); 6 12 ··· 33 27 34 28 /* Update single register based on the mask */ 35 29 int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask); 36 - 37 - /* 38 - * Indirect register read 39 - * Can be used when SCCB(System Controller Configuration Block) register 40 - * HRIM(Honor Restricted IPC Messages) is set (bit 23) 41 - */ 42 - int intel_scu_ipc_register_read(u32 addr, u32 *data); 43 - 44 - /* 45 - * Indirect register write 46 - * Can be used when SCCB(System Controller Configuration Block) register 47 - * HRIM(Honor Restricted IPC Messages) is set (bit 23) 48 - */ 49 - int intel_scu_ipc_register_write(u32 addr, u32 data); 50 30 51 31 /* Issue commands to the SCU with or without data */ 52 32 int intel_scu_ipc_simple_command(int cmd, int sub);
+18
drivers/acpi/Kconfig
··· 104 104 help 105 105 Say N to disable power /sys interface 106 106 107 + config ACPI_EC_DEBUGFS 108 + tristate "EC read/write access through /sys/kernel/debug/ec" 109 + default n 110 + help 111 + Say N to disable Embedded Controller /sys/kernel/debug interface 112 + 113 + Be aware that using this interface can confuse your Embedded 114 + Controller in a way that a normal reboot is not enough. You then 115 + have to power of your system, and remove the laptop battery for 116 + some seconds. 117 + An Embedded Controller typically is available on laptops and reads 118 + sensor values like battery state and temperature. 119 + The kernel accesses the EC through ACPI parsed code provided by BIOS 120 + tables. This option allows to access the EC directly without ACPI 121 + code being involved. 122 + Thus this option is a debug option that helps to write ACPI drivers 123 + and can be used to identify ACPI code or EC firmware bugs. 124 + 107 125 config ACPI_PROC_EVENT 108 126 bool "Deprecated /proc/acpi/event support" 109 127 depends on PROC_FS
+1
drivers/acpi/Makefile
··· 60 60 obj-$(CONFIG_ACPI_SBS) += sbs.o 61 61 obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o 62 62 obj-$(CONFIG_ACPI_HED) += hed.o 63 + obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o 63 64 64 65 # processor has its own "processor." module_param namespace 65 66 processor-y := processor_driver.o processor_throttling.o
+14 -93
drivers/acpi/ec.c
··· 34 34 #include <linux/init.h> 35 35 #include <linux/types.h> 36 36 #include <linux/delay.h> 37 - #include <linux/proc_fs.h> 38 - #include <linux/seq_file.h> 39 37 #include <linux/interrupt.h> 40 38 #include <linux/list.h> 41 39 #include <linux/spinlock.h> ··· 43 45 #include <acpi/acpi_drivers.h> 44 46 #include <linux/dmi.h> 45 47 48 + #include "internal.h" 49 + 46 50 #define ACPI_EC_CLASS "embedded_controller" 47 51 #define ACPI_EC_DEVICE_NAME "Embedded Controller" 48 52 #define ACPI_EC_FILE_INFO "info" 49 53 54 + #undef PREFIX 50 55 #define PREFIX "ACPI: EC: " 51 56 52 57 /* EC status register */ ··· 107 106 bool done; 108 107 }; 109 108 110 - static struct acpi_ec { 111 - acpi_handle handle; 112 - unsigned long gpe; 113 - unsigned long command_addr; 114 - unsigned long data_addr; 115 - unsigned long global_lock; 116 - unsigned long flags; 117 - struct mutex lock; 118 - wait_queue_head_t wait; 119 - struct list_head list; 120 - struct transaction *curr; 121 - spinlock_t curr_lock; 122 - } *boot_ec, *first_ec; 109 + struct acpi_ec *boot_ec, *first_ec; 110 + EXPORT_SYMBOL(first_ec); 123 111 124 112 static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */ 125 113 static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ ··· 669 679 } 670 680 671 681 /* -------------------------------------------------------------------------- 672 - FS Interface (/proc) 673 - -------------------------------------------------------------------------- */ 674 - 675 - static struct proc_dir_entry *acpi_ec_dir; 676 - 677 - static int acpi_ec_read_info(struct seq_file *seq, void *offset) 678 - { 679 - struct acpi_ec *ec = seq->private; 680 - 681 - if (!ec) 682 - goto end; 683 - 684 - seq_printf(seq, "gpe:\t\t\t0x%02x\n", (u32) ec->gpe); 685 - seq_printf(seq, "ports:\t\t\t0x%02x, 0x%02x\n", 686 - (unsigned)ec->command_addr, (unsigned)ec->data_addr); 687 - seq_printf(seq, "use global lock:\t%s\n", 688 - ec->global_lock ? "yes" : "no"); 689 - end: 690 - return 0; 691 - } 692 - 693 - static int acpi_ec_info_open_fs(struct inode *inode, struct file *file) 694 - { 695 - return single_open(file, acpi_ec_read_info, PDE(inode)->data); 696 - } 697 - 698 - static const struct file_operations acpi_ec_info_ops = { 699 - .open = acpi_ec_info_open_fs, 700 - .read = seq_read, 701 - .llseek = seq_lseek, 702 - .release = single_release, 703 - .owner = THIS_MODULE, 704 - }; 705 - 706 - static int acpi_ec_add_fs(struct acpi_device *device) 707 - { 708 - struct proc_dir_entry *entry = NULL; 709 - 710 - if (!acpi_device_dir(device)) { 711 - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 712 - acpi_ec_dir); 713 - if (!acpi_device_dir(device)) 714 - return -ENODEV; 715 - } 716 - 717 - entry = proc_create_data(ACPI_EC_FILE_INFO, S_IRUGO, 718 - acpi_device_dir(device), 719 - &acpi_ec_info_ops, acpi_driver_data(device)); 720 - if (!entry) 721 - return -ENODEV; 722 - return 0; 723 - } 724 - 725 - static int acpi_ec_remove_fs(struct acpi_device *device) 726 - { 727 - 728 - if (acpi_device_dir(device)) { 729 - remove_proc_entry(ACPI_EC_FILE_INFO, acpi_device_dir(device)); 730 - remove_proc_entry(acpi_device_bid(device), acpi_ec_dir); 731 - acpi_device_dir(device) = NULL; 732 - } 733 - 734 - return 0; 735 - } 736 - 737 - /* -------------------------------------------------------------------------- 738 682 Driver Interface 739 683 -------------------------------------------------------------------------- */ 740 684 static acpi_status ··· 818 894 if (!first_ec) 819 895 first_ec = ec; 820 896 device->driver_data = ec; 821 - acpi_ec_add_fs(device); 897 + 898 + WARN(!request_region(ec->data_addr, 1, "EC data"), 899 + "Could not request EC data io port 0x%lx", ec->data_addr); 900 + WARN(!request_region(ec->command_addr, 1, "EC cmd"), 901 + "Could not request EC cmd io port 0x%lx", ec->command_addr); 902 + 822 903 pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", 823 904 ec->gpe, ec->command_addr, ec->data_addr); 824 905 ··· 850 921 kfree(handler); 851 922 } 852 923 mutex_unlock(&ec->lock); 853 - acpi_ec_remove_fs(device); 924 + release_region(ec->data_addr, 1); 925 + release_region(ec->command_addr, 1); 854 926 device->driver_data = NULL; 855 927 if (ec == first_ec) 856 928 first_ec = NULL; ··· 1050 1120 { 1051 1121 int result = 0; 1052 1122 1053 - acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir); 1054 - if (!acpi_ec_dir) 1055 - return -ENODEV; 1056 - 1057 1123 /* Now register the driver for the EC */ 1058 1124 result = acpi_bus_register_driver(&acpi_ec_driver); 1059 - if (result < 0) { 1060 - remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir); 1125 + if (result < 0) 1061 1126 return -ENODEV; 1062 - } 1063 1127 1064 1128 return result; 1065 1129 } ··· 1064 1140 { 1065 1141 1066 1142 acpi_bus_unregister_driver(&acpi_ec_driver); 1067 - 1068 - remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir); 1069 - 1070 1143 return; 1071 1144 } 1072 1145 #endif /* 0 */
+160
drivers/acpi/ec_sys.c
··· 1 + /* 2 + * ec_sys.c 3 + * 4 + * Copyright (C) 2010 SUSE Products GmbH/Novell 5 + * Author: 6 + * Thomas Renninger <trenn@suse.de> 7 + * 8 + * This work is licensed under the terms of the GNU GPL, version 2. 9 + */ 10 + 11 + #include <linux/kernel.h> 12 + #include <linux/acpi.h> 13 + #include <linux/debugfs.h> 14 + #include "internal.h" 15 + 16 + MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>"); 17 + MODULE_DESCRIPTION("ACPI EC sysfs access driver"); 18 + MODULE_LICENSE("GPL"); 19 + 20 + static bool write_support; 21 + module_param(write_support, bool, 0644); 22 + MODULE_PARM_DESC(write_support, "Dangerous, reboot and removal of battery may " 23 + "be needed."); 24 + 25 + #define EC_SPACE_SIZE 256 26 + 27 + struct sysdev_class acpi_ec_sysdev_class = { 28 + .name = "ec", 29 + }; 30 + 31 + static struct dentry *acpi_ec_debugfs_dir; 32 + 33 + static int acpi_ec_open_io(struct inode *i, struct file *f) 34 + { 35 + f->private_data = i->i_private; 36 + return 0; 37 + } 38 + 39 + static ssize_t acpi_ec_read_io(struct file *f, char __user *buf, 40 + size_t count, loff_t *off) 41 + { 42 + /* Use this if support reading/writing multiple ECs exists in ec.c: 43 + * struct acpi_ec *ec = ((struct seq_file *)f->private_data)->private; 44 + */ 45 + unsigned int size = EC_SPACE_SIZE; 46 + u8 *data = (u8 *) buf; 47 + loff_t init_off = *off; 48 + int err = 0; 49 + 50 + if (*off >= size) 51 + return 0; 52 + if (*off + count >= size) { 53 + size -= *off; 54 + count = size; 55 + } else 56 + size = count; 57 + 58 + while (size) { 59 + err = ec_read(*off, &data[*off - init_off]); 60 + if (err) 61 + return err; 62 + *off += 1; 63 + size--; 64 + } 65 + return count; 66 + } 67 + 68 + static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf, 69 + size_t count, loff_t *off) 70 + { 71 + /* Use this if support reading/writing multiple ECs exists in ec.c: 72 + * struct acpi_ec *ec = ((struct seq_file *)f->private_data)->private; 73 + */ 74 + 75 + unsigned int size = count; 76 + loff_t init_off = *off; 77 + u8 *data = (u8 *) buf; 78 + int err = 0; 79 + 80 + if (*off >= EC_SPACE_SIZE) 81 + return 0; 82 + if (*off + count >= EC_SPACE_SIZE) { 83 + size = EC_SPACE_SIZE - *off; 84 + count = size; 85 + } 86 + 87 + while (size) { 88 + u8 byte_write = data[*off - init_off]; 89 + err = ec_write(*off, byte_write); 90 + if (err) 91 + return err; 92 + 93 + *off += 1; 94 + size--; 95 + } 96 + return count; 97 + } 98 + 99 + static struct file_operations acpi_ec_io_ops = { 100 + .owner = THIS_MODULE, 101 + .open = acpi_ec_open_io, 102 + .read = acpi_ec_read_io, 103 + .write = acpi_ec_write_io, 104 + }; 105 + 106 + int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count) 107 + { 108 + struct dentry *dev_dir; 109 + char name[64]; 110 + mode_t mode = 0400; 111 + 112 + if (ec_device_count == 0) { 113 + acpi_ec_debugfs_dir = debugfs_create_dir("ec", NULL); 114 + if (!acpi_ec_debugfs_dir) 115 + return -ENOMEM; 116 + } 117 + 118 + sprintf(name, "ec%u", ec_device_count); 119 + dev_dir = debugfs_create_dir(name, acpi_ec_debugfs_dir); 120 + if (!dev_dir) { 121 + if (ec_device_count != 0) 122 + goto error; 123 + return -ENOMEM; 124 + } 125 + 126 + if (!debugfs_create_x32("gpe", 0444, dev_dir, (u32 *)&first_ec->gpe)) 127 + goto error; 128 + if (!debugfs_create_bool("use_global_lock", 0444, dev_dir, 129 + (u32 *)&first_ec->global_lock)) 130 + goto error; 131 + 132 + if (write_support) 133 + mode = 0600; 134 + if (!debugfs_create_file("io", mode, dev_dir, ec, &acpi_ec_io_ops)) 135 + goto error; 136 + 137 + return 0; 138 + 139 + error: 140 + debugfs_remove_recursive(acpi_ec_debugfs_dir); 141 + return -ENOMEM; 142 + } 143 + 144 + static int __init acpi_ec_sys_init(void) 145 + { 146 + int err = 0; 147 + if (first_ec) 148 + err = acpi_ec_add_debugfs(first_ec, 0); 149 + else 150 + err = -ENODEV; 151 + return err; 152 + } 153 + 154 + static void __exit acpi_ec_sys_exit(void) 155 + { 156 + debugfs_remove_recursive(acpi_ec_debugfs_dir); 157 + } 158 + 159 + module_init(acpi_ec_sys_init); 160 + module_exit(acpi_ec_sys_exit);
+24
drivers/acpi/internal.h
··· 18 18 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 19 19 */ 20 20 21 + #ifndef _ACPI_INTERNAL_H_ 22 + #define _ACPI_INTERNAL_H_ 23 + 24 + #include <linux/sysdev.h> 25 + 21 26 #define PREFIX "ACPI: " 22 27 23 28 int init_acpi_device_notify(void); ··· 51 46 /* -------------------------------------------------------------------------- 52 47 Embedded Controller 53 48 -------------------------------------------------------------------------- */ 49 + struct acpi_ec { 50 + acpi_handle handle; 51 + unsigned long gpe; 52 + unsigned long command_addr; 53 + unsigned long data_addr; 54 + unsigned long global_lock; 55 + unsigned long flags; 56 + struct mutex lock; 57 + wait_queue_head_t wait; 58 + struct list_head list; 59 + struct transaction *curr; 60 + spinlock_t curr_lock; 61 + struct sys_device sysdev; 62 + }; 63 + 64 + extern struct acpi_ec *first_ec; 65 + 54 66 int acpi_ec_init(void); 55 67 int acpi_ec_ecdt_probe(void); 56 68 int acpi_boot_ec_enable(void); ··· 85 63 #else 86 64 static inline int acpi_sleep_proc_init(void) { return 0; } 87 65 #endif 66 + 67 + #endif /* _ACPI_INTERNAL_H_ */
+44
drivers/platform/x86/Kconfig
··· 5 5 menuconfig X86_PLATFORM_DEVICES 6 6 bool "X86 Platform Specific Device Drivers" 7 7 default y 8 + depends on X86 8 9 ---help--- 9 10 Say Y here to get to see options for device drivers for various 10 11 x86 platforms, including vendor-specific laptop extension drivers. ··· 152 151 depends on ACPI 153 152 depends on BACKLIGHT_CLASS_DEVICE 154 153 depends on RFKILL 154 + depends on SERIO_I8042 155 155 ---help--- 156 156 This is a driver for laptops built by MSI (MICRO-STAR 157 157 INTERNATIONAL): ··· 183 181 depends on ACPI 184 182 depends on BACKLIGHT_CLASS_DEVICE 185 183 depends on RFKILL 184 + depends on HWMON 185 + depends on POWER_SUPPLY 186 186 ---help--- 187 187 This is a driver for laptops built by Compal: 188 188 ··· 524 520 config ACPI_CMPC 525 521 tristate "CMPC Laptop Extras" 526 522 depends on X86 && ACPI 523 + depends on RFKILL || RFKILL=n 527 524 select INPUT 528 525 select BACKLIGHT_CLASS_DEVICE 529 526 default n ··· 541 536 IPC is used to bridge the communications between kernel and SCU on 542 537 some embedded Intel x86 platforms. This is not needed for PC-type 543 538 machines. 539 + 540 + config GPIO_INTEL_PMIC 541 + bool "Intel PMIC GPIO support" 542 + depends on INTEL_SCU_IPC && GPIOLIB 543 + ---help--- 544 + Say Y here to support GPIO via the SCU IPC interface 545 + on Intel MID platforms. 546 + 547 + config RAR_REGISTER 548 + bool "Restricted Access Region Register Driver" 549 + depends on PCI && X86_MRST 550 + default n 551 + ---help--- 552 + This driver allows other kernel drivers access to the 553 + contents of the restricted access region control registers. 554 + 555 + The restricted access region control registers 556 + (rar_registers) are used to pass address and 557 + locking information on restricted access regions 558 + to other drivers that use restricted access regions. 559 + 560 + The restricted access regions are regions of memory 561 + on the Intel MID Platform that are not accessible to 562 + the x86 processor, but are accessible to dedicated 563 + processors on board peripheral devices. 564 + 565 + The purpose of the restricted access regions is to 566 + protect sensitive data from compromise by unauthorized 567 + programs running on the x86 processor. 568 + 569 + config INTEL_IPS 570 + tristate "Intel Intelligent Power Sharing" 571 + depends on ACPI 572 + ---help--- 573 + Intel Calpella platforms support dynamic power sharing between the 574 + CPU and GPU, maximizing performance in a given TDP. This driver, 575 + along with the CPU frequency and i915 drivers, provides that 576 + functionality. If in doubt, say Y here; it will only load on 577 + supported platforms. 544 578 545 579 endif # X86_PLATFORM_DEVICES
+4
drivers/platform/x86/Makefile
··· 26 26 obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o 27 27 obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o 28 28 obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o 29 + obj-$(CONFIG_RAR_REGISTER) += intel_rar_register.o 30 + obj-$(CONFIG_INTEL_IPS) += intel_ips.o 31 + obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o 32 +
+48 -31
drivers/platform/x86/acer-wmi.c
··· 50 50 #define ACER_INFO KERN_INFO ACER_LOGPREFIX 51 51 52 52 /* 53 - * The following defines quirks to get some specific functions to work 54 - * which are known to not be supported over ACPI-WMI (such as the mail LED 55 - * on WMID based Acer's) 56 - */ 57 - struct acer_quirks { 58 - const char *vendor; 59 - const char *model; 60 - u16 quirks; 61 - }; 62 - 63 - /* 64 53 * Magic Number 65 54 * Meaning is unknown - this number is required for writing to ACPI for AMW0 66 55 * (it's also used in acerhk when directly accessing the BIOS) ··· 189 200 static int dmi_matched(const struct dmi_system_id *dmi) 190 201 { 191 202 quirks = dmi->driver_data; 192 - return 0; 203 + return 1; 193 204 } 194 205 195 206 static struct quirk_entry quirk_unknown = { ··· 544 555 obj->buffer.length == sizeof(struct wmab_ret)) { 545 556 ret = *((struct wmab_ret *) obj->buffer.pointer); 546 557 } else { 558 + kfree(out.pointer); 547 559 return AE_ERROR; 548 560 } 549 561 ··· 560 570 { 561 571 struct wmab_args args; 562 572 struct wmab_ret ret; 563 - acpi_status status = AE_OK; 573 + acpi_status status; 564 574 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; 565 575 union acpi_object *obj; 566 576 ··· 583 593 if (ACPI_FAILURE(status)) 584 594 return status; 585 595 586 - obj = (union acpi_object *) out.pointer; 596 + obj = out.pointer; 587 597 if (obj && obj->type == ACPI_TYPE_BUFFER && 588 598 obj->buffer.length == sizeof(struct wmab_ret)) { 589 599 ret = *((struct wmab_ret *) obj->buffer.pointer); 590 600 } else { 591 - return AE_ERROR; 601 + status = AE_ERROR; 602 + goto out; 592 603 } 593 604 594 605 if (ret.eax & 0x1) ··· 598 607 args.ebx = 2 << 8; 599 608 args.ebx |= ACER_AMW0_BLUETOOTH_MASK; 600 609 610 + /* 611 + * It's ok to use existing buffer for next wmab_execute call. 612 + * But we need to kfree(out.pointer) if next wmab_execute fail. 613 + */ 601 614 status = wmab_execute(&args, &out); 602 615 if (ACPI_FAILURE(status)) 603 - return status; 616 + goto out; 604 617 605 618 obj = (union acpi_object *) out.pointer; 606 619 if (obj && obj->type == ACPI_TYPE_BUFFER 607 620 && obj->buffer.length == sizeof(struct wmab_ret)) { 608 621 ret = *((struct wmab_ret *) obj->buffer.pointer); 609 622 } else { 610 - return AE_ERROR; 623 + status = AE_ERROR; 624 + goto out; 611 625 } 612 626 613 627 if (ret.eax & 0x1) 614 628 interface->capability |= ACER_CAP_BLUETOOTH; 615 - 616 - kfree(out.pointer); 617 629 618 630 /* 619 631 * This appears to be safe to enable, since all Wistron based laptops ··· 626 632 if (quirks->brightness >= 0) 627 633 interface->capability |= ACER_CAP_BRIGHTNESS; 628 634 629 - return AE_OK; 635 + status = AE_OK; 636 + out: 637 + kfree(out.pointer); 638 + return status; 630 639 } 631 640 632 641 static struct wmi_interface AMW0_interface = { ··· 769 772 obj->buffer.length == sizeof(u32)) { 770 773 devices = *((u32 *) obj->buffer.pointer); 771 774 } else { 775 + kfree(out.pointer); 772 776 return AE_ERROR; 773 777 } 774 778 ··· 786 788 if (!(devices & 0x20)) 787 789 max_brightness = 0x9; 788 790 791 + kfree(out.pointer); 789 792 return status; 790 793 } 791 794 ··· 1083 1084 } 1084 1085 } 1085 1086 1086 - static DEVICE_ATTR(interface, S_IWUGO | S_IRUGO | S_IWUSR, 1087 - show_interface, NULL); 1087 + static DEVICE_ATTR(interface, S_IRUGO, show_interface, NULL); 1088 1088 1089 1089 /* 1090 1090 * debugfs functions ··· 1093 1095 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 1094 1096 union acpi_object *obj; 1095 1097 acpi_status status; 1098 + u32 devices = 0; 1096 1099 1097 1100 status = wmi_query_block(WMID_GUID2, 1, &out); 1098 1101 if (ACPI_FAILURE(status)) ··· 1102 1103 obj = (union acpi_object *) out.pointer; 1103 1104 if (obj && obj->type == ACPI_TYPE_BUFFER && 1104 1105 obj->buffer.length == sizeof(u32)) { 1105 - return *((u32 *) obj->buffer.pointer); 1106 - } else { 1107 - return 0; 1106 + devices = *((u32 *) obj->buffer.pointer); 1108 1107 } 1108 + 1109 + kfree(out.pointer); 1110 + return devices; 1109 1111 } 1110 1112 1111 1113 /* ··· 1327 1327 "generic video driver\n"); 1328 1328 } 1329 1329 1330 - if (platform_driver_register(&acer_platform_driver)) { 1330 + err = platform_driver_register(&acer_platform_driver); 1331 + if (err) { 1331 1332 printk(ACER_ERR "Unable to register platform driver.\n"); 1332 1333 goto error_platform_register; 1333 1334 } 1335 + 1334 1336 acer_platform_device = platform_device_alloc("acer-wmi", -1); 1335 - platform_device_add(acer_platform_device); 1337 + if (!acer_platform_device) { 1338 + err = -ENOMEM; 1339 + goto error_device_alloc; 1340 + } 1341 + 1342 + err = platform_device_add(acer_platform_device); 1343 + if (err) 1344 + goto error_device_add; 1336 1345 1337 1346 err = create_sysfs(); 1338 1347 if (err) 1339 - return err; 1348 + goto error_create_sys; 1340 1349 1341 1350 if (wmi_has_guid(WMID_GUID2)) { 1342 1351 interface->debug.wmid_devices = get_wmid_devices(); 1343 1352 err = create_debugfs(); 1344 1353 if (err) 1345 - return err; 1354 + goto error_create_debugfs; 1346 1355 } 1347 1356 1348 1357 /* Override any initial settings with values from the commandline */ ··· 1359 1350 1360 1351 return 0; 1361 1352 1353 + error_create_debugfs: 1354 + remove_sysfs(acer_platform_device); 1355 + error_create_sys: 1356 + platform_device_del(acer_platform_device); 1357 + error_device_add: 1358 + platform_device_put(acer_platform_device); 1359 + error_device_alloc: 1360 + platform_driver_unregister(&acer_platform_driver); 1362 1361 error_platform_register: 1363 - return -ENODEV; 1362 + return err; 1364 1363 } 1365 1364 1366 1365 static void __exit acer_wmi_exit(void) 1367 1366 { 1368 1367 remove_sysfs(acer_platform_device); 1369 1368 remove_debugfs(); 1370 - platform_device_del(acer_platform_device); 1369 + platform_device_unregister(acer_platform_device); 1371 1370 platform_driver_unregister(&acer_platform_driver); 1372 1371 1373 1372 printk(ACER_INFO "Acer Laptop WMI Extras unloaded\n");
+99 -52
drivers/platform/x86/acerhdf.c
··· 52 52 */ 53 53 #undef START_IN_KERNEL_MODE 54 54 55 - #define DRV_VER "0.5.22" 55 + #define DRV_VER "0.5.24" 56 56 57 57 /* 58 58 * According to the Atom N270 datasheet, ··· 92 92 static char force_bios[16]; 93 93 static char force_product[16]; 94 94 static unsigned int prev_interval; 95 - struct thermal_zone_device *thz_dev; 96 - struct thermal_cooling_device *cl_dev; 97 - struct platform_device *acerhdf_dev; 95 + static struct thermal_zone_device *thz_dev; 96 + static struct thermal_cooling_device *cl_dev; 97 + static struct platform_device *acerhdf_dev; 98 98 99 99 module_param(kernelmode, uint, 0); 100 100 MODULE_PARM_DESC(kernelmode, "Kernel mode fan control on / off"); ··· 112 112 MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check"); 113 113 114 114 /* 115 - * cmd_off: to switch the fan completely off 116 - * chk_off: to check if the fan is off 115 + * cmd_off: to switch the fan completely off and check if the fan is off 117 116 * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then 118 117 * the fan speed depending on the temperature 119 118 */ 120 119 struct fancmd { 121 120 u8 cmd_off; 122 - u8 chk_off; 123 121 u8 cmd_auto; 124 122 }; 125 123 ··· 134 136 /* Register addresses and values for different BIOS versions */ 135 137 static const struct bios_settings_t bios_tbl[] = { 136 138 /* AOA110 */ 137 - {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x1f, 0x00} }, 138 - {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x1f, 0x00} }, 139 - {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, 140 - {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, 141 - {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, 142 - {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0xaf, 0x00} }, 143 - {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x21, 0x00} }, 144 - {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x21, 0x00} }, 145 - {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x21, 0x00} }, 139 + {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, 140 + {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, 141 + {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, 142 + {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, 143 + {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, 144 + {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00} }, 145 + {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, 146 + {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, 147 + {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, 146 148 /* AOA150 */ 147 - {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x20, 0x00} }, 148 - {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x20, 0x00} }, 149 - {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x20, 0x00} }, 150 - {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x20, 0x00} }, 151 - {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x20, 0x00} }, 152 - {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x20, 0x00} }, 153 - {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x20, 0x00} }, 154 - {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x20, 0x00} }, 149 + {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, 150 + {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00} }, 151 + {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00} }, 152 + {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00} }, 153 + {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00} }, 154 + {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} }, 155 + {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} }, 156 + {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} }, 155 157 /* Acer 1410 */ 156 - {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 157 - {"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 158 + {"Acer", "Aspire 1410", "v0.3108", 0x55, 0x58, {0x9e, 0x00} }, 159 + {"Acer", "Aspire 1410", "v0.3113", 0x55, 0x58, {0x9e, 0x00} }, 160 + {"Acer", "Aspire 1410", "v0.3115", 0x55, 0x58, {0x9e, 0x00} }, 161 + {"Acer", "Aspire 1410", "v0.3117", 0x55, 0x58, {0x9e, 0x00} }, 162 + {"Acer", "Aspire 1410", "v0.3119", 0x55, 0x58, {0x9e, 0x00} }, 163 + {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x00} }, 164 + {"Acer", "Aspire 1410", "v1.3204", 0x55, 0x58, {0x9e, 0x00} }, 165 + {"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x00} }, 166 + {"Acer", "Aspire 1410", "v1.3308", 0x55, 0x58, {0x9e, 0x00} }, 167 + {"Acer", "Aspire 1410", "v1.3310", 0x55, 0x58, {0x9e, 0x00} }, 158 168 /* Acer 1810xx */ 159 - {"Acer", "Aspire 1810TZ", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 160 - {"Acer", "Aspire 1810T", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 161 - {"Acer", "Aspire 1810T", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 162 - {"Acer", "Aspire 1810TZ", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 169 + {"Acer", "Aspire 1810TZ", "v0.3108", 0x55, 0x58, {0x9e, 0x00} }, 170 + {"Acer", "Aspire 1810T", "v0.3108", 0x55, 0x58, {0x9e, 0x00} }, 171 + {"Acer", "Aspire 1810TZ", "v0.3113", 0x55, 0x58, {0x9e, 0x00} }, 172 + {"Acer", "Aspire 1810T", "v0.3113", 0x55, 0x58, {0x9e, 0x00} }, 173 + {"Acer", "Aspire 1810TZ", "v0.3115", 0x55, 0x58, {0x9e, 0x00} }, 174 + {"Acer", "Aspire 1810T", "v0.3115", 0x55, 0x58, {0x9e, 0x00} }, 175 + {"Acer", "Aspire 1810TZ", "v0.3117", 0x55, 0x58, {0x9e, 0x00} }, 176 + {"Acer", "Aspire 1810T", "v0.3117", 0x55, 0x58, {0x9e, 0x00} }, 177 + {"Acer", "Aspire 1810TZ", "v0.3119", 0x55, 0x58, {0x9e, 0x00} }, 178 + {"Acer", "Aspire 1810T", "v0.3119", 0x55, 0x58, {0x9e, 0x00} }, 179 + {"Acer", "Aspire 1810TZ", "v0.3120", 0x55, 0x58, {0x9e, 0x00} }, 180 + {"Acer", "Aspire 1810T", "v0.3120", 0x55, 0x58, {0x9e, 0x00} }, 181 + {"Acer", "Aspire 1810TZ", "v1.3204", 0x55, 0x58, {0x9e, 0x00} }, 182 + {"Acer", "Aspire 1810T", "v1.3204", 0x55, 0x58, {0x9e, 0x00} }, 183 + {"Acer", "Aspire 1810TZ", "v1.3303", 0x55, 0x58, {0x9e, 0x00} }, 184 + {"Acer", "Aspire 1810T", "v1.3303", 0x55, 0x58, {0x9e, 0x00} }, 185 + {"Acer", "Aspire 1810TZ", "v1.3308", 0x55, 0x58, {0x9e, 0x00} }, 186 + {"Acer", "Aspire 1810T", "v1.3308", 0x55, 0x58, {0x9e, 0x00} }, 187 + {"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00} }, 188 + {"Acer", "Aspire 1810T", "v1.3310", 0x55, 0x58, {0x9e, 0x00} }, 189 + /* Acer 531 */ 190 + {"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} }, 163 191 /* Gateway */ 164 - {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x21, 0x00} }, 165 - {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x20, 0x00} }, 166 - {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x10, 0x0f, 0x00} }, 167 - {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x10, 0x0f, 0x00} }, 168 - {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x10, 0x0f, 0x00} }, 192 + {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, 193 + {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} }, 194 + {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x9e, 0x00} }, 195 + {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x9e, 0x00} }, 196 + {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x9e, 0x00} }, 169 197 /* Packard Bell */ 170 - {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x21, 0x00} }, 171 - {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, 172 - {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x21, 0x00} }, 173 - {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, 174 - {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 175 - {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, 198 + {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} }, 199 + {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} }, 200 + {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, 201 + {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} }, 202 + {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x00} }, 203 + {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x00} }, 204 + {"Packard Bell", "DOTMU", "v0.3108", 0x55, 0x58, {0x9e, 0x00} }, 205 + {"Packard Bell", "DOTMU", "v0.3113", 0x55, 0x58, {0x9e, 0x00} }, 206 + {"Packard Bell", "DOTMU", "v0.3115", 0x55, 0x58, {0x9e, 0x00} }, 207 + {"Packard Bell", "DOTMU", "v0.3117", 0x55, 0x58, {0x9e, 0x00} }, 208 + {"Packard Bell", "DOTMU", "v0.3119", 0x55, 0x58, {0x9e, 0x00} }, 209 + {"Packard Bell", "DOTMU", "v1.3204", 0x55, 0x58, {0x9e, 0x00} }, 210 + {"Packard Bell", "DOTMA", "v1.3201", 0x55, 0x58, {0x9e, 0x00} }, 211 + {"Packard Bell", "DOTMA", "v1.3302", 0x55, 0x58, {0x9e, 0x00} }, 176 212 /* pewpew-terminator */ 177 - {"", "", "", 0, 0, {0, 0, 0} } 213 + {"", "", "", 0, 0, {0, 0} } 178 214 }; 179 215 180 216 static const struct bios_settings_t *bios_cfg __read_mostly; ··· 232 200 if (ec_read(bios_cfg->fanreg, &fan)) 233 201 return -EINVAL; 234 202 235 - if (fan != bios_cfg->cmd.chk_off) 203 + if (fan != bios_cfg->cmd.cmd_off) 236 204 *state = ACERHDF_FAN_AUTO; 237 205 else 238 206 *state = ACERHDF_FAN_OFF; ··· 406 374 } 407 375 408 376 /* bind callback functions to thermalzone */ 409 - struct thermal_zone_device_ops acerhdf_dev_ops = { 377 + static struct thermal_zone_device_ops acerhdf_dev_ops = { 410 378 .bind = acerhdf_bind, 411 379 .unbind = acerhdf_unbind, 412 380 .get_temp = acerhdf_get_ec_temp, ··· 481 449 } 482 450 483 451 /* bind fan callbacks to fan device */ 484 - struct thermal_cooling_device_ops acerhdf_cooling_ops = { 452 + static struct thermal_cooling_device_ops acerhdf_cooling_ops = { 485 453 .get_max_state = acerhdf_get_max_state, 486 454 .get_cur_state = acerhdf_get_cur_state, 487 455 .set_cur_state = acerhdf_set_cur_state, ··· 550 518 version = dmi_get_system_info(DMI_BIOS_VERSION); 551 519 product = dmi_get_system_info(DMI_PRODUCT_NAME); 552 520 521 + if (!vendor || !version || !product) { 522 + pr_err("error getting hardware information\n"); 523 + return -EINVAL; 524 + } 553 525 554 526 pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER); 555 527 ··· 615 579 return err; 616 580 617 581 acerhdf_dev = platform_device_alloc("acerhdf", -1); 618 - platform_device_add(acerhdf_dev); 582 + if (!acerhdf_dev) { 583 + err = -ENOMEM; 584 + goto err_device_alloc; 585 + } 586 + err = platform_device_add(acerhdf_dev); 587 + if (err) 588 + goto err_device_add; 619 589 620 590 return 0; 591 + 592 + err_device_add: 593 + platform_device_put(acerhdf_dev); 594 + err_device_alloc: 595 + platform_driver_unregister(&acerhdf_driver); 596 + return err; 621 597 } 622 598 623 599 static void acerhdf_unregister_platform(void) 624 600 { 625 - if (!acerhdf_dev) 626 - return; 627 - 628 - platform_device_del(acerhdf_dev); 601 + platform_device_unregister(acerhdf_dev); 629 602 platform_driver_unregister(&acerhdf_driver); 630 603 } 631 604 ··· 678 633 679 634 err = acerhdf_register_platform(); 680 635 if (err) 681 - goto err_unreg; 636 + goto out_err; 682 637 683 638 err = acerhdf_register_thermal(); 684 639 if (err) ··· 691 646 acerhdf_unregister_platform(); 692 647 693 648 out_err: 694 - return -ENODEV; 649 + return err; 695 650 } 696 651 697 652 static void __exit acerhdf_exit(void) ··· 707 662 MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:"); 708 663 MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1410*:"); 709 664 MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1810*:"); 665 + MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:"); 710 666 MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:"); 711 667 MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:"); 712 668 MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:"); 713 669 MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:"); 714 670 MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMU*:"); 671 + MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMA*:"); 715 672 716 673 module_init(acerhdf_init); 717 674 module_exit(acerhdf_exit);
+16 -13
drivers/platform/x86/asus-laptop.c
··· 76 76 * So, if something doesn't work as you want, just try other values =) 77 77 */ 78 78 static uint wapf = 1; 79 - module_param(wapf, uint, 0644); 79 + module_param(wapf, uint, 0444); 80 80 MODULE_PARM_DESC(wapf, "WAPF value"); 81 81 82 82 static int wlan_status = 1; 83 83 static int bluetooth_status = 1; 84 84 85 - module_param(wlan_status, int, 0644); 85 + module_param(wlan_status, int, 0444); 86 86 MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot " 87 87 "(0 = disabled, 1 = enabled, -1 = don't do anything). " 88 88 "default is 1"); 89 89 90 - module_param(bluetooth_status, int, 0644); 90 + module_param(bluetooth_status, int, 0444); 91 91 MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " 92 92 "(0 = disabled, 1 = enabled, -1 = don't do anything). " 93 93 "default is 1"); ··· 297 297 acpi_status status; 298 298 299 299 if (!handle) 300 - return 0; 300 + return -1; 301 301 302 302 params.count = 1; 303 303 params.pointer = &in_obj; ··· 796 796 797 797 rv = parse_arg(buf, count, &value); 798 798 if (rv > 0) { 799 - if (write_acpi_int(asus->handle, METHOD_LEDD, value)) 799 + if (write_acpi_int(asus->handle, METHOD_LEDD, value)) { 800 800 pr_warning("LED display write failed\n"); 801 - else 802 - asus->ledd_status = (u32) value; 801 + return -ENODEV; 802 + } 803 + asus->ledd_status = (u32) value; 803 804 } 804 805 return rv; 805 806 } ··· 1124 1123 input = input_allocate_device(); 1125 1124 if (!input) { 1126 1125 pr_info("Unable to allocate input device\n"); 1127 - return 0; 1126 + return -ENOMEM; 1128 1127 } 1129 1128 input->name = "Asus Laptop extra buttons"; 1130 1129 input->phys = ASUS_LAPTOP_FILE "/input0"; ··· 1135 1134 error = sparse_keymap_setup(input, asus_keymap, NULL); 1136 1135 if (error) { 1137 1136 pr_err("Unable to setup input device keymap\n"); 1138 - goto err_keymap; 1137 + goto err_free_dev; 1139 1138 } 1140 1139 error = input_register_device(input); 1141 1140 if (error) { 1142 1141 pr_info("Unable to register input device\n"); 1143 - goto err_device; 1142 + goto err_free_keymap; 1144 1143 } 1145 1144 1146 1145 asus->inputdev = input; 1147 1146 return 0; 1148 1147 1149 - err_keymap: 1148 + err_free_keymap: 1150 1149 sparse_keymap_free(input); 1151 - err_device: 1150 + err_free_dev: 1152 1151 input_free_device(input); 1153 1152 return error; 1154 1153 } ··· 1398 1397 } 1399 1398 } 1400 1399 asus->name = kstrdup(string, GFP_KERNEL); 1401 - if (!asus->name) 1400 + if (!asus->name) { 1401 + kfree(buffer.pointer); 1402 1402 return -ENOMEM; 1403 + } 1403 1404 1404 1405 if (*string) 1405 1406 pr_notice(" %s model detected\n", string);
+4 -3
drivers/platform/x86/asus_acpi.c
··· 1330 1330 hotk->model = P30; 1331 1331 printk(KERN_NOTICE 1332 1332 " Samsung P30 detected, supported\n"); 1333 + hotk->methods = &model_conf[hotk->model]; 1334 + kfree(model); 1335 + return 0; 1333 1336 } else { 1334 1337 hotk->model = M2E; 1335 1338 printk(KERN_NOTICE " unsupported model %s, trying " ··· 1342 1339 kfree(model); 1343 1340 return -ENODEV; 1344 1341 } 1345 - hotk->methods = &model_conf[hotk->model]; 1346 - return AE_OK; 1347 1342 } 1348 1343 hotk->methods = &model_conf[hotk->model]; 1349 1344 printk(KERN_NOTICE " %s model detected, supported\n", string); ··· 1375 1374 1376 1375 kfree(model); 1377 1376 1378 - return AE_OK; 1377 + return 0; 1379 1378 } 1380 1379 1381 1380 static int asus_hotk_check(void)
+7 -6
drivers/platform/x86/classmate-laptop.c
··· 208 208 return strnlen(buf, count); 209 209 } 210 210 211 - struct device_attribute cmpc_accel_sensitivity_attr = { 211 + static struct device_attribute cmpc_accel_sensitivity_attr = { 212 212 .attr = { .name = "sensitivity", .mode = 0660 }, 213 213 .show = cmpc_accel_sensitivity_show, 214 214 .store = cmpc_accel_sensitivity_store ··· 573 573 574 574 ipml->rf = rfkill_alloc("cmpc_rfkill", &acpi->dev, RFKILL_TYPE_WLAN, 575 575 &cmpc_rfkill_ops, acpi->handle); 576 - /* rfkill_alloc may fail if RFKILL is disabled. We should still work 577 - * anyway. */ 578 - if (!IS_ERR(ipml->rf)) { 576 + /* 577 + * If RFKILL is disabled, rfkill_alloc will return ERR_PTR(-ENODEV). 578 + * This is OK, however, since all other uses of the device will not 579 + * derefence it. 580 + */ 581 + if (ipml->rf) { 579 582 retval = rfkill_register(ipml->rf); 580 583 if (retval) { 581 584 rfkill_destroy(ipml->rf); 582 585 ipml->rf = NULL; 583 586 } 584 - } else { 585 - ipml->rf = NULL; 586 587 } 587 588 588 589 dev_set_drvdata(&acpi->dev, ipml);
+833 -116
drivers/platform/x86/compal-laptop.c
··· 24 24 */ 25 25 26 26 /* 27 - * comapl-laptop.c - Compal laptop support. 27 + * compal-laptop.c - Compal laptop support. 28 28 * 29 - * The driver registers itself with the rfkill subsystem and 30 - * the Linux backlight control subsystem. 29 + * This driver exports a few files in /sys/devices/platform/compal-laptop/: 30 + * wake_up_XXX Whether or not we listen to such wake up events (rw) 31 + * 32 + * In addition to these platform device attributes the driver 33 + * registers itself in the Linux backlight control, power_supply, rfkill 34 + * and hwmon subsystem and is available to userspace under: 35 + * 36 + * /sys/class/backlight/compal-laptop/ 37 + * /sys/class/power_supply/compal-laptop/ 38 + * /sys/class/rfkill/rfkillX/ 39 + * /sys/class/hwmon/hwmonX/ 40 + * 41 + * Notes on the power_supply battery interface: 42 + * - the "minimum" design voltage is *the* design voltage 43 + * - the ambient temperature is the average battery temperature 44 + * and the value is an educated guess (see commented code below) 45 + * 31 46 * 32 47 * This driver might work on other laptops produced by Compal. If you 33 48 * want to try it you can pass force=1 as argument to the module which 34 49 * will force it to load even when the DMI data doesn't identify the 35 - * laptop as FL9x. 50 + * laptop as compatible. 51 + * 52 + * Lots of data available at: 53 + * http://service1.marasst.com/Compal/JHL90_91/Service%20Manual/ 54 + * JHL90%20service%20manual-Final-0725.pdf 55 + * 56 + * 57 + * 58 + * Support for the Compal JHL90 added by Roald Frederickx 59 + * (roald.frederickx@gmail.com): 60 + * Driver got large revision. Added functionalities: backlight 61 + * power, wake_on_XXX, a hwmon and power_supply interface. 62 + * 63 + * In case this gets merged into the kernel source: I want to dedicate this 64 + * to Kasper Meerts, the awesome guy who showed me Linux and C! 36 65 */ 66 + 67 + /* NOTE: currently the wake_on_XXX, hwmon and power_supply interfaces are 68 + * only enabled on a JHL90 board until it is verified that they work on the 69 + * other boards too. See the extra_features variable. */ 37 70 38 71 #include <linux/module.h> 39 72 #include <linux/kernel.h> ··· 76 43 #include <linux/backlight.h> 77 44 #include <linux/platform_device.h> 78 45 #include <linux/rfkill.h> 46 + #include <linux/hwmon.h> 47 + #include <linux/hwmon-sysfs.h> 48 + #include <linux/power_supply.h> 49 + #include <linux/fb.h> 79 50 80 - #define COMPAL_DRIVER_VERSION "0.2.6" 81 51 82 - #define COMPAL_LCD_LEVEL_MAX 8 52 + /* ======= */ 53 + /* Defines */ 54 + /* ======= */ 55 + #define DRIVER_NAME "compal-laptop" 56 + #define DRIVER_VERSION "0.2.7" 83 57 84 - #define COMPAL_EC_COMMAND_WIRELESS 0xBB 85 - #define COMPAL_EC_COMMAND_LCD_LEVEL 0xB9 58 + #define BACKLIGHT_LEVEL_ADDR 0xB9 59 + #define BACKLIGHT_LEVEL_MAX 7 60 + #define BACKLIGHT_STATE_ADDR 0x59 61 + #define BACKLIGHT_STATE_ON_DATA 0xE1 62 + #define BACKLIGHT_STATE_OFF_DATA 0xE2 86 63 87 - #define KILLSWITCH_MASK 0x10 88 - #define WLAN_MASK 0x01 89 - #define BT_MASK 0x02 64 + #define WAKE_UP_ADDR 0xA4 65 + #define WAKE_UP_PME (1 << 0) 66 + #define WAKE_UP_MODEM (1 << 1) 67 + #define WAKE_UP_LAN (1 << 2) 68 + #define WAKE_UP_WLAN (1 << 4) 69 + #define WAKE_UP_KEY (1 << 6) 70 + #define WAKE_UP_MOUSE (1 << 7) 90 71 91 - static struct rfkill *wifi_rfkill; 92 - static struct rfkill *bt_rfkill; 93 - static struct platform_device *compal_device; 72 + #define WIRELESS_ADDR 0xBB 73 + #define WIRELESS_WLAN (1 << 0) 74 + #define WIRELESS_BT (1 << 1) 75 + #define WIRELESS_WLAN_EXISTS (1 << 2) 76 + #define WIRELESS_BT_EXISTS (1 << 3) 77 + #define WIRELESS_KILLSWITCH (1 << 4) 94 78 79 + #define PWM_ADDRESS 0x46 80 + #define PWM_DISABLE_ADDR 0x59 81 + #define PWM_DISABLE_DATA 0xA5 82 + #define PWM_ENABLE_ADDR 0x59 83 + #define PWM_ENABLE_DATA 0xA8 84 + 85 + #define FAN_ADDRESS 0x46 86 + #define FAN_DATA 0x81 87 + #define FAN_FULL_ON_CMD 0x59 /* Doesn't seem to work. Just */ 88 + #define FAN_FULL_ON_ENABLE 0x76 /* force the pwm signal to its */ 89 + #define FAN_FULL_ON_DISABLE 0x77 /* maximum value instead */ 90 + 91 + #define TEMP_CPU 0xB0 92 + #define TEMP_CPU_LOCAL 0xB1 93 + #define TEMP_CPU_DTS 0xB5 94 + #define TEMP_NORTHBRIDGE 0xB6 95 + #define TEMP_VGA 0xB4 96 + #define TEMP_SKIN 0xB2 97 + 98 + #define BAT_MANUFACTURER_NAME_ADDR 0x10 99 + #define BAT_MANUFACTURER_NAME_LEN 9 100 + #define BAT_MODEL_NAME_ADDR 0x19 101 + #define BAT_MODEL_NAME_LEN 6 102 + #define BAT_SERIAL_NUMBER_ADDR 0xC4 103 + #define BAT_SERIAL_NUMBER_LEN 5 104 + #define BAT_CHARGE_NOW 0xC2 105 + #define BAT_CHARGE_DESIGN 0xCA 106 + #define BAT_VOLTAGE_NOW 0xC6 107 + #define BAT_VOLTAGE_DESIGN 0xC8 108 + #define BAT_CURRENT_NOW 0xD0 109 + #define BAT_CURRENT_AVG 0xD2 110 + #define BAT_POWER 0xD4 111 + #define BAT_CAPACITY 0xCE 112 + #define BAT_TEMP 0xD6 113 + #define BAT_TEMP_AVG 0xD7 114 + #define BAT_STATUS0 0xC1 115 + #define BAT_STATUS1 0xF0 116 + #define BAT_STATUS2 0xF1 117 + #define BAT_STOP_CHARGE1 0xF2 118 + #define BAT_STOP_CHARGE2 0xF3 119 + 120 + #define BAT_S0_DISCHARGE (1 << 0) 121 + #define BAT_S0_DISCHRG_CRITICAL (1 << 2) 122 + #define BAT_S0_LOW (1 << 3) 123 + #define BAT_S0_CHARGING (1 << 1) 124 + #define BAT_S0_AC (1 << 7) 125 + #define BAT_S1_EXISTS (1 << 0) 126 + #define BAT_S1_FULL (1 << 1) 127 + #define BAT_S1_EMPTY (1 << 2) 128 + #define BAT_S1_LiION_OR_NiMH (1 << 7) 129 + #define BAT_S2_LOW_LOW (1 << 0) 130 + #define BAT_STOP_CHRG1_BAD_CELL (1 << 1) 131 + #define BAT_STOP_CHRG1_COMM_FAIL (1 << 2) 132 + #define BAT_STOP_CHRG1_OVERVOLTAGE (1 << 6) 133 + #define BAT_STOP_CHRG1_OVERTEMPERATURE (1 << 7) 134 + 135 + 136 + /* ======= */ 137 + /* Structs */ 138 + /* ======= */ 139 + struct compal_data{ 140 + /* Fan control */ 141 + struct device *hwmon_dev; 142 + int pwm_enable; /* 0:full on, 1:set by pwm1, 2:control by moterboard */ 143 + unsigned char curr_pwm; 144 + 145 + /* Power supply */ 146 + struct power_supply psy; 147 + struct power_supply_info psy_info; 148 + char bat_model_name[BAT_MODEL_NAME_LEN + 1]; 149 + char bat_manufacturer_name[BAT_MANUFACTURER_NAME_LEN + 1]; 150 + char bat_serial_number[BAT_SERIAL_NUMBER_LEN + 1]; 151 + }; 152 + 153 + 154 + /* =============== */ 155 + /* General globals */ 156 + /* =============== */ 95 157 static int force; 96 158 module_param(force, bool, 0); 97 159 MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); 98 160 99 - /* Hardware access */ 161 + /* Support for the wake_on_XXX, hwmon and power_supply interface. Currently 162 + * only gets enabled on a JHL90 board. Might work with the others too */ 163 + static bool extra_features; 100 164 101 - static int set_lcd_level(int level) 165 + /* Nasty stuff. For some reason the fan control is very un-linear. I've 166 + * come up with these values by looping through the possible inputs and 167 + * watching the output of address 0x4F (do an ec_transaction writing 0x33 168 + * into 0x4F and read a few bytes from the output, like so: 169 + * u8 writeData = 0x33; 170 + * ec_transaction(0x4F, &writeData, 1, buffer, 32, 0); 171 + * That address is labled "fan1 table information" in the service manual. 172 + * It should be clear which value in 'buffer' changes). This seems to be 173 + * related to fan speed. It isn't a proper 'realtime' fan speed value 174 + * though, because physically stopping or speeding up the fan doesn't 175 + * change it. It might be the average voltage or current of the pwm output. 176 + * Nevertheless, it is more fine-grained than the actual RPM reading */ 177 + static const unsigned char pwm_lookup_table[256] = { 178 + 0, 0, 0, 1, 1, 1, 2, 253, 254, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 179 + 7, 7, 7, 8, 86, 86, 9, 9, 9, 10, 10, 10, 11, 92, 92, 12, 12, 95, 180 + 13, 66, 66, 14, 14, 98, 15, 15, 15, 16, 16, 67, 17, 17, 72, 18, 70, 181 + 75, 19, 90, 90, 73, 73, 73, 21, 21, 91, 91, 91, 96, 23, 94, 94, 94, 182 + 94, 94, 94, 94, 94, 94, 94, 141, 141, 238, 223, 192, 139, 139, 139, 183 + 139, 139, 142, 142, 142, 142, 142, 78, 78, 78, 78, 78, 76, 76, 76, 184 + 76, 76, 79, 79, 79, 79, 79, 79, 79, 20, 20, 20, 20, 20, 22, 22, 22, 185 + 22, 22, 24, 24, 24, 24, 24, 24, 219, 219, 219, 219, 219, 219, 219, 186 + 219, 27, 27, 188, 188, 28, 28, 28, 29, 186, 186, 186, 186, 186, 187 + 186, 186, 186, 186, 186, 31, 31, 31, 31, 31, 32, 32, 32, 41, 33, 188 + 33, 33, 33, 33, 252, 252, 34, 34, 34, 43, 35, 35, 35, 36, 36, 38, 189 + 206, 206, 206, 206, 206, 206, 206, 206, 206, 37, 37, 37, 46, 46, 190 + 47, 47, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 48, 48, 191 + 48, 48, 48, 40, 40, 40, 49, 42, 42, 42, 42, 42, 42, 42, 42, 44, 192 + 189, 189, 189, 189, 54, 54, 45, 45, 45, 45, 45, 45, 45, 45, 251, 193 + 191, 199, 199, 199, 199, 199, 215, 215, 215, 215, 187, 187, 187, 194 + 187, 187, 193, 50 195 + }; 196 + 197 + 198 + 199 + 200 + /* ========================= */ 201 + /* Hardware access functions */ 202 + /* ========================= */ 203 + /* General access */ 204 + static u8 ec_read_u8(u8 addr) 102 205 { 103 - if (level < 0 || level >= COMPAL_LCD_LEVEL_MAX) 206 + u8 value; 207 + ec_read(addr, &value); 208 + return value; 209 + } 210 + 211 + static s8 ec_read_s8(u8 addr) 212 + { 213 + return (s8)ec_read_u8(addr); 214 + } 215 + 216 + static u16 ec_read_u16(u8 addr) 217 + { 218 + int hi, lo; 219 + lo = ec_read_u8(addr); 220 + hi = ec_read_u8(addr + 1); 221 + return (hi << 8) + lo; 222 + } 223 + 224 + static s16 ec_read_s16(u8 addr) 225 + { 226 + return (s16) ec_read_u16(addr); 227 + } 228 + 229 + static void ec_read_sequence(u8 addr, u8 *buf, int len) 230 + { 231 + int i; 232 + for (i = 0; i < len; i++) 233 + ec_read(addr + i, buf + i); 234 + } 235 + 236 + 237 + /* Backlight access */ 238 + static int set_backlight_level(int level) 239 + { 240 + if (level < 0 || level > BACKLIGHT_LEVEL_MAX) 104 241 return -EINVAL; 105 242 106 - ec_write(COMPAL_EC_COMMAND_LCD_LEVEL, level); 243 + ec_write(BACKLIGHT_LEVEL_ADDR, level); 107 244 245 + return 1; 246 + } 247 + 248 + static int get_backlight_level(void) 249 + { 250 + return (int) ec_read_u8(BACKLIGHT_LEVEL_ADDR); 251 + } 252 + 253 + static void set_backlight_state(bool on) 254 + { 255 + u8 data = on ? BACKLIGHT_STATE_ON_DATA : BACKLIGHT_STATE_OFF_DATA; 256 + ec_transaction(BACKLIGHT_STATE_ADDR, &data, 1, NULL, 0, 0); 257 + } 258 + 259 + 260 + /* Fan control access */ 261 + static void pwm_enable_control(void) 262 + { 263 + unsigned char writeData = PWM_ENABLE_DATA; 264 + ec_transaction(PWM_ENABLE_ADDR, &writeData, 1, NULL, 0, 0); 265 + } 266 + 267 + static void pwm_disable_control(void) 268 + { 269 + unsigned char writeData = PWM_DISABLE_DATA; 270 + ec_transaction(PWM_DISABLE_ADDR, &writeData, 1, NULL, 0, 0); 271 + } 272 + 273 + static void set_pwm(int pwm) 274 + { 275 + ec_transaction(PWM_ADDRESS, &pwm_lookup_table[pwm], 1, NULL, 0, 0); 276 + } 277 + 278 + static int get_fan_rpm(void) 279 + { 280 + u8 value, data = FAN_DATA; 281 + ec_transaction(FAN_ADDRESS, &data, 1, &value, 1, 0); 282 + return 100 * (int)value; 283 + } 284 + 285 + 286 + 287 + 288 + /* =================== */ 289 + /* Interface functions */ 290 + /* =================== */ 291 + 292 + /* Backlight interface */ 293 + static int bl_get_brightness(struct backlight_device *b) 294 + { 295 + return get_backlight_level(); 296 + } 297 + 298 + static int bl_update_status(struct backlight_device *b) 299 + { 300 + int ret = set_backlight_level(b->props.brightness); 301 + if (ret) 302 + return ret; 303 + 304 + set_backlight_state((b->props.power == FB_BLANK_UNBLANK) 305 + && !(b->props.state & BL_CORE_SUSPENDED) 306 + && !(b->props.state & BL_CORE_FBBLANK)); 108 307 return 0; 109 308 } 110 309 111 - static int get_lcd_level(void) 112 - { 113 - u8 result; 310 + static const struct backlight_ops compalbl_ops = { 311 + .get_brightness = bl_get_brightness, 312 + .update_status = bl_update_status, 313 + }; 114 314 115 - ec_read(COMPAL_EC_COMMAND_LCD_LEVEL, &result); 116 315 117 - return (int) result; 118 - } 119 - 316 + /* Wireless interface */ 120 317 static int compal_rfkill_set(void *data, bool blocked) 121 318 { 122 319 unsigned long radio = (unsigned long) data; 123 - u8 result, value; 124 - 125 - ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); 320 + u8 result = ec_read_u8(WIRELESS_ADDR); 321 + u8 value; 126 322 127 323 if (!blocked) 128 324 value = (u8) (result | radio); 129 325 else 130 326 value = (u8) (result & ~radio); 131 - ec_write(COMPAL_EC_COMMAND_WIRELESS, value); 327 + ec_write(WIRELESS_ADDR, value); 132 328 133 329 return 0; 134 330 } 135 331 136 332 static void compal_rfkill_poll(struct rfkill *rfkill, void *data) 137 333 { 138 - u8 result; 139 - bool hw_blocked; 140 - 141 - ec_read(COMPAL_EC_COMMAND_WIRELESS, &result); 142 - 143 - hw_blocked = !(result & KILLSWITCH_MASK); 334 + u8 result = ec_read_u8(WIRELESS_ADDR); 335 + bool hw_blocked = !(result & WIRELESS_KILLSWITCH); 144 336 rfkill_set_hw_state(rfkill, hw_blocked); 145 337 } 146 338 ··· 374 116 .set_block = compal_rfkill_set, 375 117 }; 376 118 377 - static int setup_rfkill(void) 119 + 120 + /* Wake_up interface */ 121 + #define SIMPLE_MASKED_STORE_SHOW(NAME, ADDR, MASK) \ 122 + static ssize_t NAME##_show(struct device *dev, \ 123 + struct device_attribute *attr, char *buf) \ 124 + { \ 125 + return sprintf(buf, "%d\n", ((ec_read_u8(ADDR) & MASK) != 0)); \ 126 + } \ 127 + static ssize_t NAME##_store(struct device *dev, \ 128 + struct device_attribute *attr, const char *buf, size_t count) \ 129 + { \ 130 + int state; \ 131 + u8 old_val = ec_read_u8(ADDR); \ 132 + if (sscanf(buf, "%d", &state) != 1 || (state < 0 || state > 1)) \ 133 + return -EINVAL; \ 134 + ec_write(ADDR, state ? (old_val | MASK) : (old_val & ~MASK)); \ 135 + return count; \ 136 + } 137 + 138 + SIMPLE_MASKED_STORE_SHOW(wake_up_pme, WAKE_UP_ADDR, WAKE_UP_PME) 139 + SIMPLE_MASKED_STORE_SHOW(wake_up_modem, WAKE_UP_ADDR, WAKE_UP_MODEM) 140 + SIMPLE_MASKED_STORE_SHOW(wake_up_lan, WAKE_UP_ADDR, WAKE_UP_LAN) 141 + SIMPLE_MASKED_STORE_SHOW(wake_up_wlan, WAKE_UP_ADDR, WAKE_UP_WLAN) 142 + SIMPLE_MASKED_STORE_SHOW(wake_up_key, WAKE_UP_ADDR, WAKE_UP_KEY) 143 + SIMPLE_MASKED_STORE_SHOW(wake_up_mouse, WAKE_UP_ADDR, WAKE_UP_MOUSE) 144 + 145 + 146 + /* General hwmon interface */ 147 + static ssize_t hwmon_name_show(struct device *dev, 148 + struct device_attribute *attr, char *buf) 378 149 { 379 - int ret; 150 + return sprintf(buf, "%s\n", DRIVER_NAME); 151 + } 380 152 381 - wifi_rfkill = rfkill_alloc("compal-wifi", &compal_device->dev, 382 - RFKILL_TYPE_WLAN, &compal_rfkill_ops, 383 - (void *) WLAN_MASK); 384 - if (!wifi_rfkill) 385 - return -ENOMEM; 386 153 387 - ret = rfkill_register(wifi_rfkill); 388 - if (ret) 389 - goto err_wifi; 154 + /* Fan control interface */ 155 + static ssize_t pwm_enable_show(struct device *dev, 156 + struct device_attribute *attr, char *buf) 157 + { 158 + struct compal_data *data = dev_get_drvdata(dev); 159 + return sprintf(buf, "%d\n", data->pwm_enable); 160 + } 390 161 391 - bt_rfkill = rfkill_alloc("compal-bluetooth", &compal_device->dev, 392 - RFKILL_TYPE_BLUETOOTH, &compal_rfkill_ops, 393 - (void *) BT_MASK); 394 - if (!bt_rfkill) { 395 - ret = -ENOMEM; 396 - goto err_allocate_bt; 162 + static ssize_t pwm_enable_store(struct device *dev, 163 + struct device_attribute *attr, const char *buf, size_t count) 164 + { 165 + struct compal_data *data = dev_get_drvdata(dev); 166 + long val; 167 + int err; 168 + err = strict_strtol(buf, 10, &val); 169 + if (err) 170 + return err; 171 + if (val < 0) 172 + return -EINVAL; 173 + 174 + data->pwm_enable = val; 175 + 176 + switch (val) { 177 + case 0: /* Full speed */ 178 + pwm_enable_control(); 179 + set_pwm(255); 180 + break; 181 + case 1: /* As set by pwm1 */ 182 + pwm_enable_control(); 183 + set_pwm(data->curr_pwm); 184 + break; 185 + default: /* Control by motherboard */ 186 + pwm_disable_control(); 187 + break; 397 188 } 398 - ret = rfkill_register(bt_rfkill); 399 - if (ret) 400 - goto err_register_bt; 401 189 190 + return count; 191 + } 192 + 193 + static ssize_t pwm_show(struct device *dev, struct device_attribute *attr, 194 + char *buf) 195 + { 196 + struct compal_data *data = dev_get_drvdata(dev); 197 + return sprintf(buf, "%hhu\n", data->curr_pwm); 198 + } 199 + 200 + static ssize_t pwm_store(struct device *dev, struct device_attribute *attr, 201 + const char *buf, size_t count) 202 + { 203 + struct compal_data *data = dev_get_drvdata(dev); 204 + long val; 205 + int err; 206 + err = strict_strtol(buf, 10, &val); 207 + if (err) 208 + return err; 209 + if (val < 0 || val > 255) 210 + return -EINVAL; 211 + 212 + data->curr_pwm = val; 213 + 214 + if (data->pwm_enable != 1) 215 + return count; 216 + set_pwm(val); 217 + 218 + return count; 219 + } 220 + 221 + static ssize_t fan_show(struct device *dev, struct device_attribute *attr, 222 + char *buf) 223 + { 224 + return sprintf(buf, "%d\n", get_fan_rpm()); 225 + } 226 + 227 + 228 + /* Temperature interface */ 229 + #define TEMPERATURE_SHOW_TEMP_AND_LABEL(POSTFIX, ADDRESS, LABEL) \ 230 + static ssize_t temp_##POSTFIX(struct device *dev, \ 231 + struct device_attribute *attr, char *buf) \ 232 + { \ 233 + return sprintf(buf, "%d\n", 1000 * (int)ec_read_s8(ADDRESS)); \ 234 + } \ 235 + static ssize_t label_##POSTFIX(struct device *dev, \ 236 + struct device_attribute *attr, char *buf) \ 237 + { \ 238 + return sprintf(buf, "%s\n", LABEL); \ 239 + } 240 + 241 + /* Labels as in service guide */ 242 + TEMPERATURE_SHOW_TEMP_AND_LABEL(cpu, TEMP_CPU, "CPU_TEMP"); 243 + TEMPERATURE_SHOW_TEMP_AND_LABEL(cpu_local, TEMP_CPU_LOCAL, "CPU_TEMP_LOCAL"); 244 + TEMPERATURE_SHOW_TEMP_AND_LABEL(cpu_DTS, TEMP_CPU_DTS, "CPU_DTS"); 245 + TEMPERATURE_SHOW_TEMP_AND_LABEL(northbridge,TEMP_NORTHBRIDGE,"NorthBridge"); 246 + TEMPERATURE_SHOW_TEMP_AND_LABEL(vga, TEMP_VGA, "VGA_TEMP"); 247 + TEMPERATURE_SHOW_TEMP_AND_LABEL(SKIN, TEMP_SKIN, "SKIN_TEMP90"); 248 + 249 + 250 + /* Power supply interface */ 251 + static int bat_status(void) 252 + { 253 + u8 status0 = ec_read_u8(BAT_STATUS0); 254 + u8 status1 = ec_read_u8(BAT_STATUS1); 255 + 256 + if (status0 & BAT_S0_CHARGING) 257 + return POWER_SUPPLY_STATUS_CHARGING; 258 + if (status0 & BAT_S0_DISCHARGE) 259 + return POWER_SUPPLY_STATUS_DISCHARGING; 260 + if (status1 & BAT_S1_FULL) 261 + return POWER_SUPPLY_STATUS_FULL; 262 + return POWER_SUPPLY_STATUS_NOT_CHARGING; 263 + } 264 + 265 + static int bat_health(void) 266 + { 267 + u8 status = ec_read_u8(BAT_STOP_CHARGE1); 268 + 269 + if (status & BAT_STOP_CHRG1_OVERTEMPERATURE) 270 + return POWER_SUPPLY_HEALTH_OVERHEAT; 271 + if (status & BAT_STOP_CHRG1_OVERVOLTAGE) 272 + return POWER_SUPPLY_HEALTH_OVERVOLTAGE; 273 + if (status & BAT_STOP_CHRG1_BAD_CELL) 274 + return POWER_SUPPLY_HEALTH_DEAD; 275 + if (status & BAT_STOP_CHRG1_COMM_FAIL) 276 + return POWER_SUPPLY_HEALTH_UNKNOWN; 277 + return POWER_SUPPLY_HEALTH_GOOD; 278 + } 279 + 280 + static int bat_is_present(void) 281 + { 282 + u8 status = ec_read_u8(BAT_STATUS2); 283 + return ((status & BAT_S1_EXISTS) != 0); 284 + } 285 + 286 + static int bat_technology(void) 287 + { 288 + u8 status = ec_read_u8(BAT_STATUS1); 289 + 290 + if (status & BAT_S1_LiION_OR_NiMH) 291 + return POWER_SUPPLY_TECHNOLOGY_LION; 292 + return POWER_SUPPLY_TECHNOLOGY_NiMH; 293 + } 294 + 295 + static int bat_capacity_level(void) 296 + { 297 + u8 status0 = ec_read_u8(BAT_STATUS0); 298 + u8 status1 = ec_read_u8(BAT_STATUS1); 299 + u8 status2 = ec_read_u8(BAT_STATUS2); 300 + 301 + if (status0 & BAT_S0_DISCHRG_CRITICAL 302 + || status1 & BAT_S1_EMPTY 303 + || status2 & BAT_S2_LOW_LOW) 304 + return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; 305 + if (status0 & BAT_S0_LOW) 306 + return POWER_SUPPLY_CAPACITY_LEVEL_LOW; 307 + if (status1 & BAT_S1_FULL) 308 + return POWER_SUPPLY_CAPACITY_LEVEL_FULL; 309 + return POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 310 + } 311 + 312 + static int bat_get_property(struct power_supply *psy, 313 + enum power_supply_property psp, 314 + union power_supply_propval *val) 315 + { 316 + struct compal_data *data; 317 + data = container_of(psy, struct compal_data, psy); 318 + 319 + switch (psp) { 320 + case POWER_SUPPLY_PROP_STATUS: 321 + val->intval = bat_status(); 322 + break; 323 + case POWER_SUPPLY_PROP_HEALTH: 324 + val->intval = bat_health(); 325 + break; 326 + case POWER_SUPPLY_PROP_PRESENT: 327 + val->intval = bat_is_present(); 328 + break; 329 + case POWER_SUPPLY_PROP_TECHNOLOGY: 330 + val->intval = bat_technology(); 331 + break; 332 + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: /* THE design voltage... */ 333 + val->intval = ec_read_u16(BAT_VOLTAGE_DESIGN) * 1000; 334 + break; 335 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 336 + val->intval = ec_read_u16(BAT_VOLTAGE_NOW) * 1000; 337 + break; 338 + case POWER_SUPPLY_PROP_CURRENT_NOW: 339 + val->intval = ec_read_s16(BAT_CURRENT_NOW) * 1000; 340 + break; 341 + case POWER_SUPPLY_PROP_CURRENT_AVG: 342 + val->intval = ec_read_s16(BAT_CURRENT_AVG) * 1000; 343 + break; 344 + case POWER_SUPPLY_PROP_POWER_NOW: 345 + val->intval = ec_read_u8(BAT_POWER) * 1000000; 346 + break; 347 + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 348 + val->intval = ec_read_u16(BAT_CHARGE_DESIGN) * 1000; 349 + break; 350 + case POWER_SUPPLY_PROP_CHARGE_NOW: 351 + val->intval = ec_read_u16(BAT_CHARGE_NOW) * 1000; 352 + break; 353 + case POWER_SUPPLY_PROP_CAPACITY: 354 + val->intval = ec_read_u8(BAT_CAPACITY); 355 + break; 356 + case POWER_SUPPLY_PROP_CAPACITY_LEVEL: 357 + val->intval = bat_capacity_level(); 358 + break; 359 + /* It smees that BAT_TEMP_AVG is a (2's complement?) value showing 360 + * the number of degrees, whereas BAT_TEMP is somewhat more 361 + * complicated. It looks like this is a negative nember with a 362 + * 100/256 divider and an offset of 222. Both were determined 363 + * experimentally by comparing BAT_TEMP and BAT_TEMP_AVG. */ 364 + case POWER_SUPPLY_PROP_TEMP: 365 + val->intval = ((222 - (int)ec_read_u8(BAT_TEMP)) * 1000) >> 8; 366 + break; 367 + case POWER_SUPPLY_PROP_TEMP_AMBIENT: /* Ambient, Avg, ... same thing */ 368 + val->intval = ec_read_s8(BAT_TEMP_AVG) * 10; 369 + break; 370 + /* Neither the model name nor manufacturer name work for me. */ 371 + case POWER_SUPPLY_PROP_MODEL_NAME: 372 + val->strval = data->bat_model_name; 373 + break; 374 + case POWER_SUPPLY_PROP_MANUFACTURER: 375 + val->strval = data->bat_manufacturer_name; 376 + break; 377 + case POWER_SUPPLY_PROP_SERIAL_NUMBER: 378 + val->strval = data->bat_serial_number; 379 + break; 380 + default: 381 + break; 382 + } 402 383 return 0; 403 - 404 - err_register_bt: 405 - rfkill_destroy(bt_rfkill); 406 - 407 - err_allocate_bt: 408 - rfkill_unregister(wifi_rfkill); 409 - 410 - err_wifi: 411 - rfkill_destroy(wifi_rfkill); 412 - 413 - return ret; 414 - } 415 - 416 - /* Backlight device stuff */ 417 - 418 - static int bl_get_brightness(struct backlight_device *b) 419 - { 420 - return get_lcd_level(); 421 384 } 422 385 423 386 424 - static int bl_update_status(struct backlight_device *b) 425 - { 426 - return set_lcd_level(b->props.brightness); 427 - } 428 387 429 - static struct backlight_ops compalbl_ops = { 430 - .get_brightness = bl_get_brightness, 431 - .update_status = bl_update_status, 388 + 389 + 390 + /* ============== */ 391 + /* Driver Globals */ 392 + /* ============== */ 393 + static DEVICE_ATTR(wake_up_pme, 394 + 0644, wake_up_pme_show, wake_up_pme_store); 395 + static DEVICE_ATTR(wake_up_modem, 396 + 0644, wake_up_modem_show, wake_up_modem_store); 397 + static DEVICE_ATTR(wake_up_lan, 398 + 0644, wake_up_lan_show, wake_up_lan_store); 399 + static DEVICE_ATTR(wake_up_wlan, 400 + 0644, wake_up_wlan_show, wake_up_wlan_store); 401 + static DEVICE_ATTR(wake_up_key, 402 + 0644, wake_up_key_show, wake_up_key_store); 403 + static DEVICE_ATTR(wake_up_mouse, 404 + 0644, wake_up_mouse_show, wake_up_mouse_store); 405 + 406 + static SENSOR_DEVICE_ATTR(name, S_IRUGO, hwmon_name_show, NULL, 1); 407 + static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, fan_show, NULL, 1); 408 + static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, temp_cpu, NULL, 1); 409 + static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, temp_cpu_local, NULL, 1); 410 + static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, temp_cpu_DTS, NULL, 1); 411 + static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, temp_northbridge, NULL, 1); 412 + static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, temp_vga, NULL, 1); 413 + static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, temp_SKIN, NULL, 1); 414 + static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, label_cpu, NULL, 1); 415 + static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, label_cpu_local, NULL, 1); 416 + static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, label_cpu_DTS, NULL, 1); 417 + static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, label_northbridge, NULL, 1); 418 + static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, label_vga, NULL, 1); 419 + static SENSOR_DEVICE_ATTR(temp6_label, S_IRUGO, label_SKIN, NULL, 1); 420 + static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, pwm_show, pwm_store, 1); 421 + static SENSOR_DEVICE_ATTR(pwm1_enable, 422 + S_IRUGO | S_IWUSR, pwm_enable_show, pwm_enable_store, 0); 423 + 424 + static struct attribute *compal_attributes[] = { 425 + &dev_attr_wake_up_pme.attr, 426 + &dev_attr_wake_up_modem.attr, 427 + &dev_attr_wake_up_lan.attr, 428 + &dev_attr_wake_up_wlan.attr, 429 + &dev_attr_wake_up_key.attr, 430 + &dev_attr_wake_up_mouse.attr, 431 + /* Maybe put the sensor-stuff in a separate hwmon-driver? That way, 432 + * the hwmon sysfs won't be cluttered with the above files. */ 433 + &sensor_dev_attr_name.dev_attr.attr, 434 + &sensor_dev_attr_pwm1_enable.dev_attr.attr, 435 + &sensor_dev_attr_pwm1.dev_attr.attr, 436 + &sensor_dev_attr_fan1_input.dev_attr.attr, 437 + &sensor_dev_attr_temp1_input.dev_attr.attr, 438 + &sensor_dev_attr_temp2_input.dev_attr.attr, 439 + &sensor_dev_attr_temp3_input.dev_attr.attr, 440 + &sensor_dev_attr_temp4_input.dev_attr.attr, 441 + &sensor_dev_attr_temp5_input.dev_attr.attr, 442 + &sensor_dev_attr_temp6_input.dev_attr.attr, 443 + &sensor_dev_attr_temp1_label.dev_attr.attr, 444 + &sensor_dev_attr_temp2_label.dev_attr.attr, 445 + &sensor_dev_attr_temp3_label.dev_attr.attr, 446 + &sensor_dev_attr_temp4_label.dev_attr.attr, 447 + &sensor_dev_attr_temp5_label.dev_attr.attr, 448 + &sensor_dev_attr_temp6_label.dev_attr.attr, 449 + NULL 450 + }; 451 + 452 + static struct attribute_group compal_attribute_group = { 453 + .attrs = compal_attributes 454 + }; 455 + 456 + static int __devinit compal_probe(struct platform_device *); 457 + static int __devexit compal_remove(struct platform_device *); 458 + static struct platform_driver compal_driver = { 459 + .driver = { 460 + .name = DRIVER_NAME, 461 + .owner = THIS_MODULE, 462 + }, 463 + .probe = compal_probe, 464 + .remove = __devexit_p(compal_remove) 465 + }; 466 + 467 + static enum power_supply_property compal_bat_properties[] = { 468 + POWER_SUPPLY_PROP_STATUS, 469 + POWER_SUPPLY_PROP_HEALTH, 470 + POWER_SUPPLY_PROP_PRESENT, 471 + POWER_SUPPLY_PROP_TECHNOLOGY, 472 + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 473 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 474 + POWER_SUPPLY_PROP_CURRENT_NOW, 475 + POWER_SUPPLY_PROP_CURRENT_AVG, 476 + POWER_SUPPLY_PROP_POWER_NOW, 477 + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 478 + POWER_SUPPLY_PROP_CHARGE_NOW, 479 + POWER_SUPPLY_PROP_CAPACITY, 480 + POWER_SUPPLY_PROP_CAPACITY_LEVEL, 481 + POWER_SUPPLY_PROP_TEMP, 482 + POWER_SUPPLY_PROP_TEMP_AMBIENT, 483 + POWER_SUPPLY_PROP_MODEL_NAME, 484 + POWER_SUPPLY_PROP_MANUFACTURER, 485 + POWER_SUPPLY_PROP_SERIAL_NUMBER, 432 486 }; 433 487 434 488 static struct backlight_device *compalbl_device; 435 489 490 + static struct platform_device *compal_device; 436 491 437 - static struct platform_driver compal_driver = { 438 - .driver = { 439 - .name = "compal-laptop", 440 - .owner = THIS_MODULE, 441 - } 442 - }; 492 + static struct rfkill *wifi_rfkill; 493 + static struct rfkill *bt_rfkill; 443 494 444 - /* Initialization */ 495 + 496 + 497 + 498 + 499 + /* =================================== */ 500 + /* Initialization & clean-up functions */ 501 + /* =================================== */ 445 502 446 503 static int dmi_check_cb(const struct dmi_system_id *id) 447 504 { 448 - printk(KERN_INFO "compal-laptop: Identified laptop model '%s'.\n", 505 + printk(KERN_INFO DRIVER_NAME": Identified laptop model '%s'\n", 449 506 id->ident); 507 + extra_features = false; 508 + return 0; 509 + } 450 510 511 + static int dmi_check_cb_extra(const struct dmi_system_id *id) 512 + { 513 + printk(KERN_INFO DRIVER_NAME": Identified laptop model '%s', " 514 + "enabling extra features\n", 515 + id->ident); 516 + extra_features = true; 451 517 return 0; 452 518 } 453 519 ··· 856 274 }, 857 275 .callback = dmi_check_cb 858 276 }, 859 - 277 + { 278 + .ident = "JHL90", 279 + .matches = { 280 + DMI_MATCH(DMI_BOARD_NAME, "JHL90"), 281 + DMI_MATCH(DMI_BOARD_VERSION, "REFERENCE"), 282 + }, 283 + .callback = dmi_check_cb_extra 284 + }, 860 285 { } 861 286 }; 287 + 288 + static void initialize_power_supply_data(struct compal_data *data) 289 + { 290 + data->psy.name = DRIVER_NAME; 291 + data->psy.type = POWER_SUPPLY_TYPE_BATTERY; 292 + data->psy.properties = compal_bat_properties; 293 + data->psy.num_properties = ARRAY_SIZE(compal_bat_properties); 294 + data->psy.get_property = bat_get_property; 295 + 296 + ec_read_sequence(BAT_MANUFACTURER_NAME_ADDR, 297 + data->bat_manufacturer_name, 298 + BAT_MANUFACTURER_NAME_LEN); 299 + data->bat_manufacturer_name[BAT_MANUFACTURER_NAME_LEN] = 0; 300 + 301 + ec_read_sequence(BAT_MODEL_NAME_ADDR, 302 + data->bat_model_name, 303 + BAT_MODEL_NAME_LEN); 304 + data->bat_model_name[BAT_MODEL_NAME_LEN] = 0; 305 + 306 + scnprintf(data->bat_serial_number, BAT_SERIAL_NUMBER_LEN + 1, "%d", 307 + ec_read_u16(BAT_SERIAL_NUMBER_ADDR)); 308 + } 309 + 310 + static void initialize_fan_control_data(struct compal_data *data) 311 + { 312 + data->pwm_enable = 2; /* Keep motherboard in control for now */ 313 + data->curr_pwm = 255; /* Try not to cause a CPU_on_fire exception 314 + if we take over... */ 315 + } 316 + 317 + static int setup_rfkill(void) 318 + { 319 + int ret; 320 + 321 + wifi_rfkill = rfkill_alloc("compal-wifi", &compal_device->dev, 322 + RFKILL_TYPE_WLAN, &compal_rfkill_ops, 323 + (void *) WIRELESS_WLAN); 324 + if (!wifi_rfkill) 325 + return -ENOMEM; 326 + 327 + ret = rfkill_register(wifi_rfkill); 328 + if (ret) 329 + goto err_wifi; 330 + 331 + bt_rfkill = rfkill_alloc("compal-bluetooth", &compal_device->dev, 332 + RFKILL_TYPE_BLUETOOTH, &compal_rfkill_ops, 333 + (void *) WIRELESS_BT); 334 + if (!bt_rfkill) { 335 + ret = -ENOMEM; 336 + goto err_allocate_bt; 337 + } 338 + ret = rfkill_register(bt_rfkill); 339 + if (ret) 340 + goto err_register_bt; 341 + 342 + return 0; 343 + 344 + err_register_bt: 345 + rfkill_destroy(bt_rfkill); 346 + 347 + err_allocate_bt: 348 + rfkill_unregister(wifi_rfkill); 349 + 350 + err_wifi: 351 + rfkill_destroy(wifi_rfkill); 352 + 353 + return ret; 354 + } 862 355 863 356 static int __init compal_init(void) 864 357 { 865 358 int ret; 866 359 867 - if (acpi_disabled) 360 + if (acpi_disabled) { 361 + printk(KERN_ERR DRIVER_NAME": ACPI needs to be enabled for " 362 + "this driver to work!\n"); 868 363 return -ENODEV; 364 + } 869 365 870 - if (!force && !dmi_check_system(compal_dmi_table)) 366 + if (!force && !dmi_check_system(compal_dmi_table)) { 367 + printk(KERN_ERR DRIVER_NAME": Motherboard not recognized (You " 368 + "could try the module's force-parameter)"); 871 369 return -ENODEV; 872 - 873 - /* Register backlight stuff */ 370 + } 874 371 875 372 if (!acpi_video_backlight_support()) { 876 373 struct backlight_properties props; 877 374 memset(&props, 0, sizeof(struct backlight_properties)); 878 - props.max_brightness = COMPAL_LCD_LEVEL_MAX - 1; 879 - compalbl_device = backlight_device_register("compal-laptop", 375 + props.max_brightness = BACKLIGHT_LEVEL_MAX; 376 + compalbl_device = backlight_device_register(DRIVER_NAME, 880 377 NULL, NULL, 881 378 &compalbl_ops, 882 379 &props); ··· 965 304 966 305 ret = platform_driver_register(&compal_driver); 967 306 if (ret) 968 - goto fail_backlight; 307 + goto err_backlight; 969 308 970 - /* Register platform stuff */ 971 - 972 - compal_device = platform_device_alloc("compal-laptop", -1); 309 + compal_device = platform_device_alloc(DRIVER_NAME, -1); 973 310 if (!compal_device) { 974 311 ret = -ENOMEM; 975 - goto fail_platform_driver; 312 + goto err_platform_driver; 976 313 } 977 314 978 - ret = platform_device_add(compal_device); 315 + ret = platform_device_add(compal_device); /* This calls compal_probe */ 979 316 if (ret) 980 - goto fail_platform_device; 317 + goto err_platform_device; 981 318 982 319 ret = setup_rfkill(); 983 320 if (ret) 984 - goto fail_rfkill; 321 + goto err_rfkill; 985 322 986 - printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION 987 - " successfully loaded.\n"); 988 - 323 + printk(KERN_INFO DRIVER_NAME": Driver "DRIVER_VERSION 324 + " successfully loaded\n"); 989 325 return 0; 990 326 991 - fail_rfkill: 327 + err_rfkill: 992 328 platform_device_del(compal_device); 993 329 994 - fail_platform_device: 995 - 330 + err_platform_device: 996 331 platform_device_put(compal_device); 997 332 998 - fail_platform_driver: 999 - 333 + err_platform_driver: 1000 334 platform_driver_unregister(&compal_driver); 1001 335 1002 - fail_backlight: 1003 - 336 + err_backlight: 1004 337 backlight_device_unregister(compalbl_device); 1005 338 1006 339 return ret; 1007 340 } 1008 341 342 + static int __devinit compal_probe(struct platform_device *pdev) 343 + { 344 + int err; 345 + struct compal_data *data; 346 + 347 + if (!extra_features) 348 + return 0; 349 + 350 + /* Fan control */ 351 + data = kzalloc(sizeof(struct compal_data), GFP_KERNEL); 352 + if (!data) 353 + return -ENOMEM; 354 + 355 + initialize_fan_control_data(data); 356 + 357 + err = sysfs_create_group(&pdev->dev.kobj, &compal_attribute_group); 358 + if (err) 359 + return err; 360 + 361 + data->hwmon_dev = hwmon_device_register(&pdev->dev); 362 + if (IS_ERR(data->hwmon_dev)) { 363 + err = PTR_ERR(data->hwmon_dev); 364 + sysfs_remove_group(&pdev->dev.kobj, 365 + &compal_attribute_group); 366 + kfree(data); 367 + return err; 368 + } 369 + 370 + /* Power supply */ 371 + initialize_power_supply_data(data); 372 + power_supply_register(&compal_device->dev, &data->psy); 373 + 374 + platform_set_drvdata(pdev, data); 375 + 376 + return 0; 377 + } 378 + 1009 379 static void __exit compal_cleanup(void) 1010 380 { 1011 - 1012 381 platform_device_unregister(compal_device); 1013 382 platform_driver_unregister(&compal_driver); 1014 383 backlight_device_unregister(compalbl_device); 1015 384 rfkill_unregister(wifi_rfkill); 1016 - rfkill_destroy(wifi_rfkill); 1017 385 rfkill_unregister(bt_rfkill); 386 + rfkill_destroy(wifi_rfkill); 1018 387 rfkill_destroy(bt_rfkill); 1019 388 1020 - printk(KERN_INFO "compal-laptop: driver unloaded.\n"); 389 + printk(KERN_INFO DRIVER_NAME": Driver unloaded\n"); 1021 390 } 391 + 392 + static int __devexit compal_remove(struct platform_device *pdev) 393 + { 394 + struct compal_data *data; 395 + 396 + if (!extra_features) 397 + return 0; 398 + 399 + printk(KERN_INFO DRIVER_NAME": Unloading: resetting fan control " 400 + "to motherboard\n"); 401 + pwm_disable_control(); 402 + 403 + data = platform_get_drvdata(pdev); 404 + hwmon_device_unregister(data->hwmon_dev); 405 + power_supply_unregister(&data->psy); 406 + 407 + platform_set_drvdata(pdev, NULL); 408 + kfree(data); 409 + 410 + sysfs_remove_group(&pdev->dev.kobj, &compal_attribute_group); 411 + 412 + return 0; 413 + } 414 + 1022 415 1023 416 module_init(compal_init); 1024 417 module_exit(compal_cleanup); 1025 418 1026 419 MODULE_AUTHOR("Cezary Jackiewicz"); 420 + MODULE_AUTHOR("Roald Frederickx (roald.frederickx@gmail.com)"); 1027 421 MODULE_DESCRIPTION("Compal Laptop Support"); 1028 - MODULE_VERSION(COMPAL_DRIVER_VERSION); 422 + MODULE_VERSION(DRIVER_VERSION); 1029 423 MODULE_LICENSE("GPL"); 1030 424 1031 425 MODULE_ALIAS("dmi:*:rnIFL90:rvrIFT00:*"); ··· 1088 372 MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*"); 1089 373 MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*"); 1090 374 MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*"); 375 + MODULE_ALIAS("dmi:*:rnJHL90:rvrREFERENCE:*"); 1091 376 MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron910:*"); 1092 377 MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1010:*"); 1093 378 MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1011:*");
+8 -1
drivers/platform/x86/dell-laptop.c
··· 83 83 }, 84 84 }, 85 85 { 86 + .matches = { 87 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 88 + DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /*Laptop*/ 89 + }, 90 + }, 91 + { 86 92 .ident = "Dell Computer Corporation", 87 93 .matches = { 88 94 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), ··· 473 467 .update_status = dell_send_intensity, 474 468 }; 475 469 476 - bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, 470 + static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, 477 471 struct serio *port) 478 472 { 479 473 static bool extended; ··· 627 621 MODULE_DESCRIPTION("Dell laptop driver"); 628 622 MODULE_LICENSE("GPL"); 629 623 MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*"); 624 + MODULE_ALIAS("dmi:*svnDellInc.:*:ct9:*"); 630 625 MODULE_ALIAS("dmi:*svnDellComputerCorporation.:*:ct8:*");
+9 -2
drivers/platform/x86/dell-wmi.c
··· 221 221 return; 222 222 } 223 223 224 - if (dell_new_hk_type) 224 + if (dell_new_hk_type || buffer_entry[1] == 0x0) 225 225 reported_key = (int)buffer_entry[2]; 226 226 else 227 227 reported_key = (int)buffer_entry[1] & 0xffff; ··· 339 339 acpi_video = acpi_video_backlight_support(); 340 340 341 341 err = dell_wmi_input_setup(); 342 - if (err) 342 + if (err) { 343 + if (dell_new_hk_type) 344 + kfree(dell_wmi_keymap); 343 345 return err; 346 + } 344 347 345 348 status = wmi_install_notify_handler(DELL_EVENT_GUID, 346 349 dell_wmi_notify, NULL); 347 350 if (ACPI_FAILURE(status)) { 348 351 input_unregister_device(dell_wmi_input_dev); 352 + if (dell_new_hk_type) 353 + kfree(dell_wmi_keymap); 349 354 printk(KERN_ERR 350 355 "dell-wmi: Unable to register notify handler - %d\n", 351 356 status); ··· 364 359 { 365 360 wmi_remove_notify_handler(DELL_EVENT_GUID); 366 361 input_unregister_device(dell_wmi_input_dev); 362 + if (dell_new_hk_type) 363 + kfree(dell_wmi_keymap); 367 364 } 368 365 369 366 module_init(dell_wmi_init);
+1 -1
drivers/platform/x86/eeepc-laptop.c
··· 53 53 54 54 static bool hotplug_disabled; 55 55 56 - module_param(hotplug_disabled, bool, 0644); 56 + module_param(hotplug_disabled, bool, 0444); 57 57 MODULE_PARM_DESC(hotplug_disabled, 58 58 "Disable hotplug for wireless device. " 59 59 "If your laptop need that, please report to "
+7 -9
drivers/platform/x86/fujitsu-laptop.c
··· 182 182 static void logolamp_set(struct led_classdev *cdev, 183 183 enum led_brightness brightness); 184 184 185 - struct led_classdev logolamp_led = { 185 + static struct led_classdev logolamp_led = { 186 186 .name = "fujitsu::logolamp", 187 187 .brightness_get = logolamp_get, 188 188 .brightness_set = logolamp_set ··· 192 192 static void kblamps_set(struct led_classdev *cdev, 193 193 enum led_brightness brightness); 194 194 195 - struct led_classdev kblamps_led = { 195 + static struct led_classdev kblamps_led = { 196 196 .name = "fujitsu::kblamps", 197 197 .brightness_get = kblamps_get, 198 198 .brightness_set = kblamps_set ··· 603 603 dmi_check_cb_common(id); 604 604 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ 605 605 fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */ 606 - return 0; 606 + return 1; 607 607 } 608 608 609 609 static int dmi_check_cb_s6420(const struct dmi_system_id *id) ··· 611 611 dmi_check_cb_common(id); 612 612 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ 613 613 fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */ 614 - return 0; 614 + return 1; 615 615 } 616 616 617 617 static int dmi_check_cb_p8010(const struct dmi_system_id *id) ··· 620 620 fujitsu->keycode1 = KEY_HELP; /* "Support" */ 621 621 fujitsu->keycode3 = KEY_SWITCHVIDEOMODE; /* "Presentation" */ 622 622 fujitsu->keycode4 = KEY_WWW; /* "Internet" */ 623 - return 0; 623 + return 1; 624 624 } 625 625 626 626 static struct dmi_system_id fujitsu_dmi_table[] = { ··· 725 725 726 726 err_unregister_input_dev: 727 727 input_unregister_device(input); 728 + input = NULL; 728 729 err_free_input_dev: 729 730 input_free_device(input); 730 731 err_stop: ··· 738 737 struct input_dev *input = fujitsu->input; 739 738 740 739 input_unregister_device(input); 741 - 742 - input_free_device(input); 743 740 744 741 fujitsu->acpi_handle = NULL; 745 742 ··· 929 930 930 931 err_unregister_input_dev: 931 932 input_unregister_device(input); 933 + input = NULL; 932 934 err_free_input_dev: 933 935 input_free_device(input); 934 936 err_free_fifo: ··· 952 952 #endif 953 953 954 954 input_unregister_device(input); 955 - 956 - input_free_device(input); 957 955 958 956 kfifo_free(&fujitsu_hotkey->fifo); 959 957
+219 -62
drivers/platform/x86/hp-wmi.c
··· 29 29 #include <linux/slab.h> 30 30 #include <linux/types.h> 31 31 #include <linux/input.h> 32 - #include <acpi/acpi_drivers.h> 33 32 #include <linux/platform_device.h> 34 33 #include <linux/acpi.h> 35 34 #include <linux/rfkill.h> ··· 51 52 #define HPWMI_WIRELESS_QUERY 0x5 52 53 #define HPWMI_HOTKEY_QUERY 0xc 53 54 55 + #define PREFIX "HP WMI: " 56 + #define UNIMP "Unimplemented " 57 + 54 58 enum hp_wmi_radio { 55 59 HPWMI_WIFI = 0, 56 60 HPWMI_BLUETOOTH = 1, 57 61 HPWMI_WWAN = 2, 62 + }; 63 + 64 + enum hp_wmi_event_ids { 65 + HPWMI_DOCK_EVENT = 1, 66 + HPWMI_PARK_HDD = 2, 67 + HPWMI_SMART_ADAPTER = 3, 68 + HPWMI_BEZEL_BUTTON = 4, 69 + HPWMI_WIRELESS = 5, 70 + HPWMI_CPU_BATTERY_THROTTLE = 6, 71 + HPWMI_LOCK_SWITCH = 7, 58 72 }; 59 73 60 74 static int __devinit hp_wmi_bios_setup(struct platform_device *device); ··· 79 67 u32 command; 80 68 u32 commandtype; 81 69 u32 datasize; 82 - u32 data; 70 + char *data; 83 71 }; 84 72 85 73 struct bios_return { 86 74 u32 sigpass; 87 75 u32 return_code; 88 - u32 value; 89 76 }; 90 77 91 78 struct key_entry { ··· 99 88 {KE_KEY, 0x02, KEY_BRIGHTNESSUP}, 100 89 {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN}, 101 90 {KE_KEY, 0x20e6, KEY_PROG1}, 91 + {KE_KEY, 0x20e8, KEY_MEDIA}, 102 92 {KE_KEY, 0x2142, KEY_MEDIA}, 103 93 {KE_KEY, 0x213b, KEY_INFO}, 104 94 {KE_KEY, 0x2169, KEY_DIRECTION}, ··· 129 117 .remove = hp_wmi_bios_remove, 130 118 }; 131 119 132 - static int hp_wmi_perform_query(int query, int write, int value) 120 + /* 121 + * hp_wmi_perform_query 122 + * 123 + * query: The commandtype -> What should be queried 124 + * write: The command -> 0 read, 1 write, 3 ODM specific 125 + * buffer: Buffer used as input and/or output 126 + * buffersize: Size of buffer 127 + * 128 + * returns zero on success 129 + * an HP WMI query specific error code (which is positive) 130 + * -EINVAL if the query was not successful at all 131 + * -EINVAL if the output buffer size exceeds buffersize 132 + * 133 + * Note: The buffersize must at least be the maximum of the input and output 134 + * size. E.g. Battery info query (0x7) is defined to have 1 byte input 135 + * and 128 byte output. The caller would do: 136 + * buffer = kzalloc(128, GFP_KERNEL); 137 + * ret = hp_wmi_perform_query(0x7, 0, buffer, 128) 138 + */ 139 + static int hp_wmi_perform_query(int query, int write, char *buffer, 140 + int buffersize) 133 141 { 134 142 struct bios_return bios_return; 135 143 acpi_status status; ··· 158 126 .signature = 0x55434553, 159 127 .command = write ? 0x2 : 0x1, 160 128 .commandtype = query, 161 - .datasize = write ? 0x4 : 0, 162 - .data = value, 129 + .datasize = buffersize, 130 + .data = buffer, 163 131 }; 164 132 struct acpi_buffer input = { sizeof(struct bios_args), &args }; 165 133 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; ··· 176 144 } 177 145 178 146 bios_return = *((struct bios_return *)obj->buffer.pointer); 147 + 148 + if (bios_return.return_code) { 149 + printk(KERN_WARNING PREFIX "Query %d returned %d\n", query, 150 + bios_return.return_code); 151 + kfree(obj); 152 + return bios_return.return_code; 153 + } 154 + if (obj->buffer.length - sizeof(bios_return) > buffersize) { 155 + kfree(obj); 156 + return -EINVAL; 157 + } 158 + 159 + memset(buffer, 0, buffersize); 160 + memcpy(buffer, 161 + ((char *)obj->buffer.pointer) + sizeof(struct bios_return), 162 + obj->buffer.length - sizeof(bios_return)); 179 163 kfree(obj); 180 - if (bios_return.return_code > 0) 181 - return bios_return.return_code * -1; 182 - else 183 - return bios_return.value; 164 + return 0; 184 165 } 185 166 186 167 static int hp_wmi_display_state(void) 187 168 { 188 - return hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, 0); 169 + int state; 170 + int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, (char *)&state, 171 + sizeof(state)); 172 + if (ret) 173 + return -EINVAL; 174 + return state; 189 175 } 190 176 191 177 static int hp_wmi_hddtemp_state(void) 192 178 { 193 - return hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, 0); 179 + int state; 180 + int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, (char *)&state, 181 + sizeof(state)); 182 + if (ret) 183 + return -EINVAL; 184 + return state; 194 185 } 195 186 196 187 static int hp_wmi_als_state(void) 197 188 { 198 - return hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, 0); 189 + int state; 190 + int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, (char *)&state, 191 + sizeof(state)); 192 + if (ret) 193 + return -EINVAL; 194 + return state; 199 195 } 200 196 201 197 static int hp_wmi_dock_state(void) 202 198 { 203 - int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, 0); 199 + int state; 200 + int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, (char *)&state, 201 + sizeof(state)); 204 202 205 - if (ret < 0) 206 - return ret; 203 + if (ret) 204 + return -EINVAL; 207 205 208 - return ret & 0x1; 206 + return state & 0x1; 209 207 } 210 208 211 209 static int hp_wmi_tablet_state(void) 212 210 { 213 - int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, 0); 214 - 215 - if (ret < 0) 211 + int state; 212 + int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, (char *)&state, 213 + sizeof(state)); 214 + if (ret) 216 215 return ret; 217 216 218 - return (ret & 0x4) ? 1 : 0; 217 + return (state & 0x4) ? 1 : 0; 219 218 } 220 219 221 220 static int hp_wmi_set_block(void *data, bool blocked) 222 221 { 223 222 enum hp_wmi_radio r = (enum hp_wmi_radio) data; 224 223 int query = BIT(r + 8) | ((!blocked) << r); 224 + int ret; 225 225 226 - return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); 226 + ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 227 + (char *)&query, sizeof(query)); 228 + if (ret) 229 + return -EINVAL; 230 + return 0; 227 231 } 228 232 229 233 static const struct rfkill_ops hp_wmi_rfkill_ops = { ··· 268 200 269 201 static bool hp_wmi_get_sw_state(enum hp_wmi_radio r) 270 202 { 271 - int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 272 - int mask = 0x200 << (r * 8); 203 + int wireless; 204 + int mask; 205 + hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 206 + (char *)&wireless, sizeof(wireless)); 207 + /* TBD: Pass error */ 208 + 209 + mask = 0x200 << (r * 8); 273 210 274 211 if (wireless & mask) 275 212 return false; ··· 284 211 285 212 static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) 286 213 { 287 - int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 288 - int mask = 0x800 << (r * 8); 214 + int wireless; 215 + int mask; 216 + hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 217 + (char *)&wireless, sizeof(wireless)); 218 + /* TBD: Pass error */ 219 + 220 + mask = 0x800 << (r * 8); 289 221 290 222 if (wireless & mask) 291 223 return false; ··· 347 269 const char *buf, size_t count) 348 270 { 349 271 u32 tmp = simple_strtoul(buf, NULL, 10); 350 - hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, tmp); 272 + int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, (char *)&tmp, 273 + sizeof(tmp)); 274 + if (ret) 275 + return -EINVAL; 276 + 351 277 return count; 352 278 } 353 279 ··· 420 338 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 421 339 static struct key_entry *key; 422 340 union acpi_object *obj; 423 - int eventcode; 341 + u32 event_id, event_data; 342 + int key_code, ret; 343 + u32 *location; 424 344 acpi_status status; 425 345 426 346 status = wmi_get_event_data(value, &response); 427 347 if (status != AE_OK) { 428 - printk(KERN_INFO "hp-wmi: bad event status 0x%x\n", status); 348 + printk(KERN_INFO PREFIX "bad event status 0x%x\n", status); 429 349 return; 430 350 } 431 351 432 352 obj = (union acpi_object *)response.pointer; 433 353 434 - if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) { 435 - printk(KERN_INFO "HP WMI: Unknown response received\n"); 354 + if (!obj) 355 + return; 356 + if (obj->type != ACPI_TYPE_BUFFER) { 357 + printk(KERN_INFO "hp-wmi: Unknown response received %d\n", 358 + obj->type); 436 359 kfree(obj); 437 360 return; 438 361 } 439 362 440 - eventcode = *((u8 *) obj->buffer.pointer); 363 + /* 364 + * Depending on ACPI version the concatenation of id and event data 365 + * inside _WED function will result in a 8 or 16 byte buffer. 366 + */ 367 + location = (u32 *)obj->buffer.pointer; 368 + if (obj->buffer.length == 8) { 369 + event_id = *location; 370 + event_data = *(location + 1); 371 + } else if (obj->buffer.length == 16) { 372 + event_id = *location; 373 + event_data = *(location + 2); 374 + } else { 375 + printk(KERN_INFO "hp-wmi: Unknown buffer length %d\n", 376 + obj->buffer.length); 377 + kfree(obj); 378 + return; 379 + } 441 380 kfree(obj); 442 - if (eventcode == 0x4) 443 - eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, 444 - 0); 445 - key = hp_wmi_get_entry_by_scancode(eventcode); 446 - if (key) { 447 - switch (key->type) { 448 - case KE_KEY: 449 - input_report_key(hp_wmi_input_dev, 450 - key->keycode, 1); 451 - input_sync(hp_wmi_input_dev); 452 - input_report_key(hp_wmi_input_dev, 453 - key->keycode, 0); 454 - input_sync(hp_wmi_input_dev); 455 - break; 456 - } 457 - } else if (eventcode == 0x1) { 381 + 382 + switch (event_id) { 383 + case HPWMI_DOCK_EVENT: 458 384 input_report_switch(hp_wmi_input_dev, SW_DOCK, 459 385 hp_wmi_dock_state()); 460 386 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, 461 387 hp_wmi_tablet_state()); 462 388 input_sync(hp_wmi_input_dev); 463 - } else if (eventcode == 0x5) { 389 + break; 390 + case HPWMI_PARK_HDD: 391 + break; 392 + case HPWMI_SMART_ADAPTER: 393 + break; 394 + case HPWMI_BEZEL_BUTTON: 395 + ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, 396 + (char *)&key_code, 397 + sizeof(key_code)); 398 + if (ret) 399 + break; 400 + key = hp_wmi_get_entry_by_scancode(key_code); 401 + if (key) { 402 + switch (key->type) { 403 + case KE_KEY: 404 + input_report_key(hp_wmi_input_dev, 405 + key->keycode, 1); 406 + input_sync(hp_wmi_input_dev); 407 + input_report_key(hp_wmi_input_dev, 408 + key->keycode, 0); 409 + input_sync(hp_wmi_input_dev); 410 + break; 411 + } 412 + } else 413 + printk(KERN_INFO PREFIX "Unknown key code - 0x%x\n", 414 + key_code); 415 + break; 416 + case HPWMI_WIRELESS: 464 417 if (wifi_rfkill) 465 418 rfkill_set_states(wifi_rfkill, 466 419 hp_wmi_get_sw_state(HPWMI_WIFI), ··· 508 391 rfkill_set_states(wwan_rfkill, 509 392 hp_wmi_get_sw_state(HPWMI_WWAN), 510 393 hp_wmi_get_hw_state(HPWMI_WWAN)); 511 - } else 512 - printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", 513 - eventcode); 394 + break; 395 + case HPWMI_CPU_BATTERY_THROTTLE: 396 + printk(KERN_INFO PREFIX UNIMP "CPU throttle because of 3 Cell" 397 + " battery event detected\n"); 398 + break; 399 + case HPWMI_LOCK_SWITCH: 400 + break; 401 + default: 402 + printk(KERN_INFO PREFIX "Unknown event_id - %d - 0x%x\n", 403 + event_id, event_data); 404 + break; 405 + } 514 406 } 515 407 516 408 static int __init hp_wmi_input_setup(void) ··· 528 402 int err; 529 403 530 404 hp_wmi_input_dev = input_allocate_device(); 405 + if (!hp_wmi_input_dev) 406 + return -ENOMEM; 531 407 532 408 hp_wmi_input_dev->name = "HP WMI hotkeys"; 533 409 hp_wmi_input_dev->phys = "wmi/input0"; ··· 578 450 static int __devinit hp_wmi_bios_setup(struct platform_device *device) 579 451 { 580 452 int err; 581 - int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 453 + int wireless; 454 + 455 + err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, (char *)&wireless, 456 + sizeof(wireless)); 457 + if (err) 458 + return err; 582 459 583 460 err = device_create_file(&device->dev, &dev_attr_display); 584 461 if (err) ··· 714 581 static int __init hp_wmi_init(void) 715 582 { 716 583 int err; 584 + int event_capable = wmi_has_guid(HPWMI_EVENT_GUID); 585 + int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID); 717 586 718 - if (wmi_has_guid(HPWMI_EVENT_GUID)) { 587 + if (event_capable) { 719 588 err = wmi_install_notify_handler(HPWMI_EVENT_GUID, 720 589 hp_wmi_notify, NULL); 721 - if (ACPI_SUCCESS(err)) 722 - hp_wmi_input_setup(); 590 + if (ACPI_FAILURE(err)) 591 + return -EINVAL; 592 + err = hp_wmi_input_setup(); 593 + if (err) { 594 + wmi_remove_notify_handler(HPWMI_EVENT_GUID); 595 + return err; 596 + } 723 597 } 724 598 725 - if (wmi_has_guid(HPWMI_BIOS_GUID)) { 599 + if (bios_capable) { 726 600 err = platform_driver_register(&hp_wmi_driver); 727 601 if (err) 728 - return 0; 602 + goto err_driver_reg; 729 603 hp_wmi_platform_dev = platform_device_alloc("hp-wmi", -1); 730 604 if (!hp_wmi_platform_dev) { 731 - platform_driver_unregister(&hp_wmi_driver); 732 - return 0; 605 + err = -ENOMEM; 606 + goto err_device_alloc; 733 607 } 734 - platform_device_add(hp_wmi_platform_dev); 608 + err = platform_device_add(hp_wmi_platform_dev); 609 + if (err) 610 + goto err_device_add; 735 611 } 736 612 613 + if (!bios_capable && !event_capable) 614 + return -ENODEV; 615 + 737 616 return 0; 617 + 618 + err_device_add: 619 + platform_device_put(hp_wmi_platform_dev); 620 + err_device_alloc: 621 + platform_driver_unregister(&hp_wmi_driver); 622 + err_driver_reg: 623 + if (wmi_has_guid(HPWMI_EVENT_GUID)) { 624 + input_unregister_device(hp_wmi_input_dev); 625 + wmi_remove_notify_handler(HPWMI_EVENT_GUID); 626 + } 627 + 628 + return err; 738 629 } 739 630 740 631 static void __exit hp_wmi_exit(void) ··· 768 611 input_unregister_device(hp_wmi_input_dev); 769 612 } 770 613 if (hp_wmi_platform_dev) { 771 - platform_device_del(hp_wmi_platform_dev); 614 + platform_device_unregister(hp_wmi_platform_dev); 772 615 platform_driver_unregister(&hp_wmi_driver); 773 616 } 774 617 }
+1660
drivers/platform/x86/intel_ips.c
··· 1 + /* 2 + * Copyright (c) 2009-2010 Intel Corporation 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 15 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 + * 17 + * The full GNU General Public License is included in this distribution in 18 + * the file called "COPYING". 19 + * 20 + * Authors: 21 + * Jesse Barnes <jbarnes@virtuousgeek.org> 22 + */ 23 + 24 + /* 25 + * Some Intel Ibex Peak based platforms support so-called "intelligent 26 + * power sharing", which allows the CPU and GPU to cooperate to maximize 27 + * performance within a given TDP (thermal design point). This driver 28 + * performs the coordination between the CPU and GPU, monitors thermal and 29 + * power statistics in the platform, and initializes power monitoring 30 + * hardware. It also provides a few tunables to control behavior. Its 31 + * primary purpose is to safely allow CPU and GPU turbo modes to be enabled 32 + * by tracking power and thermal budget; secondarily it can boost turbo 33 + * performance by allocating more power or thermal budget to the CPU or GPU 34 + * based on available headroom and activity. 35 + * 36 + * The basic algorithm is driven by a 5s moving average of tempurature. If 37 + * thermal headroom is available, the CPU and/or GPU power clamps may be 38 + * adjusted upwards. If we hit the thermal ceiling or a thermal trigger, 39 + * we scale back the clamp. Aside from trigger events (when we're critically 40 + * close or over our TDP) we don't adjust the clamps more than once every 41 + * five seconds. 42 + * 43 + * The thermal device (device 31, function 6) has a set of registers that 44 + * are updated by the ME firmware. The ME should also take the clamp values 45 + * written to those registers and write them to the CPU, but we currently 46 + * bypass that functionality and write the CPU MSR directly. 47 + * 48 + * UNSUPPORTED: 49 + * - dual MCP configs 50 + * 51 + * TODO: 52 + * - handle CPU hotplug 53 + * - provide turbo enable/disable api 54 + * - make sure we can write turbo enable/disable reg based on MISC_EN 55 + * 56 + * Related documents: 57 + * - CDI 403777, 403778 - Auburndale EDS vol 1 & 2 58 + * - CDI 401376 - Ibex Peak EDS 59 + * - ref 26037, 26641 - IPS BIOS spec 60 + * - ref 26489 - Nehalem BIOS writer's guide 61 + * - ref 26921 - Ibex Peak BIOS Specification 62 + */ 63 + 64 + #include <linux/debugfs.h> 65 + #include <linux/delay.h> 66 + #include <linux/interrupt.h> 67 + #include <linux/kernel.h> 68 + #include <linux/kthread.h> 69 + #include <linux/module.h> 70 + #include <linux/pci.h> 71 + #include <linux/sched.h> 72 + #include <linux/seq_file.h> 73 + #include <linux/string.h> 74 + #include <linux/tick.h> 75 + #include <linux/timer.h> 76 + #include <drm/i915_drm.h> 77 + #include <asm/msr.h> 78 + #include <asm/processor.h> 79 + 80 + #define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32 81 + 82 + /* 83 + * Package level MSRs for monitor/control 84 + */ 85 + #define PLATFORM_INFO 0xce 86 + #define PLATFORM_TDP (1<<29) 87 + #define PLATFORM_RATIO (1<<28) 88 + 89 + #define IA32_MISC_ENABLE 0x1a0 90 + #define IA32_MISC_TURBO_EN (1ULL<<38) 91 + 92 + #define TURBO_POWER_CURRENT_LIMIT 0x1ac 93 + #define TURBO_TDC_OVR_EN (1UL<<31) 94 + #define TURBO_TDC_MASK (0x000000007fff0000UL) 95 + #define TURBO_TDC_SHIFT (16) 96 + #define TURBO_TDP_OVR_EN (1UL<<15) 97 + #define TURBO_TDP_MASK (0x0000000000003fffUL) 98 + 99 + /* 100 + * Core/thread MSRs for monitoring 101 + */ 102 + #define IA32_PERF_CTL 0x199 103 + #define IA32_PERF_TURBO_DIS (1ULL<<32) 104 + 105 + /* 106 + * Thermal PCI device regs 107 + */ 108 + #define THM_CFG_TBAR 0x10 109 + #define THM_CFG_TBAR_HI 0x14 110 + 111 + #define THM_TSIU 0x00 112 + #define THM_TSE 0x01 113 + #define TSE_EN 0xb8 114 + #define THM_TSS 0x02 115 + #define THM_TSTR 0x03 116 + #define THM_TSTTP 0x04 117 + #define THM_TSCO 0x08 118 + #define THM_TSES 0x0c 119 + #define THM_TSGPEN 0x0d 120 + #define TSGPEN_HOT_LOHI (1<<1) 121 + #define TSGPEN_CRIT_LOHI (1<<2) 122 + #define THM_TSPC 0x0e 123 + #define THM_PPEC 0x10 124 + #define THM_CTA 0x12 125 + #define THM_PTA 0x14 126 + #define PTA_SLOPE_MASK (0xff00) 127 + #define PTA_SLOPE_SHIFT 8 128 + #define PTA_OFFSET_MASK (0x00ff) 129 + #define THM_MGTA 0x16 130 + #define MGTA_SLOPE_MASK (0xff00) 131 + #define MGTA_SLOPE_SHIFT 8 132 + #define MGTA_OFFSET_MASK (0x00ff) 133 + #define THM_TRC 0x1a 134 + #define TRC_CORE2_EN (1<<15) 135 + #define TRC_THM_EN (1<<12) 136 + #define TRC_C6_WAR (1<<8) 137 + #define TRC_CORE1_EN (1<<7) 138 + #define TRC_CORE_PWR (1<<6) 139 + #define TRC_PCH_EN (1<<5) 140 + #define TRC_MCH_EN (1<<4) 141 + #define TRC_DIMM4 (1<<3) 142 + #define TRC_DIMM3 (1<<2) 143 + #define TRC_DIMM2 (1<<1) 144 + #define TRC_DIMM1 (1<<0) 145 + #define THM_TES 0x20 146 + #define THM_TEN 0x21 147 + #define TEN_UPDATE_EN 1 148 + #define THM_PSC 0x24 149 + #define PSC_NTG (1<<0) /* No GFX turbo support */ 150 + #define PSC_NTPC (1<<1) /* No CPU turbo support */ 151 + #define PSC_PP_DEF (0<<2) /* Perf policy up to driver */ 152 + #define PSP_PP_PC (1<<2) /* BIOS prefers CPU perf */ 153 + #define PSP_PP_BAL (2<<2) /* BIOS wants balanced perf */ 154 + #define PSP_PP_GFX (3<<2) /* BIOS prefers GFX perf */ 155 + #define PSP_PBRT (1<<4) /* BIOS run time support */ 156 + #define THM_CTV1 0x30 157 + #define CTV_TEMP_ERROR (1<<15) 158 + #define CTV_TEMP_MASK 0x3f 159 + #define CTV_ 160 + #define THM_CTV2 0x32 161 + #define THM_CEC 0x34 /* undocumented power accumulator in joules */ 162 + #define THM_AE 0x3f 163 + #define THM_HTS 0x50 /* 32 bits */ 164 + #define HTS_PCPL_MASK (0x7fe00000) 165 + #define HTS_PCPL_SHIFT 21 166 + #define HTS_GPL_MASK (0x001ff000) 167 + #define HTS_GPL_SHIFT 12 168 + #define HTS_PP_MASK (0x00000c00) 169 + #define HTS_PP_SHIFT 10 170 + #define HTS_PP_DEF 0 171 + #define HTS_PP_PROC 1 172 + #define HTS_PP_BAL 2 173 + #define HTS_PP_GFX 3 174 + #define HTS_PCTD_DIS (1<<9) 175 + #define HTS_GTD_DIS (1<<8) 176 + #define HTS_PTL_MASK (0x000000fe) 177 + #define HTS_PTL_SHIFT 1 178 + #define HTS_NVV (1<<0) 179 + #define THM_HTSHI 0x54 /* 16 bits */ 180 + #define HTS2_PPL_MASK (0x03ff) 181 + #define HTS2_PRST_MASK (0x3c00) 182 + #define HTS2_PRST_SHIFT 10 183 + #define HTS2_PRST_UNLOADED 0 184 + #define HTS2_PRST_RUNNING 1 185 + #define HTS2_PRST_TDISOP 2 /* turbo disabled due to power */ 186 + #define HTS2_PRST_TDISHT 3 /* turbo disabled due to high temp */ 187 + #define HTS2_PRST_TDISUSR 4 /* user disabled turbo */ 188 + #define HTS2_PRST_TDISPLAT 5 /* platform disabled turbo */ 189 + #define HTS2_PRST_TDISPM 6 /* power management disabled turbo */ 190 + #define HTS2_PRST_TDISERR 7 /* some kind of error disabled turbo */ 191 + #define THM_PTL 0x56 192 + #define THM_MGTV 0x58 193 + #define TV_MASK 0x000000000000ff00 194 + #define TV_SHIFT 8 195 + #define THM_PTV 0x60 196 + #define PTV_MASK 0x00ff 197 + #define THM_MMGPC 0x64 198 + #define THM_MPPC 0x66 199 + #define THM_MPCPC 0x68 200 + #define THM_TSPIEN 0x82 201 + #define TSPIEN_AUX_LOHI (1<<0) 202 + #define TSPIEN_HOT_LOHI (1<<1) 203 + #define TSPIEN_CRIT_LOHI (1<<2) 204 + #define TSPIEN_AUX2_LOHI (1<<3) 205 + #define THM_TSLOCK 0x83 206 + #define THM_ATR 0x84 207 + #define THM_TOF 0x87 208 + #define THM_STS 0x98 209 + #define STS_PCPL_MASK (0x7fe00000) 210 + #define STS_PCPL_SHIFT 21 211 + #define STS_GPL_MASK (0x001ff000) 212 + #define STS_GPL_SHIFT 12 213 + #define STS_PP_MASK (0x00000c00) 214 + #define STS_PP_SHIFT 10 215 + #define STS_PP_DEF 0 216 + #define STS_PP_PROC 1 217 + #define STS_PP_BAL 2 218 + #define STS_PP_GFX 3 219 + #define STS_PCTD_DIS (1<<9) 220 + #define STS_GTD_DIS (1<<8) 221 + #define STS_PTL_MASK (0x000000fe) 222 + #define STS_PTL_SHIFT 1 223 + #define STS_NVV (1<<0) 224 + #define THM_SEC 0x9c 225 + #define SEC_ACK (1<<0) 226 + #define THM_TC3 0xa4 227 + #define THM_TC1 0xa8 228 + #define STS_PPL_MASK (0x0003ff00) 229 + #define STS_PPL_SHIFT 16 230 + #define THM_TC2 0xac 231 + #define THM_DTV 0xb0 232 + #define THM_ITV 0xd8 233 + #define ITV_ME_SEQNO_MASK 0x000f0000 /* ME should update every ~200ms */ 234 + #define ITV_ME_SEQNO_SHIFT (16) 235 + #define ITV_MCH_TEMP_MASK 0x0000ff00 236 + #define ITV_MCH_TEMP_SHIFT (8) 237 + #define ITV_PCH_TEMP_MASK 0x000000ff 238 + 239 + #define thm_readb(off) readb(ips->regmap + (off)) 240 + #define thm_readw(off) readw(ips->regmap + (off)) 241 + #define thm_readl(off) readl(ips->regmap + (off)) 242 + #define thm_readq(off) readq(ips->regmap + (off)) 243 + 244 + #define thm_writeb(off, val) writeb((val), ips->regmap + (off)) 245 + #define thm_writew(off, val) writew((val), ips->regmap + (off)) 246 + #define thm_writel(off, val) writel((val), ips->regmap + (off)) 247 + 248 + static const int IPS_ADJUST_PERIOD = 5000; /* ms */ 249 + 250 + /* For initial average collection */ 251 + static const int IPS_SAMPLE_PERIOD = 200; /* ms */ 252 + static const int IPS_SAMPLE_WINDOW = 5000; /* 5s moving window of samples */ 253 + #define IPS_SAMPLE_COUNT (IPS_SAMPLE_WINDOW / IPS_SAMPLE_PERIOD) 254 + 255 + /* Per-SKU limits */ 256 + struct ips_mcp_limits { 257 + int cpu_family; 258 + int cpu_model; /* includes extended model... */ 259 + int mcp_power_limit; /* mW units */ 260 + int core_power_limit; 261 + int mch_power_limit; 262 + int core_temp_limit; /* degrees C */ 263 + int mch_temp_limit; 264 + }; 265 + 266 + /* Max temps are -10 degrees C to avoid PROCHOT# */ 267 + 268 + struct ips_mcp_limits ips_sv_limits = { 269 + .mcp_power_limit = 35000, 270 + .core_power_limit = 29000, 271 + .mch_power_limit = 20000, 272 + .core_temp_limit = 95, 273 + .mch_temp_limit = 90 274 + }; 275 + 276 + struct ips_mcp_limits ips_lv_limits = { 277 + .mcp_power_limit = 25000, 278 + .core_power_limit = 21000, 279 + .mch_power_limit = 13000, 280 + .core_temp_limit = 95, 281 + .mch_temp_limit = 90 282 + }; 283 + 284 + struct ips_mcp_limits ips_ulv_limits = { 285 + .mcp_power_limit = 18000, 286 + .core_power_limit = 14000, 287 + .mch_power_limit = 11000, 288 + .core_temp_limit = 95, 289 + .mch_temp_limit = 90 290 + }; 291 + 292 + struct ips_driver { 293 + struct pci_dev *dev; 294 + void *regmap; 295 + struct task_struct *monitor; 296 + struct task_struct *adjust; 297 + struct dentry *debug_root; 298 + 299 + /* Average CPU core temps (all averages in .01 degrees C for precision) */ 300 + u16 ctv1_avg_temp; 301 + u16 ctv2_avg_temp; 302 + /* GMCH average */ 303 + u16 mch_avg_temp; 304 + /* Average for the CPU (both cores?) */ 305 + u16 mcp_avg_temp; 306 + /* Average power consumption (in mW) */ 307 + u32 cpu_avg_power; 308 + u32 mch_avg_power; 309 + 310 + /* Offset values */ 311 + u16 cta_val; 312 + u16 pta_val; 313 + u16 mgta_val; 314 + 315 + /* Maximums & prefs, protected by turbo status lock */ 316 + spinlock_t turbo_status_lock; 317 + u16 mcp_temp_limit; 318 + u16 mcp_power_limit; 319 + u16 core_power_limit; 320 + u16 mch_power_limit; 321 + bool cpu_turbo_enabled; 322 + bool __cpu_turbo_on; 323 + bool gpu_turbo_enabled; 324 + bool __gpu_turbo_on; 325 + bool gpu_preferred; 326 + bool poll_turbo_status; 327 + bool second_cpu; 328 + struct ips_mcp_limits *limits; 329 + 330 + /* Optional MCH interfaces for if i915 is in use */ 331 + unsigned long (*read_mch_val)(void); 332 + bool (*gpu_raise)(void); 333 + bool (*gpu_lower)(void); 334 + bool (*gpu_busy)(void); 335 + bool (*gpu_turbo_disable)(void); 336 + 337 + /* For restoration at unload */ 338 + u64 orig_turbo_limit; 339 + u64 orig_turbo_ratios; 340 + }; 341 + 342 + /** 343 + * ips_cpu_busy - is CPU busy? 344 + * @ips: IPS driver struct 345 + * 346 + * Check CPU for load to see whether we should increase its thermal budget. 347 + * 348 + * RETURNS: 349 + * True if the CPU could use more power, false otherwise. 350 + */ 351 + static bool ips_cpu_busy(struct ips_driver *ips) 352 + { 353 + if ((avenrun[0] >> FSHIFT) > 1) 354 + return true; 355 + 356 + return false; 357 + } 358 + 359 + /** 360 + * ips_cpu_raise - raise CPU power clamp 361 + * @ips: IPS driver struct 362 + * 363 + * Raise the CPU power clamp by %IPS_CPU_STEP, in accordance with TDP for 364 + * this platform. 365 + * 366 + * We do this by adjusting the TURBO_POWER_CURRENT_LIMIT MSR upwards (as 367 + * long as we haven't hit the TDP limit for the SKU). 368 + */ 369 + static void ips_cpu_raise(struct ips_driver *ips) 370 + { 371 + u64 turbo_override; 372 + u16 cur_tdp_limit, new_tdp_limit; 373 + 374 + if (!ips->cpu_turbo_enabled) 375 + return; 376 + 377 + rdmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override); 378 + 379 + cur_tdp_limit = turbo_override & TURBO_TDP_MASK; 380 + new_tdp_limit = cur_tdp_limit + 8; /* 1W increase */ 381 + 382 + /* Clamp to SKU TDP limit */ 383 + if (((new_tdp_limit * 10) / 8) > ips->core_power_limit) 384 + new_tdp_limit = cur_tdp_limit; 385 + 386 + thm_writew(THM_MPCPC, (new_tdp_limit * 10) / 8); 387 + 388 + turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN; 389 + wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override); 390 + 391 + turbo_override &= ~TURBO_TDP_MASK; 392 + turbo_override |= new_tdp_limit; 393 + 394 + wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override); 395 + } 396 + 397 + /** 398 + * ips_cpu_lower - lower CPU power clamp 399 + * @ips: IPS driver struct 400 + * 401 + * Lower CPU power clamp b %IPS_CPU_STEP if possible. 402 + * 403 + * We do this by adjusting the TURBO_POWER_CURRENT_LIMIT MSR down, going 404 + * as low as the platform limits will allow (though we could go lower there 405 + * wouldn't be much point). 406 + */ 407 + static void ips_cpu_lower(struct ips_driver *ips) 408 + { 409 + u64 turbo_override; 410 + u16 cur_limit, new_limit; 411 + 412 + rdmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override); 413 + 414 + cur_limit = turbo_override & TURBO_TDP_MASK; 415 + new_limit = cur_limit - 8; /* 1W decrease */ 416 + 417 + /* Clamp to SKU TDP limit */ 418 + if (((new_limit * 10) / 8) < (ips->orig_turbo_limit & TURBO_TDP_MASK)) 419 + new_limit = ips->orig_turbo_limit & TURBO_TDP_MASK; 420 + 421 + thm_writew(THM_MPCPC, (new_limit * 10) / 8); 422 + 423 + turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN; 424 + wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override); 425 + 426 + turbo_override &= ~TURBO_TDP_MASK; 427 + turbo_override |= new_limit; 428 + 429 + wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override); 430 + } 431 + 432 + /** 433 + * do_enable_cpu_turbo - internal turbo enable function 434 + * @data: unused 435 + * 436 + * Internal function for actually updating MSRs. When we enable/disable 437 + * turbo, we need to do it on each CPU; this function is the one called 438 + * by on_each_cpu() when needed. 439 + */ 440 + static void do_enable_cpu_turbo(void *data) 441 + { 442 + u64 perf_ctl; 443 + 444 + rdmsrl(IA32_PERF_CTL, perf_ctl); 445 + if (perf_ctl & IA32_PERF_TURBO_DIS) { 446 + perf_ctl &= ~IA32_PERF_TURBO_DIS; 447 + wrmsrl(IA32_PERF_CTL, perf_ctl); 448 + } 449 + } 450 + 451 + /** 452 + * ips_enable_cpu_turbo - enable turbo mode on all CPUs 453 + * @ips: IPS driver struct 454 + * 455 + * Enable turbo mode by clearing the disable bit in IA32_PERF_CTL on 456 + * all logical threads. 457 + */ 458 + static void ips_enable_cpu_turbo(struct ips_driver *ips) 459 + { 460 + /* Already on, no need to mess with MSRs */ 461 + if (ips->__cpu_turbo_on) 462 + return; 463 + 464 + on_each_cpu(do_enable_cpu_turbo, ips, 1); 465 + 466 + ips->__cpu_turbo_on = true; 467 + } 468 + 469 + /** 470 + * do_disable_cpu_turbo - internal turbo disable function 471 + * @data: unused 472 + * 473 + * Internal function for actually updating MSRs. When we enable/disable 474 + * turbo, we need to do it on each CPU; this function is the one called 475 + * by on_each_cpu() when needed. 476 + */ 477 + static void do_disable_cpu_turbo(void *data) 478 + { 479 + u64 perf_ctl; 480 + 481 + rdmsrl(IA32_PERF_CTL, perf_ctl); 482 + if (!(perf_ctl & IA32_PERF_TURBO_DIS)) { 483 + perf_ctl |= IA32_PERF_TURBO_DIS; 484 + wrmsrl(IA32_PERF_CTL, perf_ctl); 485 + } 486 + } 487 + 488 + /** 489 + * ips_disable_cpu_turbo - disable turbo mode on all CPUs 490 + * @ips: IPS driver struct 491 + * 492 + * Disable turbo mode by setting the disable bit in IA32_PERF_CTL on 493 + * all logical threads. 494 + */ 495 + static void ips_disable_cpu_turbo(struct ips_driver *ips) 496 + { 497 + /* Already off, leave it */ 498 + if (!ips->__cpu_turbo_on) 499 + return; 500 + 501 + on_each_cpu(do_disable_cpu_turbo, ips, 1); 502 + 503 + ips->__cpu_turbo_on = false; 504 + } 505 + 506 + /** 507 + * ips_gpu_busy - is GPU busy? 508 + * @ips: IPS driver struct 509 + * 510 + * Check GPU for load to see whether we should increase its thermal budget. 511 + * We need to call into the i915 driver in this case. 512 + * 513 + * RETURNS: 514 + * True if the GPU could use more power, false otherwise. 515 + */ 516 + static bool ips_gpu_busy(struct ips_driver *ips) 517 + { 518 + if (!ips->gpu_turbo_enabled) 519 + return false; 520 + 521 + return ips->gpu_busy(); 522 + } 523 + 524 + /** 525 + * ips_gpu_raise - raise GPU power clamp 526 + * @ips: IPS driver struct 527 + * 528 + * Raise the GPU frequency/power if possible. We need to call into the 529 + * i915 driver in this case. 530 + */ 531 + static void ips_gpu_raise(struct ips_driver *ips) 532 + { 533 + if (!ips->gpu_turbo_enabled) 534 + return; 535 + 536 + if (!ips->gpu_raise()) 537 + ips->gpu_turbo_enabled = false; 538 + 539 + return; 540 + } 541 + 542 + /** 543 + * ips_gpu_lower - lower GPU power clamp 544 + * @ips: IPS driver struct 545 + * 546 + * Lower GPU frequency/power if possible. Need to call i915. 547 + */ 548 + static void ips_gpu_lower(struct ips_driver *ips) 549 + { 550 + if (!ips->gpu_turbo_enabled) 551 + return; 552 + 553 + if (!ips->gpu_lower()) 554 + ips->gpu_turbo_enabled = false; 555 + 556 + return; 557 + } 558 + 559 + /** 560 + * ips_enable_gpu_turbo - notify the gfx driver turbo is available 561 + * @ips: IPS driver struct 562 + * 563 + * Call into the graphics driver indicating that it can safely use 564 + * turbo mode. 565 + */ 566 + static void ips_enable_gpu_turbo(struct ips_driver *ips) 567 + { 568 + if (ips->__gpu_turbo_on) 569 + return; 570 + ips->__gpu_turbo_on = true; 571 + } 572 + 573 + /** 574 + * ips_disable_gpu_turbo - notify the gfx driver to disable turbo mode 575 + * @ips: IPS driver struct 576 + * 577 + * Request that the graphics driver disable turbo mode. 578 + */ 579 + static void ips_disable_gpu_turbo(struct ips_driver *ips) 580 + { 581 + /* Avoid calling i915 if turbo is already disabled */ 582 + if (!ips->__gpu_turbo_on) 583 + return; 584 + 585 + if (!ips->gpu_turbo_disable()) 586 + dev_err(&ips->dev->dev, "failed to disable graphis turbo\n"); 587 + else 588 + ips->__gpu_turbo_on = false; 589 + } 590 + 591 + /** 592 + * mcp_exceeded - check whether we're outside our thermal & power limits 593 + * @ips: IPS driver struct 594 + * 595 + * Check whether the MCP is over its thermal or power budget. 596 + */ 597 + static bool mcp_exceeded(struct ips_driver *ips) 598 + { 599 + unsigned long flags; 600 + bool ret = false; 601 + 602 + spin_lock_irqsave(&ips->turbo_status_lock, flags); 603 + if (ips->mcp_avg_temp > (ips->mcp_temp_limit * 100)) 604 + ret = true; 605 + if (ips->cpu_avg_power + ips->mch_avg_power > ips->mcp_power_limit) 606 + ret = true; 607 + spin_unlock_irqrestore(&ips->turbo_status_lock, flags); 608 + 609 + if (ret) 610 + dev_info(&ips->dev->dev, 611 + "MCP power or thermal limit exceeded\n"); 612 + 613 + return ret; 614 + } 615 + 616 + /** 617 + * cpu_exceeded - check whether a CPU core is outside its limits 618 + * @ips: IPS driver struct 619 + * @cpu: CPU number to check 620 + * 621 + * Check a given CPU's average temp or power is over its limit. 622 + */ 623 + static bool cpu_exceeded(struct ips_driver *ips, int cpu) 624 + { 625 + unsigned long flags; 626 + int avg; 627 + bool ret = false; 628 + 629 + spin_lock_irqsave(&ips->turbo_status_lock, flags); 630 + avg = cpu ? ips->ctv2_avg_temp : ips->ctv1_avg_temp; 631 + if (avg > (ips->limits->core_temp_limit * 100)) 632 + ret = true; 633 + if (ips->cpu_avg_power > ips->core_power_limit * 100) 634 + ret = true; 635 + spin_unlock_irqrestore(&ips->turbo_status_lock, flags); 636 + 637 + if (ret) 638 + dev_info(&ips->dev->dev, 639 + "CPU power or thermal limit exceeded\n"); 640 + 641 + return ret; 642 + } 643 + 644 + /** 645 + * mch_exceeded - check whether the GPU is over budget 646 + * @ips: IPS driver struct 647 + * 648 + * Check the MCH temp & power against their maximums. 649 + */ 650 + static bool mch_exceeded(struct ips_driver *ips) 651 + { 652 + unsigned long flags; 653 + bool ret = false; 654 + 655 + spin_lock_irqsave(&ips->turbo_status_lock, flags); 656 + if (ips->mch_avg_temp > (ips->limits->mch_temp_limit * 100)) 657 + ret = true; 658 + if (ips->mch_avg_power > ips->mch_power_limit) 659 + ret = true; 660 + spin_unlock_irqrestore(&ips->turbo_status_lock, flags); 661 + 662 + return ret; 663 + } 664 + 665 + /** 666 + * update_turbo_limits - get various limits & settings from regs 667 + * @ips: IPS driver struct 668 + * 669 + * Update the IPS power & temp limits, along with turbo enable flags, 670 + * based on latest register contents. 671 + * 672 + * Used at init time and for runtime BIOS support, which requires polling 673 + * the regs for updates (as a result of AC->DC transition for example). 674 + * 675 + * LOCKING: 676 + * Caller must hold turbo_status_lock (outside of init) 677 + */ 678 + static void update_turbo_limits(struct ips_driver *ips) 679 + { 680 + u32 hts = thm_readl(THM_HTS); 681 + 682 + ips->cpu_turbo_enabled = !(hts & HTS_PCTD_DIS); 683 + ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS); 684 + ips->core_power_limit = thm_readw(THM_MPCPC); 685 + ips->mch_power_limit = thm_readw(THM_MMGPC); 686 + ips->mcp_temp_limit = thm_readw(THM_PTL); 687 + ips->mcp_power_limit = thm_readw(THM_MPPC); 688 + 689 + /* Ignore BIOS CPU vs GPU pref */ 690 + } 691 + 692 + /** 693 + * ips_adjust - adjust power clamp based on thermal state 694 + * @data: ips driver structure 695 + * 696 + * Wake up every 5s or so and check whether we should adjust the power clamp. 697 + * Check CPU and GPU load to determine which needs adjustment. There are 698 + * several things to consider here: 699 + * - do we need to adjust up or down? 700 + * - is CPU busy? 701 + * - is GPU busy? 702 + * - is CPU in turbo? 703 + * - is GPU in turbo? 704 + * - is CPU or GPU preferred? (CPU is default) 705 + * 706 + * So, given the above, we do the following: 707 + * - up (TDP available) 708 + * - CPU not busy, GPU not busy - nothing 709 + * - CPU busy, GPU not busy - adjust CPU up 710 + * - CPU not busy, GPU busy - adjust GPU up 711 + * - CPU busy, GPU busy - adjust preferred unit up, taking headroom from 712 + * non-preferred unit if necessary 713 + * - down (at TDP limit) 714 + * - adjust both CPU and GPU down if possible 715 + * 716 + cpu+ gpu+ cpu+gpu- cpu-gpu+ cpu-gpu- 717 + cpu < gpu < cpu+gpu+ cpu+ gpu+ nothing 718 + cpu < gpu >= cpu+gpu-(mcp<) cpu+gpu-(mcp<) gpu- gpu- 719 + cpu >= gpu < cpu-gpu+(mcp<) cpu- cpu-gpu+(mcp<) cpu- 720 + cpu >= gpu >= cpu-gpu- cpu-gpu- cpu-gpu- cpu-gpu- 721 + * 722 + */ 723 + static int ips_adjust(void *data) 724 + { 725 + struct ips_driver *ips = data; 726 + unsigned long flags; 727 + 728 + dev_dbg(&ips->dev->dev, "starting ips-adjust thread\n"); 729 + 730 + /* 731 + * Adjust CPU and GPU clamps every 5s if needed. Doing it more 732 + * often isn't recommended due to ME interaction. 733 + */ 734 + do { 735 + bool cpu_busy = ips_cpu_busy(ips); 736 + bool gpu_busy = ips_gpu_busy(ips); 737 + 738 + spin_lock_irqsave(&ips->turbo_status_lock, flags); 739 + if (ips->poll_turbo_status) 740 + update_turbo_limits(ips); 741 + spin_unlock_irqrestore(&ips->turbo_status_lock, flags); 742 + 743 + /* Update turbo status if necessary */ 744 + if (ips->cpu_turbo_enabled) 745 + ips_enable_cpu_turbo(ips); 746 + else 747 + ips_disable_cpu_turbo(ips); 748 + 749 + if (ips->gpu_turbo_enabled) 750 + ips_enable_gpu_turbo(ips); 751 + else 752 + ips_disable_gpu_turbo(ips); 753 + 754 + /* We're outside our comfort zone, crank them down */ 755 + if (mcp_exceeded(ips)) { 756 + ips_cpu_lower(ips); 757 + ips_gpu_lower(ips); 758 + goto sleep; 759 + } 760 + 761 + if (!cpu_exceeded(ips, 0) && cpu_busy) 762 + ips_cpu_raise(ips); 763 + else 764 + ips_cpu_lower(ips); 765 + 766 + if (!mch_exceeded(ips) && gpu_busy) 767 + ips_gpu_raise(ips); 768 + else 769 + ips_gpu_lower(ips); 770 + 771 + sleep: 772 + schedule_timeout_interruptible(msecs_to_jiffies(IPS_ADJUST_PERIOD)); 773 + } while (!kthread_should_stop()); 774 + 775 + dev_dbg(&ips->dev->dev, "ips-adjust thread stopped\n"); 776 + 777 + return 0; 778 + } 779 + 780 + /* 781 + * Helpers for reading out temp/power values and calculating their 782 + * averages for the decision making and monitoring functions. 783 + */ 784 + 785 + static u16 calc_avg_temp(struct ips_driver *ips, u16 *array) 786 + { 787 + u64 total = 0; 788 + int i; 789 + u16 avg; 790 + 791 + for (i = 0; i < IPS_SAMPLE_COUNT; i++) 792 + total += (u64)(array[i] * 100); 793 + 794 + do_div(total, IPS_SAMPLE_COUNT); 795 + 796 + avg = (u16)total; 797 + 798 + return avg; 799 + } 800 + 801 + static u16 read_mgtv(struct ips_driver *ips) 802 + { 803 + u16 ret; 804 + u64 slope, offset; 805 + u64 val; 806 + 807 + val = thm_readq(THM_MGTV); 808 + val = (val & TV_MASK) >> TV_SHIFT; 809 + 810 + slope = offset = thm_readw(THM_MGTA); 811 + slope = (slope & MGTA_SLOPE_MASK) >> MGTA_SLOPE_SHIFT; 812 + offset = offset & MGTA_OFFSET_MASK; 813 + 814 + ret = ((val * slope + 0x40) >> 7) + offset; 815 + 816 + return 0; /* MCH temp reporting buggy */ 817 + } 818 + 819 + static u16 read_ptv(struct ips_driver *ips) 820 + { 821 + u16 val, slope, offset; 822 + 823 + slope = (ips->pta_val & PTA_SLOPE_MASK) >> PTA_SLOPE_SHIFT; 824 + offset = ips->pta_val & PTA_OFFSET_MASK; 825 + 826 + val = thm_readw(THM_PTV) & PTV_MASK; 827 + 828 + return val; 829 + } 830 + 831 + static u16 read_ctv(struct ips_driver *ips, int cpu) 832 + { 833 + int reg = cpu ? THM_CTV2 : THM_CTV1; 834 + u16 val; 835 + 836 + val = thm_readw(reg); 837 + if (!(val & CTV_TEMP_ERROR)) 838 + val = (val) >> 6; /* discard fractional component */ 839 + else 840 + val = 0; 841 + 842 + return val; 843 + } 844 + 845 + static u32 get_cpu_power(struct ips_driver *ips, u32 *last, int period) 846 + { 847 + u32 val; 848 + u32 ret; 849 + 850 + /* 851 + * CEC is in joules/65535. Take difference over time to 852 + * get watts. 853 + */ 854 + val = thm_readl(THM_CEC); 855 + 856 + /* period is in ms and we want mW */ 857 + ret = (((val - *last) * 1000) / period); 858 + ret = (ret * 1000) / 65535; 859 + *last = val; 860 + 861 + return ret; 862 + } 863 + 864 + static const u16 temp_decay_factor = 2; 865 + static u16 update_average_temp(u16 avg, u16 val) 866 + { 867 + u16 ret; 868 + 869 + /* Multiply by 100 for extra precision */ 870 + ret = (val * 100 / temp_decay_factor) + 871 + (((temp_decay_factor - 1) * avg) / temp_decay_factor); 872 + return ret; 873 + } 874 + 875 + static const u16 power_decay_factor = 2; 876 + static u16 update_average_power(u32 avg, u32 val) 877 + { 878 + u32 ret; 879 + 880 + ret = (val / power_decay_factor) + 881 + (((power_decay_factor - 1) * avg) / power_decay_factor); 882 + 883 + return ret; 884 + } 885 + 886 + static u32 calc_avg_power(struct ips_driver *ips, u32 *array) 887 + { 888 + u64 total = 0; 889 + u32 avg; 890 + int i; 891 + 892 + for (i = 0; i < IPS_SAMPLE_COUNT; i++) 893 + total += array[i]; 894 + 895 + do_div(total, IPS_SAMPLE_COUNT); 896 + avg = (u32)total; 897 + 898 + return avg; 899 + } 900 + 901 + static void monitor_timeout(unsigned long arg) 902 + { 903 + wake_up_process((struct task_struct *)arg); 904 + } 905 + 906 + /** 907 + * ips_monitor - temp/power monitoring thread 908 + * @data: ips driver structure 909 + * 910 + * This is the main function for the IPS driver. It monitors power and 911 + * tempurature in the MCP and adjusts CPU and GPU power clams accordingly. 912 + * 913 + * We keep a 5s moving average of power consumption and tempurature. Using 914 + * that data, along with CPU vs GPU preference, we adjust the power clamps 915 + * up or down. 916 + */ 917 + static int ips_monitor(void *data) 918 + { 919 + struct ips_driver *ips = data; 920 + struct timer_list timer; 921 + unsigned long seqno_timestamp, expire, last_msecs, last_sample_period; 922 + int i; 923 + u32 *cpu_samples, *mchp_samples, old_cpu_power; 924 + u16 *mcp_samples, *ctv1_samples, *ctv2_samples, *mch_samples; 925 + u8 cur_seqno, last_seqno; 926 + 927 + mcp_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL); 928 + ctv1_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL); 929 + ctv2_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL); 930 + mch_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL); 931 + cpu_samples = kzalloc(sizeof(u32) * IPS_SAMPLE_COUNT, GFP_KERNEL); 932 + mchp_samples = kzalloc(sizeof(u32) * IPS_SAMPLE_COUNT, GFP_KERNEL); 933 + if (!mcp_samples || !ctv1_samples || !ctv2_samples || !mch_samples || 934 + !cpu_samples || !mchp_samples) { 935 + dev_err(&ips->dev->dev, 936 + "failed to allocate sample array, ips disabled\n"); 937 + kfree(mcp_samples); 938 + kfree(ctv1_samples); 939 + kfree(ctv2_samples); 940 + kfree(mch_samples); 941 + kfree(cpu_samples); 942 + kfree(mchp_samples); 943 + kthread_stop(ips->adjust); 944 + return -ENOMEM; 945 + } 946 + 947 + last_seqno = (thm_readl(THM_ITV) & ITV_ME_SEQNO_MASK) >> 948 + ITV_ME_SEQNO_SHIFT; 949 + seqno_timestamp = get_jiffies_64(); 950 + 951 + old_cpu_power = thm_readl(THM_CEC) / 65535; 952 + schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD)); 953 + 954 + /* Collect an initial average */ 955 + for (i = 0; i < IPS_SAMPLE_COUNT; i++) { 956 + u32 mchp, cpu_power; 957 + u16 val; 958 + 959 + mcp_samples[i] = read_ptv(ips); 960 + 961 + val = read_ctv(ips, 0); 962 + ctv1_samples[i] = val; 963 + 964 + val = read_ctv(ips, 1); 965 + ctv2_samples[i] = val; 966 + 967 + val = read_mgtv(ips); 968 + mch_samples[i] = val; 969 + 970 + cpu_power = get_cpu_power(ips, &old_cpu_power, 971 + IPS_SAMPLE_PERIOD); 972 + cpu_samples[i] = cpu_power; 973 + 974 + if (ips->read_mch_val) { 975 + mchp = ips->read_mch_val(); 976 + mchp_samples[i] = mchp; 977 + } 978 + 979 + schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD)); 980 + if (kthread_should_stop()) 981 + break; 982 + } 983 + 984 + ips->mcp_avg_temp = calc_avg_temp(ips, mcp_samples); 985 + ips->ctv1_avg_temp = calc_avg_temp(ips, ctv1_samples); 986 + ips->ctv2_avg_temp = calc_avg_temp(ips, ctv2_samples); 987 + ips->mch_avg_temp = calc_avg_temp(ips, mch_samples); 988 + ips->cpu_avg_power = calc_avg_power(ips, cpu_samples); 989 + ips->mch_avg_power = calc_avg_power(ips, mchp_samples); 990 + kfree(mcp_samples); 991 + kfree(ctv1_samples); 992 + kfree(ctv2_samples); 993 + kfree(mch_samples); 994 + kfree(cpu_samples); 995 + kfree(mchp_samples); 996 + 997 + /* Start the adjustment thread now that we have data */ 998 + wake_up_process(ips->adjust); 999 + 1000 + /* 1001 + * Ok, now we have an initial avg. From here on out, we track the 1002 + * running avg using a decaying average calculation. This allows 1003 + * us to reduce the sample frequency if the CPU and GPU are idle. 1004 + */ 1005 + old_cpu_power = thm_readl(THM_CEC); 1006 + schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD)); 1007 + last_sample_period = IPS_SAMPLE_PERIOD; 1008 + 1009 + setup_deferrable_timer_on_stack(&timer, monitor_timeout, 1010 + (unsigned long)current); 1011 + do { 1012 + u32 cpu_val, mch_val; 1013 + u16 val; 1014 + 1015 + /* MCP itself */ 1016 + val = read_ptv(ips); 1017 + ips->mcp_avg_temp = update_average_temp(ips->mcp_avg_temp, val); 1018 + 1019 + /* Processor 0 */ 1020 + val = read_ctv(ips, 0); 1021 + ips->ctv1_avg_temp = 1022 + update_average_temp(ips->ctv1_avg_temp, val); 1023 + /* Power */ 1024 + cpu_val = get_cpu_power(ips, &old_cpu_power, 1025 + last_sample_period); 1026 + ips->cpu_avg_power = 1027 + update_average_power(ips->cpu_avg_power, cpu_val); 1028 + 1029 + if (ips->second_cpu) { 1030 + /* Processor 1 */ 1031 + val = read_ctv(ips, 1); 1032 + ips->ctv2_avg_temp = 1033 + update_average_temp(ips->ctv2_avg_temp, val); 1034 + } 1035 + 1036 + /* MCH */ 1037 + val = read_mgtv(ips); 1038 + ips->mch_avg_temp = update_average_temp(ips->mch_avg_temp, val); 1039 + /* Power */ 1040 + if (ips->read_mch_val) { 1041 + mch_val = ips->read_mch_val(); 1042 + ips->mch_avg_power = 1043 + update_average_power(ips->mch_avg_power, 1044 + mch_val); 1045 + } 1046 + 1047 + /* 1048 + * Make sure ME is updating thermal regs. 1049 + * Note: 1050 + * If it's been more than a second since the last update, 1051 + * the ME is probably hung. 1052 + */ 1053 + cur_seqno = (thm_readl(THM_ITV) & ITV_ME_SEQNO_MASK) >> 1054 + ITV_ME_SEQNO_SHIFT; 1055 + if (cur_seqno == last_seqno && 1056 + time_after(jiffies, seqno_timestamp + HZ)) { 1057 + dev_warn(&ips->dev->dev, "ME failed to update for more than 1s, likely hung\n"); 1058 + } else { 1059 + seqno_timestamp = get_jiffies_64(); 1060 + last_seqno = cur_seqno; 1061 + } 1062 + 1063 + last_msecs = jiffies_to_msecs(jiffies); 1064 + expire = jiffies + msecs_to_jiffies(IPS_SAMPLE_PERIOD); 1065 + 1066 + __set_current_state(TASK_UNINTERRUPTIBLE); 1067 + mod_timer(&timer, expire); 1068 + schedule(); 1069 + 1070 + /* Calculate actual sample period for power averaging */ 1071 + last_sample_period = jiffies_to_msecs(jiffies) - last_msecs; 1072 + if (!last_sample_period) 1073 + last_sample_period = 1; 1074 + } while (!kthread_should_stop()); 1075 + 1076 + del_timer_sync(&timer); 1077 + destroy_timer_on_stack(&timer); 1078 + 1079 + dev_dbg(&ips->dev->dev, "ips-monitor thread stopped\n"); 1080 + 1081 + return 0; 1082 + } 1083 + 1084 + #if 0 1085 + #define THM_DUMPW(reg) \ 1086 + { \ 1087 + u16 val = thm_readw(reg); \ 1088 + dev_dbg(&ips->dev->dev, #reg ": 0x%04x\n", val); \ 1089 + } 1090 + #define THM_DUMPL(reg) \ 1091 + { \ 1092 + u32 val = thm_readl(reg); \ 1093 + dev_dbg(&ips->dev->dev, #reg ": 0x%08x\n", val); \ 1094 + } 1095 + #define THM_DUMPQ(reg) \ 1096 + { \ 1097 + u64 val = thm_readq(reg); \ 1098 + dev_dbg(&ips->dev->dev, #reg ": 0x%016x\n", val); \ 1099 + } 1100 + 1101 + static void dump_thermal_info(struct ips_driver *ips) 1102 + { 1103 + u16 ptl; 1104 + 1105 + ptl = thm_readw(THM_PTL); 1106 + dev_dbg(&ips->dev->dev, "Processor temp limit: %d\n", ptl); 1107 + 1108 + THM_DUMPW(THM_CTA); 1109 + THM_DUMPW(THM_TRC); 1110 + THM_DUMPW(THM_CTV1); 1111 + THM_DUMPL(THM_STS); 1112 + THM_DUMPW(THM_PTV); 1113 + THM_DUMPQ(THM_MGTV); 1114 + } 1115 + #endif 1116 + 1117 + /** 1118 + * ips_irq_handler - handle temperature triggers and other IPS events 1119 + * @irq: irq number 1120 + * @arg: unused 1121 + * 1122 + * Handle temperature limit trigger events, generally by lowering the clamps. 1123 + * If we're at a critical limit, we clamp back to the lowest possible value 1124 + * to prevent emergency shutdown. 1125 + */ 1126 + static irqreturn_t ips_irq_handler(int irq, void *arg) 1127 + { 1128 + struct ips_driver *ips = arg; 1129 + u8 tses = thm_readb(THM_TSES); 1130 + u8 tes = thm_readb(THM_TES); 1131 + 1132 + if (!tses && !tes) 1133 + return IRQ_NONE; 1134 + 1135 + dev_info(&ips->dev->dev, "TSES: 0x%02x\n", tses); 1136 + dev_info(&ips->dev->dev, "TES: 0x%02x\n", tes); 1137 + 1138 + /* STS update from EC? */ 1139 + if (tes & 1) { 1140 + u32 sts, tc1; 1141 + 1142 + sts = thm_readl(THM_STS); 1143 + tc1 = thm_readl(THM_TC1); 1144 + 1145 + if (sts & STS_NVV) { 1146 + spin_lock(&ips->turbo_status_lock); 1147 + ips->core_power_limit = (sts & STS_PCPL_MASK) >> 1148 + STS_PCPL_SHIFT; 1149 + ips->mch_power_limit = (sts & STS_GPL_MASK) >> 1150 + STS_GPL_SHIFT; 1151 + /* ignore EC CPU vs GPU pref */ 1152 + ips->cpu_turbo_enabled = !(sts & STS_PCTD_DIS); 1153 + ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS); 1154 + ips->mcp_temp_limit = (sts & STS_PTL_MASK) >> 1155 + STS_PTL_SHIFT; 1156 + ips->mcp_power_limit = (tc1 & STS_PPL_MASK) >> 1157 + STS_PPL_SHIFT; 1158 + spin_unlock(&ips->turbo_status_lock); 1159 + 1160 + thm_writeb(THM_SEC, SEC_ACK); 1161 + } 1162 + thm_writeb(THM_TES, tes); 1163 + } 1164 + 1165 + /* Thermal trip */ 1166 + if (tses) { 1167 + dev_warn(&ips->dev->dev, 1168 + "thermal trip occurred, tses: 0x%04x\n", tses); 1169 + thm_writeb(THM_TSES, tses); 1170 + } 1171 + 1172 + return IRQ_HANDLED; 1173 + } 1174 + 1175 + #ifndef CONFIG_DEBUG_FS 1176 + static void ips_debugfs_init(struct ips_driver *ips) { return; } 1177 + static void ips_debugfs_cleanup(struct ips_driver *ips) { return; } 1178 + #else 1179 + 1180 + /* Expose current state and limits in debugfs if possible */ 1181 + 1182 + struct ips_debugfs_node { 1183 + struct ips_driver *ips; 1184 + char *name; 1185 + int (*show)(struct seq_file *m, void *data); 1186 + }; 1187 + 1188 + static int show_cpu_temp(struct seq_file *m, void *data) 1189 + { 1190 + struct ips_driver *ips = m->private; 1191 + 1192 + seq_printf(m, "%d.%02d\n", ips->ctv1_avg_temp / 100, 1193 + ips->ctv1_avg_temp % 100); 1194 + 1195 + return 0; 1196 + } 1197 + 1198 + static int show_cpu_power(struct seq_file *m, void *data) 1199 + { 1200 + struct ips_driver *ips = m->private; 1201 + 1202 + seq_printf(m, "%dmW\n", ips->cpu_avg_power); 1203 + 1204 + return 0; 1205 + } 1206 + 1207 + static int show_cpu_clamp(struct seq_file *m, void *data) 1208 + { 1209 + u64 turbo_override; 1210 + int tdp, tdc; 1211 + 1212 + rdmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override); 1213 + 1214 + tdp = (int)(turbo_override & TURBO_TDP_MASK); 1215 + tdc = (int)((turbo_override & TURBO_TDC_MASK) >> TURBO_TDC_SHIFT); 1216 + 1217 + /* Convert to .1W/A units */ 1218 + tdp = tdp * 10 / 8; 1219 + tdc = tdc * 10 / 8; 1220 + 1221 + /* Watts Amperes */ 1222 + seq_printf(m, "%d.%dW %d.%dA\n", tdp / 10, tdp % 10, 1223 + tdc / 10, tdc % 10); 1224 + 1225 + return 0; 1226 + } 1227 + 1228 + static int show_mch_temp(struct seq_file *m, void *data) 1229 + { 1230 + struct ips_driver *ips = m->private; 1231 + 1232 + seq_printf(m, "%d.%02d\n", ips->mch_avg_temp / 100, 1233 + ips->mch_avg_temp % 100); 1234 + 1235 + return 0; 1236 + } 1237 + 1238 + static int show_mch_power(struct seq_file *m, void *data) 1239 + { 1240 + struct ips_driver *ips = m->private; 1241 + 1242 + seq_printf(m, "%dmW\n", ips->mch_avg_power); 1243 + 1244 + return 0; 1245 + } 1246 + 1247 + static struct ips_debugfs_node ips_debug_files[] = { 1248 + { NULL, "cpu_temp", show_cpu_temp }, 1249 + { NULL, "cpu_power", show_cpu_power }, 1250 + { NULL, "cpu_clamp", show_cpu_clamp }, 1251 + { NULL, "mch_temp", show_mch_temp }, 1252 + { NULL, "mch_power", show_mch_power }, 1253 + }; 1254 + 1255 + static int ips_debugfs_open(struct inode *inode, struct file *file) 1256 + { 1257 + struct ips_debugfs_node *node = inode->i_private; 1258 + 1259 + return single_open(file, node->show, node->ips); 1260 + } 1261 + 1262 + static const struct file_operations ips_debugfs_ops = { 1263 + .owner = THIS_MODULE, 1264 + .open = ips_debugfs_open, 1265 + .read = seq_read, 1266 + .llseek = seq_lseek, 1267 + .release = single_release, 1268 + }; 1269 + 1270 + static void ips_debugfs_cleanup(struct ips_driver *ips) 1271 + { 1272 + if (ips->debug_root) 1273 + debugfs_remove_recursive(ips->debug_root); 1274 + return; 1275 + } 1276 + 1277 + static void ips_debugfs_init(struct ips_driver *ips) 1278 + { 1279 + int i; 1280 + 1281 + ips->debug_root = debugfs_create_dir("ips", NULL); 1282 + if (!ips->debug_root) { 1283 + dev_err(&ips->dev->dev, 1284 + "failed to create debugfs entries: %ld\n", 1285 + PTR_ERR(ips->debug_root)); 1286 + return; 1287 + } 1288 + 1289 + for (i = 0; i < ARRAY_SIZE(ips_debug_files); i++) { 1290 + struct dentry *ent; 1291 + struct ips_debugfs_node *node = &ips_debug_files[i]; 1292 + 1293 + node->ips = ips; 1294 + ent = debugfs_create_file(node->name, S_IFREG | S_IRUGO, 1295 + ips->debug_root, node, 1296 + &ips_debugfs_ops); 1297 + if (!ent) { 1298 + dev_err(&ips->dev->dev, 1299 + "failed to create debug file: %ld\n", 1300 + PTR_ERR(ent)); 1301 + goto err_cleanup; 1302 + } 1303 + } 1304 + 1305 + return; 1306 + 1307 + err_cleanup: 1308 + ips_debugfs_cleanup(ips); 1309 + return; 1310 + } 1311 + #endif /* CONFIG_DEBUG_FS */ 1312 + 1313 + /** 1314 + * ips_detect_cpu - detect whether CPU supports IPS 1315 + * 1316 + * Walk our list and see if we're on a supported CPU. If we find one, 1317 + * return the limits for it. 1318 + */ 1319 + static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) 1320 + { 1321 + u64 turbo_power, misc_en; 1322 + struct ips_mcp_limits *limits = NULL; 1323 + u16 tdp; 1324 + 1325 + if (!(boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 37)) { 1326 + dev_info(&ips->dev->dev, "Non-IPS CPU detected.\n"); 1327 + goto out; 1328 + } 1329 + 1330 + rdmsrl(IA32_MISC_ENABLE, misc_en); 1331 + /* 1332 + * If the turbo enable bit isn't set, we shouldn't try to enable/disable 1333 + * turbo manually or we'll get an illegal MSR access, even though 1334 + * turbo will still be available. 1335 + */ 1336 + if (!(misc_en & IA32_MISC_TURBO_EN)) 1337 + ; /* add turbo MSR write allowed flag if necessary */ 1338 + 1339 + if (strstr(boot_cpu_data.x86_model_id, "CPU M")) 1340 + limits = &ips_sv_limits; 1341 + else if (strstr(boot_cpu_data.x86_model_id, "CPU L")) 1342 + limits = &ips_lv_limits; 1343 + else if (strstr(boot_cpu_data.x86_model_id, "CPU U")) 1344 + limits = &ips_ulv_limits; 1345 + else 1346 + dev_info(&ips->dev->dev, "No CPUID match found.\n"); 1347 + 1348 + rdmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_power); 1349 + tdp = turbo_power & TURBO_TDP_MASK; 1350 + 1351 + /* Sanity check TDP against CPU */ 1352 + if (limits->mcp_power_limit != (tdp / 8) * 1000) { 1353 + dev_warn(&ips->dev->dev, "Warning: CPU TDP doesn't match expected value (found %d, expected %d)\n", 1354 + tdp / 8, limits->mcp_power_limit / 1000); 1355 + } 1356 + 1357 + out: 1358 + return limits; 1359 + } 1360 + 1361 + /** 1362 + * ips_get_i915_syms - try to get GPU control methods from i915 driver 1363 + * @ips: IPS driver 1364 + * 1365 + * The i915 driver exports several interfaces to allow the IPS driver to 1366 + * monitor and control graphics turbo mode. If we can find them, we can 1367 + * enable graphics turbo, otherwise we must disable it to avoid exceeding 1368 + * thermal and power limits in the MCP. 1369 + */ 1370 + static bool ips_get_i915_syms(struct ips_driver *ips) 1371 + { 1372 + ips->read_mch_val = symbol_get(i915_read_mch_val); 1373 + if (!ips->read_mch_val) 1374 + goto out_err; 1375 + ips->gpu_raise = symbol_get(i915_gpu_raise); 1376 + if (!ips->gpu_raise) 1377 + goto out_put_mch; 1378 + ips->gpu_lower = symbol_get(i915_gpu_lower); 1379 + if (!ips->gpu_lower) 1380 + goto out_put_raise; 1381 + ips->gpu_busy = symbol_get(i915_gpu_busy); 1382 + if (!ips->gpu_busy) 1383 + goto out_put_lower; 1384 + ips->gpu_turbo_disable = symbol_get(i915_gpu_turbo_disable); 1385 + if (!ips->gpu_turbo_disable) 1386 + goto out_put_busy; 1387 + 1388 + return true; 1389 + 1390 + out_put_busy: 1391 + symbol_put(i915_gpu_turbo_disable); 1392 + out_put_lower: 1393 + symbol_put(i915_gpu_lower); 1394 + out_put_raise: 1395 + symbol_put(i915_gpu_raise); 1396 + out_put_mch: 1397 + symbol_put(i915_read_mch_val); 1398 + out_err: 1399 + return false; 1400 + } 1401 + 1402 + static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = { 1403 + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 1404 + PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), }, 1405 + { 0, } 1406 + }; 1407 + 1408 + MODULE_DEVICE_TABLE(pci, ips_id_table); 1409 + 1410 + static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) 1411 + { 1412 + u64 platform_info; 1413 + struct ips_driver *ips; 1414 + u32 hts; 1415 + int ret = 0; 1416 + u16 htshi, trc, trc_required_mask; 1417 + u8 tse; 1418 + 1419 + ips = kzalloc(sizeof(struct ips_driver), GFP_KERNEL); 1420 + if (!ips) 1421 + return -ENOMEM; 1422 + 1423 + pci_set_drvdata(dev, ips); 1424 + ips->dev = dev; 1425 + 1426 + ips->limits = ips_detect_cpu(ips); 1427 + if (!ips->limits) { 1428 + dev_info(&dev->dev, "IPS not supported on this CPU\n"); 1429 + ret = -ENXIO; 1430 + goto error_free; 1431 + } 1432 + 1433 + spin_lock_init(&ips->turbo_status_lock); 1434 + 1435 + if (!pci_resource_start(dev, 0)) { 1436 + dev_err(&dev->dev, "TBAR not assigned, aborting\n"); 1437 + ret = -ENXIO; 1438 + goto error_free; 1439 + } 1440 + 1441 + ret = pci_request_regions(dev, "ips thermal sensor"); 1442 + if (ret) { 1443 + dev_err(&dev->dev, "thermal resource busy, aborting\n"); 1444 + goto error_free; 1445 + } 1446 + 1447 + ret = pci_enable_device(dev); 1448 + if (ret) { 1449 + dev_err(&dev->dev, "can't enable PCI device, aborting\n"); 1450 + goto error_free; 1451 + } 1452 + 1453 + ips->regmap = ioremap(pci_resource_start(dev, 0), 1454 + pci_resource_len(dev, 0)); 1455 + if (!ips->regmap) { 1456 + dev_err(&dev->dev, "failed to map thermal regs, aborting\n"); 1457 + ret = -EBUSY; 1458 + goto error_release; 1459 + } 1460 + 1461 + tse = thm_readb(THM_TSE); 1462 + if (tse != TSE_EN) { 1463 + dev_err(&dev->dev, "thermal device not enabled (0x%02x), aborting\n", tse); 1464 + ret = -ENXIO; 1465 + goto error_unmap; 1466 + } 1467 + 1468 + trc = thm_readw(THM_TRC); 1469 + trc_required_mask = TRC_CORE1_EN | TRC_CORE_PWR | TRC_MCH_EN; 1470 + if ((trc & trc_required_mask) != trc_required_mask) { 1471 + dev_err(&dev->dev, "thermal reporting for required devices not enabled, aborting\n"); 1472 + ret = -ENXIO; 1473 + goto error_unmap; 1474 + } 1475 + 1476 + if (trc & TRC_CORE2_EN) 1477 + ips->second_cpu = true; 1478 + 1479 + update_turbo_limits(ips); 1480 + dev_dbg(&dev->dev, "max cpu power clamp: %dW\n", 1481 + ips->mcp_power_limit / 10); 1482 + dev_dbg(&dev->dev, "max core power clamp: %dW\n", 1483 + ips->core_power_limit / 10); 1484 + /* BIOS may update limits at runtime */ 1485 + if (thm_readl(THM_PSC) & PSP_PBRT) 1486 + ips->poll_turbo_status = true; 1487 + 1488 + if (!ips_get_i915_syms(ips)) { 1489 + dev_err(&dev->dev, "failed to get i915 symbols, graphics turbo disabled\n"); 1490 + ips->gpu_turbo_enabled = false; 1491 + } else { 1492 + dev_dbg(&dev->dev, "graphics turbo enabled\n"); 1493 + ips->gpu_turbo_enabled = true; 1494 + } 1495 + 1496 + /* 1497 + * Check PLATFORM_INFO MSR to make sure this chip is 1498 + * turbo capable. 1499 + */ 1500 + rdmsrl(PLATFORM_INFO, platform_info); 1501 + if (!(platform_info & PLATFORM_TDP)) { 1502 + dev_err(&dev->dev, "platform indicates TDP override unavailable, aborting\n"); 1503 + ret = -ENODEV; 1504 + goto error_unmap; 1505 + } 1506 + 1507 + /* 1508 + * IRQ handler for ME interaction 1509 + * Note: don't use MSI here as the PCH has bugs. 1510 + */ 1511 + pci_disable_msi(dev); 1512 + ret = request_irq(dev->irq, ips_irq_handler, IRQF_SHARED, "ips", 1513 + ips); 1514 + if (ret) { 1515 + dev_err(&dev->dev, "request irq failed, aborting\n"); 1516 + goto error_unmap; 1517 + } 1518 + 1519 + /* Enable aux, hot & critical interrupts */ 1520 + thm_writeb(THM_TSPIEN, TSPIEN_AUX2_LOHI | TSPIEN_CRIT_LOHI | 1521 + TSPIEN_HOT_LOHI | TSPIEN_AUX_LOHI); 1522 + thm_writeb(THM_TEN, TEN_UPDATE_EN); 1523 + 1524 + /* Collect adjustment values */ 1525 + ips->cta_val = thm_readw(THM_CTA); 1526 + ips->pta_val = thm_readw(THM_PTA); 1527 + ips->mgta_val = thm_readw(THM_MGTA); 1528 + 1529 + /* Save turbo limits & ratios */ 1530 + rdmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit); 1531 + 1532 + ips_enable_cpu_turbo(ips); 1533 + ips->cpu_turbo_enabled = true; 1534 + 1535 + /* Set up the work queue and monitor/adjust threads */ 1536 + ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor"); 1537 + if (IS_ERR(ips->monitor)) { 1538 + dev_err(&dev->dev, 1539 + "failed to create thermal monitor thread, aborting\n"); 1540 + ret = -ENOMEM; 1541 + goto error_free_irq; 1542 + } 1543 + 1544 + ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust"); 1545 + if (IS_ERR(ips->adjust)) { 1546 + dev_err(&dev->dev, 1547 + "failed to create thermal adjust thread, aborting\n"); 1548 + ret = -ENOMEM; 1549 + goto error_thread_cleanup; 1550 + } 1551 + 1552 + hts = (ips->core_power_limit << HTS_PCPL_SHIFT) | 1553 + (ips->mcp_temp_limit << HTS_PTL_SHIFT) | HTS_NVV; 1554 + htshi = HTS2_PRST_RUNNING << HTS2_PRST_SHIFT; 1555 + 1556 + thm_writew(THM_HTSHI, htshi); 1557 + thm_writel(THM_HTS, hts); 1558 + 1559 + ips_debugfs_init(ips); 1560 + 1561 + dev_info(&dev->dev, "IPS driver initialized, MCP temp limit %d\n", 1562 + ips->mcp_temp_limit); 1563 + return ret; 1564 + 1565 + error_thread_cleanup: 1566 + kthread_stop(ips->monitor); 1567 + error_free_irq: 1568 + free_irq(ips->dev->irq, ips); 1569 + error_unmap: 1570 + iounmap(ips->regmap); 1571 + error_release: 1572 + pci_release_regions(dev); 1573 + error_free: 1574 + kfree(ips); 1575 + return ret; 1576 + } 1577 + 1578 + static void ips_remove(struct pci_dev *dev) 1579 + { 1580 + struct ips_driver *ips = pci_get_drvdata(dev); 1581 + u64 turbo_override; 1582 + 1583 + if (!ips) 1584 + return; 1585 + 1586 + ips_debugfs_cleanup(ips); 1587 + 1588 + /* Release i915 driver */ 1589 + if (ips->read_mch_val) 1590 + symbol_put(i915_read_mch_val); 1591 + if (ips->gpu_raise) 1592 + symbol_put(i915_gpu_raise); 1593 + if (ips->gpu_lower) 1594 + symbol_put(i915_gpu_lower); 1595 + if (ips->gpu_busy) 1596 + symbol_put(i915_gpu_busy); 1597 + if (ips->gpu_turbo_disable) 1598 + symbol_put(i915_gpu_turbo_disable); 1599 + 1600 + rdmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override); 1601 + turbo_override &= ~(TURBO_TDC_OVR_EN | TURBO_TDP_OVR_EN); 1602 + wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override); 1603 + wrmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit); 1604 + 1605 + free_irq(ips->dev->irq, ips); 1606 + if (ips->adjust) 1607 + kthread_stop(ips->adjust); 1608 + if (ips->monitor) 1609 + kthread_stop(ips->monitor); 1610 + iounmap(ips->regmap); 1611 + pci_release_regions(dev); 1612 + kfree(ips); 1613 + dev_dbg(&dev->dev, "IPS driver removed\n"); 1614 + } 1615 + 1616 + #ifdef CONFIG_PM 1617 + static int ips_suspend(struct pci_dev *dev, pm_message_t state) 1618 + { 1619 + return 0; 1620 + } 1621 + 1622 + static int ips_resume(struct pci_dev *dev) 1623 + { 1624 + return 0; 1625 + } 1626 + #else 1627 + #define ips_suspend NULL 1628 + #define ips_resume NULL 1629 + #endif /* CONFIG_PM */ 1630 + 1631 + static void ips_shutdown(struct pci_dev *dev) 1632 + { 1633 + } 1634 + 1635 + static struct pci_driver ips_pci_driver = { 1636 + .name = "intel ips", 1637 + .id_table = ips_id_table, 1638 + .probe = ips_probe, 1639 + .remove = ips_remove, 1640 + .suspend = ips_suspend, 1641 + .resume = ips_resume, 1642 + .shutdown = ips_shutdown, 1643 + }; 1644 + 1645 + static int __init ips_init(void) 1646 + { 1647 + return pci_register_driver(&ips_pci_driver); 1648 + } 1649 + module_init(ips_init); 1650 + 1651 + static void ips_exit(void) 1652 + { 1653 + pci_unregister_driver(&ips_pci_driver); 1654 + return; 1655 + } 1656 + module_exit(ips_exit); 1657 + 1658 + MODULE_LICENSE("GPL"); 1659 + MODULE_AUTHOR("Jesse Barnes <jbarnes@virtuousgeek.org>"); 1660 + MODULE_DESCRIPTION("Intelligent Power Sharing Driver");
+22 -11
drivers/platform/x86/intel_menlow.c
··· 53 53 #define MEMORY_ARG_CUR_BANDWIDTH 1 54 54 #define MEMORY_ARG_MAX_BANDWIDTH 0 55 55 56 + static void intel_menlow_unregister_sensor(void); 57 + 56 58 /* 57 59 * GTHS returning 'n' would mean that [0,n-1] states are supported 58 60 * In that case max_cstate would be n-1 ··· 408 406 attr->handle = handle; 409 407 410 408 result = device_create_file(dev, &attr->attr); 411 - if (result) 409 + if (result) { 410 + kfree(attr); 412 411 return result; 412 + } 413 413 414 414 mutex_lock(&intel_menlow_attr_lock); 415 415 list_add_tail(&attr->node, &intel_menlow_attr_list); ··· 435 431 /* _TZ must have the AUX0/1 methods */ 436 432 status = acpi_get_handle(handle, GET_AUX0, &dummy); 437 433 if (ACPI_FAILURE(status)) 438 - goto not_found; 434 + return (status == AE_NOT_FOUND) ? AE_OK : status; 439 435 440 436 status = acpi_get_handle(handle, SET_AUX0, &dummy); 441 437 if (ACPI_FAILURE(status)) 442 - goto not_found; 438 + return (status == AE_NOT_FOUND) ? AE_OK : status; 443 439 444 440 result = intel_menlow_add_one_attribute("aux0", 0644, 445 441 aux0_show, aux0_store, ··· 449 445 450 446 status = acpi_get_handle(handle, GET_AUX1, &dummy); 451 447 if (ACPI_FAILURE(status)) 452 - goto not_found; 448 + goto aux1_not_found; 453 449 454 450 status = acpi_get_handle(handle, SET_AUX1, &dummy); 455 451 if (ACPI_FAILURE(status)) 456 - goto not_found; 452 + goto aux1_not_found; 457 453 458 454 result = intel_menlow_add_one_attribute("aux1", 0644, 459 455 aux1_show, aux1_store, 460 456 &thermal->device, handle); 461 - if (result) 457 + if (result) { 458 + intel_menlow_unregister_sensor(); 462 459 return AE_ERROR; 460 + } 463 461 464 462 /* 465 463 * create the "dabney_enabled" attribute which means the user app ··· 471 465 result = intel_menlow_add_one_attribute("bios_enabled", 0444, 472 466 bios_enabled_show, NULL, 473 467 &thermal->device, handle); 474 - if (result) 468 + if (result) { 469 + intel_menlow_unregister_sensor(); 475 470 return AE_ERROR; 471 + } 476 472 477 - not_found: 473 + aux1_not_found: 478 474 if (status == AE_NOT_FOUND) 479 475 return AE_OK; 480 - else 481 - return status; 476 + 477 + intel_menlow_unregister_sensor(); 478 + return status; 482 479 } 483 480 484 481 static void intel_menlow_unregister_sensor(void) ··· 522 513 status = acpi_walk_namespace(ACPI_TYPE_THERMAL, ACPI_ROOT_OBJECT, 523 514 ACPI_UINT32_MAX, 524 515 intel_menlow_register_sensor, NULL, NULL, NULL); 525 - if (ACPI_FAILURE(status)) 516 + if (ACPI_FAILURE(status)) { 517 + acpi_bus_unregister_driver(&intel_menlow_memory_driver); 526 518 return -ENODEV; 519 + } 527 520 528 521 return 0; 529 522 }
+340
drivers/platform/x86/intel_pmic_gpio.c
··· 1 + /* Moorestown PMIC GPIO (access through IPC) driver 2 + * Copyright (c) 2008 - 2009, Intel Corporation. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public License 14 + * along with this program; if not, write to the Free Software 15 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 16 + */ 17 + 18 + /* Supports: 19 + * Moorestown platform PMIC chip 20 + */ 21 + 22 + #include <linux/module.h> 23 + #include <linux/kernel.h> 24 + #include <linux/interrupt.h> 25 + #include <linux/delay.h> 26 + #include <linux/stddef.h> 27 + #include <linux/slab.h> 28 + #include <linux/ioport.h> 29 + #include <linux/init.h> 30 + #include <linux/io.h> 31 + #include <linux/gpio.h> 32 + #include <linux/interrupt.h> 33 + #include <asm/intel_scu_ipc.h> 34 + #include <linux/device.h> 35 + #include <linux/intel_pmic_gpio.h> 36 + #include <linux/platform_device.h> 37 + 38 + #define DRIVER_NAME "pmic_gpio" 39 + 40 + /* register offset that IPC driver should use 41 + * 8 GPIO + 8 GPOSW (6 controllable) + 8GPO 42 + */ 43 + enum pmic_gpio_register { 44 + GPIO0 = 0xE0, 45 + GPIO7 = 0xE7, 46 + GPIOINT = 0xE8, 47 + GPOSWCTL0 = 0xEC, 48 + GPOSWCTL5 = 0xF1, 49 + GPO = 0xF4, 50 + }; 51 + 52 + /* bits definition for GPIO & GPOSW */ 53 + #define GPIO_DRV 0x01 54 + #define GPIO_DIR 0x02 55 + #define GPIO_DIN 0x04 56 + #define GPIO_DOU 0x08 57 + #define GPIO_INTCTL 0x30 58 + #define GPIO_DBC 0xc0 59 + 60 + #define GPOSW_DRV 0x01 61 + #define GPOSW_DOU 0x08 62 + #define GPOSW_RDRV 0x30 63 + 64 + 65 + #define NUM_GPIO 24 66 + 67 + struct pmic_gpio_irq { 68 + spinlock_t lock; 69 + u32 trigger[NUM_GPIO]; 70 + u32 dirty; 71 + struct work_struct work; 72 + }; 73 + 74 + 75 + struct pmic_gpio { 76 + struct gpio_chip chip; 77 + struct pmic_gpio_irq irqtypes; 78 + void *gpiointr; 79 + int irq; 80 + unsigned irq_base; 81 + }; 82 + 83 + static void pmic_program_irqtype(int gpio, int type) 84 + { 85 + if (type & IRQ_TYPE_EDGE_RISING) 86 + intel_scu_ipc_update_register(GPIO0 + gpio, 0x20, 0x20); 87 + else 88 + intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x20); 89 + 90 + if (type & IRQ_TYPE_EDGE_FALLING) 91 + intel_scu_ipc_update_register(GPIO0 + gpio, 0x10, 0x10); 92 + else 93 + intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x10); 94 + }; 95 + 96 + static void pmic_irqtype_work(struct work_struct *work) 97 + { 98 + struct pmic_gpio_irq *t = 99 + container_of(work, struct pmic_gpio_irq, work); 100 + unsigned long flags; 101 + int i; 102 + u16 type; 103 + 104 + spin_lock_irqsave(&t->lock, flags); 105 + /* As we drop the lock, we may need multiple scans if we race the 106 + pmic_irq_type function */ 107 + while (t->dirty) { 108 + /* 109 + * For each pin that has the dirty bit set send an IPC 110 + * message to configure the hardware via the PMIC 111 + */ 112 + for (i = 0; i < NUM_GPIO; i++) { 113 + if (!(t->dirty & (1 << i))) 114 + continue; 115 + t->dirty &= ~(1 << i); 116 + /* We can't trust the array entry or dirty 117 + once the lock is dropped */ 118 + type = t->trigger[i]; 119 + spin_unlock_irqrestore(&t->lock, flags); 120 + pmic_program_irqtype(i, type); 121 + spin_lock_irqsave(&t->lock, flags); 122 + } 123 + } 124 + spin_unlock_irqrestore(&t->lock, flags); 125 + } 126 + 127 + static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 128 + { 129 + if (offset > 8) { 130 + printk(KERN_ERR 131 + "%s: only pin 0-7 support input\n", __func__); 132 + return -1;/* we only have 8 GPIO can use as input */ 133 + } 134 + return intel_scu_ipc_update_register(GPIO0 + offset, 135 + GPIO_DIR, GPIO_DIR); 136 + } 137 + 138 + static int pmic_gpio_direction_output(struct gpio_chip *chip, 139 + unsigned offset, int value) 140 + { 141 + int rc = 0; 142 + 143 + if (offset < 8)/* it is GPIO */ 144 + rc = intel_scu_ipc_update_register(GPIO0 + offset, 145 + GPIO_DRV | GPIO_DOU | GPIO_DIR, 146 + GPIO_DRV | (value ? GPIO_DOU : 0)); 147 + else if (offset < 16)/* it is GPOSW */ 148 + rc = intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8, 149 + GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV, 150 + GPOSW_DRV | (value ? GPOSW_DOU : 0)); 151 + else if (offset > 15 && offset < 24)/* it is GPO */ 152 + rc = intel_scu_ipc_update_register(GPO, 153 + 1 << (offset - 16), 154 + value ? 1 << (offset - 16) : 0); 155 + else { 156 + printk(KERN_ERR 157 + "%s: invalid PMIC GPIO pin %d!\n", __func__, offset); 158 + WARN_ON(1); 159 + } 160 + 161 + return rc; 162 + } 163 + 164 + static int pmic_gpio_get(struct gpio_chip *chip, unsigned offset) 165 + { 166 + u8 r; 167 + int ret; 168 + 169 + /* we only have 8 GPIO pins we can use as input */ 170 + if (offset > 8) 171 + return -EOPNOTSUPP; 172 + ret = intel_scu_ipc_ioread8(GPIO0 + offset, &r); 173 + if (ret < 0) 174 + return ret; 175 + return r & GPIO_DIN; 176 + } 177 + 178 + static void pmic_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 179 + { 180 + if (offset < 8)/* it is GPIO */ 181 + intel_scu_ipc_update_register(GPIO0 + offset, 182 + GPIO_DRV | GPIO_DOU, 183 + GPIO_DRV | (value ? GPIO_DOU : 0)); 184 + else if (offset < 16)/* it is GPOSW */ 185 + intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8, 186 + GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV, 187 + GPOSW_DRV | (value ? GPOSW_DOU : 0)); 188 + else if (offset > 15 && offset < 24) /* it is GPO */ 189 + intel_scu_ipc_update_register(GPO, 190 + 1 << (offset - 16), 191 + value ? 1 << (offset - 16) : 0); 192 + } 193 + 194 + static int pmic_irq_type(unsigned irq, unsigned type) 195 + { 196 + struct pmic_gpio *pg = get_irq_chip_data(irq); 197 + u32 gpio = irq - pg->irq_base; 198 + unsigned long flags; 199 + 200 + if (gpio > pg->chip.ngpio) 201 + return -EINVAL; 202 + 203 + spin_lock_irqsave(&pg->irqtypes.lock, flags); 204 + pg->irqtypes.trigger[gpio] = type; 205 + pg->irqtypes.dirty |= (1 << gpio); 206 + spin_unlock_irqrestore(&pg->irqtypes.lock, flags); 207 + schedule_work(&pg->irqtypes.work); 208 + return 0; 209 + } 210 + 211 + 212 + 213 + static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 214 + { 215 + struct pmic_gpio *pg = container_of(chip, struct pmic_gpio, chip); 216 + 217 + return pg->irq_base + offset; 218 + } 219 + 220 + /* the gpiointr register is read-clear, so just do nothing. */ 221 + static void pmic_irq_unmask(unsigned irq) 222 + { 223 + }; 224 + 225 + static void pmic_irq_mask(unsigned irq) 226 + { 227 + }; 228 + 229 + static struct irq_chip pmic_irqchip = { 230 + .name = "PMIC-GPIO", 231 + .mask = pmic_irq_mask, 232 + .unmask = pmic_irq_unmask, 233 + .set_type = pmic_irq_type, 234 + }; 235 + 236 + static void pmic_irq_handler(unsigned irq, struct irq_desc *desc) 237 + { 238 + struct pmic_gpio *pg = (struct pmic_gpio *)get_irq_data(irq); 239 + u8 intsts = *((u8 *)pg->gpiointr + 4); 240 + int gpio; 241 + 242 + for (gpio = 0; gpio < 8; gpio++) { 243 + if (intsts & (1 << gpio)) { 244 + pr_debug("pmic pin %d triggered\n", gpio); 245 + generic_handle_irq(pg->irq_base + gpio); 246 + } 247 + } 248 + desc->chip->eoi(irq); 249 + } 250 + 251 + static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev) 252 + { 253 + struct device *dev = &pdev->dev; 254 + int irq = platform_get_irq(pdev, 0); 255 + struct intel_pmic_gpio_platform_data *pdata = dev->platform_data; 256 + 257 + struct pmic_gpio *pg; 258 + int retval; 259 + int i; 260 + 261 + if (irq < 0) { 262 + dev_dbg(dev, "no IRQ line\n"); 263 + return -EINVAL; 264 + } 265 + 266 + if (!pdata || !pdata->gpio_base || !pdata->irq_base) { 267 + dev_dbg(dev, "incorrect or missing platform data\n"); 268 + return -EINVAL; 269 + } 270 + 271 + pg = kzalloc(sizeof(*pg), GFP_KERNEL); 272 + if (!pg) 273 + return -ENOMEM; 274 + 275 + dev_set_drvdata(dev, pg); 276 + 277 + pg->irq = irq; 278 + /* setting up SRAM mapping for GPIOINT register */ 279 + pg->gpiointr = ioremap_nocache(pdata->gpiointr, 8); 280 + if (!pg->gpiointr) { 281 + printk(KERN_ERR "%s: Can not map GPIOINT.\n", __func__); 282 + retval = -EINVAL; 283 + goto err2; 284 + } 285 + pg->irq_base = pdata->irq_base; 286 + pg->chip.label = "intel_pmic"; 287 + pg->chip.direction_input = pmic_gpio_direction_input; 288 + pg->chip.direction_output = pmic_gpio_direction_output; 289 + pg->chip.get = pmic_gpio_get; 290 + pg->chip.set = pmic_gpio_set; 291 + pg->chip.to_irq = pmic_gpio_to_irq; 292 + pg->chip.base = pdata->gpio_base; 293 + pg->chip.ngpio = NUM_GPIO; 294 + pg->chip.can_sleep = 1; 295 + pg->chip.dev = dev; 296 + 297 + INIT_WORK(&pg->irqtypes.work, pmic_irqtype_work); 298 + spin_lock_init(&pg->irqtypes.lock); 299 + 300 + pg->chip.dev = dev; 301 + retval = gpiochip_add(&pg->chip); 302 + if (retval) { 303 + printk(KERN_ERR "%s: Can not add pmic gpio chip.\n", __func__); 304 + goto err; 305 + } 306 + set_irq_data(pg->irq, pg); 307 + set_irq_chained_handler(pg->irq, pmic_irq_handler); 308 + for (i = 0; i < 8; i++) { 309 + set_irq_chip_and_handler_name(i + pg->irq_base, &pmic_irqchip, 310 + handle_simple_irq, "demux"); 311 + set_irq_chip_data(i + pg->irq_base, pg); 312 + } 313 + return 0; 314 + err: 315 + iounmap(pg->gpiointr); 316 + err2: 317 + kfree(pg); 318 + return retval; 319 + } 320 + 321 + /* at the same time, register a platform driver 322 + * this supports the sfi 0.81 fw */ 323 + static struct platform_driver platform_pmic_gpio_driver = { 324 + .driver = { 325 + .name = DRIVER_NAME, 326 + .owner = THIS_MODULE, 327 + }, 328 + .probe = platform_pmic_gpio_probe, 329 + }; 330 + 331 + static int __init platform_pmic_gpio_init(void) 332 + { 333 + return platform_driver_register(&platform_pmic_gpio_driver); 334 + } 335 + 336 + subsys_initcall(platform_pmic_gpio_init); 337 + 338 + MODULE_AUTHOR("Alek Du <alek.du@intel.com>"); 339 + MODULE_DESCRIPTION("Intel Moorestown PMIC GPIO driver"); 340 + MODULE_LICENSE("GPL v2");
+52 -128
drivers/platform/x86/intel_scu_ipc.c
··· 23 23 #include <linux/pm.h> 24 24 #include <linux/pci.h> 25 25 #include <linux/interrupt.h> 26 - #include <asm/setup.h> 26 + #include <asm/mrst.h> 27 27 #include <asm/intel_scu_ipc.h> 28 28 29 29 /* IPC defines the following message types */ ··· 37 37 #define IPC_CMD_PCNTRL_W 0 /* Register write */ 38 38 #define IPC_CMD_PCNTRL_R 1 /* Register read */ 39 39 #define IPC_CMD_PCNTRL_M 2 /* Register read-modify-write */ 40 - 41 - /* Miscelaneous Command ids */ 42 - #define IPC_CMD_INDIRECT_RD 2 /* 32bit indirect read */ 43 - #define IPC_CMD_INDIRECT_WR 5 /* 32bit indirect write */ 44 40 45 41 /* 46 42 * IPC register summary ··· 58 62 59 63 #define IPC_BASE_ADDR 0xFF11C000 /* IPC1 base register address */ 60 64 #define IPC_MAX_ADDR 0x100 /* Maximum IPC regisers */ 61 - #define IPC_WWBUF_SIZE 16 /* IPC Write buffer Size */ 62 - #define IPC_RWBUF_SIZE 16 /* IPC Read buffer Size */ 65 + #define IPC_WWBUF_SIZE 20 /* IPC Write buffer Size */ 66 + #define IPC_RWBUF_SIZE 20 /* IPC Read buffer Size */ 63 67 #define IPC_I2C_BASE 0xFF12B000 /* I2C control register base address */ 64 68 #define IPC_I2C_MAX_ADDR 0x10 /* Maximum I2C regisers */ 65 69 ··· 74 78 75 79 static struct intel_scu_ipc_dev ipcdev; /* Only one for now */ 76 80 77 - static int platform = 1; 78 - module_param(platform, int, 0); 79 - MODULE_PARM_DESC(platform, "1 for moorestown platform"); 80 - 81 - 82 - 81 + static int platform; /* Platform type */ 83 82 84 83 /* 85 84 * IPC Read Buffer (Read Only): ··· 110 119 } 111 120 112 121 /* 113 - * IPC destination Pointer (Write Only): 114 - * Use content as pointer for destination write 115 - */ 116 - static inline void ipc_write_dptr(u32 data) /* Write dptr data */ 117 - { 118 - writel(data, ipcdev.ipc_base + 0x0C); 119 - } 120 - 121 - /* 122 - * IPC Source Pointer (Write Only): 123 - * Use content as pointer for read location 124 - */ 125 - static inline void ipc_write_sptr(u32 data) /* Write dptr data */ 126 - { 127 - writel(data, ipcdev.ipc_base + 0x08); 128 - } 129 - 130 - /* 131 122 * Status Register (Read Only): 132 123 * Driver will read this register to get the ready/busy status of the IPC 133 124 * block and error status of the IPC command that was just processed by SCU ··· 127 154 return readb(ipcdev.ipc_base + IPC_READ_BUFFER + offset); 128 155 } 129 156 130 - static inline u8 ipc_data_readl(u32 offset) /* Read ipc u32 data */ 157 + static inline u32 ipc_data_readl(u32 offset) /* Read ipc u32 data */ 131 158 { 132 159 return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset); 133 160 } ··· 148 175 return -ETIMEDOUT; 149 176 } 150 177 } 151 - return (status >> 1) & 1; 178 + if ((status >> 1) & 1) 179 + return -EIO; 180 + 181 + return 0; 152 182 } 153 183 154 184 /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */ 155 185 static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) 156 186 { 157 - int nc; 187 + int i, nc, bytes, d; 158 188 u32 offset = 0; 159 189 u32 err = 0; 160 - u8 cbuf[IPC_WWBUF_SIZE] = { '\0' }; 190 + u8 cbuf[IPC_WWBUF_SIZE] = { }; 161 191 u32 *wbuf = (u32 *)&cbuf; 162 192 163 193 mutex_lock(&ipclock); 194 + 195 + memset(cbuf, 0, sizeof(cbuf)); 196 + 164 197 if (ipcdev.pdev == NULL) { 165 198 mutex_unlock(&ipclock); 166 199 return -ENODEV; 167 200 } 168 201 169 - if (platform == 1) { 170 - /* Entry is 4 bytes for read/write, 5 bytes for read modify */ 171 - for (nc = 0; nc < count; nc++) { 202 + if (platform != MRST_CPU_CHIP_PENWELL) { 203 + bytes = 0; 204 + d = 0; 205 + for (i = 0; i < count; i++) { 206 + cbuf[bytes++] = addr[i]; 207 + cbuf[bytes++] = addr[i] >> 8; 208 + if (id != IPC_CMD_PCNTRL_R) 209 + cbuf[bytes++] = data[d++]; 210 + if (id == IPC_CMD_PCNTRL_M) 211 + cbuf[bytes++] = data[d++]; 212 + } 213 + for (i = 0; i < bytes; i += 4) 214 + ipc_data_writel(wbuf[i/4], i); 215 + ipc_command(bytes << 16 | id << 12 | 0 << 8 | op); 216 + } else { 217 + for (nc = 0; nc < count; nc++, offset += 2) { 172 218 cbuf[offset] = addr[nc]; 173 219 cbuf[offset + 1] = addr[nc] >> 8; 174 - if (id != IPC_CMD_PCNTRL_R) 175 - cbuf[offset + 2] = data[nc]; 176 - if (id == IPC_CMD_PCNTRL_M) { 177 - cbuf[offset + 3] = data[nc + 1]; 178 - offset += 1; 179 - } 180 - offset += 3; 181 220 } 182 - for (nc = 0, offset = 0; nc < count; nc++, offset += 4) 183 - ipc_data_writel(wbuf[nc], offset); /* Write wbuff */ 184 221 185 - } else { 186 - for (nc = 0, offset = 0; nc < count; nc++, offset += 2) 187 - ipc_data_writel(addr[nc], offset); /* Write addresses */ 188 - if (id != IPC_CMD_PCNTRL_R) { 189 - for (nc = 0; nc < count; nc++, offset++) 190 - ipc_data_writel(data[nc], offset); /* Write data */ 191 - if (id == IPC_CMD_PCNTRL_M) 192 - ipc_data_writel(data[nc + 1], offset); /* Mask value*/ 222 + if (id == IPC_CMD_PCNTRL_R) { 223 + for (nc = 0, offset = 0; nc < count; nc++, offset += 4) 224 + ipc_data_writel(wbuf[nc], offset); 225 + ipc_command((count*2) << 16 | id << 12 | 0 << 8 | op); 226 + } else if (id == IPC_CMD_PCNTRL_W) { 227 + for (nc = 0; nc < count; nc++, offset += 1) 228 + cbuf[offset] = data[nc]; 229 + for (nc = 0, offset = 0; nc < count; nc++, offset += 4) 230 + ipc_data_writel(wbuf[nc], offset); 231 + ipc_command((count*3) << 16 | id << 12 | 0 << 8 | op); 232 + } else if (id == IPC_CMD_PCNTRL_M) { 233 + cbuf[offset] = data[0]; 234 + cbuf[offset + 1] = data[1]; 235 + ipc_data_writel(wbuf[0], 0); /* Write wbuff */ 236 + ipc_command(4 << 16 | id << 12 | 0 << 8 | op); 193 237 } 194 238 } 195 239 196 - if (id != IPC_CMD_PCNTRL_M) 197 - ipc_command((count * 3) << 16 | id << 12 | 0 << 8 | op); 198 - else 199 - ipc_command((count * 4) << 16 | id << 12 | 0 << 8 | op); 200 - 201 240 err = busy_loop(); 202 - 203 241 if (id == IPC_CMD_PCNTRL_R) { /* Read rbuf */ 204 242 /* Workaround: values are read as 0 without memcpy_fromio */ 205 - memcpy_fromio(cbuf, ipcdev.ipc_base + IPC_READ_BUFFER, 16); 206 - if (platform == 1) { 243 + memcpy_fromio(cbuf, ipcdev.ipc_base + 0x90, 16); 244 + if (platform != MRST_CPU_CHIP_PENWELL) { 207 245 for (nc = 0, offset = 2; nc < count; nc++, offset += 3) 208 246 data[nc] = ipc_data_readb(offset); 209 247 } else { ··· 389 405 EXPORT_SYMBOL(intel_scu_ipc_update_register); 390 406 391 407 /** 392 - * intel_scu_ipc_register_read - 32bit indirect read 393 - * @addr: register address 394 - * @value: 32bit value return 395 - * 396 - * Performs IA 32 bit indirect read, returns 0 on success, or an 397 - * error code. 398 - * 399 - * Can be used when SCCB(System Controller Configuration Block) register 400 - * HRIM(Honor Restricted IPC Messages) is set (bit 23) 401 - * 402 - * This function may sleep. Locking for SCU accesses is handled for 403 - * the caller. 404 - */ 405 - int intel_scu_ipc_register_read(u32 addr, u32 *value) 406 - { 407 - u32 err = 0; 408 - 409 - mutex_lock(&ipclock); 410 - if (ipcdev.pdev == NULL) { 411 - mutex_unlock(&ipclock); 412 - return -ENODEV; 413 - } 414 - ipc_write_sptr(addr); 415 - ipc_command(4 << 16 | IPC_CMD_INDIRECT_RD); 416 - err = busy_loop(); 417 - *value = ipc_data_readl(0); 418 - mutex_unlock(&ipclock); 419 - return err; 420 - } 421 - EXPORT_SYMBOL(intel_scu_ipc_register_read); 422 - 423 - /** 424 - * intel_scu_ipc_register_write - 32bit indirect write 425 - * @addr: register address 426 - * @value: 32bit value to write 427 - * 428 - * Performs IA 32 bit indirect write, returns 0 on success, or an 429 - * error code. 430 - * 431 - * Can be used when SCCB(System Controller Configuration Block) register 432 - * HRIM(Honor Restricted IPC Messages) is set (bit 23) 433 - * 434 - * This function may sleep. Locking for SCU accesses is handled for 435 - * the caller. 436 - */ 437 - int intel_scu_ipc_register_write(u32 addr, u32 value) 438 - { 439 - u32 err = 0; 440 - 441 - mutex_lock(&ipclock); 442 - if (ipcdev.pdev == NULL) { 443 - mutex_unlock(&ipclock); 444 - return -ENODEV; 445 - } 446 - ipc_write_dptr(addr); 447 - ipc_data_writel(value, 0); 448 - ipc_command(4 << 16 | IPC_CMD_INDIRECT_WR); 449 - err = busy_loop(); 450 - mutex_unlock(&ipclock); 451 - return err; 452 - } 453 - EXPORT_SYMBOL(intel_scu_ipc_register_write); 454 - 455 - /** 456 408 * intel_scu_ipc_simple_command - send a simple command 457 409 * @cmd: command 458 410 * @sub: sub type ··· 444 524 for (i = 0; i < inlen; i++) 445 525 ipc_data_writel(*in++, 4 * i); 446 526 447 - ipc_command((sub << 12) | cmd | (inlen << 18)); 527 + ipc_command((inlen << 16) | (sub << 12) | cmd); 448 528 err = busy_loop(); 449 529 450 530 for (i = 0; i < outlen; i++) ··· 723 803 724 804 static const struct pci_device_id pci_ids[] = { 725 805 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080e)}, 806 + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)}, 726 807 { 0,} 727 808 }; 728 809 MODULE_DEVICE_TABLE(pci, pci_ids); ··· 738 817 739 818 static int __init intel_scu_ipc_init(void) 740 819 { 820 + platform = mrst_identify_cpu(); 821 + if (platform == 0) 822 + return -ENODEV; 741 823 return pci_register_driver(&ipc_driver); 742 824 } 743 825
+4 -4
drivers/platform/x86/msi-laptop.c
··· 434 434 { 435 435 printk(KERN_INFO "msi-laptop: Identified laptop model '%s'.\n", 436 436 id->ident); 437 - return 0; 437 + return 1; 438 438 } 439 439 440 440 static struct dmi_system_id __initdata msi_dmi_table[] = { ··· 562 562 return 0; 563 563 } 564 564 565 - static struct rfkill_ops rfkill_bluetooth_ops = { 565 + static const struct rfkill_ops rfkill_bluetooth_ops = { 566 566 .set_block = rfkill_bluetooth_set 567 567 }; 568 568 569 - static struct rfkill_ops rfkill_wlan_ops = { 569 + static const struct rfkill_ops rfkill_wlan_ops = { 570 570 .set_block = rfkill_wlan_set 571 571 }; 572 572 573 - static struct rfkill_ops rfkill_threeg_ops = { 573 + static const struct rfkill_ops rfkill_threeg_ops = { 574 574 .set_block = rfkill_threeg_set 575 575 }; 576 576
+1 -1
drivers/platform/x86/msi-wmi.c
··· 57 57 }; 58 58 static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1]; 59 59 60 - struct backlight_device *backlight; 60 + static struct backlight_device *backlight; 61 61 62 62 static int backlight_map[] = { 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF }; 63 63
+2 -5
drivers/platform/x86/panasonic-laptop.c
··· 248 248 status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SSET, 249 249 &params, NULL); 250 250 251 - return status == AE_OK; 251 + return (status == AE_OK) ? 0 : -EIO; 252 252 } 253 253 254 254 static inline int acpi_pcc_get_sqty(struct acpi_device *device) ··· 586 586 static int acpi_pcc_hotkey_resume(struct acpi_device *device) 587 587 { 588 588 struct pcc_acpi *pcc = acpi_driver_data(device); 589 - acpi_status status = AE_OK; 590 589 591 590 if (device == NULL || pcc == NULL) 592 591 return -EINVAL; ··· 593 594 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Sticky mode restore: %d\n", 594 595 pcc->sticky_mode)); 595 596 596 - status = acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_mode); 597 - 598 - return status == AE_OK ? 0 : -EINVAL; 597 + return acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_mode); 599 598 } 600 599 601 600 static int acpi_pcc_hotkey_add(struct acpi_device *device)
+8 -5
drivers/platform/x86/sony-laptop.c
··· 561 561 if (!atomic_dec_and_test(&sony_pf_users)) 562 562 return; 563 563 564 - platform_device_del(sony_pf_device); 565 - platform_device_put(sony_pf_device); 564 + platform_device_unregister(sony_pf_device); 566 565 platform_driver_unregister(&sony_pf_driver); 567 566 } 568 567 ··· 1195 1196 } 1196 1197 1197 1198 device_enum = (union acpi_object *) buffer.pointer; 1198 - if (!device_enum || device_enum->type != ACPI_TYPE_BUFFER) { 1199 - printk(KERN_ERR "Invalid SN06 return object 0x%.2x\n", 1200 - device_enum->type); 1199 + if (!device_enum) { 1200 + pr_err("Invalid SN06 return object\n"); 1201 + goto out_no_enum; 1202 + } 1203 + if (device_enum->type != ACPI_TYPE_BUFFER) { 1204 + pr_err("Invalid SN06 return object type 0x%.2x\n", 1205 + device_enum->type); 1201 1206 goto out_no_enum; 1202 1207 } 1203 1208
-73
drivers/platform/x86/thinkpad_acpi.c
··· 5838 5838 }; 5839 5839 5840 5840 /************************************************************************* 5841 - * EC Dump subdriver 5842 - */ 5843 - 5844 - static u8 ecdump_regs[256]; 5845 - 5846 - static int ecdump_read(struct seq_file *m) 5847 - { 5848 - int i, j; 5849 - u8 v; 5850 - 5851 - seq_printf(m, "EC " 5852 - " +00 +01 +02 +03 +04 +05 +06 +07" 5853 - " +08 +09 +0a +0b +0c +0d +0e +0f\n"); 5854 - for (i = 0; i < 256; i += 16) { 5855 - seq_printf(m, "EC 0x%02x:", i); 5856 - for (j = 0; j < 16; j++) { 5857 - if (!acpi_ec_read(i + j, &v)) 5858 - break; 5859 - if (v != ecdump_regs[i + j]) 5860 - seq_printf(m, " *%02x", v); 5861 - else 5862 - seq_printf(m, " %02x", v); 5863 - ecdump_regs[i + j] = v; 5864 - } 5865 - seq_putc(m, '\n'); 5866 - if (j != 16) 5867 - break; 5868 - } 5869 - 5870 - /* These are way too dangerous to advertise openly... */ 5871 - #if 0 5872 - seq_printf(m, "commands:\t0x<offset> 0x<value>" 5873 - " (<offset> is 00-ff, <value> is 00-ff)\n"); 5874 - seq_printf(m, "commands:\t0x<offset> <value> " 5875 - " (<offset> is 00-ff, <value> is 0-255)\n"); 5876 - #endif 5877 - return 0; 5878 - } 5879 - 5880 - static int ecdump_write(char *buf) 5881 - { 5882 - char *cmd; 5883 - int i, v; 5884 - 5885 - while ((cmd = next_cmd(&buf))) { 5886 - if (sscanf(cmd, "0x%x 0x%x", &i, &v) == 2) { 5887 - /* i and v set */ 5888 - } else if (sscanf(cmd, "0x%x %u", &i, &v) == 2) { 5889 - /* i and v set */ 5890 - } else 5891 - return -EINVAL; 5892 - if (i >= 0 && i < 256 && v >= 0 && v < 256) { 5893 - if (!acpi_ec_write(i, v)) 5894 - return -EIO; 5895 - } else 5896 - return -EINVAL; 5897 - } 5898 - 5899 - return 0; 5900 - } 5901 - 5902 - static struct ibm_struct ecdump_driver_data = { 5903 - .name = "ecdump", 5904 - .read = ecdump_read, 5905 - .write = ecdump_write, 5906 - .flags.experimental = 1, 5907 - }; 5908 - 5909 - /************************************************************************* 5910 5841 * Backlight/brightness subdriver 5911 5842 */ 5912 5843 ··· 8814 8883 .data = &thermal_driver_data, 8815 8884 }, 8816 8885 { 8817 - .data = &ecdump_driver_data, 8818 - }, 8819 - { 8820 8886 .init = brightness_init, 8821 8887 .data = &brightness_driver_data, 8822 8888 }, ··· 8921 8993 TPACPI_PARAM(cmos); 8922 8994 TPACPI_PARAM(led); 8923 8995 TPACPI_PARAM(beep); 8924 - TPACPI_PARAM(ecdump); 8925 8996 TPACPI_PARAM(brightness); 8926 8997 TPACPI_PARAM(volume); 8927 8998 TPACPI_PARAM(fan);
+123 -12
drivers/platform/x86/toshiba_acpi.c
··· 4 4 * 5 5 * Copyright (C) 2002-2004 John Belmonte 6 6 * Copyright (C) 2008 Philip Langdale 7 + * Copyright (C) 2010 Pierre Ducroquet 7 8 * 8 9 * This program is free software; you can redistribute it and/or modify 9 10 * it under the terms of the GNU General Public License as published by ··· 48 47 #include <linux/platform_device.h> 49 48 #include <linux/rfkill.h> 50 49 #include <linux/input.h> 50 + #include <linux/leds.h> 51 51 #include <linux/slab.h> 52 52 53 53 #include <asm/uaccess.h> ··· 131 129 132 130 static struct key_entry toshiba_acpi_keymap[] = { 133 131 {KE_KEY, 0x101, KEY_MUTE}, 132 + {KE_KEY, 0x102, KEY_ZOOMOUT}, 133 + {KE_KEY, 0x103, KEY_ZOOMIN}, 134 134 {KE_KEY, 0x13b, KEY_COFFEE}, 135 135 {KE_KEY, 0x13c, KEY_BATTERY}, 136 136 {KE_KEY, 0x13d, KEY_SLEEP}, ··· 289 285 struct platform_device *p_dev; 290 286 struct rfkill *bt_rfk; 291 287 struct input_dev *hotkey_dev; 288 + int illumination_installed; 292 289 acpi_handle handle; 293 290 294 291 const char *bt_name; 295 292 296 293 struct mutex mutex; 294 + }; 295 + 296 + /* Illumination support */ 297 + static int toshiba_illumination_available(void) 298 + { 299 + u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; 300 + u32 out[HCI_WORDS]; 301 + acpi_status status; 302 + 303 + in[0] = 0xf100; 304 + status = hci_raw(in, out); 305 + if (ACPI_FAILURE(status)) { 306 + printk(MY_INFO "Illumination device not available\n"); 307 + return 0; 308 + } 309 + in[0] = 0xf400; 310 + status = hci_raw(in, out); 311 + return 1; 312 + } 313 + 314 + static void toshiba_illumination_set(struct led_classdev *cdev, 315 + enum led_brightness brightness) 316 + { 317 + u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; 318 + u32 out[HCI_WORDS]; 319 + acpi_status status; 320 + 321 + /* First request : initialize communication. */ 322 + in[0] = 0xf100; 323 + status = hci_raw(in, out); 324 + if (ACPI_FAILURE(status)) { 325 + printk(MY_INFO "Illumination device not available\n"); 326 + return; 327 + } 328 + 329 + if (brightness) { 330 + /* Switch the illumination on */ 331 + in[0] = 0xf400; 332 + in[1] = 0x14e; 333 + in[2] = 1; 334 + status = hci_raw(in, out); 335 + if (ACPI_FAILURE(status)) { 336 + printk(MY_INFO "ACPI call for illumination failed.\n"); 337 + return; 338 + } 339 + } else { 340 + /* Switch the illumination off */ 341 + in[0] = 0xf400; 342 + in[1] = 0x14e; 343 + in[2] = 0; 344 + status = hci_raw(in, out); 345 + if (ACPI_FAILURE(status)) { 346 + printk(MY_INFO "ACPI call for illumination failed.\n"); 347 + return; 348 + } 349 + } 350 + 351 + /* Last request : close communication. */ 352 + in[0] = 0xf200; 353 + in[1] = 0; 354 + in[2] = 0; 355 + hci_raw(in, out); 356 + } 357 + 358 + static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev) 359 + { 360 + u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; 361 + u32 out[HCI_WORDS]; 362 + acpi_status status; 363 + enum led_brightness result; 364 + 365 + /* First request : initialize communication. */ 366 + in[0] = 0xf100; 367 + status = hci_raw(in, out); 368 + if (ACPI_FAILURE(status)) { 369 + printk(MY_INFO "Illumination device not available\n"); 370 + return LED_OFF; 371 + } 372 + 373 + /* Check the illumination */ 374 + in[0] = 0xf300; 375 + in[1] = 0x14e; 376 + status = hci_raw(in, out); 377 + if (ACPI_FAILURE(status)) { 378 + printk(MY_INFO "ACPI call for illumination failed.\n"); 379 + return LED_OFF; 380 + } 381 + 382 + result = out[2] ? LED_FULL : LED_OFF; 383 + 384 + /* Last request : close communication. */ 385 + in[0] = 0xf200; 386 + in[1] = 0; 387 + in[2] = 0; 388 + hci_raw(in, out); 389 + 390 + return result; 391 + } 392 + 393 + static struct led_classdev toshiba_led = { 394 + .name = "toshiba::illumination", 395 + .max_brightness = 1, 396 + .brightness_set = toshiba_illumination_set, 397 + .brightness_get = toshiba_illumination_get, 297 398 }; 298 399 299 400 static struct toshiba_acpi_dev toshiba_acpi = { ··· 829 720 830 721 #define PROC_TOSHIBA "toshiba" 831 722 832 - static acpi_status __init add_device(void) 723 + static void __init create_toshiba_proc_entries(void) 833 724 { 834 725 proc_create("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, &lcd_proc_fops); 835 726 proc_create("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, &video_proc_fops); 836 727 proc_create("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, &fan_proc_fops); 837 728 proc_create("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, &keys_proc_fops); 838 729 proc_create("version", S_IRUGO, toshiba_proc_dir, &version_proc_fops); 839 - 840 - return AE_OK; 841 730 } 842 731 843 - static acpi_status remove_device(void) 732 + static void remove_toshiba_proc_entries(void) 844 733 { 845 734 remove_proc_entry("lcd", toshiba_proc_dir); 846 735 remove_proc_entry("video", toshiba_proc_dir); 847 736 remove_proc_entry("fan", toshiba_proc_dir); 848 737 remove_proc_entry("keys", toshiba_proc_dir); 849 738 remove_proc_entry("version", toshiba_proc_dir); 850 - return AE_OK; 851 739 } 852 740 853 741 static struct backlight_ops toshiba_backlight_data = { ··· 1012 906 if (toshiba_backlight_device) 1013 907 backlight_device_unregister(toshiba_backlight_device); 1014 908 1015 - remove_device(); 909 + remove_toshiba_proc_entries(); 1016 910 1017 911 if (toshiba_proc_dir) 1018 912 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); 1019 913 1020 914 acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY, 1021 915 toshiba_acpi_notify); 916 + 917 + if (toshiba_acpi.illumination_installed) 918 + led_classdev_unregister(&toshiba_led); 1022 919 1023 920 platform_device_unregister(toshiba_acpi.p_dev); 1024 921 ··· 1030 921 1031 922 static int __init toshiba_acpi_init(void) 1032 923 { 1033 - acpi_status status = AE_OK; 1034 924 u32 hci_result; 1035 925 bool bt_present; 1036 926 int ret = 0; ··· 1077 969 toshiba_acpi_exit(); 1078 970 return -ENODEV; 1079 971 } else { 1080 - status = add_device(); 1081 - if (ACPI_FAILURE(status)) { 1082 - toshiba_acpi_exit(); 1083 - return -ENODEV; 1084 - } 972 + create_toshiba_proc_entries(); 1085 973 } 1086 974 1087 975 props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; ··· 1115 1011 toshiba_acpi_exit(); 1116 1012 return ret; 1117 1013 } 1014 + } 1015 + 1016 + toshiba_acpi.illumination_installed = 0; 1017 + if (toshiba_illumination_available()) { 1018 + if (!led_classdev_register(&(toshiba_acpi.p_dev->dev), 1019 + &toshiba_led)) 1020 + toshiba_acpi.illumination_installed = 1; 1118 1021 } 1119 1022 1120 1023 return 0;
+20 -8
drivers/platform/x86/wmi.c
··· 518 518 { 519 519 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 520 520 union acpi_object *obj; 521 + acpi_status status; 521 522 522 - wmi_get_event_data(value, &response); 523 + status = wmi_get_event_data(value, &response); 524 + if (status != AE_OK) { 525 + printk(KERN_INFO "wmi: bad event status 0x%x\n", status); 526 + return; 527 + } 523 528 524 529 obj = (union acpi_object *)response.pointer; 525 530 ··· 548 543 default: 549 544 printk("object type 0x%X\n", obj->type); 550 545 } 546 + kfree(obj); 551 547 } 552 548 553 549 /** ··· 810 804 /* 811 805 * Parse the _WDG method for the GUID data blocks 812 806 */ 813 - static __init acpi_status parse_wdg(acpi_handle handle) 807 + static acpi_status parse_wdg(acpi_handle handle) 814 808 { 815 809 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 816 810 union acpi_object *obj; ··· 833 827 total = obj->buffer.length / sizeof(struct guid_block); 834 828 835 829 gblock = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL); 836 - if (!gblock) 837 - return AE_NO_MEMORY; 830 + if (!gblock) { 831 + status = AE_NO_MEMORY; 832 + goto out_free_pointer; 833 + } 838 834 839 835 for (i = 0; i < total; i++) { 840 836 /* ··· 856 848 wmi_dump_wdg(&gblock[i]); 857 849 858 850 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); 859 - if (!wblock) 860 - return AE_NO_MEMORY; 851 + if (!wblock) { 852 + status = AE_NO_MEMORY; 853 + goto out_free_gblock; 854 + } 861 855 862 856 wblock->gblock = gblock[i]; 863 857 wblock->handle = handle; ··· 870 860 list_add_tail(&wblock->list, &wmi_blocks.list); 871 861 } 872 862 873 - kfree(out.pointer); 863 + out_free_gblock: 874 864 kfree(gblock); 865 + out_free_pointer: 866 + kfree(out.pointer); 875 867 876 868 return status; 877 869 } ··· 959 947 return 0; 960 948 } 961 949 962 - static int __init acpi_wmi_add(struct acpi_device *device) 950 + static int acpi_wmi_add(struct acpi_device *device) 963 951 { 964 952 acpi_status status; 965 953 int result = 0;
-2
drivers/staging/Kconfig
··· 109 109 110 110 source "drivers/staging/vme/Kconfig" 111 111 112 - source "drivers/staging/rar_register/Kconfig" 113 - 114 112 source "drivers/staging/memrar/Kconfig" 115 113 116 114 source "drivers/staging/sep/Kconfig"
-1
drivers/staging/Makefile
··· 36 36 obj-$(CONFIG_FB_UDL) += udlfb/ 37 37 obj-$(CONFIG_HYPERV) += hv/ 38 38 obj-$(CONFIG_VME_BUS) += vme/ 39 - obj-$(CONFIG_RAR_REGISTER) += rar_register/ 40 39 obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/ 41 40 obj-$(CONFIG_DX_SEP) += sep/ 42 41 obj-$(CONFIG_IIO) += iio/
+1 -2
drivers/staging/memrar/memrar_handler.c
··· 47 47 #include <linux/mm.h> 48 48 #include <linux/ioport.h> 49 49 #include <linux/io.h> 50 - 51 - #include "../rar_register/rar_register.h" 50 + #include <linux/rar_register.h> 52 51 53 52 #include "memrar.h" 54 53 #include "memrar_allocator.h"
-30
drivers/staging/rar_register/Kconfig
··· 1 - # 2 - # RAR device configuration 3 - # 4 - 5 - menu "RAR Register Driver" 6 - # 7 - # Restricted Access Register Manager 8 - # 9 - config RAR_REGISTER 10 - tristate "Restricted Access Region Register Driver" 11 - depends on PCI 12 - default n 13 - ---help--- 14 - This driver allows other kernel drivers access to the 15 - contents of the restricted access region control registers. 16 - 17 - The restricted access region control registers 18 - (rar_registers) are used to pass address and 19 - locking information on restricted access regions 20 - to other drivers that use restricted access regions. 21 - 22 - The restricted access regions are regions of memory 23 - on the Intel MID Platform that are not accessible to 24 - the x86 processor, but are accessible to dedicated 25 - processors on board peripheral devices. 26 - 27 - The purpose of the restricted access regions is to 28 - protect sensitive data from compromise by unauthorized 29 - programs running on the x86 processor. 30 - endmenu
-2
drivers/staging/rar_register/Makefile
··· 1 - EXTRA_CFLAGS += -DLITTLE__ENDIAN 2 - obj-$(CONFIG_RAR_REGISTER) += rar_register.o
+2 -6
drivers/staging/rar_register/rar_register.c drivers/platform/x86/intel_rar_register.c
··· 40 40 * Initial publish 41 41 */ 42 42 43 - #define DEBUG 1 44 - 45 - #include "rar_register.h" 46 - 47 43 #include <linux/module.h> 48 44 #include <linux/pci.h> 49 45 #include <linux/spinlock.h> 50 46 #include <linux/device.h> 51 47 #include <linux/kernel.h> 48 + #include <linux/rar_register.h> 52 49 53 50 /* === Lincroft Message Bus Interface === */ 54 51 #define LNC_MCR_OFFSET 0xD0 /* Message Control Register */ ··· 151 154 } 152 155 return NULL; 153 156 } 154 - 155 157 156 158 /** 157 159 * rar_to_device - return the device handling this RAR ··· 492 496 * a driver that do require a valid RAR address. One of those 493 497 * steps would be to call rar_get_address() 494 498 * 495 - * This function return 0 on success an error code on failure. 499 + * This function return 0 on success or an error code on failure. 496 500 */ 497 501 int register_rar(int num, int (*callback)(unsigned long data), 498 502 unsigned long data)
drivers/staging/rar_register/rar_register.h include/linux/rar_register.h
+9
include/drm/i915_drm.h
··· 33 33 * subject to backwards-compatibility constraints. 34 34 */ 35 35 36 + #ifdef __KERNEL__ 37 + /* For use by IPS driver */ 38 + extern unsigned long i915_read_mch_val(void); 39 + extern bool i915_gpu_raise(void); 40 + extern bool i915_gpu_lower(void); 41 + extern bool i915_gpu_busy(void); 42 + extern bool i915_gpu_turbo_disable(void); 43 + #endif 44 + 36 45 /* Each region is a minimum of 16k, and there are at most 255 of them. 37 46 */ 38 47 #define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
+15
include/linux/intel_pmic_gpio.h
··· 1 + #ifndef LINUX_INTEL_PMIC_H 2 + #define LINUX_INTEL_PMIC_H 3 + 4 + struct intel_pmic_gpio_platform_data { 5 + /* the first IRQ of the chip */ 6 + unsigned irq_base; 7 + /* number assigned to the first GPIO */ 8 + unsigned gpio_base; 9 + /* sram address for gpiointr register, the langwell chip will map 10 + * the PMIC spi GPIO expander's GPIOINTR register in sram. 11 + */ 12 + unsigned gpiointr; 13 + }; 14 + 15 + #endif
+15
include/linux/timer.h
··· 100 100 setup_timer_on_stack_key((timer), #timer, &__key, \ 101 101 (fn), (data)); \ 102 102 } while (0) 103 + #define setup_deferrable_timer_on_stack(timer, fn, data) \ 104 + do { \ 105 + static struct lock_class_key __key; \ 106 + setup_deferrable_timer_on_stack_key((timer), #timer, \ 107 + &__key, (fn), \ 108 + (data)); \ 109 + } while (0) 103 110 #else 104 111 #define init_timer(timer)\ 105 112 init_timer_key((timer), NULL, NULL) ··· 118 111 setup_timer_key((timer), NULL, NULL, (fn), (data)) 119 112 #define setup_timer_on_stack(timer, fn, data)\ 120 113 setup_timer_on_stack_key((timer), NULL, NULL, (fn), (data)) 114 + #define setup_deferrable_timer_on_stack(timer, fn, data)\ 115 + setup_deferrable_timer_on_stack_key((timer), NULL, NULL, (fn), (data)) 121 116 #endif 122 117 123 118 #ifdef CONFIG_DEBUG_OBJECTS_TIMERS ··· 158 149 timer->data = data; 159 150 init_timer_on_stack_key(timer, name, key); 160 151 } 152 + 153 + extern void setup_deferrable_timer_on_stack_key(struct timer_list *timer, 154 + const char *name, 155 + struct lock_class_key *key, 156 + void (*function)(unsigned long), 157 + unsigned long data); 161 158 162 159 /** 163 160 * timer_pending - is a timer pending?
+13
kernel/timer.c
··· 577 577 lockdep_init_map(&timer->lockdep_map, name, key, 0); 578 578 } 579 579 580 + void setup_deferrable_timer_on_stack_key(struct timer_list *timer, 581 + const char *name, 582 + struct lock_class_key *key, 583 + void (*function)(unsigned long), 584 + unsigned long data) 585 + { 586 + timer->function = function; 587 + timer->data = data; 588 + init_timer_on_stack_key(timer, name, key); 589 + timer_set_deferrable(timer); 590 + } 591 + EXPORT_SYMBOL_GPL(setup_deferrable_timer_on_stack_key); 592 + 580 593 /** 581 594 * init_timer_key - initialize a timer 582 595 * @timer: the timer to be initialized