--- zzzz-none-000/linux-5.4.213/drivers/hwtracing/coresight/coresight-platform.c 2022-09-15 10:04:56.000000000 +0000 +++ miami-7690-761/linux-5.4.213/drivers/hwtracing/coresight/coresight-platform.c 2024-05-29 11:19:51.000000000 +0000 @@ -67,6 +67,7 @@ int *nr_inport, int *nr_outport) { struct device_node *ep = NULL; + struct of_endpoint endpoint; int in = 0, out = 0; do { @@ -74,10 +75,16 @@ if (!ep) break; - if (of_coresight_legacy_ep_is_input(ep)) - in++; - else - out++; + if (of_graph_parse_endpoint(ep, &endpoint)) + continue; + + if (of_coresight_legacy_ep_is_input(ep)) { + in = (endpoint.port + 1 > in) ? + endpoint.port + 1 : in; + } else { + out = (endpoint.port + 1) > out ? + endpoint.port + 1 : out; + } } while (ep); @@ -117,9 +124,16 @@ { int i = 0; struct device_node *ep = NULL; + struct of_endpoint endpoint; + + while ((ep = of_graph_get_next_endpoint(port_parent, ep))) { + /* Defer error handling to parsing */ + if (of_graph_parse_endpoint(ep, &endpoint)) + continue; + if (endpoint.port + 1 > i) + i = endpoint.port + 1; + } - while ((ep = of_graph_get_next_endpoint(port_parent, ep))) - i++; return i; } @@ -165,20 +179,39 @@ } /* + * of_coresight_get_atid_number: Get the atid number of a source device. + * + * Returns the number of the atid. If the result is less than zero, it means + * failure. + */ +int of_coresight_get_atid_number(struct coresight_device *csdev) +{ + return of_property_count_u32_elems(csdev->dev.parent->of_node, "atid"); +} + +/* + * of_coresight_get_atid: Get the atid array of a source device. + * + * Returns 0 on success. + */ +int of_coresight_get_atid(struct coresight_device *csdev, u32 *atid, int atid_num) +{ + return of_property_read_u32_array(csdev->dev.parent->of_node, "atid", atid, atid_num); +} + +/* * of_coresight_parse_endpoint : Parse the given output endpoint @ep * and fill the connection information in @conn * * Parses the local port, remote device name and the remote port. * * Returns : - * 1 - If the parsing is successful and a connection record - * was created for an output connection. * 0 - If the parsing completed without any fatal errors. * -Errno - Fatal error, abort the scanning. */ static int of_coresight_parse_endpoint(struct device *dev, struct device_node *ep, - struct coresight_connection *conn) + struct coresight_platform_data *pdata) { int ret = 0; struct of_endpoint endpoint, rendpoint; @@ -186,6 +219,7 @@ struct device_node *rep = NULL; struct device *rdev = NULL; struct fwnode_handle *rdev_fwnode; + struct coresight_connection *conn; do { /* Parse the local port details */ @@ -212,6 +246,14 @@ break; } + conn = &pdata->conns[endpoint.port]; + if (conn->child_fwnode) { + dev_warn(dev, "Duplicate output port %d\n", + endpoint.port); + ret = -EINVAL; + break; + } + conn->outport = endpoint.port; /* * Hold the refcount to the target device. This could be @@ -224,7 +266,6 @@ conn->child_fwnode = fwnode_handle_get(rdev_fwnode); conn->child_port = rendpoint.port; /* Connection record updated */ - ret = 1; } while (0); of_node_put(rparent); @@ -238,7 +279,6 @@ struct coresight_platform_data *pdata) { int ret = 0; - struct coresight_connection *conn; struct device_node *ep = NULL; const struct device_node *parent = NULL; bool legacy_binding = false; @@ -267,8 +307,6 @@ dev_warn_once(dev, "Uses obsolete Coresight DT bindings\n"); } - conn = pdata->conns; - /* Iterate through each output port to discover topology */ while ((ep = of_graph_get_next_endpoint(parent, ep))) { /* @@ -280,15 +318,9 @@ if (legacy_binding && of_coresight_legacy_ep_is_input(ep)) continue; - ret = of_coresight_parse_endpoint(dev, ep, conn); - switch (ret) { - case 1: - conn++; /* Fall through */ - case 0: - break; - default: + ret = of_coresight_parse_endpoint(dev, ep, pdata); + if (ret) return ret; - } } return 0; @@ -627,6 +659,16 @@ * coresight_remove_match(). */ conn->child_fwnode = fwnode_handle_get(&r_adev->fwnode); + } else if (dir == ACPI_CORESIGHT_LINK_SLAVE) { + /* + * We are only interested in the port number + * for the input ports at this component. + * Store the port number in child_port. + */ + conn->child_port = fields[0].integer.value; + } else { + /* Invalid direction */ + return -EINVAL; } return dir; @@ -672,10 +714,20 @@ return dir; if (dir == ACPI_CORESIGHT_LINK_MASTER) { - pdata->nr_outport++; + if (ptr->outport > pdata->nr_outport) + pdata->nr_outport = ptr->outport; ptr++; } else { - pdata->nr_inport++; + WARN_ON(pdata->nr_inport == ptr->child_port); + /* + * We do not track input port connections for a device. + * However we need the highest port number described, + * which can be recorded now and reuse this connection + * record for an output connection. Hence, do not move + * the ptr for input connections + */ + if (ptr->child_port > pdata->nr_inport) + pdata->nr_inport = ptr->child_port; } } @@ -684,8 +736,14 @@ return rc; /* Copy the connection information to the final location */ - for (i = 0; i < pdata->nr_outport; i++) - pdata->conns[i] = conns[i]; + + for (i = 0; conns + i < ptr; i++) { + int port = conns[i].outport; + + /* Duplicate output port */ + WARN_ON(pdata->conns[port].child_fwnode); + pdata->conns[port] = conns[i]; + } devm_kfree(&adev->dev, conns); return 0;