aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/Makefile6
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c2
-rw-r--r--drivers/pci/hotplug/fakephp.c42
-rw-r--r--drivers/pci/hotplug/pciehp.h2
-rw-r--r--drivers/pci/hotplug/pciehp_core.c11
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c15
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 @@
5obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o 5obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
6obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o 6obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
7obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o 7obj-$(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
12obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o
8obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o 13obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
9obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o 14obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o
10obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o 15obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o
11obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o 16obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o
12obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o
13obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o 17obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o
14obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o 18obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o
15obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o 19obj-$(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 */
198static void pci_rescan_slot(struct pci_dev *temp) 198static 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);
170extern int pciehp_unconfigure_device(struct slot *p_slot); 171extern int pciehp_unconfigure_device(struct slot *p_slot);
171extern void pciehp_queue_pushbutton_work(struct work_struct *work); 172extern void pciehp_queue_pushbutton_work(struct work_struct *work);
172struct controller *pcie_init(struct pcie_device *dev); 173struct controller *pcie_init(struct pcie_device *dev);
174int pcie_init_notification(struct controller *ctrl);
173int pciehp_enable_slot(struct slot *p_slot); 175int pciehp_enable_slot(struct slot *p_slot);
174int pciehp_disable_slot(struct slot *p_slot); 176int pciehp_disable_slot(struct slot *p_slot);
175int pcie_enable_notification(struct controller *ctrl); 177int 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
937static int pcie_init_notification(struct controller *ctrl) 937int 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
948static void pcie_shutdown_notification(struct controller *ctrl) 949static 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
954static int pcie_init_slot(struct controller *ctrl) 958static 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
1118abort_slot:
1119 pcie_cleanup_slot(ctrl);
1120abort_ctrl: 1119abort_ctrl:
1121 kfree(ctrl); 1120 kfree(ctrl);
1122abort: 1121abort: