Commit 2fcf3ae5 authored by Michael Bringmann's avatar Michael Bringmann Committed by Michael Ellerman

hotplug/drc-info: Add code to search ibm,drc-info property

rpadlpar_core.c: Provide parallel routines to search the older device-
tree properties ("ibm,drc-indexes", "ibm,drc-names", "ibm,drc-types"
and "ibm,drc-power-domains"), or the new property "ibm,drc-info".

The interface to examine the DRC information is changed from a "get"
function that returns values for local verification elsewhere, to a
"check" function that validates the 'name' and/or 'type' of a device
node.  This update hides the format of the underlying device-tree
properties, and concentrates the value checks into a single function
without requiring the user to verify whether a search was successful.
Signed-off-by: default avatarMichael Bringmann <mwb@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent e83636ac
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <asm/rtas.h> #include <asm/rtas.h>
#include <asm/vio.h> #include <asm/vio.h>
#include <linux/firmware.h>
#include "../pci.h" #include "../pci.h"
#include "rpaphp.h" #include "rpaphp.h"
...@@ -44,15 +45,14 @@ static struct device_node *find_vio_slot_node(char *drc_name) ...@@ -44,15 +45,14 @@ static struct device_node *find_vio_slot_node(char *drc_name)
{ {
struct device_node *parent = of_find_node_by_name(NULL, "vdevice"); struct device_node *parent = of_find_node_by_name(NULL, "vdevice");
struct device_node *dn = NULL; struct device_node *dn = NULL;
char *name;
int rc; int rc;
if (!parent) if (!parent)
return NULL; return NULL;
while ((dn = of_get_next_child(parent, dn))) { while ((dn = of_get_next_child(parent, dn))) {
rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL); rc = rpaphp_check_drc_props(dn, drc_name, NULL);
if ((rc == 0) && (!strcmp(drc_name, name))) if (rc == 0)
break; break;
} }
...@@ -64,14 +64,11 @@ static struct device_node *find_php_slot_pci_node(char *drc_name, ...@@ -64,14 +64,11 @@ static struct device_node *find_php_slot_pci_node(char *drc_name,
char *drc_type) char *drc_type)
{ {
struct device_node *np = NULL; struct device_node *np = NULL;
char *name;
char *type;
int rc; int rc;
while ((np = of_find_node_by_name(np, "pci"))) { while ((np = of_find_node_by_name(np, "pci"))) {
rc = rpaphp_get_drc_props(np, NULL, &name, &type, NULL); rc = rpaphp_check_drc_props(np, drc_name, drc_type);
if (rc == 0) if (rc == 0)
if (!strcmp(drc_name, name) && !strcmp(drc_type, type))
break; break;
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pci_hotplug.h> #include <linux/pci_hotplug.h>
#include "rpaphp.h"
#include "rpadlpar.h" #include "rpadlpar.h"
#include "../pci.h" #include "../pci.h"
...@@ -27,8 +28,6 @@ ...@@ -27,8 +28,6 @@
#define ADD_SLOT_ATTR_NAME add_slot #define ADD_SLOT_ATTR_NAME add_slot
#define REMOVE_SLOT_ATTR_NAME remove_slot #define REMOVE_SLOT_ATTR_NAME remove_slot
#define MAX_DRC_NAME_LEN 64
static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr, static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t nbytes) const char *buf, size_t nbytes)
{ {
......
...@@ -64,6 +64,10 @@ extern bool rpaphp_debug; ...@@ -64,6 +64,10 @@ extern bool rpaphp_debug;
#define CONFIGURED 1 #define CONFIGURED 1
#define EMPTY 0 #define EMPTY 0
/* DRC constants */
#define MAX_DRC_NAME_LEN 64
/* /*
* struct slot - slot information for each *physical* slot * struct slot - slot information for each *physical* slot
*/ */
...@@ -91,8 +95,8 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state); ...@@ -91,8 +95,8 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state);
/* rpaphp_core.c */ /* rpaphp_core.c */
int rpaphp_add_slot(struct device_node *dn); int rpaphp_add_slot(struct device_node *dn);
int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, int rpaphp_check_drc_props(struct device_node *dn, char *drc_name,
char **drc_name, char **drc_type, int *drc_power_domain); char *drc_type);
/* rpaphp_slot.c */ /* rpaphp_slot.c */
void dealloc_slot_struct(struct slot *slot); void dealloc_slot_struct(struct slot *slot);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/firmware.h>
#include <asm/eeh.h> /* for eeh_add_device() */ #include <asm/eeh.h> /* for eeh_add_device() */
#include <asm/rtas.h> /* rtas_call */ #include <asm/rtas.h> /* rtas_call */
#include <asm/pci-bridge.h> /* for pci_controller */ #include <asm/pci-bridge.h> /* for pci_controller */
...@@ -196,25 +197,21 @@ static int get_children_props(struct device_node *dn, const int **drc_indexes, ...@@ -196,25 +197,21 @@ static int get_children_props(struct device_node *dn, const int **drc_indexes,
return 0; return 0;
} }
/* To get the DRC props describing the current node, first obtain it's
* my-drc-index property. Next obtain the DRC list from it's parent. Use /* Verify the existence of 'drc_name' and/or 'drc_type' within the
* the my-drc-index for correlation, and obtain the requested properties. * current node. First obtain it's my-drc-index property. Next,
* obtain the DRC info from it's parent. Use the my-drc-index for
* correlation, and obtain/validate the requested properties.
*/ */
int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
char **drc_name, char **drc_type, int *drc_power_domain) static int rpaphp_check_drc_props_v1(struct device_node *dn, char *drc_name,
char *drc_type, unsigned int my_index)
{ {
char *name_tmp, *type_tmp;
const int *indexes, *names; const int *indexes, *names;
const int *types, *domains; const int *types, *domains;
const unsigned int *my_index;
char *name_tmp, *type_tmp;
int i, rc; int i, rc;
my_index = of_get_property(dn, "ibm,my-drc-index", NULL);
if (!my_index) {
/* Node isn't DLPAR/hotplug capable */
return -EINVAL;
}
rc = get_children_props(dn->parent, &indexes, &names, &types, &domains); rc = get_children_props(dn->parent, &indexes, &names, &types, &domains);
if (rc < 0) { if (rc < 0) {
return -EINVAL; return -EINVAL;
...@@ -225,24 +222,84 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, ...@@ -225,24 +222,84 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
/* Iterate through parent properties, looking for my-drc-index */ /* Iterate through parent properties, looking for my-drc-index */
for (i = 0; i < be32_to_cpu(indexes[0]); i++) { for (i = 0; i < be32_to_cpu(indexes[0]); i++) {
if ((unsigned int) indexes[i + 1] == *my_index) { if ((unsigned int) indexes[i + 1] == my_index)
if (drc_name) break;
*drc_name = name_tmp;
if (drc_type)
*drc_type = type_tmp;
if (drc_index)
*drc_index = be32_to_cpu(*my_index);
if (drc_power_domain)
*drc_power_domain = be32_to_cpu(domains[i+1]);
return 0;
}
name_tmp += (strlen(name_tmp) + 1); name_tmp += (strlen(name_tmp) + 1);
type_tmp += (strlen(type_tmp) + 1); type_tmp += (strlen(type_tmp) + 1);
} }
if (((drc_name == NULL) || (drc_name && !strcmp(drc_name, name_tmp))) &&
((drc_type == NULL) || (drc_type && !strcmp(drc_type, type_tmp))))
return 0;
return -EINVAL;
}
static int rpaphp_check_drc_props_v2(struct device_node *dn, char *drc_name,
char *drc_type, unsigned int my_index)
{
struct property *info;
unsigned int entries;
struct of_drc_info drc;
const __be32 *value;
char cell_drc_name[MAX_DRC_NAME_LEN];
int j, fndit;
info = of_find_property(dn->parent, "ibm,drc-info", NULL);
if (info == NULL)
return -EINVAL;
value = of_prop_next_u32(info, NULL, &entries);
if (!value)
return -EINVAL;
for (j = 0; j < entries; j++) {
of_read_drc_info_cell(&info, &value, &drc);
/* Should now know end of current entry */
if (my_index > drc.last_drc_index)
continue;
fndit = 1;
break;
}
/* Found it */
if (fndit)
sprintf(cell_drc_name, "%s%d", drc.drc_name_prefix,
my_index);
if (((drc_name == NULL) ||
(drc_name && !strcmp(drc_name, cell_drc_name))) &&
((drc_type == NULL) ||
(drc_type && !strcmp(drc_type, drc.drc_type))))
return 0;
return -EINVAL; return -EINVAL;
} }
EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);
int rpaphp_check_drc_props(struct device_node *dn, char *drc_name,
char *drc_type)
{
const unsigned int *my_index;
my_index = of_get_property(dn, "ibm,my-drc-index", NULL);
if (!my_index) {
/* Node isn't DLPAR/hotplug capable */
return -EINVAL;
}
if (firmware_has_feature(FW_FEATURE_DRC_INFO))
return rpaphp_check_drc_props_v2(dn, drc_name, drc_type,
*my_index);
else
return rpaphp_check_drc_props_v1(dn, drc_name, drc_type,
*my_index);
}
EXPORT_SYMBOL_GPL(rpaphp_check_drc_props);
static int is_php_type(char *drc_type) static int is_php_type(char *drc_type)
{ {
......
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