diff options
author | Mike Waychison <mikew@google.com> | 2011-03-11 20:43:00 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-03-14 11:40:49 -0400 |
commit | 29422693c410c68071bdd60e0a0ec590490781aa (patch) | |
tree | f402b6ea9b360eee4078a9ebc28e84b626bec894 /drivers/firmware/efivars.c | |
parent | c1605f2e3312ca149caf32129e0b25b1e7296f36 (diff) |
efivars: move efivars globals into struct efivars
In preparation for abstracting out efivars to be usable by other similar
variable services, move the global lock, list and kset into a structure.
Later patches will change the scope of 'efivars' and have it be passed
by function argument.
Signed-off-by: Mike Waychison <mikew@google.com>
Cc: Matt Domsch <Matt_Domsch@dell.com>,
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/firmware/efivars.c')
-rw-r--r-- | drivers/firmware/efivars.c | 86 |
1 files changed, 46 insertions, 40 deletions
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 2a62ec6390e0..f10ecb6d04b2 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
@@ -89,16 +89,21 @@ MODULE_DESCRIPTION("sysfs interface to EFI Variables"); | |||
89 | MODULE_LICENSE("GPL"); | 89 | MODULE_LICENSE("GPL"); |
90 | MODULE_VERSION(EFIVARS_VERSION); | 90 | MODULE_VERSION(EFIVARS_VERSION); |
91 | 91 | ||
92 | /* | 92 | struct efivars { |
93 | * efivars_lock protects two things: | 93 | /* |
94 | * 1) efivar_list - adds, removals, reads, writes | 94 | * ->lock protects two things: |
95 | * 2) efi.[gs]et_variable() calls. | 95 | * 1) ->list - adds, removals, reads, writes |
96 | * It must not be held when creating sysfs entries or calling kmalloc. | 96 | * 2) efi.[gs]et_variable() calls. |
97 | * efi.get_next_variable() is only called from efivars_init(), | 97 | * It must not be held when creating sysfs entries or calling kmalloc. |
98 | * which is protected by the BKL, so that path is safe. | 98 | * efi.get_next_variable() is only called from efivars_init(), |
99 | */ | 99 | * which is protected by the BKL, so that path is safe. |
100 | static DEFINE_SPINLOCK(efivars_lock); | 100 | */ |
101 | static LIST_HEAD(efivar_list); | 101 | spinlock_t lock; |
102 | struct list_head list; | ||
103 | struct kset *kset; | ||
104 | }; | ||
105 | static struct efivars __efivars; | ||
106 | static struct efivars *efivars = &__efivars; | ||
102 | 107 | ||
103 | /* | 108 | /* |
104 | * The maximum size of VariableName + Data = 1024 | 109 | * The maximum size of VariableName + Data = 1024 |
@@ -174,14 +179,14 @@ get_var_data(struct efi_variable *var) | |||
174 | { | 179 | { |
175 | efi_status_t status; | 180 | efi_status_t status; |
176 | 181 | ||
177 | spin_lock(&efivars_lock); | 182 | spin_lock(&efivars->lock); |
178 | var->DataSize = 1024; | 183 | var->DataSize = 1024; |
179 | status = efi.get_variable(var->VariableName, | 184 | status = efi.get_variable(var->VariableName, |
180 | &var->VendorGuid, | 185 | &var->VendorGuid, |
181 | &var->Attributes, | 186 | &var->Attributes, |
182 | &var->DataSize, | 187 | &var->DataSize, |
183 | var->Data); | 188 | var->Data); |
184 | spin_unlock(&efivars_lock); | 189 | spin_unlock(&efivars->lock); |
185 | if (status != EFI_SUCCESS) { | 190 | if (status != EFI_SUCCESS) { |
186 | printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n", | 191 | printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n", |
187 | status); | 192 | status); |
@@ -291,14 +296,14 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) | |||
291 | return -EINVAL; | 296 | return -EINVAL; |
292 | } | 297 | } |
293 | 298 | ||
294 | spin_lock(&efivars_lock); | 299 | spin_lock(&efivars->lock); |
295 | status = efi.set_variable(new_var->VariableName, | 300 | status = efi.set_variable(new_var->VariableName, |
296 | &new_var->VendorGuid, | 301 | &new_var->VendorGuid, |
297 | new_var->Attributes, | 302 | new_var->Attributes, |
298 | new_var->DataSize, | 303 | new_var->DataSize, |
299 | new_var->Data); | 304 | new_var->Data); |
300 | 305 | ||
301 | spin_unlock(&efivars_lock); | 306 | spin_unlock(&efivars->lock); |
302 | 307 | ||
303 | if (status != EFI_SUCCESS) { | 308 | if (status != EFI_SUCCESS) { |
304 | printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", | 309 | printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", |
@@ -415,12 +420,12 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
415 | if (!capable(CAP_SYS_ADMIN)) | 420 | if (!capable(CAP_SYS_ADMIN)) |
416 | return -EACCES; | 421 | return -EACCES; |
417 | 422 | ||
418 | spin_lock(&efivars_lock); | 423 | spin_lock(&efivars->lock); |
419 | 424 | ||
420 | /* | 425 | /* |
421 | * Does this variable already exist? | 426 | * Does this variable already exist? |
422 | */ | 427 | */ |
423 | list_for_each_entry_safe(search_efivar, n, &efivar_list, list) { | 428 | list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { |
424 | strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024); | 429 | strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024); |
425 | strsize2 = utf8_strsize(new_var->VariableName, 1024); | 430 | strsize2 = utf8_strsize(new_var->VariableName, 1024); |
426 | if (strsize1 == strsize2 && | 431 | if (strsize1 == strsize2 && |
@@ -433,7 +438,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
433 | } | 438 | } |
434 | } | 439 | } |
435 | if (found) { | 440 | if (found) { |
436 | spin_unlock(&efivars_lock); | 441 | spin_unlock(&efivars->lock); |
437 | return -EINVAL; | 442 | return -EINVAL; |
438 | } | 443 | } |
439 | 444 | ||
@@ -447,10 +452,10 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
447 | if (status != EFI_SUCCESS) { | 452 | if (status != EFI_SUCCESS) { |
448 | printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", | 453 | printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", |
449 | status); | 454 | status); |
450 | spin_unlock(&efivars_lock); | 455 | spin_unlock(&efivars->lock); |
451 | return -EIO; | 456 | return -EIO; |
452 | } | 457 | } |
453 | spin_unlock(&efivars_lock); | 458 | spin_unlock(&efivars->lock); |
454 | 459 | ||
455 | /* Create the entry in sysfs. Locking is not required here */ | 460 | /* Create the entry in sysfs. Locking is not required here */ |
456 | status = efivar_create_sysfs_entry(utf8_strsize(new_var->VariableName, | 461 | status = efivar_create_sysfs_entry(utf8_strsize(new_var->VariableName, |
@@ -474,12 +479,12 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, | |||
474 | if (!capable(CAP_SYS_ADMIN)) | 479 | if (!capable(CAP_SYS_ADMIN)) |
475 | return -EACCES; | 480 | return -EACCES; |
476 | 481 | ||
477 | spin_lock(&efivars_lock); | 482 | spin_lock(&efivars->lock); |
478 | 483 | ||
479 | /* | 484 | /* |
480 | * Does this variable already exist? | 485 | * Does this variable already exist? |
481 | */ | 486 | */ |
482 | list_for_each_entry_safe(search_efivar, n, &efivar_list, list) { | 487 | list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { |
483 | strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024); | 488 | strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024); |
484 | strsize2 = utf8_strsize(del_var->VariableName, 1024); | 489 | strsize2 = utf8_strsize(del_var->VariableName, 1024); |
485 | if (strsize1 == strsize2 && | 490 | if (strsize1 == strsize2 && |
@@ -492,7 +497,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, | |||
492 | } | 497 | } |
493 | } | 498 | } |
494 | if (!found) { | 499 | if (!found) { |
495 | spin_unlock(&efivars_lock); | 500 | spin_unlock(&efivars->lock); |
496 | return -EINVAL; | 501 | return -EINVAL; |
497 | } | 502 | } |
498 | /* force the Attributes/DataSize to 0 to ensure deletion */ | 503 | /* force the Attributes/DataSize to 0 to ensure deletion */ |
@@ -508,12 +513,12 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, | |||
508 | if (status != EFI_SUCCESS) { | 513 | if (status != EFI_SUCCESS) { |
509 | printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", | 514 | printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n", |
510 | status); | 515 | status); |
511 | spin_unlock(&efivars_lock); | 516 | spin_unlock(&efivars->lock); |
512 | return -EIO; | 517 | return -EIO; |
513 | } | 518 | } |
514 | list_del(&search_efivar->list); | 519 | list_del(&search_efivar->list); |
515 | /* We need to release this lock before unregistering. */ | 520 | /* We need to release this lock before unregistering. */ |
516 | spin_unlock(&efivars_lock); | 521 | spin_unlock(&efivars->lock); |
517 | efivar_unregister(search_efivar); | 522 | efivar_unregister(search_efivar); |
518 | 523 | ||
519 | /* It's dead Jim.... */ | 524 | /* It's dead Jim.... */ |
@@ -572,8 +577,6 @@ static struct attribute_group efi_subsys_attr_group = { | |||
572 | .attrs = efi_subsys_attrs, | 577 | .attrs = efi_subsys_attrs, |
573 | }; | 578 | }; |
574 | 579 | ||
575 | |||
576 | static struct kset *vars_kset; | ||
577 | static struct kobject *efi_kobj; | 580 | static struct kobject *efi_kobj; |
578 | 581 | ||
579 | /* | 582 | /* |
@@ -582,7 +585,7 @@ static struct kobject *efi_kobj; | |||
582 | * variable_name_size = number of bytes required to hold | 585 | * variable_name_size = number of bytes required to hold |
583 | * variable_name (not counting the NULL | 586 | * variable_name (not counting the NULL |
584 | * character at the end. | 587 | * character at the end. |
585 | * efivars_lock is not held on entry or exit. | 588 | * efivars->lock is not held on entry or exit. |
586 | * Returns 1 on failure, 0 on success | 589 | * Returns 1 on failure, 0 on success |
587 | */ | 590 | */ |
588 | static int | 591 | static int |
@@ -618,7 +621,7 @@ efivar_create_sysfs_entry(unsigned long variable_name_size, | |||
618 | *(short_name + strlen(short_name)) = '-'; | 621 | *(short_name + strlen(short_name)) = '-'; |
619 | efi_guid_unparse(vendor_guid, short_name + strlen(short_name)); | 622 | efi_guid_unparse(vendor_guid, short_name + strlen(short_name)); |
620 | 623 | ||
621 | new_efivar->kobj.kset = vars_kset; | 624 | new_efivar->kobj.kset = efivars->kset; |
622 | i = kobject_init_and_add(&new_efivar->kobj, &efivar_ktype, NULL, | 625 | i = kobject_init_and_add(&new_efivar->kobj, &efivar_ktype, NULL, |
623 | "%s", short_name); | 626 | "%s", short_name); |
624 | if (i) { | 627 | if (i) { |
@@ -631,9 +634,9 @@ efivar_create_sysfs_entry(unsigned long variable_name_size, | |||
631 | kfree(short_name); | 634 | kfree(short_name); |
632 | short_name = NULL; | 635 | short_name = NULL; |
633 | 636 | ||
634 | spin_lock(&efivars_lock); | 637 | spin_lock(&efivars->lock); |
635 | list_add(&new_efivar->list, &efivar_list); | 638 | list_add(&new_efivar->list, &efivars->list); |
636 | spin_unlock(&efivars_lock); | 639 | spin_unlock(&efivars->lock); |
637 | 640 | ||
638 | return 0; | 641 | return 0; |
639 | } | 642 | } |
@@ -674,8 +677,11 @@ efivars_init(void) | |||
674 | goto out_free; | 677 | goto out_free; |
675 | } | 678 | } |
676 | 679 | ||
677 | vars_kset = kset_create_and_add("vars", NULL, efi_kobj); | 680 | spin_lock_init(&efivars->lock); |
678 | if (!vars_kset) { | 681 | INIT_LIST_HEAD(&efivars->list); |
682 | |||
683 | efivars->kset = kset_create_and_add("vars", NULL, efi_kobj); | ||
684 | if (!efivars->kset) { | ||
679 | printk(KERN_ERR "efivars: Subsystem registration failed.\n"); | 685 | printk(KERN_ERR "efivars: Subsystem registration failed.\n"); |
680 | error = -ENOMEM; | 686 | error = -ENOMEM; |
681 | goto out_firmware_unregister; | 687 | goto out_firmware_unregister; |
@@ -712,12 +718,12 @@ efivars_init(void) | |||
712 | * Now add attributes to allow creation of new vars | 718 | * Now add attributes to allow creation of new vars |
713 | * and deletion of existing ones... | 719 | * and deletion of existing ones... |
714 | */ | 720 | */ |
715 | error = sysfs_create_bin_file(&vars_kset->kobj, | 721 | error = sysfs_create_bin_file(&efivars->kset->kobj, |
716 | &var_subsys_attr_new_var); | 722 | &var_subsys_attr_new_var); |
717 | if (error) | 723 | if (error) |
718 | printk(KERN_ERR "efivars: unable to create new_var sysfs file" | 724 | printk(KERN_ERR "efivars: unable to create new_var sysfs file" |
719 | " due to error %d\n", error); | 725 | " due to error %d\n", error); |
720 | error = sysfs_create_bin_file(&vars_kset->kobj, | 726 | error = sysfs_create_bin_file(&efivars->kset->kobj, |
721 | &var_subsys_attr_del_var); | 727 | &var_subsys_attr_del_var); |
722 | if (error) | 728 | if (error) |
723 | printk(KERN_ERR "efivars: unable to create del_var sysfs file" | 729 | printk(KERN_ERR "efivars: unable to create del_var sysfs file" |
@@ -730,7 +736,7 @@ efivars_init(void) | |||
730 | else | 736 | else |
731 | goto out_free; | 737 | goto out_free; |
732 | 738 | ||
733 | kset_unregister(vars_kset); | 739 | kset_unregister(efivars->kset); |
734 | 740 | ||
735 | out_firmware_unregister: | 741 | out_firmware_unregister: |
736 | kobject_put(efi_kobj); | 742 | kobject_put(efi_kobj); |
@@ -746,14 +752,14 @@ efivars_exit(void) | |||
746 | { | 752 | { |
747 | struct efivar_entry *entry, *n; | 753 | struct efivar_entry *entry, *n; |
748 | 754 | ||
749 | list_for_each_entry_safe(entry, n, &efivar_list, list) { | 755 | list_for_each_entry_safe(entry, n, &efivars->list, list) { |
750 | spin_lock(&efivars_lock); | 756 | spin_lock(&efivars->lock); |
751 | list_del(&entry->list); | 757 | list_del(&entry->list); |
752 | spin_unlock(&efivars_lock); | 758 | spin_unlock(&efivars->lock); |
753 | efivar_unregister(entry); | 759 | efivar_unregister(entry); |
754 | } | 760 | } |
755 | 761 | ||
756 | kset_unregister(vars_kset); | 762 | kset_unregister(efivars->kset); |
757 | kobject_put(efi_kobj); | 763 | kobject_put(efi_kobj); |
758 | } | 764 | } |
759 | 765 | ||