client_list = client;
mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name)
- client->add(cur_mdesc, node);
+ client->add(cur_mdesc, node, client->node_name);
mutex_unlock(&mdesc_mutex);
}
static void invoke_on_missing(const char *name,
struct mdesc_handle *a,
struct mdesc_handle *b,
- void (*func)(struct mdesc_handle *, u64))
+ void (*func)(struct mdesc_handle *, u64,
+ const char *node_name))
{
- u64 node;
+ mdesc_node_info_get_f get_info_func;
+ mdesc_node_info_rel_f rel_info_func;
+ mdesc_node_match_f node_match_func;
+ union md_node_info a_node_info;
+ union md_node_info b_node_info;
+ bool found;
+ u64 a_node;
+ u64 b_node;
+ int rv;
- mdesc_for_each_node_by_name(a, node, name) {
- int found = 0, is_vdc_port = 0;
- const char *name_prop;
- const u64 *id;
- u64 fnode;
-
- name_prop = mdesc_get_property(a, node, "name", NULL);
- if (name_prop && !strcmp(name_prop, "vdc-port")) {
- is_vdc_port = 1;
- id = parent_cfg_handle(a, node);
- } else
- id = mdesc_get_property(a, node, "id", NULL);
-
- if (!id) {
- printk(KERN_ERR "MD: Cannot find ID for %s node.\n",
- (name_prop ? name_prop : name));
+ /*
+ * Find the get_info, rel_info and node_match ops for the given
+ * node name
+ */
+ mdesc_get_node_ops(name, &get_info_func, &rel_info_func,
+ &node_match_func);
+
+ /* If we didn't find a match, the node type is not supported */
+ if (!get_info_func || !rel_info_func || !node_match_func) {
+ pr_err("MD: %s node type is not supported\n", name);
+ return;
+ }
+
+ mdesc_for_each_node_by_name(a, a_node, name) {
+ found = false;
+
+ rv = get_info_func(a, a_node, &a_node_info);
+ if (rv != 0) {
+ pr_err("MD: Cannot find 1 or more required match properties for %s node.\n",
+ name);
continue;
}
- mdesc_for_each_node_by_name(b, fnode, name) {
- const u64 *fid;
-
- if (is_vdc_port) {
- name_prop = mdesc_get_property(b, fnode,
- "name", NULL);
- if (!name_prop ||
- strcmp(name_prop, "vdc-port"))
- continue;
- fid = parent_cfg_handle(b, fnode);
- if (!fid) {
- printk(KERN_ERR "MD: Cannot find ID "
- "for vdc-port node.\n");
- continue;
- }
- } else
- fid = mdesc_get_property(b, fnode,
- "id", NULL);
-
- if (*id == *fid) {
- found = 1;
+ /* Check each node in B for node matching a_node */
+ mdesc_for_each_node_by_name(b, b_node, name) {
+ rv = get_info_func(b, b_node, &b_node_info);
+ if (rv != 0)
+ continue;
+
+ if (node_match_func(&a_node_info, &b_node_info)) {
+ found = true;
+ rel_info_func(&b_node_info);
break;
}
+
+ rel_info_func(&b_node_info);
}
+
+ rel_info_func(&a_node_info);
+
if (!found)
- func(a, node);
+ func(a, a_node, name);
}
}
EXPORT_SYMBOL(vio_set_intr);
static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
+ const char *node_name,
struct device *parent)
{
const char *type, *compat, *bus_id_name;
tlen = strlen(type) + 1;
}
}
- if (tlen > VIO_MAX_TYPE_LEN) {
+ if (tlen > VIO_MAX_TYPE_LEN || strlen(type) >= VIO_MAX_TYPE_LEN) {
printk(KERN_ERR "VIO: Type string [%s] is too long.\n",
type);
return NULL;
printk(KERN_INFO "VIO: Adding device %s\n", dev_name(&vdev->dev));
+ /* node_name is NULL for the parent/channel-devices node */
+ if (node_name != NULL)
+ (void) snprintf(vdev->node_name, VIO_MAX_NAME_LEN, "%s",
+ node_name);
+
err = device_register(&vdev->dev);
if (err) {
printk(KERN_ERR "VIO: Could not register device %s, err=%d\n",
return vdev;
}
-static void vio_add(struct mdesc_handle *hp, u64 node)
+static void vio_add(struct mdesc_handle *hp, u64 node,
+ const char *node_name)
{
- (void) vio_create_one(hp, node, &root_vdev->dev);
+ (void) vio_create_one(hp, node, node_name, &root_vdev->dev);
}
struct vio_md_node_query {
return 1;
}
-static void vio_remove(struct mdesc_handle *hp, u64 node)
+static void vio_remove(struct mdesc_handle *hp, u64 node, const char *node_name)
{
const char *type;
const u64 *id, *cfg_handle;
* under "openboot" that we should not mess with as aparently that is
* reserved exclusively for OBP use.
*/
-static void vio_add_ds(struct mdesc_handle *hp, u64 node)
+static void vio_add_ds(struct mdesc_handle *hp, u64 node,
+ const char *node_name)
{
int found;
u64 a;
}
if (found)
- (void) vio_create_one(hp, node, &root_vdev->dev);
+ (void) vio_create_one(hp, node, node_name, &root_vdev->dev);
}
static struct mdesc_notifier_client vio_ds_notifier = {
cdev_cfg_handle = *cfg_handle;
- root_vdev = vio_create_one(hp, root, NULL);
+ root_vdev = vio_create_one(hp, root, NULL, NULL);
err = -ENODEV;
if (!root_vdev) {
printk(KERN_ERR "VIO: Could not create root device.\n");