Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.8-rc3 267 lines 6.0 kB view raw
1/* 2 * ACPI configfs support 3 * 4 * Copyright (c) 2016 Intel Corporation 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published by 8 * the Free Software Foundation. 9 */ 10 11#define pr_fmt(fmt) "ACPI configfs: " fmt 12 13#include <linux/init.h> 14#include <linux/module.h> 15#include <linux/configfs.h> 16#include <linux/acpi.h> 17 18static struct config_group *acpi_table_group; 19 20struct acpi_table { 21 struct config_item cfg; 22 struct acpi_table_header *header; 23}; 24 25static ssize_t acpi_table_aml_write(struct config_item *cfg, 26 const void *data, size_t size) 27{ 28 const struct acpi_table_header *header = data; 29 struct acpi_table *table; 30 int ret; 31 32 table = container_of(cfg, struct acpi_table, cfg); 33 34 if (table->header) { 35 pr_err("table already loaded\n"); 36 return -EBUSY; 37 } 38 39 if (header->length != size) { 40 pr_err("invalid table length\n"); 41 return -EINVAL; 42 } 43 44 if (memcmp(header->signature, ACPI_SIG_SSDT, 4)) { 45 pr_err("invalid table signature\n"); 46 return -EINVAL; 47 } 48 49 table = container_of(cfg, struct acpi_table, cfg); 50 51 table->header = kmemdup(header, header->length, GFP_KERNEL); 52 if (!table->header) 53 return -ENOMEM; 54 55 ret = acpi_load_table(table->header); 56 if (ret) { 57 kfree(table->header); 58 table->header = NULL; 59 } 60 61 return ret; 62} 63 64static inline struct acpi_table_header *get_header(struct config_item *cfg) 65{ 66 struct acpi_table *table = container_of(cfg, struct acpi_table, cfg); 67 68 if (!table->header) 69 pr_err("table not loaded\n"); 70 71 return table->header; 72} 73 74static ssize_t acpi_table_aml_read(struct config_item *cfg, 75 void *data, size_t size) 76{ 77 struct acpi_table_header *h = get_header(cfg); 78 79 if (!h) 80 return -EINVAL; 81 82 if (data) 83 memcpy(data, h, h->length); 84 85 return h->length; 86} 87 88#define MAX_ACPI_TABLE_SIZE (128 * 1024) 89 90CONFIGFS_BIN_ATTR(acpi_table_, aml, NULL, MAX_ACPI_TABLE_SIZE); 91 92struct configfs_bin_attribute *acpi_table_bin_attrs[] = { 93 &acpi_table_attr_aml, 94 NULL, 95}; 96 97ssize_t acpi_table_signature_show(struct config_item *cfg, char *str) 98{ 99 struct acpi_table_header *h = get_header(cfg); 100 101 if (!h) 102 return -EINVAL; 103 104 return sprintf(str, "%.*s\n", ACPI_NAME_SIZE, h->signature); 105} 106 107ssize_t acpi_table_length_show(struct config_item *cfg, char *str) 108{ 109 struct acpi_table_header *h = get_header(cfg); 110 111 if (!h) 112 return -EINVAL; 113 114 return sprintf(str, "%d\n", h->length); 115} 116 117ssize_t acpi_table_revision_show(struct config_item *cfg, char *str) 118{ 119 struct acpi_table_header *h = get_header(cfg); 120 121 if (!h) 122 return -EINVAL; 123 124 return sprintf(str, "%d\n", h->revision); 125} 126 127ssize_t acpi_table_oem_id_show(struct config_item *cfg, char *str) 128{ 129 struct acpi_table_header *h = get_header(cfg); 130 131 if (!h) 132 return -EINVAL; 133 134 return sprintf(str, "%.*s\n", ACPI_OEM_ID_SIZE, h->oem_id); 135} 136 137ssize_t acpi_table_oem_table_id_show(struct config_item *cfg, char *str) 138{ 139 struct acpi_table_header *h = get_header(cfg); 140 141 if (!h) 142 return -EINVAL; 143 144 return sprintf(str, "%.*s\n", ACPI_OEM_TABLE_ID_SIZE, h->oem_table_id); 145} 146 147ssize_t acpi_table_oem_revision_show(struct config_item *cfg, char *str) 148{ 149 struct acpi_table_header *h = get_header(cfg); 150 151 if (!h) 152 return -EINVAL; 153 154 return sprintf(str, "%d\n", h->oem_revision); 155} 156 157ssize_t acpi_table_asl_compiler_id_show(struct config_item *cfg, char *str) 158{ 159 struct acpi_table_header *h = get_header(cfg); 160 161 if (!h) 162 return -EINVAL; 163 164 return sprintf(str, "%.*s\n", ACPI_NAME_SIZE, h->asl_compiler_id); 165} 166 167ssize_t acpi_table_asl_compiler_revision_show(struct config_item *cfg, 168 char *str) 169{ 170 struct acpi_table_header *h = get_header(cfg); 171 172 if (!h) 173 return -EINVAL; 174 175 return sprintf(str, "%d\n", h->asl_compiler_revision); 176} 177 178CONFIGFS_ATTR_RO(acpi_table_, signature); 179CONFIGFS_ATTR_RO(acpi_table_, length); 180CONFIGFS_ATTR_RO(acpi_table_, revision); 181CONFIGFS_ATTR_RO(acpi_table_, oem_id); 182CONFIGFS_ATTR_RO(acpi_table_, oem_table_id); 183CONFIGFS_ATTR_RO(acpi_table_, oem_revision); 184CONFIGFS_ATTR_RO(acpi_table_, asl_compiler_id); 185CONFIGFS_ATTR_RO(acpi_table_, asl_compiler_revision); 186 187struct configfs_attribute *acpi_table_attrs[] = { 188 &acpi_table_attr_signature, 189 &acpi_table_attr_length, 190 &acpi_table_attr_revision, 191 &acpi_table_attr_oem_id, 192 &acpi_table_attr_oem_table_id, 193 &acpi_table_attr_oem_revision, 194 &acpi_table_attr_asl_compiler_id, 195 &acpi_table_attr_asl_compiler_revision, 196 NULL, 197}; 198 199static struct config_item_type acpi_table_type = { 200 .ct_owner = THIS_MODULE, 201 .ct_bin_attrs = acpi_table_bin_attrs, 202 .ct_attrs = acpi_table_attrs, 203}; 204 205static struct config_item *acpi_table_make_item(struct config_group *group, 206 const char *name) 207{ 208 struct acpi_table *table; 209 210 table = kzalloc(sizeof(*table), GFP_KERNEL); 211 if (!table) 212 return ERR_PTR(-ENOMEM); 213 214 config_item_init_type_name(&table->cfg, name, &acpi_table_type); 215 return &table->cfg; 216} 217 218struct configfs_group_operations acpi_table_group_ops = { 219 .make_item = acpi_table_make_item, 220}; 221 222static struct config_item_type acpi_tables_type = { 223 .ct_owner = THIS_MODULE, 224 .ct_group_ops = &acpi_table_group_ops, 225}; 226 227static struct config_item_type acpi_root_group_type = { 228 .ct_owner = THIS_MODULE, 229}; 230 231static struct configfs_subsystem acpi_configfs = { 232 .su_group = { 233 .cg_item = { 234 .ci_namebuf = "acpi", 235 .ci_type = &acpi_root_group_type, 236 }, 237 }, 238 .su_mutex = __MUTEX_INITIALIZER(acpi_configfs.su_mutex), 239}; 240 241static int __init acpi_configfs_init(void) 242{ 243 int ret; 244 struct config_group *root = &acpi_configfs.su_group; 245 246 config_group_init(root); 247 248 ret = configfs_register_subsystem(&acpi_configfs); 249 if (ret) 250 return ret; 251 252 acpi_table_group = configfs_register_default_group(root, "table", 253 &acpi_tables_type); 254 return PTR_ERR_OR_ZERO(acpi_table_group); 255} 256module_init(acpi_configfs_init); 257 258static void __exit acpi_configfs_exit(void) 259{ 260 configfs_unregister_default_group(acpi_table_group); 261 configfs_unregister_subsystem(&acpi_configfs); 262} 263module_exit(acpi_configfs_exit); 264 265MODULE_AUTHOR("Octavian Purdila <octavian.purdila@intel.com>"); 266MODULE_DESCRIPTION("ACPI configfs support"); 267MODULE_LICENSE("GPL v2");