aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c85
-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.c86
-rw-r--r--drivers/pci/hotplug/ibmphp_ebda.c3
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c284
-rw-r--r--drivers/pci/hotplug/pciehp.h16
-rw-r--r--drivers/pci/hotplug/pciehp_core.c127
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c318
-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.c12
-rw-r--r--drivers/pci/hotplug/shpchp.h14
-rw-r--r--drivers/pci/hotplug/shpchp_core.c37
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c1
19 files changed, 471 insertions, 622 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index f8c187a763bd..93e37f0666ab 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -30,6 +30,7 @@
30#include <linux/types.h> 30#include <linux/types.h>
31#include <linux/pci.h> 31#include <linux/pci.h>
32#include <linux/pci_hotplug.h> 32#include <linux/pci_hotplug.h>
33#include <linux/pci-acpi.h>
33#include <acpi/acpi.h> 34#include <acpi/acpi.h>
34#include <acpi/acpi_bus.h> 35#include <acpi/acpi_bus.h>
35#include <acpi/actypes.h> 36#include <acpi/actypes.h>
@@ -299,7 +300,7 @@ free_and_return:
299 * 300 *
300 * @handle - the handle of the hotplug controller. 301 * @handle - the handle of the hotplug controller.
301 */ 302 */
302acpi_status acpi_run_oshp(acpi_handle handle) 303static acpi_status acpi_run_oshp(acpi_handle handle)
303{ 304{
304 acpi_status status; 305 acpi_status status;
305 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; 306 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -322,9 +323,6 @@ acpi_status acpi_run_oshp(acpi_handle handle)
322 kfree(string.pointer); 323 kfree(string.pointer);
323 return status; 324 return status;
324} 325}
325EXPORT_SYMBOL_GPL(acpi_run_oshp);
326
327
328 326
329/* acpi_get_hp_params_from_firmware 327/* acpi_get_hp_params_from_firmware
330 * 328 *
@@ -374,6 +372,85 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
374} 372}
375EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); 373EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
376 374
375/**
376 * acpi_get_hp_hw_control_from_firmware
377 * @dev: the pci_dev of the bridge that has a hotplug controller
378 * @flags: requested control bits for _OSC
379 *
380 * Attempt to take hotplug control from firmware.
381 */
382int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags)
383{
384 acpi_status status;
385 acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
386 struct pci_dev *pdev = dev;
387 struct pci_bus *parent;
388 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
389
390 flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
391 OSC_SHPC_NATIVE_HP_CONTROL |
392 OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
393 if (!flags) {
394 err("Invalid flags %u specified!\n", flags);
395 return -EINVAL;
396 }
397
398 /*
399 * Per PCI firmware specification, we should run the ACPI _OSC
400 * method to get control of hotplug hardware before using it. If
401 * an _OSC is missing, we look for an OSHP to do the same thing.
402 * To handle different BIOS behavior, we look for _OSC and OSHP
403 * within the scope of the hotplug controller and its parents,
404 * upto the host bridge under which this controller exists.
405 */
406 while (!handle) {
407 /*
408 * This hotplug controller was not listed in the ACPI name
409 * space at all. Try to get acpi handle of parent pci bus.
410 */
411 if (!pdev || !pdev->bus->parent)
412 break;
413 parent = pdev->bus->parent;
414 dbg("Could not find %s in acpi namespace, trying parent\n",
415 pci_name(pdev));
416 if (!parent->self)
417 /* Parent must be a host bridge */
418 handle = acpi_get_pci_rootbridge_handle(
419 pci_domain_nr(parent),
420 parent->number);
421 else
422 handle = DEVICE_ACPI_HANDLE(&(parent->self->dev));
423 pdev = parent->self;
424 }
425
426 while (handle) {
427 acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
428 dbg("Trying to get hotplug control for %s \n",
429 (char *)string.pointer);
430 status = pci_osc_control_set(handle, flags);
431 if (status == AE_NOT_FOUND)
432 status = acpi_run_oshp(handle);
433 if (ACPI_SUCCESS(status)) {
434 dbg("Gained control for hotplug HW for pci %s (%s)\n",
435 pci_name(dev), (char *)string.pointer);
436 kfree(string.pointer);
437 return 0;
438 }
439 if (acpi_root_bridge(handle))
440 break;
441 chandle = handle;
442 status = acpi_get_parent(chandle, &handle);
443 if (ACPI_FAILURE(status))
444 break;
445 }
446
447 dbg("Cannot get control of hotplug hardware for pci %s\n",
448 pci_name(dev));
449
450 kfree(string.pointer);
451 return -ENODEV;
452}
453EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware);
377 454
378/* acpi_root_bridge - check to see if this acpi object is a root bridge 455/* acpi_root_bridge - check to see if this acpi object is a root bridge
379 * 456 *
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 91156f85a926..a3e4705dd8f0 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 }
@@ -1878,19 +1883,3 @@ u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot)
1878 1883
1879 return (sta == 0) ? 0 : 1; 1884 return (sta == 0) ? 0 : 1;
1880} 1885}
1881
1882
1883/*
1884 * pci address (seg/bus/dev)
1885 */
1886u32 acpiphp_get_address(struct acpiphp_slot *slot)
1887{
1888 u32 address;
1889 struct pci_bus *pci_bus = slot->bridge->pci_bus;
1890
1891 address = (pci_domain_nr(pci_bus) << 16) |
1892 (pci_bus->number << 8) |
1893 slot->device;
1894
1895 return address;
1896}
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 7e9a827c2687..40337a06c18a 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -66,6 +66,7 @@ struct dummy_slot {
66 struct pci_dev *dev; 66 struct pci_dev *dev;
67 struct work_struct remove_work; 67 struct work_struct remove_work;
68 unsigned long removed; 68 unsigned long removed;
69 char name[8];
69}; 70};
70 71
71static int debug; 72static int debug;
@@ -100,6 +101,7 @@ static int add_slot(struct pci_dev *dev)
100 struct dummy_slot *dslot; 101 struct dummy_slot *dslot;
101 struct hotplug_slot *slot; 102 struct hotplug_slot *slot;
102 int retval = -ENOMEM; 103 int retval = -ENOMEM;
104 static int count = 1;
103 105
104 slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); 106 slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
105 if (!slot) 107 if (!slot)
@@ -113,18 +115,18 @@ static int add_slot(struct pci_dev *dev)
113 slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; 115 slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
114 slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; 116 slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
115 117
116 slot->name = &dev->dev.bus_id[0];
117 dbg("slot->name = %s\n", slot->name);
118
119 dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL); 118 dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL);
120 if (!dslot) 119 if (!dslot)
121 goto error_info; 120 goto error_info;
122 121
122 slot->name = dslot->name;
123 snprintf(slot->name, sizeof(dslot->name), "fake%d", count++);
124 dbg("slot->name = %s\n", slot->name);
123 slot->ops = &dummy_hotplug_slot_ops; 125 slot->ops = &dummy_hotplug_slot_ops;
124 slot->release = &dummy_release; 126 slot->release = &dummy_release;
125 slot->private = dslot; 127 slot->private = dslot;
126 128
127 retval = pci_hp_register(slot); 129 retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn));
128 if (retval) { 130 if (retval) {
129 err("pci_hp_register failed with error %d\n", retval); 131 err("pci_hp_register failed with error %d\n", retval);
130 goto error_dslot; 132 goto error_dslot;
@@ -148,17 +150,17 @@ error:
148static int __init pci_scan_buses(void) 150static int __init pci_scan_buses(void)
149{ 151{
150 struct pci_dev *dev = NULL; 152 struct pci_dev *dev = NULL;
151 int retval = 0; 153 int lastslot = 0;
152 154
153 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { 155 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
154 retval = add_slot(dev); 156 if (PCI_FUNC(dev->devfn) > 0 &&
155 if (retval) { 157 lastslot == PCI_SLOT(dev->devfn))
156 pci_dev_put(dev); 158 continue;
157 break; 159 lastslot = PCI_SLOT(dev->devfn);
158 } 160 add_slot(dev);
159 } 161 }
160 162
161 return retval; 163 return 0;
162} 164}
163 165
164static void remove_slot(struct dummy_slot *dslot) 166static void remove_slot(struct dummy_slot *dslot)
@@ -296,23 +298,9 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
296 return 0; 298 return 0;
297} 299}
298 300
299/* find the hotplug_slot for the pci_dev */
300static struct hotplug_slot *get_slot_from_dev(struct pci_dev *dev)
301{
302 struct dummy_slot *dslot;
303
304 list_for_each_entry(dslot, &slot_list, node) {
305 if (dslot->dev == dev)
306 return dslot->slot;
307 }
308 return NULL;
309}
310
311
312static int disable_slot(struct hotplug_slot *slot) 301static int disable_slot(struct hotplug_slot *slot)
313{ 302{
314 struct dummy_slot *dslot; 303 struct dummy_slot *dslot;
315 struct hotplug_slot *hslot;
316 struct pci_dev *dev; 304 struct pci_dev *dev;
317 int func; 305 int func;
318 306
@@ -322,41 +310,27 @@ static int disable_slot(struct hotplug_slot *slot)
322 310
323 dbg("%s - physical_slot = %s\n", __func__, slot->name); 311 dbg("%s - physical_slot = %s\n", __func__, slot->name);
324 312
325 /* don't disable bridged devices just yet, we can't handle them easily... */ 313 for (func = 7; func >= 0; func--) {
326 if (dslot->dev->subordinate) { 314 dev = pci_get_slot(dslot->dev->bus, dslot->dev->devfn + func);
327 err("Can't remove PCI devices with other PCI devices behind it yet.\n"); 315 if (!dev)
328 return -ENODEV; 316 continue;
329 } 317
330 if (test_and_set_bit(0, &dslot->removed)) { 318 if (test_and_set_bit(0, &dslot->removed)) {
331 dbg("Slot already scheduled for removal\n"); 319 dbg("Slot already scheduled for removal\n");
332 return -ENODEV; 320 return -ENODEV;
333 }
334 /* search for subfunctions and disable them first */
335 if (!(dslot->dev->devfn & 7)) {
336 for (func = 1; func < 8; func++) {
337 dev = pci_get_slot(dslot->dev->bus,
338 dslot->dev->devfn + func);
339 if (dev) {
340 hslot = get_slot_from_dev(dev);
341 if (hslot)
342 disable_slot(hslot);
343 else {
344 err("Hotplug slot not found for subfunction of PCI device\n");
345 return -ENODEV;
346 }
347 pci_dev_put(dev);
348 } else
349 dbg("No device in slot found\n");
350 } 321 }
351 }
352 322
353 /* remove the device from the pci core */ 323 /* queue work item to blow away this sysfs entry and other
354 pci_remove_bus_device(dslot->dev); 324 * parts.
325 */
326 INIT_WORK(&dslot->remove_work, remove_slot_worker);
327 queue_work(dummyphp_wq, &dslot->remove_work);
355 328
356 /* queue work item to blow away this sysfs entry and other parts. */ 329 /* blow away this sysfs entry and other parts. */
357 INIT_WORK(&dslot->remove_work, remove_slot_worker); 330 remove_slot(dslot);
358 queue_work(dummyphp_wq, &dslot->remove_work);
359 331
332 pci_dev_put(dev);
333 }
360 return 0; 334 return 0;
361} 335}
362 336
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..5f85b1b120e3 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,27 +530,33 @@ 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/**
611 * pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem 546 * pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem
547 * @bus: bus this slot is on
612 * @slot: pointer to the &struct hotplug_slot to register 548 * @slot: pointer to the &struct hotplug_slot to register
549 * @slot_nr: slot number
613 * 550 *
614 * Registers a hotplug slot with the pci hotplug subsystem, which will allow 551 * Registers a hotplug slot with the pci hotplug subsystem, which will allow
615 * userspace interaction to the slot. 552 * userspace interaction to the slot.
616 * 553 *
617 * Returns 0 if successful, anything else for an error. 554 * Returns 0 if successful, anything else for an error.
618 */ 555 */
619int pci_hp_register (struct hotplug_slot *slot) 556int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr)
620{ 557{
621 int result; 558 int result;
622 struct hotplug_slot *tmp; 559 struct pci_slot *pci_slot;
623 560
624 if (slot == NULL) 561 if (slot == NULL)
625 return -ENODEV; 562 return -ENODEV;
@@ -632,57 +569,89 @@ int pci_hp_register (struct hotplug_slot *slot)
632 } 569 }
633 570
634 /* Check if we have already registered a slot with the same name. */ 571 /* Check if we have already registered a slot with the same name. */
635 tmp = get_slot_from_name(slot->name); 572 if (get_slot_from_name(slot->name))
636 if (tmp)
637 return -EEXIST; 573 return -EEXIST;
638 574
639 slot->kobj.kset = pci_hotplug_slots_kset; 575 /*
640 result = kobject_init_and_add(&slot->kobj, &hotplug_slot_ktype, NULL, 576 * No problems if we call this interface from both ACPI_PCI_SLOT
641 "%s", slot->name); 577 * driver and call it here again. If we've already created the
642 if (result) { 578 * pci_slot, the interface will simply bump the refcount.
643 err("Unable to register kobject '%s'", slot->name); 579 */
644 return -EINVAL; 580 pci_slot = pci_create_slot(bus, slot_nr, slot->name);
581 if (IS_ERR(pci_slot))
582 return PTR_ERR(pci_slot);
583
584 if (pci_slot->hotplug) {
585 dbg("%s: already claimed\n", __func__);
586 pci_destroy_slot(pci_slot);
587 return -EBUSY;
645 } 588 }
646 589
647 list_add (&slot->slot_list, &pci_hotplug_slot_list); 590 slot->pci_slot = pci_slot;
591 pci_slot->hotplug = slot;
592
593 /*
594 * Allow pcihp drivers to override the ACPI_PCI_SLOT name.
595 */
596 if (strcmp(kobject_name(&pci_slot->kobj), slot->name)) {
597 result = kobject_rename(&pci_slot->kobj, slot->name);
598 if (result) {
599 pci_destroy_slot(pci_slot);
600 return result;
601 }
602 }
603
604 spin_lock(&pci_hotplug_slot_list_lock);
605 list_add(&slot->slot_list, &pci_hotplug_slot_list);
606 spin_unlock(&pci_hotplug_slot_list_lock);
607
608 result = fs_add_slot(pci_slot);
609 kobject_uevent(&pci_slot->kobj, KOBJ_ADD);
610 dbg("Added slot %s to the list\n", slot->name);
611
648 612
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; 613 return result;
653} 614}
654 615
655/** 616/**
656 * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem 617 * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem
657 * @slot: pointer to the &struct hotplug_slot to deregister 618 * @hotplug: pointer to the &struct hotplug_slot to deregister
658 * 619 *
659 * The @slot must have been registered with the pci hotplug subsystem 620 * The @slot must have been registered with the pci hotplug subsystem
660 * previously with a call to pci_hp_register(). 621 * previously with a call to pci_hp_register().
661 * 622 *
662 * Returns 0 if successful, anything else for an error. 623 * Returns 0 if successful, anything else for an error.
663 */ 624 */
664int pci_hp_deregister (struct hotplug_slot *slot) 625int pci_hp_deregister(struct hotplug_slot *hotplug)
665{ 626{
666 struct hotplug_slot *temp; 627 struct hotplug_slot *temp;
628 struct pci_slot *slot;
667 629
668 if (slot == NULL) 630 if (!hotplug)
669 return -ENODEV; 631 return -ENODEV;
670 632
671 temp = get_slot_from_name (slot->name); 633 temp = get_slot_from_name(hotplug->name);
672 if (temp != slot) { 634 if (temp != hotplug)
673 return -ENODEV; 635 return -ENODEV;
674 }
675 list_del (&slot->slot_list);
676 636
677 fs_remove_slot (slot); 637 spin_lock(&pci_hotplug_slot_list_lock);
678 dbg ("Removed slot %s from the list\n", slot->name); 638 list_del(&hotplug->slot_list);
679 kobject_put(&slot->kobj); 639 spin_unlock(&pci_hotplug_slot_list_lock);
640
641 slot = hotplug->pci_slot;
642 fs_remove_slot(slot);
643 dbg("Removed slot %s from the list\n", hotplug->name);
644
645 hotplug->release(hotplug);
646 slot->hotplug = NULL;
647 pci_destroy_slot(slot);
648
680 return 0; 649 return 0;
681} 650}
682 651
683/** 652/**
684 * pci_hp_change_slot_info - changes the slot's information structure in the core 653 * pci_hp_change_slot_info - changes the slot's information structure in the core
685 * @slot: pointer to the slot whose info has changed 654 * @hotplug: pointer to the slot whose info has changed
686 * @info: pointer to the info copy into the slot's info structure 655 * @info: pointer to the info copy into the slot's info structure
687 * 656 *
688 * @slot must have been registered with the pci 657 * @slot must have been registered with the pci
@@ -690,13 +659,15 @@ int pci_hp_deregister (struct hotplug_slot *slot)
690 * 659 *
691 * Returns 0 if successful, anything else for an error. 660 * Returns 0 if successful, anything else for an error.
692 */ 661 */
693int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot, 662int __must_check pci_hp_change_slot_info(struct hotplug_slot *hotplug,
694 struct hotplug_slot_info *info) 663 struct hotplug_slot_info *info)
695{ 664{
696 if ((slot == NULL) || (info == NULL)) 665 struct pci_slot *slot;
666 if (!hotplug || !info)
697 return -ENODEV; 667 return -ENODEV;
668 slot = hotplug->pci_slot;
698 669
699 memcpy (slot->info, info, sizeof (struct hotplug_slot_info)); 670 memcpy(hotplug->info, info, sizeof(struct hotplug_slot_info));
700 671
701 return 0; 672 return 0;
702} 673}
@@ -704,36 +675,22 @@ int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
704static int __init pci_hotplug_init (void) 675static int __init pci_hotplug_init (void)
705{ 676{
706 int result; 677 int result;
707 struct kset *pci_bus_kset;
708 678
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); 679 result = cpci_hotplug_init(debug);
719 if (result) { 680 if (result) {
720 err ("cpci_hotplug_init with error %d\n", result); 681 err ("cpci_hotplug_init with error %d\n", result);
721 goto err_subsys; 682 goto err_cpci;
722 } 683 }
723 684
724 info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); 685 info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
725 goto exit;
726 686
727err_subsys: 687err_cpci:
728 kset_unregister(pci_hotplug_slots_kset);
729exit:
730 return result; 688 return result;
731} 689}
732 690
733static void __exit pci_hotplug_exit (void) 691static void __exit pci_hotplug_exit (void)
734{ 692{
735 cpci_hotplug_exit(); 693 cpci_hotplug_exit();
736 kset_unregister(pci_hotplug_slots_kset);
737} 694}
738 695
739module_init(pci_hotplug_init); 696module_init(pci_hotplug_init);
@@ -745,7 +702,6 @@ MODULE_LICENSE("GPL");
745module_param(debug, bool, 0644); 702module_param(debug, bool, 0644);
746MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); 703MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
747 704
748EXPORT_SYMBOL_GPL(pci_hotplug_slots_kset);
749EXPORT_SYMBOL_GPL(pci_hp_register); 705EXPORT_SYMBOL_GPL(pci_hp_register);
750EXPORT_SYMBOL_GPL(pci_hp_deregister); 706EXPORT_SYMBOL_GPL(pci_hp_deregister);
751EXPORT_SYMBOL_GPL(pci_hp_change_slot_info); 707EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 79c9ddaad3fb..e3a1e7e7dba2 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -43,6 +43,7 @@ extern int pciehp_poll_mode;
43extern int pciehp_poll_time; 43extern int pciehp_poll_time;
44extern int pciehp_debug; 44extern int pciehp_debug;
45extern int pciehp_force; 45extern int pciehp_force;
46extern int pciehp_slot_with_bus;
46extern struct workqueue_struct *pciehp_wq; 47extern struct workqueue_struct *pciehp_wq;
47 48
48#define dbg(format, arg...) \ 49#define dbg(format, arg...) \
@@ -96,7 +97,7 @@ struct controller {
96 u32 slot_cap; 97 u32 slot_cap;
97 u8 cap_base; 98 u8 cap_base;
98 struct timer_list poll_timer; 99 struct timer_list poll_timer;
99 volatile int cmd_busy; 100 int cmd_busy;
100 unsigned int no_cmd_complete:1; 101 unsigned int no_cmd_complete:1;
101}; 102};
102 103
@@ -156,10 +157,10 @@ extern u8 pciehp_handle_power_fault(struct slot *p_slot);
156extern int pciehp_configure_device(struct slot *p_slot); 157extern int pciehp_configure_device(struct slot *p_slot);
157extern int pciehp_unconfigure_device(struct slot *p_slot); 158extern int pciehp_unconfigure_device(struct slot *p_slot);
158extern void pciehp_queue_pushbutton_work(struct work_struct *work); 159extern void pciehp_queue_pushbutton_work(struct work_struct *work);
159int pcie_init(struct controller *ctrl, struct pcie_device *dev); 160struct controller *pcie_init(struct pcie_device *dev);
160int pciehp_enable_slot(struct slot *p_slot); 161int pciehp_enable_slot(struct slot *p_slot);
161int pciehp_disable_slot(struct slot *p_slot); 162int pciehp_disable_slot(struct slot *p_slot);
162int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev); 163int pcie_enable_notification(struct controller *ctrl);
163 164
164static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) 165static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
165{ 166{
@@ -202,8 +203,13 @@ struct hpc_ops {
202#include <acpi/actypes.h> 203#include <acpi/actypes.h>
203#include <linux/pci-acpi.h> 204#include <linux/pci-acpi.h>
204 205
205#define pciehp_get_hp_hw_control_from_firmware(dev) \ 206static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
206 pciehp_acpi_get_hp_hw_control_from_firmware(dev) 207{
208 u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
209 OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
210 return acpi_get_hp_hw_control_from_firmware(dev, flags);
211}
212
207static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, 213static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
208 struct hotplug_params *hpp) 214 struct hotplug_params *hpp)
209{ 215{
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 48a2ed378914..3677495c4f91 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};
@@ -185,23 +183,10 @@ static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
185 */ 183 */
186static void release_slot(struct hotplug_slot *hotplug_slot) 184static void release_slot(struct hotplug_slot *hotplug_slot)
187{ 185{
188 struct slot *slot = hotplug_slot->private;
189
190 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 186 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
191 187
192 kfree(slot->hotplug_slot->info); 188 kfree(hotplug_slot->info);
193 kfree(slot->hotplug_slot); 189 kfree(hotplug_slot);
194 kfree(slot);
195}
196
197static void make_slot_name(struct slot *slot)
198{
199 if (pciehp_slot_with_bus)
200 snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
201 slot->bus, slot->number);
202 else
203 snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
204 slot->number);
205} 190}
206 191
207static int init_slots(struct controller *ctrl) 192static int init_slots(struct controller *ctrl)
@@ -210,49 +195,34 @@ static int init_slots(struct controller *ctrl)
210 struct hotplug_slot *hotplug_slot; 195 struct hotplug_slot *hotplug_slot;
211 struct hotplug_slot_info *info; 196 struct hotplug_slot_info *info;
212 int retval = -ENOMEM; 197 int retval = -ENOMEM;
213 int i;
214
215 for (i = 0; i < ctrl->num_slots; i++) {
216 slot = kzalloc(sizeof(*slot), GFP_KERNEL);
217 if (!slot)
218 goto error;
219 198
199 list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
220 hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); 200 hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
221 if (!hotplug_slot) 201 if (!hotplug_slot)
222 goto error_slot; 202 goto error;
223 slot->hotplug_slot = hotplug_slot;
224 203
225 info = kzalloc(sizeof(*info), GFP_KERNEL); 204 info = kzalloc(sizeof(*info), GFP_KERNEL);
226 if (!info) 205 if (!info)
227 goto error_hpslot; 206 goto error_hpslot;
228 hotplug_slot->info = info;
229
230 hotplug_slot->name = slot->name;
231
232 slot->hp_slot = i;
233 slot->ctrl = ctrl;
234 slot->bus = ctrl->pci_dev->subordinate->number;
235 slot->device = ctrl->slot_device_offset + i;
236 slot->hpc_ops = ctrl->hpc_ops;
237 slot->number = ctrl->first_slot;
238 mutex_init(&slot->lock);
239 INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
240 207
241 /* register this slot with the hotplug pci core */ 208 /* register this slot with the hotplug pci core */
209 hotplug_slot->info = info;
210 hotplug_slot->name = slot->name;
242 hotplug_slot->private = slot; 211 hotplug_slot->private = slot;
243 hotplug_slot->release = &release_slot; 212 hotplug_slot->release = &release_slot;
244 make_slot_name(slot);
245 hotplug_slot->ops = &pciehp_hotplug_slot_ops; 213 hotplug_slot->ops = &pciehp_hotplug_slot_ops;
246
247 get_power_status(hotplug_slot, &info->power_status); 214 get_power_status(hotplug_slot, &info->power_status);
248 get_attention_status(hotplug_slot, &info->attention_status); 215 get_attention_status(hotplug_slot, &info->attention_status);
249 get_latch_status(hotplug_slot, &info->latch_status); 216 get_latch_status(hotplug_slot, &info->latch_status);
250 get_adapter_status(hotplug_slot, &info->adapter_status); 217 get_adapter_status(hotplug_slot, &info->adapter_status);
218 slot->hotplug_slot = hotplug_slot;
251 219
252 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " 220 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
253 "slot_device_offset=%x\n", slot->bus, slot->device, 221 "slot_device_offset=%x\n", slot->bus, slot->device,
254 slot->hp_slot, slot->number, ctrl->slot_device_offset); 222 slot->hp_slot, slot->number, ctrl->slot_device_offset);
255 retval = pci_hp_register(hotplug_slot); 223 retval = pci_hp_register(hotplug_slot,
224 ctrl->pci_dev->subordinate,
225 slot->device);
256 if (retval) { 226 if (retval) {
257 err("pci_hp_register failed with error %d\n", retval); 227 err("pci_hp_register failed with error %d\n", retval);
258 if (retval == -EEXIST) 228 if (retval == -EEXIST)
@@ -263,7 +233,7 @@ static int init_slots(struct controller *ctrl)
263 } 233 }
264 /* create additional sysfs entries */ 234 /* create additional sysfs entries */
265 if (EMI(ctrl)) { 235 if (EMI(ctrl)) {
266 retval = sysfs_create_file(&hotplug_slot->kobj, 236 retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
267 &hotplug_slot_attr_lock.attr); 237 &hotplug_slot_attr_lock.attr);
268 if (retval) { 238 if (retval) {
269 pci_hp_deregister(hotplug_slot); 239 pci_hp_deregister(hotplug_slot);
@@ -271,8 +241,6 @@ static int init_slots(struct controller *ctrl)
271 goto error_info; 241 goto error_info;
272 } 242 }
273 } 243 }
274
275 list_add(&slot->slot_list, &ctrl->slot_list);
276 } 244 }
277 245
278 return 0; 246 return 0;
@@ -280,27 +248,18 @@ error_info:
280 kfree(info); 248 kfree(info);
281error_hpslot: 249error_hpslot:
282 kfree(hotplug_slot); 250 kfree(hotplug_slot);
283error_slot:
284 kfree(slot);
285error: 251error:
286 return retval; 252 return retval;
287} 253}
288 254
289static void cleanup_slots(struct controller *ctrl) 255static void cleanup_slots(struct controller *ctrl)
290{ 256{
291 struct list_head *tmp;
292 struct list_head *next;
293 struct slot *slot; 257 struct slot *slot;
294 258
295 list_for_each_safe(tmp, next, &ctrl->slot_list) { 259 list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
296 slot = list_entry(tmp, struct slot, slot_list);
297 list_del(&slot->slot_list);
298 if (EMI(ctrl)) 260 if (EMI(ctrl))
299 sysfs_remove_file(&slot->hotplug_slot->kobj, 261 sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
300 &hotplug_slot_attr_lock.attr); 262 &hotplug_slot_attr_lock.attr);
301 cancel_delayed_work(&slot->work);
302 flush_scheduled_work();
303 flush_workqueue(pciehp_wq);
304 pci_hp_deregister(slot->hotplug_slot); 263 pci_hp_deregister(slot->hotplug_slot);
305 } 264 }
306} 265}
@@ -398,19 +357,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
398 return 0; 357 return 0;
399} 358}
400 359
401static int get_address(struct hotplug_slot *hotplug_slot, u32 *value) 360static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
402{ 361 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{ 362{
415 struct slot *slot = hotplug_slot->private; 363 struct slot *slot = hotplug_slot->private;
416 int retval; 364 int retval;
@@ -444,34 +392,30 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
444 struct controller *ctrl; 392 struct controller *ctrl;
445 struct slot *t_slot; 393 struct slot *t_slot;
446 u8 value; 394 u8 value;
447 struct pci_dev *pdev; 395 struct pci_dev *pdev = dev->port;
448 396
449 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); 397 if (pciehp_force)
450 if (!ctrl) { 398 dbg("Bypassing BIOS check for pciehp use on %s\n",
451 err("%s : out of memory\n", __func__); 399 pci_name(pdev));
400 else if (pciehp_get_hp_hw_control_from_firmware(pdev))
452 goto err_out_none; 401 goto err_out_none;
453 }
454 INIT_LIST_HEAD(&ctrl->slot_list);
455
456 pdev = dev->port;
457 ctrl->pci_dev = pdev;
458 402
459 rc = pcie_init(ctrl, dev); 403 ctrl = pcie_init(dev);
460 if (rc) { 404 if (!ctrl) {
461 dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); 405 dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
462 goto err_out_free_ctrl; 406 goto err_out_none;
463 } 407 }
464 408 set_service_data(dev, ctrl);
465 pci_set_drvdata(pdev, ctrl);
466
467 dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
468 __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
469 PCI_FUNC(pdev->devfn), pdev->irq);
470 409
471 /* Setup the slot information structures */ 410 /* Setup the slot information structures */
472 rc = init_slots(ctrl); 411 rc = init_slots(ctrl);
473 if (rc) { 412 if (rc) {
474 err("%s: slot initialization failed\n", PCIE_MODULE_NAME); 413 if (rc == -EBUSY)
414 warn("%s: slot already registered by another "
415 "hotplug driver\n", PCIE_MODULE_NAME);
416 else
417 err("%s: slot initialization failed\n",
418 PCIE_MODULE_NAME);
475 goto err_out_release_ctlr; 419 goto err_out_release_ctlr;
476 } 420 }
477 421
@@ -495,20 +439,16 @@ err_out_free_ctrl_slot:
495 cleanup_slots(ctrl); 439 cleanup_slots(ctrl);
496err_out_release_ctlr: 440err_out_release_ctlr:
497 ctrl->hpc_ops->release_ctlr(ctrl); 441 ctrl->hpc_ops->release_ctlr(ctrl);
498err_out_free_ctrl:
499 kfree(ctrl);
500err_out_none: 442err_out_none:
501 return -ENODEV; 443 return -ENODEV;
502} 444}
503 445
504static void pciehp_remove (struct pcie_device *dev) 446static void pciehp_remove (struct pcie_device *dev)
505{ 447{
506 struct pci_dev *pdev = dev->port; 448 struct controller *ctrl = get_service_data(dev);
507 struct controller *ctrl = pci_get_drvdata(pdev);
508 449
509 cleanup_slots(ctrl); 450 cleanup_slots(ctrl);
510 ctrl->hpc_ops->release_ctlr(ctrl); 451 ctrl->hpc_ops->release_ctlr(ctrl);
511 kfree(ctrl);
512} 452}
513 453
514#ifdef CONFIG_PM 454#ifdef CONFIG_PM
@@ -522,13 +462,12 @@ static int pciehp_resume (struct pcie_device *dev)
522{ 462{
523 printk("%s ENTRY\n", __func__); 463 printk("%s ENTRY\n", __func__);
524 if (pciehp_force) { 464 if (pciehp_force) {
525 struct pci_dev *pdev = dev->port; 465 struct controller *ctrl = get_service_data(dev);
526 struct controller *ctrl = pci_get_drvdata(pdev);
527 struct slot *t_slot; 466 struct slot *t_slot;
528 u8 status; 467 u8 status;
529 468
530 /* reinitialize the chipset's event detection logic */ 469 /* reinitialize the chipset's event detection logic */
531 pcie_init_hardware_part2(ctrl, dev); 470 pcie_enable_notification(ctrl);
532 471
533 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 472 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
534 473
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 79f104963166..1323a43285d7 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -247,30 +247,32 @@ static inline void pciehp_free_irq(struct controller *ctrl)
247 free_irq(ctrl->pci_dev->irq, ctrl); 247 free_irq(ctrl->pci_dev->irq, ctrl);
248} 248}
249 249
250static inline int pcie_poll_cmd(struct controller *ctrl) 250static int pcie_poll_cmd(struct controller *ctrl)
251{ 251{
252 u16 slot_status; 252 u16 slot_status;
253 int timeout = 1000; 253 int timeout = 1000;
254 254
255 if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) 255 if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) {
256 if (slot_status & CMD_COMPLETED) 256 if (slot_status & CMD_COMPLETED) {
257 goto completed; 257 pciehp_writew(ctrl, SLOTSTATUS, CMD_COMPLETED);
258 for (timeout = 1000; timeout > 0; timeout -= 100) { 258 return 1;
259 msleep(100); 259 }
260 if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) 260 }
261 if (slot_status & CMD_COMPLETED) 261 while (timeout > 1000) {
262 goto completed; 262 msleep(10);
263 timeout -= 10;
264 if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) {
265 if (slot_status & CMD_COMPLETED) {
266 pciehp_writew(ctrl, SLOTSTATUS, CMD_COMPLETED);
267 return 1;
268 }
269 }
263 } 270 }
264 return 0; /* timeout */ 271 return 0; /* timeout */
265
266completed:
267 pciehp_writew(ctrl, SLOTSTATUS, CMD_COMPLETED);
268 return timeout;
269} 272}
270 273
271static inline int pcie_wait_cmd(struct controller *ctrl, int poll) 274static void pcie_wait_cmd(struct controller *ctrl, int poll)
272{ 275{
273 int retval = 0;
274 unsigned int msecs = pciehp_poll_mode ? 2500 : 1000; 276 unsigned int msecs = pciehp_poll_mode ? 2500 : 1000;
275 unsigned long timeout = msecs_to_jiffies(msecs); 277 unsigned long timeout = msecs_to_jiffies(msecs);
276 int rc; 278 int rc;
@@ -278,16 +280,9 @@ static inline int pcie_wait_cmd(struct controller *ctrl, int poll)
278 if (poll) 280 if (poll)
279 rc = pcie_poll_cmd(ctrl); 281 rc = pcie_poll_cmd(ctrl);
280 else 282 else
281 rc = wait_event_interruptible_timeout(ctrl->queue, 283 rc = wait_event_timeout(ctrl->queue, !ctrl->cmd_busy, timeout);
282 !ctrl->cmd_busy, timeout);
283 if (!rc) 284 if (!rc)
284 dbg("Command not completed in 1000 msec\n"); 285 dbg("Command not completed in 1000 msec\n");
285 else if (rc < 0) {
286 retval = -EINTR;
287 info("Command was interrupted by a signal\n");
288 }
289
290 return retval;
291} 286}
292 287
293/** 288/**
@@ -342,10 +337,6 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
342 337
343 slot_ctrl &= ~mask; 338 slot_ctrl &= ~mask;
344 slot_ctrl |= (cmd & mask); 339 slot_ctrl |= (cmd & mask);
345 /* Don't enable command completed if caller is changing it. */
346 if (!(mask & CMD_CMPL_INTR_ENABLE))
347 slot_ctrl |= CMD_CMPL_INTR_ENABLE;
348
349 ctrl->cmd_busy = 1; 340 ctrl->cmd_busy = 1;
350 smp_mb(); 341 smp_mb();
351 retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl); 342 retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
@@ -365,7 +356,7 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
365 if (!(slot_ctrl & HP_INTR_ENABLE) || 356 if (!(slot_ctrl & HP_INTR_ENABLE) ||
366 !(slot_ctrl & CMD_CMPL_INTR_ENABLE)) 357 !(slot_ctrl & CMD_CMPL_INTR_ENABLE))
367 poll = 1; 358 poll = 1;
368 retval = pcie_wait_cmd(ctrl, poll); 359 pcie_wait_cmd(ctrl, poll);
369 } 360 }
370 out: 361 out:
371 mutex_unlock(&ctrl->ctrl_lock); 362 mutex_unlock(&ctrl->ctrl_lock);
@@ -614,23 +605,6 @@ static void hpc_set_green_led_blink(struct slot *slot)
614 __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); 605 __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
615} 606}
616 607
617static void hpc_release_ctlr(struct controller *ctrl)
618{
619 /* Mask Hot-plug Interrupt Enable */
620 if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE))
621 err("%s: Cannot mask hotplut interrupt enable\n", __func__);
622
623 /* Free interrupt handler or interrupt polling timer */
624 pciehp_free_irq(ctrl);
625
626 /*
627 * If this is the last controller to be released, destroy the
628 * pciehp work queue
629 */
630 if (atomic_dec_and_test(&pciehp_num_controllers))
631 destroy_workqueue(pciehp_wq);
632}
633
634static int hpc_power_on_slot(struct slot * slot) 608static int hpc_power_on_slot(struct slot * slot)
635{ 609{
636 struct controller *ctrl = slot->ctrl; 610 struct controller *ctrl = slot->ctrl;
@@ -785,7 +759,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
785 intr_loc |= detected; 759 intr_loc |= detected;
786 if (!intr_loc) 760 if (!intr_loc)
787 return IRQ_NONE; 761 return IRQ_NONE;
788 if (pciehp_writew(ctrl, SLOTSTATUS, detected)) { 762 if (detected && pciehp_writew(ctrl, SLOTSTATUS, detected)) {
789 err("%s: Cannot write to SLOTSTATUS\n", __func__); 763 err("%s: Cannot write to SLOTSTATUS\n", __func__);
790 return IRQ_NONE; 764 return IRQ_NONE;
791 } 765 }
@@ -797,25 +771,13 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
797 if (intr_loc & CMD_COMPLETED) { 771 if (intr_loc & CMD_COMPLETED) {
798 ctrl->cmd_busy = 0; 772 ctrl->cmd_busy = 0;
799 smp_mb(); 773 smp_mb();
800 wake_up_interruptible(&ctrl->queue); 774 wake_up(&ctrl->queue);
801 } 775 }
802 776
803 if (!(intr_loc & ~CMD_COMPLETED)) 777 if (!(intr_loc & ~CMD_COMPLETED))
804 return IRQ_HANDLED; 778 return IRQ_HANDLED;
805 779
806 /*
807 * Return without handling events if this handler routine is
808 * called before controller initialization is done. This may
809 * happen if hotplug event or another interrupt that shares
810 * the IRQ with pciehp arrives before slot initialization is
811 * done after interrupt handler is registered.
812 *
813 * FIXME - Need more structural fixes. We need to be ready to
814 * handle the event before installing interrupt handler.
815 */
816 p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 780 p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
817 if (!p_slot || !p_slot->hpc_ops)
818 return IRQ_HANDLED;
819 781
820 /* Check MRL Sensor Changed */ 782 /* Check MRL Sensor Changed */
821 if (intr_loc & MRL_SENS_CHANGED) 783 if (intr_loc & MRL_SENS_CHANGED)
@@ -992,6 +954,7 @@ static int hpc_get_cur_lnk_width(struct slot *slot,
992 return retval; 954 return retval;
993} 955}
994 956
957static void pcie_release_ctrl(struct controller *ctrl);
995static struct hpc_ops pciehp_hpc_ops = { 958static struct hpc_ops pciehp_hpc_ops = {
996 .power_on_slot = hpc_power_on_slot, 959 .power_on_slot = hpc_power_on_slot,
997 .power_off_slot = hpc_power_off_slot, 960 .power_off_slot = hpc_power_off_slot,
@@ -1013,97 +976,11 @@ static struct hpc_ops pciehp_hpc_ops = {
1013 .green_led_off = hpc_set_green_led_off, 976 .green_led_off = hpc_set_green_led_off,
1014 .green_led_blink = hpc_set_green_led_blink, 977 .green_led_blink = hpc_set_green_led_blink,
1015 978
1016 .release_ctlr = hpc_release_ctlr, 979 .release_ctlr = pcie_release_ctrl,
1017 .check_lnk_status = hpc_check_lnk_status, 980 .check_lnk_status = hpc_check_lnk_status,
1018}; 981};
1019 982
1020#ifdef CONFIG_ACPI 983int pcie_enable_notification(struct controller *ctrl)
1021static int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
1022{
1023 acpi_status status;
1024 acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
1025 struct pci_dev *pdev = dev;
1026 struct pci_bus *parent;
1027 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
1028
1029 /*
1030 * Per PCI firmware specification, we should run the ACPI _OSC
1031 * method to get control of hotplug hardware before using it.
1032 * If an _OSC is missing, we look for an OSHP to do the same thing.
1033 * To handle different BIOS behavior, we look for _OSC and OSHP
1034 * within the scope of the hotplug controller and its parents, upto
1035 * the host bridge under which this controller exists.
1036 */
1037 while (!handle) {
1038 /*
1039 * This hotplug controller was not listed in the ACPI name
1040 * space at all. Try to get acpi handle of parent pci bus.
1041 */
1042 if (!pdev || !pdev->bus->parent)
1043 break;
1044 parent = pdev->bus->parent;
1045 dbg("Could not find %s in acpi namespace, trying parent\n",
1046 pci_name(pdev));
1047 if (!parent->self)
1048 /* Parent must be a host bridge */
1049 handle = acpi_get_pci_rootbridge_handle(
1050 pci_domain_nr(parent),
1051 parent->number);
1052 else
1053 handle = DEVICE_ACPI_HANDLE(
1054 &(parent->self->dev));
1055 pdev = parent->self;
1056 }
1057
1058 while (handle) {
1059 acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
1060 dbg("Trying to get hotplug control for %s \n",
1061 (char *)string.pointer);
1062 status = pci_osc_control_set(handle,
1063 OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL |
1064 OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
1065 if (status == AE_NOT_FOUND)
1066 status = acpi_run_oshp(handle);
1067 if (ACPI_SUCCESS(status)) {
1068 dbg("Gained control for hotplug HW for pci %s (%s)\n",
1069 pci_name(dev), (char *)string.pointer);
1070 kfree(string.pointer);
1071 return 0;
1072 }
1073 if (acpi_root_bridge(handle))
1074 break;
1075 chandle = handle;
1076 status = acpi_get_parent(chandle, &handle);
1077 if (ACPI_FAILURE(status))
1078 break;
1079 }
1080
1081 dbg("Cannot get control of hotplug hardware for pci %s\n",
1082 pci_name(dev));
1083
1084 kfree(string.pointer);
1085 return -1;
1086}
1087#endif
1088
1089static int pcie_init_hardware_part1(struct controller *ctrl,
1090 struct pcie_device *dev)
1091{
1092 /* Clear all remaining event bits in Slot Status register */
1093 if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) {
1094 err("%s: Cannot write to SLOTSTATUS register\n", __func__);
1095 return -1;
1096 }
1097
1098 /* Mask Hot-plug Interrupt Enable */
1099 if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) {
1100 err("%s: Cannot mask hotplug interrupt enable\n", __func__);
1101 return -1;
1102 }
1103 return 0;
1104}
1105
1106int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
1107{ 984{
1108 u16 cmd, mask; 985 u16 cmd, mask;
1109 986
@@ -1115,30 +992,83 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
1115 if (MRL_SENS(ctrl)) 992 if (MRL_SENS(ctrl))
1116 cmd |= MRL_DETECT_ENABLE; 993 cmd |= MRL_DETECT_ENABLE;
1117 if (!pciehp_poll_mode) 994 if (!pciehp_poll_mode)
1118 cmd |= HP_INTR_ENABLE; 995 cmd |= HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE;
1119 996
1120 mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | 997 mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | MRL_DETECT_ENABLE |
1121 PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | HP_INTR_ENABLE; 998 PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE;
1122 999
1123 if (pcie_write_cmd(ctrl, cmd, mask)) { 1000 if (pcie_write_cmd(ctrl, cmd, mask)) {
1124 err("%s: Cannot enable software notification\n", __func__); 1001 err("%s: Cannot enable software notification\n", __func__);
1125 goto abort; 1002 return -1;
1126 } 1003 }
1004 return 0;
1005}
1127 1006
1128 if (pciehp_force) 1007static void pcie_disable_notification(struct controller *ctrl)
1129 dbg("Bypassing BIOS check for pciehp use on %s\n", 1008{
1130 pci_name(ctrl->pci_dev)); 1009 u16 mask;
1131 else if (pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev)) 1010 mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | MRL_DETECT_ENABLE |
1132 goto abort_disable_intr; 1011 PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE;
1012 if (pcie_write_cmd(ctrl, 0, mask))
1013 warn("%s: Cannot disable software notification\n", __func__);
1014}
1133 1015
1016static int pcie_init_notification(struct controller *ctrl)
1017{
1018 if (pciehp_request_irq(ctrl))
1019 return -1;
1020 if (pcie_enable_notification(ctrl)) {
1021 pciehp_free_irq(ctrl);
1022 return -1;
1023 }
1134 return 0; 1024 return 0;
1025}
1135 1026
1136 /* We end up here for the many possible ways to fail this API. */ 1027static void pcie_shutdown_notification(struct controller *ctrl)
1137abort_disable_intr: 1028{
1138 if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE)) 1029 pcie_disable_notification(ctrl);
1139 err("%s : disabling interrupts failed\n", __func__); 1030 pciehp_free_irq(ctrl);
1140abort: 1031}
1141 return -1; 1032
1033static void make_slot_name(struct slot *slot)
1034{
1035 if (pciehp_slot_with_bus)
1036 snprintf(slot->name, SLOT_NAME_SIZE, "%04d_%04d",
1037 slot->bus, slot->number);
1038 else
1039 snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number);
1040}
1041
1042static int pcie_init_slot(struct controller *ctrl)
1043{
1044 struct slot *slot;
1045
1046 slot = kzalloc(sizeof(*slot), GFP_KERNEL);
1047 if (!slot)
1048 return -ENOMEM;
1049
1050 slot->hp_slot = 0;
1051 slot->ctrl = ctrl;
1052 slot->bus = ctrl->pci_dev->subordinate->number;
1053 slot->device = ctrl->slot_device_offset + slot->hp_slot;
1054 slot->hpc_ops = ctrl->hpc_ops;
1055 slot->number = ctrl->first_slot;
1056 make_slot_name(slot);
1057 mutex_init(&slot->lock);
1058 INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
1059 list_add(&slot->slot_list, &ctrl->slot_list);
1060 return 0;
1061}
1062
1063static void pcie_cleanup_slot(struct controller *ctrl)
1064{
1065 struct slot *slot;
1066 slot = list_first_entry(&ctrl->slot_list, struct slot, slot_list);
1067 list_del(&slot->slot_list);
1068 cancel_delayed_work(&slot->work);
1069 flush_scheduled_work();
1070 flush_workqueue(pciehp_wq);
1071 kfree(slot);
1142} 1072}
1143 1073
1144static inline void dbg_ctrl(struct controller *ctrl) 1074static inline void dbg_ctrl(struct controller *ctrl)
@@ -1176,15 +1106,23 @@ static inline void dbg_ctrl(struct controller *ctrl)
1176 dbg(" Comamnd Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes"); 1106 dbg(" Comamnd Completed : %3s\n", NO_CMD_CMPL(ctrl)? "no" : "yes");
1177 pciehp_readw(ctrl, SLOTSTATUS, &reg16); 1107 pciehp_readw(ctrl, SLOTSTATUS, &reg16);
1178 dbg("Slot Status : 0x%04x\n", reg16); 1108 dbg("Slot Status : 0x%04x\n", reg16);
1179 pciehp_readw(ctrl, SLOTSTATUS, &reg16); 1109 pciehp_readw(ctrl, SLOTCTRL, &reg16);
1180 dbg("Slot Control : 0x%04x\n", reg16); 1110 dbg("Slot Control : 0x%04x\n", reg16);
1181} 1111}
1182 1112
1183int pcie_init(struct controller *ctrl, struct pcie_device *dev) 1113struct controller *pcie_init(struct pcie_device *dev)
1184{ 1114{
1115 struct controller *ctrl;
1185 u32 slot_cap; 1116 u32 slot_cap;
1186 struct pci_dev *pdev = dev->port; 1117 struct pci_dev *pdev = dev->port;
1187 1118
1119 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
1120 if (!ctrl) {
1121 err("%s : out of memory\n", __func__);
1122 goto abort;
1123 }
1124 INIT_LIST_HEAD(&ctrl->slot_list);
1125
1188 ctrl->pci_dev = pdev; 1126 ctrl->pci_dev = pdev;
1189 ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); 1127 ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
1190 if (!ctrl->cap_base) { 1128 if (!ctrl->cap_base) {
@@ -1215,15 +1153,12 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
1215 !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl))) 1153 !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl)))
1216 ctrl->no_cmd_complete = 1; 1154 ctrl->no_cmd_complete = 1;
1217 1155
1218 info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", 1156 /* Clear all remaining event bits in Slot Status register */
1219 pdev->vendor, pdev->device, 1157 if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f))
1220 pdev->subsystem_vendor, pdev->subsystem_device); 1158 goto abort_ctrl;
1221 1159
1222 if (pcie_init_hardware_part1(ctrl, dev)) 1160 /* Disable sotfware notification */
1223 goto abort; 1161 pcie_disable_notification(ctrl);
1224
1225 if (pciehp_request_irq(ctrl))
1226 goto abort;
1227 1162
1228 /* 1163 /*
1229 * If this is the first controller to be initialized, 1164 * If this is the first controller to be initialized,
@@ -1231,18 +1166,39 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
1231 */ 1166 */
1232 if (atomic_add_return(1, &pciehp_num_controllers) == 1) { 1167 if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
1233 pciehp_wq = create_singlethread_workqueue("pciehpd"); 1168 pciehp_wq = create_singlethread_workqueue("pciehpd");
1234 if (!pciehp_wq) { 1169 if (!pciehp_wq)
1235 goto abort_free_irq; 1170 goto abort_ctrl;
1236 }
1237 } 1171 }
1238 1172
1239 if (pcie_init_hardware_part2(ctrl, dev)) 1173 info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
1240 goto abort_free_irq; 1174 pdev->vendor, pdev->device,
1175 pdev->subsystem_vendor, pdev->subsystem_device);
1176
1177 if (pcie_init_slot(ctrl))
1178 goto abort_ctrl;
1241 1179
1242 return 0; 1180 if (pcie_init_notification(ctrl))
1181 goto abort_slot;
1243 1182
1244abort_free_irq: 1183 return ctrl;
1245 pciehp_free_irq(ctrl); 1184
1185abort_slot:
1186 pcie_cleanup_slot(ctrl);
1187abort_ctrl:
1188 kfree(ctrl);
1246abort: 1189abort:
1247 return -1; 1190 return NULL;
1191}
1192
1193void pcie_release_ctrl(struct controller *ctrl)
1194{
1195 pcie_shutdown_notification(ctrl);
1196 pcie_cleanup_slot(ctrl);
1197 /*
1198 * If this is the last controller to be released, destroy the
1199 * pciehp work queue
1200 */
1201 if (atomic_dec_and_test(&pciehp_num_controllers))
1202 destroy_workqueue(pciehp_wq);
1203 kfree(ctrl);
1248} 1204}
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..410fe0394a8e 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;
@@ -664,7 +668,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
664 668
665register_err: 669register_err:
666 dev_dbg(&pci_bus->self->dev, "bus failed to register with err = %d\n", 670 dev_dbg(&pci_bus->self->dev, "bus failed to register with err = %d\n",
667 rc); 671 rc);
668 672
669alloc_err: 673alloc_err:
670 if (rc == -ENOMEM) 674 if (rc == -ENOMEM)
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index f66e8d6315ab..8a026f750deb 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -170,6 +170,7 @@ extern void shpchp_queue_pushbutton_work(struct work_struct *work);
170extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); 170extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
171 171
172#ifdef CONFIG_ACPI 172#ifdef CONFIG_ACPI
173#include <linux/pci-acpi.h>
173static inline int get_hp_params_from_firmware(struct pci_dev *dev, 174static inline int get_hp_params_from_firmware(struct pci_dev *dev,
174 struct hotplug_params *hpp) 175 struct hotplug_params *hpp)
175{ 176{
@@ -177,14 +178,15 @@ static inline int get_hp_params_from_firmware(struct pci_dev *dev,
177 return -ENODEV; 178 return -ENODEV;
178 return 0; 179 return 0;
179} 180}
180#define get_hp_hw_control_from_firmware(pdev) \ 181
181 do { \ 182static inline int get_hp_hw_control_from_firmware(struct pci_dev *dev)
182 if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \ 183{
183 acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev)));\ 184 u32 flags = OSC_SHPC_NATIVE_HP_CONTROL;
184 } while (0) 185 return acpi_get_hp_hw_control_from_firmware(dev, flags);
186}
185#else 187#else
186#define get_hp_params_from_firmware(dev, hpp) (-ENODEV) 188#define get_hp_params_from_firmware(dev, hpp) (-ENODEV)
187#define get_hp_hw_control_from_firmware(dev) do { } while (0) 189#define get_hp_hw_control_from_firmware(dev) (0)
188#endif 190#endif
189 191
190struct ctrl_reg { 192struct ctrl_reg {
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 97848654652a..a8cbd039b85b 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -39,7 +39,7 @@
39int shpchp_debug; 39int shpchp_debug;
40int shpchp_poll_mode; 40int shpchp_poll_mode;
41int shpchp_poll_time; 41int shpchp_poll_time;
42int shpchp_slot_with_bus; 42static int shpchp_slot_with_bus;
43struct workqueue_struct *shpchp_wq; 43struct workqueue_struct *shpchp_wq;
44 44
45#define DRIVER_VERSION "0.4" 45#define DRIVER_VERSION "0.4"
@@ -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;
@@ -330,13 +318,14 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
330 318
331static int is_shpc_capable(struct pci_dev *dev) 319static int is_shpc_capable(struct pci_dev *dev)
332{ 320{
333 if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == 321 if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
334 PCI_DEVICE_ID_AMD_GOLAM_7450)) 322 PCI_DEVICE_ID_AMD_GOLAM_7450))
335 return 1; 323 return 1;
336 if (pci_find_capability(dev, PCI_CAP_ID_SHPC)) 324 if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
337 return 1; 325 return 0;
338 326 if (get_hp_hw_control_from_firmware(dev))
339 return 0; 327 return 0;
328 return 1;
340} 329}
341 330
342static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 331static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 7d770b2cd889..7a0bff364cd4 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -1084,7 +1084,6 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
1084 dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __func__, 1084 dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __func__,
1085 pdev->bus->number, PCI_SLOT(pdev->devfn), 1085 pdev->bus->number, PCI_SLOT(pdev->devfn),
1086 PCI_FUNC(pdev->devfn), pdev->irq); 1086 PCI_FUNC(pdev->devfn), pdev->irq);
1087 get_hp_hw_control_from_firmware(pdev);
1088 1087
1089 /* 1088 /*
1090 * If this is the first controller to be initialized, 1089 * If this is the first controller to be initialized,