aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2006-02-09 04:29:00 -0500
committerJeff Garzik <jgarzik@pobox.com>2006-02-09 04:29:00 -0500
commit9caafa6c8686e319cf4d5f3757b3972c6c522b7c (patch)
treeb38979b835b5d22e681b175d0b98a3c7560d9c59 /drivers/pci/hotplug
parent51e9f2ff83df6b1c81c5c44f4486c68ed87aa20e (diff)
parentcac0e8e8bb2e7a086643bdd00c41d900a79bb4fa (diff)
Merge branch 'upstream-fixes'
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/Kconfig3
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c21
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c4
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c64
-rw-r--r--drivers/pci/hotplug/rpaphp.h14
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c114
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c267
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c17
-rw-r--r--drivers/pci/hotplug/shpchp.h94
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c12
10 files changed, 232 insertions, 378 deletions
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 2f1289eebb3c..222a1cc4aa28 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -11,8 +11,7 @@ config HOTPLUG_PCI
11 ---help--- 11 ---help---
12 Say Y here if you have a motherboard with a PCI Hotplug controller. 12 Say Y here if you have a motherboard with a PCI Hotplug controller.
13 This allows you to add and remove PCI cards while the machine is 13 This allows you to add and remove PCI cards while the machine is
14 powered up and running. The file system pcihpfs must be mounted 14 powered up and running.
15 in order to interact with any PCI Hotplug controllers.
16 15
17 To compile this driver as a module, choose M here: the 16 To compile this driver as a module, choose M here: the
18 module will be called pci_hotplug. 17 module will be called pci_hotplug.
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index 7e7f913ba7b9..317457dd4014 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -302,7 +302,7 @@ static int ibm_get_table_from_acpi(char **bufp)
302 } 302 }
303 303
304 package = (union acpi_object *) buffer.pointer; 304 package = (union acpi_object *) buffer.pointer;
305 if(!(package) || 305 if (!(package) ||
306 (package->type != ACPI_TYPE_PACKAGE) || 306 (package->type != ACPI_TYPE_PACKAGE) ||
307 !(package->package.elements)) { 307 !(package->package.elements)) {
308 err("%s: Invalid APCI object\n", __FUNCTION__); 308 err("%s: Invalid APCI object\n", __FUNCTION__);
@@ -405,7 +405,7 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
405 } 405 }
406 info.hardware_id.value[sizeof(info.hardware_id.value) - 1] = '\0'; 406 info.hardware_id.value[sizeof(info.hardware_id.value) - 1] = '\0';
407 407
408 if(info.current_status && (info.valid & ACPI_VALID_HID) && 408 if (info.current_status && (info.valid & ACPI_VALID_HID) &&
409 (!strcmp(info.hardware_id.value, IBM_HARDWARE_ID1) || 409 (!strcmp(info.hardware_id.value, IBM_HARDWARE_ID1) ||
410 !strcmp(info.hardware_id.value, IBM_HARDWARE_ID2))) { 410 !strcmp(info.hardware_id.value, IBM_HARDWARE_ID2))) {
411 dbg("found hardware: %s, handle: %p\n", info.hardware_id.value, 411 dbg("found hardware: %s, handle: %p\n", info.hardware_id.value,
@@ -449,13 +449,11 @@ static int __init ibm_acpiphp_init(void)
449 } 449 }
450 450
451 ibm_note.device = device; 451 ibm_note.device = device;
452 status = acpi_install_notify_handler( 452 status = acpi_install_notify_handler(ibm_acpi_handle,
453 ibm_acpi_handle, 453 ACPI_DEVICE_NOTIFY, ibm_handle_events,
454 ACPI_DEVICE_NOTIFY,
455 ibm_handle_events,
456 &ibm_note); 454 &ibm_note);
457 if (ACPI_FAILURE(status)) { 455 if (ACPI_FAILURE(status)) {
458 err("%s: Failed to register notification handler\n", 456 err("%s: Failed to register notification handler\n",
459 __FUNCTION__); 457 __FUNCTION__);
460 retval = -EBUSY; 458 retval = -EBUSY;
461 goto init_cleanup; 459 goto init_cleanup;
@@ -482,14 +480,13 @@ static void __exit ibm_acpiphp_exit(void)
482 if (acpiphp_unregister_attention(&ibm_attention_info)) 480 if (acpiphp_unregister_attention(&ibm_attention_info))
483 err("%s: attention info deregistration failed", __FUNCTION__); 481 err("%s: attention info deregistration failed", __FUNCTION__);
484 482
485 status = acpi_remove_notify_handler( 483 status = acpi_remove_notify_handler(
486 ibm_acpi_handle, 484 ibm_acpi_handle,
487 ACPI_DEVICE_NOTIFY, 485 ACPI_DEVICE_NOTIFY,
488 ibm_handle_events); 486 ibm_handle_events);
489 if (ACPI_FAILURE(status)) 487 if (ACPI_FAILURE(status))
490 err("%s: Notification handler removal failed\n", 488 err("%s: Notification handler removal failed\n", __FUNCTION__);
491 __FUNCTION__); 489 /* remove the /sys entries */
492 // remove the /sys entries
493 if (sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr)) 490 if (sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr))
494 err("%s: removal of sysfs file apci_table failed\n", 491 err("%s: removal of sysfs file apci_table failed\n",
495 __FUNCTION__); 492 __FUNCTION__);
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index aabf1e70b528..dc59da675c08 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -235,12 +235,12 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)
235{ 235{
236 int rc = 0; 236 int rc = 0;
237 struct slot *pslot; 237 struct slot *pslot;
238 u8 cmd; 238 u8 cmd = 0x00; /* avoid compiler warning */
239 239
240 debug("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n", 240 debug("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n",
241 (ulong) hotplug_slot, value); 241 (ulong) hotplug_slot, value);
242 ibmphp_lock_operations(); 242 ibmphp_lock_operations();
243 cmd = 0x00; // avoid compiler warning 243
244 244
245 if (hotplug_slot) { 245 if (hotplug_slot) {
246 switch (value) { 246 switch (value) {
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 7d93dbaf628d..3eefe2cec72d 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -103,13 +103,13 @@ static struct slot *find_slot(struct device_node *dn)
103 struct list_head *tmp, *n; 103 struct list_head *tmp, *n;
104 struct slot *slot; 104 struct slot *slot;
105 105
106 list_for_each_safe(tmp, n, &rpaphp_slot_head) { 106 list_for_each_safe(tmp, n, &rpaphp_slot_head) {
107 slot = list_entry(tmp, struct slot, rpaphp_slot_list); 107 slot = list_entry(tmp, struct slot, rpaphp_slot_list);
108 if (slot->dn == dn) 108 if (slot->dn == dn)
109 return slot; 109 return slot;
110 } 110 }
111 111
112 return NULL; 112 return NULL;
113} 113}
114 114
115static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent, 115static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
@@ -126,9 +126,9 @@ static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
126 return NULL; 126 return NULL;
127} 127}
128 128
129static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) 129static void dlpar_pci_add_bus(struct device_node *dn)
130{ 130{
131 struct pci_dn *pdn = dn->data; 131 struct pci_dn *pdn = PCI_DN(dn);
132 struct pci_controller *phb = pdn->phb; 132 struct pci_controller *phb = pdn->phb;
133 struct pci_dev *dev = NULL; 133 struct pci_dev *dev = NULL;
134 134
@@ -139,52 +139,52 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
139 if (!dev) { 139 if (!dev) {
140 printk(KERN_ERR "%s: failed to create pci dev for %s\n", 140 printk(KERN_ERR "%s: failed to create pci dev for %s\n",
141 __FUNCTION__, dn->full_name); 141 __FUNCTION__, dn->full_name);
142 return NULL; 142 return;
143 } 143 }
144 144
145 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || 145 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
146 dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) 146 dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
147 of_scan_pci_bridge(dn, dev); 147 of_scan_pci_bridge(dn, dev);
148 148
149 rpaphp_init_new_devs(dev->subordinate); 149 pcibios_fixup_new_pci_devices(dev->subordinate,0);
150 150
151 /* Claim new bus resources */ 151 /* Claim new bus resources */
152 pcibios_claim_one_bus(dev->bus); 152 pcibios_claim_one_bus(dev->bus);
153 153
154 /* ioremap() for child bus, which may or may not succeed */ 154 /* ioremap() for child bus, which may or may not succeed */
155 (void) remap_bus_range(dev->bus); 155 remap_bus_range(dev->subordinate);
156 156
157 /* Add new devices to global lists. Register in proc, sysfs. */ 157 /* Add new devices to global lists. Register in proc, sysfs. */
158 pci_bus_add_devices(phb->bus); 158 pci_bus_add_devices(phb->bus);
159
160 /* Confirm new bridge dev was created */
161 dev = dlpar_find_new_dev(phb->bus, dn);
162 if (dev) {
163 if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
164 printk(KERN_ERR "%s: unexpected header type %d\n",
165 __FUNCTION__, dev->hdr_type);
166 return NULL;
167 }
168 }
169
170 return dev;
171} 159}
172 160
173static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) 161static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
174{ 162{
175 struct pci_dev *dev; 163 struct pci_dev *dev;
164 struct pci_controller *phb;
176 165
177 if (rpaphp_find_pci_bus(dn)) 166 if (pcibios_find_pci_bus(dn))
178 return -EINVAL; 167 return -EINVAL;
179 168
180 /* Add pci bus */ 169 /* Add pci bus */
181 dev = dlpar_pci_add_bus(dn); 170 dlpar_pci_add_bus(dn);
171
172 /* Confirm new bridge dev was created */
173 phb = PCI_DN(dn)->phb;
174 dev = dlpar_find_new_dev(phb->bus, dn);
175
182 if (!dev) { 176 if (!dev) {
183 printk(KERN_ERR "%s: unable to add bus %s\n", __FUNCTION__, 177 printk(KERN_ERR "%s: unable to add bus %s\n", __FUNCTION__,
184 drc_name); 178 drc_name);
185 return -EIO; 179 return -EIO;
186 } 180 }
187 181
182 if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
183 printk(KERN_ERR "%s: unexpected header type %d, unable to add bus %s\n",
184 __FUNCTION__, dev->hdr_type, drc_name);
185 return -EIO;
186 }
187
188 /* Add hotplug slot */ 188 /* Add hotplug slot */
189 if (rpaphp_add_slot(dn)) { 189 if (rpaphp_add_slot(dn)) {
190 printk(KERN_ERR "%s: unable to add hotplug slot %s\n", 190 printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
@@ -221,13 +221,13 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
221 struct pci_dn *pdn; 221 struct pci_dn *pdn;
222 int rc = 0; 222 int rc = 0;
223 223
224 if (!rpaphp_find_pci_bus(dn)) 224 if (!pcibios_find_pci_bus(dn))
225 return -EINVAL; 225 return -EINVAL;
226 226
227 slot = find_slot(dn); 227 slot = find_slot(dn);
228 if (slot) { 228 if (slot) {
229 /* Remove hotplug slot */ 229 /* Remove hotplug slot */
230 if (rpaphp_remove_slot(slot)) { 230 if (rpaphp_deregister_slot(slot)) {
231 printk(KERN_ERR 231 printk(KERN_ERR
232 "%s: unable to remove hotplug slot %s\n", 232 "%s: unable to remove hotplug slot %s\n",
233 __FUNCTION__, drc_name); 233 __FUNCTION__, drc_name);
@@ -366,21 +366,25 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
366 struct pci_bus *bus; 366 struct pci_bus *bus;
367 struct slot *slot; 367 struct slot *slot;
368 368
369 bus = rpaphp_find_pci_bus(dn); 369 bus = pcibios_find_pci_bus(dn);
370 if (!bus) 370 if (!bus)
371 return -EINVAL; 371 return -EINVAL;
372 372
373 slot = find_slot(dn); 373 slot = find_slot(dn);
374 if (slot) { 374 if (slot) {
375 /* Remove hotplug slot */ 375 /* Remove hotplug slot */
376 if (rpaphp_remove_slot(slot)) { 376 if (rpaphp_deregister_slot(slot)) {
377 printk(KERN_ERR 377 printk(KERN_ERR
378 "%s: unable to remove hotplug slot %s\n", 378 "%s: unable to remove hotplug slot %s\n",
379 __FUNCTION__, drc_name); 379 __FUNCTION__, drc_name);
380 return -EIO; 380 return -EIO;
381 } 381 }
382 } else { 382 } else {
383 rpaphp_unconfig_pci_adapter(bus); 383 struct pci_dev *dev, *tmp;
384 list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
385 eeh_remove_bus_device(dev);
386 pci_remove_bus_device(dev);
387 }
384 } 388 }
385 389
386 if (unmap_bus_range(bus)) { 390 if (unmap_bus_range(bus)) {
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 57ea71a7bda5..310b6186c0e5 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -88,16 +88,10 @@ extern int num_slots;
88/* function prototypes */ 88/* function prototypes */
89 89
90/* rpaphp_pci.c */ 90/* rpaphp_pci.c */
91extern struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn);
92extern int rpaphp_claim_resource(struct pci_dev *dev, int resource);
93extern int rpaphp_enable_pci_slot(struct slot *slot); 91extern int rpaphp_enable_pci_slot(struct slot *slot);
94extern int register_pci_slot(struct slot *slot); 92extern int rpaphp_register_pci_slot(struct slot *slot);
95extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); 93extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
96extern void rpaphp_init_new_devs(struct pci_bus *bus); 94extern int rpaphp_get_sensor_state(struct slot *slot, int *state);
97extern void rpaphp_eeh_init_nodes(struct device_node *dn);
98
99extern int rpaphp_config_pci_adapter(struct pci_bus *bus);
100extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus);
101 95
102/* rpaphp_core.c */ 96/* rpaphp_core.c */
103extern int rpaphp_add_slot(struct device_node *dn); 97extern int rpaphp_add_slot(struct device_node *dn);
@@ -108,8 +102,8 @@ extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
108/* rpaphp_slot.c */ 102/* rpaphp_slot.c */
109extern void dealloc_slot_struct(struct slot *slot); 103extern void dealloc_slot_struct(struct slot *slot);
110extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain); 104extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
111extern int register_slot(struct slot *slot); 105extern int rpaphp_register_slot(struct slot *slot);
112extern int deregister_slot(struct slot *slot); 106extern int rpaphp_deregister_slot(struct slot *slot);
113extern int rpaphp_get_power_status(struct slot *slot, u8 * value); 107extern int rpaphp_get_power_status(struct slot *slot, u8 * value);
114extern int rpaphp_set_attention_status(struct slot *slot, u8 status); 108extern int rpaphp_set_attention_status(struct slot *slot, u8 status);
115 109
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index cf075c34b578..6e79f5675b0d 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -56,25 +56,6 @@ MODULE_LICENSE("GPL");
56 56
57module_param(debug, bool, 0644); 57module_param(debug, bool, 0644);
58 58
59static int enable_slot(struct hotplug_slot *slot);
60static int disable_slot(struct hotplug_slot *slot);
61static int set_attention_status(struct hotplug_slot *slot, u8 value);
62static int get_power_status(struct hotplug_slot *slot, u8 * value);
63static int get_attention_status(struct hotplug_slot *slot, u8 * value);
64static int get_adapter_status(struct hotplug_slot *slot, u8 * value);
65static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value);
66
67struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
68 .owner = THIS_MODULE,
69 .enable_slot = enable_slot,
70 .disable_slot = disable_slot,
71 .set_attention_status = set_attention_status,
72 .get_power_status = get_power_status,
73 .get_attention_status = get_attention_status,
74 .get_adapter_status = get_adapter_status,
75 .get_max_bus_speed = get_max_bus_speed,
76};
77
78static int rpaphp_get_attention_status(struct slot *slot) 59static int rpaphp_get_attention_status(struct slot *slot)
79{ 60{
80 return slot->hotplug_slot->info->attention_status; 61 return slot->hotplug_slot->info->attention_status;
@@ -196,11 +177,6 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
196 return 0; 177 return 0;
197} 178}
198 179
199int rpaphp_remove_slot(struct slot *slot)
200{
201 return deregister_slot(slot);
202}
203
204static int get_children_props(struct device_node *dn, int **drc_indexes, 180static int get_children_props(struct device_node *dn, int **drc_indexes,
205 int **drc_names, int **drc_types, int **drc_power_domains) 181 int **drc_names, int **drc_types, int **drc_power_domains)
206{ 182{
@@ -307,13 +283,15 @@ static int is_php_dn(struct device_node *dn, int **indexes, int **names,
307 return 0; 283 return 0;
308} 284}
309 285
310/**************************************************************** 286/**
287 * rpaphp_add_slot -- add hotplug or dlpar slot
288 *
311 * rpaphp not only registers PCI hotplug slots(HOTPLUG), 289 * rpaphp not only registers PCI hotplug slots(HOTPLUG),
312 * but also logical DR slots(EMBEDDED). 290 * but also logical DR slots(EMBEDDED).
313 * HOTPLUG slot: An adapter can be physically added/removed. 291 * HOTPLUG slot: An adapter can be physically added/removed.
314 * EMBEDDED slot: An adapter can be logically removed/added 292 * EMBEDDED slot: An adapter can be logically removed/added
315 * from/to a partition with the slot. 293 * from/to a partition with the slot.
316 ***************************************************************/ 294 */
317int rpaphp_add_slot(struct device_node *dn) 295int rpaphp_add_slot(struct device_node *dn)
318{ 296{
319 struct slot *slot; 297 struct slot *slot;
@@ -344,7 +322,7 @@ int rpaphp_add_slot(struct device_node *dn)
344 dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n", 322 dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n",
345 indexes[i + 1], name, type); 323 indexes[i + 1], name, type);
346 324
347 retval = register_pci_slot(slot); 325 retval = rpaphp_register_pci_slot(slot);
348 } 326 }
349 } 327 }
350exit: 328exit:
@@ -393,53 +371,85 @@ static void __exit rpaphp_exit(void)
393 cleanup_slots(); 371 cleanup_slots();
394} 372}
395 373
396static int enable_slot(struct hotplug_slot *hotplug_slot) 374static int __enable_slot(struct slot *slot)
397{ 375{
398 int retval = 0; 376 int state;
399 struct slot *slot = (struct slot *)hotplug_slot->private; 377 int retval;
400 378
401 if (slot->state == CONFIGURED) { 379 if (slot->state == CONFIGURED)
402 dbg("%s: %s is already enabled\n", __FUNCTION__, slot->name); 380 return 0;
403 goto exit; 381
382 retval = rpaphp_get_sensor_state(slot, &state);
383 if (retval)
384 return retval;
385
386 if (state == PRESENT) {
387 pcibios_add_pci_devices(slot->bus);
388 slot->state = CONFIGURED;
389 } else if (state == EMPTY) {
390 slot->state = EMPTY;
391 } else {
392 err("%s: slot[%s] is in invalid state\n", __FUNCTION__, slot->name);
393 slot->state = NOT_VALID;
394 return -EINVAL;
404 } 395 }
396 return 0;
397}
398
399static int enable_slot(struct hotplug_slot *hotplug_slot)
400{
401 int retval;
402 struct slot *slot = (struct slot *)hotplug_slot->private;
405 403
406 dbg("ENABLING SLOT %s\n", slot->name);
407 down(&rpaphp_sem); 404 down(&rpaphp_sem);
408 retval = rpaphp_enable_pci_slot(slot); 405 retval = __enable_slot(slot);
409 up(&rpaphp_sem); 406 up(&rpaphp_sem);
410exit: 407
411 dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
412 return retval; 408 return retval;
413} 409}
414 410
415static int disable_slot(struct hotplug_slot *hotplug_slot) 411static int __disable_slot(struct slot *slot)
416{ 412{
417 int retval = -EINVAL; 413 struct pci_dev *dev, *tmp;
418 struct slot *slot = (struct slot *)hotplug_slot->private;
419 414
420 dbg("%s - Entry: slot[%s]\n", __FUNCTION__, slot->name); 415 if (slot->state == NOT_CONFIGURED)
416 return -EINVAL;
421 417
422 if (slot->state == NOT_CONFIGURED) { 418 list_for_each_entry_safe(dev, tmp, &slot->bus->devices, bus_list) {
423 dbg("%s: %s is already disabled\n", __FUNCTION__, slot->name); 419 eeh_remove_bus_device(dev);
424 goto exit; 420 pci_remove_bus_device(dev);
425 } 421 }
426 422
427 dbg("DISABLING SLOT %s\n", slot->name); 423 slot->state = NOT_CONFIGURED;
424 return 0;
425}
426
427static int disable_slot(struct hotplug_slot *hotplug_slot)
428{
429 struct slot *slot = (struct slot *)hotplug_slot->private;
430 int retval;
431
428 down(&rpaphp_sem); 432 down(&rpaphp_sem);
429 retval = rpaphp_unconfig_pci_adapter(slot->bus); 433 retval = __disable_slot (slot);
430 up(&rpaphp_sem); 434 up(&rpaphp_sem);
431 slot->state = NOT_CONFIGURED; 435
432 info("%s: devices in slot[%s] unconfigured.\n", __FUNCTION__,
433 slot->name);
434exit:
435 dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
436 return retval; 436 return retval;
437} 437}
438 438
439struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
440 .owner = THIS_MODULE,
441 .enable_slot = enable_slot,
442 .disable_slot = disable_slot,
443 .set_attention_status = set_attention_status,
444 .get_power_status = get_power_status,
445 .get_attention_status = get_attention_status,
446 .get_adapter_status = get_adapter_status,
447 .get_max_bus_speed = get_max_bus_speed,
448};
449
439module_init(rpaphp_init); 450module_init(rpaphp_init);
440module_exit(rpaphp_exit); 451module_exit(rpaphp_exit);
441 452
442EXPORT_SYMBOL_GPL(rpaphp_add_slot); 453EXPORT_SYMBOL_GPL(rpaphp_add_slot);
443EXPORT_SYMBOL_GPL(rpaphp_remove_slot);
444EXPORT_SYMBOL_GPL(rpaphp_slot_head); 454EXPORT_SYMBOL_GPL(rpaphp_slot_head);
445EXPORT_SYMBOL_GPL(rpaphp_get_drc_props); 455EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 396b54b0c847..6f6cbede5135 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -32,37 +32,7 @@
32#include "../pci.h" /* for pci_add_new_bus */ 32#include "../pci.h" /* for pci_add_new_bus */
33#include "rpaphp.h" 33#include "rpaphp.h"
34 34
35static struct pci_bus *find_bus_among_children(struct pci_bus *bus, 35int rpaphp_get_sensor_state(struct slot *slot, int *state)
36 struct device_node *dn)
37{
38 struct pci_bus *child = NULL;
39 struct list_head *tmp;
40 struct device_node *busdn;
41
42 busdn = pci_bus_to_OF_node(bus);
43 if (busdn == dn)
44 return bus;
45
46 list_for_each(tmp, &bus->children) {
47 child = find_bus_among_children(pci_bus_b(tmp), dn);
48 if (child)
49 break;
50 }
51 return child;
52}
53
54struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn)
55{
56 struct pci_dn *pdn = dn->data;
57
58 if (!pdn || !pdn->phb || !pdn->phb->bus)
59 return NULL;
60
61 return find_bus_among_children(pdn->phb->bus, dn);
62}
63EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus);
64
65static int rpaphp_get_sensor_state(struct slot *slot, int *state)
66{ 36{
67 int rc; 37 int rc;
68 int setlevel; 38 int setlevel;
@@ -120,7 +90,7 @@ int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
120 /* config/unconfig adapter */ 90 /* config/unconfig adapter */
121 *value = slot->state; 91 *value = slot->state;
122 } else { 92 } else {
123 bus = rpaphp_find_pci_bus(slot->dn); 93 bus = pcibios_find_pci_bus(slot->dn);
124 if (bus && !list_empty(&bus->devices)) 94 if (bus && !list_empty(&bus->devices))
125 *value = CONFIGURED; 95 *value = CONFIGURED;
126 else 96 else
@@ -131,140 +101,6 @@ exit:
131 return rc; 101 return rc;
132} 102}
133 103
134/* Must be called before pci_bus_add_devices */
135void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
136{
137 struct pci_dev *dev;
138
139 list_for_each_entry(dev, &bus->devices, bus_list) {
140 /*
141 * Skip already-present devices (which are on the
142 * global device list.)
143 */
144 if (list_empty(&dev->global_list)) {
145 int i;
146
147 /* Need to setup IOMMU tables */
148 ppc_md.iommu_dev_setup(dev);
149
150 if(fix_bus)
151 pcibios_fixup_device_resources(dev, bus);
152 pci_read_irq_line(dev);
153 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
154 struct resource *r = &dev->resource[i];
155
156 if (r->parent || !r->start || !r->flags)
157 continue;
158 pci_claim_resource(dev, i);
159 }
160 }
161 }
162}
163
164static void rpaphp_eeh_add_bus_device(struct pci_bus *bus)
165{
166 struct pci_dev *dev;
167
168 list_for_each_entry(dev, &bus->devices, bus_list) {
169 eeh_add_device_late(dev);
170 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
171 struct pci_bus *subbus = dev->subordinate;
172 if (subbus)
173 rpaphp_eeh_add_bus_device (subbus);
174 }
175 }
176}
177
178static int rpaphp_pci_config_bridge(struct pci_dev *dev)
179{
180 u8 sec_busno;
181 struct pci_bus *child_bus;
182 struct pci_dev *child_dev;
183
184 dbg("Enter %s: BRIDGE dev=%s\n", __FUNCTION__, pci_name(dev));
185
186 /* get busno of downstream bus */
187 pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
188
189 /* add to children of PCI bridge dev->bus */
190 child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
191 if (!child_bus) {
192 err("%s: could not add second bus\n", __FUNCTION__);
193 return -EIO;
194 }
195 sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
196 /* do pci_scan_child_bus */
197 pci_scan_child_bus(child_bus);
198
199 list_for_each_entry(child_dev, &child_bus->devices, bus_list) {
200 eeh_add_device_late(child_dev);
201 }
202
203 /* fixup new pci devices without touching bus struct */
204 rpaphp_fixup_new_pci_devices(child_bus, 0);
205
206 /* Make the discovered devices available */
207 pci_bus_add_devices(child_bus);
208 return 0;
209}
210
211void rpaphp_init_new_devs(struct pci_bus *bus)
212{
213 rpaphp_fixup_new_pci_devices(bus, 0);
214 rpaphp_eeh_add_bus_device(bus);
215}
216EXPORT_SYMBOL_GPL(rpaphp_init_new_devs);
217
218/*****************************************************************************
219 rpaphp_pci_config_slot() will configure all devices under the
220 given slot->dn and return the the first pci_dev.
221 *****************************************************************************/
222static struct pci_dev *
223rpaphp_pci_config_slot(struct pci_bus *bus)
224{
225 struct device_node *dn = pci_bus_to_OF_node(bus);
226 struct pci_dev *dev = NULL;
227 int slotno;
228 int num;
229
230 dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
231 if (!dn || !dn->child)
232 return NULL;
233
234 if (_machine == PLATFORM_PSERIES_LPAR) {
235 of_scan_bus(dn, bus);
236 if (list_empty(&bus->devices)) {
237 err("%s: No new device found\n", __FUNCTION__);
238 return NULL;
239 }
240
241 rpaphp_init_new_devs(bus);
242 pci_bus_add_devices(bus);
243 dev = list_entry(&bus->devices, struct pci_dev, bus_list);
244 } else {
245 slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
246
247 /* pci_scan_slot should find all children */
248 num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
249 if (num) {
250 rpaphp_fixup_new_pci_devices(bus, 1);
251 pci_bus_add_devices(bus);
252 }
253 if (list_empty(&bus->devices)) {
254 err("%s: No new device found\n", __FUNCTION__);
255 return NULL;
256 }
257 list_for_each_entry(dev, &bus->devices, bus_list) {
258 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
259 rpaphp_pci_config_bridge(dev);
260
261 rpaphp_eeh_add_bus_device(bus);
262 }
263 }
264
265 return dev;
266}
267
268static void print_slot_pci_funcs(struct pci_bus *bus) 104static void print_slot_pci_funcs(struct pci_bus *bus)
269{ 105{
270 struct device_node *dn; 106 struct device_node *dn;
@@ -280,60 +116,6 @@ static void print_slot_pci_funcs(struct pci_bus *bus)
280 return; 116 return;
281} 117}
282 118
283int rpaphp_config_pci_adapter(struct pci_bus *bus)
284{
285 struct device_node *dn = pci_bus_to_OF_node(bus);
286 struct pci_dev *dev;
287 int rc = -ENODEV;
288
289 dbg("Entry %s: slot[%s]\n", __FUNCTION__, dn->full_name);
290 if (!dn)
291 goto exit;
292
293 eeh_add_device_tree_early(dn);
294 dev = rpaphp_pci_config_slot(bus);
295 if (!dev) {
296 err("%s: can't find any devices.\n", __FUNCTION__);
297 goto exit;
298 }
299 print_slot_pci_funcs(bus);
300 rc = 0;
301exit:
302 dbg("Exit %s: rc=%d\n", __FUNCTION__, rc);
303 return rc;
304}
305EXPORT_SYMBOL_GPL(rpaphp_config_pci_adapter);
306
307static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
308{
309 eeh_remove_device(dev);
310 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
311 struct pci_bus *bus = dev->subordinate;
312 struct list_head *ln;
313 if (!bus)
314 return;
315 for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
316 struct pci_dev *pdev = pci_dev_b(ln);
317 if (pdev)
318 rpaphp_eeh_remove_bus_device(pdev);
319 }
320
321 }
322 return;
323}
324
325int rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
326{
327 struct pci_dev *dev, *tmp;
328
329 list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
330 rpaphp_eeh_remove_bus_device(dev);
331 pci_remove_bus_device(dev);
332 }
333 return 0;
334}
335EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter);
336
337static int setup_pci_hotplug_slot_info(struct slot *slot) 119static int setup_pci_hotplug_slot_info(struct slot *slot)
338{ 120{
339 struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info; 121 struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info;
@@ -370,7 +152,7 @@ static int setup_pci_slot(struct slot *slot)
370 struct pci_bus *bus; 152 struct pci_bus *bus;
371 153
372 BUG_ON(!dn); 154 BUG_ON(!dn);
373 bus = rpaphp_find_pci_bus(dn); 155 bus = pcibios_find_pci_bus(dn);
374 if (!bus) { 156 if (!bus) {
375 err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name); 157 err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name);
376 goto exit_rc; 158 goto exit_rc;
@@ -395,10 +177,7 @@ static int setup_pci_slot(struct slot *slot)
395 if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) { 177 if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
396 dbg("%s CONFIGURING pci adapter in slot[%s]\n", 178 dbg("%s CONFIGURING pci adapter in slot[%s]\n",
397 __FUNCTION__, slot->name); 179 __FUNCTION__, slot->name);
398 if (rpaphp_config_pci_adapter(slot->bus)) { 180 pcibios_add_pci_devices(slot->bus);
399 err("%s: CONFIG pci adapter failed\n", __FUNCTION__);
400 goto exit_rc;
401 }
402 181
403 } else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) { 182 } else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) {
404 err("%s: slot[%s]'s adapter_status is NOT_VALID.\n", 183 err("%s: slot[%s]'s adapter_status is NOT_VALID.\n",
@@ -420,7 +199,7 @@ exit_rc:
420 return -EINVAL; 199 return -EINVAL;
421} 200}
422 201
423int register_pci_slot(struct slot *slot) 202int rpaphp_register_pci_slot(struct slot *slot)
424{ 203{
425 int rc = -EINVAL; 204 int rc = -EINVAL;
426 205
@@ -428,42 +207,8 @@ int register_pci_slot(struct slot *slot)
428 goto exit_rc; 207 goto exit_rc;
429 if (setup_pci_slot(slot)) 208 if (setup_pci_slot(slot))
430 goto exit_rc; 209 goto exit_rc;
431 rc = register_slot(slot); 210 rc = rpaphp_register_slot(slot);
432exit_rc: 211exit_rc:
433 return rc; 212 return rc;
434} 213}
435 214
436int rpaphp_enable_pci_slot(struct slot *slot)
437{
438 int retval = 0, state;
439
440 retval = rpaphp_get_sensor_state(slot, &state);
441 if (retval)
442 goto exit;
443 dbg("%s: sensor state[%d]\n", __FUNCTION__, state);
444 /* if slot is not empty, enable the adapter */
445 if (state == PRESENT) {
446 dbg("%s : slot[%s] is occupied.\n", __FUNCTION__, slot->name);
447 retval = rpaphp_config_pci_adapter(slot->bus);
448 if (!retval) {
449 slot->state = CONFIGURED;
450 info("%s: devices in slot[%s] configured\n",
451 __FUNCTION__, slot->name);
452 } else {
453 slot->state = NOT_CONFIGURED;
454 dbg("%s: no pci_dev struct for adapter in slot[%s]\n",
455 __FUNCTION__, slot->name);
456 }
457 } else if (state == EMPTY) {
458 dbg("%s : slot[%s] is empty\n", __FUNCTION__, slot->name);
459 slot->state = EMPTY;
460 } else {
461 err("%s: slot[%s] is in invalid state\n", __FUNCTION__,
462 slot->name);
463 slot->state = NOT_VALID;
464 retval = -EINVAL;
465 }
466exit:
467 dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
468 return retval;
469}
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index daa89ae57123..78943e064b59 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -35,16 +35,16 @@
35 35
36static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf) 36static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
37{ 37{
38 char *value; 38 char *value;
39 int retval = -ENOENT; 39 int retval = -ENOENT;
40 struct slot *slot = (struct slot *)php_slot->private; 40 struct slot *slot = (struct slot *)php_slot->private;
41 41
42 if (!slot) 42 if (!slot)
43 return retval; 43 return retval;
44 44
45 value = slot->location; 45 value = slot->location;
46 retval = sprintf (buf, "%s\n", value); 46 retval = sprintf (buf, "%s\n", value);
47 return retval; 47 return retval;
48} 48}
49 49
50static struct hotplug_slot_attribute hotplug_slot_attr_location = { 50static struct hotplug_slot_attribute hotplug_slot_attr_location = {
@@ -137,7 +137,7 @@ static int is_registered(struct slot *slot)
137 return 0; 137 return 0;
138} 138}
139 139
140int deregister_slot(struct slot *slot) 140int rpaphp_deregister_slot(struct slot *slot)
141{ 141{
142 int retval = 0; 142 int retval = 0;
143 struct hotplug_slot *php_slot = slot->hotplug_slot; 143 struct hotplug_slot *php_slot = slot->hotplug_slot;
@@ -159,8 +159,9 @@ int deregister_slot(struct slot *slot)
159 dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); 159 dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
160 return retval; 160 return retval;
161} 161}
162EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);
162 163
163int register_slot(struct slot *slot) 164int rpaphp_register_slot(struct slot *slot)
164{ 165{
165 int retval; 166 int retval;
166 167
@@ -169,7 +170,7 @@ int register_slot(struct slot *slot)
169 slot->power_domain, slot->type); 170 slot->power_domain, slot->type);
170 /* should not try to register the same slot twice */ 171 /* should not try to register the same slot twice */
171 if (is_registered(slot)) { /* should't be here */ 172 if (is_registered(slot)) { /* should't be here */
172 err("register_slot: slot[%s] is already registered\n", slot->name); 173 err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name);
173 rpaphp_release_slot(slot->hotplug_slot); 174 rpaphp_release_slot(slot->hotplug_slot);
174 return -EAGAIN; 175 return -EAGAIN;
175 } 176 }
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index ce0e9b6ce833..7d6f521d02ea 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -95,6 +95,7 @@ struct controller {
95 u8 function; 95 u8 function;
96 u8 slot_device_offset; 96 u8 slot_device_offset;
97 u8 add_support; 97 u8 add_support;
98 u32 pcix_misc2_reg; /* for amd pogo errata */
98 enum pci_bus_speed speed; 99 enum pci_bus_speed speed;
99 u32 first_slot; /* First physical slot number */ 100 u32 first_slot; /* First physical slot number */
100 u8 slot_bus; /* Bus where the slots handled by this controller sit */ 101 u8 slot_bus; /* Bus where the slots handled by this controller sit */
@@ -113,6 +114,26 @@ struct hotplug_params {
113 114
114/* Define AMD SHPC ID */ 115/* Define AMD SHPC ID */
115#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 116#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
117#define PCI_DEVICE_ID_AMD_POGO_7458 0x7458
118
119/* AMD PCIX bridge registers */
120
121#define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C
122#define PCIX_MISCII_OFFSET 0x48
123#define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80
124
125/* AMD PCIX_MISCII masks and offsets */
126#define PERRNONFATALENABLE_MASK 0x00040000
127#define PERRFATALENABLE_MASK 0x00080000
128#define PERRFLOODENABLE_MASK 0x00100000
129#define SERRNONFATALENABLE_MASK 0x00200000
130#define SERRFATALENABLE_MASK 0x00400000
131
132/* AMD PCIX_MISC_BRIDGE_ERRORS masks and offsets */
133#define PERR_OBSERVED_MASK 0x00000001
134
135/* AMD PCIX_MEM_BASE_LIMIT masks */
136#define RSE_MASK 0x40000000
116 137
117#define INT_BUTTON_IGNORE 0 138#define INT_BUTTON_IGNORE 0
118#define INT_PRESENCE_ON 1 139#define INT_PRESENCE_ON 1
@@ -333,6 +354,79 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
333 return retval; 354 return retval;
334} 355}
335 356
357static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot)
358{
359 u32 pcix_misc2_temp;
360
361 /* save MiscII register */
362 pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp);
363
364 p_slot->ctrl->pcix_misc2_reg = pcix_misc2_temp;
365
366 /* clear SERR/PERR enable bits */
367 pcix_misc2_temp &= ~SERRFATALENABLE_MASK;
368 pcix_misc2_temp &= ~SERRNONFATALENABLE_MASK;
369 pcix_misc2_temp &= ~PERRFLOODENABLE_MASK;
370 pcix_misc2_temp &= ~PERRFATALENABLE_MASK;
371 pcix_misc2_temp &= ~PERRNONFATALENABLE_MASK;
372 pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
373}
374
375static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
376{
377 u32 pcix_misc2_temp;
378 u32 pcix_bridge_errors_reg;
379 u32 pcix_mem_base_reg;
380 u8 perr_set;
381 u8 rse_set;
382
383 /* write-one-to-clear Bridge_Errors[ PERR_OBSERVED ] */
384 pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, &pcix_bridge_errors_reg);
385 perr_set = pcix_bridge_errors_reg & PERR_OBSERVED_MASK;
386 if (perr_set) {
387 dbg ("%s W1C: Bridge_Errors[ PERR_OBSERVED = %08X]\n",__FUNCTION__ , perr_set);
388
389 pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, perr_set);
390 }
391
392 /* write-one-to-clear Memory_Base_Limit[ RSE ] */
393 pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, &pcix_mem_base_reg);
394 rse_set = pcix_mem_base_reg & RSE_MASK;
395 if (rse_set) {
396 dbg ("%s W1C: Memory_Base_Limit[ RSE ]\n",__FUNCTION__ );
397
398 pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, rse_set);
399 }
400 /* restore MiscII register */
401 pci_read_config_dword( p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp );
402
403 if (p_slot->ctrl->pcix_misc2_reg & SERRFATALENABLE_MASK)
404 pcix_misc2_temp |= SERRFATALENABLE_MASK;
405 else
406 pcix_misc2_temp &= ~SERRFATALENABLE_MASK;
407
408 if (p_slot->ctrl->pcix_misc2_reg & SERRNONFATALENABLE_MASK)
409 pcix_misc2_temp |= SERRNONFATALENABLE_MASK;
410 else
411 pcix_misc2_temp &= ~SERRNONFATALENABLE_MASK;
412
413 if (p_slot->ctrl->pcix_misc2_reg & PERRFLOODENABLE_MASK)
414 pcix_misc2_temp |= PERRFLOODENABLE_MASK;
415 else
416 pcix_misc2_temp &= ~PERRFLOODENABLE_MASK;
417
418 if (p_slot->ctrl->pcix_misc2_reg & PERRFATALENABLE_MASK)
419 pcix_misc2_temp |= PERRFATALENABLE_MASK;
420 else
421 pcix_misc2_temp &= ~PERRFATALENABLE_MASK;
422
423 if (p_slot->ctrl->pcix_misc2_reg & PERRNONFATALENABLE_MASK)
424 pcix_misc2_temp |= PERRNONFATALENABLE_MASK;
425 else
426 pcix_misc2_temp &= ~PERRNONFATALENABLE_MASK;
427 pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
428}
429
336#define SLOT_NAME_SIZE 10 430#define SLOT_NAME_SIZE 10
337 431
338static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) 432static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 25ccb0e47593..643252d9bf3b 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -894,7 +894,17 @@ int shpchp_enable_slot (struct slot *p_slot)
894 dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save); 894 dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save);
895 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); 895 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
896 896
897 rc = board_added(p_slot); 897 if(((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD) ||
898 (p_slot->ctrl->pci_dev->device == PCI_DEVICE_ID_AMD_POGO_7458))
899 && p_slot->ctrl->num_slots == 1) {
900 /* handle amd pogo errata; this must be done before enable */
901 amd_pogo_errata_save_misc_reg(p_slot);
902 rc = board_added(p_slot);
903 /* handle amd pogo errata; this must be done after enable */
904 amd_pogo_errata_restore_misc_reg(p_slot);
905 } else
906 rc = board_added(p_slot);
907
898 if (rc) { 908 if (rc) {
899 p_slot->hpc_ops->get_adapter_status(p_slot, 909 p_slot->hpc_ops->get_adapter_status(p_slot,
900 &(p_slot->presence_save)); 910 &(p_slot->presence_save));