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