Commit 6b8b1d3c authored by John Rose's avatar John Rose Committed by Greg Kroah-Hartman

[PATCH] PCI Hotplug: add host bridges to RPA hotplug subsystem

The following patch implements the registration of PCI Host Bridges as hotplug
slots.  Only host bridges that are dynamically removable will be registered.
The hotplug slots directory goes from looking like this:

# ls /sys/bus/pci/slots
.             0000:00:02.2  0001:00:02.4  0002:00:02.2  30000000
..            0000:00:02.4  0001:00:02.6  0002:00:02.4  control
0000:00:02.0  0001:00:02.2  0002:00:02.0  0002:00:02.6

to this:

# ls /sys/bus/pci/slots
.             0000:00:02.0  0001:00:00.0  0001:00:02.6  0002:00:02.2  30000000
..            0000:00:02.2  0001:00:02.2  0002:00:00.0  0002:00:02.4  control
0000:00:00.0  0000:00:02.4  0001:00:02.4  0002:00:02.0  0002:00:02.6

This work is precursory to the DLPAR module changes that implement
addition/removal of these bridges.  Please apply if there are no objections.
Signed-off-by: default avatarJohn Rose <johnrose@austin.ibm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 493b82d4
......@@ -30,6 +30,7 @@
#include <linux/pci.h>
#include "pci_hotplug.h"
#define PHB 2
#define HOTPLUG 1
#define EMBEDDED 0
......
......@@ -245,9 +245,6 @@ static int is_php_dn(struct device_node *dn, int **indexes, int **names, int **t
static int is_dr_dn(struct device_node *dn, int **indexes, int **names, int **types,
int **power_domains, int **my_drc_index)
{
if (!is_hotplug_capable(dn))
return (0);
*my_drc_index = (int *) get_property(dn, "ibm,my-drc-index", NULL);
if(!*my_drc_index)
return (0);
......@@ -293,6 +290,12 @@ char *rpaphp_get_drc_name(struct device_node *dn)
return ptr;
}
static int is_dlpar_drc_type(const char *type_str)
{
/* Only register DLPAR-capable nodes of drc-type PHB or SLOT */
return (!strcmp(type_str, "PHB") || !strcmp(type_str, "SLOT"));
}
/****************************************************************
* rpaphp not only registers PCI hotplug slots(HOTPLUG),
* but also logical DR slots(EMBEDDED).
......@@ -329,15 +332,18 @@ int rpaphp_add_slot(struct device_node *dn)
for (i = 0; i < indexes[0]; i++,
name += (strlen(name) + 1), type += (strlen(type) + 1)) {
if ( slot_type == HOTPLUG ||
(slot_type == EMBEDDED && indexes[i + 1] == my_drc_index[0])) {
if (slot_type == HOTPLUG ||
(slot_type == EMBEDDED &&
indexes[i + 1] == my_drc_index[0] &&
is_dlpar_drc_type(type))) {
if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name,
power_domains[i + 1]))) {
retval = -ENOMEM;
goto exit;
}
if (slot_type == EMBEDDED)
if (!strcmp(type, "PHB"))
slot->type = PHB;
else if (slot_type == EMBEDDED)
slot->type = EMBEDDED;
else
slot->type = simple_strtoul(type, NULL, 10);
......
......@@ -408,15 +408,52 @@ static int setup_pci_hotplug_slot_info(struct slot *slot)
return 0;
}
static int set_phb_slot_name(struct slot *slot)
{
struct device_node *dn;
struct pci_controller *phb;
struct pci_bus *bus;
dn = slot->dn;
if (!dn) {
return 1;
}
phb = dn->phb;
if (!phb) {
return 1;
}
bus = phb->bus;
if (!bus) {
return 1;
}
sprintf(slot->name, "%04x:%02x:%02x.%x", pci_domain_nr(bus),
bus->number, 0, 0);
return 0;
}
static int setup_pci_slot(struct slot *slot)
{
slot->bridge = rpaphp_find_bridge_pdev(slot);
if (!slot->bridge) { /* slot being added doesn't have pci_dev yet */
err("%s: no pci_dev for bridge dn %s\n", __FUNCTION__, slot->name);
goto exit_rc;
int rc;
if (slot->type == PHB) {
rc = set_phb_slot_name(slot);
if (rc) {
err("%s: failed to set phb slot name\n", __FUNCTION__);
goto exit_rc;
}
} else {
slot->bridge = rpaphp_find_bridge_pdev(slot);
if (!slot->bridge) {
/* slot being added doesn't have pci_dev yet */
err("%s: no pci_dev for bridge dn %s\n",
__FUNCTION__, slot->name);
goto exit_rc;
}
dbg("%s set slot->name to %s\n", __FUNCTION__,
pci_name(slot->bridge));
strcpy(slot->name, pci_name(slot->bridge));
}
dbg("%s set slot->name to %s\n", __FUNCTION__, pci_name(slot->bridge));
strcpy(slot->name, pci_name(slot->bridge));
/* find slot's pci_dev if it's not empty */
if (slot->hotplug_slot->info->adapter_status == EMPTY) {
......@@ -470,10 +507,10 @@ int register_pci_slot(struct slot *slot)
int rc = 1;
slot->dev_type = PCI_DEV;
if (slot->type == EMBEDDED)
slot->removable = EMBEDDED;
if ((slot->type == EMBEDDED) || (slot->type == PHB))
slot->removable = 0;
else
slot->removable = HOTPLUG;
slot->removable = 1;
INIT_LIST_HEAD(&slot->dev.pci_funcs);
if (setup_pci_hotplug_slot_info(slot))
goto exit_rc;
......
......@@ -246,12 +246,7 @@ int rpaphp_get_power_status(struct slot *slot, u8 * value)
{
int rc = 0, level;
if (slot->type == EMBEDDED) {
dbg("%s set to POWER_ON for EMBEDDED slot %s\n",
__FUNCTION__, slot->location);
*value = POWER_ON;
}
else {
if (slot->type == HOTPLUG) {
rc = rtas_get_power_level(slot->power_domain, &level);
if (!rc) {
dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n",
......@@ -260,6 +255,10 @@ int rpaphp_get_power_status(struct slot *slot, u8 * value)
} else
err("failed to get power-level for slot(%s), rc=0x%x\n",
slot->location, rc);
} else {
dbg("%s report POWER_ON for EMBEDDED or PHB slot %s\n",
__FUNCTION__, slot->location);
*value = (u8) POWER_ON;
}
return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment