|
@@ -30,6 +30,7 @@
|
|
|
#include <linux/smp.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/vmalloc.h>
|
|
|
+#include <asm/firmware.h>
|
|
|
#include <asm/eeh.h> /* for eeh_add_device() */
|
|
|
#include <asm/rtas.h> /* rtas_call */
|
|
|
#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,
|
|
|
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
|
|
|
- * the my-drc-index for correlation, and obtain the requested properties.
|
|
|
+
|
|
|
+/* Verify the existence of 'drc_name' and/or 'drc_type' within the
|
|
|
+ * 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 *types, *domains;
|
|
|
- const unsigned int *my_index;
|
|
|
- char *name_tmp, *type_tmp;
|
|
|
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);
|
|
|
if (rc < 0) {
|
|
|
return -EINVAL;
|
|
@@ -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 */
|
|
|
for (i = 0; i < be32_to_cpu(indexes[0]); i++) {
|
|
|
- if ((unsigned int) indexes[i + 1] == *my_index) {
|
|
|
- if (drc_name)
|
|
|
- *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;
|
|
|
- }
|
|
|
+ if ((unsigned int) indexes[i + 1] == my_index)
|
|
|
+ break;
|
|
|
+
|
|
|
name_tmp += (strlen(name_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;
|
|
|
}
|
|
|
-EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);
|
|
|
+
|
|
|
+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;
|
|
|
+}
|
|
|
+
|
|
|
+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)
|
|
|
{
|