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,
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;
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";
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;
u64 operations;
u32 vdisk_size;
u8 vdisk_type;
- u8 dev_no;
char disk_name[32];
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;
{
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;
}
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),
char compat[VIO_MAX_COMPAT_LEN];
int compat_len;
+ u64 dev_no;
+
unsigned long channel_id;
unsigned int tx_irq;