mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-16 05:50:19 +00:00
[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: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
48db7b7c50
commit
91ba3c2128
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user