diff options
Diffstat (limited to 'drivers/acpi/sysfs.c')
| -rw-r--r-- | drivers/acpi/sysfs.c | 99 | 
1 files changed, 61 insertions, 38 deletions
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 358165e9f5b8..703c26e7022c 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -314,10 +314,14 @@ static struct kobject *tables_kobj;  static struct kobject *dynamic_tables_kobj;  static struct kobject *hotplug_kobj; +#define ACPI_MAX_TABLE_INSTANCES	999 +#define ACPI_INST_SIZE			4 /* including trailing 0 */ +  struct acpi_table_attr {  	struct bin_attribute attr; -	char name[8]; +	char name[ACPI_NAME_SIZE];  	int instance; +	char filename[ACPI_NAME_SIZE+ACPI_INST_SIZE];  	struct list_head node;  }; @@ -329,14 +333,9 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj,  	    container_of(bin_attr, struct acpi_table_attr, attr);  	struct acpi_table_header *table_header = NULL;  	acpi_status status; -	char name[ACPI_NAME_SIZE]; - -	if (strncmp(table_attr->name, "NULL", 4)) -		memcpy(name, table_attr->name, ACPI_NAME_SIZE); -	else -		memcpy(name, "\0\0\0\0", 4); -	status = acpi_get_table(name, table_attr->instance, &table_header); +	status = acpi_get_table(table_attr->name, table_attr->instance, +				&table_header);  	if (ACPI_FAILURE(status))  		return -ENODEV; @@ -344,38 +343,45 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj,  				       table_header, table_header->length);  } -static void acpi_table_attr_init(struct acpi_table_attr *table_attr, -				 struct acpi_table_header *table_header) +static int acpi_table_attr_init(struct kobject *tables_obj, +				struct acpi_table_attr *table_attr, +				struct acpi_table_header *table_header)  {  	struct acpi_table_header *header = NULL;  	struct acpi_table_attr *attr = NULL; +	char instance_str[ACPI_INST_SIZE];  	sysfs_attr_init(&table_attr->attr.attr); -	if (table_header->signature[0] != '\0') -		memcpy(table_attr->name, table_header->signature, -		       ACPI_NAME_SIZE); -	else -		memcpy(table_attr->name, "NULL", 4); +	ACPI_MOVE_NAME(table_attr->name, table_header->signature);  	list_for_each_entry(attr, &acpi_table_attr_list, node) { -		if (!memcmp(table_attr->name, attr->name, ACPI_NAME_SIZE)) +		if (ACPI_COMPARE_NAME(table_attr->name, attr->name))  			if (table_attr->instance < attr->instance)  				table_attr->instance = attr->instance;  	}  	table_attr->instance++; +	if (table_attr->instance > ACPI_MAX_TABLE_INSTANCES) { +		pr_warn("%4.4s: too many table instances\n", +			table_attr->name); +		return -ERANGE; +	} +	ACPI_MOVE_NAME(table_attr->filename, table_header->signature); +	table_attr->filename[ACPI_NAME_SIZE] = '\0';  	if (table_attr->instance > 1 || (table_attr->instance == 1 &&  					 !acpi_get_table -					 (table_header->signature, 2, &header))) -		sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", -			table_attr->instance); +					 (table_header->signature, 2, &header))) { +		snprintf(instance_str, sizeof(instance_str), "%u", +			 table_attr->instance); +		strcat(table_attr->filename, instance_str); +	}  	table_attr->attr.size = table_header->length;  	table_attr->attr.read = acpi_table_show; -	table_attr->attr.attr.name = table_attr->name; +	table_attr->attr.attr.name = table_attr->filename;  	table_attr->attr.attr.mode = 0400; -	return; +	return sysfs_create_bin_file(tables_obj, &table_attr->attr);  }  acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context) @@ -383,21 +389,22 @@ acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context)  	struct acpi_table_attr *table_attr;  	switch (event) { -	case ACPI_TABLE_EVENT_LOAD: +	case ACPI_TABLE_EVENT_INSTALL:  		table_attr =  		    kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL);  		if (!table_attr)  			return AE_NO_MEMORY; -		acpi_table_attr_init(table_attr, table); -		if (sysfs_create_bin_file(dynamic_tables_kobj, -					  &table_attr->attr)) { +		if (acpi_table_attr_init(dynamic_tables_kobj, +					 table_attr, table)) {  			kfree(table_attr);  			return AE_ERROR; -		} else -			list_add_tail(&table_attr->node, &acpi_table_attr_list); +		} +		list_add_tail(&table_attr->node, &acpi_table_attr_list);  		break; +	case ACPI_TABLE_EVENT_LOAD:  	case ACPI_TABLE_EVENT_UNLOAD: +	case ACPI_TABLE_EVENT_UNINSTALL:  		/*  		 * we do not need to do anything right now  		 * because the table is not deleted from the @@ -435,13 +442,12 @@ static int acpi_tables_sysfs_init(void)  		if (ACPI_FAILURE(status))  			continue; -		table_attr = NULL;  		table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL);  		if (!table_attr)  			return -ENOMEM; -		acpi_table_attr_init(table_attr, table_header); -		ret = sysfs_create_bin_file(tables_kobj, &table_attr->attr); +		ret = acpi_table_attr_init(tables_kobj, +					   table_attr, table_header);  		if (ret) {  			kfree(table_attr);  			return ret; @@ -597,14 +603,27 @@ static ssize_t counter_show(struct kobject *kobj,  	if (result)  		goto end; +	if (status & ACPI_EVENT_FLAG_ENABLE_SET) +		size += sprintf(buf + size, "  EN"); +	else +		size += sprintf(buf + size, "    "); +	if (status & ACPI_EVENT_FLAG_STATUS_SET) +		size += sprintf(buf + size, " STS"); +	else +		size += sprintf(buf + size, "    "); +  	if (!(status & ACPI_EVENT_FLAG_HAS_HANDLER)) -		size += sprintf(buf + size, "   invalid"); +		size += sprintf(buf + size, " invalid     ");  	else if (status & ACPI_EVENT_FLAG_ENABLED) -		size += sprintf(buf + size, "   enabled"); +		size += sprintf(buf + size, " enabled     ");  	else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) -		size += sprintf(buf + size, "   wake_enabled"); +		size += sprintf(buf + size, " wake_enabled"); +	else +		size += sprintf(buf + size, " disabled    "); +	if (status & ACPI_EVENT_FLAG_MASKED) +		size += sprintf(buf + size, " masked  ");  	else -		size += sprintf(buf + size, "   disabled"); +		size += sprintf(buf + size, " unmasked");  end:  	size += sprintf(buf + size, "\n"); @@ -655,8 +674,12 @@ static ssize_t counter_set(struct kobject *kobj,  			 !(status & ACPI_EVENT_FLAG_ENABLED))  			result = acpi_enable_gpe(handle, index);  		else if (!strcmp(buf, "clear\n") && -			 (status & ACPI_EVENT_FLAG_SET)) +			 (status & ACPI_EVENT_FLAG_STATUS_SET))  			result = acpi_clear_gpe(handle, index); +		else if (!strcmp(buf, "mask\n")) +			result = acpi_mask_gpe(handle, index, TRUE); +		else if (!strcmp(buf, "unmask\n")) +			result = acpi_mask_gpe(handle, index, FALSE);  		else if (!kstrtoul(buf, 0, &tmp))  			all_counters[index].count = tmp;  		else @@ -664,13 +687,13 @@ static ssize_t counter_set(struct kobject *kobj,  	} else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) {  		int event = index - num_gpes;  		if (!strcmp(buf, "disable\n") && -		    (status & ACPI_EVENT_FLAG_ENABLED)) +		    (status & ACPI_EVENT_FLAG_ENABLE_SET))  			result = acpi_disable_event(event, ACPI_NOT_ISR);  		else if (!strcmp(buf, "enable\n") && -			 !(status & ACPI_EVENT_FLAG_ENABLED)) +			 !(status & ACPI_EVENT_FLAG_ENABLE_SET))  			result = acpi_enable_event(event, ACPI_NOT_ISR);  		else if (!strcmp(buf, "clear\n") && -			 (status & ACPI_EVENT_FLAG_SET)) +			 (status & ACPI_EVENT_FLAG_STATUS_SET))  			result = acpi_clear_event(event);  		else if (!kstrtoul(buf, 0, &tmp))  			all_counters[index].count = tmp;  | 
