software node: add support for reference properties
Subsystems (5)
v6 cover software node: add support for reference properties
These series implement "references" properties for software nodes as true properties, instead of managing them completely separately.
The first 10 patches are generic cleanups and consolidation and unification of the existing code; patch #11 implements moving of small properties inline when copying property entries; patch #12 implements PROPERTY_ENTRY_REF() and friends; patch #13 converts the user of references to the property syntax, and patch #14 removes the remains of references as entities that are managed separately.
Patch #15 adds unit tests to verify that the handling of property entries is correct.
Changes in v6:
- rebased onto next-20191023
- fixed patch moving small properties inline
- fixed handling boolean properties after is_array -> is_inline conversion
- changed comments around is_inline "stored directly" vs embedded in one place (Andy)
- added unit tests for property entries based on KUnit framework
- added Any's reviewed-by/acked-by
Changes in v5:
- rebased onto next-20191011
Changes in v4:
- dealt with union aliasing concerns
- inline small properties on copy
Changes in v3:
- added various cleanups before implementing reference properties
Changes in v2:
- reworked code so that even single-entry reference properties are stored as arrays (i.e. the software_node_ref_args instances are not part of property_entry structure) to avoid size increase. From user's POV nothing is changed, one can still use PROPERTY_ENTRY_REF macro to define reference "inline".
- dropped unused DEV_PROP_MAX
- rebased on linux-next
Dmitry Torokhov (15):
software node: remove DEV_PROP_MAX
software node: introduce PROPERTY_ENTRY_ARRAY_XXX_LEN() efi/apple-properties: use PROPERTY_ENTRY_U8_ARRAY_LEN software node: mark internal macros with double underscores software node: clean up property_copy_string_array() software node: get rid of property_set_pointer() software node: remove property_entry_read_uNN_array functions software node: unify PROPERTY_ENTRY_XXX macros software node: simplify property_entry_read_string_array() software node: rename is_array to is_inline
software node: move small properties inline when copying software node: implement reference properties platform/x86: intel_cht_int33fe: use inline reference properties software node: remove separate handling of references software node: add basic tests for property entries
drivers/base/swnode.c | 263 ++++------ drivers/base/test/Makefile | 2 + drivers/base/test/property-entry-test.c | 472 ++++++++++++++++++ drivers/firmware/efi/apple-properties.c | 18 +- .../platform/x86/intel_cht_int33fe_typec.c | 81 +-- include/linux/property.h | 178 +++---- 6 files changed, 702 insertions(+), 312 deletions(-) create mode 100644 drivers/base/test/property-entry-test.c
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 1/15 software node: remove DEV_PROP_MAX
This definition is not used anywhere, let's remove it.
--- include/linux/property.h | 1 - 1 file changed, 1 deletion(-)
include/linux/property.h +0 -1
@@ -22,7 +22,6 @@ enum dev_prop_type {DEV_PROP_U32 ,DEV_PROP_U64 , DEV_PROP_STRING, - DEV_PROP_MAX, }; enum dev_dma_attr {
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 2/15 software node: introduce PROPERTY_ENTRY_ARRAY_XXX_LEN()
In reply to Dmitry TorokhovSometimes we want to initialize property entry array from a regular pointer, when we can't determine length automatically via ARRAY_SIZE. Let's introduce PROPERTY_ENTRY_ARRAY_XXX_LEN macros that take explicit "len" argument.
--- include/linux/property.h | 45 +++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 17 deletions(-)
include/linux/property.h +28 -17
@@ -261,33 +261,44 @@ struct property_entry {* and structs. */ -#define PROPERTY_ENTRY_INTEGER_ARRAY (_name_, _type_, _Type_, _val_) \ +#define PROPERTY_ENTRY_ARRAY_LEN (_name_, _type_, _Type_, _val_, _len_) \ (struct property_entry) { \ .name = _name_, \ - .length = ARRAY_SIZE(_val_) * sizeof(_type_), \ + .length = (_len_) * sizeof(_type_), \ .is_array = true, \ .type = DEV_PROP_##_Type_, \ { .pointer = { ._type_##_data = _val_ } }, \ } -#define PROPERTY_ENTRY_U8_ARRAY (_name_, _val_) \ - PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u8, U8, _val_) -#define PROPERTY_ENTRY_U16_ARRAY (_name_, _val_) \ - PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u16, U16, _val_) -#define PROPERTY_ENTRY_U32_ARRAY (_name_, _val_) \ - PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u32, U32, _val_) -#define PROPERTY_ENTRY_U64_ARRAY (_name_, _val_) \ - PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u64, U64, _val_) +#define PROPERTY_ENTRY_U8_ARRAY_LEN (_name_, _val_, _len_) \ + PROPERTY_ENTRY_ARRAY_LEN(_name_, u8, U8, _val_, _len_) +#define PROPERTY_ENTRY_U16_ARRAY_LEN (_name_, _val_, _len_) \ + PROPERTY_ENTRY_ARRAY_LEN(_name_, u16, U16, _val_, _len_) +#define PROPERTY_ENTRY_U32_ARRAY_LEN (_name_, _val_, _len_) \ + PROPERTY_ENTRY_ARRAY_LEN(_name_, u32, U32, _val_, _len_) +#define PROPERTY_ENTRY_U64_ARRAY_LEN (_name_, _val_, _len_) \ + PROPERTY_ENTRY_ARRAY_LEN(_name_, u64, U64, _val_, _len_) -#define PROPERTY_ENTRY_STRING_ARRAY (_name_, _val_) \ -(struct property_entry) { \ - .name = _name_, \ - .length = ARRAY_SIZE(_val_) * sizeof(const char *), \ - .is_array = true, \ - .type = DEV_PROP_STRING, \ - { .pointer = { .str = _val_ } }, \ +#define PROPERTY_ENTRY_STRING_ARRAY_LEN (_name_, _val_, _len_) \ +(struct property_entry) { \ + .name = _name_, \ + .length = (_len_) * sizeof(const char *), \ + .is_array = true, \ + .type = DEV_PROP_STRING, \ + { .pointer = { .str = _val_ } }, \ } +#define PROPERTY_ENTRY_U8_ARRAY (_name_, _val_) \ + PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) +#define PROPERTY_ENTRY_U16_ARRAY (_name_, _val_) \ + PROPERTY_ENTRY_U16_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) +#define PROPERTY_ENTRY_U32_ARRAY (_name_, _val_) \ + PROPERTY_ENTRY_U32_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) +#define PROPERTY_ENTRY_U64_ARRAY (_name_, _val_) \ + PROPERTY_ENTRY_U64_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) +#define PROPERTY_ENTRY_STRING_ARRAY (_name_, _val_) \ + PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) +#define PROPERTY_ENTRY_INTEGER (_name_, _type_, _Type_, _val_) \ (struct property_entry) { \ .name = _name_, \
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 3/15 efi/apple-properties: use PROPERTY_ENTRY_U8_ARRAY_LEN
In reply to Dmitry TorokhovLet's switch to using PROPERTY_ENTRY_U8_ARRAY_LEN() to initialize property entries. Also, when dumping data, rely on local variables instead of poking into the property entry structure directly.
--- drivers/firmware/efi/apple-properties.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-)
drivers/firmware/efi/apple-properties.c +8 -10
@@ -53,7 +53,8 @@ static void __init unmarshal_key_value_pairs(struct dev_header *dev_header,for (i =0 ; i < dev_header->prop_count; i++) {int remaining = dev_header->len - (ptr - (void *)dev_header); -u32 key_len, val_len; +u32 key_len, val_len, entry_len; +const u8 *entry_data;char *key;if (sizeof (key_len) > remaining)
@@ -85,17 +86,14 @@ static void __init unmarshal_key_value_pairs(struct dev_header *dev_header,ucs2_as_utf8 (key, ptr +sizeof (key_len), key_len -sizeof (key_len)); - entry[i].name = key; - entry[i].length = val_len -sizeof (val_len); - entry[i].is_array = !!entry[i].length; - entry[i].type =DEV_PROP_U8 ; - entry[i].pointer.u8_data = ptr + key_len +sizeof (val_len); - + entry_data = ptr + key_len +sizeof (val_len); + entry_len = val_len -sizeof (val_len); + entry[i] =PROPERTY_ENTRY_U8_ARRAY_LEN (key, entry_data, + entry_len);if (dump_properties) { -dev_info (dev,"property: %s\n" , entry[i].name); +dev_info (dev,"property: %s\n" , key);print_hex_dump (KERN_INFO ,pr_fmt (),DUMP_PREFIX_OFFSET , -16 ,1 , entry[i].pointer.u8_data, - entry[i].length, true); +16 ,1 , entry_data, entry_len, true); } ptr += key_len + val_len;
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 4/15 software node: mark internal macros with double underscores
In reply to Dmitry TorokhovLet's mark PROPERTY_ENTRY_* macros that are internal with double leading underscores so users are not tempted to use them.
--- include/linux/property.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
include/linux/property.h +10 -10
@@ -261,7 +261,7 @@ struct property_entry {* and structs. */ -#define PROPERTY_ENTRY_ARRAY_LEN (_name_, _type_, _Type_, _val_, _len_) \ +#define __PROPERTY_ENTRY_ARRAY_LEN (_name_, _type_, _Type_, _val_, _len_)\ (struct property_entry) { \ .name = _name_, \ .length = (_len_) * sizeof(_type_), \
@@ -271,13 +271,13 @@ struct property_entry { }#define PROPERTY_ENTRY_U8_ARRAY_LEN (_name_, _val_, _len_) \ - PROPERTY_ENTRY_ARRAY_LEN(_name_, u8, U8, _val_, _len_) + __PROPERTY_ENTRY_ARRAY_LEN(_name_, u8, U8, _val_, _len_)#define PROPERTY_ENTRY_U16_ARRAY_LEN (_name_, _val_, _len_) \ - PROPERTY_ENTRY_ARRAY_LEN(_name_, u16, U16, _val_, _len_) + __PROPERTY_ENTRY_ARRAY_LEN(_name_, u16, U16, _val_, _len_)#define PROPERTY_ENTRY_U32_ARRAY_LEN (_name_, _val_, _len_) \ - PROPERTY_ENTRY_ARRAY_LEN(_name_, u32, U32, _val_, _len_) + __PROPERTY_ENTRY_ARRAY_LEN(_name_, u32, U32, _val_, _len_)#define PROPERTY_ENTRY_U64_ARRAY_LEN (_name_, _val_, _len_) \ - PROPERTY_ENTRY_ARRAY_LEN(_name_, u64, U64, _val_, _len_) + __PROPERTY_ENTRY_ARRAY_LEN(_name_, u64, U64, _val_, _len_)#define PROPERTY_ENTRY_STRING_ARRAY_LEN (_name_, _val_, _len_) \ (struct property_entry) { \
@@ -299,7 +299,7 @@ struct property_entry {#define PROPERTY_ENTRY_STRING_ARRAY (_name_, _val_) \ PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) -#define PROPERTY_ENTRY_INTEGER (_name_, _type_, _Type_, _val_) \ +#define __PROPERTY_ENTRY_INTEGER (_name_, _type_, _Type_, _val_) \ (struct property_entry) { \ .name = _name_, \ .length = sizeof(_type_), \
@@ -308,13 +308,13 @@ struct property_entry { }#define PROPERTY_ENTRY_U8 (_name_, _val_) \ - PROPERTY_ENTRY_INTEGER(_name_, u8, U8, _val_) + __PROPERTY_ENTRY_INTEGER(_name_, u8, U8, _val_)#define PROPERTY_ENTRY_U16 (_name_, _val_) \ - PROPERTY_ENTRY_INTEGER(_name_, u16, U16, _val_) + __PROPERTY_ENTRY_INTEGER(_name_, u16, U16, _val_)#define PROPERTY_ENTRY_U32 (_name_, _val_) \ - PROPERTY_ENTRY_INTEGER(_name_, u32, U32, _val_) + __PROPERTY_ENTRY_INTEGER(_name_, u32, U32, _val_)#define PROPERTY_ENTRY_U64 (_name_, _val_) \ - PROPERTY_ENTRY_INTEGER(_name_, u64, U64, _val_) + __PROPERTY_ENTRY_INTEGER(_name_, u64, U64, _val_)#define PROPERTY_ENTRY_STRING (_name_, _val_) \ (struct property_entry) { \
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 5/15 software node: clean up property_copy_string_array()
In reply to Dmitry TorokhovBecause property_copy_string_array() stores the newly allocated pointer in the destination property, we have an awkward code in property_entry_copy_data() where we fetch the new pointer from dst.
Let's change property_copy_string_array() to return pointer and rely on the common path in property_entry_copy_data() to store it in destination structure.
--- drivers/base/swnode.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-)
drivers/base/swnode.c +8 -11
@@ -337,8 +337,8 @@ static void property_entry_free_data(const struct property_entry *p)kfree (p->name); } -static int property_copy_string_array (struct property_entry *dst, -const struct property_entry *src) +static const char *const * +property_copy_string_array (const struct property_entry *src) {const char **d;size_t nval = src->length /sizeof (*d);
@@ -346,7 +346,7 @@ static int property_copy_string_array(struct property_entry *dst, d =kcalloc (nval,sizeof (*d),GFP_KERNEL );if (!d) -return -ENOMEM ; +return NULL ;for (i =0 ; i < nval; i++) { d[i] =kstrdup (src->pointer.str[i],GFP_KERNEL );
@@ -354,12 +354,11 @@ static int property_copy_string_array(struct property_entry *dst,while (--i >=0 )kfree (d[i]);kfree (d); -return -ENOMEM ; +return NULL ; } } - dst->pointer.str = d; -return 0 ; +return d; } static int property_entry_copy_data(struct property_entry *dst,
@@ -367,17 +366,15 @@ static int property_entry_copy_data(struct property_entry *dst, {const void *pointer =property_get_pointer (src);const void *new; -int error;if (src->is_array) {if (!src->length)return -ENODATA ;if (src->type ==DEV_PROP_STRING ) { - error =property_copy_string_array (dst, src); -if (error) -return error; - new = dst->pointer.str; + new =property_copy_string_array (src); +if (!new) +return -ENOMEM ; }else { new =kmemdup (pointer, src->length,GFP_KERNEL );if (!new)
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 6/15 software node: get rid of property_set_pointer()
In reply to Dmitry TorokhovInstead of explicitly setting values of integer types when copying property entries lets just copy entire value union when processing non-array values.
For value arrays we no longer use union of pointers, but rather a single void pointer, which allows us to remove property_set_pointer().
In property_get_pointer() we do not need to handle each data type separately, we can simply return either the pointer or pointer to values union.
We are not losing anything from removing typed pointer union because the upper layers do their accesses through void pointers anyway, and we trust the "type" of the property when interpret the data. We rely on users of property entries on using PROPERTY_ENTRY_XXX() macros to properly initialize entries instead of poking in the instances directly.
--- drivers/base/swnode.c | 90 +++++++++------------------------------- include/linux/property.h | 12 ++---- 2 files changed, 22 insertions(+), 80 deletions(-)
drivers/base/swnode.c +19 -71
@@ -103,71 +103,15 @@ property_entry_get(const struct property_entry *prop, const char *name)return NULL ; } -static void -property_set_pointer (struct property_entry *prop,const void *pointer) -{ -switch (prop->type) { -case DEV_PROP_U8 : -if (prop->is_array) - prop->pointer.u8_data = pointer; -else - prop->value.u8_data = *((u8 *)pointer); -break ; -case DEV_PROP_U16 : -if (prop->is_array) - prop->pointer.u16_data = pointer; -else - prop->value.u16_data = *((u16 *)pointer); -break ; -case DEV_PROP_U32 : -if (prop->is_array) - prop->pointer.u32_data = pointer; -else - prop->value.u32_data = *((u32 *)pointer); -break ; -case DEV_PROP_U64 : -if (prop->is_array) - prop->pointer.u64_data = pointer; -else - prop->value.u64_data = *((u64 *)pointer); -break ; -case DEV_PROP_STRING : -if (prop->is_array) - prop->pointer.str = pointer; -else - prop->value.str = pointer; -break ; -default : -break ; - } -} -static const void *property_get_pointer (const struct property_entry *prop) { -switch (prop->type) { -case DEV_PROP_U8 : -if (prop->is_array) -return prop->pointer.u8_data; -return &prop->value.u8_data; -case DEV_PROP_U16 : -if (prop->is_array) -return prop->pointer.u16_data; -return &prop->value.u16_data; -case DEV_PROP_U32 : -if (prop->is_array) -return prop->pointer.u32_data; -return &prop->value.u32_data; -case DEV_PROP_U64 : -if (prop->is_array) -return prop->pointer.u64_data; -return &prop->value.u64_data; -case DEV_PROP_STRING : -if (prop->is_array) -return prop->pointer.str; -return &prop->value.str; -default : +if (!prop->length)return NULL ; - } + +if (prop->is_array) +return prop->pointer; + +return &prop->value; } static const void *property_entry_find(const struct property_entry *props,
@@ -322,13 +266,15 @@ static int property_entry_read_string_array(const struct property_entry *props,static void property_entry_free_data (const struct property_entry *p) {const void *pointer =property_get_pointer (p); +const char *const *src_str;size_t i, nval;if (p->is_array) { -if (p->type ==DEV_PROP_STRING && p->pointer.str) { +if (p->type ==DEV_PROP_STRING && p->pointer) { + src_str = p->pointer; nval = p->length /sizeof (const char *);for (i =0 ; i < nval; i++) -kfree (p->pointer.str[i]); +kfree (src_str[i]); }kfree (pointer); }else if (p->type ==DEV_PROP_STRING ) {
@@ -341,6 +287,7 @@ static const char * const * property_copy_string_array(const struct property_entry *src) {const char **d; +const char *const *src_str = src->pointer;size_t nval = src->length /sizeof (*d);int i;
@@ -349,8 +296,8 @@ property_copy_string_array(const struct property_entry *src)return NULL ;for (i =0 ; i < nval; i++) { - d[i] =kstrdup (src->pointer.str[i],GFP_KERNEL ); -if (!d[i] && src->pointer.str[i]) { + d[i] =kstrdup (src_str[i],GFP_KERNEL ); +if (!d[i] && src_str[i]) {while (--i >=0 )kfree (d[i]);kfree (d);
@@ -380,20 +327,21 @@ static int property_entry_copy_data(struct property_entry *dst,if (!new)return -ENOMEM ; } + + dst->is_array = true; + dst->pointer = new; }else if (src->type ==DEV_PROP_STRING ) { new =kstrdup (src->value.str,GFP_KERNEL );if (!new && src->value.str)return -ENOMEM ; + + dst->value.str = new; }else { - new = pointer; + dst->value = src->value; } dst->length = src->length; - dst->is_array = src->is_array; dst->type = src->type; - -property_set_pointer (dst, new); - dst->name =kstrdup (src->name,GFP_KERNEL );if (!dst->name) goto out_free_data;
include/linux/property.h +3 -9
@@ -238,13 +238,7 @@ struct property_entry {bool is_array;enum dev_prop_type type;union { -union { -const u8 *u8_data; -const u16 *u16_data; -const u32 *u32_data; -const u64 *u64_data; -const char *const *str; - } pointer; +const void *pointer;union {u8 u8_data;u16 u16_data;
@@ -267,7 +261,7 @@ struct property_entry { .length = (_len_) * sizeof(_type_), \ .is_array = true, \ .type = DEV_PROP_##_Type_, \ - { .pointer = { ._type_##_data = _val_ } }, \ + { .pointer = _val_ }, \ }#define PROPERTY_ENTRY_U8_ARRAY_LEN (_name_, _val_, _len_) \
@@ -285,7 +279,7 @@ struct property_entry { .length = (_len_) * sizeof(const char *), \ .is_array = true, \ .type = DEV_PROP_STRING, \ - { .pointer = { .str = _val_ } }, \ + { .pointer = _val_ }, \ }#define PROPERTY_ENTRY_U8_ARRAY (_name_, _val_) \
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 7/15 software node: remove property_entry_read_uNN_array functions
In reply to Dmitry TorokhovThere is absolutely no reason to have them as we can handle it all nicely in property_entry_read_int_array().
--- drivers/base/swnode.c | 85 +++++++------------------------------------ 1 file changed, 14 insertions(+), 71 deletions(-)
drivers/base/swnode.c +14 -71
@@ -131,66 +131,6 @@ static const void *property_entry_find(const struct property_entry *props,return pointer; } -static int property_entry_read_u8_array (const struct property_entry *props, -const char *propname, -u8 *values,size_t nval) -{ -const void *pointer; -size_t length = nval *sizeof (*values); - - pointer =property_entry_find (props, propname, length); -if (IS_ERR (pointer)) -return PTR_ERR (pointer); - -memcpy (values, pointer, length); -return 0 ; -} - -static int property_entry_read_u16_array (const struct property_entry *props, -const char *propname, -u16 *values,size_t nval) -{ -const void *pointer; -size_t length = nval *sizeof (*values); - - pointer =property_entry_find (props, propname, length); -if (IS_ERR (pointer)) -return PTR_ERR (pointer); - -memcpy (values, pointer, length); -return 0 ; -} - -static int property_entry_read_u32_array (const struct property_entry *props, -const char *propname, -u32 *values,size_t nval) -{ -const void *pointer; -size_t length = nval *sizeof (*values); - - pointer =property_entry_find (props, propname, length); -if (IS_ERR (pointer)) -return PTR_ERR (pointer); - -memcpy (values, pointer, length); -return 0 ; -} - -static int property_entry_read_u64_array (const struct property_entry *props, -const char *propname, -u64 *values,size_t nval) -{ -const void *pointer; -size_t length = nval *sizeof (*values); - - pointer =property_entry_find (props, propname, length); -if (IS_ERR (pointer)) -return PTR_ERR (pointer); - -memcpy (values, pointer, length); -return 0 ; -} -static int property_entry_count_elems_of_size (const struct property_entry *props,const char *propname,size_t length)
@@ -209,21 +149,24 @@ static int property_entry_read_int_array(const struct property_entry *props, unsigned int elem_size, void *val, size_t nval) { + const void *pointer; +size_t length; +if (!val)return property_entry_count_elems_of_size (props, name, elem_size); -switch (elem_size) { -case sizeof (u8): -return property_entry_read_u8_array (props, name, val, nval); -case sizeof (u16): -return property_entry_read_u16_array (props, name, val, nval); -case sizeof (u32): -return property_entry_read_u32_array (props, name, val, nval); -case sizeof (u64): -return property_entry_read_u64_array (props, name, val, nval); - } -return -ENXIO ; +if (!is_power_of_2 (elem_size) || elem_size >sizeof (u64)) +return -ENXIO ; + + length = nval * elem_size; + + pointer =property_entry_find (props, name, length); +if (IS_ERR (pointer)) +return PTR_ERR (pointer); + +memcpy (val, pointer, length); +return 0 ; } static int property_entry_read_string_array(const struct property_entry *props,
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 8/15 software node: unify PROPERTY_ENTRY_XXX macros
In reply to Dmitry TorokhovWe can unify string properties initializer macros with integer initializers.
--- include/linux/property.h | 64 +++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 37 deletions(-)
include/linux/property.h +27 -37
@@ -250,37 +250,33 @@ struct property_entry { };/* -* Note: the below four initializers for the anonymous union are carefully +* Note: the below initializers for the anonymous union are carefully * crafted to avoid gcc-4.4.4's problems with initialization of anon unions * and structs. */ -#define __PROPERTY_ENTRY_ARRAY_LEN (_name_, _type_, _Type_, _val_, _len_)\ +#define __PROPERTY_ENTRY_ELEMENT_SIZE (_elem_) \ + sizeof(((struct property_entry *)NULL)->value._elem_) + +#define __PROPERTY_ENTRY_ARRAY_LEN (_name_, _elem_, _Type_, _val_, _len_)\ (struct property_entry) { \ .name = _name_, \ - .length = (_len_) * sizeof(_type_), \ + .length = (_len_) * __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_), \ .is_array = true, \ .type = DEV_PROP_##_Type_, \ { .pointer = _val_ }, \ }#define PROPERTY_ENTRY_U8_ARRAY_LEN (_name_, _val_, _len_) \ - __PROPERTY_ENTRY_ARRAY_LEN(_name_, u8, U8, _val_, _len_) + __PROPERTY_ENTRY_ARRAY_LEN(_name_, u8_data, U8, _val_, _len_)#define PROPERTY_ENTRY_U16_ARRAY_LEN (_name_, _val_, _len_) \ - __PROPERTY_ENTRY_ARRAY_LEN(_name_, u16, U16, _val_, _len_) + __PROPERTY_ENTRY_ARRAY_LEN(_name_, u16_data, U16, _val_, _len_)#define PROPERTY_ENTRY_U32_ARRAY_LEN (_name_, _val_, _len_) \ - __PROPERTY_ENTRY_ARRAY_LEN(_name_, u32, U32, _val_, _len_) + __PROPERTY_ENTRY_ARRAY_LEN(_name_, u32_data, U32, _val_, _len_)#define PROPERTY_ENTRY_U64_ARRAY_LEN (_name_, _val_, _len_) \ - __PROPERTY_ENTRY_ARRAY_LEN(_name_, u64, U64, _val_, _len_) - + __PROPERTY_ENTRY_ARRAY_LEN(_name_, u64_data, U64, _val_, _len_)#define PROPERTY_ENTRY_STRING_ARRAY_LEN (_name_, _val_, _len_) \ -(struct property_entry) { \ - .name = _name_, \ - .length = (_len_) * sizeof(const char *), \ - .is_array = true, \ - .type = DEV_PROP_STRING, \ - { .pointer = _val_ }, \ -} + __PROPERTY_ENTRY_ARRAY_LEN(_name_, str, STRING, _val_, _len_)#define PROPERTY_ENTRY_U8_ARRAY (_name_, _val_) \ PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
@@ -293,30 +289,24 @@ struct property_entry {#define PROPERTY_ENTRY_STRING_ARRAY (_name_, _val_) \ PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) -#define __PROPERTY_ENTRY_INTEGER (_name_, _type_, _Type_, _val_) \ -(struct property_entry) { \ - .name = _name_, \ - .length = sizeof(_type_), \ - .type = DEV_PROP_##_Type_, \ - { .value = { ._type_##_data = _val_ } }, \ +#define __PROPERTY_ENTRY_ELEMENT (_name_, _elem_, _Type_, _val_) \ +(struct property_entry) { \ + .name = _name_, \ + .length = __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_), \ + .type = DEV_PROP_##_Type_, \ + { .value = { ._elem_ = _val_ } }, \ } -#define PROPERTY_ENTRY_U8 (_name_, _val_) \ - __PROPERTY_ENTRY_INTEGER(_name_, u8, U8, _val_) -#define PROPERTY_ENTRY_U16 (_name_, _val_) \ - __PROPERTY_ENTRY_INTEGER(_name_, u16, U16, _val_) -#define PROPERTY_ENTRY_U32 (_name_, _val_) \ - __PROPERTY_ENTRY_INTEGER(_name_, u32, U32, _val_) -#define PROPERTY_ENTRY_U64 (_name_, _val_) \ - __PROPERTY_ENTRY_INTEGER(_name_, u64, U64, _val_) - -#define PROPERTY_ENTRY_STRING (_name_, _val_) \ -(struct property_entry) { \ - .name = _name_, \ - .length = sizeof(const char *), \ - .type = DEV_PROP_STRING, \ - { .value = { .str = _val_ } }, \ -} +#define PROPERTY_ENTRY_U8 (_name_, _val_) \ + __PROPERTY_ENTRY_ELEMENT(_name_, u8_data, U8, _val_) +#define PROPERTY_ENTRY_U16 (_name_, _val_) \ + __PROPERTY_ENTRY_ELEMENT(_name_, u16_data, U16, _val_) +#define PROPERTY_ENTRY_U32 (_name_, _val_) \ + __PROPERTY_ENTRY_ELEMENT(_name_, u32_data, U32, _val_) +#define PROPERTY_ENTRY_U64 (_name_, _val_) \ + __PROPERTY_ENTRY_ELEMENT(_name_, u64_data, U64, _val_) +#define PROPERTY_ENTRY_STRING (_name_, _val_) \ + __PROPERTY_ENTRY_ELEMENT(_name_, str, STRING, _val_)#define PROPERTY_ENTRY_BOOL (_name_) \ (struct property_entry) { \
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 9/15 software node: simplify property_entry_read_string_array()
In reply to Dmitry TorokhovThere is no need to treat string arrays and single strings separately, we can go exclusively by the element length in relation to data type size.
--- drivers/base/swnode.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-)
drivers/base/swnode.c +7 -14
@@ -173,28 +173,21 @@ static int property_entry_read_string_array(const struct property_entry *props,const char *propname, const char **strings, size_t nval) { - const struct property_entry *prop; const void *pointer; -size_t array_len, length; +size_t length; +int array_len;/* Find out the array length. */ - prop =property_entry_get (props, propname); -if (!prop) -return -EINVAL ; - -if (prop->is_array) -/* Find the length of an array. */ - array_len =property_entry_count_elems_of_size (props, propname, -sizeof (const char *)); -else -/* The array length for a non-array string property is 1. */ - array_len =1 ; + array_len =property_entry_count_elems_of_size (props, propname, +sizeof (const char *)); +if (array_len <0 ) +return array_len;/* Return how many there are if strings is NULL. */ if (!strings)return array_len; - array_len =min (nval, array_len); + array_len =min_t (size_t, nval, array_len); length = array_len *sizeof (*strings); pointer =property_entry_find (props, propname, length);
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 10/15 software node: rename is_array to is_inline
In reply to Dmitry TorokhovWe do not need a special flag to know if we are dealing with an array, as we can get that data from ratio between element length and the data size, however we do need a flag to know whether the data is stored directly inside property_entry or separately.
--- drivers/base/swnode.c | 12 +++++------- include/linux/property.h | 13 ++++++++----- 2 files changed, 13 insertions(+), 12 deletions(-)
drivers/base/swnode.c +5 -7
@@ -108,10 +108,7 @@ static const void *property_get_pointer(const struct property_entry *prop)if (!prop->length)return NULL ; -if (prop->is_array) -return prop->pointer; - -return &prop->value; +return prop->is_inline ? &prop->value : prop->pointer; } static const void *property_entry_find(const struct property_entry *props,
@@ -205,7 +202,7 @@ static void property_entry_free_data(const struct property_entry *p)const char *const *src_str;size_t i, nval; -if (p->is_array) { +if (!p->is_inline) {if (p->type ==DEV_PROP_STRING && p->pointer) { src_str = p->pointer; nval = p->length /sizeof (const char *);
@@ -250,7 +247,7 @@ static int property_entry_copy_data(struct property_entry *dst,const void *pointer =property_get_pointer (src);const void *new; -if (src->is_array) { +if (!src->is_inline) {if (!src->length)return -ENODATA ;
@@ -264,15 +261,16 @@ static int property_entry_copy_data(struct property_entry *dst,return -ENOMEM ; } - dst->is_array = true; dst->pointer = new; }else if (src->type ==DEV_PROP_STRING ) { new =kstrdup (src->value.str,GFP_KERNEL );if (!new && src->value.str)return -ENOMEM ; + dst->is_inline = true; dst->value.str = new; }else { + dst->is_inline = true; dst->value = src->value; }
include/linux/property.h +8 -5
@@ -227,15 +227,17 @@ static inline int fwnode_property_count_u64(const struct fwnode_handle *fwnode,* struct property_entry - "Built-in" device property representation. * @name: Name of the property. * @length: Length of data making up the value. -* @is_array: True when the property is an array. +* @is_inline: True when the property value is embedded in +* &struct property_entry instance. * @type: Type of the data in unions. -* @pointer: Pointer to the property (an array of items of the given type). -* @value: Value of the property (when it is a single item of the given type). +* @pointer: Pointer to the property when it is stored separately from +* the &struct property_entry instance. +* @value: Value of the property when it is stored inline. */ struct property_entry {const char *name;size_t length; -bool is_array; +bool is_inline;enum dev_prop_type type;union {const void *pointer;
@@ -262,7 +264,6 @@ struct property_entry { (struct property_entry ) { \ .name = _name_, \ .length = (_len_) *__PROPERTY_ENTRY_ELEMENT_SIZE (_elem_), \ - .is_array = true, \ .type = DEV_PROP_##_Type_, \ { .pointer = _val_ }, \ }
@@ -293,6 +294,7 @@ struct property_entry { (struct property_entry ) { \ .name = _name_, \ .length =__PROPERTY_ENTRY_ELEMENT_SIZE (_elem_), \ + .is_inline = true, \ .type = DEV_PROP_##_Type_, \ { .value = { ._elem_ = _val_ } }, \ }
@@ -311,6 +313,7 @@ struct property_entry {#define PROPERTY_ENTRY_BOOL (_name_) \ (struct property_entry) { \ .name = _name_, \ + .is_inline = true, \ } struct property_entry *
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 11/15 software node: move small properties inline when copying
In reply to Dmitry TorokhovWhen copying/duplicating set of properties, move smaller properties that were stored separately directly inside property entry structures. We can move:
- up to 8 bytes from U8 arrays
- up to 4 words
- up to 2 double words
- one U64 value
- one or 2 strings.
--- drivers/base/swnode.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/base/swnode.c +10 -0
@@ -280,6 +280,16 @@ static int property_entry_copy_data(struct property_entry *dst,if (!dst->name) goto out_free_data; +if (!dst->is_inline && dst->length <=sizeof (dst->value)) { +/* We have an opportunity to move the data inline */ +const void *tmp = dst->pointer; + +memcpy (&dst->value, tmp, dst->length); + dst->is_inline = true; + +kfree (tmp); + } +return 0 ; out_free_data:
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
Re: [PATCH v6 11/15] software node: move small properties inline when copying
Quoted 9 lines · CET Dmitry Torokhov
When copying/duplicating set of properties, move smaller properties that were stored separately directly inside property entry structures. We can move:
- up to 8 bytes from U8 arrays
- up to 4 words
- up to 2 double words
- one U64 value
- one or 2 strings.
Yes, we can do that, but how much of a difference does this really make?
Also, how can one distinguish between a single-value property and an inline array which this change? By looking at the length?
Quoted 11 lines
Signed-off-by Dmitry Torokhov <[email protected]>--- drivers/base/swnode.c | 10 ++++++++++ 1 file changed, 10 insertions(+)drivers/base/swnode.c +0
-0@@ -280,6 +280,16 @@ static int property_entry_copy_data(struct property_entry *dst,if (!dst->name)
drivers/base/swnode.c static int property_entry_copy_data(struct property_entry *dst, · line 290
Quoted 10 lines
drivers/base/swnode.c +8
-0goto out_free_data; +if (!dst->is_inline && dst->length <=sizeof (dst->value)) { +/* We have an opportunity to move the data inline */ +const void *tmp = dst->pointer; + +memcpy (&dst->value, tmp, dst->length); + dst->is_inline = true; + +kfree (tmp);
This would have been more useful if we had been able to avoid making the allocation altogether.
Quoted 6 lines
drivers/base/swnode.c +2
-0+ } +return 0 ; out_free_data:
Re: [PATCH v6 11/15] software node: move small properties inline when copying
Hi Rafael,
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · CET Dmitry Torokhov
When copying/duplicating set of properties, move smaller properties that were stored separately directly inside property entry structures. We can move:
Quoted 7 lines
Quoted 5 lines
- up to 8 bytes from U8 arrays
- up to 4 words
- up to 2 double words
- one U64 value
- one or 2 strings.Yes, we can do that, but how much of a difference does this really make?
Arguably not much I think, but it was pretty cheap to do.
Quoted 3 lines
Also, how can one distinguish between a single-value property and an inline array which this change? By looking at the length?
We do not really need to distinguish between the 2. The device properties API is typically wrap single values around arrays (i.e. it is perfectly fine to use scalar API to fetch first element of array and use array API to fetch a scalar). So we have property of certain type with certain number of elements, and it can either be stored inside property_entry structure, or outside of it. They are 2 orthogonal concepts.
Quoted 14 lines
Quoted 14 lines
Signed-off-by Dmitry Torokhov <[email protected]>--- drivers/base/swnode.c | 10 ++++++++++ 1 file changed, 10 insertions(+)drivers/base/swnode.c +0
-0@@ -280,6 +280,16 @@ static int property_entry_copy_data(struct property_entry *dst,if (!dst->name) goto out_free_data;
Quoted 11 lines
drivers/base/swnode.c static int property_entry_copy_data(struct property_entry *dst, · line 290
Quoted 8 lines
drivers/base/swnode.c +8
-0+if (!dst->is_inline && dst->length <=sizeof (dst->value)) { +/* We have an opportunity to move the data inline */ +const void *tmp = dst->pointer; + +memcpy (&dst->value, tmp, dst->length); + dst->is_inline = true; + +kfree (tmp);This would have been more useful if we had been able to avoid making the allocation altogether.
OK, I can do that and re-send this patch and the one with the tests. In the mean time, can you please consider patches 12-14? They can be applied even if you temporarily drop this one (#11).
Thanks.
Signature · 1 line
Dmitry
Re: [PATCH v6 11/15] software node: move small properties inline when copying
Quoted 56 lines · CET Dmitry Torokhov
Hi Rafael,
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · CET Dmitry Torokhov
When copying/duplicating set of properties, move smaller properties that were stored separately directly inside property entry structures. We can move:
Quoted 7 lines
Quoted 5 lines
- up to 8 bytes from U8 arrays
- up to 4 words
- up to 2 double words
- one U64 value
- one or 2 strings.Yes, we can do that, but how much of a difference does this really make?
Arguably not much I think, but it was pretty cheap to do.
Quoted 3 lines
Also, how can one distinguish between a single-value property and an inline array which this change? By looking at the length?
We do not really need to distinguish between the 2. The device properties API is typically wrap single values around arrays (i.e. it is perfectly fine to use scalar API to fetch first element of array and use array API to fetch a scalar). So we have property of certain type with certain number of elements, and it can either be stored inside
property_entrystructure, or outside of it. They are 2 orthogonal concepts.Quoted 14 lines
Quoted 14 lines
Signed-off-by Dmitry Torokhov <[email protected]>--- drivers/base/swnode.c | 10 ++++++++++ 1 file changed, 10 insertions(+)drivers/base/swnode.c +0
-0@@ -280,6 +280,16 @@ static int property_entry_copy_data(struct property_entry *dst,if (!dst->name) goto out_free_data;Quoted 11 lines
drivers/base/swnode.c static int property_entry_copy_data(struct property_entry *dst, · line 290
Quoted 8 lines
drivers/base/swnode.c +8
-0+if (!dst->is_inline && dst->length <=sizeof (dst->value)) { +/* We have an opportunity to move the data inline */ +const void *tmp = dst->pointer; + +memcpy (&dst->value, tmp, dst->length); + dst->is_inline = true; + +kfree (tmp);This would have been more useful if we had been able to avoid making the allocation altogether.
Quoted 1 line
OK, I can do that and re-send this patch and the one with the tests.
But if you do that, IMO it would be prudent to extend the definition of struct property_entry like this:
struct property_entry {
const char *name;
size_t length;
bool is_array;
enum dev_prop_type type;
union {
union {
const u8 *u8_data;
const u16 *u16_data;
const u32 *u32_data;
const u64 *u64_data;
const char * const *str;
} pointer;
union {
u8 u8_data;
u16 u16_data;
u32 u32_data;
u64 u64_data;
const char *str;
+ u8 u8_buf[sizeof(u64)];
+ u16 u16_buf[sizeof(u64)/sizeof(u16)];
+ u32 u32_buf[sizeof(u64)/sizeof(u32)];
+ char char_buf[sizeof(u64)];
} value;
};
};
to make it clear that the value field is going to be used as an array in some cases.
Quoted 1 line
In the mean time, can you please consider patches 12-14?
I cannot find drivers/platform/x86/intel_cht_int33fe_typec.c in the mainline, so I cannot apply patch [13/15] now and I'm not sure how useful it would be to apply patches [10,12/15] without the other two.
Re: [PATCH v6 11/15] software node: move small properties inline when copying
Quoted 89 lines · Rafael J. Wysocki
Quoted 56 lines · CET Dmitry Torokhov
Hi Rafael,
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · CET Dmitry Torokhov
When copying/duplicating set of properties, move smaller properties that were stored separately directly inside property entry structures. We can move:
Quoted 7 lines
Quoted 5 lines
- up to 8 bytes from U8 arrays
- up to 4 words
- up to 2 double words
- one U64 value
- one or 2 strings.Yes, we can do that, but how much of a difference does this really make?
Arguably not much I think, but it was pretty cheap to do.
Quoted 3 lines
Also, how can one distinguish between a single-value property and an inline array which this change? By looking at the length?
We do not really need to distinguish between the 2. The device properties API is typically wrap single values around arrays (i.e. it is perfectly fine to use scalar API to fetch first element of array and use array API to fetch a scalar). So we have property of certain type with certain number of elements, and it can either be stored inside
property_entrystructure, or outside of it. They are 2 orthogonal concepts.Quoted 14 lines
Quoted 14 lines
Signed-off-by Dmitry Torokhov <[email protected]>--- drivers/base/swnode.c | 10 ++++++++++ 1 file changed, 10 insertions(+)drivers/base/swnode.c +0
-0@@ -280,6 +280,16 @@ static int property_entry_copy_data(struct property_entry *dst,if (!dst->name) goto out_free_data;Quoted 11 lines
drivers/base/swnode.c static int property_entry_copy_data(struct property_entry *dst, · line 290
Quoted 8 lines
drivers/base/swnode.c +8
-0+if (!dst->is_inline && dst->length <=sizeof (dst->value)) { +/* We have an opportunity to move the data inline */ +const void *tmp = dst->pointer; + +memcpy (&dst->value, tmp, dst->length); + dst->is_inline = true; + +kfree (tmp);This would have been more useful if we had been able to avoid making the allocation altogether.
Quoted 1 line
OK, I can do that and re-send this patch and the one with the tests.
But if you do that, IMO it would be prudent to extend the definition of struct
property_entrylike this:struct
property_entry{(quoted diff) +4
-0const char *name; size_t length; bool is_array; enum dev_prop_type type; union { union { const u8 *u8_data; const u16 *u16_data; const u32 *u32_data; const u64 *u64_data; const char * const *str; } pointer; union { u8 u8_data; u16 u16_data; u32 u32_data; u64 u64_data; const char *str; + u8 u8_buf[sizeof(u64)]; + u16 u16_buf[sizeof(u64)/sizeof(u16)]; + u32 u32_buf[sizeof(u64)/sizeof(u32)]; + char char_buf[sizeof(u64)]; } value; }; };
Quoted 2 lines
to make it clear that the value field is going to be used as an array in some cases.
Sorry, just sent out updated series before receiving your email. I can cook up new patch cleaning this. I think we can drop scalars and only have arrays and have initializers use <type>_data[0] to create initial property entries.
Quoted 6 lines
Quoted 2 lines
In the mean time, can you please consider patches 12-14?
I cannot find
drivers/platform/x86/intel_cht_int33fe_typec.cin the mainline, so I cannot apply patch [13/15] now and I'm not sure how useful it would be to apply patches [10,12/15] without the other two.
Hmm, drivers/platform/x86/intel_cht_int33fe_typec.c used to be drivers/platform/x86/intel_cht_int33fe.c I think.
I can either regenerate against your tree instead of -next (but then there will be merge conflict) or we could postpone #13 and #14 (or #5 and #6 in v7) till after merge window.
Please let me know.
Signature · 1 line
Dmitry
Re: [PATCH v6 11/15] software node: move small properties inline when copying
Quoted 90 lines · CET Dmitry Torokhov
Quoted 89 lines · Rafael J. Wysocki
Quoted 56 lines · CET Dmitry Torokhov
Hi Rafael,
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · CET Dmitry Torokhov
When copying/duplicating set of properties, move smaller properties that were stored separately directly inside property entry structures. We can move:
Quoted 7 lines
Quoted 5 lines
- up to 8 bytes from U8 arrays
- up to 4 words
- up to 2 double words
- one U64 value
- one or 2 strings.Yes, we can do that, but how much of a difference does this really make?
Arguably not much I think, but it was pretty cheap to do.
Quoted 3 lines
Also, how can one distinguish between a single-value property and an inline array which this change? By looking at the length?
We do not really need to distinguish between the 2. The device properties API is typically wrap single values around arrays (i.e. it is perfectly fine to use scalar API to fetch first element of array and use array API to fetch a scalar). So we have property of certain type with certain number of elements, and it can either be stored inside
property_entrystructure, or outside of it. They are 2 orthogonal concepts.Quoted 14 lines
Quoted 14 lines
Signed-off-by Dmitry Torokhov <[email protected]>--- drivers/base/swnode.c | 10 ++++++++++ 1 file changed, 10 insertions(+)drivers/base/swnode.c +0
-0@@ -280,6 +280,16 @@ static int property_entry_copy_data(struct property_entry *dst,if (!dst->name) goto out_free_data;Quoted 11 lines
drivers/base/swnode.c static int property_entry_copy_data(struct property_entry *dst, · line 290
Quoted 8 lines
drivers/base/swnode.c +8
-0+if (!dst->is_inline && dst->length <=sizeof (dst->value)) { +/* We have an opportunity to move the data inline */ +const void *tmp = dst->pointer; + +memcpy (&dst->value, tmp, dst->length); + dst->is_inline = true; + +kfree (tmp);This would have been more useful if we had been able to avoid making the allocation altogether.
Quoted 1 line
OK, I can do that and re-send this patch and the one with the tests.
But if you do that, IMO it would be prudent to extend the definition of struct
property_entrylike this:struct
property_entry{(quoted diff) +4
-0const char *name; size_t length; bool is_array; enum dev_prop_type type; union { union { const u8 *u8_data; const u16 *u16_data; const u32 *u32_data; const u64 *u64_data; const char * const *str; } pointer; union { u8 u8_data; u16 u16_data; u32 u32_data; u64 u64_data; const char *str; + u8 u8_buf[sizeof(u64)]; + u16 u16_buf[sizeof(u64)/sizeof(u16)]; + u32 u32_buf[sizeof(u64)/sizeof(u32)]; + char char_buf[sizeof(u64)]; } value; }; };
Quoted 5 lines
Quoted 2 lines
to make it clear that the value field is going to be used as an array in some cases.
Sorry, just sent out updated series before receiving your email. I can cook up new patch cleaning this.
I'd prefer a new version of the series, honestly.
Quoted 2 lines
I think we can drop scalars and only have arrays and have initializers use <type>_data[0] to create initial property entries.
Why [0]? IMO it is better to use the exact size (which is known) in this particular case.
Also note that u64 is naturally a scalar only.
Quoted 7 lines
Quoted 6 lines
Quoted 2 lines
In the mean time, can you please consider patches 12-14?
I cannot find
drivers/platform/x86/intel_cht_int33fe_typec.cin the mainline, so I cannot apply patch [13/15] now and I'm not sure how useful it would be to apply patches [10,12/15] without the other two.
Quoted 8 lines
Hmm,
drivers/platform/x86/intel_cht_int33fe_typec.cused to bedrivers/platform/x86/intel_cht_int33fe.cI think.I can either regenerate against your tree instead of -next (but then there will be merge conflict) or we could postpone #13 and #14 (or #5 and #6 in v7) till after merge window.
Please let me know.
I'd rather postpone the whole series to until the dependencies are in, which may be during the merge window (e.g. if this happens during the first week of it, waiting for another extra week just for the merge window to end is not quite useful IMO).
Re: [PATCH v6 11/15] software node: move small properties inline when copying
Quoted 91 lines · Rafael J. Wysocki
Quoted 90 lines · CET Dmitry Torokhov
Quoted 89 lines · Rafael J. Wysocki
Quoted 56 lines · CET Dmitry Torokhov
Hi Rafael,
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · CET Dmitry Torokhov
When copying/duplicating set of properties, move smaller properties that were stored separately directly inside property entry structures. We can move:
Quoted 7 lines
Quoted 5 lines
- up to 8 bytes from U8 arrays
- up to 4 words
- up to 2 double words
- one U64 value
- one or 2 strings.Yes, we can do that, but how much of a difference does this really make?
Arguably not much I think, but it was pretty cheap to do.
Quoted 3 lines
Also, how can one distinguish between a single-value property and an inline array which this change? By looking at the length?
We do not really need to distinguish between the 2. The device properties API is typically wrap single values around arrays (i.e. it is perfectly fine to use scalar API to fetch first element of array and use array API to fetch a scalar). So we have property of certain type with certain number of elements, and it can either be stored inside
property_entrystructure, or outside of it. They are 2 orthogonal concepts.Quoted 14 lines
Quoted 14 lines
Signed-off-by Dmitry Torokhov <[email protected]>--- drivers/base/swnode.c | 10 ++++++++++ 1 file changed, 10 insertions(+)drivers/base/swnode.c +0
-0@@ -280,6 +280,16 @@ static int property_entry_copy_data(struct property_entry *dst,if (!dst->name) goto out_free_data;Quoted 11 lines
drivers/base/swnode.c static int property_entry_copy_data(struct property_entry *dst, · line 290
Quoted 8 lines
drivers/base/swnode.c +8
-0+if (!dst->is_inline && dst->length <=sizeof (dst->value)) { +/* We have an opportunity to move the data inline */ +const void *tmp = dst->pointer; + +memcpy (&dst->value, tmp, dst->length); + dst->is_inline = true; + +kfree (tmp);This would have been more useful if we had been able to avoid making the allocation altogether.
Quoted 1 line
OK, I can do that and re-send this patch and the one with the tests.
But if you do that, IMO it would be prudent to extend the definition of struct
property_entrylike this:struct
property_entry{(quoted diff) +4
-0const char *name; size_t length; bool is_array; enum dev_prop_type type; union { union { const u8 *u8_data; const u16 *u16_data; const u32 *u32_data; const u64 *u64_data; const char * const *str; } pointer; union { u8 u8_data; u16 u16_data; u32 u32_data; u64 u64_data; const char *str; + u8 u8_buf[sizeof(u64)]; + u16 u16_buf[sizeof(u64)/sizeof(u16)]; + u32 u32_buf[sizeof(u64)/sizeof(u32)]; + char char_buf[sizeof(u64)]; } value; }; };
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
to make it clear that the value field is going to be used as an array in some cases.
Sorry, just sent out updated series before receiving your email. I can cook up new patch cleaning this.
I'd prefer a new version of the series, honestly.
OK, sure.
Quoted 6 lines
Quoted 3 lines
I think we can drop scalars and only have arrays and have initializers use <type>_data[0] to create initial property entries.
Why [0]? IMO it is better to use the exact size (which is known) in this particular case.
include/linux/property.h +7 -7
@@ -257,11 +257,11 @@ struct property_entry {union {const void *pointer;union { -u8 u8_data; -u16 u16_data; -u32 u32_data; -u64 u64_data; -const char *str; +u8 u8_data[sizeof (u64) /sizeof (u8)]; +u16 u16_data[sizeof (u64) /sizeof (u16)]; +u32 u32_data[sizeof (u64) /sizeof (u32)]; +u64 u64_data[sizeof (u64) /sizeof (u64)]; +const char *str[sizeof (u64) /sizeof (char *)]; } value; }; };
@@ -273,7 +273,7 @@ struct property_entry {*/ #define __PROPERTY_ENTRY_ELEMENT_SIZE (_elem_) \ - sizeof(((struct property_entry *)NULL)->value._elem_) + sizeof(((struct property_entry *)NULL)->value._elem_[0])#define __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN (_name_, _elsize_, _Type_, \ _val_, _len_) \
@@ -323,7 +323,7 @@ struct property_entry { .length = __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_), \ .is_inline = true, \ .type = DEV_PROP_##_Type_, \ - { .value = { ._elem_ = _val_ } }, \ + { .value = { ._elem_[0] = _val_ } }, \ }#define PROPERTY_ENTRY_U8 (_name_, _val_) \
Quoted 2 lines
Also note that u64 is naturally a scalar only.
It still can be expressed as array of 1 element.
Quoted 15 lines
Quoted 15 lines
Quoted 7 lines
Quoted 3 lines
In the mean time, can you please consider patches 12-14?
I cannot find
drivers/platform/x86/intel_cht_int33fe_typec.cin the mainline, so I cannot apply patch [13/15] now and I'm not sure how useful it would be to apply patches [10,12/15] without the other two.Hmm,
drivers/platform/x86/intel_cht_int33fe_typec.cused to bedrivers/platform/x86/intel_cht_int33fe.cI think.I can either regenerate against your tree instead of -next (but then there will be merge conflict) or we could postpone #13 and #14 (or #5 and #6 in v7) till after merge window.
Quoted 6 lines
Quoted 1 line
Please let me know.
I'd rather postpone the whole series to until the dependencies are in, which may be during the merge window (e.g. if this happens during the first week of it, waiting for another extra week just for the merge window to end is not quite useful IMO).
Hmm, OK, but I am not sure why we can't apply new functionality now and get cleanup patches in afterwards...
Thanks.
Signature · 1 line
Dmitry
Re: [PATCH v6 11/15] software node: move small properties inline when copying
Quoted 116 lines · CET Dmitry Torokhov
Quoted 91 lines · Rafael J. Wysocki
Quoted 90 lines · CET Dmitry Torokhov
Quoted 89 lines · Rafael J. Wysocki
Quoted 56 lines · CET Dmitry Torokhov
Hi Rafael,
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · CET Dmitry Torokhov
When copying/duplicating set of properties, move smaller properties that were stored separately directly inside property entry structures. We can move:
Quoted 7 lines
Quoted 5 lines
- up to 8 bytes from U8 arrays
- up to 4 words
- up to 2 double words
- one U64 value
- one or 2 strings.Yes, we can do that, but how much of a difference does this really make?
Arguably not much I think, but it was pretty cheap to do.
Quoted 3 lines
Also, how can one distinguish between a single-value property and an inline array which this change? By looking at the length?
We do not really need to distinguish between the 2. The device properties API is typically wrap single values around arrays (i.e. it is perfectly fine to use scalar API to fetch first element of array and use array API to fetch a scalar). So we have property of certain type with certain number of elements, and it can either be stored inside
property_entrystructure, or outside of it. They are 2 orthogonal concepts.Quoted 14 lines
Quoted 14 lines
Signed-off-by Dmitry Torokhov <[email protected]>--- drivers/base/swnode.c | 10 ++++++++++ 1 file changed, 10 insertions(+)drivers/base/swnode.c +0
-0@@ -280,6 +280,16 @@ static int property_entry_copy_data(struct property_entry *dst,if (!dst->name) goto out_free_data;Quoted 11 lines
drivers/base/swnode.c static int property_entry_copy_data(struct property_entry *dst, · line 290
Quoted 8 lines
drivers/base/swnode.c +8
-0+if (!dst->is_inline && dst->length <=sizeof (dst->value)) { +/* We have an opportunity to move the data inline */ +const void *tmp = dst->pointer; + +memcpy (&dst->value, tmp, dst->length); + dst->is_inline = true; + +kfree (tmp);This would have been more useful if we had been able to avoid making the allocation altogether.
Quoted 1 line
OK, I can do that and re-send this patch and the one with the tests.
But if you do that, IMO it would be prudent to extend the definition of struct
property_entrylike this:struct
property_entry{(quoted diff) +4
-0const char *name; size_t length; bool is_array; enum dev_prop_type type; union { union { const u8 *u8_data; const u16 *u16_data; const u32 *u32_data; const u64 *u64_data; const char * const *str; } pointer; union { u8 u8_data; u16 u16_data; u32 u32_data; u64 u64_data; const char *str; + u8 u8_buf[sizeof(u64)]; + u16 u16_buf[sizeof(u64)/sizeof(u16)]; + u32 u32_buf[sizeof(u64)/sizeof(u32)]; + char char_buf[sizeof(u64)]; } value; }; };Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
to make it clear that the value field is going to be used as an array in some cases.
Sorry, just sent out updated series before receiving your email. I can cook up new patch cleaning this.
I'd prefer a new version of the series, honestly.
OK, sure.
Quoted 6 lines
Quoted 3 lines
I think we can drop scalars and only have arrays and have initializers use <type>_data[0] to create initial property entries.
Why [0]? IMO it is better to use the exact size (which is known) in this particular case.
include/linux/property.h +0
-0@@ -257,11 +257,11 @@ struct property_entry {union {const void *pointer;
include/linux/property.h struct property_entry { · line 263
Quoted 10 lines
include/linux/property.h +4
-5union { -u8 u8_data; -u16 u16_data; -u32 u32_data; -u64 u64_data; -const char *str; +u8 u8_data[sizeof (u64) /sizeof (u8)]; +u16 u16_data[sizeof (u64) /sizeof (u16)]; +u32 u32_data[sizeof (u64) /sizeof (u32)]; +u64 u64_data[sizeof (u64) /sizeof (u64)];
IMO with a scalar u64 this kind of would explain itself, but with a u64 array it becomes somewhat confusing.
Quoted 24 lines
include/linux/property.h +3
-2+const char *str[sizeof (u64) /sizeof (char *)]; } value; }; };@@ -273,7 +273,7 @@ struct property_entry {*/ #define __PROPERTY_ENTRY_ELEMENT_SIZE (_elem_) \ - sizeof(((struct property_entry *)NULL)->value._elem_) + sizeof(((struct property_entry *)NULL)->value._elem_[0])#define __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN (_name_, _elsize_, _Type_, \ _val_, _len_) \@@ -323,7 +323,7 @@ struct property_entry { .length = __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_), \ .is_inline = true, \ .type = DEV_PROP_##_Type_, \ - { .value = { ._elem_ = _val_ } }, \ + { .value = { ._elem_[0] = _val_ } }, \ }#define PROPERTY_ENTRY_U8 (_name_, _val_) \Quoted 2 lines
Quoted 3 lines
Quoted 1 line
Also note that u64 is naturally a scalar only.
It still can be expressed as array of 1 element.
It can, but for what purpose?
Quoted 17 lines
Quoted 17 lines
Quoted 16 lines
Quoted 7 lines
Quoted 3 lines
In the mean time, can you please consider patches 12-14?
I cannot find
drivers/platform/x86/intel_cht_int33fe_typec.cin the mainline, so I cannot apply patch [13/15] now and I'm not sure how useful it would be to apply patches [10,12/15] without the other two.Hmm,
drivers/platform/x86/intel_cht_int33fe_typec.cused to bedrivers/platform/x86/intel_cht_int33fe.cI think.I can either regenerate against your tree instead of -next (but then there will be merge conflict) or we could postpone #13 and #14 (or #5 and #6 in v7) till after merge window.
Please let me know.
Quoted 7 lines
Quoted 4 lines
I'd rather postpone the whole series to until the dependencies are in, which may be during the merge window (e.g. if this happens during the first week of it, waiting for another extra week just for the merge window to end is not quite useful IMO).
Hmm, OK, but I am not sure why we can't apply new functionality now and get cleanup patches in afterwards...
Because that's harder to follow from the history perspective and makes no real difference in the end of the day.
Re: [PATCH v6 11/15] software node: move small properties inline when copying
Quoted 152 lines · Rafael J. Wysocki
Quoted 116 lines · CET Dmitry Torokhov
Quoted 91 lines · Rafael J. Wysocki
Quoted 90 lines · CET Dmitry Torokhov
Quoted 89 lines · Rafael J. Wysocki
Quoted 56 lines · CET Dmitry Torokhov
Hi Rafael,
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · CET Dmitry Torokhov
When copying/duplicating set of properties, move smaller properties that were stored separately directly inside property entry structures. We can move:
Quoted 7 lines
Quoted 5 lines
- up to 8 bytes from U8 arrays
- up to 4 words
- up to 2 double words
- one U64 value
- one or 2 strings.Yes, we can do that, but how much of a difference does this really make?
Arguably not much I think, but it was pretty cheap to do.
Quoted 3 lines
Also, how can one distinguish between a single-value property and an inline array which this change? By looking at the length?
We do not really need to distinguish between the 2. The device properties API is typically wrap single values around arrays (i.e. it is perfectly fine to use scalar API to fetch first element of array and use array API to fetch a scalar). So we have property of certain type with certain number of elements, and it can either be stored inside
property_entrystructure, or outside of it. They are 2 orthogonal concepts.Quoted 14 lines
Quoted 14 lines
Signed-off-by Dmitry Torokhov <[email protected]>--- drivers/base/swnode.c | 10 ++++++++++ 1 file changed, 10 insertions(+)drivers/base/swnode.c +0
-0@@ -280,6 +280,16 @@ static int property_entry_copy_data(struct property_entry *dst,if (!dst->name) goto out_free_data;Quoted 11 lines
drivers/base/swnode.c static int property_entry_copy_data(struct property_entry *dst, · line 290
Quoted 8 lines
drivers/base/swnode.c +8
-0+if (!dst->is_inline && dst->length <=sizeof (dst->value)) { +/* We have an opportunity to move the data inline */ +const void *tmp = dst->pointer; + +memcpy (&dst->value, tmp, dst->length); + dst->is_inline = true; + +kfree (tmp);This would have been more useful if we had been able to avoid making the allocation altogether.
Quoted 1 line
OK, I can do that and re-send this patch and the one with the tests.
But if you do that, IMO it would be prudent to extend the definition of struct
property_entrylike this:struct
property_entry{(quoted diff) +4
-0const char *name; size_t length; bool is_array; enum dev_prop_type type; union { union { const u8 *u8_data; const u16 *u16_data; const u32 *u32_data; const u64 *u64_data; const char * const *str; } pointer; union { u8 u8_data; u16 u16_data; u32 u32_data; u64 u64_data; const char *str; + u8 u8_buf[sizeof(u64)]; + u16 u16_buf[sizeof(u64)/sizeof(u16)]; + u32 u32_buf[sizeof(u64)/sizeof(u32)]; + char char_buf[sizeof(u64)]; } value; }; };Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
to make it clear that the value field is going to be used as an array in some cases.
Sorry, just sent out updated series before receiving your email. I can cook up new patch cleaning this.
I'd prefer a new version of the series, honestly.
OK, sure.
Quoted 6 lines
Quoted 3 lines
I think we can drop scalars and only have arrays and have initializers use <type>_data[0] to create initial property entries.
Why [0]? IMO it is better to use the exact size (which is known) in this particular case.
include/linux/property.h +0
-0@@ -257,11 +257,11 @@ struct property_entry {union {const void *pointer;include/linux/property.h struct property_entry { · line 263
Quoted 10 lines
include/linux/property.h +4
-5union { -u8 u8_data; -u16 u16_data; -u32 u32_data; -u64 u64_data; -const char *str; +u8 u8_data[sizeof (u64) /sizeof (u8)]; +u16 u16_data[sizeof (u64) /sizeof (u16)]; +u32 u32_data[sizeof (u64) /sizeof (u32)]; +u64 u64_data[sizeof (u64) /sizeof (u64)];IMO with a scalar u64 this kind of would explain itself, but with a u64 array it becomes somewhat confusing.
Quoted 21 lines
include/linux/property.h +3
-2+const char *str[sizeof (u64) /sizeof (char *)]; } value; }; };@@ -273,7 +273,7 @@ struct property_entry {*/ #define __PROPERTY_ENTRY_ELEMENT_SIZE (_elem_) \ - sizeof(((struct property_entry *)NULL)->value._elem_) + sizeof(((struct property_entry *)NULL)->value._elem_[0])#define __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN (_name_, _elsize_, _Type_, \ _val_, _len_) \@@ -323,7 +323,7 @@ struct property_entry { .length = __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_), \ .is_inline = true, \ .type = DEV_PROP_##_Type_, \ - { .value = { ._elem_ = _val_ } }, \ + { .value = { ._elem_[0] = _val_ } }, \ }
Quoted 8 lines
Quoted 6 lines
include/linux/property.h +0
-0#define PROPERTY_ENTRY_U8 (_name_, _val_) \Quoted 3 lines
Also note that u64 is naturally a scalar only.
It still can be expressed as array of 1 element.
It can, but for what purpose?
Just so we do not have to special-case handling of U64 in PROPERTY_ENTRY_Unnn() macros, as I shown in the snippet above.
Signature · 1 line
Dmitry
PATCH v6 12/15 software node: implement reference properties
In reply to Dmitry TorokhovIt is possible to store references to software nodes in the same fashion as other static properties, so that users do not need to define separate structures:
static const struct software_node gpio_bank_b_node = {
.name = "B",
};static const struct property_entry simone_key_enter_props[] = {
PROPERTY_ENTRY_U32("linux,code", KEY_ENTER),
PROPERTY_ENTRY_STRING("label", "enter"),
PROPERTY_ENTRY_REF("gpios", &gpio_bank_b_node, 123, GPIO_ACTIVE_LOW),
{ }
};--- drivers/base/swnode.c | 48 +++++++++++++++++++++++++++------ include/linux/property.h | 57 +++++++++++++++++++++++++++++----------- 2 files changed, 81 insertions(+), 24 deletions(-)
drivers/base/swnode.c +40 -8
@@ -262,6 +262,12 @@ static int property_entry_copy_data(struct property_entry *dst, } dst->pointer = new; + }else if (src->type ==DEV_PROP_REF ) { +/* +* Reference properties are never stored inline as +* they are too big. +*/ +return -EINVAL ; }else if (src->type ==DEV_PROP_STRING ) { new =kstrdup (src->value.str,GFP_KERNEL );if (!new && src->value.str)
@@ -492,21 +498,47 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode, {struct swnode *swnode =to_swnode (fwnode);const struct software_node_reference *ref; +const struct software_node_ref_args *ref_array; +const struct software_node_ref_args *ref_args;const struct property_entry *prop;struct fwnode_handle *refnode;int i; -if (!swnode || !swnode->node->references) +if (!swnode)return -ENOENT ; -for (ref = swnode->node->references; ref->name; ref++) -if (!strcmp (ref->name, propname)) -break ; + prop =property_entry_get (swnode->node->properties, propname); +if (prop) { +if (prop->type !=DEV_PROP_REF ) +return -EINVAL ; -if (!ref->name || index > (ref->nrefs -1 )) -return -ENOENT ; +/* +* We expect that references are never stored inline, even +* single ones, as they are too big. +*/ +if (prop->is_inline) +return -EINVAL ; + +if (index *sizeof (*ref_args) >= prop->length) +return -ENOENT ; + + ref_array = prop->pointer; + ref_args = &ref_array[index]; + }else { +if (!swnode->node->references) +return -ENOENT ; + +for (ref = swnode->node->references; ref->name; ref++) +if (!strcmp (ref->name, propname)) +break ; + +if (!ref->name || index > (ref->nrefs -1 )) +return -ENOENT ; + + ref_args = &ref->refs[index]; + } - refnode =software_node_fwnode (ref->refs[index].node); + refnode =software_node_fwnode (ref_args->node);if (!refnode)return -ENOENT ;
@@ -525,7 +557,7 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode, args->nargs = nargs;for (i =0 ; i < nargs; i++) - args->args[i] = ref->refs[index].args[i]; + args->args[i] = ref_args->args[i];return 0 ; }
include/linux/property.h +41 -16
105 lines not on this page · raw message
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 13/15 platform/x86: intel_cht_int33fe: use inline reference properties
In reply to Dmitry TorokhovNow that static device properties allow defining reference properties together with all other types of properties, instead of managing them separately, let's adjust the driver.
--- .../platform/x86/intel_cht_int33fe_typec.c | 81 ++++++++++--------- 1 file changed, 41 insertions(+), 40 deletions(-)
drivers/platform/x86/intel_cht_int33fe_typec.c +41 -40
@@ -36,30 +36,6 @@ enum { INT33FE_NODE_MAX, }; -static const struct software_node nodes[]; - -static const struct software_node_ref_args pi3usb30532_ref = { - &nodes[INT33FE_NODE_PI3USB30532 ] -}; - -static const struct software_node_ref_args dp_ref = { - &nodes[INT33FE_NODE_DISPLAYPORT ] -}; - -static struct software_node_ref_args mux_ref; - -static const struct software_node_reference usb_connector_refs[] = { - {"orientation-switch" ,1 , &pi3usb30532_ref}, - {"mode-switch" ,1 , &pi3usb30532_ref}, - {"displayport" ,1 , &dp_ref}, - { } -}; - -static const struct software_node_reference fusb302_refs[] = { - {"usb-role-switch" ,1 , &mux_ref}, - { } -}; -/* * Grrr I severly dislike buggy BIOS-es. At least one BIOS enumerates * the max17047 both through the INT33FE ACPI device (it is right there
@@ -95,8 +71,18 @@ static const struct property_entry max17047_props[] = { { } }; +/* +* We are not using inline property here because those are constant, +* and we need to adjust this one at runtime to point to real +* software node. +*/ +static struct software_node_ref_args fusb302_mux_refs[] = { + { .node =NULL }, +}; +static const struct property_entry fusb302_props[] = {PROPERTY_ENTRY_STRING ("linux,extcon-name" ,"cht_wcove_pwrsrc" ), +PROPERTY_ENTRY_REF_ARRAY ("usb-role-switch" , fusb302_mux_refs), { } };
@@ -112,6 +98,8 @@ static const u32 snk_pdo[] = { PDO_VAR(5000, 12000, 3000), }; +static const struct software_node nodes[]; +static const struct property_entry usb_connector_props[] = {PROPERTY_ENTRY_STRING ("data-role" ,"dual" ),PROPERTY_ENTRY_STRING ("power-role" ,"dual" ),
@@ -119,15 +107,21 @@ static const struct property_entry usb_connector_props[] = {PROPERTY_ENTRY_U32_ARRAY ("source-pdos" , src_pdo),PROPERTY_ENTRY_U32_ARRAY ("sink-pdos" , snk_pdo),PROPERTY_ENTRY_U32 ("op-sink-microwatt" ,2500000 ), +PROPERTY_ENTRY_REF ("orientation-switch" , + &nodes[INT33FE_NODE_PI3USB30532 ]), +PROPERTY_ENTRY_REF ("mode-switch" , + &nodes[INT33FE_NODE_PI3USB30532 ]), +PROPERTY_ENTRY_REF ("displayport" , + &nodes[INT33FE_NODE_DISPLAYPORT]), { } };static const struct software_node nodes[] = { - {"fusb302" ,NULL , fusb302_props, fusb302_refs }, + {"fusb302" ,NULL , fusb302_props }, {"max17047" ,NULL , max17047_props }, {"pi3usb30532" }, {"displayport" }, - {"connector" , &nodes[0 ], usb_connector_props, usb_connector_refs }, + {"connector" , &nodes[0 ], usb_connector_props }, { } };
@@ -163,9 +157,10 @@ static void cht_int33fe_remove_nodes(struct cht_int33fe_data *data) {software_node_unregister_nodes (nodes); -if (mux_ref.node) { -fwnode_handle_put (software_node_fwnode (mux_ref.node)); - mux_ref.node =NULL ; +if (fusb302_mux_refs[0 ].node) { +fwnode_handle_put ( +software_node_fwnode (fusb302_mux_refs[0 ].node)); + fusb302_mux_refs[0 ].node =NULL ; }if (data->dp) {
@@ -177,25 +172,31 @@ static void cht_int33fe_remove_nodes(struct cht_int33fe_data *data)static int cht_int33fe_add_nodes (struct cht_int33fe_data *data) { +const struct software_node *mux_ref_node;int ret; - ret =software_node_register_nodes (nodes); -if (ret) -return ret; - -/* The devices that are not created in this driver need extra steps. */ -/* * There is no ACPI device node for the USB role mux, so we need to wait * until the mux driver has created software node for the mux device. * It means we depend on the mux driver. This function will return * -EPROBE_DEFER until the mux device is registered. */ - mux_ref.node =software_node_find_by_name (NULL ,"intel-xhci-usb-sw" ); -if (!mux_ref.node) { - ret = -EPROBE_DEFER ; - goto err_remove_nodes; - } + mux_ref_node =software_node_find_by_name (NULL ,"intel-xhci-usb-sw" ); +if (!mux_ref_node) +return -EPROBE_DEFER ; + +/* +* Update node used in "usb-role-switch" property. Note that we +* rely on software_node_register_nodes() to use the original +* instance of properties instead of copying them. +*/ + fusb302_mux_refs[0 ].node = mux_ref_node; + + ret =software_node_register_nodes (nodes); +if (ret) +return ret; + +/* The devices that are not created in this driver need extra steps. */ /* * The DP connector does have ACPI device node. In this case we can just
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 14/15 software node: remove separate handling of references
In reply to Dmitry TorokhovNow that all users of references have moved to reference properties, we can remove separate handling of references.
--- drivers/base/swnode.c | 46 +++++++++++++++------------------------- include/linux/property.h | 14 ------------ 2 files changed, 17 insertions(+), 43 deletions(-)
drivers/base/swnode.c +17 -29
@@ -497,9 +497,8 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode, struct fwnode_reference_args *args) {struct swnode *swnode =to_swnode (fwnode); -const struct software_node_reference *ref;const struct software_node_ref_args *ref_array; -const struct software_node_ref_args *ref_args; +const struct software_node_ref_args *ref;const struct property_entry *prop;struct fwnode_handle *refnode;int i;
@@ -508,37 +507,26 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,return -ENOENT ; prop =property_entry_get (swnode->node->properties, propname); -if (prop) { -if (prop->type !=DEV_PROP_REF ) -return -EINVAL ; - -/* -* We expect that references are never stored inline, even -* single ones, as they are too big. -*/ -if (prop->is_inline) -return -EINVAL ; - -if (index *sizeof (*ref_args) >= prop->length) -return -ENOENT ; +if (!prop) +return -ENOENT ; - ref_array = prop->pointer; - ref_args = &ref_array[index]; - }else { -if (!swnode->node->references) -return -ENOENT ; +if (prop->type !=DEV_PROP_REF ) +return -EINVAL ; -for (ref = swnode->node->references; ref->name; ref++) -if (!strcmp (ref->name, propname)) -break ; +/* +* We expect that references are never stored inline, even +* single ones, as they are too big. +*/ +if (prop->is_inline) +return -EINVAL ; -if (!ref->name || index > (ref->nrefs -1 )) -return -ENOENT ; +if (index *sizeof (*ref) >= prop->length) +return -ENOENT ; - ref_args = &ref->refs[index]; - } + ref_array = prop->pointer; + ref = &ref_array[index]; - refnode =software_node_fwnode (ref_args->node); + refnode =software_node_fwnode (ref->node);if (!refnode)return -ENOENT ;
@@ -557,7 +545,7 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode, args->nargs = nargs;for (i =0 ; i < nargs; i++) - args->args[i] = ref_args->args[i]; + args->args[i] = ref->args[i];return 0 ; }
include/linux/property.h +0 -14
@@ -418,30 +418,16 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,/* -------------------------------------------------------------------------- */ /* Software fwnode support - when HW description is incomplete or missing */ -/** -* struct software_node_reference - Named software node reference property -* @name: Name of the property -* @nrefs: Number of elements in @refs array -* @refs: Array of references with optional arguments -*/ -struct software_node_reference { -const char *name; -unsigned int nrefs; -const struct software_node_ref_args *refs; -}; -/** * struct software_node - Software node description * @name: Name of the software node * @parent: Parent of the software node * @properties: Array of device properties -* @references: Array of software node reference properties */ struct software_node {const char *name;const struct software_node *parent;const struct property_entry *properties; -const struct software_node_reference *references; };bool is_software_node (const struct fwnode_handle *fwnode);
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
PATCH v6 15/15 software node: add basic tests for property entries
In reply to Dmitry TorokhovThis adds tests for creating software nodes with properties supplied by PROPERTY_ENTRY_XXX() macros and fetching and validating data from said nodes/properties.
We are using KUnit framework for the tests.
--- drivers/base/test/Makefile | 2 + drivers/base/test/property-entry-test.c | 472 ++++++++++++++++++++++++ 2 files changed, 474 insertions(+) create mode 100644 drivers/base/test/property-entry-test.c
drivers/base/test/Makefile +2 -0
@@ -1,2 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE) += test_async_driver_probe.o + +obj-$(CONFIG_KUNIT) += property-entry-test.o
drivers/base/test/property-entry-test.c new file +472 -0
472 lines not on this page · raw message
Signature · 1 line
2.23.0.866.gb869b98d4c-goog
Hi Rafael,
Quoted 10 lines · Dmitry Torokhov
These series implement "references" properties for software nodes as true properties, instead of managing them completely separately.
The first 10 patches are generic cleanups and consolidation and unification of the existing code; patch #11 implements moving of small properties inline when copying property entries; patch #12 implements
PROPERTY_ENTRY_REF()and friends; patch #13 converts the user of references to the property syntax, and patch #14 removes the remains of references as entities that are managed separately.
Quoted 2 lines
Patch #15 adds unit tests to verify that the handling of property entries is correct.
Do you have any concerns with the series? I think Andy did all the reviewing that he could...
Thanks!
Quoted 59 lines
Changes in v6:
- rebased onto next-20191023
- fixed patch moving small properties inline
- fixed handling boolean properties afteris_array->is_inlineconversion
- changed comments aroundis_inline"stored directly" vs embedded in one place (Andy)
- added unit tests for property entries based on KUnit framework
- added Any's reviewed-by/acked-byChanges in v5:
- rebased onto next-20191011Changes in v4:
- dealt with union aliasing concerns
- inline small properties on copyChanges in v3:
- added various cleanups before implementing reference propertiesChanges in v2:
- reworked code so that even single-entry reference properties are stored as arrays (i.e. thesoftware_node_ref_argsinstances are not part ofproperty_entrystructure) to avoid size increase. From user's POV nothing is changed, one can still usePROPERTY_ENTRY_REFmacro to define reference "inline".
- dropped unusedDEV_PROP_MAX
- rebased on linux-nextDmitry Torokhov (15):
software node: removeDEV_PROP_MAX
software node: introducePROPERTY_ENTRY_ARRAY_XXX_LEN()efi/apple-properties: usePROPERTY_ENTRY_U8_ARRAY_LENsoftware node: mark internal macros with double underscores software node: clean upproperty_copy_string_array()software node: get rid ofproperty_set_pointer()software node: removeproperty_entry_read_uNN_arrayfunctions software node: unifyPROPERTY_ENTRY_XXXmacros software node: simplifyproperty_entry_read_string_array()software node: renameis_arraytois_inline
software node: move small properties inline when copying software node: implement reference properties platform/x86:intel_cht_int33fe: use inline reference properties software node: remove separate handling of references software node: add basic tests for property entriesdrivers/base/swnode.c | 263 ++++------ drivers/base/test/Makefile | 2 + drivers/base/test/property-entry-test.c | 472 ++++++++++++++++++ drivers/firmware/efi/apple-properties.c | 18 +- .../platform/x86/intel_cht_int33fe_typec.c | 81 +-- include/linux/property.h | 178 +++---- 6 files changed, 702 insertions(+), 312 deletions(-) create mode 100644 drivers/base/test/property-entry-test.cSignature · 1 line
2.23.0.866.gb869b98d4c-goog
Signature · 1 line
Dmitry
Rafael J. Wysocki
maintainerQuoted 14 lines · Dmitry Torokhov
Hi Rafael,
Quoted 10 lines · Dmitry Torokhov
These series implement "references" properties for software nodes as true properties, instead of managing them completely separately.
The first 10 patches are generic cleanups and consolidation and unification of the existing code; patch #11 implements moving of small properties inline when copying property entries; patch #12 implements
PROPERTY_ENTRY_REF()and friends; patch #13 converts the user of references to the property syntax, and patch #14 removes the remains of references as entities that are managed separately.
Quoted 5 lines
Quoted 2 lines
Patch #15 adds unit tests to verify that the handling of property entries is correct.
Do you have any concerns with the series? I think Andy did all the reviewing that he could...
Yes, he did, and he is unconvinced.
I basically have no problems with patches [1-9/15], so I'm going to queue them up for 5.5.
Patch [10/15] by itself is kind of pointless IMO, so it'll depend on what happens to the rest.
Patch [11/15] kind of causes brows to rise, so let me reply to it directly.