Skip to content

Commit 4dd2ab9

Browse files
committed
Merge tag 'devprop-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull device properties framework updates from Rafael Wysocki: "These fix the handling of data nodes in the ACPI properties support code, add a new helper for endpoint lookup in property graphs and restore a comment inadvertently removed by one of previous changes. Specifics: - Fix the handling of data nodes in the ACPI properties support code for devices with child devices and hierarchical _DSD properties (Pierre-Louis Bossart). - Add fwnode_graph_get_endpoint_by_id() helper for endpoint lookup in device property graphs (Sakari Ailus). - Restore the _DSD data subnodes GUID comment inadvertently removed by one of previous changes (Shunyong Yang)" * tag 'devprop-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI / property: fix handling of data_nodes in acpi_get_next_subnode() device property: Add fwnode_graph_get_endpoint_by_id() ACPI: property: restore _DSD data subnodes GUID comment
2 parents 8f5e823 + 23583f7 commit 4dd2ab9

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

drivers/acpi/property.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ static const guid_t prp_guids[] = {
4444
0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89),
4545
};
4646

47+
/* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
4748
static const guid_t ads_guid =
4849
GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
4950
0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b);
@@ -1031,6 +1032,14 @@ struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
10311032
const struct acpi_data_node *data = to_acpi_data_node(fwnode);
10321033
struct acpi_data_node *dn;
10331034

1035+
/*
1036+
* We can have a combination of device and data nodes, e.g. with
1037+
* hierarchical _DSD properties. Make sure the adev pointer is
1038+
* restored before going through data nodes, otherwise we will
1039+
* be looking for data_nodes below the last device found instead
1040+
* of the common fwnode shared by device_nodes and data_nodes.
1041+
*/
1042+
adev = to_acpi_device_node(fwnode);
10341043
if (adev)
10351044
head = &adev->data.subnodes;
10361045
else if (data)

drivers/base/property.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,81 @@ fwnode_graph_get_remote_node(const struct fwnode_handle *fwnode, u32 port_id,
983983
}
984984
EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_node);
985985

986+
/**
987+
* fwnode_graph_get_endpoint_by_id - get endpoint by port and endpoint numbers
988+
* @fwnode: parent fwnode_handle containing the graph
989+
* @port: identifier of the port node
990+
* @endpoint: identifier of the endpoint node under the port node
991+
* @flags: fwnode lookup flags
992+
*
993+
* Return the fwnode handle of the local endpoint corresponding the port and
994+
* endpoint IDs or NULL if not found.
995+
*
996+
* If FWNODE_GRAPH_ENDPOINT_NEXT is passed in @flags and the specified endpoint
997+
* has not been found, look for the closest endpoint ID greater than the
998+
* specified one and return the endpoint that corresponds to it, if present.
999+
*
1000+
* Do not return endpoints that belong to disabled devices, unless
1001+
* FWNODE_GRAPH_DEVICE_DISABLED is passed in @flags.
1002+
*
1003+
* The returned endpoint needs to be released by calling fwnode_handle_put() on
1004+
* it when it is not needed any more.
1005+
*/
1006+
struct fwnode_handle *
1007+
fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
1008+
u32 port, u32 endpoint, unsigned long flags)
1009+
{
1010+
struct fwnode_handle *ep = NULL, *best_ep = NULL;
1011+
unsigned int best_ep_id = 0;
1012+
bool endpoint_next = flags & FWNODE_GRAPH_ENDPOINT_NEXT;
1013+
bool enabled_only = !(flags & FWNODE_GRAPH_DEVICE_DISABLED);
1014+
1015+
while ((ep = fwnode_graph_get_next_endpoint(fwnode, ep))) {
1016+
struct fwnode_endpoint fwnode_ep = { 0 };
1017+
int ret;
1018+
1019+
if (enabled_only) {
1020+
struct fwnode_handle *dev_node;
1021+
bool available;
1022+
1023+
dev_node = fwnode_graph_get_remote_port_parent(ep);
1024+
available = fwnode_device_is_available(dev_node);
1025+
fwnode_handle_put(dev_node);
1026+
if (!available)
1027+
continue;
1028+
}
1029+
1030+
ret = fwnode_graph_parse_endpoint(ep, &fwnode_ep);
1031+
if (ret < 0)
1032+
continue;
1033+
1034+
if (fwnode_ep.port != port)
1035+
continue;
1036+
1037+
if (fwnode_ep.id == endpoint)
1038+
return ep;
1039+
1040+
if (!endpoint_next)
1041+
continue;
1042+
1043+
/*
1044+
* If the endpoint that has just been found is not the first
1045+
* matching one and the ID of the one found previously is closer
1046+
* to the requested endpoint ID, skip it.
1047+
*/
1048+
if (fwnode_ep.id < endpoint ||
1049+
(best_ep && best_ep_id < fwnode_ep.id))
1050+
continue;
1051+
1052+
fwnode_handle_put(best_ep);
1053+
best_ep = fwnode_handle_get(ep);
1054+
best_ep_id = fwnode_ep.id;
1055+
}
1056+
1057+
return best_ep;
1058+
}
1059+
EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id);
1060+
9861061
/**
9871062
* fwnode_graph_parse_endpoint - parse common endpoint node properties
9881063
* @fwnode: pointer to endpoint fwnode_handle

include/linux/property.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef _LINUX_PROPERTY_H_
1414
#define _LINUX_PROPERTY_H_
1515

16+
#include <linux/bits.h>
1617
#include <linux/fwnode.h>
1718
#include <linux/types.h>
1819

@@ -304,6 +305,23 @@ struct fwnode_handle *
304305
fwnode_graph_get_remote_node(const struct fwnode_handle *fwnode, u32 port,
305306
u32 endpoint);
306307

308+
/*
309+
* Fwnode lookup flags
310+
*
311+
* @FWNODE_GRAPH_ENDPOINT_NEXT: In the case of no exact match, look for the
312+
* closest endpoint ID greater than the specified
313+
* one.
314+
* @FWNODE_GRAPH_DEVICE_DISABLED: That the device to which the remote
315+
* endpoint of the given endpoint belongs to,
316+
* may be disabled.
317+
*/
318+
#define FWNODE_GRAPH_ENDPOINT_NEXT BIT(0)
319+
#define FWNODE_GRAPH_DEVICE_DISABLED BIT(1)
320+
321+
struct fwnode_handle *
322+
fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
323+
u32 port, u32 endpoint, unsigned long flags);
324+
307325
#define fwnode_graph_for_each_endpoint(fwnode, child) \
308326
for (child = NULL; \
309327
(child = fwnode_graph_get_next_endpoint(fwnode, child)); )

0 commit comments

Comments
 (0)