17328c8f4SBjorn Helgaas // SPDX-License-Identifier: GPL-2.0
2f46753c5SAlex Chiang /*
3f46753c5SAlex Chiang * Copyright (C) 2006 Matthew Wilcox <matthew@wil.cx>
462795041SAlex Chiang * Copyright (C) 2006-2009 Hewlett-Packard Development Company, L.P.
5f46753c5SAlex Chiang * Alex Chiang <achiang@hp.com>
6f46753c5SAlex Chiang */
7f46753c5SAlex Chiang
8f46753c5SAlex Chiang #include <linux/kobject.h>
95a0e3ad6STejun Heo #include <linux/slab.h>
10eefa9cfcSPaul Gortmaker #include <linux/module.h>
11f46753c5SAlex Chiang #include <linux/pci.h>
12f46753c5SAlex Chiang #include <linux/err.h>
13f46753c5SAlex Chiang #include "pci.h"
14f46753c5SAlex Chiang
15f46753c5SAlex Chiang struct kset *pci_slots_kset;
16f46753c5SAlex Chiang EXPORT_SYMBOL_GPL(pci_slots_kset);
17f46753c5SAlex Chiang
pci_slot_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)18f46753c5SAlex Chiang static ssize_t pci_slot_attr_show(struct kobject *kobj,
19f46753c5SAlex Chiang struct attribute *attr, char *buf)
20f46753c5SAlex Chiang {
21f46753c5SAlex Chiang struct pci_slot *slot = to_pci_slot(kobj);
22f46753c5SAlex Chiang struct pci_slot_attribute *attribute = to_pci_slot_attr(attr);
23f46753c5SAlex Chiang return attribute->show ? attribute->show(slot, buf) : -EIO;
24f46753c5SAlex Chiang }
25f46753c5SAlex Chiang
pci_slot_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t len)26f46753c5SAlex Chiang static ssize_t pci_slot_attr_store(struct kobject *kobj,
27f46753c5SAlex Chiang struct attribute *attr, const char *buf, size_t len)
28f46753c5SAlex Chiang {
29f46753c5SAlex Chiang struct pci_slot *slot = to_pci_slot(kobj);
30f46753c5SAlex Chiang struct pci_slot_attribute *attribute = to_pci_slot_attr(attr);
31f46753c5SAlex Chiang return attribute->store ? attribute->store(slot, buf, len) : -EIO;
32f46753c5SAlex Chiang }
33f46753c5SAlex Chiang
3452cf25d0SEmese Revfy static const struct sysfs_ops pci_slot_sysfs_ops = {
35f46753c5SAlex Chiang .show = pci_slot_attr_show,
36f46753c5SAlex Chiang .store = pci_slot_attr_store,
37f46753c5SAlex Chiang };
38f46753c5SAlex Chiang
address_read_file(struct pci_slot * slot,char * buf)39f46753c5SAlex Chiang static ssize_t address_read_file(struct pci_slot *slot, char *buf)
40f46753c5SAlex Chiang {
41f46753c5SAlex Chiang if (slot->number == 0xff)
42f8cf6e51SKrzysztof Wilczyński return sysfs_emit(buf, "%04x:%02x\n",
43f46753c5SAlex Chiang pci_domain_nr(slot->bus),
44f46753c5SAlex Chiang slot->bus->number);
45f8cf6e51SKrzysztof Wilczyński
46f8cf6e51SKrzysztof Wilczyński return sysfs_emit(buf, "%04x:%02x:%02x\n",
47f46753c5SAlex Chiang pci_domain_nr(slot->bus),
48f46753c5SAlex Chiang slot->bus->number,
49f46753c5SAlex Chiang slot->number);
50f46753c5SAlex Chiang }
51f46753c5SAlex Chiang
bus_speed_read(enum pci_bus_speed speed,char * buf)523749c51aSMatthew Wilcox static ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf)
533749c51aSMatthew Wilcox {
54f8cf6e51SKrzysztof Wilczyński return sysfs_emit(buf, "%s\n", pci_speed_string(speed));
553749c51aSMatthew Wilcox }
563749c51aSMatthew Wilcox
max_speed_read_file(struct pci_slot * slot,char * buf)573749c51aSMatthew Wilcox static ssize_t max_speed_read_file(struct pci_slot *slot, char *buf)
583749c51aSMatthew Wilcox {
593749c51aSMatthew Wilcox return bus_speed_read(slot->bus->max_bus_speed, buf);
603749c51aSMatthew Wilcox }
613749c51aSMatthew Wilcox
cur_speed_read_file(struct pci_slot * slot,char * buf)623749c51aSMatthew Wilcox static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf)
633749c51aSMatthew Wilcox {
643749c51aSMatthew Wilcox return bus_speed_read(slot->bus->cur_bus_speed, buf);
653749c51aSMatthew Wilcox }
663749c51aSMatthew Wilcox
pci_slot_release(struct kobject * kobj)67f46753c5SAlex Chiang static void pci_slot_release(struct kobject *kobj)
68f46753c5SAlex Chiang {
69cef354dbSAlex Chiang struct pci_dev *dev;
70f46753c5SAlex Chiang struct pci_slot *slot = to_pci_slot(kobj);
71f46753c5SAlex Chiang
7262795041SAlex Chiang dev_dbg(&slot->bus->dev, "dev %02x, released physical slot %s\n",
7362795041SAlex Chiang slot->number, pci_slot_name(slot));
74f46753c5SAlex Chiang
7567546762SYijing Wang down_read(&pci_bus_sem);
76cef354dbSAlex Chiang list_for_each_entry(dev, &slot->bus->devices, bus_list)
77cef354dbSAlex Chiang if (PCI_SLOT(dev->devfn) == slot->number)
78cef354dbSAlex Chiang dev->slot = NULL;
7967546762SYijing Wang up_read(&pci_bus_sem);
80cef354dbSAlex Chiang
81f46753c5SAlex Chiang list_del(&slot->list);
82f46753c5SAlex Chiang
83f46753c5SAlex Chiang kfree(slot);
84f46753c5SAlex Chiang }
85f46753c5SAlex Chiang
86f46753c5SAlex Chiang static struct pci_slot_attribute pci_slot_attr_address =
8758f86cc8SRusty Russell __ATTR(address, S_IRUGO, address_read_file, NULL);
883749c51aSMatthew Wilcox static struct pci_slot_attribute pci_slot_attr_max_speed =
8958f86cc8SRusty Russell __ATTR(max_bus_speed, S_IRUGO, max_speed_read_file, NULL);
903749c51aSMatthew Wilcox static struct pci_slot_attribute pci_slot_attr_cur_speed =
9158f86cc8SRusty Russell __ATTR(cur_bus_speed, S_IRUGO, cur_speed_read_file, NULL);
92f46753c5SAlex Chiang
93f46753c5SAlex Chiang static struct attribute *pci_slot_default_attrs[] = {
94f46753c5SAlex Chiang &pci_slot_attr_address.attr,
953749c51aSMatthew Wilcox &pci_slot_attr_max_speed.attr,
963749c51aSMatthew Wilcox &pci_slot_attr_cur_speed.attr,
97f46753c5SAlex Chiang NULL,
98f46753c5SAlex Chiang };
990cf948aaSGreg Kroah-Hartman ATTRIBUTE_GROUPS(pci_slot_default);
100f46753c5SAlex Chiang
101*10473777SThomas Weißschuh static const struct kobj_type pci_slot_ktype = {
102f46753c5SAlex Chiang .sysfs_ops = &pci_slot_sysfs_ops,
103f46753c5SAlex Chiang .release = &pci_slot_release,
1040cf948aaSGreg Kroah-Hartman .default_groups = pci_slot_default_groups,
105f46753c5SAlex Chiang };
106f46753c5SAlex Chiang
make_slot_name(const char * name)1075fe6cc60SAlex Chiang static char *make_slot_name(const char *name)
1085fe6cc60SAlex Chiang {
1095fe6cc60SAlex Chiang char *new_name;
1105fe6cc60SAlex Chiang int len, max, dup;
1115fe6cc60SAlex Chiang
1125fe6cc60SAlex Chiang new_name = kstrdup(name, GFP_KERNEL);
1135fe6cc60SAlex Chiang if (!new_name)
1145fe6cc60SAlex Chiang return NULL;
1155fe6cc60SAlex Chiang
1165fe6cc60SAlex Chiang /*
1175fe6cc60SAlex Chiang * Make sure we hit the realloc case the first time through the
1185fe6cc60SAlex Chiang * loop. 'len' will be strlen(name) + 3 at that point which is
1195fe6cc60SAlex Chiang * enough space for "name-X" and the trailing NUL.
1205fe6cc60SAlex Chiang */
1215fe6cc60SAlex Chiang len = strlen(name) + 2;
1225fe6cc60SAlex Chiang max = 1;
1235fe6cc60SAlex Chiang dup = 1;
1245fe6cc60SAlex Chiang
1255fe6cc60SAlex Chiang for (;;) {
1265fe6cc60SAlex Chiang struct kobject *dup_slot;
1275fe6cc60SAlex Chiang dup_slot = kset_find_obj(pci_slots_kset, new_name);
1285fe6cc60SAlex Chiang if (!dup_slot)
1295fe6cc60SAlex Chiang break;
1305fe6cc60SAlex Chiang kobject_put(dup_slot);
1315fe6cc60SAlex Chiang if (dup == max) {
1325fe6cc60SAlex Chiang len++;
1335fe6cc60SAlex Chiang max *= 10;
1345fe6cc60SAlex Chiang kfree(new_name);
1355fe6cc60SAlex Chiang new_name = kmalloc(len, GFP_KERNEL);
1365fe6cc60SAlex Chiang if (!new_name)
1375fe6cc60SAlex Chiang break;
1385fe6cc60SAlex Chiang }
1395fe6cc60SAlex Chiang sprintf(new_name, "%s-%d", name, dup++);
1405fe6cc60SAlex Chiang }
1415fe6cc60SAlex Chiang
1425fe6cc60SAlex Chiang return new_name;
1435fe6cc60SAlex Chiang }
1445fe6cc60SAlex Chiang
rename_slot(struct pci_slot * slot,const char * name)1455fe6cc60SAlex Chiang static int rename_slot(struct pci_slot *slot, const char *name)
1465fe6cc60SAlex Chiang {
1475fe6cc60SAlex Chiang int result = 0;
1485fe6cc60SAlex Chiang char *slot_name;
1495fe6cc60SAlex Chiang
1500ad772ecSAlex Chiang if (strcmp(pci_slot_name(slot), name) == 0)
1515fe6cc60SAlex Chiang return result;
1525fe6cc60SAlex Chiang
1535fe6cc60SAlex Chiang slot_name = make_slot_name(name);
1545fe6cc60SAlex Chiang if (!slot_name)
1555fe6cc60SAlex Chiang return -ENOMEM;
1565fe6cc60SAlex Chiang
1575fe6cc60SAlex Chiang result = kobject_rename(&slot->kobj, slot_name);
1585fe6cc60SAlex Chiang kfree(slot_name);
1595fe6cc60SAlex Chiang
1605fe6cc60SAlex Chiang return result;
1615fe6cc60SAlex Chiang }
1625fe6cc60SAlex Chiang
pci_dev_assign_slot(struct pci_dev * dev)163017ffe64SYijing Wang void pci_dev_assign_slot(struct pci_dev *dev)
164017ffe64SYijing Wang {
165017ffe64SYijing Wang struct pci_slot *slot;
166017ffe64SYijing Wang
167017ffe64SYijing Wang mutex_lock(&pci_slot_mutex);
168017ffe64SYijing Wang list_for_each_entry(slot, &dev->bus->slots, list)
169017ffe64SYijing Wang if (PCI_SLOT(dev->devfn) == slot->number)
170017ffe64SYijing Wang dev->slot = slot;
171017ffe64SYijing Wang mutex_unlock(&pci_slot_mutex);
172017ffe64SYijing Wang }
173017ffe64SYijing Wang
get_slot(struct pci_bus * parent,int slot_nr)1745fe6cc60SAlex Chiang static struct pci_slot *get_slot(struct pci_bus *parent, int slot_nr)
1755fe6cc60SAlex Chiang {
1765fe6cc60SAlex Chiang struct pci_slot *slot;
17767546762SYijing Wang
17867546762SYijing Wang /* We already hold pci_slot_mutex */
1795fe6cc60SAlex Chiang list_for_each_entry(slot, &parent->slots, list)
1805fe6cc60SAlex Chiang if (slot->number == slot_nr) {
1815fe6cc60SAlex Chiang kobject_get(&slot->kobj);
1825fe6cc60SAlex Chiang return slot;
1835fe6cc60SAlex Chiang }
1845fe6cc60SAlex Chiang
1855fe6cc60SAlex Chiang return NULL;
1865fe6cc60SAlex Chiang }
1875fe6cc60SAlex Chiang
188f46753c5SAlex Chiang /**
189f46753c5SAlex Chiang * pci_create_slot - create or increment refcount for physical PCI slot
190f46753c5SAlex Chiang * @parent: struct pci_bus of parent bridge
191f46753c5SAlex Chiang * @slot_nr: PCI_SLOT(pci_dev->devfn) or -1 for placeholder
192f46753c5SAlex Chiang * @name: user visible string presented in /sys/bus/pci/slots/<name>
193828f3768SAlex Chiang * @hotplug: set if caller is hotplug driver, NULL otherwise
194f46753c5SAlex Chiang *
195f46753c5SAlex Chiang * PCI slots have first class attributes such as address, speed, width,
196f46753c5SAlex Chiang * and a &struct pci_slot is used to manage them. This interface will
197f46753c5SAlex Chiang * either return a new &struct pci_slot to the caller, or if the pci_slot
198f46753c5SAlex Chiang * already exists, its refcount will be incremented.
199f46753c5SAlex Chiang *
2005fe6cc60SAlex Chiang * Slots are uniquely identified by a @pci_bus, @slot_nr tuple.
2015fe6cc60SAlex Chiang *
2025fe6cc60SAlex Chiang * There are known platforms with broken firmware that assign the same
2035fe6cc60SAlex Chiang * name to multiple slots. Workaround these broken platforms by renaming
2045fe6cc60SAlex Chiang * the slots on behalf of the caller. If firmware assigns name N to
2055fe6cc60SAlex Chiang * multiple slots:
2065fe6cc60SAlex Chiang *
2075fe6cc60SAlex Chiang * The first slot is assigned N
2085fe6cc60SAlex Chiang * The second slot is assigned N-1
2095fe6cc60SAlex Chiang * The third slot is assigned N-2
2105fe6cc60SAlex Chiang * etc.
211f46753c5SAlex Chiang *
212f46753c5SAlex Chiang * Placeholder slots:
213f46753c5SAlex Chiang * In most cases, @pci_bus, @slot_nr will be sufficient to uniquely identify
214f46753c5SAlex Chiang * a slot. There is one notable exception - pSeries (rpaphp), where the
215f46753c5SAlex Chiang * @slot_nr cannot be determined until a device is actually inserted into
216f46753c5SAlex Chiang * the slot. In this scenario, the caller may pass -1 for @slot_nr.
217f46753c5SAlex Chiang *
218f46753c5SAlex Chiang * The following semantics are imposed when the caller passes @slot_nr ==
2195fe6cc60SAlex Chiang * -1. First, we no longer check for an existing %struct pci_slot, as there
2205fe6cc60SAlex Chiang * may be many slots with @slot_nr of -1. The other change in semantics is
221f46753c5SAlex Chiang * user-visible, which is the 'address' parameter presented in sysfs will
222f46753c5SAlex Chiang * consist solely of a dddd:bb tuple, where dddd is the PCI domain of the
223f46753c5SAlex Chiang * %struct pci_bus and bb is the bus number. In other words, the devfn of
224f46753c5SAlex Chiang * the 'placeholder' slot will not be displayed.
225f46753c5SAlex Chiang */
pci_create_slot(struct pci_bus * parent,int slot_nr,const char * name,struct hotplug_slot * hotplug)226f46753c5SAlex Chiang struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
227828f3768SAlex Chiang const char *name,
228828f3768SAlex Chiang struct hotplug_slot *hotplug)
229f46753c5SAlex Chiang {
230cef354dbSAlex Chiang struct pci_dev *dev;
231f46753c5SAlex Chiang struct pci_slot *slot;
2325fe6cc60SAlex Chiang int err = 0;
2335fe6cc60SAlex Chiang char *slot_name = NULL;
234f46753c5SAlex Chiang
23567546762SYijing Wang mutex_lock(&pci_slot_mutex);
236f46753c5SAlex Chiang
237f46753c5SAlex Chiang if (slot_nr == -1)
238f46753c5SAlex Chiang goto placeholder;
239f46753c5SAlex Chiang
2405fe6cc60SAlex Chiang /*
2415fe6cc60SAlex Chiang * Hotplug drivers are allowed to rename an existing slot,
2425fe6cc60SAlex Chiang * but only if not already claimed.
2435fe6cc60SAlex Chiang */
2445fe6cc60SAlex Chiang slot = get_slot(parent, slot_nr);
2455fe6cc60SAlex Chiang if (slot) {
2465fe6cc60SAlex Chiang if (hotplug) {
2475fe6cc60SAlex Chiang if ((err = slot->hotplug ? -EBUSY : 0)
2485fe6cc60SAlex Chiang || (err = rename_slot(slot, name))) {
2495fe6cc60SAlex Chiang kobject_put(&slot->kobj);
2505fe6cc60SAlex Chiang slot = NULL;
2515fe6cc60SAlex Chiang goto err;
252f46753c5SAlex Chiang }
253f46753c5SAlex Chiang }
2545fe6cc60SAlex Chiang goto out;
2555fe6cc60SAlex Chiang }
256f46753c5SAlex Chiang
257f46753c5SAlex Chiang placeholder:
258f46753c5SAlex Chiang slot = kzalloc(sizeof(*slot), GFP_KERNEL);
259f46753c5SAlex Chiang if (!slot) {
2605fe6cc60SAlex Chiang err = -ENOMEM;
2615fe6cc60SAlex Chiang goto err;
262f46753c5SAlex Chiang }
263f46753c5SAlex Chiang
264f46753c5SAlex Chiang slot->bus = parent;
265f46753c5SAlex Chiang slot->number = slot_nr;
266f46753c5SAlex Chiang
267f46753c5SAlex Chiang slot->kobj.kset = pci_slots_kset;
2685fe6cc60SAlex Chiang
2695fe6cc60SAlex Chiang slot_name = make_slot_name(name);
2705fe6cc60SAlex Chiang if (!slot_name) {
2715fe6cc60SAlex Chiang err = -ENOMEM;
2728a94644bSQiushi Wu kfree(slot);
273f46753c5SAlex Chiang goto err;
274f46753c5SAlex Chiang }
275f46753c5SAlex Chiang
2764684709bSJubin Zhong INIT_LIST_HEAD(&slot->list);
2774684709bSJubin Zhong list_add(&slot->list, &parent->slots);
2784684709bSJubin Zhong
2795fe6cc60SAlex Chiang err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL,
2805fe6cc60SAlex Chiang "%s", slot_name);
2818a94644bSQiushi Wu if (err) {
2828a94644bSQiushi Wu kobject_put(&slot->kobj);
2835fe6cc60SAlex Chiang goto err;
2848a94644bSQiushi Wu }
2855fe6cc60SAlex Chiang
28667546762SYijing Wang down_read(&pci_bus_sem);
287cef354dbSAlex Chiang list_for_each_entry(dev, &parent->devices, bus_list)
288cef354dbSAlex Chiang if (PCI_SLOT(dev->devfn) == slot_nr)
289cef354dbSAlex Chiang dev->slot = slot;
29067546762SYijing Wang up_read(&pci_bus_sem);
291cef354dbSAlex Chiang
29262795041SAlex Chiang dev_dbg(&parent->dev, "dev %02x, created physical slot %s\n",
29362795041SAlex Chiang slot_nr, pci_slot_name(slot));
294f46753c5SAlex Chiang
295f46753c5SAlex Chiang out:
2963b5dd45eSAlex Chiang kfree(slot_name);
29767546762SYijing Wang mutex_unlock(&pci_slot_mutex);
298f46753c5SAlex Chiang return slot;
299f46753c5SAlex Chiang err:
300f46753c5SAlex Chiang slot = ERR_PTR(err);
301f46753c5SAlex Chiang goto out;
302f46753c5SAlex Chiang }
303f46753c5SAlex Chiang EXPORT_SYMBOL_GPL(pci_create_slot);
304f46753c5SAlex Chiang
305f46753c5SAlex Chiang /**
306f46753c5SAlex Chiang * pci_destroy_slot - decrement refcount for physical PCI slot
307f46753c5SAlex Chiang * @slot: struct pci_slot to decrement
308f46753c5SAlex Chiang *
309f46753c5SAlex Chiang * %struct pci_slot is refcounted, so destroying them is really easy; we
310f46753c5SAlex Chiang * just call kobject_put on its kobj and let our release methods do the
311f46753c5SAlex Chiang * rest.
312f46753c5SAlex Chiang */
pci_destroy_slot(struct pci_slot * slot)313f46753c5SAlex Chiang void pci_destroy_slot(struct pci_slot *slot)
314f46753c5SAlex Chiang {
31562795041SAlex Chiang dev_dbg(&slot->bus->dev, "dev %02x, dec refcount to %d\n",
3162c935bc5SPeter Zijlstra slot->number, kref_read(&slot->kobj.kref) - 1);
317f46753c5SAlex Chiang
31867546762SYijing Wang mutex_lock(&pci_slot_mutex);
319f46753c5SAlex Chiang kobject_put(&slot->kobj);
32067546762SYijing Wang mutex_unlock(&pci_slot_mutex);
321f46753c5SAlex Chiang }
322f46753c5SAlex Chiang EXPORT_SYMBOL_GPL(pci_destroy_slot);
323f46753c5SAlex Chiang
324c825bc94SKenji Kaneshige #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
325c825bc94SKenji Kaneshige #include <linux/pci_hotplug.h>
326c825bc94SKenji Kaneshige /**
3272f0cd59cSMauro Carvalho Chehab * pci_hp_create_module_link - create symbolic link to hotplug driver module
328503998caSRandy Dunlap * @pci_slot: struct pci_slot
329c825bc94SKenji Kaneshige *
330c825bc94SKenji Kaneshige * Helper function for pci_hotplug_core.c to create symbolic link to
331c825bc94SKenji Kaneshige * the hotplug driver module.
332c825bc94SKenji Kaneshige */
pci_hp_create_module_link(struct pci_slot * pci_slot)333c825bc94SKenji Kaneshige void pci_hp_create_module_link(struct pci_slot *pci_slot)
334c825bc94SKenji Kaneshige {
335c825bc94SKenji Kaneshige struct hotplug_slot *slot = pci_slot->hotplug;
336c825bc94SKenji Kaneshige struct kobject *kobj = NULL;
3379fc9eea0SBjorn Helgaas int ret;
338c825bc94SKenji Kaneshige
339c825bc94SKenji Kaneshige if (!slot || !slot->ops)
340c825bc94SKenji Kaneshige return;
34181c4b5bfSLukas Wunner kobj = kset_find_obj(module_kset, slot->mod_name);
342c825bc94SKenji Kaneshige if (!kobj)
343c825bc94SKenji Kaneshige return;
3449fc9eea0SBjorn Helgaas ret = sysfs_create_link(&pci_slot->kobj, kobj, "module");
3459fc9eea0SBjorn Helgaas if (ret)
3469fc9eea0SBjorn Helgaas dev_err(&pci_slot->bus->dev, "Error creating sysfs link (%d)\n",
3479fc9eea0SBjorn Helgaas ret);
348c825bc94SKenji Kaneshige kobject_put(kobj);
349c825bc94SKenji Kaneshige }
350c825bc94SKenji Kaneshige EXPORT_SYMBOL_GPL(pci_hp_create_module_link);
351c825bc94SKenji Kaneshige
352c825bc94SKenji Kaneshige /**
3532f0cd59cSMauro Carvalho Chehab * pci_hp_remove_module_link - remove symbolic link to the hotplug driver
3542f0cd59cSMauro Carvalho Chehab * module.
355503998caSRandy Dunlap * @pci_slot: struct pci_slot
356c825bc94SKenji Kaneshige *
357c825bc94SKenji Kaneshige * Helper function for pci_hotplug_core.c to remove symbolic link to
358c825bc94SKenji Kaneshige * the hotplug driver module.
359c825bc94SKenji Kaneshige */
pci_hp_remove_module_link(struct pci_slot * pci_slot)360c825bc94SKenji Kaneshige void pci_hp_remove_module_link(struct pci_slot *pci_slot)
361c825bc94SKenji Kaneshige {
362c825bc94SKenji Kaneshige sysfs_remove_link(&pci_slot->kobj, "module");
363c825bc94SKenji Kaneshige }
364c825bc94SKenji Kaneshige EXPORT_SYMBOL_GPL(pci_hp_remove_module_link);
365c825bc94SKenji Kaneshige #endif
366c825bc94SKenji Kaneshige
pci_slot_init(void)367f46753c5SAlex Chiang static int pci_slot_init(void)
368f46753c5SAlex Chiang {
369f46753c5SAlex Chiang struct kset *pci_bus_kset;
370f46753c5SAlex Chiang
371f46753c5SAlex Chiang pci_bus_kset = bus_get_kset(&pci_bus_type);
372f46753c5SAlex Chiang pci_slots_kset = kset_create_and_add("slots", NULL,
373f46753c5SAlex Chiang &pci_bus_kset->kobj);
374f46753c5SAlex Chiang if (!pci_slots_kset) {
37525da8dbaSMohan Kumar pr_err("PCI: Slot initialization failure\n");
376f46753c5SAlex Chiang return -ENOMEM;
377f46753c5SAlex Chiang }
378f46753c5SAlex Chiang return 0;
379f46753c5SAlex Chiang }
380f46753c5SAlex Chiang
381f46753c5SAlex Chiang subsys_initcall(pci_slot_init);
382