Commit 7d3084c0 authored by Mika Westerberg's avatar Mika Westerberg
Browse files

thunderbolt: Add tb_property_copy_dir()



This function takes a deep copy of the properties. We need this in order
to support more dynamic properties per XDomain connection as required by
the USB4 inter-domain service spec.

Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
parent 3bb16333
Loading
Loading
Loading
Loading
+71 −0
Original line number Diff line number Diff line
@@ -501,6 +501,77 @@ ssize_t tb_property_format_dir(const struct tb_property_dir *dir, u32 *block,
	return ret < 0 ? ret : 0;
}

/**
 * tb_property_copy_dir() - Take a deep copy of directory
 * @dir: Directory to copy
 *
 * This function takes a deep copy of @dir and returns back the copy. In
 * case of error returns %NULL. The resulting directory needs to be
 * released by calling tb_property_free_dir().
 */
struct tb_property_dir *tb_property_copy_dir(const struct tb_property_dir *dir)
{
	struct tb_property *property, *p = NULL;
	struct tb_property_dir *d;

	if (!dir)
		return NULL;

	d = tb_property_create_dir(dir->uuid);
	if (!d)
		return NULL;

	list_for_each_entry(property, &dir->properties, list) {
		struct tb_property *p;

		p = tb_property_alloc(property->key, property->type);
		if (!p)
			goto err_free;

		p->length = property->length;

		switch (property->type) {
		case TB_PROPERTY_TYPE_DIRECTORY:
			p->value.dir = tb_property_copy_dir(property->value.dir);
			if (!p->value.dir)
				goto err_free;
			break;

		case TB_PROPERTY_TYPE_DATA:
			p->value.data = kmemdup(property->value.data,
						property->length * 4,
						GFP_KERNEL);
			if (!p->value.data)
				goto err_free;
			break;

		case TB_PROPERTY_TYPE_TEXT:
			p->value.text = kzalloc(p->length * 4, GFP_KERNEL);
			if (!p->value.text)
				goto err_free;
			strcpy(p->value.text, property->value.text);
			break;

		case TB_PROPERTY_TYPE_VALUE:
			p->value.immediate = property->value.immediate;
			break;

		default:
			break;
		}

		list_add_tail(&p->list, &d->properties);
	}

	return d;

err_free:
	kfree(p);
	tb_property_free_dir(d);

	return NULL;
}

/**
 * tb_property_add_immediate() - Add immediate property to directory
 * @parent: Directory to add the property
+1 −0
Original line number Diff line number Diff line
@@ -146,6 +146,7 @@ struct tb_property_dir *tb_property_parse_dir(const u32 *block,
					      size_t block_len);
ssize_t tb_property_format_dir(const struct tb_property_dir *dir, u32 *block,
			       size_t block_len);
struct tb_property_dir *tb_property_copy_dir(const struct tb_property_dir *dir);
struct tb_property_dir *tb_property_create_dir(const uuid_t *uuid);
void tb_property_free_dir(struct tb_property_dir *dir);
int tb_property_add_immediate(struct tb_property_dir *parent, const char *key,