diff options
Diffstat (limited to 'drivers/pci/slot.c')
| -rw-r--r-- | drivers/pci/slot.c | 194 |
1 files changed, 56 insertions, 138 deletions
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index c1e9284a677b..50fb3eb595fe 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -1,5 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * drivers/pci/slot.c * Copyright (C) 2006 Matthew Wilcox <matthew@wil.cx> * Copyright (C) 2006-2009 Hewlett-Packard Development Company, L.P. * Alex Chiang <achiang@hp.com> @@ -7,7 +7,6 @@ #include <linux/kobject.h> #include <linux/slab.h> -#include <linux/module.h> #include <linux/pci.h> #include <linux/err.h> #include "pci.h" @@ -39,53 +38,19 @@ static const struct sysfs_ops pci_slot_sysfs_ops = { static ssize_t address_read_file(struct pci_slot *slot, char *buf) { if (slot->number == 0xff) - return sprintf(buf, "%04x:%02x\n", - pci_domain_nr(slot->bus), - slot->bus->number); - else - return sprintf(buf, "%04x:%02x:%02x\n", - pci_domain_nr(slot->bus), - slot->bus->number, - slot->number); + return sysfs_emit(buf, "%04x:%02x\n", + pci_domain_nr(slot->bus), + slot->bus->number); + + return sysfs_emit(buf, "%04x:%02x:%02x\n", + pci_domain_nr(slot->bus), + slot->bus->number, + slot->number); } -/* these strings match up with the values in pci_bus_speed */ -static const char *pci_bus_speed_strings[] = { - "33 MHz PCI", /* 0x00 */ - "66 MHz PCI", /* 0x01 */ - "66 MHz PCI-X", /* 0x02 */ - "100 MHz PCI-X", /* 0x03 */ - "133 MHz PCI-X", /* 0x04 */ - NULL, /* 0x05 */ - NULL, /* 0x06 */ - NULL, /* 0x07 */ - NULL, /* 0x08 */ - "66 MHz PCI-X 266", /* 0x09 */ - "100 MHz PCI-X 266", /* 0x0a */ - "133 MHz PCI-X 266", /* 0x0b */ - "Unknown AGP", /* 0x0c */ - "1x AGP", /* 0x0d */ - "2x AGP", /* 0x0e */ - "4x AGP", /* 0x0f */ - "8x AGP", /* 0x10 */ - "66 MHz PCI-X 533", /* 0x11 */ - "100 MHz PCI-X 533", /* 0x12 */ - "133 MHz PCI-X 533", /* 0x13 */ - "2.5 GT/s PCIe", /* 0x14 */ - "5.0 GT/s PCIe", /* 0x15 */ - "8.0 GT/s PCIe", /* 0x16 */ -}; - static ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf) { - const char *speed_string; - - if (speed < ARRAY_SIZE(pci_bus_speed_strings)) - speed_string = pci_bus_speed_strings[speed]; - else - speed_string = "Unknown"; - - return sprintf(buf, "%s\n", speed_string); + return sysfs_emit(buf, "%s\n", pci_speed_string(speed)); } static ssize_t max_speed_read_file(struct pci_slot *slot, char *buf) @@ -106,21 +71,24 @@ static void pci_slot_release(struct kobject *kobj) dev_dbg(&slot->bus->dev, "dev %02x, released physical slot %s\n", slot->number, pci_slot_name(slot)); + down_read(&pci_bus_sem); list_for_each_entry(dev, &slot->bus->devices, bus_list) if (PCI_SLOT(dev->devfn) == slot->number) dev->slot = NULL; + up_read(&pci_bus_sem); list_del(&slot->list); + pci_bus_put(slot->bus); kfree(slot); } static struct pci_slot_attribute pci_slot_attr_address = - __ATTR(address, (S_IFREG | S_IRUGO), address_read_file, NULL); + __ATTR(address, S_IRUGO, address_read_file, NULL); static struct pci_slot_attribute pci_slot_attr_max_speed = - __ATTR(max_bus_speed, (S_IFREG | S_IRUGO), max_speed_read_file, NULL); + __ATTR(max_bus_speed, S_IRUGO, max_speed_read_file, NULL); static struct pci_slot_attribute pci_slot_attr_cur_speed = - __ATTR(cur_bus_speed, (S_IFREG | S_IRUGO), cur_speed_read_file, NULL); + __ATTR(cur_bus_speed, S_IRUGO, cur_speed_read_file, NULL); static struct attribute *pci_slot_default_attrs[] = { &pci_slot_attr_address.attr, @@ -128,11 +96,12 @@ static struct attribute *pci_slot_default_attrs[] = { &pci_slot_attr_cur_speed.attr, NULL, }; +ATTRIBUTE_GROUPS(pci_slot_default); -static struct kobj_type pci_slot_ktype = { +static const struct kobj_type pci_slot_ktype = { .sysfs_ops = &pci_slot_sysfs_ops, .release = &pci_slot_release, - .default_attrs = pci_slot_default_attrs, + .default_groups = pci_slot_default_groups, }; static char *make_slot_name(const char *name) @@ -191,12 +160,22 @@ static int rename_slot(struct pci_slot *slot, const char *name) return result; } +void pci_dev_assign_slot(struct pci_dev *dev) +{ + struct pci_slot *slot; + + mutex_lock(&pci_slot_mutex); + list_for_each_entry(slot, &dev->bus->slots, list) + if (PCI_SLOT(dev->devfn) == slot->number) + dev->slot = slot; + mutex_unlock(&pci_slot_mutex); +} + static struct pci_slot *get_slot(struct pci_bus *parent, int slot_nr) { struct pci_slot *slot; - /* - * We already hold pci_bus_sem so don't worry - */ + + /* We already hold pci_slot_mutex */ list_for_each_entry(slot, &parent->slots, list) if (slot->number == slot_nr) { kobject_get(&slot->kobj); @@ -253,7 +232,7 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, int err = 0; char *slot_name = NULL; - down_write(&pci_bus_sem); + mutex_lock(&pci_slot_mutex); if (slot_nr == -1) goto placeholder; @@ -265,12 +244,13 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, slot = get_slot(parent, slot_nr); if (slot) { if (hotplug) { - if ((err = slot->hotplug ? -EBUSY : 0) - || (err = rename_slot(slot, name))) { - kobject_put(&slot->kobj); - slot = NULL; - goto err; + if (slot->hotplug) { + err = -EBUSY; + goto put_slot; } + err = rename_slot(slot, name); + if (err) + goto put_slot; } goto out; } @@ -282,7 +262,7 @@ placeholder: goto err; } - slot->bus = parent; + slot->bus = pci_bus_get(parent); slot->number = slot_nr; slot->kobj.kset = pci_slots_kset; @@ -290,62 +270,42 @@ placeholder: slot_name = make_slot_name(name); if (!slot_name) { err = -ENOMEM; + pci_bus_put(slot->bus); + kfree(slot); goto err; } + INIT_LIST_HEAD(&slot->list); + list_add(&slot->list, &parent->slots); + err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL, "%s", slot_name); if (err) - goto err; - - INIT_LIST_HEAD(&slot->list); - list_add(&slot->list, &parent->slots); + goto put_slot; + down_read(&pci_bus_sem); list_for_each_entry(dev, &parent->devices, bus_list) if (PCI_SLOT(dev->devfn) == slot_nr) dev->slot = slot; + up_read(&pci_bus_sem); dev_dbg(&parent->dev, "dev %02x, created physical slot %s\n", slot_nr, pci_slot_name(slot)); out: kfree(slot_name); - up_write(&pci_bus_sem); + mutex_unlock(&pci_slot_mutex); return slot; + +put_slot: + kobject_put(&slot->kobj); err: - kfree(slot); slot = ERR_PTR(err); goto out; } EXPORT_SYMBOL_GPL(pci_create_slot); /** - * pci_renumber_slot - update %struct pci_slot -> number - * @slot: &struct pci_slot to update - * @slot_nr: new number for slot - * - * The primary purpose of this interface is to allow callers who earlier - * created a placeholder slot in pci_create_slot() by passing a -1 as - * slot_nr, to update their %struct pci_slot with the correct @slot_nr. - */ -void pci_renumber_slot(struct pci_slot *slot, int slot_nr) -{ - struct pci_slot *tmp; - - down_write(&pci_bus_sem); - - list_for_each_entry(tmp, &slot->bus->slots, list) { - WARN_ON(tmp->number == slot_nr); - goto out; - } - - slot->number = slot_nr; -out: - up_write(&pci_bus_sem); -} -EXPORT_SYMBOL_GPL(pci_renumber_slot); - -/** * pci_destroy_slot - decrement refcount for physical PCI slot * @slot: struct pci_slot to decrement * @@ -356,56 +316,14 @@ EXPORT_SYMBOL_GPL(pci_renumber_slot); void pci_destroy_slot(struct pci_slot *slot) { dev_dbg(&slot->bus->dev, "dev %02x, dec refcount to %d\n", - slot->number, atomic_read(&slot->kobj.kref.refcount) - 1); + slot->number, kref_read(&slot->kobj.kref) - 1); - down_write(&pci_bus_sem); + mutex_lock(&pci_slot_mutex); kobject_put(&slot->kobj); - up_write(&pci_bus_sem); + mutex_unlock(&pci_slot_mutex); } EXPORT_SYMBOL_GPL(pci_destroy_slot); -#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE) -#include <linux/pci_hotplug.h> -/** - * pci_hp_create_link - create symbolic link to the hotplug driver module. - * @pci_slot: struct pci_slot - * - * Helper function for pci_hotplug_core.c to create symbolic link to - * the hotplug driver module. - */ -void pci_hp_create_module_link(struct pci_slot *pci_slot) -{ - struct hotplug_slot *slot = pci_slot->hotplug; - struct kobject *kobj = NULL; - int ret; - - if (!slot || !slot->ops) - return; - kobj = kset_find_obj(module_kset, slot->ops->mod_name); - if (!kobj) - return; - ret = sysfs_create_link(&pci_slot->kobj, kobj, "module"); - if (ret) - dev_err(&pci_slot->bus->dev, "Error creating sysfs link (%d)\n", - ret); - kobject_put(kobj); -} -EXPORT_SYMBOL_GPL(pci_hp_create_module_link); - -/** - * pci_hp_remove_link - remove symbolic link to the hotplug driver module. - * @pci_slot: struct pci_slot - * - * Helper function for pci_hotplug_core.c to remove symbolic link to - * the hotplug driver module. - */ -void pci_hp_remove_module_link(struct pci_slot *pci_slot) -{ - sysfs_remove_link(&pci_slot->kobj, "module"); -} -EXPORT_SYMBOL_GPL(pci_hp_remove_module_link); -#endif - static int pci_slot_init(void) { struct kset *pci_bus_kset; @@ -414,7 +332,7 @@ static int pci_slot_init(void) pci_slots_kset = kset_create_and_add("slots", NULL, &pci_bus_kset->kobj); if (!pci_slots_kset) { - printk(KERN_ERR "PCI: Slot initialization failure\n"); + pr_err("PCI: Slot initialization failure\n"); return -ENOMEM; } return 0; |
