rpaphp_pci.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform.
  4. * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com>
  5. *
  6. * All rights reserved.
  7. *
  8. * Send feedback to <lxie@us.ibm.com>
  9. *
  10. */
  11. #include <linux/pci.h>
  12. #include <linux/string.h>
  13. #include <asm/pci-bridge.h>
  14. #include <asm/rtas.h>
  15. #include <asm/machdep.h>
  16. #include "../pci.h" /* for pci_add_new_bus */
  17. #include "rpaphp.h"
  18. int rpaphp_get_sensor_state(struct slot *slot, int *state)
  19. {
  20. int rc;
  21. int setlevel;
  22. rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state);
  23. if (rc < 0) {
  24. if (rc == -EFAULT || rc == -EEXIST) {
  25. dbg("%s: slot must be power up to get sensor-state\n",
  26. __func__);
  27. /* some slots have to be powered up
  28. * before get-sensor will succeed.
  29. */
  30. rc = rtas_set_power_level(slot->power_domain, POWER_ON,
  31. &setlevel);
  32. if (rc < 0) {
  33. dbg("%s: power on slot[%s] failed rc=%d.\n",
  34. __func__, slot->name, rc);
  35. } else {
  36. rc = rtas_get_sensor(DR_ENTITY_SENSE,
  37. slot->index, state);
  38. }
  39. } else if (rc == -ENODEV)
  40. info("%s: slot is unusable\n", __func__);
  41. else
  42. err("%s failed to get sensor state\n", __func__);
  43. }
  44. return rc;
  45. }
  46. /**
  47. * rpaphp_enable_slot - record slot state, config pci device
  48. * @slot: target &slot
  49. *
  50. * Initialize values in the slot, and the hotplug_slot info
  51. * structures to indicate if there is a pci card plugged into
  52. * the slot. If the slot is not empty, run the pcibios routine
  53. * to get pcibios stuff correctly set up.
  54. */
  55. int rpaphp_enable_slot(struct slot *slot)
  56. {
  57. int rc, level, state;
  58. struct pci_bus *bus;
  59. struct hotplug_slot_info *info = slot->hotplug_slot->info;
  60. info->adapter_status = NOT_VALID;
  61. slot->state = EMPTY;
  62. /* Find out if the power is turned on for the slot */
  63. rc = rtas_get_power_level(slot->power_domain, &level);
  64. if (rc)
  65. return rc;
  66. info->power_status = level;
  67. /* Figure out if there is an adapter in the slot */
  68. rc = rpaphp_get_sensor_state(slot, &state);
  69. if (rc)
  70. return rc;
  71. bus = pci_find_bus_by_node(slot->dn);
  72. if (!bus) {
  73. err("%s: no pci_bus for dn %pOF\n", __func__, slot->dn);
  74. return -EINVAL;
  75. }
  76. info->adapter_status = EMPTY;
  77. slot->bus = bus;
  78. slot->pci_devs = &bus->devices;
  79. /* if there's an adapter in the slot, go add the pci devices */
  80. if (state == PRESENT) {
  81. info->adapter_status = NOT_CONFIGURED;
  82. slot->state = NOT_CONFIGURED;
  83. /* non-empty slot has to have child */
  84. if (!slot->dn->child) {
  85. err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
  86. __func__, slot->name);
  87. return -EINVAL;
  88. }
  89. if (list_empty(&bus->devices))
  90. pci_hp_add_devices(bus);
  91. if (!list_empty(&bus->devices)) {
  92. info->adapter_status = CONFIGURED;
  93. slot->state = CONFIGURED;
  94. }
  95. if (rpaphp_debug) {
  96. struct pci_dev *dev;
  97. dbg("%s: pci_devs of slot[%pOF]\n", __func__, slot->dn);
  98. list_for_each_entry(dev, &bus->devices, bus_list)
  99. dbg("\t%s\n", pci_name(dev));
  100. }
  101. }
  102. return 0;
  103. }