^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Interface for Dynamic Logical Partitioning of I/O Slots on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * RPA-compliant PPC64 platform.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * John Rose <johnrose@austin.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * October 2003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2003 IBM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/pci_hotplug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "rpaphp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "rpadlpar.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "../pci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define DLPAR_KOBJ_NAME "control"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* Those two have no quotes because they are passed to __ATTR() which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * stringifies the argument (yuck !)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define ADD_SLOT_ATTR_NAME add_slot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define REMOVE_SLOT_ATTR_NAME remove_slot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) const char *buf, size_t nbytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) char drc_name[MAX_DRC_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (nbytes >= MAX_DRC_NAME_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) strscpy(drc_name, buf, nbytes + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) end = strchr(drc_name, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *end = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) rc = dlpar_add_slot(drc_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return nbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static ssize_t add_slot_show(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct kobj_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return sprintf(buf, "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static ssize_t remove_slot_store(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct kobj_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) const char *buf, size_t nbytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) char drc_name[MAX_DRC_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (nbytes >= MAX_DRC_NAME_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) strscpy(drc_name, buf, nbytes + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) end = strchr(drc_name, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) *end = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) rc = dlpar_remove_slot(drc_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return nbytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static ssize_t remove_slot_show(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct kobj_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return sprintf(buf, "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static struct kobj_attribute add_slot_attr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) __ATTR(ADD_SLOT_ATTR_NAME, 0644, add_slot_show, add_slot_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static struct kobj_attribute remove_slot_attr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) __ATTR(REMOVE_SLOT_ATTR_NAME, 0644, remove_slot_show, remove_slot_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static struct attribute *default_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) &add_slot_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) &remove_slot_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static const struct attribute_group dlpar_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .attrs = default_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static struct kobject *dlpar_kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int dlpar_sysfs_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) dlpar_kobj = kobject_create_and_add(DLPAR_KOBJ_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) &pci_slots_kset->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (!dlpar_kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) error = sysfs_create_group(dlpar_kobj, &dlpar_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) kobject_put(dlpar_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) void dlpar_sysfs_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) sysfs_remove_group(dlpar_kobj, &dlpar_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) kobject_put(dlpar_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }