diff options
author | Len Brown <len.brown@intel.com> | 2009-01-09 03:39:43 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-01-09 03:39:43 -0500 |
commit | b2576e1d4408e134e2188c967b1f28af39cd79d4 (patch) | |
tree | 004f3c82faab760f304ce031d6d2f572e7746a50 /drivers/pci/hotplug | |
parent | 3cc8a5f4ba91f67bbdb81a43a99281a26aab8d77 (diff) | |
parent | 2150edc6c5cf00f7adb54538b9ea2a3e9cedca3f (diff) |
Merge branch 'linus' into release
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r-- | drivers/pci/hotplug/Makefile | 3 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpi_pcihp.c | 69 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 117 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_ibm.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_core.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_ctrl.c | 6 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_pci.c | 4 | ||||
-rw-r--r-- | drivers/pci/hotplug/fakephp.c | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/ibmphp_core.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 15 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_acpi.c | 141 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 26 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 329 | ||||
-rw-r--r-- | drivers/pci/hotplug/rpadlpar_core.c | 69 |
16 files changed, 400 insertions, 389 deletions
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 9bdbe1a6688f..e31fb91652ce 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile | |||
@@ -55,6 +55,9 @@ pciehp-objs := pciehp_core.o \ | |||
55 | pciehp_ctrl.o \ | 55 | pciehp_ctrl.o \ |
56 | pciehp_pci.o \ | 56 | pciehp_pci.o \ |
57 | pciehp_hpc.o | 57 | pciehp_hpc.o |
58 | ifdef CONFIG_ACPI | ||
59 | pciehp-objs += pciehp_acpi.o | ||
60 | endif | ||
58 | 61 | ||
59 | shpchp-objs := shpchp_core.o \ | 62 | shpchp-objs := shpchp_core.o \ |
60 | shpchp_ctrl.o \ | 63 | shpchp_ctrl.o \ |
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 2c981cbb0719..1c1141801060 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
@@ -500,5 +500,74 @@ int acpi_root_bridge(acpi_handle handle) | |||
500 | } | 500 | } |
501 | EXPORT_SYMBOL_GPL(acpi_root_bridge); | 501 | EXPORT_SYMBOL_GPL(acpi_root_bridge); |
502 | 502 | ||
503 | |||
504 | static int is_ejectable(acpi_handle handle) | ||
505 | { | ||
506 | acpi_status status; | ||
507 | acpi_handle tmp; | ||
508 | unsigned long long removable; | ||
509 | status = acpi_get_handle(handle, "_ADR", &tmp); | ||
510 | if (ACPI_FAILURE(status)) | ||
511 | return 0; | ||
512 | status = acpi_get_handle(handle, "_EJ0", &tmp); | ||
513 | if (ACPI_SUCCESS(status)) | ||
514 | return 1; | ||
515 | status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable); | ||
516 | if (ACPI_SUCCESS(status) && removable) | ||
517 | return 1; | ||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | /** | ||
522 | * acpi_pcihp_check_ejectable - check if handle is ejectable ACPI PCI slot | ||
523 | * @pbus: the PCI bus of the PCI slot corresponding to 'handle' | ||
524 | * @handle: ACPI handle to check | ||
525 | * | ||
526 | * Return 1 if handle is ejectable PCI slot, 0 otherwise. | ||
527 | */ | ||
528 | int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle) | ||
529 | { | ||
530 | acpi_handle bridge_handle, parent_handle; | ||
531 | |||
532 | if (!(bridge_handle = acpi_pci_get_bridge_handle(pbus))) | ||
533 | return 0; | ||
534 | if ((ACPI_FAILURE(acpi_get_parent(handle, &parent_handle)))) | ||
535 | return 0; | ||
536 | if (bridge_handle != parent_handle) | ||
537 | return 0; | ||
538 | return is_ejectable(handle); | ||
539 | } | ||
540 | EXPORT_SYMBOL_GPL(acpi_pci_check_ejectable); | ||
541 | |||
542 | static acpi_status | ||
543 | check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
544 | { | ||
545 | int *found = (int *)context; | ||
546 | if (is_ejectable(handle)) { | ||
547 | *found = 1; | ||
548 | return AE_CTRL_TERMINATE; | ||
549 | } | ||
550 | return AE_OK; | ||
551 | } | ||
552 | |||
553 | /** | ||
554 | * acpi_pci_detect_ejectable - check if the PCI bus has ejectable slots | ||
555 | * @pbus - PCI bus to scan | ||
556 | * | ||
557 | * Returns 1 if the PCI bus has ACPI based ejectable slots, 0 otherwise. | ||
558 | */ | ||
559 | int acpi_pci_detect_ejectable(struct pci_bus *pbus) | ||
560 | { | ||
561 | acpi_handle handle; | ||
562 | int found = 0; | ||
563 | |||
564 | if (!(handle = acpi_pci_get_bridge_handle(pbus))) | ||
565 | return 0; | ||
566 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | ||
567 | check_hotplug, (void *)&found, NULL); | ||
568 | return found; | ||
569 | } | ||
570 | EXPORT_SYMBOL_GPL(acpi_pci_detect_ejectable); | ||
571 | |||
503 | module_param(debug_acpi, bool, 0644); | 572 | module_param(debug_acpi, bool, 0644); |
504 | MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not"); | 573 | MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not"); |
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 9bcb6cbd5aa9..4fc168b70095 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -44,7 +44,7 @@ | |||
44 | do { \ | 44 | do { \ |
45 | if (acpiphp_debug) \ | 45 | if (acpiphp_debug) \ |
46 | printk(KERN_DEBUG "%s: " format, \ | 46 | printk(KERN_DEBUG "%s: " format, \ |
47 | MY_NAME , ## arg); \ | 47 | MY_NAME , ## arg); \ |
48 | } while (0) | 48 | } while (0) |
49 | #define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) | 49 | #define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) |
50 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) | 50 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 3affc6472e65..f09b1010d477 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
47 | #include <linux/pci.h> | 47 | #include <linux/pci.h> |
48 | #include <linux/pci_hotplug.h> | 48 | #include <linux/pci_hotplug.h> |
49 | #include <linux/pci-acpi.h> | ||
49 | #include <linux/mutex.h> | 50 | #include <linux/mutex.h> |
50 | 51 | ||
51 | #include "../pci.h" | 52 | #include "../pci.h" |
@@ -62,61 +63,6 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus); | |||
62 | static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus); | 63 | static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus); |
63 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); | 64 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); |
64 | 65 | ||
65 | |||
66 | /* | ||
67 | * initialization & terminatation routines | ||
68 | */ | ||
69 | |||
70 | /** | ||
71 | * is_ejectable - determine if a slot is ejectable | ||
72 | * @handle: handle to acpi namespace | ||
73 | * | ||
74 | * Ejectable slot should satisfy at least these conditions: | ||
75 | * | ||
76 | * 1. has _ADR method | ||
77 | * 2. has _EJ0 method | ||
78 | * | ||
79 | * optionally | ||
80 | * | ||
81 | * 1. has _STA method | ||
82 | * 2. has _PS0 method | ||
83 | * 3. has _PS3 method | ||
84 | * 4. .. | ||
85 | */ | ||
86 | static int is_ejectable(acpi_handle handle) | ||
87 | { | ||
88 | acpi_status status; | ||
89 | acpi_handle tmp; | ||
90 | |||
91 | status = acpi_get_handle(handle, "_ADR", &tmp); | ||
92 | if (ACPI_FAILURE(status)) { | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | status = acpi_get_handle(handle, "_EJ0", &tmp); | ||
97 | if (ACPI_FAILURE(status)) { | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | return 1; | ||
102 | } | ||
103 | |||
104 | |||
105 | /* callback routine to check for the existence of ejectable slots */ | ||
106 | static acpi_status | ||
107 | is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
108 | { | ||
109 | int *count = (int *)context; | ||
110 | |||
111 | if (is_ejectable(handle)) { | ||
112 | (*count)++; | ||
113 | /* only one ejectable slot is enough */ | ||
114 | return AE_CTRL_TERMINATE; | ||
115 | } else { | ||
116 | return AE_OK; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | /* callback routine to check for the existence of a pci dock device */ | 66 | /* callback routine to check for the existence of a pci dock device */ |
121 | static acpi_status | 67 | static acpi_status |
122 | is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) | 68 | is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) |
@@ -131,9 +77,6 @@ is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
131 | } | 77 | } |
132 | } | 78 | } |
133 | 79 | ||
134 | |||
135 | |||
136 | |||
137 | /* | 80 | /* |
138 | * the _DCK method can do funny things... and sometimes not | 81 | * the _DCK method can do funny things... and sometimes not |
139 | * hah-hah funny. | 82 | * hah-hah funny. |
@@ -160,9 +103,9 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val, | |||
160 | 103 | ||
161 | if (((buses >> 8) & 0xff) != bus->secondary) { | 104 | if (((buses >> 8) & 0xff) != bus->secondary) { |
162 | buses = (buses & 0xff000000) | 105 | buses = (buses & 0xff000000) |
163 | | ((unsigned int)(bus->primary) << 0) | 106 | | ((unsigned int)(bus->primary) << 0) |
164 | | ((unsigned int)(bus->secondary) << 8) | 107 | | ((unsigned int)(bus->secondary) << 8) |
165 | | ((unsigned int)(bus->subordinate) << 16); | 108 | | ((unsigned int)(bus->subordinate) << 16); |
166 | pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); | 109 | pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); |
167 | } | 110 | } |
168 | return NOTIFY_OK; | 111 | return NOTIFY_OK; |
@@ -184,17 +127,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
184 | acpi_status status = AE_OK; | 127 | acpi_status status = AE_OK; |
185 | unsigned long long adr, sun; | 128 | unsigned long long adr, sun; |
186 | int device, function, retval; | 129 | int device, function, retval; |
130 | struct pci_bus *pbus = bridge->pci_bus; | ||
187 | 131 | ||
188 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); | 132 | if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) |
189 | |||
190 | if (ACPI_FAILURE(status)) | ||
191 | return AE_OK; | ||
192 | |||
193 | status = acpi_get_handle(handle, "_EJ0", &tmp); | ||
194 | |||
195 | if (ACPI_FAILURE(status) && !(is_dock_device(handle))) | ||
196 | return AE_OK; | 133 | return AE_OK; |
197 | 134 | ||
135 | acpi_evaluate_integer(handle, "_ADR", NULL, &adr); | ||
198 | device = (adr >> 16) & 0xffff; | 136 | device = (adr >> 16) & 0xffff; |
199 | function = adr & 0xffff; | 137 | function = adr & 0xffff; |
200 | 138 | ||
@@ -205,7 +143,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
205 | INIT_LIST_HEAD(&newfunc->sibling); | 143 | INIT_LIST_HEAD(&newfunc->sibling); |
206 | newfunc->handle = handle; | 144 | newfunc->handle = handle; |
207 | newfunc->function = function; | 145 | newfunc->function = function; |
208 | if (ACPI_SUCCESS(status)) | 146 | |
147 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp))) | ||
209 | newfunc->flags = FUNC_HAS_EJ0; | 148 | newfunc->flags = FUNC_HAS_EJ0; |
210 | 149 | ||
211 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) | 150 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) |
@@ -256,8 +195,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
256 | bridge->nr_slots++; | 195 | bridge->nr_slots++; |
257 | 196 | ||
258 | dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", | 197 | dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", |
259 | slot->sun, pci_domain_nr(bridge->pci_bus), | 198 | slot->sun, pci_domain_nr(pbus), pbus->number, device); |
260 | bridge->pci_bus->number, slot->device); | ||
261 | retval = acpiphp_register_hotplug_slot(slot); | 199 | retval = acpiphp_register_hotplug_slot(slot); |
262 | if (retval) { | 200 | if (retval) { |
263 | if (retval == -EBUSY) | 201 | if (retval == -EBUSY) |
@@ -274,8 +212,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
274 | list_add_tail(&newfunc->sibling, &slot->funcs); | 212 | list_add_tail(&newfunc->sibling, &slot->funcs); |
275 | 213 | ||
276 | /* associate corresponding pci_dev */ | 214 | /* associate corresponding pci_dev */ |
277 | newfunc->pci_dev = pci_get_slot(bridge->pci_bus, | 215 | newfunc->pci_dev = pci_get_slot(pbus, PCI_DEVFN(device, function)); |
278 | PCI_DEVFN(device, function)); | ||
279 | if (newfunc->pci_dev) { | 216 | if (newfunc->pci_dev) { |
280 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); | 217 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); |
281 | } | 218 | } |
@@ -324,27 +261,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
324 | 261 | ||
325 | 262 | ||
326 | /* see if it's worth looking at this bridge */ | 263 | /* see if it's worth looking at this bridge */ |
327 | static int detect_ejectable_slots(acpi_handle *bridge_handle) | 264 | static int detect_ejectable_slots(struct pci_bus *pbus) |
328 | { | 265 | { |
329 | acpi_status status; | 266 | int found = acpi_pci_detect_ejectable(pbus); |
330 | int count; | 267 | if (!found) { |
331 | 268 | acpi_handle bridge_handle = acpi_pci_get_bridge_handle(pbus); | |
332 | count = 0; | 269 | acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1, |
333 | 270 | is_pci_dock_device, (void *)&found, NULL); | |
334 | /* only check slots defined directly below bridge object */ | 271 | } |
335 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1, | 272 | return found; |
336 | is_ejectable_slot, (void *)&count, NULL); | ||
337 | |||
338 | /* | ||
339 | * we also need to add this bridge if there is a dock bridge or | ||
340 | * other pci device on a dock station (removable) | ||
341 | */ | ||
342 | if (!count) | ||
343 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, | ||
344 | (u32)1, is_pci_dock_device, (void *)&count, | ||
345 | NULL); | ||
346 | |||
347 | return count; | ||
348 | } | 273 | } |
349 | 274 | ||
350 | 275 | ||
@@ -554,7 +479,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
554 | goto out; | 479 | goto out; |
555 | 480 | ||
556 | /* check if this bridge has ejectable slots */ | 481 | /* check if this bridge has ejectable slots */ |
557 | if ((detect_ejectable_slots(handle) > 0)) { | 482 | if ((detect_ejectable_slots(dev->subordinate) > 0)) { |
558 | dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); | 483 | dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); |
559 | add_p2p_bridge(handle, dev); | 484 | add_p2p_bridge(handle, dev); |
560 | } | 485 | } |
@@ -615,7 +540,7 @@ static int add_bridge(acpi_handle handle) | |||
615 | } | 540 | } |
616 | 541 | ||
617 | /* check if this bridge has ejectable slots */ | 542 | /* check if this bridge has ejectable slots */ |
618 | if (detect_ejectable_slots(handle) > 0) { | 543 | if (detect_ejectable_slots(pci_bus) > 0) { |
619 | dbg("found PCI host-bus bridge with hot-pluggable slots\n"); | 544 | dbg("found PCI host-bus bridge with hot-pluggable slots\n"); |
620 | add_host_bridge(handle, pci_bus); | 545 | add_host_bridge(handle, pci_bus); |
621 | } | 546 | } |
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 881fdd2b7313..5befa7e379b7 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c | |||
@@ -271,7 +271,7 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context) | |||
271 | dbg("%s: generationg bus event\n", __func__); | 271 | dbg("%s: generationg bus event\n", __func__); |
272 | acpi_bus_generate_proc_event(note->device, note->event, detail); | 272 | acpi_bus_generate_proc_event(note->device, note->event, detail); |
273 | acpi_bus_generate_netlink_event(note->device->pnp.device_class, | 273 | acpi_bus_generate_netlink_event(note->device->pnp.device_class, |
274 | note->device->dev.bus_id, | 274 | dev_name(¬e->device->dev), |
275 | note->event, detail); | 275 | note->event, detail); |
276 | } else | 276 | } else |
277 | note->event = event; | 277 | note->event = event; |
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 8514c3a1746a..c2e1bcbb28a7 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c | |||
@@ -45,7 +45,7 @@ | |||
45 | 45 | ||
46 | #include "cpqphp.h" | 46 | #include "cpqphp.h" |
47 | #include "cpqphp_nvram.h" | 47 | #include "cpqphp_nvram.h" |
48 | #include "../../../arch/x86/pci/pci.h" /* horrible hack showing how processor dependent we are... */ | 48 | #include <asm/pci_x86.h> |
49 | 49 | ||
50 | 50 | ||
51 | /* Global variables */ | 51 | /* Global variables */ |
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index a60a25290995..cc227a8c4b11 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c | |||
@@ -1954,7 +1954,7 @@ void cpqhp_pushbutton_thread(unsigned long slot) | |||
1954 | return ; | 1954 | return ; |
1955 | } | 1955 | } |
1956 | 1956 | ||
1957 | if (func != NULL && ctrl != NULL) { | 1957 | if (ctrl != NULL) { |
1958 | if (cpqhp_process_SI(ctrl, func) != 0) { | 1958 | if (cpqhp_process_SI(ctrl, func) != 0) { |
1959 | amber_LED_on(ctrl, hp_slot); | 1959 | amber_LED_on(ctrl, hp_slot); |
1960 | green_LED_off(ctrl, hp_slot); | 1960 | green_LED_off(ctrl, hp_slot); |
@@ -2604,7 +2604,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func | |||
2604 | for (cloop = 0; cloop < 4; cloop++) { | 2604 | for (cloop = 0; cloop < 4; cloop++) { |
2605 | if (irqs.valid_INT & (0x01 << cloop)) { | 2605 | if (irqs.valid_INT & (0x01 << cloop)) { |
2606 | rc = cpqhp_set_irq(func->bus, func->device, | 2606 | rc = cpqhp_set_irq(func->bus, func->device, |
2607 | 0x0A + cloop, irqs.interrupt[cloop]); | 2607 | cloop + 1, irqs.interrupt[cloop]); |
2608 | if (rc) | 2608 | if (rc) |
2609 | goto free_and_out; | 2609 | goto free_and_out; |
2610 | } | 2610 | } |
@@ -2945,7 +2945,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func | |||
2945 | } | 2945 | } |
2946 | 2946 | ||
2947 | if (!behind_bridge) { | 2947 | if (!behind_bridge) { |
2948 | rc = cpqhp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ); | 2948 | rc = cpqhp_set_irq(func->bus, func->device, temp_byte, IRQ); |
2949 | if (rc) | 2949 | if (rc) |
2950 | return 1; | 2950 | return 1; |
2951 | } else { | 2951 | } else { |
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index 09021930589f..6c0ed0fcb8ee 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include "../pci.h" | 37 | #include "../pci.h" |
38 | #include "cpqphp.h" | 38 | #include "cpqphp.h" |
39 | #include "cpqphp_nvram.h" | 39 | #include "cpqphp_nvram.h" |
40 | #include "../../../arch/x86/pci/pci.h" /* horrible hack showing how processor dependent we are... */ | 40 | #include <asm/pci_x86.h> |
41 | 41 | ||
42 | 42 | ||
43 | u8 cpqhp_nic_irq; | 43 | u8 cpqhp_nic_irq; |
@@ -171,7 +171,7 @@ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num) | |||
171 | fakebus->number = bus_num; | 171 | fakebus->number = bus_num; |
172 | dbg("%s: dev %d, bus %d, pin %d, num %d\n", | 172 | dbg("%s: dev %d, bus %d, pin %d, num %d\n", |
173 | __func__, dev_num, bus_num, int_pin, irq_num); | 173 | __func__, dev_num, bus_num, int_pin, irq_num); |
174 | rc = pcibios_set_irq_routing(fakedev, int_pin - 0x0a, irq_num); | 174 | rc = pcibios_set_irq_routing(fakedev, int_pin - 1, irq_num); |
175 | kfree(fakedev); | 175 | kfree(fakedev); |
176 | kfree(fakebus); | 176 | kfree(fakebus); |
177 | dbg("%s: rc %d\n", __func__, rc); | 177 | dbg("%s: rc %d\n", __func__, rc); |
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 3a2637a00934..b0e7de9e536d 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c | |||
@@ -324,6 +324,7 @@ static int disable_slot(struct hotplug_slot *slot) | |||
324 | 324 | ||
325 | if (test_and_set_bit(0, &dslot->removed)) { | 325 | if (test_and_set_bit(0, &dslot->removed)) { |
326 | dbg("Slot already scheduled for removal\n"); | 326 | dbg("Slot already scheduled for removal\n"); |
327 | pci_dev_put(dev); | ||
327 | return -ENODEV; | 328 | return -ENODEV; |
328 | } | 329 | } |
329 | 330 | ||
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index 633e743442ac..dd18f857dfb0 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | #include <linux/wait.h> | 36 | #include <linux/wait.h> |
37 | #include "../pci.h" | 37 | #include "../pci.h" |
38 | #include "../../../arch/x86/pci/pci.h" /* for struct irq_routing_table */ | 38 | #include <asm/pci_x86.h> /* for struct irq_routing_table */ |
39 | #include "ibmphp.h" | 39 | #include "ibmphp.h" |
40 | 40 | ||
41 | #define attn_on(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNON) | 41 | #define attn_on(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNON) |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 7072952ea1d2..db85284ffb62 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -219,11 +219,23 @@ struct hpc_ops { | |||
219 | #include <acpi/acpi_bus.h> | 219 | #include <acpi/acpi_bus.h> |
220 | #include <linux/pci-acpi.h> | 220 | #include <linux/pci-acpi.h> |
221 | 221 | ||
222 | extern void __init pciehp_acpi_slot_detection_init(void); | ||
223 | extern int pciehp_acpi_slot_detection_check(struct pci_dev *dev); | ||
224 | |||
225 | static inline void pciehp_firmware_init(void) | ||
226 | { | ||
227 | pciehp_acpi_slot_detection_init(); | ||
228 | } | ||
229 | |||
222 | static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) | 230 | static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) |
223 | { | 231 | { |
232 | int retval; | ||
224 | u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | | 233 | u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | |
225 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | 234 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); |
226 | return acpi_get_hp_hw_control_from_firmware(dev, flags); | 235 | retval = acpi_get_hp_hw_control_from_firmware(dev, flags); |
236 | if (retval) | ||
237 | return retval; | ||
238 | return pciehp_acpi_slot_detection_check(dev); | ||
227 | } | 239 | } |
228 | 240 | ||
229 | static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, | 241 | static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, |
@@ -234,6 +246,7 @@ static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, | |||
234 | return 0; | 246 | return 0; |
235 | } | 247 | } |
236 | #else | 248 | #else |
249 | #define pciehp_firmware_init() do {} while (0) | ||
237 | #define pciehp_get_hp_hw_control_from_firmware(dev) 0 | 250 | #define pciehp_get_hp_hw_control_from_firmware(dev) 0 |
238 | #define pciehp_get_hp_params_from_firmware(dev, hpp) (-ENODEV) | 251 | #define pciehp_get_hp_params_from_firmware(dev, hpp) (-ENODEV) |
239 | #endif /* CONFIG_ACPI */ | 252 | #endif /* CONFIG_ACPI */ |
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c new file mode 100644 index 000000000000..438d795f9fe3 --- /dev/null +++ b/drivers/pci/hotplug/pciehp_acpi.c | |||
@@ -0,0 +1,141 @@ | |||
1 | /* | ||
2 | * ACPI related functions for PCI Express Hot Plug driver. | ||
3 | * | ||
4 | * Copyright (C) 2008 Kenji Kaneshige | ||
5 | * Copyright (C) 2008 Fujitsu Limited. | ||
6 | * | ||
7 | * All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or (at | ||
12 | * your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
17 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
18 | * details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <linux/acpi.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/pci_hotplug.h> | ||
29 | #include "pciehp.h" | ||
30 | |||
31 | #define PCIEHP_DETECT_PCIE (0) | ||
32 | #define PCIEHP_DETECT_ACPI (1) | ||
33 | #define PCIEHP_DETECT_AUTO (2) | ||
34 | #define PCIEHP_DETECT_DEFAULT PCIEHP_DETECT_AUTO | ||
35 | |||
36 | static int slot_detection_mode; | ||
37 | static char *pciehp_detect_mode; | ||
38 | module_param(pciehp_detect_mode, charp, 0444); | ||
39 | MODULE_PARM_DESC(pciehp_detect_mode, | ||
40 | "Slot detection mode: pcie, acpi, auto\n" | ||
41 | " pcie - Use PCIe based slot detection\n" | ||
42 | " acpi - Use ACPI for slot detection\n" | ||
43 | " auto(default) - Auto select mode. Use acpi option if duplicate\n" | ||
44 | " slot ids are found. Otherwise, use pcie option\n"); | ||
45 | |||
46 | int pciehp_acpi_slot_detection_check(struct pci_dev *dev) | ||
47 | { | ||
48 | if (slot_detection_mode != PCIEHP_DETECT_ACPI) | ||
49 | return 0; | ||
50 | if (acpi_pci_detect_ejectable(dev->subordinate)) | ||
51 | return 0; | ||
52 | return -ENODEV; | ||
53 | } | ||
54 | |||
55 | static int __init parse_detect_mode(void) | ||
56 | { | ||
57 | if (!pciehp_detect_mode) | ||
58 | return PCIEHP_DETECT_DEFAULT; | ||
59 | if (!strcmp(pciehp_detect_mode, "pcie")) | ||
60 | return PCIEHP_DETECT_PCIE; | ||
61 | if (!strcmp(pciehp_detect_mode, "acpi")) | ||
62 | return PCIEHP_DETECT_ACPI; | ||
63 | if (!strcmp(pciehp_detect_mode, "auto")) | ||
64 | return PCIEHP_DETECT_AUTO; | ||
65 | warn("bad specifier '%s' for pciehp_detect_mode. Use default\n", | ||
66 | pciehp_detect_mode); | ||
67 | return PCIEHP_DETECT_DEFAULT; | ||
68 | } | ||
69 | |||
70 | static struct pcie_port_service_id __initdata port_pci_ids[] = { | ||
71 | { | ||
72 | .vendor = PCI_ANY_ID, | ||
73 | .device = PCI_ANY_ID, | ||
74 | .port_type = PCIE_ANY_PORT, | ||
75 | .service_type = PCIE_PORT_SERVICE_HP, | ||
76 | .driver_data = 0, | ||
77 | }, { /* end: all zeroes */ } | ||
78 | }; | ||
79 | |||
80 | static int __initdata dup_slot_id; | ||
81 | static int __initdata acpi_slot_detected; | ||
82 | static struct list_head __initdata dummy_slots = LIST_HEAD_INIT(dummy_slots); | ||
83 | |||
84 | /* Dummy driver for dumplicate name detection */ | ||
85 | static int __init dummy_probe(struct pcie_device *dev, | ||
86 | const struct pcie_port_service_id *id) | ||
87 | { | ||
88 | int pos; | ||
89 | u32 slot_cap; | ||
90 | struct slot *slot, *tmp; | ||
91 | struct pci_dev *pdev = dev->port; | ||
92 | struct pci_bus *pbus = pdev->subordinate; | ||
93 | if (!(slot = kzalloc(sizeof(*slot), GFP_KERNEL))) | ||
94 | return -ENOMEM; | ||
95 | /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ | ||
96 | if (pciehp_get_hp_hw_control_from_firmware(pdev)) | ||
97 | return -ENODEV; | ||
98 | if (!(pos = pci_find_capability(pdev, PCI_CAP_ID_EXP))) | ||
99 | return -ENODEV; | ||
100 | pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap); | ||
101 | slot->number = slot_cap >> 19; | ||
102 | list_for_each_entry(tmp, &dummy_slots, slot_list) { | ||
103 | if (tmp->number == slot->number) | ||
104 | dup_slot_id++; | ||
105 | } | ||
106 | list_add_tail(&slot->slot_list, &dummy_slots); | ||
107 | if (!acpi_slot_detected && acpi_pci_detect_ejectable(pbus)) | ||
108 | acpi_slot_detected = 1; | ||
109 | return -ENODEV; /* dummy driver always returns error */ | ||
110 | } | ||
111 | |||
112 | static struct pcie_port_service_driver __initdata dummy_driver = { | ||
113 | .name = "pciehp_dummy", | ||
114 | .id_table = port_pci_ids, | ||
115 | .probe = dummy_probe, | ||
116 | }; | ||
117 | |||
118 | static int __init select_detection_mode(void) | ||
119 | { | ||
120 | struct slot *slot, *tmp; | ||
121 | pcie_port_service_register(&dummy_driver); | ||
122 | pcie_port_service_unregister(&dummy_driver); | ||
123 | list_for_each_entry_safe(slot, tmp, &dummy_slots, slot_list) { | ||
124 | list_del(&slot->slot_list); | ||
125 | kfree(slot); | ||
126 | } | ||
127 | if (acpi_slot_detected && dup_slot_id) | ||
128 | return PCIEHP_DETECT_ACPI; | ||
129 | return PCIEHP_DETECT_PCIE; | ||
130 | } | ||
131 | |||
132 | void __init pciehp_acpi_slot_detection_init(void) | ||
133 | { | ||
134 | slot_detection_mode = parse_detect_mode(); | ||
135 | if (slot_detection_mode != PCIEHP_DETECT_AUTO) | ||
136 | goto out; | ||
137 | slot_detection_mode = select_detection_mode(); | ||
138 | out: | ||
139 | if (slot_detection_mode == PCIEHP_DETECT_ACPI) | ||
140 | info("Using ACPI for slot detection.\n"); | ||
141 | } | ||
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 39cf248d24e3..5482d4ed8256 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -522,6 +522,7 @@ static int __init pcied_init(void) | |||
522 | { | 522 | { |
523 | int retval = 0; | 523 | int retval = 0; |
524 | 524 | ||
525 | pciehp_firmware_init(); | ||
525 | retval = pcie_port_service_register(&hpdriver_portdrv); | 526 | retval = pcie_port_service_register(&hpdriver_portdrv); |
526 | dbg("pcie_port_service_register = %d\n", retval); | 527 | dbg("pcie_port_service_register = %d\n", retval); |
527 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 528 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index fead63c6b49e..ff4034502d24 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -178,15 +178,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) | |||
178 | "Issue of Slot Power Off command failed\n"); | 178 | "Issue of Slot Power Off command failed\n"); |
179 | return; | 179 | return; |
180 | } | 180 | } |
181 | /* | ||
182 | * After turning power off, we must wait for at least 1 second | ||
183 | * before taking any action that relies on power having been | ||
184 | * removed from the slot/adapter. | ||
185 | */ | ||
186 | msleep(1000); | ||
181 | } | 187 | } |
182 | 188 | ||
183 | /* | ||
184 | * After turning power off, we must wait for at least 1 second | ||
185 | * before taking any action that relies on power having been | ||
186 | * removed from the slot/adapter. | ||
187 | */ | ||
188 | msleep(1000); | ||
189 | |||
190 | if (PWR_LED(ctrl)) | 189 | if (PWR_LED(ctrl)) |
191 | pslot->hpc_ops->green_led_off(pslot); | 190 | pslot->hpc_ops->green_led_off(pslot); |
192 | 191 | ||
@@ -286,15 +285,14 @@ static int remove_board(struct slot *p_slot) | |||
286 | "Issue of Slot Disable command failed\n"); | 285 | "Issue of Slot Disable command failed\n"); |
287 | return retval; | 286 | return retval; |
288 | } | 287 | } |
288 | /* | ||
289 | * After turning power off, we must wait for at least 1 second | ||
290 | * before taking any action that relies on power having been | ||
291 | * removed from the slot/adapter. | ||
292 | */ | ||
293 | msleep(1000); | ||
289 | } | 294 | } |
290 | 295 | ||
291 | /* | ||
292 | * After turning power off, we must wait for at least 1 second | ||
293 | * before taking any action that relies on power having been | ||
294 | * removed from the slot/adapter. | ||
295 | */ | ||
296 | msleep(1000); | ||
297 | |||
298 | if (PWR_LED(ctrl)) | 296 | if (PWR_LED(ctrl)) |
299 | /* turn off Green LED */ | 297 | /* turn off Green LED */ |
300 | p_slot->hpc_ops->green_led_off(p_slot); | 298 | p_slot->hpc_ops->green_led_off(p_slot); |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index b643ca13e4f1..71a8012886b0 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -42,42 +42,6 @@ | |||
42 | 42 | ||
43 | static atomic_t pciehp_num_controllers = ATOMIC_INIT(0); | 43 | static atomic_t pciehp_num_controllers = ATOMIC_INIT(0); |
44 | 44 | ||
45 | struct ctrl_reg { | ||
46 | u8 cap_id; | ||
47 | u8 nxt_ptr; | ||
48 | u16 cap_reg; | ||
49 | u32 dev_cap; | ||
50 | u16 dev_ctrl; | ||
51 | u16 dev_status; | ||
52 | u32 lnk_cap; | ||
53 | u16 lnk_ctrl; | ||
54 | u16 lnk_status; | ||
55 | u32 slot_cap; | ||
56 | u16 slot_ctrl; | ||
57 | u16 slot_status; | ||
58 | u16 root_ctrl; | ||
59 | u16 rsvp; | ||
60 | u32 root_status; | ||
61 | } __attribute__ ((packed)); | ||
62 | |||
63 | /* offsets to the controller registers based on the above structure layout */ | ||
64 | enum ctrl_offsets { | ||
65 | PCIECAPID = offsetof(struct ctrl_reg, cap_id), | ||
66 | NXTCAPPTR = offsetof(struct ctrl_reg, nxt_ptr), | ||
67 | CAPREG = offsetof(struct ctrl_reg, cap_reg), | ||
68 | DEVCAP = offsetof(struct ctrl_reg, dev_cap), | ||
69 | DEVCTRL = offsetof(struct ctrl_reg, dev_ctrl), | ||
70 | DEVSTATUS = offsetof(struct ctrl_reg, dev_status), | ||
71 | LNKCAP = offsetof(struct ctrl_reg, lnk_cap), | ||
72 | LNKCTRL = offsetof(struct ctrl_reg, lnk_ctrl), | ||
73 | LNKSTATUS = offsetof(struct ctrl_reg, lnk_status), | ||
74 | SLOTCAP = offsetof(struct ctrl_reg, slot_cap), | ||
75 | SLOTCTRL = offsetof(struct ctrl_reg, slot_ctrl), | ||
76 | SLOTSTATUS = offsetof(struct ctrl_reg, slot_status), | ||
77 | ROOTCTRL = offsetof(struct ctrl_reg, root_ctrl), | ||
78 | ROOTSTATUS = offsetof(struct ctrl_reg, root_status), | ||
79 | }; | ||
80 | |||
81 | static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) | 45 | static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) |
82 | { | 46 | { |
83 | struct pci_dev *dev = ctrl->pci_dev; | 47 | struct pci_dev *dev = ctrl->pci_dev; |
@@ -102,95 +66,9 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) | |||
102 | return pci_write_config_dword(dev, ctrl->cap_base + reg, value); | 66 | return pci_write_config_dword(dev, ctrl->cap_base + reg, value); |
103 | } | 67 | } |
104 | 68 | ||
105 | /* Field definitions in PCI Express Capabilities Register */ | ||
106 | #define CAP_VER 0x000F | ||
107 | #define DEV_PORT_TYPE 0x00F0 | ||
108 | #define SLOT_IMPL 0x0100 | ||
109 | #define MSG_NUM 0x3E00 | ||
110 | |||
111 | /* Device or Port Type */ | ||
112 | #define NAT_ENDPT 0x00 | ||
113 | #define LEG_ENDPT 0x01 | ||
114 | #define ROOT_PORT 0x04 | ||
115 | #define UP_STREAM 0x05 | ||
116 | #define DN_STREAM 0x06 | ||
117 | #define PCIE_PCI_BRDG 0x07 | ||
118 | #define PCI_PCIE_BRDG 0x10 | ||
119 | |||
120 | /* Field definitions in Device Capabilities Register */ | ||
121 | #define DATTN_BUTTN_PRSN 0x1000 | ||
122 | #define DATTN_LED_PRSN 0x2000 | ||
123 | #define DPWR_LED_PRSN 0x4000 | ||
124 | |||
125 | /* Field definitions in Link Capabilities Register */ | ||
126 | #define MAX_LNK_SPEED 0x000F | ||
127 | #define MAX_LNK_WIDTH 0x03F0 | ||
128 | #define LINK_ACTIVE_REPORTING 0x00100000 | ||
129 | |||
130 | /* Link Width Encoding */ | ||
131 | #define LNK_X1 0x01 | ||
132 | #define LNK_X2 0x02 | ||
133 | #define LNK_X4 0x04 | ||
134 | #define LNK_X8 0x08 | ||
135 | #define LNK_X12 0x0C | ||
136 | #define LNK_X16 0x10 | ||
137 | #define LNK_X32 0x20 | ||
138 | |||
139 | /*Field definitions of Link Status Register */ | ||
140 | #define LNK_SPEED 0x000F | ||
141 | #define NEG_LINK_WD 0x03F0 | ||
142 | #define LNK_TRN_ERR 0x0400 | ||
143 | #define LNK_TRN 0x0800 | ||
144 | #define SLOT_CLK_CONF 0x1000 | ||
145 | #define LINK_ACTIVE 0x2000 | ||
146 | |||
147 | /* Field definitions in Slot Capabilities Register */ | ||
148 | #define ATTN_BUTTN_PRSN 0x00000001 | ||
149 | #define PWR_CTRL_PRSN 0x00000002 | ||
150 | #define MRL_SENS_PRSN 0x00000004 | ||
151 | #define ATTN_LED_PRSN 0x00000008 | ||
152 | #define PWR_LED_PRSN 0x00000010 | ||
153 | #define HP_SUPR_RM_SUP 0x00000020 | ||
154 | #define HP_CAP 0x00000040 | ||
155 | #define SLOT_PWR_VALUE 0x000003F8 | ||
156 | #define SLOT_PWR_LIMIT 0x00000C00 | ||
157 | #define PSN 0xFFF80000 /* PSN: Physical Slot Number */ | ||
158 | |||
159 | /* Field definitions in Slot Control Register */ | ||
160 | #define ATTN_BUTTN_ENABLE 0x0001 | ||
161 | #define PWR_FAULT_DETECT_ENABLE 0x0002 | ||
162 | #define MRL_DETECT_ENABLE 0x0004 | ||
163 | #define PRSN_DETECT_ENABLE 0x0008 | ||
164 | #define CMD_CMPL_INTR_ENABLE 0x0010 | ||
165 | #define HP_INTR_ENABLE 0x0020 | ||
166 | #define ATTN_LED_CTRL 0x00C0 | ||
167 | #define PWR_LED_CTRL 0x0300 | ||
168 | #define PWR_CTRL 0x0400 | ||
169 | #define EMI_CTRL 0x0800 | ||
170 | |||
171 | /* Attention indicator and Power indicator states */ | ||
172 | #define LED_ON 0x01 | ||
173 | #define LED_BLINK 0x10 | ||
174 | #define LED_OFF 0x11 | ||
175 | |||
176 | /* Power Control Command */ | 69 | /* Power Control Command */ |
177 | #define POWER_ON 0 | 70 | #define POWER_ON 0 |
178 | #define POWER_OFF 0x0400 | 71 | #define POWER_OFF PCI_EXP_SLTCTL_PCC |
179 | |||
180 | /* EMI Status defines */ | ||
181 | #define EMI_DISENGAGED 0 | ||
182 | #define EMI_ENGAGED 1 | ||
183 | |||
184 | /* Field definitions in Slot Status Register */ | ||
185 | #define ATTN_BUTTN_PRESSED 0x0001 | ||
186 | #define PWR_FAULT_DETECTED 0x0002 | ||
187 | #define MRL_SENS_CHANGED 0x0004 | ||
188 | #define PRSN_DETECT_CHANGED 0x0008 | ||
189 | #define CMD_COMPLETED 0x0010 | ||
190 | #define MRL_STATE 0x0020 | ||
191 | #define PRSN_STATE 0x0040 | ||
192 | #define EMI_STATE 0x0080 | ||
193 | #define EMI_STATUS_BIT 7 | ||
194 | 72 | ||
195 | static irqreturn_t pcie_isr(int irq, void *dev_id); | 73 | static irqreturn_t pcie_isr(int irq, void *dev_id); |
196 | static void start_int_poll_timer(struct controller *ctrl, int sec); | 74 | static void start_int_poll_timer(struct controller *ctrl, int sec); |
@@ -253,22 +131,20 @@ static inline void pciehp_free_irq(struct controller *ctrl) | |||
253 | static int pcie_poll_cmd(struct controller *ctrl) | 131 | static int pcie_poll_cmd(struct controller *ctrl) |
254 | { | 132 | { |
255 | u16 slot_status; | 133 | u16 slot_status; |
256 | int timeout = 1000; | 134 | int err, timeout = 1000; |
257 | 135 | ||
258 | if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) { | 136 | err = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); |
259 | if (slot_status & CMD_COMPLETED) { | 137 | if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) { |
260 | pciehp_writew(ctrl, SLOTSTATUS, CMD_COMPLETED); | 138 | pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); |
261 | return 1; | 139 | return 1; |
262 | } | ||
263 | } | 140 | } |
264 | while (timeout > 0) { | 141 | while (timeout > 0) { |
265 | msleep(10); | 142 | msleep(10); |
266 | timeout -= 10; | 143 | timeout -= 10; |
267 | if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) { | 144 | err = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); |
268 | if (slot_status & CMD_COMPLETED) { | 145 | if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) { |
269 | pciehp_writew(ctrl, SLOTSTATUS, CMD_COMPLETED); | 146 | pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); |
270 | return 1; | 147 | return 1; |
271 | } | ||
272 | } | 148 | } |
273 | } | 149 | } |
274 | return 0; /* timeout */ | 150 | return 0; /* timeout */ |
@@ -302,14 +178,14 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) | |||
302 | 178 | ||
303 | mutex_lock(&ctrl->ctrl_lock); | 179 | mutex_lock(&ctrl->ctrl_lock); |
304 | 180 | ||
305 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | 181 | retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); |
306 | if (retval) { | 182 | if (retval) { |
307 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", | 183 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", |
308 | __func__); | 184 | __func__); |
309 | goto out; | 185 | goto out; |
310 | } | 186 | } |
311 | 187 | ||
312 | if (slot_status & CMD_COMPLETED) { | 188 | if (slot_status & PCI_EXP_SLTSTA_CC) { |
313 | if (!ctrl->no_cmd_complete) { | 189 | if (!ctrl->no_cmd_complete) { |
314 | /* | 190 | /* |
315 | * After 1 sec and CMD_COMPLETED still not set, just | 191 | * After 1 sec and CMD_COMPLETED still not set, just |
@@ -332,7 +208,7 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) | |||
332 | } | 208 | } |
333 | } | 209 | } |
334 | 210 | ||
335 | retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 211 | retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); |
336 | if (retval) { | 212 | if (retval) { |
337 | ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); | 213 | ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); |
338 | goto out; | 214 | goto out; |
@@ -342,7 +218,7 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) | |||
342 | slot_ctrl |= (cmd & mask); | 218 | slot_ctrl |= (cmd & mask); |
343 | ctrl->cmd_busy = 1; | 219 | ctrl->cmd_busy = 1; |
344 | smp_mb(); | 220 | smp_mb(); |
345 | retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl); | 221 | retval = pciehp_writew(ctrl, PCI_EXP_SLTCTL, slot_ctrl); |
346 | if (retval) | 222 | if (retval) |
347 | ctrl_err(ctrl, "Cannot write to SLOTCTRL register\n"); | 223 | ctrl_err(ctrl, "Cannot write to SLOTCTRL register\n"); |
348 | 224 | ||
@@ -356,8 +232,8 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) | |||
356 | * completed interrupt is not enabled, we need to poll | 232 | * completed interrupt is not enabled, we need to poll |
357 | * command completed event. | 233 | * command completed event. |
358 | */ | 234 | */ |
359 | if (!(slot_ctrl & HP_INTR_ENABLE) || | 235 | if (!(slot_ctrl & PCI_EXP_SLTCTL_HPIE) || |
360 | !(slot_ctrl & CMD_CMPL_INTR_ENABLE)) | 236 | !(slot_ctrl & PCI_EXP_SLTCTL_CCIE)) |
361 | poll = 1; | 237 | poll = 1; |
362 | pcie_wait_cmd(ctrl, poll); | 238 | pcie_wait_cmd(ctrl, poll); |
363 | } | 239 | } |
@@ -370,9 +246,9 @@ static inline int check_link_active(struct controller *ctrl) | |||
370 | { | 246 | { |
371 | u16 link_status; | 247 | u16 link_status; |
372 | 248 | ||
373 | if (pciehp_readw(ctrl, LNKSTATUS, &link_status)) | 249 | if (pciehp_readw(ctrl, PCI_EXP_LNKSTA, &link_status)) |
374 | return 0; | 250 | return 0; |
375 | return !!(link_status & LINK_ACTIVE); | 251 | return !!(link_status & PCI_EXP_LNKSTA_DLLLA); |
376 | } | 252 | } |
377 | 253 | ||
378 | static void pcie_wait_link_active(struct controller *ctrl) | 254 | static void pcie_wait_link_active(struct controller *ctrl) |
@@ -412,15 +288,15 @@ static int hpc_check_lnk_status(struct controller *ctrl) | |||
412 | } else | 288 | } else |
413 | msleep(1000); | 289 | msleep(1000); |
414 | 290 | ||
415 | retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status); | 291 | retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); |
416 | if (retval) { | 292 | if (retval) { |
417 | ctrl_err(ctrl, "Cannot read LNKSTATUS register\n"); | 293 | ctrl_err(ctrl, "Cannot read LNKSTATUS register\n"); |
418 | return retval; | 294 | return retval; |
419 | } | 295 | } |
420 | 296 | ||
421 | ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status); | 297 | ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status); |
422 | if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) || | 298 | if ((lnk_status & PCI_EXP_LNKSTA_LT) || |
423 | !(lnk_status & NEG_LINK_WD)) { | 299 | !(lnk_status & PCI_EXP_LNKSTA_NLW)) { |
424 | ctrl_err(ctrl, "Link Training Error occurs \n"); | 300 | ctrl_err(ctrl, "Link Training Error occurs \n"); |
425 | retval = -1; | 301 | retval = -1; |
426 | return retval; | 302 | return retval; |
@@ -436,16 +312,16 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status) | |||
436 | u8 atten_led_state; | 312 | u8 atten_led_state; |
437 | int retval = 0; | 313 | int retval = 0; |
438 | 314 | ||
439 | retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 315 | retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); |
440 | if (retval) { | 316 | if (retval) { |
441 | ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); | 317 | ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); |
442 | return retval; | 318 | return retval; |
443 | } | 319 | } |
444 | 320 | ||
445 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", | 321 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", |
446 | __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl); | 322 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl); |
447 | 323 | ||
448 | atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6; | 324 | atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6; |
449 | 325 | ||
450 | switch (atten_led_state) { | 326 | switch (atten_led_state) { |
451 | case 0: | 327 | case 0: |
@@ -475,15 +351,15 @@ static int hpc_get_power_status(struct slot *slot, u8 *status) | |||
475 | u8 pwr_state; | 351 | u8 pwr_state; |
476 | int retval = 0; | 352 | int retval = 0; |
477 | 353 | ||
478 | retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 354 | retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); |
479 | if (retval) { | 355 | if (retval) { |
480 | ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); | 356 | ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); |
481 | return retval; | 357 | return retval; |
482 | } | 358 | } |
483 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", | 359 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", |
484 | __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl); | 360 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl); |
485 | 361 | ||
486 | pwr_state = (slot_ctrl & PWR_CTRL) >> 10; | 362 | pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10; |
487 | 363 | ||
488 | switch (pwr_state) { | 364 | switch (pwr_state) { |
489 | case 0: | 365 | case 0: |
@@ -504,17 +380,15 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status) | |||
504 | { | 380 | { |
505 | struct controller *ctrl = slot->ctrl; | 381 | struct controller *ctrl = slot->ctrl; |
506 | u16 slot_status; | 382 | u16 slot_status; |
507 | int retval = 0; | 383 | int retval; |
508 | 384 | ||
509 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | 385 | retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); |
510 | if (retval) { | 386 | if (retval) { |
511 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", | 387 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", |
512 | __func__); | 388 | __func__); |
513 | return retval; | 389 | return retval; |
514 | } | 390 | } |
515 | 391 | *status = !!(slot_status & PCI_EXP_SLTSTA_MRLSS); | |
516 | *status = (((slot_status & MRL_STATE) >> 5) == 0) ? 0 : 1; | ||
517 | |||
518 | return 0; | 392 | return 0; |
519 | } | 393 | } |
520 | 394 | ||
@@ -522,18 +396,15 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status) | |||
522 | { | 396 | { |
523 | struct controller *ctrl = slot->ctrl; | 397 | struct controller *ctrl = slot->ctrl; |
524 | u16 slot_status; | 398 | u16 slot_status; |
525 | u8 card_state; | 399 | int retval; |
526 | int retval = 0; | ||
527 | 400 | ||
528 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | 401 | retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); |
529 | if (retval) { | 402 | if (retval) { |
530 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", | 403 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", |
531 | __func__); | 404 | __func__); |
532 | return retval; | 405 | return retval; |
533 | } | 406 | } |
534 | card_state = (u8)((slot_status & PRSN_STATE) >> 6); | 407 | *status = !!(slot_status & PCI_EXP_SLTSTA_PDS); |
535 | *status = (card_state == 1) ? 1 : 0; | ||
536 | |||
537 | return 0; | 408 | return 0; |
538 | } | 409 | } |
539 | 410 | ||
@@ -541,32 +412,28 @@ static int hpc_query_power_fault(struct slot *slot) | |||
541 | { | 412 | { |
542 | struct controller *ctrl = slot->ctrl; | 413 | struct controller *ctrl = slot->ctrl; |
543 | u16 slot_status; | 414 | u16 slot_status; |
544 | u8 pwr_fault; | 415 | int retval; |
545 | int retval = 0; | ||
546 | 416 | ||
547 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | 417 | retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); |
548 | if (retval) { | 418 | if (retval) { |
549 | ctrl_err(ctrl, "Cannot check for power fault\n"); | 419 | ctrl_err(ctrl, "Cannot check for power fault\n"); |
550 | return retval; | 420 | return retval; |
551 | } | 421 | } |
552 | pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); | 422 | return !!(slot_status & PCI_EXP_SLTSTA_PFD); |
553 | |||
554 | return pwr_fault; | ||
555 | } | 423 | } |
556 | 424 | ||
557 | static int hpc_get_emi_status(struct slot *slot, u8 *status) | 425 | static int hpc_get_emi_status(struct slot *slot, u8 *status) |
558 | { | 426 | { |
559 | struct controller *ctrl = slot->ctrl; | 427 | struct controller *ctrl = slot->ctrl; |
560 | u16 slot_status; | 428 | u16 slot_status; |
561 | int retval = 0; | 429 | int retval; |
562 | 430 | ||
563 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | 431 | retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); |
564 | if (retval) { | 432 | if (retval) { |
565 | ctrl_err(ctrl, "Cannot check EMI status\n"); | 433 | ctrl_err(ctrl, "Cannot check EMI status\n"); |
566 | return retval; | 434 | return retval; |
567 | } | 435 | } |
568 | *status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT; | 436 | *status = !!(slot_status & PCI_EXP_SLTSTA_EIS); |
569 | |||
570 | return retval; | 437 | return retval; |
571 | } | 438 | } |
572 | 439 | ||
@@ -576,8 +443,8 @@ static int hpc_toggle_emi(struct slot *slot) | |||
576 | u16 cmd_mask; | 443 | u16 cmd_mask; |
577 | int rc; | 444 | int rc; |
578 | 445 | ||
579 | slot_cmd = EMI_CTRL; | 446 | slot_cmd = PCI_EXP_SLTCTL_EIC; |
580 | cmd_mask = EMI_CTRL; | 447 | cmd_mask = PCI_EXP_SLTCTL_EIC; |
581 | rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask); | 448 | rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask); |
582 | slot->last_emi_toggle = get_seconds(); | 449 | slot->last_emi_toggle = get_seconds(); |
583 | 450 | ||
@@ -591,7 +458,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) | |||
591 | u16 cmd_mask; | 458 | u16 cmd_mask; |
592 | int rc; | 459 | int rc; |
593 | 460 | ||
594 | cmd_mask = ATTN_LED_CTRL; | 461 | cmd_mask = PCI_EXP_SLTCTL_AIC; |
595 | switch (value) { | 462 | switch (value) { |
596 | case 0 : /* turn off */ | 463 | case 0 : /* turn off */ |
597 | slot_cmd = 0x00C0; | 464 | slot_cmd = 0x00C0; |
@@ -607,7 +474,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) | |||
607 | } | 474 | } |
608 | rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 475 | rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
609 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 476 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", |
610 | __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 477 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); |
611 | 478 | ||
612 | return rc; | 479 | return rc; |
613 | } | 480 | } |
@@ -619,10 +486,10 @@ static void hpc_set_green_led_on(struct slot *slot) | |||
619 | u16 cmd_mask; | 486 | u16 cmd_mask; |
620 | 487 | ||
621 | slot_cmd = 0x0100; | 488 | slot_cmd = 0x0100; |
622 | cmd_mask = PWR_LED_CTRL; | 489 | cmd_mask = PCI_EXP_SLTCTL_PIC; |
623 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 490 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
624 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 491 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", |
625 | __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 492 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); |
626 | } | 493 | } |
627 | 494 | ||
628 | static void hpc_set_green_led_off(struct slot *slot) | 495 | static void hpc_set_green_led_off(struct slot *slot) |
@@ -632,10 +499,10 @@ static void hpc_set_green_led_off(struct slot *slot) | |||
632 | u16 cmd_mask; | 499 | u16 cmd_mask; |
633 | 500 | ||
634 | slot_cmd = 0x0300; | 501 | slot_cmd = 0x0300; |
635 | cmd_mask = PWR_LED_CTRL; | 502 | cmd_mask = PCI_EXP_SLTCTL_PIC; |
636 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 503 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
637 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 504 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", |
638 | __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 505 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); |
639 | } | 506 | } |
640 | 507 | ||
641 | static void hpc_set_green_led_blink(struct slot *slot) | 508 | static void hpc_set_green_led_blink(struct slot *slot) |
@@ -645,10 +512,10 @@ static void hpc_set_green_led_blink(struct slot *slot) | |||
645 | u16 cmd_mask; | 512 | u16 cmd_mask; |
646 | 513 | ||
647 | slot_cmd = 0x0200; | 514 | slot_cmd = 0x0200; |
648 | cmd_mask = PWR_LED_CTRL; | 515 | cmd_mask = PCI_EXP_SLTCTL_PIC; |
649 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 516 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
650 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 517 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", |
651 | __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 518 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); |
652 | } | 519 | } |
653 | 520 | ||
654 | static int hpc_power_on_slot(struct slot * slot) | 521 | static int hpc_power_on_slot(struct slot * slot) |
@@ -662,15 +529,15 @@ static int hpc_power_on_slot(struct slot * slot) | |||
662 | ctrl_dbg(ctrl, "%s: slot->hp_slot %x\n", __func__, slot->hp_slot); | 529 | ctrl_dbg(ctrl, "%s: slot->hp_slot %x\n", __func__, slot->hp_slot); |
663 | 530 | ||
664 | /* Clear sticky power-fault bit from previous power failures */ | 531 | /* Clear sticky power-fault bit from previous power failures */ |
665 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | 532 | retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); |
666 | if (retval) { | 533 | if (retval) { |
667 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", | 534 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", |
668 | __func__); | 535 | __func__); |
669 | return retval; | 536 | return retval; |
670 | } | 537 | } |
671 | slot_status &= PWR_FAULT_DETECTED; | 538 | slot_status &= PCI_EXP_SLTSTA_PFD; |
672 | if (slot_status) { | 539 | if (slot_status) { |
673 | retval = pciehp_writew(ctrl, SLOTSTATUS, slot_status); | 540 | retval = pciehp_writew(ctrl, PCI_EXP_SLTSTA, slot_status); |
674 | if (retval) { | 541 | if (retval) { |
675 | ctrl_err(ctrl, | 542 | ctrl_err(ctrl, |
676 | "%s: Cannot write to SLOTSTATUS register\n", | 543 | "%s: Cannot write to SLOTSTATUS register\n", |
@@ -680,13 +547,13 @@ static int hpc_power_on_slot(struct slot * slot) | |||
680 | } | 547 | } |
681 | 548 | ||
682 | slot_cmd = POWER_ON; | 549 | slot_cmd = POWER_ON; |
683 | cmd_mask = PWR_CTRL; | 550 | cmd_mask = PCI_EXP_SLTCTL_PCC; |
684 | /* Enable detection that we turned off at slot power-off time */ | 551 | /* Enable detection that we turned off at slot power-off time */ |
685 | if (!pciehp_poll_mode) { | 552 | if (!pciehp_poll_mode) { |
686 | slot_cmd |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | | 553 | slot_cmd |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | |
687 | PRSN_DETECT_ENABLE); | 554 | PCI_EXP_SLTCTL_PDCE); |
688 | cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | | 555 | cmd_mask |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | |
689 | PRSN_DETECT_ENABLE); | 556 | PCI_EXP_SLTCTL_PDCE); |
690 | } | 557 | } |
691 | 558 | ||
692 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 559 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
@@ -696,7 +563,7 @@ static int hpc_power_on_slot(struct slot * slot) | |||
696 | return -1; | 563 | return -1; |
697 | } | 564 | } |
698 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 565 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", |
699 | __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 566 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); |
700 | 567 | ||
701 | return retval; | 568 | return retval; |
702 | } | 569 | } |
@@ -753,7 +620,7 @@ static int hpc_power_off_slot(struct slot * slot) | |||
753 | changed = pcie_mask_bad_dllp(ctrl); | 620 | changed = pcie_mask_bad_dllp(ctrl); |
754 | 621 | ||
755 | slot_cmd = POWER_OFF; | 622 | slot_cmd = POWER_OFF; |
756 | cmd_mask = PWR_CTRL; | 623 | cmd_mask = PCI_EXP_SLTCTL_PCC; |
757 | /* | 624 | /* |
758 | * If we get MRL or presence detect interrupts now, the isr | 625 | * If we get MRL or presence detect interrupts now, the isr |
759 | * will notice the sticky power-fault bit too and issue power | 626 | * will notice the sticky power-fault bit too and issue power |
@@ -762,10 +629,10 @@ static int hpc_power_off_slot(struct slot * slot) | |||
762 | * till the slot is powered on again. | 629 | * till the slot is powered on again. |
763 | */ | 630 | */ |
764 | if (!pciehp_poll_mode) { | 631 | if (!pciehp_poll_mode) { |
765 | slot_cmd &= ~(PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | | 632 | slot_cmd &= ~(PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | |
766 | PRSN_DETECT_ENABLE); | 633 | PCI_EXP_SLTCTL_PDCE); |
767 | cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | | 634 | cmd_mask |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | |
768 | PRSN_DETECT_ENABLE); | 635 | PCI_EXP_SLTCTL_PDCE); |
769 | } | 636 | } |
770 | 637 | ||
771 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 638 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
@@ -775,7 +642,7 @@ static int hpc_power_off_slot(struct slot * slot) | |||
775 | goto out; | 642 | goto out; |
776 | } | 643 | } |
777 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 644 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", |
778 | __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 645 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); |
779 | out: | 646 | out: |
780 | if (changed) | 647 | if (changed) |
781 | pcie_unmask_bad_dllp(ctrl); | 648 | pcie_unmask_bad_dllp(ctrl); |
@@ -796,19 +663,19 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
796 | */ | 663 | */ |
797 | intr_loc = 0; | 664 | intr_loc = 0; |
798 | do { | 665 | do { |
799 | if (pciehp_readw(ctrl, SLOTSTATUS, &detected)) { | 666 | if (pciehp_readw(ctrl, PCI_EXP_SLTSTA, &detected)) { |
800 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS\n", | 667 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS\n", |
801 | __func__); | 668 | __func__); |
802 | return IRQ_NONE; | 669 | return IRQ_NONE; |
803 | } | 670 | } |
804 | 671 | ||
805 | detected &= (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED | | 672 | detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | |
806 | MRL_SENS_CHANGED | PRSN_DETECT_CHANGED | | 673 | PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | |
807 | CMD_COMPLETED); | 674 | PCI_EXP_SLTSTA_CC); |
808 | intr_loc |= detected; | 675 | intr_loc |= detected; |
809 | if (!intr_loc) | 676 | if (!intr_loc) |
810 | return IRQ_NONE; | 677 | return IRQ_NONE; |
811 | if (detected && pciehp_writew(ctrl, SLOTSTATUS, detected)) { | 678 | if (detected && pciehp_writew(ctrl, PCI_EXP_SLTSTA, detected)) { |
812 | ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS\n", | 679 | ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS\n", |
813 | __func__); | 680 | __func__); |
814 | return IRQ_NONE; | 681 | return IRQ_NONE; |
@@ -818,31 +685,31 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
818 | ctrl_dbg(ctrl, "%s: intr_loc %x\n", __func__, intr_loc); | 685 | ctrl_dbg(ctrl, "%s: intr_loc %x\n", __func__, intr_loc); |
819 | 686 | ||
820 | /* Check Command Complete Interrupt Pending */ | 687 | /* Check Command Complete Interrupt Pending */ |
821 | if (intr_loc & CMD_COMPLETED) { | 688 | if (intr_loc & PCI_EXP_SLTSTA_CC) { |
822 | ctrl->cmd_busy = 0; | 689 | ctrl->cmd_busy = 0; |
823 | smp_mb(); | 690 | smp_mb(); |
824 | wake_up(&ctrl->queue); | 691 | wake_up(&ctrl->queue); |
825 | } | 692 | } |
826 | 693 | ||
827 | if (!(intr_loc & ~CMD_COMPLETED)) | 694 | if (!(intr_loc & ~PCI_EXP_SLTSTA_CC)) |
828 | return IRQ_HANDLED; | 695 | return IRQ_HANDLED; |
829 | 696 | ||
830 | p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); | 697 | p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); |
831 | 698 | ||
832 | /* Check MRL Sensor Changed */ | 699 | /* Check MRL Sensor Changed */ |
833 | if (intr_loc & MRL_SENS_CHANGED) | 700 | if (intr_loc & PCI_EXP_SLTSTA_MRLSC) |
834 | pciehp_handle_switch_change(p_slot); | 701 | pciehp_handle_switch_change(p_slot); |
835 | 702 | ||
836 | /* Check Attention Button Pressed */ | 703 | /* Check Attention Button Pressed */ |
837 | if (intr_loc & ATTN_BUTTN_PRESSED) | 704 | if (intr_loc & PCI_EXP_SLTSTA_ABP) |
838 | pciehp_handle_attention_button(p_slot); | 705 | pciehp_handle_attention_button(p_slot); |
839 | 706 | ||
840 | /* Check Presence Detect Changed */ | 707 | /* Check Presence Detect Changed */ |
841 | if (intr_loc & PRSN_DETECT_CHANGED) | 708 | if (intr_loc & PCI_EXP_SLTSTA_PDC) |
842 | pciehp_handle_presence_change(p_slot); | 709 | pciehp_handle_presence_change(p_slot); |
843 | 710 | ||
844 | /* Check Power Fault Detected */ | 711 | /* Check Power Fault Detected */ |
845 | if (intr_loc & PWR_FAULT_DETECTED) | 712 | if (intr_loc & PCI_EXP_SLTSTA_PFD) |
846 | pciehp_handle_power_fault(p_slot); | 713 | pciehp_handle_power_fault(p_slot); |
847 | 714 | ||
848 | return IRQ_HANDLED; | 715 | return IRQ_HANDLED; |
@@ -855,7 +722,7 @@ static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value) | |||
855 | u32 lnk_cap; | 722 | u32 lnk_cap; |
856 | int retval = 0; | 723 | int retval = 0; |
857 | 724 | ||
858 | retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap); | 725 | retval = pciehp_readl(ctrl, PCI_EXP_LNKCAP, &lnk_cap); |
859 | if (retval) { | 726 | if (retval) { |
860 | ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); | 727 | ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); |
861 | return retval; | 728 | return retval; |
@@ -884,13 +751,13 @@ static int hpc_get_max_lnk_width(struct slot *slot, | |||
884 | u32 lnk_cap; | 751 | u32 lnk_cap; |
885 | int retval = 0; | 752 | int retval = 0; |
886 | 753 | ||
887 | retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap); | 754 | retval = pciehp_readl(ctrl, PCI_EXP_LNKCAP, &lnk_cap); |
888 | if (retval) { | 755 | if (retval) { |
889 | ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); | 756 | ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); |
890 | return retval; | 757 | return retval; |
891 | } | 758 | } |
892 | 759 | ||
893 | switch ((lnk_cap & 0x03F0) >> 4){ | 760 | switch ((lnk_cap & PCI_EXP_LNKSTA_NLW) >> 4){ |
894 | case 0: | 761 | case 0: |
895 | lnk_wdth = PCIE_LNK_WIDTH_RESRV; | 762 | lnk_wdth = PCIE_LNK_WIDTH_RESRV; |
896 | break; | 763 | break; |
@@ -933,14 +800,14 @@ static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value) | |||
933 | int retval = 0; | 800 | int retval = 0; |
934 | u16 lnk_status; | 801 | u16 lnk_status; |
935 | 802 | ||
936 | retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status); | 803 | retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); |
937 | if (retval) { | 804 | if (retval) { |
938 | ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n", | 805 | ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n", |
939 | __func__); | 806 | __func__); |
940 | return retval; | 807 | return retval; |
941 | } | 808 | } |
942 | 809 | ||
943 | switch (lnk_status & 0x0F) { | 810 | switch (lnk_status & PCI_EXP_LNKSTA_CLS) { |
944 | case 1: | 811 | case 1: |
945 | lnk_speed = PCIE_2PT5GB; | 812 | lnk_speed = PCIE_2PT5GB; |
946 | break; | 813 | break; |
@@ -963,14 +830,14 @@ static int hpc_get_cur_lnk_width(struct slot *slot, | |||
963 | int retval = 0; | 830 | int retval = 0; |
964 | u16 lnk_status; | 831 | u16 lnk_status; |
965 | 832 | ||
966 | retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status); | 833 | retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); |
967 | if (retval) { | 834 | if (retval) { |
968 | ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n", | 835 | ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n", |
969 | __func__); | 836 | __func__); |
970 | return retval; | 837 | return retval; |
971 | } | 838 | } |
972 | 839 | ||
973 | switch ((lnk_status & 0x03F0) >> 4){ | 840 | switch ((lnk_status & PCI_EXP_LNKSTA_NLW) >> 4){ |
974 | case 0: | 841 | case 0: |
975 | lnk_wdth = PCIE_LNK_WIDTH_RESRV; | 842 | lnk_wdth = PCIE_LNK_WIDTH_RESRV; |
976 | break; | 843 | break; |
@@ -1036,18 +903,19 @@ int pcie_enable_notification(struct controller *ctrl) | |||
1036 | { | 903 | { |
1037 | u16 cmd, mask; | 904 | u16 cmd, mask; |
1038 | 905 | ||
1039 | cmd = PRSN_DETECT_ENABLE; | 906 | cmd = PCI_EXP_SLTCTL_PDCE; |
1040 | if (ATTN_BUTTN(ctrl)) | 907 | if (ATTN_BUTTN(ctrl)) |
1041 | cmd |= ATTN_BUTTN_ENABLE; | 908 | cmd |= PCI_EXP_SLTCTL_ABPE; |
1042 | if (POWER_CTRL(ctrl)) | 909 | if (POWER_CTRL(ctrl)) |
1043 | cmd |= PWR_FAULT_DETECT_ENABLE; | 910 | cmd |= PCI_EXP_SLTCTL_PFDE; |
1044 | if (MRL_SENS(ctrl)) | 911 | if (MRL_SENS(ctrl)) |
1045 | cmd |= MRL_DETECT_ENABLE; | 912 | cmd |= PCI_EXP_SLTCTL_MRLSCE; |
1046 | if (!pciehp_poll_mode) | 913 | if (!pciehp_poll_mode) |
1047 | cmd |= HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE; | 914 | cmd |= PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE; |
1048 | 915 | ||
1049 | mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | MRL_DETECT_ENABLE | | 916 | mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | |
1050 | PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE; | 917 | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | |
918 | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE); | ||
1051 | 919 | ||
1052 | if (pcie_write_cmd(ctrl, cmd, mask)) { | 920 | if (pcie_write_cmd(ctrl, cmd, mask)) { |
1053 | ctrl_err(ctrl, "Cannot enable software notification\n"); | 921 | ctrl_err(ctrl, "Cannot enable software notification\n"); |
@@ -1059,8 +927,9 @@ int pcie_enable_notification(struct controller *ctrl) | |||
1059 | static void pcie_disable_notification(struct controller *ctrl) | 927 | static void pcie_disable_notification(struct controller *ctrl) |
1060 | { | 928 | { |
1061 | u16 mask; | 929 | u16 mask; |
1062 | mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | MRL_DETECT_ENABLE | | 930 | mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | |
1063 | PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE; | 931 | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | |
932 | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE); | ||
1064 | if (pcie_write_cmd(ctrl, 0, mask)) | 933 | if (pcie_write_cmd(ctrl, 0, mask)) |
1065 | ctrl_warn(ctrl, "Cannot disable software notification\n"); | 934 | ctrl_warn(ctrl, "Cannot disable software notification\n"); |
1066 | } | 935 | } |
@@ -1157,9 +1026,9 @@ static inline void dbg_ctrl(struct controller *ctrl) | |||
1157 | EMI(ctrl) ? "yes" : "no"); | 1026 | EMI(ctrl) ? "yes" : "no"); |
1158 | ctrl_info(ctrl, " Command Completed : %3s\n", | 1027 | ctrl_info(ctrl, " Command Completed : %3s\n", |
1159 | NO_CMD_CMPL(ctrl) ? "no" : "yes"); | 1028 | NO_CMD_CMPL(ctrl) ? "no" : "yes"); |
1160 | pciehp_readw(ctrl, SLOTSTATUS, ®16); | 1029 | pciehp_readw(ctrl, PCI_EXP_SLTSTA, ®16); |
1161 | ctrl_info(ctrl, "Slot Status : 0x%04x\n", reg16); | 1030 | ctrl_info(ctrl, "Slot Status : 0x%04x\n", reg16); |
1162 | pciehp_readw(ctrl, SLOTCTRL, ®16); | 1031 | pciehp_readw(ctrl, PCI_EXP_SLTCTL, ®16); |
1163 | ctrl_info(ctrl, "Slot Control : 0x%04x\n", reg16); | 1032 | ctrl_info(ctrl, "Slot Control : 0x%04x\n", reg16); |
1164 | } | 1033 | } |
1165 | 1034 | ||
@@ -1183,7 +1052,7 @@ struct controller *pcie_init(struct pcie_device *dev) | |||
1183 | ctrl_err(ctrl, "Cannot find PCI Express capability\n"); | 1052 | ctrl_err(ctrl, "Cannot find PCI Express capability\n"); |
1184 | goto abort_ctrl; | 1053 | goto abort_ctrl; |
1185 | } | 1054 | } |
1186 | if (pciehp_readl(ctrl, SLOTCAP, &slot_cap)) { | 1055 | if (pciehp_readl(ctrl, PCI_EXP_SLTCAP, &slot_cap)) { |
1187 | ctrl_err(ctrl, "Cannot read SLOTCAP register\n"); | 1056 | ctrl_err(ctrl, "Cannot read SLOTCAP register\n"); |
1188 | goto abort_ctrl; | 1057 | goto abort_ctrl; |
1189 | } | 1058 | } |
@@ -1208,17 +1077,17 @@ struct controller *pcie_init(struct pcie_device *dev) | |||
1208 | ctrl->no_cmd_complete = 1; | 1077 | ctrl->no_cmd_complete = 1; |
1209 | 1078 | ||
1210 | /* Check if Data Link Layer Link Active Reporting is implemented */ | 1079 | /* Check if Data Link Layer Link Active Reporting is implemented */ |
1211 | if (pciehp_readl(ctrl, LNKCAP, &link_cap)) { | 1080 | if (pciehp_readl(ctrl, PCI_EXP_LNKCAP, &link_cap)) { |
1212 | ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); | 1081 | ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); |
1213 | goto abort_ctrl; | 1082 | goto abort_ctrl; |
1214 | } | 1083 | } |
1215 | if (link_cap & LINK_ACTIVE_REPORTING) { | 1084 | if (link_cap & PCI_EXP_LNKCAP_DLLLARC) { |
1216 | ctrl_dbg(ctrl, "Link Active Reporting supported\n"); | 1085 | ctrl_dbg(ctrl, "Link Active Reporting supported\n"); |
1217 | ctrl->link_active_reporting = 1; | 1086 | ctrl->link_active_reporting = 1; |
1218 | } | 1087 | } |
1219 | 1088 | ||
1220 | /* Clear all remaining event bits in Slot Status register */ | 1089 | /* Clear all remaining event bits in Slot Status register */ |
1221 | if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) | 1090 | if (pciehp_writew(ctrl, PCI_EXP_SLTSTA, 0x1f)) |
1222 | goto abort_ctrl; | 1091 | goto abort_ctrl; |
1223 | 1092 | ||
1224 | /* Disable sotfware notification */ | 1093 | /* Disable sotfware notification */ |
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 9c2a22fed18b..4e3e0382c16e 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c | |||
@@ -14,6 +14,9 @@ | |||
14 | * as published by the Free Software Foundation; either version | 14 | * as published by the Free Software Foundation; either version |
15 | * 2 of the License, or (at your option) any later version. | 15 | * 2 of the License, or (at your option) any later version. |
16 | */ | 16 | */ |
17 | |||
18 | #undef DEBUG | ||
19 | |||
17 | #include <linux/init.h> | 20 | #include <linux/init.h> |
18 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
19 | #include <linux/string.h> | 22 | #include <linux/string.h> |
@@ -151,20 +154,20 @@ static void dlpar_pci_add_bus(struct device_node *dn) | |||
151 | return; | 154 | return; |
152 | } | 155 | } |
153 | 156 | ||
157 | /* Scan below the new bridge */ | ||
154 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | 158 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || |
155 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) | 159 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) |
156 | of_scan_pci_bridge(dn, dev); | 160 | of_scan_pci_bridge(dn, dev); |
157 | 161 | ||
158 | pcibios_fixup_new_pci_devices(dev->subordinate); | ||
159 | |||
160 | /* Claim new bus resources */ | ||
161 | pcibios_claim_one_bus(dev->bus); | ||
162 | |||
163 | /* Map IO space for child bus, which may or may not succeed */ | 162 | /* Map IO space for child bus, which may or may not succeed */ |
164 | pcibios_map_io_space(dev->subordinate); | 163 | pcibios_map_io_space(dev->subordinate); |
165 | 164 | ||
166 | /* Add new devices to global lists. Register in proc, sysfs. */ | 165 | /* Finish adding it : resource allocation, adding devices, etc... |
167 | pci_bus_add_devices(phb->bus); | 166 | * Note that we need to perform the finish pass on the -parent- |
167 | * bus of the EADS bridge so the bridge device itself gets | ||
168 | * properly added | ||
169 | */ | ||
170 | pcibios_finish_adding_to_bus(phb->bus); | ||
168 | } | 171 | } |
169 | 172 | ||
170 | static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) | 173 | static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) |
@@ -203,27 +206,6 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn) | |||
203 | return 0; | 206 | return 0; |
204 | } | 207 | } |
205 | 208 | ||
206 | static int dlpar_remove_root_bus(struct pci_controller *phb) | ||
207 | { | ||
208 | struct pci_bus *phb_bus; | ||
209 | int rc; | ||
210 | |||
211 | phb_bus = phb->bus; | ||
212 | if (!(list_empty(&phb_bus->children) && | ||
213 | list_empty(&phb_bus->devices))) { | ||
214 | return -EBUSY; | ||
215 | } | ||
216 | |||
217 | rc = pcibios_remove_root_bus(phb); | ||
218 | if (rc) | ||
219 | return -EIO; | ||
220 | |||
221 | device_unregister(phb_bus->bridge); | ||
222 | pci_remove_bus(phb_bus); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int dlpar_remove_phb(char *drc_name, struct device_node *dn) | 209 | static int dlpar_remove_phb(char *drc_name, struct device_node *dn) |
228 | { | 210 | { |
229 | struct slot *slot; | 211 | struct slot *slot; |
@@ -235,18 +217,15 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn) | |||
235 | 217 | ||
236 | /* If pci slot is hotplugable, use hotplug to remove it */ | 218 | /* If pci slot is hotplugable, use hotplug to remove it */ |
237 | slot = find_php_slot(dn); | 219 | slot = find_php_slot(dn); |
238 | if (slot) { | 220 | if (slot && rpaphp_deregister_slot(slot)) { |
239 | if (rpaphp_deregister_slot(slot)) { | 221 | printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", |
240 | printk(KERN_ERR | 222 | __func__, drc_name); |
241 | "%s: unable to remove hotplug slot %s\n", | 223 | return -EIO; |
242 | __func__, drc_name); | ||
243 | return -EIO; | ||
244 | } | ||
245 | } | 224 | } |
246 | 225 | ||
247 | pdn = dn->data; | 226 | pdn = dn->data; |
248 | BUG_ON(!pdn || !pdn->phb); | 227 | BUG_ON(!pdn || !pdn->phb); |
249 | rc = dlpar_remove_root_bus(pdn->phb); | 228 | rc = remove_phb_dynamic(pdn->phb); |
250 | if (rc < 0) | 229 | if (rc < 0) |
251 | return rc; | 230 | return rc; |
252 | 231 | ||
@@ -378,26 +357,38 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
378 | if (!bus) | 357 | if (!bus) |
379 | return -EINVAL; | 358 | return -EINVAL; |
380 | 359 | ||
381 | /* If pci slot is hotplugable, use hotplug to remove it */ | 360 | pr_debug("PCI: Removing PCI slot below EADS bridge %s\n", |
361 | bus->self ? pci_name(bus->self) : "<!PHB!>"); | ||
362 | |||
382 | slot = find_php_slot(dn); | 363 | slot = find_php_slot(dn); |
383 | if (slot) { | 364 | if (slot) { |
365 | pr_debug("PCI: Removing hotplug slot for %04x:%02x...\n", | ||
366 | pci_domain_nr(bus), bus->number); | ||
367 | |||
384 | if (rpaphp_deregister_slot(slot)) { | 368 | if (rpaphp_deregister_slot(slot)) { |
385 | printk(KERN_ERR | 369 | printk(KERN_ERR |
386 | "%s: unable to remove hotplug slot %s\n", | 370 | "%s: unable to remove hotplug slot %s\n", |
387 | __func__, drc_name); | 371 | __func__, drc_name); |
388 | return -EIO; | 372 | return -EIO; |
389 | } | 373 | } |
390 | } else | 374 | } |
391 | pcibios_remove_pci_devices(bus); | 375 | |
376 | /* Remove all devices below slot */ | ||
377 | pcibios_remove_pci_devices(bus); | ||
392 | 378 | ||
379 | /* Unmap PCI IO space */ | ||
393 | if (pcibios_unmap_io_space(bus)) { | 380 | if (pcibios_unmap_io_space(bus)) { |
394 | printk(KERN_ERR "%s: failed to unmap bus range\n", | 381 | printk(KERN_ERR "%s: failed to unmap bus range\n", |
395 | __func__); | 382 | __func__); |
396 | return -ERANGE; | 383 | return -ERANGE; |
397 | } | 384 | } |
398 | 385 | ||
386 | /* Remove the EADS bridge device itself */ | ||
399 | BUG_ON(!bus->self); | 387 | BUG_ON(!bus->self); |
388 | pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self)); | ||
389 | eeh_remove_bus_device(bus->self); | ||
400 | pci_remove_bus_device(bus->self); | 390 | pci_remove_bus_device(bus->self); |
391 | |||
401 | return 0; | 392 | return 0; |
402 | } | 393 | } |
403 | 394 | ||