aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp_core.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-07-16 20:25:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-16 20:25:46 -0400
commitdc7c65db2845a8d17432d89252c4227a9a7cb15f (patch)
tree79030b0aaaafc04bc4303c21495134e744afc058 /drivers/pci/hotplug/pciehp_core.c
parent8a0ca91e1db5de5eb5b18cfa919d52ff8be375af (diff)
parent58b6e5538460be358fdf1286d9a2fbcfcc2cfaba (diff)
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (72 commits) Revert "x86/PCI: ACPI based PCI gap calculation" PCI: remove unnecessary volatile in PCIe hotplug struct controller x86/PCI: ACPI based PCI gap calculation PCI: include linux/pm_wakeup.h for device_set_wakeup_capable PCI PM: Fix pci_prepare_to_sleep x86/PCI: Fix PCI config space for domains > 0 Fix acpi_pm_device_sleep_wake() by providing a stub for CONFIG_PM_SLEEP=n PCI: Simplify PCI device PM code PCI PM: Introduce pci_prepare_to_sleep and pci_back_from_sleep PCI ACPI: Rework PCI handling of wake-up ACPI: Introduce new device wakeup flag 'prepared' ACPI: Introduce acpi_device_sleep_wake function PCI: rework pci_set_power_state function to call platform first PCI: Introduce platform_pci_power_manageable function ACPI: Introduce acpi_bus_power_manageable function PCI: make pci_name use dev_name PCI: handle pci_name() being const PCI: add stub for pci_set_consistent_dma_mask() PCI: remove unused arch pcibios_update_resource() functions PCI: fix pci_setup_device()'s sprinting into a const buffer ... Fixed up conflicts in various files (arch/x86/kernel/setup_64.c, arch/x86/pci/irq.c, arch/x86/pci/pci.h, drivers/acpi/sleep/main.c, drivers/pci/pci.c, drivers/pci/pci.h, include/acpi/acpi_bus.h) from x86 and ACPI updates manually.
Diffstat (limited to 'drivers/pci/hotplug/pciehp_core.c')
-rw-r--r--drivers/pci/hotplug/pciehp_core.c127
1 files changed, 33 insertions, 94 deletions
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 48a2ed378914..3677495c4f91 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -72,7 +72,6 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);
72static int get_attention_status (struct hotplug_slot *slot, u8 *value); 72static int get_attention_status (struct hotplug_slot *slot, u8 *value);
73static int get_latch_status (struct hotplug_slot *slot, u8 *value); 73static int get_latch_status (struct hotplug_slot *slot, u8 *value);
74static int get_adapter_status (struct hotplug_slot *slot, u8 *value); 74static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
75static int get_address (struct hotplug_slot *slot, u32 *value);
76static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); 75static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
77static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); 76static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
78 77
@@ -85,7 +84,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
85 .get_attention_status = get_attention_status, 84 .get_attention_status = get_attention_status,
86 .get_latch_status = get_latch_status, 85 .get_latch_status = get_latch_status,
87 .get_adapter_status = get_adapter_status, 86 .get_adapter_status = get_adapter_status,
88 .get_address = get_address,
89 .get_max_bus_speed = get_max_bus_speed, 87 .get_max_bus_speed = get_max_bus_speed,
90 .get_cur_bus_speed = get_cur_bus_speed, 88 .get_cur_bus_speed = get_cur_bus_speed,
91}; 89};
@@ -185,23 +183,10 @@ static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
185 */ 183 */
186static void release_slot(struct hotplug_slot *hotplug_slot) 184static void release_slot(struct hotplug_slot *hotplug_slot)
187{ 185{
188 struct slot *slot = hotplug_slot->private;
189
190 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 186 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
191 187
192 kfree(slot->hotplug_slot->info); 188 kfree(hotplug_slot->info);
193 kfree(slot->hotplug_slot); 189 kfree(hotplug_slot);
194 kfree(slot);
195}
196
197static void make_slot_name(struct slot *slot)
198{
199 if (pciehp_slot_with_bus)
200 snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
201 slot->bus, slot->number);
202 else
203 snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
204 slot->number);
205} 190}
206 191
207static int init_slots(struct controller *ctrl) 192static int init_slots(struct controller *ctrl)
@@ -210,49 +195,34 @@ static int init_slots(struct controller *ctrl)
210 struct hotplug_slot *hotplug_slot; 195 struct hotplug_slot *hotplug_slot;
211 struct hotplug_slot_info *info; 196 struct hotplug_slot_info *info;
212 int retval = -ENOMEM; 197 int retval = -ENOMEM;
213 int i;
214
215 for (i = 0; i < ctrl->num_slots; i++) {
216 slot = kzalloc(sizeof(*slot), GFP_KERNEL);
217 if (!slot)
218 goto error;
219 198
199 list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
220 hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); 200 hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
221 if (!hotplug_slot) 201 if (!hotplug_slot)
222 goto error_slot; 202 goto error;
223 slot->hotplug_slot = hotplug_slot;
224 203
225 info = kzalloc(sizeof(*info), GFP_KERNEL); 204 info = kzalloc(sizeof(*info), GFP_KERNEL);
226 if (!info) 205 if (!info)
227 goto error_hpslot; 206 goto error_hpslot;
228 hotplug_slot->info = info;
229
230 hotplug_slot->name = slot->name;
231
232 slot->hp_slot = i;
233 slot->ctrl = ctrl;
234 slot->bus = ctrl->pci_dev->subordinate->number;
235 slot->device = ctrl->slot_device_offset + i;
236 slot->hpc_ops = ctrl->hpc_ops;
237 slot->number = ctrl->first_slot;
238 mutex_init(&slot->lock);
239 INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
240 207
241 /* register this slot with the hotplug pci core */ 208 /* register this slot with the hotplug pci core */
209 hotplug_slot->info = info;
210 hotplug_slot->name = slot->name;
242 hotplug_slot->private = slot; 211 hotplug_slot->private = slot;
243 hotplug_slot->release = &release_slot; 212 hotplug_slot->release = &release_slot;
244 make_slot_name(slot);
245 hotplug_slot->ops = &pciehp_hotplug_slot_ops; 213 hotplug_slot->ops = &pciehp_hotplug_slot_ops;
246
247 get_power_status(hotplug_slot, &info->power_status); 214 get_power_status(hotplug_slot, &info->power_status);
248 get_attention_status(hotplug_slot, &info->attention_status); 215 get_attention_status(hotplug_slot, &info->attention_status);
249 get_latch_status(hotplug_slot, &info->latch_status); 216 get_latch_status(hotplug_slot, &info->latch_status);
250 get_adapter_status(hotplug_slot, &info->adapter_status); 217 get_adapter_status(hotplug_slot, &info->adapter_status);
218 slot->hotplug_slot = hotplug_slot;
251 219
252 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " 220 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
253 "slot_device_offset=%x\n", slot->bus, slot->device, 221 "slot_device_offset=%x\n", slot->bus, slot->device,
254 slot->hp_slot, slot->number, ctrl->slot_device_offset); 222 slot->hp_slot, slot->number, ctrl->slot_device_offset);
255 retval = pci_hp_register(hotplug_slot); 223 retval = pci_hp_register(hotplug_slot,
224 ctrl->pci_dev->subordinate,
225 slot->device);
256 if (retval) { 226 if (retval) {
257 err("pci_hp_register failed with error %d\n", retval); 227 err("pci_hp_register failed with error %d\n", retval);
258 if (retval == -EEXIST) 228 if (retval == -EEXIST)
@@ -263,7 +233,7 @@ static int init_slots(struct controller *ctrl)
263 } 233 }
264 /* create additional sysfs entries */ 234 /* create additional sysfs entries */
265 if (EMI(ctrl)) { 235 if (EMI(ctrl)) {
266 retval = sysfs_create_file(&hotplug_slot->kobj, 236 retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj,
267 &hotplug_slot_attr_lock.attr); 237 &hotplug_slot_attr_lock.attr);
268 if (retval) { 238 if (retval) {
269 pci_hp_deregister(hotplug_slot); 239 pci_hp_deregister(hotplug_slot);
@@ -271,8 +241,6 @@ static int init_slots(struct controller *ctrl)
271 goto error_info; 241 goto error_info;
272 } 242 }
273 } 243 }
274
275 list_add(&slot->slot_list, &ctrl->slot_list);
276 } 244 }
277 245
278 return 0; 246 return 0;
@@ -280,27 +248,18 @@ error_info:
280 kfree(info); 248 kfree(info);
281error_hpslot: 249error_hpslot:
282 kfree(hotplug_slot); 250 kfree(hotplug_slot);
283error_slot:
284 kfree(slot);
285error: 251error:
286 return retval; 252 return retval;
287} 253}
288 254
289static void cleanup_slots(struct controller *ctrl) 255static void cleanup_slots(struct controller *ctrl)
290{ 256{
291 struct list_head *tmp;
292 struct list_head *next;
293 struct slot *slot; 257 struct slot *slot;
294 258
295 list_for_each_safe(tmp, next, &ctrl->slot_list) { 259 list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
296 slot = list_entry(tmp, struct slot, slot_list);
297 list_del(&slot->slot_list);
298 if (EMI(ctrl)) 260 if (EMI(ctrl))
299 sysfs_remove_file(&slot->hotplug_slot->kobj, 261 sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
300 &hotplug_slot_attr_lock.attr); 262 &hotplug_slot_attr_lock.attr);
301 cancel_delayed_work(&slot->work);
302 flush_scheduled_work();
303 flush_workqueue(pciehp_wq);
304 pci_hp_deregister(slot->hotplug_slot); 263 pci_hp_deregister(slot->hotplug_slot);
305 } 264 }
306} 265}
@@ -398,19 +357,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
398 return 0; 357 return 0;
399} 358}
400 359
401static int get_address(struct hotplug_slot *hotplug_slot, u32 *value) 360static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
402{ 361 enum pci_bus_speed *value)
403 struct slot *slot = hotplug_slot->private;
404 struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
405
406 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
407
408 *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
409
410 return 0;
411}
412
413static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
414{ 362{
415 struct slot *slot = hotplug_slot->private; 363 struct slot *slot = hotplug_slot->private;
416 int retval; 364 int retval;
@@ -444,34 +392,30 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
444 struct controller *ctrl; 392 struct controller *ctrl;
445 struct slot *t_slot; 393 struct slot *t_slot;
446 u8 value; 394 u8 value;
447 struct pci_dev *pdev; 395 struct pci_dev *pdev = dev->port;
448 396
449 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); 397 if (pciehp_force)
450 if (!ctrl) { 398 dbg("Bypassing BIOS check for pciehp use on %s\n",
451 err("%s : out of memory\n", __func__); 399 pci_name(pdev));
400 else if (pciehp_get_hp_hw_control_from_firmware(pdev))
452 goto err_out_none; 401 goto err_out_none;
453 }
454 INIT_LIST_HEAD(&ctrl->slot_list);
455
456 pdev = dev->port;
457 ctrl->pci_dev = pdev;
458 402
459 rc = pcie_init(ctrl, dev); 403 ctrl = pcie_init(dev);
460 if (rc) { 404 if (!ctrl) {
461 dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); 405 dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
462 goto err_out_free_ctrl; 406 goto err_out_none;
463 } 407 }
464 408 set_service_data(dev, ctrl);
465 pci_set_drvdata(pdev, ctrl);
466
467 dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
468 __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
469 PCI_FUNC(pdev->devfn), pdev->irq);
470 409
471 /* Setup the slot information structures */ 410 /* Setup the slot information structures */
472 rc = init_slots(ctrl); 411 rc = init_slots(ctrl);
473 if (rc) { 412 if (rc) {
474 err("%s: slot initialization failed\n", PCIE_MODULE_NAME); 413 if (rc == -EBUSY)
414 warn("%s: slot already registered by another "
415 "hotplug driver\n", PCIE_MODULE_NAME);
416 else
417 err("%s: slot initialization failed\n",
418 PCIE_MODULE_NAME);
475 goto err_out_release_ctlr; 419 goto err_out_release_ctlr;
476 } 420 }
477 421
@@ -495,20 +439,16 @@ err_out_free_ctrl_slot:
495 cleanup_slots(ctrl); 439 cleanup_slots(ctrl);
496err_out_release_ctlr: 440err_out_release_ctlr:
497 ctrl->hpc_ops->release_ctlr(ctrl); 441 ctrl->hpc_ops->release_ctlr(ctrl);
498err_out_free_ctrl:
499 kfree(ctrl);
500err_out_none: 442err_out_none:
501 return -ENODEV; 443 return -ENODEV;
502} 444}
503 445
504static void pciehp_remove (struct pcie_device *dev) 446static void pciehp_remove (struct pcie_device *dev)
505{ 447{
506 struct pci_dev *pdev = dev->port; 448 struct controller *ctrl = get_service_data(dev);
507 struct controller *ctrl = pci_get_drvdata(pdev);
508 449
509 cleanup_slots(ctrl); 450 cleanup_slots(ctrl);
510 ctrl->hpc_ops->release_ctlr(ctrl); 451 ctrl->hpc_ops->release_ctlr(ctrl);
511 kfree(ctrl);
512} 452}
513 453
514#ifdef CONFIG_PM 454#ifdef CONFIG_PM
@@ -522,13 +462,12 @@ static int pciehp_resume (struct pcie_device *dev)
522{ 462{
523 printk("%s ENTRY\n", __func__); 463 printk("%s ENTRY\n", __func__);
524 if (pciehp_force) { 464 if (pciehp_force) {
525 struct pci_dev *pdev = dev->port; 465 struct controller *ctrl = get_service_data(dev);
526 struct controller *ctrl = pci_get_drvdata(pdev);
527 struct slot *t_slot; 466 struct slot *t_slot;
528 u8 status; 467 u8 status;
529 468
530 /* reinitialize the chipset's event detection logic */ 469 /* reinitialize the chipset's event detection logic */
531 pcie_init_hardware_part2(ctrl, dev); 470 pcie_enable_notification(ctrl);
532 471
533 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 472 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
534 473