rpaphp_pci.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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 <[email protected]>
  5. *
  6. * All rights reserved.
  7. *
  8. * Send feedback to <[email protected]>
  9. *
  10. */
  11. #include <linux/of.h>
  12. #include <linux/pci.h>
  13. #include <linux/string.h>
  14. #include <asm/pci-bridge.h>
  15. #include <asm/rtas.h>
  16. #include <asm/machdep.h>
  17. #include "../pci.h" /* for pci_add_new_bus */
  18. #include "rpaphp.h"
  19. int rpaphp_get_sensor_state(struct slot *slot, int *state)
  20. {
  21. int rc;
  22. int setlevel;
  23. rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state);
  24. if (rc < 0) {
  25. if (rc == -EFAULT || rc == -EEXIST) {
  26. dbg("%s: slot must be power up to get sensor-state\n",
  27. __func__);
  28. /* some slots have to be powered up
  29. * before get-sensor will succeed.
  30. */
  31. rc = rtas_set_power_level(slot->power_domain, POWER_ON,
  32. &setlevel);
  33. if (rc < 0) {
  34. dbg("%s: power on slot[%s] failed rc=%d.\n",
  35. __func__, slot->name, rc);
  36. } else {
  37. rc = rtas_get_sensor(DR_ENTITY_SENSE,
  38. slot->index, state);
  39. }
  40. } else if (rc == -ENODEV)
  41. info("%s: slot is unusable\n", __func__);
  42. else
  43. err("%s failed to get sensor state\n", __func__);
  44. }
  45. return rc;
  46. }
  47. /**
  48. * rpaphp_enable_slot - record slot state, config pci device
  49. * @slot: target &slot
  50. *
  51. * Initialize values in the slot structure to indicate if there is a pci card
  52. * plugged into 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. slot->state = EMPTY;
  60. /* Find out if the power is turned on for the slot */
  61. rc = rtas_get_power_level(slot->power_domain, &level);
  62. if (rc)
  63. return rc;
  64. /* Figure out if there is an adapter in the slot */
  65. rc = rpaphp_get_sensor_state(slot, &state);
  66. if (rc)
  67. return rc;
  68. bus = pci_find_bus_by_node(slot->dn);
  69. if (!bus) {
  70. err("%s: no pci_bus for dn %pOF\n", __func__, slot->dn);
  71. return -EINVAL;
  72. }
  73. slot->bus = bus;
  74. slot->pci_devs = &bus->devices;
  75. /* if there's an adapter in the slot, go add the pci devices */
  76. if (state == PRESENT) {
  77. slot->state = NOT_CONFIGURED;
  78. /* non-empty slot has to have child */
  79. if (!slot->dn->child) {
  80. err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
  81. __func__, slot->name);
  82. return -EINVAL;
  83. }
  84. if (list_empty(&bus->devices)) {
  85. pseries_eeh_init_edev_recursive(PCI_DN(slot->dn));
  86. pci_hp_add_devices(bus);
  87. }
  88. if (!list_empty(&bus->devices)) {
  89. slot->state = CONFIGURED;
  90. }
  91. if (rpaphp_debug) {
  92. struct pci_dev *dev;
  93. dbg("%s: pci_devs of slot[%pOF]\n", __func__, slot->dn);
  94. list_for_each_entry(dev, &bus->devices, bus_list)
  95. dbg("\t%s\n", pci_name(dev));
  96. }
  97. }
  98. return 0;
  99. }