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