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 | |
| 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')
| -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 2a62ec6390e..f10ecb6d04b 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 | ||
