linux/drivers/pci/hotplug/rpaphp_pci.c
<<
>>
Prefs
   1/*
   2 * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform.
   3 * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com>
   4 *
   5 * All rights reserved.
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or (at
  10 * your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  15 * NON INFRINGEMENT.  See the GNU General Public License for more
  16 * details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21 *
  22 * Send feedback to <lxie@us.ibm.com>
  23 *
  24 */
  25#include <linux/pci.h>
  26#include <linux/string.h>
  27
  28#include <asm/pci-bridge.h>
  29#include <asm/rtas.h>
  30#include <asm/machdep.h>
  31
  32#include "../pci.h"             /* for pci_add_new_bus */
  33#include "rpaphp.h"
  34
  35int rpaphp_get_sensor_state(struct slot *slot, int *state)
  36{
  37        int rc;
  38        int setlevel;
  39
  40        rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state);
  41
  42        if (rc < 0) {
  43                if (rc == -EFAULT || rc == -EEXIST) {
  44                        dbg("%s: slot must be power up to get sensor-state\n",
  45                            __func__);
  46
  47                        /* some slots have to be powered up 
  48                         * before get-sensor will succeed.
  49                         */
  50                        rc = rtas_set_power_level(slot->power_domain, POWER_ON,
  51                                                  &setlevel);
  52                        if (rc < 0) {
  53                                dbg("%s: power on slot[%s] failed rc=%d.\n",
  54                                    __func__, slot->name, rc);
  55                        } else {
  56                                rc = rtas_get_sensor(DR_ENTITY_SENSE,
  57                                                     slot->index, state);
  58                        }
  59                } else if (rc == -ENODEV)
  60                        info("%s: slot is unusable\n", __func__);
  61                else
  62                        err("%s failed to get sensor state\n", __func__);
  63        }
  64        return rc;
  65}
  66
  67/**
  68 * rpaphp_enable_slot - record slot state, config pci device
  69 * @slot: target &slot
  70 *
  71 * Initialize values in the slot, and the hotplug_slot info
  72 * structures to indicate if there is a pci card plugged into
  73 * the slot. If the slot is not empty, run the pcibios routine
  74 * to get pcibios stuff correctly set up.
  75 */
  76int rpaphp_enable_slot(struct slot *slot)
  77{
  78        int rc, level, state;
  79        struct pci_bus *bus;
  80        struct hotplug_slot_info *info = slot->hotplug_slot->info;
  81
  82        info->adapter_status = NOT_VALID;
  83        slot->state = EMPTY;
  84
  85        /* Find out if the power is turned on for the slot */
  86        rc = rtas_get_power_level(slot->power_domain, &level);
  87        if (rc)
  88                return rc;
  89        info->power_status = level;
  90
  91        /* Figure out if there is an adapter in the slot */
  92        rc = rpaphp_get_sensor_state(slot, &state);
  93        if (rc)
  94                return rc;
  95
  96        bus = pcibios_find_pci_bus(slot->dn);
  97        if (!bus) {
  98                err("%s: no pci_bus for dn %s\n", __func__, slot->dn->full_name);
  99                return -EINVAL;
 100        }
 101
 102        info->adapter_status = EMPTY;
 103        slot->bus = bus;
 104        slot->pci_devs = &bus->devices;
 105
 106        /* if there's an adapter in the slot, go add the pci devices */
 107        if (state == PRESENT) {
 108                info->adapter_status = NOT_CONFIGURED;
 109                slot->state = NOT_CONFIGURED;
 110
 111                /* non-empty slot has to have child */
 112                if (!slot->dn->child) {
 113                        err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
 114                            __func__, slot->name);
 115                        return -EINVAL;
 116                }
 117
 118                if (list_empty(&bus->devices))
 119                        pcibios_add_pci_devices(bus);
 120
 121                if (!list_empty(&bus->devices)) {
 122                        info->adapter_status = CONFIGURED;
 123                        slot->state = CONFIGURED;
 124                }
 125
 126                if (rpaphp_debug) {
 127                        struct pci_dev *dev;
 128                        dbg("%s: pci_devs of slot[%s]\n", __func__, slot->dn->full_name);
 129                        list_for_each_entry (dev, &bus->devices, bus_list)
 130                                dbg("\t%s\n", pci_name(dev));
 131                }
 132        }
 133
 134        return 0;
 135}
 136
 137