1 /* 2 * drivers/pci/slot.c 3 * Copyright (C) 2006 Matthew Wilcox <matthew@wil.cx> 4 * Copyright (C) 2006-2008 Hewlett-Packard Development Company, L.P. 5 * Alex Chiang <achiang@hp.com> 6 */ 7 8 #include <linux/kobject.h> 9 #include <linux/pci.h> 10 #include <linux/err.h> 11 #include "pci.h" 12 13 struct kset *pci_slots_kset; 14 EXPORT_SYMBOL_GPL(pci_slots_kset); 15 16 static ssize_t pci_slot_attr_show(struct kobject *kobj, 17 struct attribute *attr, char *buf) 18 { 19 struct pci_slot *slot = to_pci_slot(kobj); 20 struct pci_slot_attribute *attribute = to_pci_slot_attr(attr); 21 return attribute->show ? attribute->show(slot, buf) : -EIO; 22 } 23 24 static ssize_t pci_slot_attr_store(struct kobject *kobj, 25 struct attribute *attr, const char *buf, size_t len) 26 { 27 struct pci_slot *slot = to_pci_slot(kobj); 28 struct pci_slot_attribute *attribute = to_pci_slot_attr(attr); 29 return attribute->store ? attribute->store(slot, buf, len) : -EIO; 30 } 31 32 static struct sysfs_ops pci_slot_sysfs_ops = { 33 .show = pci_slot_attr_show, 34 .store = pci_slot_attr_store, 35 }; 36 37 static ssize_t address_read_file(struct pci_slot *slot, char *buf) 38 { 39 if (slot->number == 0xff) 40 return sprintf(buf, "%04x:%02x\n", 41 pci_domain_nr(slot->bus), 42 slot->bus->number); 43 else 44 return sprintf(buf, "%04x:%02x:%02x\n", 45 pci_domain_nr(slot->bus), 46 slot->bus->number, 47 slot->number); 48 } 49 50 static void pci_slot_release(struct kobject *kobj) 51 { 52 struct pci_slot *slot = to_pci_slot(kobj); 53 54 pr_debug("%s: releasing pci_slot on %x:%d\n", __func__, 55 slot->bus->number, slot->number); 56 57 list_del(&slot->list); 58 59 kfree(slot); 60 } 61 62 static struct pci_slot_attribute pci_slot_attr_address = 63 __ATTR(address, (S_IFREG | S_IRUGO), address_read_file, NULL); 64 65 static struct attribute *pci_slot_default_attrs[] = { 66 &pci_slot_attr_address.attr, 67 NULL, 68 }; 69 70 static struct kobj_type pci_slot_ktype = { 71 .sysfs_ops = &pci_slot_sysfs_ops, 72 .release = &pci_slot_release, 73 .default_attrs = pci_slot_default_attrs, 74 }; 75 76 /** 77 * pci_create_slot - create or increment refcount for physical PCI slot 78 * @parent: struct pci_bus of parent bridge 79 * @slot_nr: PCI_SLOT(pci_dev->devfn) or -1 for placeholder 80 * @name: user visible string presented in /sys/bus/pci/slots/<name> 81 * 82 * PCI slots have first class attributes such as address, speed, width, 83 * and a &struct pci_slot is used to manage them. This interface will 84 * either return a new &struct pci_slot to the caller, or if the pci_slot 85 * already exists, its refcount will be incremented. 86 * 87 * Slots are uniquely identified by a @pci_bus, @slot_nr, @name tuple. 88 * 89 * Placeholder slots: 90 * In most cases, @pci_bus, @slot_nr will be sufficient to uniquely identify 91 * a slot. There is one notable exception - pSeries (rpaphp), where the 92 * @slot_nr cannot be determined until a device is actually inserted into 93 * the slot. In this scenario, the caller may pass -1 for @slot_nr. 94 * 95 * The following semantics are imposed when the caller passes @slot_nr == 96 * -1. First, the check for existing %struct pci_slot is skipped, as the 97 * caller may know about several unpopulated slots on a given %struct 98 * pci_bus, and each slot would have a @slot_nr of -1. Uniqueness for 99 * these slots is then determined by the @name parameter. We expect 100 * kobject_init_and_add() to warn us if the caller attempts to create 101 * multiple slots with the same name. The other change in semantics is 102 * user-visible, which is the 'address' parameter presented in sysfs will 103 * consist solely of a dddd:bb tuple, where dddd is the PCI domain of the 104 * %struct pci_bus and bb is the bus number. In other words, the devfn of 105 * the 'placeholder' slot will not be displayed. 106 */ 107 108 struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, 109 const char *name) 110 { 111 struct pci_slot *slot; 112 int err; 113 114 down_write(&pci_bus_sem); 115 116 if (slot_nr == -1) 117 goto placeholder; 118 119 /* If we've already created this slot, bump refcount and return. */ 120 list_for_each_entry(slot, &parent->slots, list) { 121 if (slot->number == slot_nr) { 122 kobject_get(&slot->kobj); 123 pr_debug("%s: inc refcount to %d on %04x:%02x:%02x\n", 124 __func__, 125 atomic_read(&slot->kobj.kref.refcount), 126 pci_domain_nr(parent), parent->number, 127 slot_nr); 128 goto out; 129 } 130 } 131 132 placeholder: 133 slot = kzalloc(sizeof(*slot), GFP_KERNEL); 134 if (!slot) { 135 slot = ERR_PTR(-ENOMEM); 136 goto out; 137 } 138 139 slot->bus = parent; 140 slot->number = slot_nr; 141 142 slot->kobj.kset = pci_slots_kset; 143 err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL, 144 "%s", name); 145 if (err) { 146 printk(KERN_ERR "Unable to register kobject %s\n", name); 147 goto err; 148 } 149 150 INIT_LIST_HEAD(&slot->list); 151 list_add(&slot->list, &parent->slots); 152 153 /* Don't care if debug printk has a -1 for slot_nr */ 154 pr_debug("%s: created pci_slot on %04x:%02x:%02x\n", 155 __func__, pci_domain_nr(parent), parent->number, slot_nr); 156 157 out: 158 up_write(&pci_bus_sem); 159 return slot; 160 err: 161 kfree(slot); 162 slot = ERR_PTR(err); 163 goto out; 164 } 165 EXPORT_SYMBOL_GPL(pci_create_slot); 166 167 /** 168 * pci_update_slot_number - update %struct pci_slot -> number 169 * @slot - %struct pci_slot to update 170 * @slot_nr - new number for slot 171 * 172 * The primary purpose of this interface is to allow callers who earlier 173 * created a placeholder slot in pci_create_slot() by passing a -1 as 174 * slot_nr, to update their %struct pci_slot with the correct @slot_nr. 175 */ 176 177 void pci_update_slot_number(struct pci_slot *slot, int slot_nr) 178 { 179 int name_count = 0; 180 struct pci_slot *tmp; 181 182 down_write(&pci_bus_sem); 183 184 list_for_each_entry(tmp, &slot->bus->slots, list) { 185 WARN_ON(tmp->number == slot_nr); 186 if (!strcmp(kobject_name(&tmp->kobj), kobject_name(&slot->kobj))) 187 name_count++; 188 } 189 190 if (name_count > 1) 191 printk(KERN_WARNING "pci_update_slot_number found %d slots with the same name: %s\n", name_count, kobject_name(&slot->kobj)); 192 193 slot->number = slot_nr; 194 up_write(&pci_bus_sem); 195 } 196 EXPORT_SYMBOL_GPL(pci_update_slot_number); 197 198 /** 199 * pci_destroy_slot - decrement refcount for physical PCI slot 200 * @slot: struct pci_slot to decrement 201 * 202 * %struct pci_slot is refcounted, so destroying them is really easy; we 203 * just call kobject_put on its kobj and let our release methods do the 204 * rest. 205 */ 206 207 void pci_destroy_slot(struct pci_slot *slot) 208 { 209 pr_debug("%s: dec refcount to %d on %04x:%02x:%02x\n", __func__, 210 atomic_read(&slot->kobj.kref.refcount) - 1, 211 pci_domain_nr(slot->bus), slot->bus->number, slot->number); 212 213 down_write(&pci_bus_sem); 214 kobject_put(&slot->kobj); 215 up_write(&pci_bus_sem); 216 } 217 EXPORT_SYMBOL_GPL(pci_destroy_slot); 218 219 static int pci_slot_init(void) 220 { 221 struct kset *pci_bus_kset; 222 223 pci_bus_kset = bus_get_kset(&pci_bus_type); 224 pci_slots_kset = kset_create_and_add("slots", NULL, 225 &pci_bus_kset->kobj); 226 if (!pci_slots_kset) { 227 printk(KERN_ERR "PCI: Slot initialization failure\n"); 228 return -ENOMEM; 229 } 230 return 0; 231 } 232 233 subsys_initcall(pci_slot_init); 234