diff options
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r-- | drivers/pci/hotplug/Makefile | 6 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/fakephp.c | 42 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 11 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 15 |
6 files changed, 52 insertions, 26 deletions
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index e31fb91652ce..2aa117c8cd87 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile | |||
@@ -5,11 +5,15 @@ | |||
5 | obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o | 5 | obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o |
6 | obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o | 6 | obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o |
7 | obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o | 7 | obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o |
8 | |||
9 | # pciehp should be linked before acpiphp in order to allow the native driver | ||
10 | # to attempt to bind first. We can then fall back to generic support. | ||
11 | |||
12 | obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o | ||
8 | obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o | 13 | obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o |
9 | obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o | 14 | obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o |
10 | obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o | 15 | obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o |
11 | obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o | 16 | obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o |
12 | obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o | ||
13 | obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o | 17 | obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o |
14 | obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o | 18 | obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o |
15 | obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o | 19 | obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index f09b1010d477..803d9ddd6e75 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -266,6 +266,8 @@ static int detect_ejectable_slots(struct pci_bus *pbus) | |||
266 | int found = acpi_pci_detect_ejectable(pbus); | 266 | int found = acpi_pci_detect_ejectable(pbus); |
267 | if (!found) { | 267 | if (!found) { |
268 | acpi_handle bridge_handle = acpi_pci_get_bridge_handle(pbus); | 268 | acpi_handle bridge_handle = acpi_pci_get_bridge_handle(pbus); |
269 | if (!bridge_handle) | ||
270 | return 0; | ||
269 | acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1, | 271 | acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1, |
270 | is_pci_dock_device, (void *)&found, NULL); | 272 | is_pci_dock_device, (void *)&found, NULL); |
271 | } | 273 | } |
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index b0e7de9e536d..d8649e127298 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c | |||
@@ -195,13 +195,13 @@ static void remove_slot_worker(struct work_struct *work) | |||
195 | * Tries hard not to re-enable already existing devices; | 195 | * Tries hard not to re-enable already existing devices; |
196 | * also handles scanning of subfunctions. | 196 | * also handles scanning of subfunctions. |
197 | */ | 197 | */ |
198 | static void pci_rescan_slot(struct pci_dev *temp) | 198 | static int pci_rescan_slot(struct pci_dev *temp) |
199 | { | 199 | { |
200 | struct pci_bus *bus = temp->bus; | 200 | struct pci_bus *bus = temp->bus; |
201 | struct pci_dev *dev; | 201 | struct pci_dev *dev; |
202 | int func; | 202 | int func; |
203 | int retval; | ||
204 | u8 hdr_type; | 203 | u8 hdr_type; |
204 | int count = 0; | ||
205 | 205 | ||
206 | if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { | 206 | if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { |
207 | temp->hdr_type = hdr_type & 0x7f; | 207 | temp->hdr_type = hdr_type & 0x7f; |
@@ -213,17 +213,12 @@ static void pci_rescan_slot(struct pci_dev *temp) | |||
213 | dbg("New device on %s function %x:%x\n", | 213 | dbg("New device on %s function %x:%x\n", |
214 | bus->name, temp->devfn >> 3, | 214 | bus->name, temp->devfn >> 3, |
215 | temp->devfn & 7); | 215 | temp->devfn & 7); |
216 | retval = pci_bus_add_device(dev); | 216 | count++; |
217 | if (retval) | ||
218 | dev_err(&dev->dev, "error adding " | ||
219 | "device, continuing.\n"); | ||
220 | else | ||
221 | add_slot(dev); | ||
222 | } | 217 | } |
223 | } | 218 | } |
224 | /* multifunction device? */ | 219 | /* multifunction device? */ |
225 | if (!(hdr_type & 0x80)) | 220 | if (!(hdr_type & 0x80)) |
226 | return; | 221 | return count; |
227 | 222 | ||
228 | /* continue scanning for other functions */ | 223 | /* continue scanning for other functions */ |
229 | for (func = 1, temp->devfn++; func < 8; func++, temp->devfn++) { | 224 | for (func = 1, temp->devfn++; func < 8; func++, temp->devfn++) { |
@@ -239,16 +234,13 @@ static void pci_rescan_slot(struct pci_dev *temp) | |||
239 | dbg("New device on %s function %x:%x\n", | 234 | dbg("New device on %s function %x:%x\n", |
240 | bus->name, temp->devfn >> 3, | 235 | bus->name, temp->devfn >> 3, |
241 | temp->devfn & 7); | 236 | temp->devfn & 7); |
242 | retval = pci_bus_add_device(dev); | 237 | count++; |
243 | if (retval) | ||
244 | dev_err(&dev->dev, "error adding " | ||
245 | "device, continuing.\n"); | ||
246 | else | ||
247 | add_slot(dev); | ||
248 | } | 238 | } |
249 | } | 239 | } |
250 | } | 240 | } |
251 | } | 241 | } |
242 | |||
243 | return count; | ||
252 | } | 244 | } |
253 | 245 | ||
254 | 246 | ||
@@ -262,6 +254,8 @@ static void pci_rescan_bus(const struct pci_bus *bus) | |||
262 | { | 254 | { |
263 | unsigned int devfn; | 255 | unsigned int devfn; |
264 | struct pci_dev *dev; | 256 | struct pci_dev *dev; |
257 | int retval; | ||
258 | int found = 0; | ||
265 | dev = alloc_pci_dev(); | 259 | dev = alloc_pci_dev(); |
266 | if (!dev) | 260 | if (!dev) |
267 | return; | 261 | return; |
@@ -270,7 +264,23 @@ static void pci_rescan_bus(const struct pci_bus *bus) | |||
270 | dev->sysdata = bus->sysdata; | 264 | dev->sysdata = bus->sysdata; |
271 | for (devfn = 0; devfn < 0x100; devfn += 8) { | 265 | for (devfn = 0; devfn < 0x100; devfn += 8) { |
272 | dev->devfn = devfn; | 266 | dev->devfn = devfn; |
273 | pci_rescan_slot(dev); | 267 | found += pci_rescan_slot(dev); |
268 | } | ||
269 | |||
270 | if (found) { | ||
271 | pci_bus_assign_resources(bus); | ||
272 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
273 | /* Skip already-added devices */ | ||
274 | if (dev->is_added) | ||
275 | continue; | ||
276 | retval = pci_bus_add_device(dev); | ||
277 | if (retval) | ||
278 | dev_err(&dev->dev, | ||
279 | "Error adding device, continuing\n"); | ||
280 | else | ||
281 | add_slot(dev); | ||
282 | } | ||
283 | pci_bus_add_devices(bus); | ||
274 | } | 284 | } |
275 | kfree(dev); | 285 | kfree(dev); |
276 | } | 286 | } |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index db85284ffb62..39ae37589fda 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -111,6 +111,7 @@ struct controller { | |||
111 | int cmd_busy; | 111 | int cmd_busy; |
112 | unsigned int no_cmd_complete:1; | 112 | unsigned int no_cmd_complete:1; |
113 | unsigned int link_active_reporting:1; | 113 | unsigned int link_active_reporting:1; |
114 | unsigned int notification_enabled:1; | ||
114 | }; | 115 | }; |
115 | 116 | ||
116 | #define INT_BUTTON_IGNORE 0 | 117 | #define INT_BUTTON_IGNORE 0 |
@@ -170,6 +171,7 @@ extern int pciehp_configure_device(struct slot *p_slot); | |||
170 | extern int pciehp_unconfigure_device(struct slot *p_slot); | 171 | extern int pciehp_unconfigure_device(struct slot *p_slot); |
171 | extern void pciehp_queue_pushbutton_work(struct work_struct *work); | 172 | extern void pciehp_queue_pushbutton_work(struct work_struct *work); |
172 | struct controller *pcie_init(struct pcie_device *dev); | 173 | struct controller *pcie_init(struct pcie_device *dev); |
174 | int pcie_init_notification(struct controller *ctrl); | ||
173 | int pciehp_enable_slot(struct slot *p_slot); | 175 | int pciehp_enable_slot(struct slot *p_slot); |
174 | int pciehp_disable_slot(struct slot *p_slot); | 176 | int pciehp_disable_slot(struct slot *p_slot); |
175 | int pcie_enable_notification(struct controller *ctrl); | 177 | int pcie_enable_notification(struct controller *ctrl); |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 5482d4ed8256..681e3912b821 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -126,8 +126,10 @@ static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status) | |||
126 | mutex_lock(&slot->ctrl->crit_sect); | 126 | mutex_lock(&slot->ctrl->crit_sect); |
127 | 127 | ||
128 | /* has it been >1 sec since our last toggle? */ | 128 | /* has it been >1 sec since our last toggle? */ |
129 | if ((get_seconds() - slot->last_emi_toggle) < 1) | 129 | if ((get_seconds() - slot->last_emi_toggle) < 1) { |
130 | mutex_unlock(&slot->ctrl->crit_sect); | ||
130 | return -EINVAL; | 131 | return -EINVAL; |
132 | } | ||
131 | 133 | ||
132 | /* see what our current state is */ | 134 | /* see what our current state is */ |
133 | retval = get_lock_status(hotplug_slot, &value); | 135 | retval = get_lock_status(hotplug_slot, &value); |
@@ -432,6 +434,13 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
432 | goto err_out_release_ctlr; | 434 | goto err_out_release_ctlr; |
433 | } | 435 | } |
434 | 436 | ||
437 | /* Enable events after we have setup the data structures */ | ||
438 | rc = pcie_init_notification(ctrl); | ||
439 | if (rc) { | ||
440 | ctrl_err(ctrl, "Notification initialization failed\n"); | ||
441 | goto err_out_release_ctlr; | ||
442 | } | ||
443 | |||
435 | /* Check if slot is occupied */ | 444 | /* Check if slot is occupied */ |
436 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); | 445 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); |
437 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); | 446 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 71a8012886b0..7a16c6897bb9 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -934,7 +934,7 @@ static void pcie_disable_notification(struct controller *ctrl) | |||
934 | ctrl_warn(ctrl, "Cannot disable software notification\n"); | 934 | ctrl_warn(ctrl, "Cannot disable software notification\n"); |
935 | } | 935 | } |
936 | 936 | ||
937 | static int pcie_init_notification(struct controller *ctrl) | 937 | int pcie_init_notification(struct controller *ctrl) |
938 | { | 938 | { |
939 | if (pciehp_request_irq(ctrl)) | 939 | if (pciehp_request_irq(ctrl)) |
940 | return -1; | 940 | return -1; |
@@ -942,13 +942,17 @@ static int pcie_init_notification(struct controller *ctrl) | |||
942 | pciehp_free_irq(ctrl); | 942 | pciehp_free_irq(ctrl); |
943 | return -1; | 943 | return -1; |
944 | } | 944 | } |
945 | ctrl->notification_enabled = 1; | ||
945 | return 0; | 946 | return 0; |
946 | } | 947 | } |
947 | 948 | ||
948 | static void pcie_shutdown_notification(struct controller *ctrl) | 949 | static void pcie_shutdown_notification(struct controller *ctrl) |
949 | { | 950 | { |
950 | pcie_disable_notification(ctrl); | 951 | if (ctrl->notification_enabled) { |
951 | pciehp_free_irq(ctrl); | 952 | pcie_disable_notification(ctrl); |
953 | pciehp_free_irq(ctrl); | ||
954 | ctrl->notification_enabled = 0; | ||
955 | } | ||
952 | } | 956 | } |
953 | 957 | ||
954 | static int pcie_init_slot(struct controller *ctrl) | 958 | static int pcie_init_slot(struct controller *ctrl) |
@@ -1110,13 +1114,8 @@ struct controller *pcie_init(struct pcie_device *dev) | |||
1110 | if (pcie_init_slot(ctrl)) | 1114 | if (pcie_init_slot(ctrl)) |
1111 | goto abort_ctrl; | 1115 | goto abort_ctrl; |
1112 | 1116 | ||
1113 | if (pcie_init_notification(ctrl)) | ||
1114 | goto abort_slot; | ||
1115 | |||
1116 | return ctrl; | 1117 | return ctrl; |
1117 | 1118 | ||
1118 | abort_slot: | ||
1119 | pcie_cleanup_slot(ctrl); | ||
1120 | abort_ctrl: | 1119 | abort_ctrl: |
1121 | kfree(ctrl); | 1120 | kfree(ctrl); |
1122 | abort: | 1121 | abort: |