aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Chiang <achiang@hp.com>2008-06-10 17:28:50 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-06-10 17:37:03 -0400
commitf46753c5e354b857b20ab8e0fe7b2579831dc369 (patch)
treeefffdb4dfec5e1f6fd624f17aa36d7d350bb1e6c
parentfe99740cac117f208707488c03f3789cf4904957 (diff)
PCI: introduce pci_slot
Currently, /sys/bus/pci/slots/ only exposes hotplug attributes when a hotplug driver is loaded, but PCI slots have attributes such as address, speed, width, etc. that are not related to hotplug at all. Introduce pci_slot as the primary data structure and kobject model. Hotplug attributes described in hotplug_slot become a secondary structure associated with the pci_slot. This patch only creates the infrastructure that allows the separation of PCI slot attributes and hotplug attributes. In this patch, the PCI hotplug core remains the only user of this infrastructure, and thus, /sys/bus/pci/slots/ will still only become populated when a hotplug driver is loaded. A later patch in this series will add a second user of this new infrastructure and demonstrate splitting the task of exposing pci_slot attributes from hotplug_slot attributes. - Make pci_slot the primary sysfs entity. hotplug_slot becomes a subsidiary structure. o pci_create_slot() creates and registers a slot with the PCI core o pci_slot_add_hotplug() gives it hotplug capability - Change the prototype of pci_hp_register() to take the bus and slot number (on parent bus) as parameters. - Remove all the ->get_address methods since this functionality is now handled by pci_slot directly. [achiang@hp.com: rpaphp-correctly-pci_hp_register-for-empty-pci-slots] Tested-by: Badari Pulavarty <pbadari@us.ibm.com> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> [akpm@linux-foundation.org: build fix] [akpm@linux-foundation.org: make headers_check happy] [akpm@linux-foundation.org: nuther build fix] [akpm@linux-foundation.org: fix typo in #include] Signed-off-by: Alex Chiang <achiang@hp.com> Signed-off-by: Matthew Wilcox <matthew@wil.cx> Cc: Greg KH <greg@kroah.com> Cc: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Cc: Len Brown <lenb@kernel.org> Acked-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--drivers/pci/Makefile2
-rw-r--r--drivers/pci/hotplug/acpiphp.h1
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c25
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c23
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c6
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_core.c2
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c4
-rw-r--r--drivers/pci/hotplug/fakephp.c2
-rw-r--r--drivers/pci/hotplug/ibmphp_ebda.c3
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c258
-rw-r--r--drivers/pci/hotplug/pciehp_core.c32
-rw-r--r--drivers/pci/hotplug/rpadlpar_sysfs.c5
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c44
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c10
-rw-r--r--drivers/pci/hotplug/shpchp_core.c20
-rw-r--r--drivers/pci/pci.h13
-rw-r--r--drivers/pci/probe.c1
-rw-r--r--drivers/pci/slot.c233
-rw-r--r--include/linux/pci.h19
-rw-r--r--include/linux/pci_hotplug.h12
20 files changed, 422 insertions, 293 deletions
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 4d1ce2e7361e..7d63f8ced24b 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -2,7 +2,7 @@
2# Makefile for the PCI bus specific drivers. 2# Makefile for the PCI bus specific drivers.
3# 3#
4 4
5obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \ 5obj-y += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \
6 pci-driver.o search.o pci-sysfs.o rom.o setup-res.o 6 pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
7obj-$(CONFIG_PROC_FS) += proc.o 7obj-$(CONFIG_PROC_FS) += proc.o
8 8
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 7a29164d4b32..eecf7cbf4139 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -215,7 +215,6 @@ extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);
215extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot); 215extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);
216extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); 216extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
217extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); 217extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
218extern u32 acpiphp_get_address (struct acpiphp_slot *slot);
219 218
220/* variables */ 219/* variables */
221extern int acpiphp_debug; 220extern int acpiphp_debug;
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index 7af68ba27903..0e496e866a84 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -70,7 +70,6 @@ static int disable_slot (struct hotplug_slot *slot);
70static int set_attention_status (struct hotplug_slot *slot, u8 value); 70static int set_attention_status (struct hotplug_slot *slot, u8 value);
71static int get_power_status (struct hotplug_slot *slot, u8 *value); 71static int get_power_status (struct hotplug_slot *slot, u8 *value);
72static int get_attention_status (struct hotplug_slot *slot, u8 *value); 72static int get_attention_status (struct hotplug_slot *slot, u8 *value);
73static int get_address (struct hotplug_slot *slot, u32 *value);
74static int get_latch_status (struct hotplug_slot *slot, u8 *value); 73static int get_latch_status (struct hotplug_slot *slot, u8 *value);
75static int get_adapter_status (struct hotplug_slot *slot, u8 *value); 74static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
76 75
@@ -83,7 +82,6 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = {
83 .get_attention_status = get_attention_status, 82 .get_attention_status = get_attention_status,
84 .get_latch_status = get_latch_status, 83 .get_latch_status = get_latch_status,
85 .get_adapter_status = get_adapter_status, 84 .get_adapter_status = get_adapter_status,
86 .get_address = get_address,
87}; 85};
88 86
89 87
@@ -274,23 +272,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
274 return 0; 272 return 0;
275} 273}
276 274
277
278/**
279 * get_address - get pci address of a slot
280 * @hotplug_slot: slot to get status
281 * @value: pointer to struct pci_busdev (seg, bus, dev)
282 */
283static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
284{
285 struct slot *slot = hotplug_slot->private;
286
287 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
288
289 *value = acpiphp_get_address(slot->acpi_slot);
290
291 return 0;
292}
293
294static int __init init_acpi(void) 275static int __init init_acpi(void)
295{ 276{
296 int retval; 277 int retval;
@@ -357,7 +338,11 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
357 acpiphp_slot->slot = slot; 338 acpiphp_slot->slot = slot;
358 snprintf(slot->name, sizeof(slot->name), "%u", slot->acpi_slot->sun); 339 snprintf(slot->name, sizeof(slot->name), "%u", slot->acpi_slot->sun);
359 340
360 retval = pci_hp_register(slot->hotplug_slot); 341 retval = pci_hp_register(slot->hotplug_slot,
342 acpiphp_slot->bridge->pci_bus,
343 acpiphp_slot->device);
344 if (retval == -EBUSY)
345 goto error_hpslot;
361 if (retval) { 346 if (retval) {
362 err("pci_hp_register failed with error %d\n", retval); 347 err("pci_hp_register failed with error %d\n", retval);
363 goto error_hpslot; 348 goto error_hpslot;
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 648596d469f6..9342c848db29 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -258,7 +258,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
258 bridge->pci_bus->number, slot->device); 258 bridge->pci_bus->number, slot->device);
259 retval = acpiphp_register_hotplug_slot(slot); 259 retval = acpiphp_register_hotplug_slot(slot);
260 if (retval) { 260 if (retval) {
261 warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval); 261 if (retval == -EBUSY)
262 warn("Slot %d already registered by another "
263 "hotplug driver\n", slot->sun);
264 else
265 warn("acpiphp_register_hotplug_slot failed "
266 "(err code = 0x%x)\n", retval);
262 goto err_exit; 267 goto err_exit;
263 } 268 }
264 } 269 }
@@ -1867,19 +1872,3 @@ u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot)
1867 1872
1868 return (sta == 0) ? 0 : 1; 1873 return (sta == 0) ? 0 : 1;
1869} 1874}
1870
1871
1872/*
1873 * pci address (seg/bus/dev)
1874 */
1875u32 acpiphp_get_address(struct acpiphp_slot *slot)
1876{
1877 u32 address;
1878 struct pci_bus *pci_bus = slot->bridge->pci_bus;
1879
1880 address = (pci_domain_nr(pci_bus) << 16) |
1881 (pci_bus->number << 8) |
1882 slot->device;
1883
1884 return address;
1885}
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index ede9051fdb5d..2b7c45e39370 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -33,8 +33,10 @@
33#include <linux/kobject.h> 33#include <linux/kobject.h>
34#include <asm/uaccess.h> 34#include <asm/uaccess.h>
35#include <linux/moduleparam.h> 35#include <linux/moduleparam.h>
36#include <linux/pci.h>
36 37
37#include "acpiphp.h" 38#include "acpiphp.h"
39#include "../pci.h"
38 40
39#define DRIVER_VERSION "1.0.1" 41#define DRIVER_VERSION "1.0.1"
40#define DRIVER_AUTHOR "Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>" 42#define DRIVER_AUTHOR "Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"
@@ -430,7 +432,7 @@ static int __init ibm_acpiphp_init(void)
430 int retval = 0; 432 int retval = 0;
431 acpi_status status; 433 acpi_status status;
432 struct acpi_device *device; 434 struct acpi_device *device;
433 struct kobject *sysdir = &pci_hotplug_slots_kset->kobj; 435 struct kobject *sysdir = &pci_slots_kset->kobj;
434 436
435 dbg("%s\n", __func__); 437 dbg("%s\n", __func__);
436 438
@@ -477,7 +479,7 @@ init_return:
477static void __exit ibm_acpiphp_exit(void) 479static void __exit ibm_acpiphp_exit(void)
478{ 480{
479 acpi_status status; 481 acpi_status status;
480 struct kobject *sysdir = &pci_hotplug_slots_kset->kobj; 482 struct kobject *sysdir = &pci_slots_kset->kobj;
481 483
482 dbg("%s\n", __func__); 484 dbg("%s\n", __func__);
483 485
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index d8a6b80ab42a..935947991dc9 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -285,7 +285,7 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
285 info->attention_status = cpci_get_attention_status(slot); 285 info->attention_status = cpci_get_attention_status(slot);
286 286
287 dbg("registering slot %s", slot->hotplug_slot->name); 287 dbg("registering slot %s", slot->hotplug_slot->name);
288 status = pci_hp_register(slot->hotplug_slot); 288 status = pci_hp_register(slot->hotplug_slot, bus, i);
289 if (status) { 289 if (status) {
290 err("pci_hp_register failed with error %d", status); 290 err("pci_hp_register failed with error %d", status);
291 goto error_name; 291 goto error_name;
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 36b115b27b0b..54defec51d08 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -434,7 +434,9 @@ static int ctrl_slot_setup(struct controller *ctrl,
434 slot->bus, slot->device, 434 slot->bus, slot->device,
435 slot->number, ctrl->slot_device_offset, 435 slot->number, ctrl->slot_device_offset,
436 slot_number); 436 slot_number);
437 result = pci_hp_register(hotplug_slot); 437 result = pci_hp_register(hotplug_slot,
438 ctrl->pci_dev->subordinate,
439 slot->device);
438 if (result) { 440 if (result) {
439 err("pci_hp_register failed with error %d\n", result); 441 err("pci_hp_register failed with error %d\n", result);
440 goto error_name; 442 goto error_name;
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index b57223f7e830..40337a06c18a 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -126,7 +126,7 @@ static int add_slot(struct pci_dev *dev)
126 slot->release = &dummy_release; 126 slot->release = &dummy_release;
127 slot->private = dslot; 127 slot->private = dslot;
128 128
129 retval = pci_hp_register(slot); 129 retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn));
130 if (retval) { 130 if (retval) {
131 err("pci_hp_register failed with error %d\n", retval); 131 err("pci_hp_register failed with error %d\n", retval);
132 goto error_dslot; 132 goto error_dslot;
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
index dca7efc14be2..8467d0287325 100644
--- a/drivers/pci/hotplug/ibmphp_ebda.c
+++ b/drivers/pci/hotplug/ibmphp_ebda.c
@@ -1001,7 +1001,8 @@ static int __init ebda_rsrc_controller (void)
1001 tmp_slot = list_entry (list, struct slot, ibm_slot_list); 1001 tmp_slot = list_entry (list, struct slot, ibm_slot_list);
1002 1002
1003 snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot)); 1003 snprintf (tmp_slot->hotplug_slot->name, 30, "%s", create_file_name (tmp_slot));
1004 pci_hp_register (tmp_slot->hotplug_slot); 1004 pci_hp_register(tmp_slot->hotplug_slot,
1005 pci_find_bus(0, tmp_slot->bus), tmp_slot->device);
1005 } 1006 }
1006 1007
1007 print_ebda_hpc (); 1008 print_ebda_hpc ();
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index a11021e8ce37..4df31f375197 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -40,6 +40,7 @@
40#include <linux/pci.h> 40#include <linux/pci.h>
41#include <linux/pci_hotplug.h> 41#include <linux/pci_hotplug.h>
42#include <asm/uaccess.h> 42#include <asm/uaccess.h>
43#include "../pci.h"
43 44
44#define MY_NAME "pci_hotplug" 45#define MY_NAME "pci_hotplug"
45 46
@@ -60,41 +61,7 @@ static int debug;
60////////////////////////////////////////////////////////////////// 61//////////////////////////////////////////////////////////////////
61 62
62static LIST_HEAD(pci_hotplug_slot_list); 63static LIST_HEAD(pci_hotplug_slot_list);
63 64static DEFINE_SPINLOCK(pci_hotplug_slot_list_lock);
64struct kset *pci_hotplug_slots_kset;
65
66static ssize_t hotplug_slot_attr_show(struct kobject *kobj,
67 struct attribute *attr, char *buf)
68{
69 struct hotplug_slot *slot = to_hotplug_slot(kobj);
70 struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr);
71 return attribute->show ? attribute->show(slot, buf) : -EIO;
72}
73
74static ssize_t hotplug_slot_attr_store(struct kobject *kobj,
75 struct attribute *attr, const char *buf, size_t len)
76{
77 struct hotplug_slot *slot = to_hotplug_slot(kobj);
78 struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr);
79 return attribute->store ? attribute->store(slot, buf, len) : -EIO;
80}
81
82static struct sysfs_ops hotplug_slot_sysfs_ops = {
83 .show = hotplug_slot_attr_show,
84 .store = hotplug_slot_attr_store,
85};
86
87static void hotplug_slot_release(struct kobject *kobj)
88{
89 struct hotplug_slot *slot = to_hotplug_slot(kobj);
90 if (slot->release)
91 slot->release(slot);
92}
93
94static struct kobj_type hotplug_slot_ktype = {
95 .sysfs_ops = &hotplug_slot_sysfs_ops,
96 .release = &hotplug_slot_release,
97};
98 65
99/* these strings match up with the values in pci_bus_speed */ 66/* these strings match up with the values in pci_bus_speed */
100static char *pci_bus_speed_strings[] = { 67static char *pci_bus_speed_strings[] = {
@@ -149,16 +116,15 @@ GET_STATUS(power_status, u8)
149GET_STATUS(attention_status, u8) 116GET_STATUS(attention_status, u8)
150GET_STATUS(latch_status, u8) 117GET_STATUS(latch_status, u8)
151GET_STATUS(adapter_status, u8) 118GET_STATUS(adapter_status, u8)
152GET_STATUS(address, u32)
153GET_STATUS(max_bus_speed, enum pci_bus_speed) 119GET_STATUS(max_bus_speed, enum pci_bus_speed)
154GET_STATUS(cur_bus_speed, enum pci_bus_speed) 120GET_STATUS(cur_bus_speed, enum pci_bus_speed)
155 121
156static ssize_t power_read_file (struct hotplug_slot *slot, char *buf) 122static ssize_t power_read_file(struct pci_slot *slot, char *buf)
157{ 123{
158 int retval; 124 int retval;
159 u8 value; 125 u8 value;
160 126
161 retval = get_power_status (slot, &value); 127 retval = get_power_status(slot->hotplug, &value);
162 if (retval) 128 if (retval)
163 goto exit; 129 goto exit;
164 retval = sprintf (buf, "%d\n", value); 130 retval = sprintf (buf, "%d\n", value);
@@ -166,9 +132,10 @@ exit:
166 return retval; 132 return retval;
167} 133}
168 134
169static ssize_t power_write_file (struct hotplug_slot *slot, const char *buf, 135static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf,
170 size_t count) 136 size_t count)
171{ 137{
138 struct hotplug_slot *slot = pci_slot->hotplug;
172 unsigned long lpower; 139 unsigned long lpower;
173 u8 power; 140 u8 power;
174 int retval = 0; 141 int retval = 0;
@@ -204,29 +171,30 @@ exit:
204 return count; 171 return count;
205} 172}
206 173
207static struct hotplug_slot_attribute hotplug_slot_attr_power = { 174static struct pci_slot_attribute hotplug_slot_attr_power = {
208 .attr = {.name = "power", .mode = S_IFREG | S_IRUGO | S_IWUSR}, 175 .attr = {.name = "power", .mode = S_IFREG | S_IRUGO | S_IWUSR},
209 .show = power_read_file, 176 .show = power_read_file,
210 .store = power_write_file 177 .store = power_write_file
211}; 178};
212 179
213static ssize_t attention_read_file (struct hotplug_slot *slot, char *buf) 180static ssize_t attention_read_file(struct pci_slot *slot, char *buf)
214{ 181{
215 int retval; 182 int retval;
216 u8 value; 183 u8 value;
217 184
218 retval = get_attention_status (slot, &value); 185 retval = get_attention_status(slot->hotplug, &value);
219 if (retval) 186 if (retval)
220 goto exit; 187 goto exit;
221 retval = sprintf (buf, "%d\n", value); 188 retval = sprintf(buf, "%d\n", value);
222 189
223exit: 190exit:
224 return retval; 191 return retval;
225} 192}
226 193
227static ssize_t attention_write_file (struct hotplug_slot *slot, const char *buf, 194static ssize_t attention_write_file(struct pci_slot *slot, const char *buf,
228 size_t count) 195 size_t count)
229{ 196{
197 struct hotplug_slot_ops *ops = slot->hotplug->ops;
230 unsigned long lattention; 198 unsigned long lattention;
231 u8 attention; 199 u8 attention;
232 int retval = 0; 200 int retval = 0;
@@ -235,13 +203,13 @@ static ssize_t attention_write_file (struct hotplug_slot *slot, const char *buf,
235 attention = (u8)(lattention & 0xff); 203 attention = (u8)(lattention & 0xff);
236 dbg (" - attention = %d\n", attention); 204 dbg (" - attention = %d\n", attention);
237 205
238 if (!try_module_get(slot->ops->owner)) { 206 if (!try_module_get(ops->owner)) {
239 retval = -ENODEV; 207 retval = -ENODEV;
240 goto exit; 208 goto exit;
241 } 209 }
242 if (slot->ops->set_attention_status) 210 if (ops->set_attention_status)
243 retval = slot->ops->set_attention_status(slot, attention); 211 retval = ops->set_attention_status(slot->hotplug, attention);
244 module_put(slot->ops->owner); 212 module_put(ops->owner);
245 213
246exit: 214exit:
247 if (retval) 215 if (retval)
@@ -249,18 +217,18 @@ exit:
249 return count; 217 return count;
250} 218}
251 219
252static struct hotplug_slot_attribute hotplug_slot_attr_attention = { 220static struct pci_slot_attribute hotplug_slot_attr_attention = {
253 .attr = {.name = "attention", .mode = S_IFREG | S_IRUGO | S_IWUSR}, 221 .attr = {.name = "attention", .mode = S_IFREG | S_IRUGO | S_IWUSR},
254 .show = attention_read_file, 222 .show = attention_read_file,
255 .store = attention_write_file 223 .store = attention_write_file
256}; 224};
257 225
258static ssize_t latch_read_file (struct hotplug_slot *slot, char *buf) 226static ssize_t latch_read_file(struct pci_slot *slot, char *buf)
259{ 227{
260 int retval; 228 int retval;
261 u8 value; 229 u8 value;
262 230
263 retval = get_latch_status (slot, &value); 231 retval = get_latch_status(slot->hotplug, &value);
264 if (retval) 232 if (retval)
265 goto exit; 233 goto exit;
266 retval = sprintf (buf, "%d\n", value); 234 retval = sprintf (buf, "%d\n", value);
@@ -269,17 +237,17 @@ exit:
269 return retval; 237 return retval;
270} 238}
271 239
272static struct hotplug_slot_attribute hotplug_slot_attr_latch = { 240static struct pci_slot_attribute hotplug_slot_attr_latch = {
273 .attr = {.name = "latch", .mode = S_IFREG | S_IRUGO}, 241 .attr = {.name = "latch", .mode = S_IFREG | S_IRUGO},
274 .show = latch_read_file, 242 .show = latch_read_file,
275}; 243};
276 244
277static ssize_t presence_read_file (struct hotplug_slot *slot, char *buf) 245static ssize_t presence_read_file(struct pci_slot *slot, char *buf)
278{ 246{
279 int retval; 247 int retval;
280 u8 value; 248 u8 value;
281 249
282 retval = get_adapter_status (slot, &value); 250 retval = get_adapter_status(slot->hotplug, &value);
283 if (retval) 251 if (retval)
284 goto exit; 252 goto exit;
285 retval = sprintf (buf, "%d\n", value); 253 retval = sprintf (buf, "%d\n", value);
@@ -288,42 +256,20 @@ exit:
288 return retval; 256 return retval;
289} 257}
290 258
291static struct hotplug_slot_attribute hotplug_slot_attr_presence = { 259static struct pci_slot_attribute hotplug_slot_attr_presence = {
292 .attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO}, 260 .attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO},
293 .show = presence_read_file, 261 .show = presence_read_file,
294}; 262};
295 263
296static ssize_t address_read_file (struct hotplug_slot *slot, char *buf)
297{
298 int retval;
299 u32 address;
300
301 retval = get_address (slot, &address);
302 if (retval)
303 goto exit;
304 retval = sprintf (buf, "%04x:%02x:%02x\n",
305 (address >> 16) & 0xffff,
306 (address >> 8) & 0xff,
307 address & 0xff);
308
309exit:
310 return retval;
311}
312
313static struct hotplug_slot_attribute hotplug_slot_attr_address = {
314 .attr = {.name = "address", .mode = S_IFREG | S_IRUGO},
315 .show = address_read_file,
316};
317
318static char *unknown_speed = "Unknown bus speed"; 264static char *unknown_speed = "Unknown bus speed";
319 265
320static ssize_t max_bus_speed_read_file (struct hotplug_slot *slot, char *buf) 266static ssize_t max_bus_speed_read_file(struct pci_slot *slot, char *buf)
321{ 267{
322 char *speed_string; 268 char *speed_string;
323 int retval; 269 int retval;
324 enum pci_bus_speed value; 270 enum pci_bus_speed value;
325 271
326 retval = get_max_bus_speed (slot, &value); 272 retval = get_max_bus_speed(slot->hotplug, &value);
327 if (retval) 273 if (retval)
328 goto exit; 274 goto exit;
329 275
@@ -338,18 +284,18 @@ exit:
338 return retval; 284 return retval;
339} 285}
340 286
341static struct hotplug_slot_attribute hotplug_slot_attr_max_bus_speed = { 287static struct pci_slot_attribute hotplug_slot_attr_max_bus_speed = {
342 .attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO}, 288 .attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO},
343 .show = max_bus_speed_read_file, 289 .show = max_bus_speed_read_file,
344}; 290};
345 291
346static ssize_t cur_bus_speed_read_file (struct hotplug_slot *slot, char *buf) 292static ssize_t cur_bus_speed_read_file(struct pci_slot *slot, char *buf)
347{ 293{
348 char *speed_string; 294 char *speed_string;
349 int retval; 295 int retval;
350 enum pci_bus_speed value; 296 enum pci_bus_speed value;
351 297
352 retval = get_cur_bus_speed (slot, &value); 298 retval = get_cur_bus_speed(slot->hotplug, &value);
353 if (retval) 299 if (retval)
354 goto exit; 300 goto exit;
355 301
@@ -364,14 +310,15 @@ exit:
364 return retval; 310 return retval;
365} 311}
366 312
367static struct hotplug_slot_attribute hotplug_slot_attr_cur_bus_speed = { 313static struct pci_slot_attribute hotplug_slot_attr_cur_bus_speed = {
368 .attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO}, 314 .attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO},
369 .show = cur_bus_speed_read_file, 315 .show = cur_bus_speed_read_file,
370}; 316};
371 317
372static ssize_t test_write_file (struct hotplug_slot *slot, const char *buf, 318static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf,
373 size_t count) 319 size_t count)
374{ 320{
321 struct hotplug_slot *slot = pci_slot->hotplug;
375 unsigned long ltest; 322 unsigned long ltest;
376 u32 test; 323 u32 test;
377 int retval = 0; 324 int retval = 0;
@@ -394,13 +341,14 @@ exit:
394 return count; 341 return count;
395} 342}
396 343
397static struct hotplug_slot_attribute hotplug_slot_attr_test = { 344static struct pci_slot_attribute hotplug_slot_attr_test = {
398 .attr = {.name = "test", .mode = S_IFREG | S_IRUGO | S_IWUSR}, 345 .attr = {.name = "test", .mode = S_IFREG | S_IRUGO | S_IWUSR},
399 .store = test_write_file 346 .store = test_write_file
400}; 347};
401 348
402static int has_power_file (struct hotplug_slot *slot) 349static int has_power_file(struct pci_slot *pci_slot)
403{ 350{
351 struct hotplug_slot *slot = pci_slot->hotplug;
404 if ((!slot) || (!slot->ops)) 352 if ((!slot) || (!slot->ops))
405 return -ENODEV; 353 return -ENODEV;
406 if ((slot->ops->enable_slot) || 354 if ((slot->ops->enable_slot) ||
@@ -410,8 +358,9 @@ static int has_power_file (struct hotplug_slot *slot)
410 return -ENOENT; 358 return -ENOENT;
411} 359}
412 360
413static int has_attention_file (struct hotplug_slot *slot) 361static int has_attention_file(struct pci_slot *pci_slot)
414{ 362{
363 struct hotplug_slot *slot = pci_slot->hotplug;
415 if ((!slot) || (!slot->ops)) 364 if ((!slot) || (!slot->ops))
416 return -ENODEV; 365 return -ENODEV;
417 if ((slot->ops->set_attention_status) || 366 if ((slot->ops->set_attention_status) ||
@@ -420,8 +369,9 @@ static int has_attention_file (struct hotplug_slot *slot)
420 return -ENOENT; 369 return -ENOENT;
421} 370}
422 371
423static int has_latch_file (struct hotplug_slot *slot) 372static int has_latch_file(struct pci_slot *pci_slot)
424{ 373{
374 struct hotplug_slot *slot = pci_slot->hotplug;
425 if ((!slot) || (!slot->ops)) 375 if ((!slot) || (!slot->ops))
426 return -ENODEV; 376 return -ENODEV;
427 if (slot->ops->get_latch_status) 377 if (slot->ops->get_latch_status)
@@ -429,8 +379,9 @@ static int has_latch_file (struct hotplug_slot *slot)
429 return -ENOENT; 379 return -ENOENT;
430} 380}
431 381
432static int has_adapter_file (struct hotplug_slot *slot) 382static int has_adapter_file(struct pci_slot *pci_slot)
433{ 383{
384 struct hotplug_slot *slot = pci_slot->hotplug;
434 if ((!slot) || (!slot->ops)) 385 if ((!slot) || (!slot->ops))
435 return -ENODEV; 386 return -ENODEV;
436 if (slot->ops->get_adapter_status) 387 if (slot->ops->get_adapter_status)
@@ -438,17 +389,9 @@ static int has_adapter_file (struct hotplug_slot *slot)
438 return -ENOENT; 389 return -ENOENT;
439} 390}
440 391
441static int has_address_file (struct hotplug_slot *slot) 392static int has_max_bus_speed_file(struct pci_slot *pci_slot)
442{
443 if ((!slot) || (!slot->ops))
444 return -ENODEV;
445 if (slot->ops->get_address)
446 return 0;
447 return -ENOENT;
448}
449
450static int has_max_bus_speed_file (struct hotplug_slot *slot)
451{ 393{
394 struct hotplug_slot *slot = pci_slot->hotplug;
452 if ((!slot) || (!slot->ops)) 395 if ((!slot) || (!slot->ops))
453 return -ENODEV; 396 return -ENODEV;
454 if (slot->ops->get_max_bus_speed) 397 if (slot->ops->get_max_bus_speed)
@@ -456,8 +399,9 @@ static int has_max_bus_speed_file (struct hotplug_slot *slot)
456 return -ENOENT; 399 return -ENOENT;
457} 400}
458 401
459static int has_cur_bus_speed_file (struct hotplug_slot *slot) 402static int has_cur_bus_speed_file(struct pci_slot *pci_slot)
460{ 403{
404 struct hotplug_slot *slot = pci_slot->hotplug;
461 if ((!slot) || (!slot->ops)) 405 if ((!slot) || (!slot->ops))
462 return -ENODEV; 406 return -ENODEV;
463 if (slot->ops->get_cur_bus_speed) 407 if (slot->ops->get_cur_bus_speed)
@@ -465,8 +409,9 @@ static int has_cur_bus_speed_file (struct hotplug_slot *slot)
465 return -ENOENT; 409 return -ENOENT;
466} 410}
467 411
468static int has_test_file (struct hotplug_slot *slot) 412static int has_test_file(struct pci_slot *pci_slot)
469{ 413{
414 struct hotplug_slot *slot = pci_slot->hotplug;
470 if ((!slot) || (!slot->ops)) 415 if ((!slot) || (!slot->ops))
471 return -ENODEV; 416 return -ENODEV;
472 if (slot->ops->hardware_test) 417 if (slot->ops->hardware_test)
@@ -474,7 +419,7 @@ static int has_test_file (struct hotplug_slot *slot)
474 return -ENOENT; 419 return -ENOENT;
475} 420}
476 421
477static int fs_add_slot (struct hotplug_slot *slot) 422static int fs_add_slot(struct pci_slot *slot)
478{ 423{
479 int retval = 0; 424 int retval = 0;
480 425
@@ -505,13 +450,6 @@ static int fs_add_slot (struct hotplug_slot *slot)
505 goto exit_adapter; 450 goto exit_adapter;
506 } 451 }
507 452
508 if (has_address_file(slot) == 0) {
509 retval = sysfs_create_file(&slot->kobj,
510 &hotplug_slot_attr_address.attr);
511 if (retval)
512 goto exit_address;
513 }
514
515 if (has_max_bus_speed_file(slot) == 0) { 453 if (has_max_bus_speed_file(slot) == 0) {
516 retval = sysfs_create_file(&slot->kobj, 454 retval = sysfs_create_file(&slot->kobj,
517 &hotplug_slot_attr_max_bus_speed.attr); 455 &hotplug_slot_attr_max_bus_speed.attr);
@@ -544,10 +482,6 @@ exit_cur_speed:
544 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); 482 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
545 483
546exit_max_speed: 484exit_max_speed:
547 if (has_address_file(slot) == 0)
548 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_address.attr);
549
550exit_address:
551 if (has_adapter_file(slot) == 0) 485 if (has_adapter_file(slot) == 0)
552 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr); 486 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
553 487
@@ -567,7 +501,7 @@ exit:
567 return retval; 501 return retval;
568} 502}
569 503
570static void fs_remove_slot (struct hotplug_slot *slot) 504static void fs_remove_slot(struct pci_slot *slot)
571{ 505{
572 if (has_power_file(slot) == 0) 506 if (has_power_file(slot) == 0)
573 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr); 507 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
@@ -581,9 +515,6 @@ static void fs_remove_slot (struct hotplug_slot *slot)
581 if (has_adapter_file(slot) == 0) 515 if (has_adapter_file(slot) == 0)
582 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr); 516 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
583 517
584 if (has_address_file(slot) == 0)
585 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_address.attr);
586
587 if (has_max_bus_speed_file(slot) == 0) 518 if (has_max_bus_speed_file(slot) == 0)
588 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr); 519 sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
589 520
@@ -599,12 +530,16 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
599 struct hotplug_slot *slot; 530 struct hotplug_slot *slot;
600 struct list_head *tmp; 531 struct list_head *tmp;
601 532
533 spin_lock(&pci_hotplug_slot_list_lock);
602 list_for_each (tmp, &pci_hotplug_slot_list) { 534 list_for_each (tmp, &pci_hotplug_slot_list) {
603 slot = list_entry (tmp, struct hotplug_slot, slot_list); 535 slot = list_entry (tmp, struct hotplug_slot, slot_list);
604 if (strcmp(slot->name, name) == 0) 536 if (strcmp(slot->name, name) == 0)
605 return slot; 537 goto out;
606 } 538 }
607 return NULL; 539 slot = NULL;
540out:
541 spin_unlock(&pci_hotplug_slot_list_lock);
542 return slot;
608} 543}
609 544
610/** 545/**
@@ -616,9 +551,10 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
616 * 551 *
617 * Returns 0 if successful, anything else for an error. 552 * Returns 0 if successful, anything else for an error.
618 */ 553 */
619int pci_hp_register (struct hotplug_slot *slot) 554int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr)
620{ 555{
621 int result; 556 int result;
557 struct pci_slot *pci_slot;
622 struct hotplug_slot *tmp; 558 struct hotplug_slot *tmp;
623 559
624 if (slot == NULL) 560 if (slot == NULL)
@@ -636,19 +572,28 @@ int pci_hp_register (struct hotplug_slot *slot)
636 if (tmp) 572 if (tmp)
637 return -EEXIST; 573 return -EEXIST;
638 574
639 slot->kobj.kset = pci_hotplug_slots_kset; 575 pci_slot = pci_create_slot(bus, slot_nr, slot->name);
640 result = kobject_init_and_add(&slot->kobj, &hotplug_slot_ktype, NULL, 576 if (IS_ERR(pci_slot))
641 "%s", slot->name); 577 return PTR_ERR(pci_slot);
642 if (result) { 578
643 err("Unable to register kobject '%s'", slot->name); 579 if (pci_slot->hotplug) {
644 return -EINVAL; 580 dbg("%s: already claimed\n", __func__);
581 pci_destroy_slot(pci_slot);
582 return -EBUSY;
645 } 583 }
646 584
647 list_add (&slot->slot_list, &pci_hotplug_slot_list); 585 slot->pci_slot = pci_slot;
586 pci_slot->hotplug = slot;
587
588 spin_lock(&pci_hotplug_slot_list_lock);
589 list_add(&slot->slot_list, &pci_hotplug_slot_list);
590 spin_unlock(&pci_hotplug_slot_list_lock);
591
592 result = fs_add_slot(pci_slot);
593 kobject_uevent(&pci_slot->kobj, KOBJ_ADD);
594 dbg("Added slot %s to the list\n", slot->name);
595
648 596
649 result = fs_add_slot (slot);
650 kobject_uevent(&slot->kobj, KOBJ_ADD);
651 dbg ("Added slot %s to the list\n", slot->name);
652 return result; 597 return result;
653} 598}
654 599
@@ -661,22 +606,30 @@ int pci_hp_register (struct hotplug_slot *slot)
661 * 606 *
662 * Returns 0 if successful, anything else for an error. 607 * Returns 0 if successful, anything else for an error.
663 */ 608 */
664int pci_hp_deregister (struct hotplug_slot *slot) 609int pci_hp_deregister(struct hotplug_slot *hotplug)
665{ 610{
666 struct hotplug_slot *temp; 611 struct hotplug_slot *temp;
612 struct pci_slot *slot;
667 613
668 if (slot == NULL) 614 if (!hotplug)
669 return -ENODEV; 615 return -ENODEV;
670 616
671 temp = get_slot_from_name (slot->name); 617 temp = get_slot_from_name(hotplug->name);
672 if (temp != slot) { 618 if (temp != hotplug)
673 return -ENODEV; 619 return -ENODEV;
674 }
675 list_del (&slot->slot_list);
676 620
677 fs_remove_slot (slot); 621 spin_lock(&pci_hotplug_slot_list_lock);
678 dbg ("Removed slot %s from the list\n", slot->name); 622 list_del(&hotplug->slot_list);
679 kobject_put(&slot->kobj); 623 spin_unlock(&pci_hotplug_slot_list_lock);
624
625 slot = hotplug->pci_slot;
626 fs_remove_slot(slot);
627 dbg("Removed slot %s from the list\n", hotplug->name);
628
629 hotplug->release(hotplug);
630 slot->hotplug = NULL;
631 pci_destroy_slot(slot);
632
680 return 0; 633 return 0;
681} 634}
682 635
@@ -690,13 +643,15 @@ int pci_hp_deregister (struct hotplug_slot *slot)
690 * 643 *
691 * Returns 0 if successful, anything else for an error. 644 * Returns 0 if successful, anything else for an error.
692 */ 645 */
693int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot, 646int __must_check pci_hp_change_slot_info(struct hotplug_slot *hotplug,
694 struct hotplug_slot_info *info) 647 struct hotplug_slot_info *info)
695{ 648{
696 if ((slot == NULL) || (info == NULL)) 649 struct pci_slot *slot;
650 if (!hotplug || !info)
697 return -ENODEV; 651 return -ENODEV;
652 slot = hotplug->pci_slot;
698 653
699 memcpy (slot->info, info, sizeof (struct hotplug_slot_info)); 654 memcpy(hotplug->info, info, sizeof(struct hotplug_slot_info));
700 655
701 return 0; 656 return 0;
702} 657}
@@ -704,36 +659,22 @@ int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
704static int __init pci_hotplug_init (void) 659static int __init pci_hotplug_init (void)
705{ 660{
706 int result; 661 int result;
707 struct kset *pci_bus_kset;
708 662
709 pci_bus_kset = bus_get_kset(&pci_bus_type);
710
711 pci_hotplug_slots_kset = kset_create_and_add("slots", NULL,
712 &pci_bus_kset->kobj);
713 if (!pci_hotplug_slots_kset) {
714 result = -ENOMEM;
715 err("Register subsys error\n");
716 goto exit;
717 }
718 result = cpci_hotplug_init(debug); 663 result = cpci_hotplug_init(debug);
719 if (result) { 664 if (result) {
720 err ("cpci_hotplug_init with error %d\n", result); 665 err ("cpci_hotplug_init with error %d\n", result);
721 goto err_subsys; 666 goto err_cpci;
722 } 667 }
723 668
724 info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); 669 info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
725 goto exit;
726 670
727err_subsys: 671err_cpci:
728 kset_unregister(pci_hotplug_slots_kset);
729exit:
730 return result; 672 return result;
731} 673}
732 674
733static void __exit pci_hotplug_exit (void) 675static void __exit pci_hotplug_exit (void)
734{ 676{
735 cpci_hotplug_exit(); 677 cpci_hotplug_exit();
736 kset_unregister(pci_hotplug_slots_kset);
737} 678}
738 679
739module_init(pci_hotplug_init); 680module_init(pci_hotplug_init);
@@ -745,7 +686,6 @@ MODULE_LICENSE("GPL");
745module_param(debug, bool, 0644); 686module_param(debug, bool, 0644);
746MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); 687MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
747 688
748EXPORT_SYMBOL_GPL(pci_hotplug_slots_kset);
749EXPORT_SYMBOL_GPL(pci_hp_register); 689EXPORT_SYMBOL_GPL(pci_hp_register);
750EXPORT_SYMBOL_GPL(pci_hp_deregister); 690EXPORT_SYMBOL_GPL(pci_hp_deregister);
751EXPORT_SYMBOL_GPL(pci_hp_change_slot_info); 691EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 49414e9100de..7b21c86e4bff 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -72,7 +72,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);
72static int get_attention_status (struct hotplug_slot *slot, u8 *value); 72static int get_attention_status (struct hotplug_slot *slot, u8 *value);
73static int get_latch_status (struct hotplug_slot *slot, u8 *value); 73static int get_latch_status (struct hotplug_slot *slot, u8 *value);
74static int get_adapter_status (struct hotplug_slot *slot, u8 *value); 74static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
75static int get_address (struct hotplug_slot *slot, u32 *value);
76static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); 75static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
77static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); 76static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
78 77
@@ -85,7 +84,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
85 .get_attention_status = get_attention_status, 84 .get_attention_status = get_attention_status,
86 .get_latch_status = get_latch_status, 85 .get_latch_status = get_latch_status,
87 .get_adapter_status = get_adapter_status, 86 .get_adapter_status = get_adapter_status,
88 .get_address = get_address,
89 .get_max_bus_speed = get_max_bus_speed, 87 .get_max_bus_speed = get_max_bus_speed,
90 .get_cur_bus_speed = get_cur_bus_speed, 88 .get_cur_bus_speed = get_cur_bus_speed,
91}; 89};
@@ -252,7 +250,9 @@ static int init_slots(struct controller *ctrl)
252 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " 250 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
253 "slot_device_offset=%x\n", slot->bus, slot->device, 251 "slot_device_offset=%x\n", slot->bus, slot->device,
254 slot->hp_slot, slot->number, ctrl->slot_device_offset); 252 slot->hp_slot, slot->number, ctrl->slot_device_offset);
255 retval = pci_hp_register(hotplug_slot); 253 retval = pci_hp_register(hotplug_slot,
254 ctrl->pci_dev->subordinate,
255 slot->device);
256 if (retval) { 256 if (retval) {
257 err("pci_hp_register failed with error %d\n", retval); 257 err("pci_hp_register failed with error %d\n", retval);
258 if (retval == -EEXIST) 258 if (retval == -EEXIST)
@@ -263,7 +263,7 @@ static int init_slots(struct controller *ctrl)
263 } 263 }
264 /* create additional sysfs entries */ 264 /* create additional sysfs entries */
265 if (EMI(ctrl)) { 265 if (EMI(ctrl)) {
266 retval = sysfs_create_file(&hotplug_slot->kobj, 266 retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
267 &hotplug_slot_attr_lock.attr); 267 &hotplug_slot_attr_lock.attr);
268 if (retval) { 268 if (retval) {
269 pci_hp_deregister(hotplug_slot); 269 pci_hp_deregister(hotplug_slot);
@@ -296,7 +296,7 @@ static void cleanup_slots(struct controller *ctrl)
296 slot = list_entry(tmp, struct slot, slot_list); 296 slot = list_entry(tmp, struct slot, slot_list);
297 list_del(&slot->slot_list); 297 list_del(&slot->slot_list);
298 if (EMI(ctrl)) 298 if (EMI(ctrl))
299 sysfs_remove_file(&slot->hotplug_slot->kobj, 299 sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
300 &hotplug_slot_attr_lock.attr); 300 &hotplug_slot_attr_lock.attr);
301 cancel_delayed_work(&slot->work); 301 cancel_delayed_work(&slot->work);
302 flush_scheduled_work(); 302 flush_scheduled_work();
@@ -398,19 +398,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
398 return 0; 398 return 0;
399} 399}
400 400
401static int get_address(struct hotplug_slot *hotplug_slot, u32 *value) 401static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
402{ 402 enum pci_bus_speed *value)
403 struct slot *slot = hotplug_slot->private;
404 struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
405
406 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
407
408 *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
409
410 return 0;
411}
412
413static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
414{ 403{
415 struct slot *slot = hotplug_slot->private; 404 struct slot *slot = hotplug_slot->private;
416 int retval; 405 int retval;
@@ -474,7 +463,12 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
474 /* Setup the slot information structures */ 463 /* Setup the slot information structures */
475 rc = init_slots(ctrl); 464 rc = init_slots(ctrl);
476 if (rc) { 465 if (rc) {
477 err("%s: slot initialization failed\n", PCIE_MODULE_NAME); 466 if (rc == -EBUSY)
467 warn("%s: slot already registered by another "
468 "hotplug driver\n", PCIE_MODULE_NAME);
469 else
470 err("%s: slot initialization failed\n",
471 PCIE_MODULE_NAME);
478 goto err_out_release_ctlr; 472 goto err_out_release_ctlr;
479 } 473 }
480 474
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c
index 779c5db71be4..a796301ea03f 100644
--- a/drivers/pci/hotplug/rpadlpar_sysfs.c
+++ b/drivers/pci/hotplug/rpadlpar_sysfs.c
@@ -14,8 +14,10 @@
14 */ 14 */
15#include <linux/kobject.h> 15#include <linux/kobject.h>
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/pci.h>
17#include <linux/pci_hotplug.h> 18#include <linux/pci_hotplug.h>
18#include "rpadlpar.h" 19#include "rpadlpar.h"
20#include "../pci.h"
19 21
20#define DLPAR_KOBJ_NAME "control" 22#define DLPAR_KOBJ_NAME "control"
21 23
@@ -27,7 +29,6 @@
27 29
28#define MAX_DRC_NAME_LEN 64 30#define MAX_DRC_NAME_LEN 64
29 31
30
31static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr, 32static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr,
32 const char *buf, size_t nbytes) 33 const char *buf, size_t nbytes)
33{ 34{
@@ -112,7 +113,7 @@ int dlpar_sysfs_init(void)
112 int error; 113 int error;
113 114
114 dlpar_kobj = kobject_create_and_add(DLPAR_KOBJ_NAME, 115 dlpar_kobj = kobject_create_and_add(DLPAR_KOBJ_NAME,
115 &pci_hotplug_slots_kset->kobj); 116 &pci_slots_kset->kobj);
116 if (!dlpar_kobj) 117 if (!dlpar_kobj)
117 return -EINVAL; 118 return -EINVAL;
118 119
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index 56197b600d36..9b714ea93d20 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -33,33 +33,6 @@
33#include <asm/rtas.h> 33#include <asm/rtas.h>
34#include "rpaphp.h" 34#include "rpaphp.h"
35 35
36static ssize_t address_read_file (struct hotplug_slot *php_slot, char *buf)
37{
38 int retval;
39 struct slot *slot = (struct slot *)php_slot->private;
40 struct pci_bus *bus;
41
42 if (!slot)
43 return -ENOENT;
44
45 bus = slot->bus;
46 if (!bus)
47 return -ENOENT;
48
49 if (bus->self)
50 retval = sprintf(buf, pci_name(bus->self));
51 else
52 retval = sprintf(buf, "%04x:%02x:00.0",
53 pci_domain_nr(bus), bus->number);
54
55 return retval;
56}
57
58static struct hotplug_slot_attribute php_attr_address = {
59 .attr = {.name = "address", .mode = S_IFREG | S_IRUGO},
60 .show = address_read_file,
61};
62
63/* free up the memory used by a slot */ 36/* free up the memory used by a slot */
64static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot) 37static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
65{ 38{
@@ -135,9 +108,6 @@ int rpaphp_deregister_slot(struct slot *slot)
135 108
136 list_del(&slot->rpaphp_slot_list); 109 list_del(&slot->rpaphp_slot_list);
137 110
138 /* remove "address" file */
139 sysfs_remove_file(&php_slot->kobj, &php_attr_address.attr);
140
141 retval = pci_hp_deregister(php_slot); 111 retval = pci_hp_deregister(php_slot);
142 if (retval) 112 if (retval)
143 err("Problem unregistering a slot %s\n", slot->name); 113 err("Problem unregistering a slot %s\n", slot->name);
@@ -151,6 +121,7 @@ int rpaphp_register_slot(struct slot *slot)
151{ 121{
152 struct hotplug_slot *php_slot = slot->hotplug_slot; 122 struct hotplug_slot *php_slot = slot->hotplug_slot;
153 int retval; 123 int retval;
124 int slotno;
154 125
155 dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n", 126 dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n",
156 __func__, slot->dn->full_name, slot->index, slot->name, 127 __func__, slot->dn->full_name, slot->index, slot->name,
@@ -162,19 +133,16 @@ int rpaphp_register_slot(struct slot *slot)
162 return -EAGAIN; 133 return -EAGAIN;
163 } 134 }
164 135
165 retval = pci_hp_register(php_slot); 136 if (slot->dn->child)
137 slotno = PCI_SLOT(PCI_DN(slot->dn->child)->devfn);
138 else
139 slotno = -1;
140 retval = pci_hp_register(php_slot, slot->bus, slotno);
166 if (retval) { 141 if (retval) {
167 err("pci_hp_register failed with error %d\n", retval); 142 err("pci_hp_register failed with error %d\n", retval);
168 return retval; 143 return retval;
169 } 144 }
170 145
171 /* create "address" file */
172 retval = sysfs_create_file(&php_slot->kobj, &php_attr_address.attr);
173 if (retval) {
174 err("sysfs_create_file failed with error %d\n", retval);
175 goto sysfs_fail;
176 }
177
178 /* add slot to our internal list */ 146 /* add slot to our internal list */
179 list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head); 147 list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
180 info("Slot [%s] registered\n", slot->name); 148 info("Slot [%s] registered\n", slot->name);
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index 2fe37cd85b69..2036a43ff2fd 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -197,13 +197,15 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
197static struct hotplug_slot * sn_hp_destroy(void) 197static struct hotplug_slot * sn_hp_destroy(void)
198{ 198{
199 struct slot *slot; 199 struct slot *slot;
200 struct pci_slot *pci_slot;
200 struct hotplug_slot *bss_hotplug_slot = NULL; 201 struct hotplug_slot *bss_hotplug_slot = NULL;
201 202
202 list_for_each_entry(slot, &sn_hp_list, hp_list) { 203 list_for_each_entry(slot, &sn_hp_list, hp_list) {
203 bss_hotplug_slot = slot->hotplug_slot; 204 bss_hotplug_slot = slot->hotplug_slot;
205 pci_slot = bss_hotplug_slot->pci_slot;
204 list_del(&((struct slot *)bss_hotplug_slot->private)-> 206 list_del(&((struct slot *)bss_hotplug_slot->private)->
205 hp_list); 207 hp_list);
206 sysfs_remove_file(&bss_hotplug_slot->kobj, 208 sysfs_remove_file(&pci_slot->kobj,
207 &sn_slot_path_attr.attr); 209 &sn_slot_path_attr.attr);
208 break; 210 break;
209 } 211 }
@@ -614,6 +616,7 @@ static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)
614static int sn_hotplug_slot_register(struct pci_bus *pci_bus) 616static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
615{ 617{
616 int device; 618 int device;
619 struct pci_slot *pci_slot;
617 struct hotplug_slot *bss_hotplug_slot; 620 struct hotplug_slot *bss_hotplug_slot;
618 int rc = 0; 621 int rc = 0;
619 622
@@ -650,11 +653,12 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
650 bss_hotplug_slot->ops = &sn_hotplug_slot_ops; 653 bss_hotplug_slot->ops = &sn_hotplug_slot_ops;
651 bss_hotplug_slot->release = &sn_release_slot; 654 bss_hotplug_slot->release = &sn_release_slot;
652 655
653 rc = pci_hp_register(bss_hotplug_slot); 656 rc = pci_hp_register(bss_hotplug_slot, pci_bus, device);
654 if (rc) 657 if (rc)
655 goto register_err; 658 goto register_err;
656 659
657 rc = sysfs_create_file(&bss_hotplug_slot->kobj, 660 pci_slot = bss_hotplug_slot->pci_slot;
661 rc = sysfs_create_file(&pci_slot->kobj,
658 &sn_slot_path_attr.attr); 662 &sn_slot_path_attr.attr);
659 if (rc) 663 if (rc)
660 goto register_err; 664 goto register_err;
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index df41ecc4e7fc..a8cbd039b85b 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -68,7 +68,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);
68static int get_attention_status (struct hotplug_slot *slot, u8 *value); 68static int get_attention_status (struct hotplug_slot *slot, u8 *value);
69static int get_latch_status (struct hotplug_slot *slot, u8 *value); 69static int get_latch_status (struct hotplug_slot *slot, u8 *value);
70static int get_adapter_status (struct hotplug_slot *slot, u8 *value); 70static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
71static int get_address (struct hotplug_slot *slot, u32 *value);
72static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); 71static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
73static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); 72static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
74 73
@@ -81,7 +80,6 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
81 .get_attention_status = get_attention_status, 80 .get_attention_status = get_attention_status,
82 .get_latch_status = get_latch_status, 81 .get_latch_status = get_latch_status,
83 .get_adapter_status = get_adapter_status, 82 .get_adapter_status = get_adapter_status,
84 .get_address = get_address,
85 .get_max_bus_speed = get_max_bus_speed, 83 .get_max_bus_speed = get_max_bus_speed,
86 .get_cur_bus_speed = get_cur_bus_speed, 84 .get_cur_bus_speed = get_cur_bus_speed,
87}; 85};
@@ -159,7 +157,8 @@ static int init_slots(struct controller *ctrl)
159 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " 157 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
160 "slot_device_offset=%x\n", slot->bus, slot->device, 158 "slot_device_offset=%x\n", slot->bus, slot->device,
161 slot->hp_slot, slot->number, ctrl->slot_device_offset); 159 slot->hp_slot, slot->number, ctrl->slot_device_offset);
162 retval = pci_hp_register(slot->hotplug_slot); 160 retval = pci_hp_register(slot->hotplug_slot,
161 ctrl->pci_dev->subordinate, slot->device);
163 if (retval) { 162 if (retval) {
164 err("pci_hp_register failed with error %d\n", retval); 163 err("pci_hp_register failed with error %d\n", retval);
165 if (retval == -EEXIST) 164 if (retval == -EEXIST)
@@ -288,19 +287,8 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
288 return 0; 287 return 0;
289} 288}
290 289
291static int get_address (struct hotplug_slot *hotplug_slot, u32 *value) 290static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
292{ 291 enum pci_bus_speed *value)
293 struct slot *slot = get_slot(hotplug_slot);
294 struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
295
296 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
297
298 *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
299
300 return 0;
301}
302
303static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
304{ 292{
305 struct slot *slot = get_slot(hotplug_slot); 293 struct slot *slot = get_slot(hotplug_slot);
306 int retval; 294 int retval;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 0a497c1b4227..e1d7bbf079b4 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -106,3 +106,16 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
106} 106}
107 107
108struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev); 108struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
109
110/* PCI slot sysfs helper code */
111#define to_pci_slot(s) container_of(s, struct pci_slot, kobj)
112
113extern struct kset *pci_slots_kset;
114
115struct pci_slot_attribute {
116 struct attribute attr;
117 ssize_t (*show)(struct pci_slot *, char *);
118 ssize_t (*store)(struct pci_slot *, const char *, size_t);
119};
120#define to_pci_slot_attr(s) container_of(s, struct pci_slot_attribute, attr)
121
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index aebab71abebf..4562827b7e22 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -414,6 +414,7 @@ static struct pci_bus * pci_alloc_bus(void)
414 INIT_LIST_HEAD(&b->node); 414 INIT_LIST_HEAD(&b->node);
415 INIT_LIST_HEAD(&b->children); 415 INIT_LIST_HEAD(&b->children);
416 INIT_LIST_HEAD(&b->devices); 416 INIT_LIST_HEAD(&b->devices);
417 INIT_LIST_HEAD(&b->slots);
417 } 418 }
418 return b; 419 return b;
419} 420}
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
new file mode 100644
index 000000000000..7e5b85cbd948
--- /dev/null
+++ b/drivers/pci/slot.c
@@ -0,0 +1,233 @@
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
13struct kset *pci_slots_kset;
14EXPORT_SYMBOL_GPL(pci_slots_kset);
15
16static 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
24static 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
32static struct sysfs_ops pci_slot_sysfs_ops = {
33 .show = pci_slot_attr_show,
34 .store = pci_slot_attr_store,
35};
36
37static 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
50static 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
62static struct pci_slot_attribute pci_slot_attr_address =
63 __ATTR(address, (S_IFREG | S_IRUGO), address_read_file, NULL);
64
65static struct attribute *pci_slot_default_attrs[] = {
66 &pci_slot_attr_address.attr,
67 NULL,
68};
69
70static 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
108struct 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
132placeholder:
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}
165EXPORT_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
177void 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}
196EXPORT_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
207void 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}
217EXPORT_SYMBOL_GPL(pci_destroy_slot);
218
219static 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
233subsys_initcall(pci_slot_init);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 507ee52323cd..f1f73f79a180 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -17,8 +17,7 @@
17#ifndef LINUX_PCI_H 17#ifndef LINUX_PCI_H
18#define LINUX_PCI_H 18#define LINUX_PCI_H
19 19
20/* Include the pci register defines */ 20#include <linux/pci_regs.h> /* The pci register defines */
21#include <linux/pci_regs.h>
22 21
23/* 22/*
24 * The PCI interface treats multi-function devices as independent 23 * The PCI interface treats multi-function devices as independent
@@ -49,12 +48,22 @@
49#include <linux/list.h> 48#include <linux/list.h>
50#include <linux/compiler.h> 49#include <linux/compiler.h>
51#include <linux/errno.h> 50#include <linux/errno.h>
51#include <linux/kobject.h>
52#include <asm/atomic.h> 52#include <asm/atomic.h>
53#include <linux/device.h> 53#include <linux/device.h>
54 54
55/* Include the ID list */ 55/* Include the ID list */
56#include <linux/pci_ids.h> 56#include <linux/pci_ids.h>
57 57
58/* pci_slot represents a physical slot */
59struct pci_slot {
60 struct pci_bus *bus; /* The bus this slot is on */
61 struct list_head list; /* node in list of slots on this bus */
62 struct hotplug_slot *hotplug; /* Hotplug info (migrate over time) */
63 unsigned char number; /* PCI_SLOT(pci_dev->devfn) */
64 struct kobject kobj;
65};
66
58/* File state for mmap()s on /proc/bus/pci/X/Y */ 67/* File state for mmap()s on /proc/bus/pci/X/Y */
59enum pci_mmap_state { 68enum pci_mmap_state {
60 pci_mmap_io, 69 pci_mmap_io,
@@ -142,6 +151,7 @@ struct pci_dev {
142 151
143 void *sysdata; /* hook for sys-specific extension */ 152 void *sysdata; /* hook for sys-specific extension */
144 struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */ 153 struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */
154 struct pci_slot *slot; /* Physical slot this device is in */
145 155
146 unsigned int devfn; /* encoded device & function index */ 156 unsigned int devfn; /* encoded device & function index */
147 unsigned short vendor; 157 unsigned short vendor;
@@ -266,6 +276,7 @@ struct pci_bus {
266 struct list_head children; /* list of child buses */ 276 struct list_head children; /* list of child buses */
267 struct list_head devices; /* list of devices on this bus */ 277 struct list_head devices; /* list of devices on this bus */
268 struct pci_dev *self; /* bridge device as seen by parent */ 278 struct pci_dev *self; /* bridge device as seen by parent */
279 struct list_head slots; /* list of slots on this bus */
269 struct resource *resource[PCI_BUS_NUM_RESOURCES]; 280 struct resource *resource[PCI_BUS_NUM_RESOURCES];
270 /* address space routed to this bus */ 281 /* address space routed to this bus */
271 282
@@ -488,6 +499,10 @@ struct pci_bus *pci_create_bus(struct device *parent, int bus,
488 struct pci_ops *ops, void *sysdata); 499 struct pci_ops *ops, void *sysdata);
489struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, 500struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
490 int busnr); 501 int busnr);
502struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
503 const char *name);
504void pci_destroy_slot(struct pci_slot *slot);
505void pci_update_slot_number(struct pci_slot *slot, int slot_nr);
491int pci_scan_slot(struct pci_bus *bus, int devfn); 506int pci_scan_slot(struct pci_bus *bus, int devfn);
492struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn); 507struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn);
493void pci_device_add(struct pci_dev *dev, struct pci_bus *bus); 508void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
index dbdcd1ad3c6a..a08cd06b541a 100644
--- a/include/linux/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -95,9 +95,6 @@ struct hotplug_slot_attribute {
95 * @get_adapter_status: Called to get see if an adapter is present in the slot or not. 95 * @get_adapter_status: Called to get see if an adapter is present in the slot or not.
96 * If this field is NULL, the value passed in the struct hotplug_slot_info 96 * If this field is NULL, the value passed in the struct hotplug_slot_info
97 * will be used when this value is requested by a user. 97 * will be used when this value is requested by a user.
98 * @get_address: Called to get pci address of a slot.
99 * If this field is NULL, the value passed in the struct hotplug_slot_info
100 * will be used when this value is requested by a user.
101 * @get_max_bus_speed: Called to get the max bus speed for a slot. 98 * @get_max_bus_speed: Called to get the max bus speed for a slot.
102 * If this field is NULL, the value passed in the struct hotplug_slot_info 99 * If this field is NULL, the value passed in the struct hotplug_slot_info
103 * will be used when this value is requested by a user. 100 * will be used when this value is requested by a user.
@@ -120,7 +117,6 @@ struct hotplug_slot_ops {
120 int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); 117 int (*get_attention_status) (struct hotplug_slot *slot, u8 *value);
121 int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); 118 int (*get_latch_status) (struct hotplug_slot *slot, u8 *value);
122 int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); 119 int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value);
123 int (*get_address) (struct hotplug_slot *slot, u32 *value);
124 int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); 120 int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value);
125 int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); 121 int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value);
126}; 122};
@@ -140,7 +136,6 @@ struct hotplug_slot_info {
140 u8 attention_status; 136 u8 attention_status;
141 u8 latch_status; 137 u8 latch_status;
142 u8 adapter_status; 138 u8 adapter_status;
143 u32 address;
144 enum pci_bus_speed max_bus_speed; 139 enum pci_bus_speed max_bus_speed;
145 enum pci_bus_speed cur_bus_speed; 140 enum pci_bus_speed cur_bus_speed;
146}; 141};
@@ -166,15 +161,14 @@ struct hotplug_slot {
166 161
167 /* Variables below this are for use only by the hotplug pci core. */ 162 /* Variables below this are for use only by the hotplug pci core. */
168 struct list_head slot_list; 163 struct list_head slot_list;
169 struct kobject kobj; 164 struct pci_slot *pci_slot;
170}; 165};
171#define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj) 166#define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj)
172 167
173extern int pci_hp_register (struct hotplug_slot *slot); 168extern int pci_hp_register(struct hotplug_slot *, struct pci_bus *, int nr);
174extern int pci_hp_deregister (struct hotplug_slot *slot); 169extern int pci_hp_deregister(struct hotplug_slot *slot);
175extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot, 170extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot,
176 struct hotplug_slot_info *info); 171 struct hotplug_slot_info *info);
177extern struct kset *pci_hotplug_slots_kset;
178 172
179/* PCI Setting Record (Type 0) */ 173/* PCI Setting Record (Type 0) */
180struct hpp_type0 { 174struct hpp_type0 {