Skip to content

Commit

Permalink
efivars: Split out variable registration
Browse files Browse the repository at this point in the history
In anticipation of re-using the variable facilities in efivars from
elsewhere, split out the registration and unregistration of struct
efivars from the rest of the EFI specific sysfs code.

Signed-off-by: Mike Waychison <mikew@google.com>
Cc: Matt Domsch <Matt_Domsch@dell.com>,
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Mike Waychison authored and Greg Kroah-Hartman committed Mar 14, 2011
1 parent 4142ef1 commit 76b53f7
Showing 1 changed file with 67 additions and 55 deletions.
122 changes: 67 additions & 55 deletions drivers/firmware/efivars.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ struct efivars {
* 1) ->list - adds, removals, reads, writes
* 2) efi.[gs]et_variable() calls.
* It must not be held when creating sysfs entries or calling kmalloc.
* efi.get_next_variable() is only called from efivars_init(),
* efi.get_next_variable() is only called from register_efivars(),
* which is protected by the BKL, so that path is safe.
*/
spinlock_t lock;
Expand Down Expand Up @@ -699,54 +699,48 @@ create_efivars_bin_attributes(struct efivars *efivars)
return error;
}

static struct efivars __efivars;
static void unregister_efivars(struct efivars *efivars)
{
struct efivar_entry *entry, *n;

/*
* For now we register the efi subsystem with the firmware subsystem
* and the vars subsystem with the efi subsystem. In the future, it
* might make sense to split off the efi subsystem into its own
* driver, but for now only efivars will register with it, so just
* include it here.
*/
list_for_each_entry_safe(entry, n, &efivars->list, list) {
spin_lock(&efivars->lock);
list_del(&entry->list);
spin_unlock(&efivars->lock);
efivar_unregister(entry);
}
if (efivars->new_var)
sysfs_remove_bin_file(&efivars->kset->kobj, efivars->new_var);
if (efivars->del_var)
sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var);
kfree(efivars->new_var);
kfree(efivars->del_var);
kset_unregister(efivars->kset);
}

static int __init
efivars_init(void)
static int register_efivars(struct efivars *efivars,
struct kobject *parent_kobj)
{
efi_status_t status = EFI_NOT_FOUND;
efi_guid_t vendor_guid;
efi_char16_t *variable_name;
unsigned long variable_name_size = 1024;
struct efivars *efivars = &__efivars;
int error = 0;

if (!efi_enabled)
return -ENODEV;

variable_name = kzalloc(variable_name_size, GFP_KERNEL);
if (!variable_name) {
printk(KERN_ERR "efivars: Memory allocation failed.\n");
return -ENOMEM;
}

printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
EFIVARS_DATE);

/* For now we'll register the efi directory at /sys/firmware/efi */
efi_kobj = kobject_create_and_add("efi", firmware_kobj);
if (!efi_kobj) {
printk(KERN_ERR "efivars: Firmware registration failed.\n");
error = -ENOMEM;
goto out_free;
}

spin_lock_init(&efivars->lock);
INIT_LIST_HEAD(&efivars->list);

efivars->kset = kset_create_and_add("vars", NULL, efi_kobj);
efivars->kset = kset_create_and_add("vars", NULL, parent_kobj);
if (!efivars->kset) {
printk(KERN_ERR "efivars: Subsystem registration failed.\n");
error = -ENOMEM;
goto out_firmware_unregister;
goto out;
}

/*
Expand Down Expand Up @@ -778,44 +772,62 @@ efivars_init(void)
} while (status != EFI_NOT_FOUND);

error = create_efivars_bin_attributes(efivars);

/* Don't forget the systab entry */
error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
if (error)
printk(KERN_ERR "efivars: Sysfs attribute export failed with error %d.\n", error);
else
goto out_free;
unregister_efivars(efivars);

kset_unregister(efivars->kset);
out:
kfree(variable_name);

out_firmware_unregister:
kobject_put(efi_kobj);
return error;
}

out_free:
kfree(variable_name);
static struct efivars __efivars;

/*
* For now we register the efi subsystem with the firmware subsystem
* and the vars subsystem with the efi subsystem. In the future, it
* might make sense to split off the efi subsystem into its own
* driver, but for now only efivars will register with it, so just
* include it here.
*/

static int __init
efivars_init(void)
{
int error = 0;

printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
EFIVARS_DATE);

if (!efi_enabled)
return -ENODEV;

/* For now we'll register the efi directory at /sys/firmware/efi */
efi_kobj = kobject_create_and_add("efi", firmware_kobj);
if (!efi_kobj) {
printk(KERN_ERR "efivars: Firmware registration failed.\n");
return -ENOMEM;
}

error = register_efivars(&__efivars, efi_kobj);

/* Don't forget the systab entry */
error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
if (error) {
printk(KERN_ERR
"efivars: Sysfs attribute export failed with error %d.\n",
error);
unregister_efivars(&__efivars);
kobject_put(efi_kobj);
}

return error;
}

static void __exit
efivars_exit(void)
{
struct efivars *efivars = &__efivars;
struct efivar_entry *entry, *n;

list_for_each_entry_safe(entry, n, &efivars->list, list) {
spin_lock(&efivars->lock);
list_del(&entry->list);
spin_unlock(&efivars->lock);
efivar_unregister(entry);
}
if (efivars->new_var)
sysfs_remove_bin_file(&efivars->kset->kobj, efivars->new_var);
if (efivars->del_var)
sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var);
kfree(efivars->new_var);
kfree(efivars->del_var);
kset_unregister(efivars->kset);
unregister_efivars(&__efivars);
kobject_put(efi_kobj);
}

Expand Down

0 comments on commit 76b53f7

Please sign in to comment.