Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform.
0004  * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com>
0005  *
0006  * All rights reserved.
0007  *
0008  * Send feedback to <lxie@us.ibm.com>
0009  *
0010  */
0011 #include <linux/of.h>
0012 #include <linux/pci.h>
0013 #include <linux/string.h>
0014 
0015 #include <asm/pci-bridge.h>
0016 #include <asm/rtas.h>
0017 #include <asm/machdep.h>
0018 
0019 #include "../pci.h"     /* for pci_add_new_bus */
0020 #include "rpaphp.h"
0021 
0022 int rpaphp_get_sensor_state(struct slot *slot, int *state)
0023 {
0024     int rc;
0025     int setlevel;
0026 
0027     rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state);
0028 
0029     if (rc < 0) {
0030         if (rc == -EFAULT || rc == -EEXIST) {
0031             dbg("%s: slot must be power up to get sensor-state\n",
0032                 __func__);
0033 
0034             /* some slots have to be powered up
0035              * before get-sensor will succeed.
0036              */
0037             rc = rtas_set_power_level(slot->power_domain, POWER_ON,
0038                           &setlevel);
0039             if (rc < 0) {
0040                 dbg("%s: power on slot[%s] failed rc=%d.\n",
0041                     __func__, slot->name, rc);
0042             } else {
0043                 rc = rtas_get_sensor(DR_ENTITY_SENSE,
0044                              slot->index, state);
0045             }
0046         } else if (rc == -ENODEV)
0047             info("%s: slot is unusable\n", __func__);
0048         else
0049             err("%s failed to get sensor state\n", __func__);
0050     }
0051     return rc;
0052 }
0053 
0054 /**
0055  * rpaphp_enable_slot - record slot state, config pci device
0056  * @slot: target &slot
0057  *
0058  * Initialize values in the slot structure to indicate if there is a pci card
0059  * plugged into the slot. If the slot is not empty, run the pcibios routine
0060  * to get pcibios stuff correctly set up.
0061  */
0062 int rpaphp_enable_slot(struct slot *slot)
0063 {
0064     int rc, level, state;
0065     struct pci_bus *bus;
0066 
0067     slot->state = EMPTY;
0068 
0069     /* Find out if the power is turned on for the slot */
0070     rc = rtas_get_power_level(slot->power_domain, &level);
0071     if (rc)
0072         return rc;
0073 
0074     /* Figure out if there is an adapter in the slot */
0075     rc = rpaphp_get_sensor_state(slot, &state);
0076     if (rc)
0077         return rc;
0078 
0079     bus = pci_find_bus_by_node(slot->dn);
0080     if (!bus) {
0081         err("%s: no pci_bus for dn %pOF\n", __func__, slot->dn);
0082         return -EINVAL;
0083     }
0084 
0085     slot->bus = bus;
0086     slot->pci_devs = &bus->devices;
0087 
0088     /* if there's an adapter in the slot, go add the pci devices */
0089     if (state == PRESENT) {
0090         slot->state = NOT_CONFIGURED;
0091 
0092         /* non-empty slot has to have child */
0093         if (!slot->dn->child) {
0094             err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
0095                 __func__, slot->name);
0096             return -EINVAL;
0097         }
0098 
0099         if (list_empty(&bus->devices)) {
0100             pseries_eeh_init_edev_recursive(PCI_DN(slot->dn));
0101             pci_hp_add_devices(bus);
0102         }
0103 
0104         if (!list_empty(&bus->devices)) {
0105             slot->state = CONFIGURED;
0106         }
0107 
0108         if (rpaphp_debug) {
0109             struct pci_dev *dev;
0110             dbg("%s: pci_devs of slot[%pOF]\n", __func__, slot->dn);
0111             list_for_each_entry(dev, &bus->devices, bus_list)
0112                 dbg("\t%s\n", pci_name(dev));
0113         }
0114     }
0115 
0116     return 0;
0117 }