mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
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: Mika Westerberg <mika.westerberg@linux.intel.com>
This commit is contained in:
parent
3bb163331e
commit
7d3084c0b7
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user