From patchwork Fri Nov 8 04:22:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 11234067 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5C63F1864 for ; Fri, 8 Nov 2019 04:22:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3915421882 for ; Fri, 8 Nov 2019 04:22:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NDw2cHmq" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729846AbfKHEWe (ORCPT ); Thu, 7 Nov 2019 23:22:34 -0500 Received: from mail-pf1-f193.google.com ([209.85.210.193]:37392 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729811AbfKHEWd (ORCPT ); Thu, 7 Nov 2019 23:22:33 -0500 Received: by mail-pf1-f193.google.com with SMTP id p24so3828516pfn.4; Thu, 07 Nov 2019 20:22:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Rq+g8QX25r6FLU6mt3y3nVsMvxAZNZkHBwmo8ESYTGM=; b=NDw2cHmqwN04zwbW5gERef8wKT1c9P3lIYoOZrO07cDL1AhDow/Xu1wdBhqn1OVlxl KzdIMKK0kwbXxt/J4IF5arPd5Lwg5Bijkf7Fm2fG6GCzV5LsBy6Blbczc3wmjuLq+u+E GL39T6hDLTJpA2ikeKV3tUpWNAY7DxuCgFCztccB6Zo2oRTN4SuNgf1wvInuvepvq7mg nsdoAZkUPSHT7Gpp1lJHcmzthCu64azdohBwbPI5JnAlYNgiqGUekKbCRCjK6NgTOrEl dQgGzLtgYiK34sqlfq0gJzeddN4oTVoHXPTa3SR+kiC1VLvjRJuEFF/MU3SpFJyVaaSX VAQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Rq+g8QX25r6FLU6mt3y3nVsMvxAZNZkHBwmo8ESYTGM=; b=SOA0sEP9GbPb+56IXTUx5TemAImHSlwILhbWGpROyC60rkILH8HbfqwKawdcBLIl7a phX7UdOTHhyQ31hbbB7NQrJkCQIdEgsJje+k4Xr8CxAwksloXxFj3/kSsBL7uBdDYaO2 R6L74OZar9sJ6WgM7Vq5LG9F3S/gTEjBiq+Ox/yY688wH9ZQPpcBWMadtKK9CkKZtFMz 0SModUBPKIbtQ4yON6Wr8QWs7RncbdanQXUhPF1JaT4xWjyJFbmJ9CjnBrwVPoW+rO9i pKj2Y3pwqvd/9jeO4l05jB3bqxnjdIcErGH3rykQ7Km6HmuLDPb3u7OvGd/g3MDqRJmc 0fkg== X-Gm-Message-State: APjAAAW9qrfGlDD8AEWDNcKLT4zhX+PZ/QYmefl9KneD35CUdoIKYhoA 2r/W1k/AHcTBNZclMXiYisg= X-Google-Smtp-Source: APXvYqxqkebKeaZPHnG9p8kqvBG8olTBLJ9LTiH4tvx3nuls/eTgMX8QMjR0UUCYSVFxkcZTNHDkgw== X-Received: by 2002:a63:5125:: with SMTP id f37mr8832705pgb.98.1573186950659; Thu, 07 Nov 2019 20:22:30 -0800 (PST) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:202:201:3adc:b08c:7acc:b325]) by smtp.gmail.com with ESMTPSA id 71sm5004106pfx.107.2019.11.07.20.22.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Nov 2019 20:22:30 -0800 (PST) From: Dmitry Torokhov To: "Rafael J. Wysocki" , Heikki Krogerus Cc: Andy Shevchenko , Mika Westerberg , Linus Walleij , Ard Biesheuvel , linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, platform-driver-x86@vger.kernel.org Subject: [PATCH v8 1/6] software node: rename is_array to is_inline Date: Thu, 7 Nov 2019 20:22:20 -0800 Message-Id: <20191108042225.45391-2-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.24.0.rc1.363.gb1bccd3e3d-goog In-Reply-To: <20191108042225.45391-1-dmitry.torokhov@gmail.com> References: <20191108042225.45391-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org We 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. Signed-off-by: Dmitry Torokhov Reported-by: Marek Szyprowski Tested-by: Marek Szyprowski --- drivers/base/swnode.c | 12 +++++------- include/linux/property.h | 13 ++++++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index d8d0dc0ca5acf..18a30fb3cc588 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -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; } diff --git a/include/linux/property.h b/include/linux/property.h index 48335288c2a96..dad0ad11b55e2 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -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 * From patchwork Fri Nov 8 04:22:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 11234065 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 248571390 for ; Fri, 8 Nov 2019 04:22:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EB95321D7F for ; Fri, 8 Nov 2019 04:22:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="sIPzoQ2b" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729816AbfKHEWd (ORCPT ); Thu, 7 Nov 2019 23:22:33 -0500 Received: from mail-pl1-f195.google.com ([209.85.214.195]:41813 "EHLO mail-pl1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726219AbfKHEWd (ORCPT ); Thu, 7 Nov 2019 23:22:33 -0500 Received: by mail-pl1-f195.google.com with SMTP id d29so3169317plj.8; Thu, 07 Nov 2019 20:22:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+Jv10kn/aNQ9++wam+0EoW0JXkYl2qX0EGR6ktqlC6g=; b=sIPzoQ2bCbKnfLOBiMuSoTEaACB2MCiZ60AyCbh5gv+v5S+hf/bOzv58MzEWACIZFe /Dx4RW3CjwJu5M6pAQdkOkrBPoUhiSFrIH67jD39lWCcklN3nYn2e4lAZFjoyXkP8nXg ueXAx7ddtXog/gCt7z3z4ypkBNicflp4rDptQToHkTzhzzInEOgGTFUitUwPoAFdTiO6 Cn2yveE+nxQGu1lveZ2Mg9GiNzxoNSLJgEZ4U0iGlAfIT3Qy/w2ahU6gBvf5hoX+tDT5 cFO7t9XkZAoF3VXISf99ucEieF33GuXMrMsTsDHd9H0iXB9hU52FY0Wne8ce7ZyTq3h0 HIyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+Jv10kn/aNQ9++wam+0EoW0JXkYl2qX0EGR6ktqlC6g=; b=F2Prgj6VFs+O7zMBZdqFbWhsGG9aFcfj9MILseR44g5zVPMUmBuUFHLChAJ39tqCOc oNcGAUDFlwHdd6nch7MM435YFKOOBJeic1v4l2J6Z2or8Vm8uzV4osnTlW4ORxkJZjq9 O3HfBqoI9+hcPzz3/t3rCt12+94x8VFyZ9fxJ9ewvlnjRR1KKnZGnbXphLDa+UD0f213 08zVUjS2fait8bmk4gQCa0YGrqrDSLh9gno8KZQnAqADxChDDzWxWlkKZT3djdikdaJi RP+3ENxrJUiDpgcvV9UFq9WlZ0UCfMGDe8KBW3GSsq2h78iyiefIiEslUZ9eNFZ93G/i NQiA== X-Gm-Message-State: APjAAAVsU4MR44wHMFks8TKWVZlaQ/U6MoVGJprChFyhvkNt0pBj67In MZWkeqBMwgnxdJVUAJVwD3Q= X-Google-Smtp-Source: APXvYqwcTkYQRHf2f1MHWxSWzrJQhuumQFKoxjWWlYrIp1z3eJKgYGG+R7qZTgI3hlMNV3iUaw9OAA== X-Received: by 2002:a17:90a:e38c:: with SMTP id b12mr10444831pjz.136.1573186951558; Thu, 07 Nov 2019 20:22:31 -0800 (PST) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:202:201:3adc:b08c:7acc:b325]) by smtp.gmail.com with ESMTPSA id 71sm5004106pfx.107.2019.11.07.20.22.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Nov 2019 20:22:31 -0800 (PST) From: Dmitry Torokhov To: "Rafael J. Wysocki" , Heikki Krogerus Cc: Andy Shevchenko , Mika Westerberg , Linus Walleij , Ard Biesheuvel , linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, platform-driver-x86@vger.kernel.org Subject: [PATCH v8 2/6] software node: allow embedding of small arrays into property_entry Date: Thu, 7 Nov 2019 20:22:21 -0800 Message-Id: <20191108042225.45391-3-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.24.0.rc1.363.gb1bccd3e3d-goog In-Reply-To: <20191108042225.45391-1-dmitry.torokhov@gmail.com> References: <20191108042225.45391-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org We should not conflate whether a property data is an array or a single value with where it is stored (embedded into property_entry structure or out-of-line). All single-value properties are in effect 1-element arrays, and we can figure the amount of data stored in a property by examining its length and the data type. And arrays can be as easily stored in property entry instances as single values are, provided that we have enough space (we have up to 8 bytes). We can embed: - up to 8 bytes from U8 arrays - up to 4 words - up to 2 double words - one U64 value - one (on 64 bit architectures) or 2 (on 32 bit) strings. This change also has an effect of switching properties with small amount of data to embed it instead of keeping it separate when copying such properties. Signed-off-by: Dmitry Torokhov --- drivers/base/swnode.c | 115 +++++++++++++++++++-------------------- include/linux/property.h | 14 ++--- 2 files changed, 62 insertions(+), 67 deletions(-) diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index 18a30fb3cc588..3d422918a53d9 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -198,93 +198,84 @@ 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_inline) { - 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(src_str[i]); - } - kfree(pointer); - } else if (p->type == DEV_PROP_STRING) { - kfree(p->value.str); + if (p->type == DEV_PROP_STRING) { + src_str = property_get_pointer(p); + nval = p->length / sizeof(*src_str); + for (i = 0; i < nval; i++) + kfree(src_str[i]); } + + if (!p->is_inline) + kfree(p->pointer); + kfree(p->name); } -static const char * const * -property_copy_string_array(const struct property_entry *src) +static bool property_copy_string_array(const char **dst_ptr, + const char * const *src_ptr, + size_t nval) { - const char **d; - const char * const *src_str = src->pointer; - size_t nval = src->length / sizeof(*d); int i; - d = kcalloc(nval, sizeof(*d), GFP_KERNEL); - if (!d) - return NULL; - for (i = 0; i < nval; i++) { - d[i] = kstrdup(src_str[i], GFP_KERNEL); - if (!d[i] && src_str[i]) { + dst_ptr[i] = kstrdup(src_ptr[i], GFP_KERNEL); + if (!dst_ptr[i] && src_ptr[i]) { while (--i >= 0) - kfree(d[i]); - kfree(d); - return NULL; + kfree(dst_ptr[i]); + return false; } } - return d; + return true; } static int property_entry_copy_data(struct property_entry *dst, const struct property_entry *src) { const void *pointer = property_get_pointer(src); - const void *new; - - if (!src->is_inline) { - if (!src->length) - return -ENODATA; - - if (src->type == DEV_PROP_STRING) { - new = property_copy_string_array(src); - if (!new) - return -ENOMEM; - } else { - new = kmemdup(pointer, src->length, GFP_KERNEL); - if (!new) - return -ENOMEM; - } - - dst->pointer = new; - } else if (src->type == DEV_PROP_STRING) { - new = kstrdup(src->value.str, GFP_KERNEL); - if (!new && src->value.str) + void *dst_ptr; + size_t nval; + + /* + * Properties with no data should not be marked as stored + * out of line. + */ + if (!src->is_inline && !src->length) + return -ENODATA; + + if (src->length <= sizeof(dst->value)) { + dst_ptr = &dst->value; + dst->is_inline = true; + } else { + dst_ptr = kmalloc(src->length, GFP_KERNEL); + if (!dst_ptr) return -ENOMEM; + dst->pointer = dst_ptr; + } - dst->is_inline = true; - dst->value.str = new; + if (src->type == DEV_PROP_STRING) { + nval = src->length / sizeof(const char *); + if (!property_copy_string_array(dst_ptr, pointer, nval)) { + if (!dst->is_inline) + kfree(dst->pointer); + return -ENOMEM; + } } else { - dst->is_inline = true; - dst->value = src->value; + memcpy(dst_ptr, pointer, src->length); } dst->length = src->length; dst->type = src->type; dst->name = kstrdup(src->name, GFP_KERNEL); - if (!dst->name) - goto out_free_data; + if (!dst->name) { + property_entry_free_data(dst); + return -ENOMEM; + } return 0; - -out_free_data: - property_entry_free_data(dst); - return -ENOMEM; } /** @@ -484,6 +475,8 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode, const struct software_node_reference *ref; const struct property_entry *prop; struct fwnode_handle *refnode; + u32 nargs_prop_val; + int error; int i; if (!swnode || !swnode->node->references) @@ -501,11 +494,13 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode, return -ENOENT; if (nargs_prop) { - prop = property_entry_get(swnode->node->properties, nargs_prop); - if (!prop) - return -EINVAL; + error = property_entry_read_int_array(swnode->node->properties, + nargs_prop, sizeof(u32), + &nargs_prop_val, 1); + if (error) + return error; - nargs = prop->value.u32_data; + nargs = nargs_prop_val; } if (nargs > NR_FWNODE_REFERENCE_ARGS) diff --git a/include/linux/property.h b/include/linux/property.h index dad0ad11b55e2..c592c286e3394 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -242,11 +242,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; }; }; @@ -258,7 +258,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_LEN(_name_, _elem_, _Type_, _val_, _len_)\ (struct property_entry) { \ @@ -296,7 +296,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_) \ From patchwork Fri Nov 8 04:22:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 11234081 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1A7FA1864 for ; Fri, 8 Nov 2019 04:22:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EC421222CF for ; Fri, 8 Nov 2019 04:22:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lYu+kGGu" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729280AbfKHEWs (ORCPT ); Thu, 7 Nov 2019 23:22:48 -0500 Received: from mail-pl1-f196.google.com ([209.85.214.196]:41819 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729895AbfKHEWf (ORCPT ); Thu, 7 Nov 2019 23:22:35 -0500 Received: by mail-pl1-f196.google.com with SMTP id d29so3169363plj.8; Thu, 07 Nov 2019 20:22:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+UAfSxO+xFzb8U0KaiRZauI96OA1CjCGgwrEB72JhoA=; b=lYu+kGGuNfcKv+qfcTC1XfqrLcTpPx70xltj+VISO1k3Xwa5ZHkjdEyxR00xcZsvT9 jFxunziqLrqCU583dzEx5/+1kPgqqZoMKlrLoNozBEzPopc1cEK18EZdXJ2ASt4F0rb9 Uj+TSZuVF6fGjWVqamrLSHHpHhkiMurEWT2TMUt8pCh4Zly5jN7bsupV+zFoy0phVEaU 3oCVVdEql1VMbD8QIgu2WZZOXtZ2vemlP87EA/ONvg/WXTsQKkMhEyUUY4HqiC8kBToy UacV0Q8urG3QLg0wHESif8DeF20ca/Et47OQLp2quDonsPBWVTMmuab0ekqxpXDJmlrL 7t8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+UAfSxO+xFzb8U0KaiRZauI96OA1CjCGgwrEB72JhoA=; b=Xm3tfyBaRpbuW20L98wu9mjLvVPrDEjQ+FJ/Y8nvVSfCW8Rz6h3QpaJDelJwwjbuCd +Rt5TRaXjEvE3y4pu8vKtyyVNZW1lg9ibARLW1uaLxlbs63uPrroysfTk04ctVbIAI7a +bods3dgtOc+1Fnhc+Gn1DwHYOp4pPxf5p7RROYT05/QU8JGIyqVOmWtUl0JtMN4kQ9t TkuQqGeaixqrmZmmCOPtoj1EniZIlsdBrWIgdkL0oYqIO2v8jAd987yOcxp+fT0FFCX0 nTrwJUu5rateb+6o3fCcwOepcGmblpYtytCAG+sK6N6VGQuXp0S6pkWdkM94PjuFD/Dx 4BZw== X-Gm-Message-State: APjAAAWwBnzz9QDxKqQJE7U/xPhBQXL7NCagOXtym7+mpOF6qxrf4JED smy5egOgD7u4vsWwlUqN26k= X-Google-Smtp-Source: APXvYqybZXJsa7klVx58NNroyaoC4gJPnr5iSNFgFwS0GAle6hHU8EzdaaUrGJw9RZle1jA47QXvQQ== X-Received: by 2002:a17:90a:fa84:: with SMTP id cu4mr10410931pjb.65.1573186952905; Thu, 07 Nov 2019 20:22:32 -0800 (PST) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:202:201:3adc:b08c:7acc:b325]) by smtp.gmail.com with ESMTPSA id 71sm5004106pfx.107.2019.11.07.20.22.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Nov 2019 20:22:31 -0800 (PST) From: Dmitry Torokhov To: "Rafael J. Wysocki" , Heikki Krogerus Cc: Andy Shevchenko , Mika Westerberg , Linus Walleij , Ard Biesheuvel , linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, platform-driver-x86@vger.kernel.org Subject: [PATCH v8 3/6] software node: implement reference properties Date: Thu, 7 Nov 2019 20:22:22 -0800 Message-Id: <20191108042225.45391-4-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.24.0.rc1.363.gb1bccd3e3d-goog In-Reply-To: <20191108042225.45391-1-dmitry.torokhov@gmail.com> References: <20191108042225.45391-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org It 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), { } }; Signed-off-by: Dmitry Torokhov --- drivers/base/swnode.c | 49 ++++++++++++++++++++++++++++------ include/linux/property.h | 57 +++++++++++++++++++++++++++++----------- 2 files changed, 82 insertions(+), 24 deletions(-) diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index 3d422918a53d9..604d7327bba79 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -246,6 +246,13 @@ static int property_entry_copy_data(struct property_entry *dst, if (!src->is_inline && !src->length) return -ENODATA; + /* + * Reference properties are never stored inline as + * they are too big. + */ + if (src->type == DEV_PROP_REF && src->is_inline) + return -EINVAL; + if (src->length <= sizeof(dst->value)) { dst_ptr = &dst->value; dst->is_inline = true; @@ -473,23 +480,49 @@ 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; u32 nargs_prop_val; int error; 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; @@ -510,7 +543,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; } diff --git a/include/linux/property.h b/include/linux/property.h index c592c286e3394..19b9dcc322763 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -22,6 +22,7 @@ enum dev_prop_type { DEV_PROP_U32, DEV_PROP_U64, DEV_PROP_STRING, + DEV_PROP_REF, }; enum dev_dma_attr { @@ -223,6 +224,20 @@ static inline int fwnode_property_count_u64(const struct fwnode_handle *fwnode, return fwnode_property_read_u64_array(fwnode, propname, NULL, 0); } +struct software_node; + +/** + * struct software_node_ref_args - Reference property with additional arguments + * @node: Reference to a software node + * @nargs: Number of elements in @args array + * @args: Integer arguments + */ +struct software_node_ref_args { + const struct software_node *node; + unsigned int nargs; + u64 args[NR_FWNODE_REFERENCE_ARGS]; +}; + /** * struct property_entry - "Built-in" device property representation. * @name: Name of the property. @@ -260,14 +275,20 @@ struct property_entry { #define __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_) \ sizeof(((struct property_entry *)NULL)->value._elem_[0]) -#define __PROPERTY_ENTRY_ARRAY_LEN(_name_, _elem_, _Type_, _val_, _len_)\ +#define __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN(_name_, _elsize_, _Type_, \ + _val_, _len_) \ (struct property_entry) { \ .name = _name_, \ - .length = (_len_) * __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_), \ + .length = (_len_) * (_elsize_), \ .type = DEV_PROP_##_Type_, \ { .pointer = _val_ }, \ } +#define __PROPERTY_ENTRY_ARRAY_LEN(_name_, _elem_, _Type_, _val_, _len_)\ + __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN(_name_, \ + __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_), \ + _Type_, _val_, _len_) + #define PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, _len_) \ __PROPERTY_ENTRY_ARRAY_LEN(_name_, u8_data, U8, _val_, _len_) #define PROPERTY_ENTRY_U16_ARRAY_LEN(_name_, _val_, _len_) \ @@ -278,6 +299,10 @@ struct property_entry { __PROPERTY_ENTRY_ARRAY_LEN(_name_, u64_data, U64, _val_, _len_) #define PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, _len_) \ __PROPERTY_ENTRY_ARRAY_LEN(_name_, str, STRING, _val_, _len_) +#define PROPERTY_ENTRY_REF_ARRAY_LEN(_name_, _val_, _len_) \ + __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN(_name_, \ + sizeof(struct software_node_ref_args), \ + REF, _val_, _len_) #define PROPERTY_ENTRY_U8_ARRAY(_name_, _val_) \ PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) @@ -289,6 +314,8 @@ struct property_entry { 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_REF_ARRAY(_name_, _val_) \ + PROPERTY_ENTRY_REF_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) #define __PROPERTY_ENTRY_ELEMENT(_name_, _elem_, _Type_, _val_) \ (struct property_entry) { \ @@ -316,6 +343,18 @@ struct property_entry { .is_inline = true, \ } +#define PROPERTY_ENTRY_REF(_name_, _ref_, ...) \ +(struct property_entry) { \ + .name = _name_, \ + .length = sizeof(struct software_node_ref_args), \ + .type = DEV_PROP_REF, \ + { .pointer = &(const struct software_node_ref_args) { \ + .node = _ref_, \ + .nargs = ARRAY_SIZE(((u64[]){ 0, ##__VA_ARGS__ })) - 1, \ + .args = { __VA_ARGS__ }, \ + } }, \ +} + struct property_entry * property_entries_dup(const struct property_entry *properties); @@ -379,20 +418,6 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode, /* -------------------------------------------------------------------------- */ /* Software fwnode support - when HW description is incomplete or missing */ -struct software_node; - -/** - * struct software_node_ref_args - Reference with additional arguments - * @node: Reference to a software node - * @nargs: Number of elements in @args array - * @args: Integer arguments - */ -struct software_node_ref_args { - const struct software_node *node; - unsigned int nargs; - u64 args[NR_FWNODE_REFERENCE_ARGS]; -}; - /** * struct software_node_reference - Named software node reference property * @name: Name of the property From patchwork Fri Nov 8 04:22:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 11234083 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0174E1515 for ; Fri, 8 Nov 2019 04:22:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C9E7B21D82 for ; Fri, 8 Nov 2019 04:22:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OW0h2Sc8" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730092AbfKHEWx (ORCPT ); Thu, 7 Nov 2019 23:22:53 -0500 Received: from mail-pl1-f196.google.com ([209.85.214.196]:42506 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729880AbfKHEWe (ORCPT ); Thu, 7 Nov 2019 23:22:34 -0500 Received: by mail-pl1-f196.google.com with SMTP id j12so3162820plt.9; Thu, 07 Nov 2019 20:22:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9yY1ilCQrcIHxsUtMS2U9uQS4obcy3+hHr81/tVLigE=; b=OW0h2Sc8T1/OqZl9vKn6J0rG0llI6pSnjYdfDfXVjDkdvoHCjRRUHuwYhAenlYzw6Q H0trYBnjxOdbnfsTFr5u8Vema3YMZOQQd3gDU3eKCL7bVhdvMrmFtKP4IGTuRRTUFkNP GXydufAafgDZX0GAbHBdWGehOWrS8e8GtWxZHg11eGybw+ZHZ7NvKz1VcWRIbmzQZ5En 4J8Khdq5mF2eJgb+KoLdoVMPzculeT5R/cb2lP89WTZoWkf+p3aBj5laVnX+X+Wx5h+Q u4j26D9vAJwlZWgVNnzuEvM/oKd3x2AN+IFjxSSOhlitKeT7rV1l6h2CWQY91SSoeOGA SUTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9yY1ilCQrcIHxsUtMS2U9uQS4obcy3+hHr81/tVLigE=; b=KY6k+67TwyrvTVDqxsj4GtdUxUASomKO5stdY+b7v1Q5gjE6aLUdMHXMt8bnhfGxj7 6tKxqlLdVWo2r1KBPmSdgn8I7vzmCNJOMhYfudrAssSbgQa1JYYUsqBPjzu8voYPIS3L I9fmAD03LGhsWjyt05zKwuJ1QBnAj17i04hJjwJVTkDSQtfrMjP0sJsuX5pOGcppm5FG aemWdJ77ijVbuljiwVCJuj+QTIXkmMs/7hZpCprInVK/af9XacaYkvGaYQaH8wV6tS/h uLebVl2+maINWy5nGIYXG6AUJ/qB33EaTWtUtMhMzNaScl+ILuPoDAhkL4vCH6MBXS2M Zo6Q== X-Gm-Message-State: APjAAAVu4mYFYhiDJis+Ig0mwhCFKvKyLM1Oaq3hsH1S+m1cwEzud0oa Z3KkmkiN1hnOLpfLSgVRqzk= X-Google-Smtp-Source: APXvYqzOOjtZ+nD42gEULjb2GrTQoJ919yybAAMjf126D4hIXJ+rN1QkdHsPReFQ8HBmkUiGe8aXmw== X-Received: by 2002:a17:90a:22a6:: with SMTP id s35mr10169084pjc.3.1573186953675; Thu, 07 Nov 2019 20:22:33 -0800 (PST) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:202:201:3adc:b08c:7acc:b325]) by smtp.gmail.com with ESMTPSA id 71sm5004106pfx.107.2019.11.07.20.22.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Nov 2019 20:22:33 -0800 (PST) From: Dmitry Torokhov To: "Rafael J. Wysocki" , Heikki Krogerus Cc: Andy Shevchenko , Mika Westerberg , Linus Walleij , Ard Biesheuvel , linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, platform-driver-x86@vger.kernel.org Subject: [PATCH v8 4/6] platform/x86: intel_cht_int33fe: use inline reference properties Date: Thu, 7 Nov 2019 20:22:23 -0800 Message-Id: <20191108042225.45391-5-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.24.0.rc1.363.gb1bccd3e3d-goog In-Reply-To: <20191108042225.45391-1-dmitry.torokhov@gmail.com> References: <20191108042225.45391-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Now 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. Acked-by: Andy Shevchenko Signed-off-by: Dmitry Torokhov --- .../platform/x86/intel_cht_int33fe_typec.c | 81 ++++++++++--------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/drivers/platform/x86/intel_cht_int33fe_typec.c b/drivers/platform/x86/intel_cht_int33fe_typec.c index 2d097fc2dd465..04138215956bf 100644 --- a/drivers/platform/x86/intel_cht_int33fe_typec.c +++ b/drivers/platform/x86/intel_cht_int33fe_typec.c @@ -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 From patchwork Fri Nov 8 04:22:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 11234075 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6C1FC1515 for ; Fri, 8 Nov 2019 04:22:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 498B92178F for ; Fri, 8 Nov 2019 04:22:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AT2aypKS" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729811AbfKHEWj (ORCPT ); Thu, 7 Nov 2019 23:22:39 -0500 Received: from mail-pf1-f194.google.com ([209.85.210.194]:45895 "EHLO mail-pf1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729904AbfKHEWg (ORCPT ); Thu, 7 Nov 2019 23:22:36 -0500 Received: by mail-pf1-f194.google.com with SMTP id z4so3778649pfn.12; Thu, 07 Nov 2019 20:22:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=po8Rb6LoWgZKfHqWrWPqkF0E9McUNGqymnwIsz+izAA=; b=AT2aypKSTuuGJ5p7oMpo5aBUjg6YyLrO3vHEHNC0kXGBhLEXdR5YQ0EXphefAfpJg6 yQ7cLIpt5+ZlbTS+0qy1J0zN9Xhi2eEO1y/cJ2DzY3VPOEiZsJxej4Ak6gQ776n/Z1iv ARl2+dGxxAraZT0B/DV/NMZorYoQSTiNWUir/vGKqaArA/EV92uxKGgsuvME5iiIrJi6 avdS3wpamKHc0Z0p2uJRed8qiyQ/sBanG3l1juaRQ4xIHDvAlQBojlqRpYxVYXgwSUqz 5h3lxkXaw9kw3eIqdvfD7m/zZPTKEQ855gJ1mCLGfsmbYPkUQwz8BgBt/TkETIk/Rk0w 44BQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=po8Rb6LoWgZKfHqWrWPqkF0E9McUNGqymnwIsz+izAA=; b=fIECz/k4KTajIXajIj1qsnW6IjqwjwFGKguLpZ1UQFqka94nKMc9heYeKUnr3f8khN 2x5SYdupRCCLVOaVQjbK2HvE2PkkLtLIH1PQtIZKvWl5Y4dASfL4S6bSunjuYyZwq1W/ ixY+O2AkN14sfeOWyA6RsocRN2AB85UybS29NxQ54emL/S/2lqxjd8lBZJPOtiGGbq/y sF/8tStR1cQLUUB7cl7YgdGlHb6WAsiDxA5Do50gNNDYtPIOX7i08UGZR6X396iAdI19 3Y7koYv8Io/62HxnD0jByczt5iKrK3MZQx/Sd+57HpE3qNsHYDCl6tJKj8/wMgx5Bldw ZC8Q== X-Gm-Message-State: APjAAAUPc06VN5C6gwiImdiBLZa4K+4sm1W06YkxMAne6FbMH0It96NK tOXmV7ceMmgTY/FgrbM0UeQ= X-Google-Smtp-Source: APXvYqyA1UPsOde6sy3mfP56M03C0nnhfiE/Dzpv7jciFSKzKQShWHUqAUynX+BKE4RJvGSFd6i0VA== X-Received: by 2002:a63:cb0f:: with SMTP id p15mr9065466pgg.81.1573186954433; Thu, 07 Nov 2019 20:22:34 -0800 (PST) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:202:201:3adc:b08c:7acc:b325]) by smtp.gmail.com with ESMTPSA id 71sm5004106pfx.107.2019.11.07.20.22.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Nov 2019 20:22:34 -0800 (PST) From: Dmitry Torokhov To: "Rafael J. Wysocki" , Heikki Krogerus Cc: Andy Shevchenko , Mika Westerberg , Linus Walleij , Ard Biesheuvel , linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, platform-driver-x86@vger.kernel.org Subject: [PATCH v8 5/6] software node: remove separate handling of references Date: Thu, 7 Nov 2019 20:22:24 -0800 Message-Id: <20191108042225.45391-6-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.24.0.rc1.363.gb1bccd3e3d-goog In-Reply-To: <20191108042225.45391-1-dmitry.torokhov@gmail.com> References: <20191108042225.45391-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Now that all users of references have moved to reference properties, we can remove separate handling of references. Signed-off-by: Dmitry Torokhov --- drivers/base/swnode.c | 48 +++++++++++++++------------------------- include/linux/property.h | 14 ------------ 2 files changed, 18 insertions(+), 44 deletions(-) diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index 604d7327bba79..0b081dee1e95c 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -479,9 +479,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; u32 nargs_prop_val; @@ -492,37 +491,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; - - ref_array = prop->pointer; - ref_args = &ref_array[index]; - } else { - if (!swnode->node->references) - return -ENOENT; + if (!prop) + 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; @@ -543,7 +531,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; } diff --git a/include/linux/property.h b/include/linux/property.h index 19b9dcc322763..b28c81af7bb68 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -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); From patchwork Fri Nov 8 04:22:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 11234073 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E2E851864 for ; Fri, 8 Nov 2019 04:22:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B660B222C2 for ; Fri, 8 Nov 2019 04:22:45 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="d1EonotI" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729996AbfKHEWl (ORCPT ); Thu, 7 Nov 2019 23:22:41 -0500 Received: from mail-pg1-f194.google.com ([209.85.215.194]:40218 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729974AbfKHEWk (ORCPT ); Thu, 7 Nov 2019 23:22:40 -0500 Received: by mail-pg1-f194.google.com with SMTP id 15so3239755pgt.7; Thu, 07 Nov 2019 20:22:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=7JQ4d+b4S8N8l/fThjQXIfSRkEpJamVb7T13kzPaTGM=; b=d1EonotIkR599AZfX/tz8AKOMlZXC692pdH5YxuDLqCOujQfsQZ12YK4ak7IuD/3hL 7dBeCh5NdEXZBvGi4LJrQjjmaiTernaXOuCr2o9YwFMyCazvwOpVzaf9Uzxp8O4QZPym 3JyxF7+Qfu1JOCjxee/mlkRZe2h2aZkRKnnydh7I+Vzn8JoGiG4KSJ+Z5XskLyoKH8W6 RFnvBOhs7F3ShPIfUK8uL+s6tftpaXzkotLw1o9qAP9CBLCGuXWo2AN8v+bXoaUiUju+ AFOU9fdtfqwtgbtTgBW8b2ydweVOxKSwGqGbQ2kfTB3eD+6kSeYtQRQqChHI/wX7gFJV ai7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=7JQ4d+b4S8N8l/fThjQXIfSRkEpJamVb7T13kzPaTGM=; b=cor6YO4Vr/EHA6Dz7lFEPt0tAaTv/CkBJVCihmKHei0d5mNBPt4gDzBHBJYhVVfZv0 zH1N3Q6rEhUoAWAzXIxxgzGA3GyemgBk31v4w33waWnxVGRtDb7lg8okIxafbl4FmGzp ocMJIDCBHSjJwcHEFKRzDGj32+J1Jdoy0LQw1wgw2JFYuUGV+TlRKdSnfPM6jSIrZBKT epVHd0NUPxizPmgLYqL4ymh2+B2U2JNxuiF/gbosg0GtdSSZaOU66xSzM8j81vPXFkgT u3K9I1/79wmT2JlKGdKT+BvOG9B35W6ioOe4/vXrXMLj3tlKj6v12yaAb4pcRcy6UepQ fgAg== X-Gm-Message-State: APjAAAVOTQ+5IqneV/FhI9wumHET8EcLnZQ4NyO++3nYue56hGwLlcu7 jsXxqOYlmgaQYAJWyeKvvh4= X-Google-Smtp-Source: APXvYqzANMLNEXdBIbRd7wff1SGWJ9KqHKvV/vxArKSY3dRsegIC8/D6lLVLtn4GqMnG4gK9yWVfNg== X-Received: by 2002:a65:60cf:: with SMTP id r15mr9189106pgv.53.1573186959338; Thu, 07 Nov 2019 20:22:39 -0800 (PST) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:202:201:3adc:b08c:7acc:b325]) by smtp.gmail.com with ESMTPSA id 71sm5004106pfx.107.2019.11.07.20.22.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Nov 2019 20:22:34 -0800 (PST) From: Dmitry Torokhov To: "Rafael J. Wysocki" , Heikki Krogerus Cc: Andy Shevchenko , Mika Westerberg , Linus Walleij , Ard Biesheuvel , linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, platform-driver-x86@vger.kernel.org Subject: [PATCH v8 6/6] software node: add basic tests for property entries Date: Thu, 7 Nov 2019 20:22:25 -0800 Message-Id: <20191108042225.45391-7-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.24.0.rc1.363.gb1bccd3e3d-goog In-Reply-To: <20191108042225.45391-1-dmitry.torokhov@gmail.com> References: <20191108042225.45391-1-dmitry.torokhov@gmail.com> MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org This 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. Signed-off-by: Dmitry Torokhov --- 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 diff --git a/drivers/base/test/Makefile b/drivers/base/test/Makefile index 0f1f7277a0139..22143102e5d21 100644 --- a/drivers/base/test/Makefile +++ b/drivers/base/test/Makefile @@ -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 diff --git a/drivers/base/test/property-entry-test.c b/drivers/base/test/property-entry-test.c new file mode 100644 index 0000000000000..d523a3d9caeda --- /dev/null +++ b/drivers/base/test/property-entry-test.c @@ -0,0 +1,472 @@ +// SPDX-License-Identifier: GPL-2.0 +// Unit tests for property entries API +// +// Copyright 2019 Google LLC. + +#include +#include +#include + +static void pe_test_uints(struct kunit *test) +{ + const struct property_entry entries[] = { + PROPERTY_ENTRY_U8("prop-u8", 8), + PROPERTY_ENTRY_U16("prop-u16", 16), + PROPERTY_ENTRY_U32("prop-u32", 32), + PROPERTY_ENTRY_U64("prop-u64", 64), + { } + }; + + struct fwnode_handle *node; + u8 val_u8, array_u8[2]; + u16 val_u16, array_u16[2]; + u32 val_u32, array_u32[2]; + u64 val_u64, array_u64[2]; + int error; + + node = fwnode_create_software_node(entries, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, node); + + error = fwnode_property_read_u8(node, "prop-u8", &val_u8); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)val_u8, 8); + + error = fwnode_property_read_u8_array(node, "prop-u8", array_u8, 1); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)array_u8[0], 8); + + error = fwnode_property_read_u8_array(node, "prop-u8", array_u8, 2); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u8(node, "no-prop-u8", &val_u8); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u8_array(node, "no-prop-u8", array_u8, 1); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u16(node, "prop-u16", &val_u16); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)val_u16, 16); + + error = fwnode_property_read_u16_array(node, "prop-u16", array_u16, 1); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)array_u16[0], 16); + + error = fwnode_property_read_u16_array(node, "prop-u16", array_u16, 2); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u16(node, "no-prop-u16", &val_u16); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u16_array(node, "no-prop-u16", array_u16, 1); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u32(node, "prop-u32", &val_u32); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)val_u32, 32); + + error = fwnode_property_read_u32_array(node, "prop-u32", array_u32, 1); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)array_u32[0], 32); + + error = fwnode_property_read_u32_array(node, "prop-u32", array_u32, 2); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u32(node, "no-prop-u32", &val_u32); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u32_array(node, "no-prop-u32", array_u32, 1); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u64(node, "prop-u64", &val_u64); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)val_u64, 64); + + error = fwnode_property_read_u64_array(node, "prop-u64", array_u64, 1); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)array_u64[0], 64); + + error = fwnode_property_read_u64_array(node, "prop-u64", array_u64, 2); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u64(node, "no-prop-u64", &val_u64); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u64_array(node, "no-prop-u64", array_u64, 1); + KUNIT_EXPECT_NE(test, error, 0); + + fwnode_remove_software_node(node); +} + +static void pe_test_uint_arrays(struct kunit *test) +{ + u8 a_u8[16] = { 8, 9 }; + u16 a_u16[16] = { 16, 17 }; + u32 a_u32[16] = { 32, 33 }; + u64 a_u64[16] = { 64, 65 }; + const struct property_entry entries[] = { + PROPERTY_ENTRY_U8_ARRAY("prop-u8", a_u8), + PROPERTY_ENTRY_U16_ARRAY("prop-u16", a_u16), + PROPERTY_ENTRY_U32_ARRAY("prop-u32", a_u32), + PROPERTY_ENTRY_U64_ARRAY("prop-u64", a_u64), + { } + }; + + struct fwnode_handle *node; + u8 val_u8, array_u8[32]; + u16 val_u16, array_u16[32]; + u32 val_u32, array_u32[32]; + u64 val_u64, array_u64[32]; + int error; + + node = fwnode_create_software_node(entries, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, node); + + error = fwnode_property_read_u8(node, "prop-u8", &val_u8); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)val_u8, 8); + + error = fwnode_property_read_u8_array(node, "prop-u8", array_u8, 1); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)array_u8[0], 8); + + error = fwnode_property_read_u8_array(node, "prop-u8", array_u8, 2); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)array_u8[0], 8); + KUNIT_EXPECT_EQ(test, (int)array_u8[1], 9); + + error = fwnode_property_read_u8_array(node, "prop-u8", array_u8, 17); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u8(node, "no-prop-u8", &val_u8); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u8_array(node, "no-prop-u8", array_u8, 1); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u16(node, "prop-u16", &val_u16); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)val_u16, 16); + + error = fwnode_property_read_u16_array(node, "prop-u16", array_u16, 1); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)array_u16[0], 16); + + error = fwnode_property_read_u16_array(node, "prop-u16", array_u16, 2); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)array_u16[0], 16); + KUNIT_EXPECT_EQ(test, (int)array_u16[1], 17); + + error = fwnode_property_read_u16_array(node, "prop-u16", array_u16, 17); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u16(node, "no-prop-u16", &val_u16); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u16_array(node, "no-prop-u16", array_u16, 1); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u32(node, "prop-u32", &val_u32); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)val_u32, 32); + + error = fwnode_property_read_u32_array(node, "prop-u32", array_u32, 1); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)array_u32[0], 32); + + error = fwnode_property_read_u32_array(node, "prop-u32", array_u32, 2); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)array_u32[0], 32); + KUNIT_EXPECT_EQ(test, (int)array_u32[1], 33); + + error = fwnode_property_read_u32_array(node, "prop-u32", array_u32, 17); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u32(node, "no-prop-u32", &val_u32); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u32_array(node, "no-prop-u32", array_u32, 1); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u64(node, "prop-u64", &val_u64); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)val_u64, 64); + + error = fwnode_property_read_u64_array(node, "prop-u64", array_u64, 1); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)array_u64[0], 64); + + error = fwnode_property_read_u64_array(node, "prop-u64", array_u64, 2); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_EQ(test, (int)array_u64[0], 64); + KUNIT_EXPECT_EQ(test, (int)array_u64[1], 65); + + error = fwnode_property_read_u64_array(node, "prop-u64", array_u64, 17); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u64(node, "no-prop-u64", &val_u64); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_u64_array(node, "no-prop-u64", array_u64, 1); + KUNIT_EXPECT_NE(test, error, 0); + + fwnode_remove_software_node(node); +} + +static void pe_test_strings(struct kunit *test) +{ + const char *strings[] = { + "string-a", + "string-b", + }; + + const struct property_entry entries[] = { + PROPERTY_ENTRY_STRING("str", "single"), + PROPERTY_ENTRY_STRING("empty", ""), + PROPERTY_ENTRY_STRING_ARRAY("strs", strings), + { } + }; + + struct fwnode_handle *node; + const char *str; + const char *strs[10]; + int error; + + node = fwnode_create_software_node(entries, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, node); + + error = fwnode_property_read_string(node, "str", &str); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_STREQ(test, str, "single"); + + error = fwnode_property_read_string_array(node, "str", strs, 1); + KUNIT_EXPECT_EQ(test, error, 1); + KUNIT_EXPECT_STREQ(test, strs[0], "single"); + + /* asking for more data returns what we have */ + error = fwnode_property_read_string_array(node, "str", strs, 2); + KUNIT_EXPECT_EQ(test, error, 1); + KUNIT_EXPECT_STREQ(test, strs[0], "single"); + + error = fwnode_property_read_string(node, "no-str", &str); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_read_string_array(node, "no-str", strs, 1); + KUNIT_EXPECT_LT(test, error, 0); + + error = fwnode_property_read_string(node, "empty", &str); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_STREQ(test, str, ""); + + error = fwnode_property_read_string_array(node, "strs", strs, 3); + KUNIT_EXPECT_EQ(test, error, 2); + KUNIT_EXPECT_STREQ(test, strs[0], "string-a"); + KUNIT_EXPECT_STREQ(test, strs[1], "string-b"); + + error = fwnode_property_read_string_array(node, "strs", strs, 1); + KUNIT_EXPECT_EQ(test, error, 1); + KUNIT_EXPECT_STREQ(test, strs[0], "string-a"); + + /* NULL argument -> returns size */ + error = fwnode_property_read_string_array(node, "strs", NULL, 0); + KUNIT_EXPECT_EQ(test, error, 2); + + /* accessing array as single value */ + error = fwnode_property_read_string(node, "strs", &str); + KUNIT_EXPECT_EQ(test, error, 0); + KUNIT_EXPECT_STREQ(test, str, "string-a"); + + fwnode_remove_software_node(node); +} + +static void pe_test_bool(struct kunit *test) +{ + const struct property_entry entries[] = { + PROPERTY_ENTRY_BOOL("prop"), + { } + }; + + struct fwnode_handle *node; + + node = fwnode_create_software_node(entries, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, node); + + KUNIT_EXPECT_TRUE(test, fwnode_property_read_bool(node, "prop")); + KUNIT_EXPECT_FALSE(test, fwnode_property_read_bool(node, "not-prop")); + + fwnode_remove_software_node(node); +} + +/* Verifies that small U8 array is stored inline when property is copied */ +static void pe_test_move_inline_u8(struct kunit *test) +{ + u8 u8_array_small[8] = { 1, 2, 3, 4 }; + u8 u8_array_big[128] = { 5, 6, 7, 8 }; + struct property_entry entries[] = { + PROPERTY_ENTRY_U8_ARRAY("small", u8_array_small), + PROPERTY_ENTRY_U8_ARRAY("big", u8_array_big), + { } + }; + struct property_entry *copy; + const u8 *data_ptr; + + copy = property_entries_dup(entries); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, copy); + + KUNIT_EXPECT_TRUE(test, copy[0].is_inline); + data_ptr = (u8 *)©[0].value; + KUNIT_EXPECT_EQ(test, (int)data_ptr[0], 1); + KUNIT_EXPECT_EQ(test, (int)data_ptr[1], 2); + + KUNIT_EXPECT_FALSE(test, copy[1].is_inline); + data_ptr = copy[1].pointer; + KUNIT_EXPECT_EQ(test, (int)data_ptr[0], 5); + KUNIT_EXPECT_EQ(test, (int)data_ptr[1], 6); + + property_entries_free(copy); +} + +/* Verifies that single string array is stored inline when property is copied */ +static void pe_test_move_inline_str(struct kunit *test) +{ + char *str_array_small[] = { "a" }; + char *str_array_big[] = { "b", "c", "d", "e" }; + char *str_array_small_empty[] = { "" }; + struct property_entry entries[] = { + PROPERTY_ENTRY_STRING_ARRAY("small", str_array_small), + PROPERTY_ENTRY_STRING_ARRAY("big", str_array_big), + PROPERTY_ENTRY_STRING_ARRAY("small-empty", str_array_small_empty), + { } + }; + struct property_entry *copy; + const char * const *data_ptr; + + copy = property_entries_dup(entries); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, copy); + + KUNIT_EXPECT_TRUE(test, copy[0].is_inline); + KUNIT_EXPECT_STREQ(test, copy[0].value.str[0], "a"); + + KUNIT_EXPECT_FALSE(test, copy[1].is_inline); + data_ptr = copy[1].pointer; + KUNIT_EXPECT_STREQ(test, data_ptr[0], "b"); + KUNIT_EXPECT_STREQ(test, data_ptr[1], "c"); + + KUNIT_EXPECT_TRUE(test, copy[2].is_inline); + KUNIT_EXPECT_STREQ(test, copy[2].value.str[0], ""); + + property_entries_free(copy); +} + +/* Handling of reference properties */ +static void pe_test_reference(struct kunit *test) +{ + const struct software_node nodes[] = { + { .name = "1", }, + { .name = "2", }, + }; + + const struct software_node_ref_args refs[] = { + { + .node = &nodes[0], + .nargs = 0, + }, + { + .node = &nodes[1], + .nargs = 2, + .args = { 3, 4 }, + }, + }; + + const struct property_entry entries[] = { + PROPERTY_ENTRY_REF("ref-1", &nodes[0]), + PROPERTY_ENTRY_REF("ref-2", &nodes[1], 1, 2), + PROPERTY_ENTRY_REF_ARRAY("ref-3", refs), + { } + }; + + struct fwnode_handle *node; + struct fwnode_reference_args ref; + int error; + + error = software_node_register_nodes(nodes); + KUNIT_ASSERT_EQ(test, error, 0); + + node = fwnode_create_software_node(entries, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, node); + + error = fwnode_property_get_reference_args(node, "ref-1", NULL, + 0, 0, &ref); + KUNIT_ASSERT_EQ(test, error, 0); + KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[0]); + KUNIT_EXPECT_EQ(test, ref.nargs, 0U); + + /* wrong index */ + error = fwnode_property_get_reference_args(node, "ref-1", NULL, + 0, 1, &ref); + KUNIT_EXPECT_NE(test, error, 0); + + error = fwnode_property_get_reference_args(node, "ref-2", NULL, + 1, 0, &ref); + KUNIT_ASSERT_EQ(test, error, 0); + KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[1]); + KUNIT_EXPECT_EQ(test, ref.nargs, 1U); + KUNIT_EXPECT_EQ(test, ref.args[0], 1LLU); + + /* asking for more args, padded with zero data */ + error = fwnode_property_get_reference_args(node, "ref-2", NULL, + 3, 0, &ref); + KUNIT_ASSERT_EQ(test, error, 0); + KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[1]); + KUNIT_EXPECT_EQ(test, ref.nargs, 3U); + KUNIT_EXPECT_EQ(test, ref.args[0], 1LLU); + KUNIT_EXPECT_EQ(test, ref.args[1], 2LLU); + KUNIT_EXPECT_EQ(test, ref.args[2], 0LLU); + + /* wrong index */ + error = fwnode_property_get_reference_args(node, "ref-2", NULL, + 2, 1, &ref); + KUNIT_EXPECT_NE(test, error, 0); + + /* array of references */ + error = fwnode_property_get_reference_args(node, "ref-3", NULL, + 0, 0, &ref); + KUNIT_ASSERT_EQ(test, error, 0); + KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[0]); + KUNIT_EXPECT_EQ(test, ref.nargs, 0U); + + /* second reference in the array */ + error = fwnode_property_get_reference_args(node, "ref-3", NULL, + 2, 1, &ref); + KUNIT_ASSERT_EQ(test, error, 0); + KUNIT_EXPECT_PTR_EQ(test, to_software_node(ref.fwnode), &nodes[1]); + KUNIT_EXPECT_EQ(test, ref.nargs, 2U); + KUNIT_EXPECT_EQ(test, ref.args[0], 3LLU); + KUNIT_EXPECT_EQ(test, ref.args[1], 4LLU); + + /* wrong index */ + error = fwnode_property_get_reference_args(node, "ref-1", NULL, + 0, 2, &ref); + KUNIT_EXPECT_NE(test, error, 0); + + fwnode_remove_software_node(node); + software_node_unregister_nodes(nodes); +} + +static struct kunit_case property_entry_test_cases[] = { + KUNIT_CASE(pe_test_uints), + KUNIT_CASE(pe_test_uint_arrays), + KUNIT_CASE(pe_test_strings), + KUNIT_CASE(pe_test_bool), + KUNIT_CASE(pe_test_move_inline_u8), + KUNIT_CASE(pe_test_move_inline_str), + KUNIT_CASE(pe_test_reference), + { } +}; + +static struct kunit_suite property_entry_test_suite = { + .name = "property-entry", + .test_cases = property_entry_test_cases, +}; + +kunit_test_suite(property_entry_test_suite);