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