Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+52 −4
Original line number Diff line number Diff line
@@ -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,12 +259,41 @@ 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,
			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) {
+26 −3
Original line number Diff line number Diff line
@@ -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;
+8 −16
Original line number Diff line number Diff line
@@ -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),
+2 −0
Original line number Diff line number Diff line
@@ -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;