forked from mirrors/linux
		
	ACPI: Provide /sys/kernel/debug/ec/...
This patch provides the same information through debugfs, which previously was provided through /proc/acpi/embedded_controller/*/info This is the gpe the EC is connected to and whether the global lock gets used. The io ports used are added to /proc/ioports in another patch. Beside the fact that /proc/acpi is deprecated for quite some time, this info is not needed for applications and thus can be moved to debugfs instead of a public interface like /sys. Signed-off-by: Thomas Renninger <trenn@suse.de> CC: Alexey Starikovskiy <astarikovskiy@suse.de> CC: Len Brown <lenb@kernel.org> CC: linux-kernel@vger.kernel.org CC: linux-acpi@vger.kernel.org CC: Bjorn Helgaas <bjorn.helgaas@hp.com> CC: platform-driver-x86@vger.kernel.org Signed-off-by: Matthew Garrett <mjg@redhat.com>
This commit is contained in:
		
							parent
							
								
									cd89e08fa0
								
							
						
					
					
						commit
						1195a09816
					
				
					 5 changed files with 100 additions and 13 deletions
				
			
		|  | @ -104,6 +104,19 @@ config ACPI_SYSFS_POWER | ||||||
| 	help | 	help | ||||||
| 	  Say N to disable power /sys interface | 	  Say N to disable power /sys interface | ||||||
| 
 | 
 | ||||||
|  | config ACPI_EC_DEBUGFS | ||||||
|  | 	tristate "EC read/write access through /sys/kernel/debug/ec" | ||||||
|  | 	default y | ||||||
|  | 	help | ||||||
|  | 	  Say N to disable Embedded Controller /sys/kernel/debug interface | ||||||
|  | 
 | ||||||
|  | 	  An Embedded Controller typically is available on laptops and reads | ||||||
|  | 	  sensor values like battery state and temperature. | ||||||
|  | 	  The kernel access the EC through ACPI parsed code provided by BIOS | ||||||
|  | 	  tables. | ||||||
|  | 	  Thus this option is a debug option that helps to write ACPI drivers | ||||||
|  | 	  and can be used to identify ACPI code or EC firmware bugs. | ||||||
|  | 
 | ||||||
| config ACPI_PROC_EVENT | config ACPI_PROC_EVENT | ||||||
| 	bool "Deprecated /proc/acpi/event support" | 	bool "Deprecated /proc/acpi/event support" | ||||||
| 	depends on PROC_FS | 	depends on PROC_FS | ||||||
|  |  | ||||||
|  | @ -60,6 +60,7 @@ obj-$(CONFIG_ACPI_SBS)		+= sbshc.o | ||||||
| obj-$(CONFIG_ACPI_SBS)		+= sbs.o | obj-$(CONFIG_ACPI_SBS)		+= sbs.o | ||||||
| obj-$(CONFIG_ACPI_POWER_METER)	+= power_meter.o | obj-$(CONFIG_ACPI_POWER_METER)	+= power_meter.o | ||||||
| obj-$(CONFIG_ACPI_HED)		+= hed.o | obj-$(CONFIG_ACPI_HED)		+= hed.o | ||||||
|  | obj-$(CONFIG_ACPI_EC_DEBUGFS)	+= ec_sys.o | ||||||
| 
 | 
 | ||||||
| # processor has its own "processor." module_param namespace
 | # processor has its own "processor." module_param namespace
 | ||||||
| processor-y			:= processor_driver.o processor_throttling.o | processor-y			:= processor_driver.o processor_throttling.o | ||||||
|  |  | ||||||
|  | @ -43,10 +43,13 @@ | ||||||
| #include <acpi/acpi_drivers.h> | #include <acpi/acpi_drivers.h> | ||||||
| #include <linux/dmi.h> | #include <linux/dmi.h> | ||||||
| 
 | 
 | ||||||
|  | #include "internal.h" | ||||||
|  | 
 | ||||||
| #define ACPI_EC_CLASS			"embedded_controller" | #define ACPI_EC_CLASS			"embedded_controller" | ||||||
| #define ACPI_EC_DEVICE_NAME		"Embedded Controller" | #define ACPI_EC_DEVICE_NAME		"Embedded Controller" | ||||||
| #define ACPI_EC_FILE_INFO		"info" | #define ACPI_EC_FILE_INFO		"info" | ||||||
| 
 | 
 | ||||||
|  | #undef PREFIX | ||||||
| #define PREFIX				"ACPI: EC: " | #define PREFIX				"ACPI: EC: " | ||||||
| 
 | 
 | ||||||
| /* EC status register */ | /* EC status register */ | ||||||
|  | @ -104,19 +107,8 @@ struct transaction { | ||||||
| 	bool done; | 	bool done; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static struct acpi_ec { | struct acpi_ec *boot_ec, *first_ec; | ||||||
| 	acpi_handle handle; | EXPORT_SYMBOL(first_ec); | ||||||
| 	unsigned long gpe; |  | ||||||
| 	unsigned long command_addr; |  | ||||||
| 	unsigned long data_addr; |  | ||||||
| 	unsigned long global_lock; |  | ||||||
| 	unsigned long flags; |  | ||||||
| 	struct mutex lock; |  | ||||||
| 	wait_queue_head_t wait; |  | ||||||
| 	struct list_head list; |  | ||||||
| 	struct transaction *curr; |  | ||||||
| 	spinlock_t curr_lock; |  | ||||||
| } *boot_ec, *first_ec; |  | ||||||
| 
 | 
 | ||||||
| static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */ | static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */ | ||||||
| static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ | static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ | ||||||
|  |  | ||||||
							
								
								
									
										57
									
								
								drivers/acpi/ec_sys.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								drivers/acpi/ec_sys.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,57 @@ | ||||||
|  | #include <linux/kernel.h> | ||||||
|  | #include <linux/acpi.h> | ||||||
|  | #include <linux/debugfs.h> | ||||||
|  | #include "internal.h" | ||||||
|  | 
 | ||||||
|  | MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>"); | ||||||
|  | MODULE_DESCRIPTION("ACPI EC sysfs access driver"); | ||||||
|  | MODULE_LICENSE("GPL"); | ||||||
|  | 
 | ||||||
|  | struct sysdev_class acpi_ec_sysdev_class = { | ||||||
|  | 	.name = "ec", | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static struct dentry *acpi_ec_debugfs_dir; | ||||||
|  | 
 | ||||||
|  | int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count) | ||||||
|  | { | ||||||
|  | 	struct dentry *dev_dir; | ||||||
|  | 	char name[64]; | ||||||
|  | 	if (ec_device_count == 0) { | ||||||
|  | 		acpi_ec_debugfs_dir = debugfs_create_dir("ec", NULL); | ||||||
|  | 		if (!acpi_ec_debugfs_dir) | ||||||
|  | 			return -ENOMEM; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sprintf(name, "ec%u", ec_device_count); | ||||||
|  | 	dev_dir = debugfs_create_dir(name, acpi_ec_debugfs_dir); | ||||||
|  | 	if (!dev_dir) { | ||||||
|  | 		if (ec_device_count == 0) | ||||||
|  | 			debugfs_remove_recursive(acpi_ec_debugfs_dir); | ||||||
|  | 		/* TBD: Proper cleanup for multiple ECs */ | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	debugfs_create_x32("gpe", 0444, dev_dir, (u32 *)&first_ec->gpe); | ||||||
|  | 	debugfs_create_bool("use_global_lock", 0444, dev_dir, | ||||||
|  | 			    (u32 *)&first_ec->global_lock); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int __init acpi_ec_sys_init(void) | ||||||
|  | { | ||||||
|  | 	int err = 0; | ||||||
|  | 	if (first_ec) | ||||||
|  | 		err = acpi_ec_add_debugfs(first_ec, 0); | ||||||
|  | 	else | ||||||
|  | 		err = -ENODEV; | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void __exit acpi_ec_sys_exit(void) | ||||||
|  | { | ||||||
|  | 	debugfs_remove_recursive(acpi_ec_debugfs_dir); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | module_init(acpi_ec_sys_init); | ||||||
|  | module_exit(acpi_ec_sys_exit); | ||||||
|  | @ -18,6 +18,11 @@ | ||||||
|  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #ifndef _ACPI_INTERNAL_H_ | ||||||
|  | #define _ACPI_INTERNAL_H_ | ||||||
|  | 
 | ||||||
|  | #include <linux/sysdev.h> | ||||||
|  | 
 | ||||||
| #define PREFIX "ACPI: " | #define PREFIX "ACPI: " | ||||||
| 
 | 
 | ||||||
| int init_acpi_device_notify(void); | int init_acpi_device_notify(void); | ||||||
|  | @ -46,6 +51,23 @@ void acpi_early_processor_set_pdc(void); | ||||||
| /* --------------------------------------------------------------------------
 | /* --------------------------------------------------------------------------
 | ||||||
|                                   Embedded Controller |                                   Embedded Controller | ||||||
|    -------------------------------------------------------------------------- */ |    -------------------------------------------------------------------------- */ | ||||||
|  | struct acpi_ec { | ||||||
|  | 	acpi_handle handle; | ||||||
|  | 	unsigned long gpe; | ||||||
|  | 	unsigned long command_addr; | ||||||
|  | 	unsigned long data_addr; | ||||||
|  | 	unsigned long global_lock; | ||||||
|  | 	unsigned long flags; | ||||||
|  | 	struct mutex lock; | ||||||
|  | 	wait_queue_head_t wait; | ||||||
|  | 	struct list_head list; | ||||||
|  | 	struct transaction *curr; | ||||||
|  | 	spinlock_t curr_lock; | ||||||
|  | 	struct sys_device sysdev; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | extern struct acpi_ec *first_ec; | ||||||
|  | 
 | ||||||
| int acpi_ec_init(void); | int acpi_ec_init(void); | ||||||
| int acpi_ec_ecdt_probe(void); | int acpi_ec_ecdt_probe(void); | ||||||
| int acpi_boot_ec_enable(void); | int acpi_boot_ec_enable(void); | ||||||
|  | @ -63,3 +85,5 @@ int acpi_sleep_proc_init(void); | ||||||
| #else | #else | ||||||
| static inline int acpi_sleep_proc_init(void) { return 0; } | static inline int acpi_sleep_proc_init(void) { return 0; } | ||||||
| #endif | #endif | ||||||
|  | 
 | ||||||
|  | #endif /* _ACPI_INTERNAL_H_ */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Thomas Renninger
						Thomas Renninger