Commit 91ba3c21 authored by David S. Miller's avatar David S. Miller

[SPARC64]: Fix handling of multiple vdc-port nodes.

The "id" property in vdc-port nodes are not unique, they
are all zero.  Therefore assign ID's using the parent's
"cfg-handle" property which will be unique.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 48db7b7c
......@@ -231,6 +231,25 @@ void mdesc_register_notifier(struct mdesc_notifier_client *client)
mutex_unlock(&mdesc_mutex);
}
static const u64 *parent_cfg_handle(struct mdesc_handle *hp, u64 node)
{
const u64 *id;
u64 a;
id = NULL;
mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
u64 target;
target = mdesc_arc_target(hp, a);
id = mdesc_get_property(hp, target,
"cfg-handle", NULL);
if (id)
break;
}
return id;
}
/* Run 'func' on nodes which are in A but not in B. */
static void invoke_on_missing(const char *name,
struct mdesc_handle *a,
......@@ -240,13 +259,42 @@ static void invoke_on_missing(const char *name,
u64 node;
mdesc_for_each_node_by_name(a, node, name) {
const u64 *id = mdesc_get_property(a, node, "id", NULL);
int found = 0;
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));
continue;
}
mdesc_for_each_node_by_name(b, fnode, name) {
const u64 *fid = mdesc_get_property(b, fnode,
"id", NULL);
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;
......
......@@ -221,6 +221,27 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
return NULL;
}
if (!strcmp(type, "vdc-port")) {
u64 a;
id = NULL;
mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
u64 target;
target = mdesc_arc_target(hp, a);
id = mdesc_get_property(hp, target,
"cfg-handle", NULL);
if (id)
break;
}
if (!id) {
printk(KERN_ERR "VIO: vdc-prot lacks parent "
"cfg-handle.\n");
return NULL;
}
} else
id = mdesc_get_property(hp, mp, "id", NULL);
bus_id_name = type;
if (!strcmp(type, "domain-services-port"))
bus_id_name = "ds";
......@@ -260,13 +281,15 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
vio_fill_channel_info(hp, mp, vdev);
id = mdesc_get_property(hp, mp, "id", NULL);
if (!id)
if (!id) {
snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s",
bus_id_name);
else
vdev->dev_no = ~(u64)0;
} else {
snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu",
bus_id_name, *id);
vdev->dev_no = *id;
}
vdev->dev.parent = parent;
vdev->dev.bus = &vio_bus_type;
......
......@@ -64,7 +64,6 @@ struct vdc_port {
u64 operations;
u32 vdisk_size;
u8 vdisk_type;
u8 dev_no;
char disk_name[32];
......@@ -703,7 +702,7 @@ static int probe_disk(struct vdc_port *port)
blk_queue_max_phys_segments(q, port->ring_cookies);
blk_queue_max_sectors(q, port->max_xfer_size);
g->major = vdc_major;
g->first_minor = port->dev_no << PARTITION_SHIFT;
g->first_minor = port->vio.vdev->dev_no << PARTITION_SHIFT;
strcpy(g->disk_name, port->disk_name);
g->fops = &vdc_fops;
......@@ -747,21 +746,16 @@ static int __devinit vdc_port_probe(struct vio_dev *vdev,
{
struct mdesc_handle *hp;
struct vdc_port *port;
const u64 *port_id;
int err;
print_version();
hp = mdesc_grab();
port_id = mdesc_get_property(hp, vdev->mp, "id", NULL);
err = -ENODEV;
if (!port_id) {
printk(KERN_ERR PFX "Port lacks id property.\n");
goto err_out_release_mdesc;
}
if ((*port_id << PARTITION_SHIFT) & ~(u64)MINORMASK) {
printk(KERN_ERR PFX "Port id [%lu] too large.\n", *port_id);
if ((vdev->dev_no << PARTITION_SHIFT) & ~(u64)MINORMASK) {
printk(KERN_ERR PFX "Port id [%lu] too large.\n",
vdev->dev_no);
goto err_out_release_mdesc;
}
......@@ -772,16 +766,14 @@ static int __devinit vdc_port_probe(struct vio_dev *vdev,
goto err_out_release_mdesc;
}
port->dev_no = *port_id;
if (port->dev_no >= 26)
if (vdev->dev_no >= 26)
snprintf(port->disk_name, sizeof(port->disk_name),
VDCBLK_NAME "%c%c",
'a' + (port->dev_no / 26) - 1,
'a' + (port->dev_no % 26));
'a' + ((int)vdev->dev_no / 26) - 1,
'a' + ((int)vdev->dev_no % 26));
else
snprintf(port->disk_name, sizeof(port->disk_name),
VDCBLK_NAME "%c", 'a' + (port->dev_no % 26));
VDCBLK_NAME "%c", 'a' + ((int)vdev->dev_no % 26));
err = vio_driver_init(&port->vio, vdev, VDEV_DISK,
vdc_versions, ARRAY_SIZE(vdc_versions),
......
......@@ -275,6 +275,8 @@ struct vio_dev {
char compat[VIO_MAX_COMPAT_LEN];
int compat_len;
u64 dev_no;
unsigned long channel_id;
unsigned int tx_irq;
......
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