The symbolic link points to the PCI device sysfs entry of the
                Physical Function this device associates with.
 
+
+What:          /sys/bus/pci/slots/...
+Date:          April 2005 (possibly older)
+KernelVersion: 2.6.12 (possibly older)
+Contact:       linux-pci@vger.kernel.org
+Description:
+               When the appropriate driver is loaded, it will create a
+               directory per claimed physical PCI slot in
+               /sys/bus/pci/slots/.  The names of these directories are
+               specific to the driver, which in turn, are specific to the
+               platform, but in general, should match the label on the
+               machine's physical chassis.
+
+               The drivers that can create slot directories include the
+               PCI hotplug drivers, and as of 2.6.27, the pci_slot driver.
+
+               The slot directories contain, at a minimum, a file named
+               'address' which contains the PCI bus:device:function tuple.
+               Other files may appear as well, but are specific to the
+               driver.
+
+What:          /sys/bus/pci/slots/.../function[0-7]
+Date:          March 2010
+KernelVersion: 2.6.35
+Contact:       linux-pci@vger.kernel.org
+Description:
+               If PCI slot directories (as described above) are created,
+               and the physical slot is actually populated with a device,
+               symbolic links in the slot directory pointing to the
+               device's PCI functions are created as well.
+
+What:          /sys/bus/pci/devices/.../slot
+Date:          March 2010
+KernelVersion: 2.6.35
+Contact:       linux-pci@vger.kernel.org
+Description:
+               If PCI slot directories (as described above) are created,
+               a symbolic link pointing to the slot directory will be
+               created as well.
+
 What:          /sys/bus/pci/slots/.../module
 Date:          June 2009
 Contact:       linux-pci@vger.kernel.org
 
        return retval;
 }
 
+static void pci_remove_slot_links(struct pci_dev *dev)
+{
+       char func[10];
+       struct pci_slot *slot;
+
+       sysfs_remove_link(&dev->dev.kobj, "slot");
+       list_for_each_entry(slot, &dev->bus->slots, list) {
+               if (slot->number != PCI_SLOT(dev->devfn))
+                       continue;
+               snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
+               sysfs_remove_link(&slot->kobj, func);
+       }
+}
+
+static int pci_create_slot_links(struct pci_dev *dev)
+{
+       int result = 0;
+       char func[10];
+       struct pci_slot *slot;
+
+       list_for_each_entry(slot, &dev->bus->slots, list) {
+               if (slot->number != PCI_SLOT(dev->devfn))
+                       continue;
+               result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot");
+               if (result)
+                       goto out;
+               snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
+               result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func);
+       }
+out:
+       return result;
+}
+
 int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
 {
        int retval;
        if (retval)
                goto err_vga_file;
 
+       pci_create_slot_links(pdev);
+
        return 0;
 
 err_vga_file:
        if (!sysfs_initialized)
                return;
 
+       pci_remove_slot_links(pdev);
+
        pci_remove_capabilities_sysfs(pdev);
 
        if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
 
        return bus_speed_read(slot->bus->cur_bus_speed, buf);
 }
 
+static void remove_sysfs_files(struct pci_slot *slot)
+{
+       char func[10];
+       struct list_head *tmp;
+
+       list_for_each(tmp, &slot->bus->devices) {
+               struct pci_dev *dev = pci_dev_b(tmp);
+               if (PCI_SLOT(dev->devfn) != slot->number)
+                       continue;
+               sysfs_remove_link(&dev->dev.kobj, "slot");
+
+               snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
+               sysfs_remove_link(&slot->kobj, func);
+       }
+}
+
+static int create_sysfs_files(struct pci_slot *slot)
+{
+       int result;
+       char func[10];
+       struct list_head *tmp;
+
+       list_for_each(tmp, &slot->bus->devices) {
+               struct pci_dev *dev = pci_dev_b(tmp);
+               if (PCI_SLOT(dev->devfn) != slot->number)
+                       continue;
+
+               result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot");
+               if (result)
+                       goto fail;
+
+               snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
+               result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func);
+               if (result)
+                       goto fail;
+       }
+
+       return 0;
+
+fail:
+       remove_sysfs_files(slot);
+       return result;
+}
+
 static void pci_slot_release(struct kobject *kobj)
 {
        struct pci_dev *dev;
                if (PCI_SLOT(dev->devfn) == slot->number)
                        dev->slot = NULL;
 
+       remove_sysfs_files(slot);
+
        list_del(&slot->list);
 
        kfree(slot);
        INIT_LIST_HEAD(&slot->list);
        list_add(&slot->list, &parent->slots);
 
+       create_sysfs_files(slot);
+
        list_for_each_entry(dev, &parent->devices, bus_list)
                if (PCI_SLOT(dev->devfn) == slot_nr)
                        dev->slot = slot;