xref: /openbmc/linux/drivers/pci/slot.c (revision 10473777)
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