LCOV - code coverage report
Current view: top level - drivers/pci - slot.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4 114 3.5 %
Date: 2023-08-24 13:40:31 Functions: 1 12 8.3 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 2006 Matthew Wilcox <matthew@wil.cx>
       4             :  * Copyright (C) 2006-2009 Hewlett-Packard Development Company, L.P.
       5             :  *      Alex Chiang <achiang@hp.com>
       6             :  */
       7             : 
       8             : #include <linux/kobject.h>
       9             : #include <linux/slab.h>
      10             : #include <linux/module.h>
      11             : #include <linux/pci.h>
      12             : #include <linux/err.h>
      13             : #include "pci.h"
      14             : 
      15             : struct kset *pci_slots_kset;
      16             : EXPORT_SYMBOL_GPL(pci_slots_kset);
      17             : 
      18           0 : static ssize_t pci_slot_attr_show(struct kobject *kobj,
      19             :                                         struct attribute *attr, char *buf)
      20             : {
      21           0 :         struct pci_slot *slot = to_pci_slot(kobj);
      22           0 :         struct pci_slot_attribute *attribute = to_pci_slot_attr(attr);
      23           0 :         return attribute->show ? attribute->show(slot, buf) : -EIO;
      24             : }
      25             : 
      26           0 : static ssize_t pci_slot_attr_store(struct kobject *kobj,
      27             :                         struct attribute *attr, const char *buf, size_t len)
      28             : {
      29           0 :         struct pci_slot *slot = to_pci_slot(kobj);
      30           0 :         struct pci_slot_attribute *attribute = to_pci_slot_attr(attr);
      31           0 :         return attribute->store ? attribute->store(slot, buf, len) : -EIO;
      32             : }
      33             : 
      34             : static const struct sysfs_ops pci_slot_sysfs_ops = {
      35             :         .show = pci_slot_attr_show,
      36             :         .store = pci_slot_attr_store,
      37             : };
      38             : 
      39           0 : static ssize_t address_read_file(struct pci_slot *slot, char *buf)
      40             : {
      41           0 :         if (slot->number == 0xff)
      42           0 :                 return sysfs_emit(buf, "%04x:%02x\n",
      43             :                                   pci_domain_nr(slot->bus),
      44           0 :                                   slot->bus->number);
      45             : 
      46           0 :         return sysfs_emit(buf, "%04x:%02x:%02x\n",
      47             :                           pci_domain_nr(slot->bus),
      48           0 :                           slot->bus->number,
      49             :                           slot->number);
      50             : }
      51             : 
      52             : static ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf)
      53             : {
      54           0 :         return sysfs_emit(buf, "%s\n", pci_speed_string(speed));
      55             : }
      56             : 
      57           0 : static ssize_t max_speed_read_file(struct pci_slot *slot, char *buf)
      58             : {
      59           0 :         return bus_speed_read(slot->bus->max_bus_speed, buf);
      60             : }
      61             : 
      62           0 : static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf)
      63             : {
      64           0 :         return bus_speed_read(slot->bus->cur_bus_speed, buf);
      65             : }
      66             : 
      67           0 : static void pci_slot_release(struct kobject *kobj)
      68             : {
      69             :         struct pci_dev *dev;
      70           0 :         struct pci_slot *slot = to_pci_slot(kobj);
      71             : 
      72             :         dev_dbg(&slot->bus->dev, "dev %02x, released physical slot %s\n",
      73             :                 slot->number, pci_slot_name(slot));
      74             : 
      75           0 :         down_read(&pci_bus_sem);
      76           0 :         list_for_each_entry(dev, &slot->bus->devices, bus_list)
      77           0 :                 if (PCI_SLOT(dev->devfn) == slot->number)
      78           0 :                         dev->slot = NULL;
      79           0 :         up_read(&pci_bus_sem);
      80             : 
      81           0 :         list_del(&slot->list);
      82             : 
      83           0 :         kfree(slot);
      84           0 : }
      85             : 
      86             : static struct pci_slot_attribute pci_slot_attr_address =
      87             :         __ATTR(address, S_IRUGO, address_read_file, NULL);
      88             : static struct pci_slot_attribute pci_slot_attr_max_speed =
      89             :         __ATTR(max_bus_speed, S_IRUGO, max_speed_read_file, NULL);
      90             : static struct pci_slot_attribute pci_slot_attr_cur_speed =
      91             :         __ATTR(cur_bus_speed, S_IRUGO, cur_speed_read_file, NULL);
      92             : 
      93             : static struct attribute *pci_slot_default_attrs[] = {
      94             :         &pci_slot_attr_address.attr,
      95             :         &pci_slot_attr_max_speed.attr,
      96             :         &pci_slot_attr_cur_speed.attr,
      97             :         NULL,
      98             : };
      99             : ATTRIBUTE_GROUPS(pci_slot_default);
     100             : 
     101             : static const struct kobj_type pci_slot_ktype = {
     102             :         .sysfs_ops = &pci_slot_sysfs_ops,
     103             :         .release = &pci_slot_release,
     104             :         .default_groups = pci_slot_default_groups,
     105             : };
     106             : 
     107           0 : static char *make_slot_name(const char *name)
     108             : {
     109             :         char *new_name;
     110             :         int len, max, dup;
     111             : 
     112           0 :         new_name = kstrdup(name, GFP_KERNEL);
     113           0 :         if (!new_name)
     114             :                 return NULL;
     115             : 
     116             :         /*
     117             :          * Make sure we hit the realloc case the first time through the
     118             :          * loop.  'len' will be strlen(name) + 3 at that point which is
     119             :          * enough space for "name-X" and the trailing NUL.
     120             :          */
     121           0 :         len = strlen(name) + 2;
     122           0 :         max = 1;
     123           0 :         dup = 1;
     124             : 
     125           0 :         for (;;) {
     126             :                 struct kobject *dup_slot;
     127           0 :                 dup_slot = kset_find_obj(pci_slots_kset, new_name);
     128           0 :                 if (!dup_slot)
     129             :                         break;
     130           0 :                 kobject_put(dup_slot);
     131           0 :                 if (dup == max) {
     132           0 :                         len++;
     133           0 :                         max *= 10;
     134           0 :                         kfree(new_name);
     135           0 :                         new_name = kmalloc(len, GFP_KERNEL);
     136           0 :                         if (!new_name)
     137             :                                 break;
     138             :                 }
     139           0 :                 sprintf(new_name, "%s-%d", name, dup++);
     140             :         }
     141             : 
     142             :         return new_name;
     143             : }
     144             : 
     145           0 : static int rename_slot(struct pci_slot *slot, const char *name)
     146             : {
     147           0 :         int result = 0;
     148             :         char *slot_name;
     149             : 
     150           0 :         if (strcmp(pci_slot_name(slot), name) == 0)
     151             :                 return result;
     152             : 
     153           0 :         slot_name = make_slot_name(name);
     154           0 :         if (!slot_name)
     155             :                 return -ENOMEM;
     156             : 
     157           0 :         result = kobject_rename(&slot->kobj, slot_name);
     158           0 :         kfree(slot_name);
     159             : 
     160           0 :         return result;
     161             : }
     162             : 
     163           0 : void pci_dev_assign_slot(struct pci_dev *dev)
     164             : {
     165             :         struct pci_slot *slot;
     166             : 
     167           0 :         mutex_lock(&pci_slot_mutex);
     168           0 :         list_for_each_entry(slot, &dev->bus->slots, list)
     169           0 :                 if (PCI_SLOT(dev->devfn) == slot->number)
     170           0 :                         dev->slot = slot;
     171           0 :         mutex_unlock(&pci_slot_mutex);
     172           0 : }
     173             : 
     174             : static struct pci_slot *get_slot(struct pci_bus *parent, int slot_nr)
     175             : {
     176             :         struct pci_slot *slot;
     177             : 
     178             :         /* We already hold pci_slot_mutex */
     179           0 :         list_for_each_entry(slot, &parent->slots, list)
     180           0 :                 if (slot->number == slot_nr) {
     181           0 :                         kobject_get(&slot->kobj);
     182             :                         return slot;
     183             :                 }
     184             : 
     185             :         return NULL;
     186             : }
     187             : 
     188             : /**
     189             :  * pci_create_slot - create or increment refcount for physical PCI slot
     190             :  * @parent: struct pci_bus of parent bridge
     191             :  * @slot_nr: PCI_SLOT(pci_dev->devfn) or -1 for placeholder
     192             :  * @name: user visible string presented in /sys/bus/pci/slots/<name>
     193             :  * @hotplug: set if caller is hotplug driver, NULL otherwise
     194             :  *
     195             :  * PCI slots have first class attributes such as address, speed, width,
     196             :  * and a &struct pci_slot is used to manage them. This interface will
     197             :  * either return a new &struct pci_slot to the caller, or if the pci_slot
     198             :  * already exists, its refcount will be incremented.
     199             :  *
     200             :  * Slots are uniquely identified by a @pci_bus, @slot_nr tuple.
     201             :  *
     202             :  * There are known platforms with broken firmware that assign the same
     203             :  * name to multiple slots. Workaround these broken platforms by renaming
     204             :  * the slots on behalf of the caller. If firmware assigns name N to
     205             :  * multiple slots:
     206             :  *
     207             :  * The first slot is assigned N
     208             :  * The second slot is assigned N-1
     209             :  * The third slot is assigned N-2
     210             :  * etc.
     211             :  *
     212             :  * Placeholder slots:
     213             :  * In most cases, @pci_bus, @slot_nr will be sufficient to uniquely identify
     214             :  * a slot. There is one notable exception - pSeries (rpaphp), where the
     215             :  * @slot_nr cannot be determined until a device is actually inserted into
     216             :  * the slot. In this scenario, the caller may pass -1 for @slot_nr.
     217             :  *
     218             :  * The following semantics are imposed when the caller passes @slot_nr ==
     219             :  * -1. First, we no longer check for an existing %struct pci_slot, as there
     220             :  * may be many slots with @slot_nr of -1.  The other change in semantics is
     221             :  * user-visible, which is the 'address' parameter presented in sysfs will
     222             :  * consist solely of a dddd:bb tuple, where dddd is the PCI domain of the
     223             :  * %struct pci_bus and bb is the bus number. In other words, the devfn of
     224             :  * the 'placeholder' slot will not be displayed.
     225             :  */
     226           0 : struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
     227             :                                  const char *name,
     228             :                                  struct hotplug_slot *hotplug)
     229             : {
     230             :         struct pci_dev *dev;
     231             :         struct pci_slot *slot;
     232           0 :         int err = 0;
     233           0 :         char *slot_name = NULL;
     234             : 
     235           0 :         mutex_lock(&pci_slot_mutex);
     236             : 
     237           0 :         if (slot_nr == -1)
     238             :                 goto placeholder;
     239             : 
     240             :         /*
     241             :          * Hotplug drivers are allowed to rename an existing slot,
     242             :          * but only if not already claimed.
     243             :          */
     244           0 :         slot = get_slot(parent, slot_nr);
     245           0 :         if (slot) {
     246           0 :                 if (hotplug) {
     247           0 :                         if ((err = slot->hotplug ? -EBUSY : 0)
     248           0 :                              || (err = rename_slot(slot, name))) {
     249           0 :                                 kobject_put(&slot->kobj);
     250           0 :                                 slot = NULL;
     251           0 :                                 goto err;
     252             :                         }
     253             :                 }
     254             :                 goto out;
     255             :         }
     256             : 
     257             : placeholder:
     258           0 :         slot = kzalloc(sizeof(*slot), GFP_KERNEL);
     259           0 :         if (!slot) {
     260             :                 err = -ENOMEM;
     261             :                 goto err;
     262             :         }
     263             : 
     264           0 :         slot->bus = parent;
     265           0 :         slot->number = slot_nr;
     266             : 
     267           0 :         slot->kobj.kset = pci_slots_kset;
     268             : 
     269           0 :         slot_name = make_slot_name(name);
     270           0 :         if (!slot_name) {
     271           0 :                 err = -ENOMEM;
     272           0 :                 kfree(slot);
     273           0 :                 goto err;
     274             :         }
     275             : 
     276           0 :         INIT_LIST_HEAD(&slot->list);
     277           0 :         list_add(&slot->list, &parent->slots);
     278             : 
     279           0 :         err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL,
     280             :                                    "%s", slot_name);
     281           0 :         if (err) {
     282           0 :                 kobject_put(&slot->kobj);
     283           0 :                 goto err;
     284             :         }
     285             : 
     286           0 :         down_read(&pci_bus_sem);
     287           0 :         list_for_each_entry(dev, &parent->devices, bus_list)
     288           0 :                 if (PCI_SLOT(dev->devfn) == slot_nr)
     289           0 :                         dev->slot = slot;
     290           0 :         up_read(&pci_bus_sem);
     291             : 
     292             :         dev_dbg(&parent->dev, "dev %02x, created physical slot %s\n",
     293             :                 slot_nr, pci_slot_name(slot));
     294             : 
     295             : out:
     296           0 :         kfree(slot_name);
     297           0 :         mutex_unlock(&pci_slot_mutex);
     298           0 :         return slot;
     299             : err:
     300           0 :         slot = ERR_PTR(err);
     301           0 :         goto out;
     302             : }
     303             : EXPORT_SYMBOL_GPL(pci_create_slot);
     304             : 
     305             : /**
     306             :  * pci_destroy_slot - decrement refcount for physical PCI slot
     307             :  * @slot: struct pci_slot to decrement
     308             :  *
     309             :  * %struct pci_slot is refcounted, so destroying them is really easy; we
     310             :  * just call kobject_put on its kobj and let our release methods do the
     311             :  * rest.
     312             :  */
     313           0 : void pci_destroy_slot(struct pci_slot *slot)
     314             : {
     315             :         dev_dbg(&slot->bus->dev, "dev %02x, dec refcount to %d\n",
     316             :                 slot->number, kref_read(&slot->kobj.kref) - 1);
     317             : 
     318           0 :         mutex_lock(&pci_slot_mutex);
     319           0 :         kobject_put(&slot->kobj);
     320           0 :         mutex_unlock(&pci_slot_mutex);
     321           0 : }
     322             : EXPORT_SYMBOL_GPL(pci_destroy_slot);
     323             : 
     324             : #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
     325             : #include <linux/pci_hotplug.h>
     326             : /**
     327             :  * pci_hp_create_module_link - create symbolic link to hotplug driver module
     328             :  * @pci_slot: struct pci_slot
     329             :  *
     330             :  * Helper function for pci_hotplug_core.c to create symbolic link to
     331             :  * the hotplug driver module.
     332             :  */
     333             : void pci_hp_create_module_link(struct pci_slot *pci_slot)
     334             : {
     335             :         struct hotplug_slot *slot = pci_slot->hotplug;
     336             :         struct kobject *kobj = NULL;
     337             :         int ret;
     338             : 
     339             :         if (!slot || !slot->ops)
     340             :                 return;
     341             :         kobj = kset_find_obj(module_kset, slot->mod_name);
     342             :         if (!kobj)
     343             :                 return;
     344             :         ret = sysfs_create_link(&pci_slot->kobj, kobj, "module");
     345             :         if (ret)
     346             :                 dev_err(&pci_slot->bus->dev, "Error creating sysfs link (%d)\n",
     347             :                         ret);
     348             :         kobject_put(kobj);
     349             : }
     350             : EXPORT_SYMBOL_GPL(pci_hp_create_module_link);
     351             : 
     352             : /**
     353             :  * pci_hp_remove_module_link - remove symbolic link to the hotplug driver
     354             :  *      module.
     355             :  * @pci_slot: struct pci_slot
     356             :  *
     357             :  * Helper function for pci_hotplug_core.c to remove symbolic link to
     358             :  * the hotplug driver module.
     359             :  */
     360             : void pci_hp_remove_module_link(struct pci_slot *pci_slot)
     361             : {
     362             :         sysfs_remove_link(&pci_slot->kobj, "module");
     363             : }
     364             : EXPORT_SYMBOL_GPL(pci_hp_remove_module_link);
     365             : #endif
     366             : 
     367           1 : static int pci_slot_init(void)
     368             : {
     369             :         struct kset *pci_bus_kset;
     370             : 
     371           1 :         pci_bus_kset = bus_get_kset(&pci_bus_type);
     372           1 :         pci_slots_kset = kset_create_and_add("slots", NULL,
     373             :                                                 &pci_bus_kset->kobj);
     374           1 :         if (!pci_slots_kset) {
     375           0 :                 pr_err("PCI: Slot initialization failure\n");
     376           0 :                 return -ENOMEM;
     377             :         }
     378             :         return 0;
     379             : }
     380             : 
     381             : subsys_initcall(pci_slot_init);

Generated by: LCOV version 1.14