162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2006 Matthew Wilcox <matthew@wil.cx> 462306a36Sopenharmony_ci * Copyright (C) 2006-2009 Hewlett-Packard Development Company, L.P. 562306a36Sopenharmony_ci * Alex Chiang <achiang@hp.com> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/kobject.h> 962306a36Sopenharmony_ci#include <linux/slab.h> 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/pci.h> 1262306a36Sopenharmony_ci#include <linux/err.h> 1362306a36Sopenharmony_ci#include "pci.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistruct kset *pci_slots_kset; 1662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_slots_kset); 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic ssize_t pci_slot_attr_show(struct kobject *kobj, 1962306a36Sopenharmony_ci struct attribute *attr, char *buf) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci struct pci_slot *slot = to_pci_slot(kobj); 2262306a36Sopenharmony_ci struct pci_slot_attribute *attribute = to_pci_slot_attr(attr); 2362306a36Sopenharmony_ci return attribute->show ? attribute->show(slot, buf) : -EIO; 2462306a36Sopenharmony_ci} 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic ssize_t pci_slot_attr_store(struct kobject *kobj, 2762306a36Sopenharmony_ci struct attribute *attr, const char *buf, size_t len) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci struct pci_slot *slot = to_pci_slot(kobj); 3062306a36Sopenharmony_ci struct pci_slot_attribute *attribute = to_pci_slot_attr(attr); 3162306a36Sopenharmony_ci return attribute->store ? attribute->store(slot, buf, len) : -EIO; 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic const struct sysfs_ops pci_slot_sysfs_ops = { 3562306a36Sopenharmony_ci .show = pci_slot_attr_show, 3662306a36Sopenharmony_ci .store = pci_slot_attr_store, 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic ssize_t address_read_file(struct pci_slot *slot, char *buf) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci if (slot->number == 0xff) 4262306a36Sopenharmony_ci return sysfs_emit(buf, "%04x:%02x\n", 4362306a36Sopenharmony_ci pci_domain_nr(slot->bus), 4462306a36Sopenharmony_ci slot->bus->number); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci return sysfs_emit(buf, "%04x:%02x:%02x\n", 4762306a36Sopenharmony_ci pci_domain_nr(slot->bus), 4862306a36Sopenharmony_ci slot->bus->number, 4962306a36Sopenharmony_ci slot->number); 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", pci_speed_string(speed)); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic ssize_t max_speed_read_file(struct pci_slot *slot, char *buf) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci return bus_speed_read(slot->bus->max_bus_speed, buf); 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci return bus_speed_read(slot->bus->cur_bus_speed, buf); 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic void pci_slot_release(struct kobject *kobj) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci struct pci_dev *dev; 7062306a36Sopenharmony_ci struct pci_slot *slot = to_pci_slot(kobj); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci dev_dbg(&slot->bus->dev, "dev %02x, released physical slot %s\n", 7362306a36Sopenharmony_ci slot->number, pci_slot_name(slot)); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci down_read(&pci_bus_sem); 7662306a36Sopenharmony_ci list_for_each_entry(dev, &slot->bus->devices, bus_list) 7762306a36Sopenharmony_ci if (PCI_SLOT(dev->devfn) == slot->number) 7862306a36Sopenharmony_ci dev->slot = NULL; 7962306a36Sopenharmony_ci up_read(&pci_bus_sem); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci list_del(&slot->list); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci kfree(slot); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic struct pci_slot_attribute pci_slot_attr_address = 8762306a36Sopenharmony_ci __ATTR(address, S_IRUGO, address_read_file, NULL); 8862306a36Sopenharmony_cistatic struct pci_slot_attribute pci_slot_attr_max_speed = 8962306a36Sopenharmony_ci __ATTR(max_bus_speed, S_IRUGO, max_speed_read_file, NULL); 9062306a36Sopenharmony_cistatic struct pci_slot_attribute pci_slot_attr_cur_speed = 9162306a36Sopenharmony_ci __ATTR(cur_bus_speed, S_IRUGO, cur_speed_read_file, NULL); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic struct attribute *pci_slot_default_attrs[] = { 9462306a36Sopenharmony_ci &pci_slot_attr_address.attr, 9562306a36Sopenharmony_ci &pci_slot_attr_max_speed.attr, 9662306a36Sopenharmony_ci &pci_slot_attr_cur_speed.attr, 9762306a36Sopenharmony_ci NULL, 9862306a36Sopenharmony_ci}; 9962306a36Sopenharmony_ciATTRIBUTE_GROUPS(pci_slot_default); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic const struct kobj_type pci_slot_ktype = { 10262306a36Sopenharmony_ci .sysfs_ops = &pci_slot_sysfs_ops, 10362306a36Sopenharmony_ci .release = &pci_slot_release, 10462306a36Sopenharmony_ci .default_groups = pci_slot_default_groups, 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic char *make_slot_name(const char *name) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci char *new_name; 11062306a36Sopenharmony_ci int len, max, dup; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci new_name = kstrdup(name, GFP_KERNEL); 11362306a36Sopenharmony_ci if (!new_name) 11462306a36Sopenharmony_ci return NULL; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci /* 11762306a36Sopenharmony_ci * Make sure we hit the realloc case the first time through the 11862306a36Sopenharmony_ci * loop. 'len' will be strlen(name) + 3 at that point which is 11962306a36Sopenharmony_ci * enough space for "name-X" and the trailing NUL. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ci len = strlen(name) + 2; 12262306a36Sopenharmony_ci max = 1; 12362306a36Sopenharmony_ci dup = 1; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci for (;;) { 12662306a36Sopenharmony_ci struct kobject *dup_slot; 12762306a36Sopenharmony_ci dup_slot = kset_find_obj(pci_slots_kset, new_name); 12862306a36Sopenharmony_ci if (!dup_slot) 12962306a36Sopenharmony_ci break; 13062306a36Sopenharmony_ci kobject_put(dup_slot); 13162306a36Sopenharmony_ci if (dup == max) { 13262306a36Sopenharmony_ci len++; 13362306a36Sopenharmony_ci max *= 10; 13462306a36Sopenharmony_ci kfree(new_name); 13562306a36Sopenharmony_ci new_name = kmalloc(len, GFP_KERNEL); 13662306a36Sopenharmony_ci if (!new_name) 13762306a36Sopenharmony_ci break; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci sprintf(new_name, "%s-%d", name, dup++); 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return new_name; 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic int rename_slot(struct pci_slot *slot, const char *name) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci int result = 0; 14862306a36Sopenharmony_ci char *slot_name; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (strcmp(pci_slot_name(slot), name) == 0) 15162306a36Sopenharmony_ci return result; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci slot_name = make_slot_name(name); 15462306a36Sopenharmony_ci if (!slot_name) 15562306a36Sopenharmony_ci return -ENOMEM; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci result = kobject_rename(&slot->kobj, slot_name); 15862306a36Sopenharmony_ci kfree(slot_name); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci return result; 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_civoid pci_dev_assign_slot(struct pci_dev *dev) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci struct pci_slot *slot; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci mutex_lock(&pci_slot_mutex); 16862306a36Sopenharmony_ci list_for_each_entry(slot, &dev->bus->slots, list) 16962306a36Sopenharmony_ci if (PCI_SLOT(dev->devfn) == slot->number) 17062306a36Sopenharmony_ci dev->slot = slot; 17162306a36Sopenharmony_ci mutex_unlock(&pci_slot_mutex); 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic struct pci_slot *get_slot(struct pci_bus *parent, int slot_nr) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci struct pci_slot *slot; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci /* We already hold pci_slot_mutex */ 17962306a36Sopenharmony_ci list_for_each_entry(slot, &parent->slots, list) 18062306a36Sopenharmony_ci if (slot->number == slot_nr) { 18162306a36Sopenharmony_ci kobject_get(&slot->kobj); 18262306a36Sopenharmony_ci return slot; 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci return NULL; 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci/** 18962306a36Sopenharmony_ci * pci_create_slot - create or increment refcount for physical PCI slot 19062306a36Sopenharmony_ci * @parent: struct pci_bus of parent bridge 19162306a36Sopenharmony_ci * @slot_nr: PCI_SLOT(pci_dev->devfn) or -1 for placeholder 19262306a36Sopenharmony_ci * @name: user visible string presented in /sys/bus/pci/slots/<name> 19362306a36Sopenharmony_ci * @hotplug: set if caller is hotplug driver, NULL otherwise 19462306a36Sopenharmony_ci * 19562306a36Sopenharmony_ci * PCI slots have first class attributes such as address, speed, width, 19662306a36Sopenharmony_ci * and a &struct pci_slot is used to manage them. This interface will 19762306a36Sopenharmony_ci * either return a new &struct pci_slot to the caller, or if the pci_slot 19862306a36Sopenharmony_ci * already exists, its refcount will be incremented. 19962306a36Sopenharmony_ci * 20062306a36Sopenharmony_ci * Slots are uniquely identified by a @pci_bus, @slot_nr tuple. 20162306a36Sopenharmony_ci * 20262306a36Sopenharmony_ci * There are known platforms with broken firmware that assign the same 20362306a36Sopenharmony_ci * name to multiple slots. Workaround these broken platforms by renaming 20462306a36Sopenharmony_ci * the slots on behalf of the caller. If firmware assigns name N to 20562306a36Sopenharmony_ci * multiple slots: 20662306a36Sopenharmony_ci * 20762306a36Sopenharmony_ci * The first slot is assigned N 20862306a36Sopenharmony_ci * The second slot is assigned N-1 20962306a36Sopenharmony_ci * The third slot is assigned N-2 21062306a36Sopenharmony_ci * etc. 21162306a36Sopenharmony_ci * 21262306a36Sopenharmony_ci * Placeholder slots: 21362306a36Sopenharmony_ci * In most cases, @pci_bus, @slot_nr will be sufficient to uniquely identify 21462306a36Sopenharmony_ci * a slot. There is one notable exception - pSeries (rpaphp), where the 21562306a36Sopenharmony_ci * @slot_nr cannot be determined until a device is actually inserted into 21662306a36Sopenharmony_ci * the slot. In this scenario, the caller may pass -1 for @slot_nr. 21762306a36Sopenharmony_ci * 21862306a36Sopenharmony_ci * The following semantics are imposed when the caller passes @slot_nr == 21962306a36Sopenharmony_ci * -1. First, we no longer check for an existing %struct pci_slot, as there 22062306a36Sopenharmony_ci * may be many slots with @slot_nr of -1. The other change in semantics is 22162306a36Sopenharmony_ci * user-visible, which is the 'address' parameter presented in sysfs will 22262306a36Sopenharmony_ci * consist solely of a dddd:bb tuple, where dddd is the PCI domain of the 22362306a36Sopenharmony_ci * %struct pci_bus and bb is the bus number. In other words, the devfn of 22462306a36Sopenharmony_ci * the 'placeholder' slot will not be displayed. 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_cistruct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, 22762306a36Sopenharmony_ci const char *name, 22862306a36Sopenharmony_ci struct hotplug_slot *hotplug) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci struct pci_dev *dev; 23162306a36Sopenharmony_ci struct pci_slot *slot; 23262306a36Sopenharmony_ci int err = 0; 23362306a36Sopenharmony_ci char *slot_name = NULL; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci mutex_lock(&pci_slot_mutex); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci if (slot_nr == -1) 23862306a36Sopenharmony_ci goto placeholder; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci /* 24162306a36Sopenharmony_ci * Hotplug drivers are allowed to rename an existing slot, 24262306a36Sopenharmony_ci * but only if not already claimed. 24362306a36Sopenharmony_ci */ 24462306a36Sopenharmony_ci slot = get_slot(parent, slot_nr); 24562306a36Sopenharmony_ci if (slot) { 24662306a36Sopenharmony_ci if (hotplug) { 24762306a36Sopenharmony_ci if ((err = slot->hotplug ? -EBUSY : 0) 24862306a36Sopenharmony_ci || (err = rename_slot(slot, name))) { 24962306a36Sopenharmony_ci kobject_put(&slot->kobj); 25062306a36Sopenharmony_ci slot = NULL; 25162306a36Sopenharmony_ci goto err; 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci goto out; 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ciplaceholder: 25862306a36Sopenharmony_ci slot = kzalloc(sizeof(*slot), GFP_KERNEL); 25962306a36Sopenharmony_ci if (!slot) { 26062306a36Sopenharmony_ci err = -ENOMEM; 26162306a36Sopenharmony_ci goto err; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci slot->bus = parent; 26562306a36Sopenharmony_ci slot->number = slot_nr; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci slot->kobj.kset = pci_slots_kset; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci slot_name = make_slot_name(name); 27062306a36Sopenharmony_ci if (!slot_name) { 27162306a36Sopenharmony_ci err = -ENOMEM; 27262306a36Sopenharmony_ci kfree(slot); 27362306a36Sopenharmony_ci goto err; 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci INIT_LIST_HEAD(&slot->list); 27762306a36Sopenharmony_ci list_add(&slot->list, &parent->slots); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL, 28062306a36Sopenharmony_ci "%s", slot_name); 28162306a36Sopenharmony_ci if (err) { 28262306a36Sopenharmony_ci kobject_put(&slot->kobj); 28362306a36Sopenharmony_ci goto err; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci down_read(&pci_bus_sem); 28762306a36Sopenharmony_ci list_for_each_entry(dev, &parent->devices, bus_list) 28862306a36Sopenharmony_ci if (PCI_SLOT(dev->devfn) == slot_nr) 28962306a36Sopenharmony_ci dev->slot = slot; 29062306a36Sopenharmony_ci up_read(&pci_bus_sem); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci dev_dbg(&parent->dev, "dev %02x, created physical slot %s\n", 29362306a36Sopenharmony_ci slot_nr, pci_slot_name(slot)); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ciout: 29662306a36Sopenharmony_ci kfree(slot_name); 29762306a36Sopenharmony_ci mutex_unlock(&pci_slot_mutex); 29862306a36Sopenharmony_ci return slot; 29962306a36Sopenharmony_cierr: 30062306a36Sopenharmony_ci slot = ERR_PTR(err); 30162306a36Sopenharmony_ci goto out; 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_create_slot); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci/** 30662306a36Sopenharmony_ci * pci_destroy_slot - decrement refcount for physical PCI slot 30762306a36Sopenharmony_ci * @slot: struct pci_slot to decrement 30862306a36Sopenharmony_ci * 30962306a36Sopenharmony_ci * %struct pci_slot is refcounted, so destroying them is really easy; we 31062306a36Sopenharmony_ci * just call kobject_put on its kobj and let our release methods do the 31162306a36Sopenharmony_ci * rest. 31262306a36Sopenharmony_ci */ 31362306a36Sopenharmony_civoid pci_destroy_slot(struct pci_slot *slot) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci dev_dbg(&slot->bus->dev, "dev %02x, dec refcount to %d\n", 31662306a36Sopenharmony_ci slot->number, kref_read(&slot->kobj.kref) - 1); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci mutex_lock(&pci_slot_mutex); 31962306a36Sopenharmony_ci kobject_put(&slot->kobj); 32062306a36Sopenharmony_ci mutex_unlock(&pci_slot_mutex); 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_destroy_slot); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE) 32562306a36Sopenharmony_ci#include <linux/pci_hotplug.h> 32662306a36Sopenharmony_ci/** 32762306a36Sopenharmony_ci * pci_hp_create_module_link - create symbolic link to hotplug driver module 32862306a36Sopenharmony_ci * @pci_slot: struct pci_slot 32962306a36Sopenharmony_ci * 33062306a36Sopenharmony_ci * Helper function for pci_hotplug_core.c to create symbolic link to 33162306a36Sopenharmony_ci * the hotplug driver module. 33262306a36Sopenharmony_ci */ 33362306a36Sopenharmony_civoid pci_hp_create_module_link(struct pci_slot *pci_slot) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci struct hotplug_slot *slot = pci_slot->hotplug; 33662306a36Sopenharmony_ci struct kobject *kobj = NULL; 33762306a36Sopenharmony_ci int ret; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci if (!slot || !slot->ops) 34062306a36Sopenharmony_ci return; 34162306a36Sopenharmony_ci kobj = kset_find_obj(module_kset, slot->mod_name); 34262306a36Sopenharmony_ci if (!kobj) 34362306a36Sopenharmony_ci return; 34462306a36Sopenharmony_ci ret = sysfs_create_link(&pci_slot->kobj, kobj, "module"); 34562306a36Sopenharmony_ci if (ret) 34662306a36Sopenharmony_ci dev_err(&pci_slot->bus->dev, "Error creating sysfs link (%d)\n", 34762306a36Sopenharmony_ci ret); 34862306a36Sopenharmony_ci kobject_put(kobj); 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_hp_create_module_link); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci/** 35362306a36Sopenharmony_ci * pci_hp_remove_module_link - remove symbolic link to the hotplug driver 35462306a36Sopenharmony_ci * module. 35562306a36Sopenharmony_ci * @pci_slot: struct pci_slot 35662306a36Sopenharmony_ci * 35762306a36Sopenharmony_ci * Helper function for pci_hotplug_core.c to remove symbolic link to 35862306a36Sopenharmony_ci * the hotplug driver module. 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_civoid pci_hp_remove_module_link(struct pci_slot *pci_slot) 36162306a36Sopenharmony_ci{ 36262306a36Sopenharmony_ci sysfs_remove_link(&pci_slot->kobj, "module"); 36362306a36Sopenharmony_ci} 36462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_hp_remove_module_link); 36562306a36Sopenharmony_ci#endif 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic int pci_slot_init(void) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci struct kset *pci_bus_kset; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci pci_bus_kset = bus_get_kset(&pci_bus_type); 37262306a36Sopenharmony_ci pci_slots_kset = kset_create_and_add("slots", NULL, 37362306a36Sopenharmony_ci &pci_bus_kset->kobj); 37462306a36Sopenharmony_ci if (!pci_slots_kset) { 37562306a36Sopenharmony_ci pr_err("PCI: Slot initialization failure\n"); 37662306a36Sopenharmony_ci return -ENOMEM; 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci return 0; 37962306a36Sopenharmony_ci} 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_cisubsys_initcall(pci_slot_init); 382