diff options
Diffstat (limited to 'drivers/pci/hotplug/rpadlpar_sysfs.c')
-rw-r--r-- | drivers/pci/hotplug/rpadlpar_sysfs.c | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c new file mode 100644 index 00000000000..3285b822478 --- /dev/null +++ b/drivers/pci/hotplug/rpadlpar_sysfs.c @@ -0,0 +1,151 @@ +/* + * Interface for Dynamic Logical Partitioning of I/O Slots on + * RPA-compliant PPC64 platform. + * + * John Rose <johnrose@austin.ibm.com> + * October 2003 + * + * Copyright (C) 2003 IBM. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <linux/kobject.h> +#include <linux/string.h> +#include "pci_hotplug.h" +#include "rpadlpar.h" + +#define DLPAR_KOBJ_NAME "control" +#define ADD_SLOT_ATTR_NAME "add_slot" +#define REMOVE_SLOT_ATTR_NAME "remove_slot" + +#define MAX_DRC_NAME_LEN 64 + +/* Store return code of dlpar operation in attribute struct */ +struct dlpar_io_attr { + int rc; + struct attribute attr; + ssize_t (*store)(struct dlpar_io_attr *dlpar_attr, const char *buf, + size_t nbytes); +}; + +/* Common show callback for all attrs, display the return code + * of the dlpar op */ +static ssize_t +dlpar_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) +{ + struct dlpar_io_attr *dlpar_attr = container_of(attr, + struct dlpar_io_attr, attr); + return sprintf(buf, "%d\n", dlpar_attr->rc); +} + +static ssize_t +dlpar_attr_store(struct kobject * kobj, struct attribute * attr, + const char *buf, size_t nbytes) +{ + struct dlpar_io_attr *dlpar_attr = container_of(attr, + struct dlpar_io_attr, attr); + return dlpar_attr->store ? + dlpar_attr->store(dlpar_attr, buf, nbytes) : 0; +} + +static struct sysfs_ops dlpar_attr_sysfs_ops = { + .show = dlpar_attr_show, + .store = dlpar_attr_store, +}; + +static ssize_t add_slot_store(struct dlpar_io_attr *dlpar_attr, + const char *buf, size_t nbytes) +{ + char drc_name[MAX_DRC_NAME_LEN]; + char *end; + + if (nbytes > MAX_DRC_NAME_LEN) + return 0; + + memcpy(drc_name, buf, nbytes); + + end = strchr(drc_name, '\n'); + if (!end) + end = &drc_name[nbytes]; + *end = '\0'; + + dlpar_attr->rc = dlpar_add_slot(drc_name); + + return nbytes; +} + +static ssize_t remove_slot_store(struct dlpar_io_attr *dlpar_attr, + const char *buf, size_t nbytes) +{ + char drc_name[MAX_DRC_NAME_LEN]; + char *end; + + if (nbytes > MAX_DRC_NAME_LEN) + return 0; + + memcpy(drc_name, buf, nbytes); + + end = strchr(drc_name, '\n'); + if (!end) + end = &drc_name[nbytes]; + *end = '\0'; + + dlpar_attr->rc = dlpar_remove_slot(drc_name); + + return nbytes; +} + +static struct dlpar_io_attr add_slot_attr = { + .rc = 0, + .attr = { .name = ADD_SLOT_ATTR_NAME, .mode = 0644, }, + .store = add_slot_store, +}; + +static struct dlpar_io_attr remove_slot_attr = { + .rc = 0, + .attr = { .name = REMOVE_SLOT_ATTR_NAME, .mode = 0644}, + .store = remove_slot_store, +}; + +static struct attribute *default_attrs[] = { + &add_slot_attr.attr, + &remove_slot_attr.attr, + NULL, +}; + +static void dlpar_io_release(struct kobject *kobj) +{ + /* noop */ + return; +} + +struct kobj_type ktype_dlpar_io = { + .release = dlpar_io_release, + .sysfs_ops = &dlpar_attr_sysfs_ops, + .default_attrs = default_attrs, +}; + +struct kset dlpar_io_kset = { + .subsys = &pci_hotplug_slots_subsys, + .kobj = {.name = DLPAR_KOBJ_NAME, .ktype=&ktype_dlpar_io,}, + .ktype = &ktype_dlpar_io, +}; + +int dlpar_sysfs_init(void) +{ + if (kset_register(&dlpar_io_kset)) { + printk(KERN_ERR "rpadlpar_io: cannot register kset for %s\n", + dlpar_io_kset.kobj.name); + return -EINVAL; + } + + return 0; +} + +void dlpar_sysfs_exit(void) +{ + kset_unregister(&dlpar_io_kset); +} |