[PATCH 2/4] coresight: Add support for multiple output ports on the funnel

Tingwei Zhang quic_tingweiz at quicinc.com
Thu Apr 18 19:11:54 PDT 2024


On 4/18/2024 8:38 PM, Suzuki K Poulose wrote:
> On 18/04/2024 13:01, Tingwei Zhang wrote:
>> Hi Mike and Suzuki
>>
>> On 4/18/2024 5:25 PM, Mike Leach wrote:
>>> Hi Suzuki
>>>
>>>> -----Original Message-----
>>>> From: Suzuki K Poulose <suzuki.poulose at arm.com>
>>>> Sent: Thursday, April 18, 2024 10:00 AM
>>>> To: Mike Leach <mike.leach at linaro.org>
>>>> Cc: Tao Zhang <quic_taozha at quicinc.com>; Mathieu Poirier
>>>> <mathieu.poirier at linaro.org>; Alexander Shishkin
>>>> <alexander.shishkin at linux.intel.com>; Konrad Dybcio
>>>> <konradybcio at gmail.com>; Rob Herring <robh+dt at kernel.org>; Krzysztof
>>>> Kozlowski <krzysztof.kozlowski+dt at linaro.org>; Jinlong Mao
>>>> <quic_jinlmao at quicinc.com>; Greg Kroah-Hartman
>>>> <gregkh at linuxfoundation.org>; coresight at lists.linaro.org; linux-arm-
>>>> kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
>>>> devicetree at vger.kernel.org; Tingwei Zhang <quic_tingweiz at quicinc.com>;
>>>> Yuanfang Zhang <quic_yuanfang at quicinc.com>; Trilok Soni
>>>> <quic_tsoni at quicinc.com>; Song Chai <quic_songchai at quicinc.com>; 
>>>> linux-arm-
>>>> msm at vger.kernel.org; andersson at kernel.org
>>>> Subject: Re: [PATCH 2/4] coresight: Add support for multiple output 
>>>> ports on the
>>>> funnel
>>>>
>>>> Hi Mike
>>>>
>>>> On 18/04/2024 09:48, Mike Leach wrote:
>>>>> Hi Suzuki
>>>>>
>>>>> On Wed, 17 Apr 2024 at 10:21, Suzuki K Poulose 
>>>>> <suzuki.poulose at arm.com>
>>>> wrote:
>>>>>>
>>>>>> Hi Mike
>>>>>>
>>>>>> On 16/04/2024 15:19, Mike Leach wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> On Mon, 15 Apr 2024 at 14:24, Suzuki K Poulose 
>>>>>>> <suzuki.poulose at arm.com>
>>>> wrote:
>>>>>>>>
>>>>>>>> On 09/04/2024 14:22, Tao Zhang wrote:
>>>>>>>>>
>>>>>>>>> On 4/9/2024 3:13 PM, Suzuki K Poulose wrote:
>>>>>>>>>> Hi
>>>>>>>>>>
>>>>>>>>>> On 29/03/2024 09:27, Tao Zhang wrote:
>>>>>>>>>>>
>>>>>>>>>>> On 3/22/2024 12:41 AM, Suzuki K Poulose wrote:
>>>>>>>>>>>> On 21/03/2024 08:32, Tao Zhang wrote:
>>>>>>>>>>>>> Funnel devices are now capable of supporting multiple-inputs
>>>>>>>>>>>>> and multiple-outputs configuration with in built hardware
>>>>>>>>>>>>> filtering for TPDM devices. Add software support to this
>>>>>>>>>>>>> function. Output port is selected according to the source 
>>>>>>>>>>>>> in the trace
>>>> path.
>>>>>>>>>>>>>
>>>>>>>>>>>>> The source of the input port on funnels will be marked in the
>>>>>>>>>>>>> device tree.
>>>>>>>>>>>>> e.g.
>>>>>>>>>>>>> tpdm at xxxxxxx {
>>>>>>>>>>>>>         ... ... ... ...
>>>>>>>>>>>>> };
>>>>>>>>>>>>>
>>>>>>>>>>>>> funnel_XXX: funnel at xxxxxxx {
>>>>>>>>>>>>>         ... ... ... ...
>>>>>>>>>>>>>         out-ports {
>>>>>>>>>>>>>             ... ... ... ...
>>>>>>>>>>>>>             port at x {
>>>>>>>>>>>>>                 ... ... ... ...
>>>>>>>>>>>>>                 label = "xxxxxxx.tpdm"; <-- To label the 
>>>>>>>>>>>>> source
>>>>>>>>>>>>>             };                           corresponding to 
>>>>>>>>>>>>> the output
>>>>>>>>>>>>>         ... ... ... ...                  connection 
>>>>>>>>>>>>> "port at x". And this
>>>>>>>>>>>>>         };                               is a hardware static
>>>>>>>>>>>>> connections.
>>>>>>>>>>>>>         ... ... ... ...                  Here needs to 
>>>>>>>>>>>>> refer to hardware
>>>>>>>>>>>>> };                                   design.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Then driver will parse the source label marked in the device
>>>>>>>>>>>>> tree, and save it to the coresight path. When the function
>>>>>>>>>>>>> needs to know the source label, it could obtain it from 
>>>>>>>>>>>>> coresight path
>>>> parameter.
>>>>>>>>>>>>> Finally,
>>>>>>>>>>>>> the output port knows which source it corresponds to, and it
>>>>>>>>>>>>> also knows which input port it corresponds to.
>>>>>>>>>>>>
>>>>>>>>>>>> Why do we need labels ? We have connection information for all
>>>>>>>>>>>> devices (both in and out), so, why do we need this label to 
>>>>>>>>>>>> find a device
>>>> ?
>>>>>>>>>>>
>>>>>>>>>>> Because our funnel's design has multi-output ports, the data
>>>>>>>>>>> stream will not
>>>>>>>>>>>
>>>>>>>>>>> know which output port should pass in building the data trace 
>>>>>>>>>>> path.
>>>>>>>>>>> This source
>>>>>>>>>>>
>>>>>>>>>>> label can make the data stream find the right output port to go.
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> And also, I thought TPDM is a source device, why does a funnel
>>>>>>>>>>>> output port link to a source ?
>>>>>>>>>>>
>>>>>>>>>>> No, this label doesn't mean this funnel output port link to a
>>>>>>>>>>> source, it just let
>>>>>>>>>>>
>>>>>>>>>>> the output port know its data source.
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Are these funnels programmable ? Or, are they static ? If they
>>>>>>>>>>>> are static, do these need to be described in the DT ? If they
>>>>>>>>>>>> are simply acting as a "LINK" (or HWFIFO ?)
>>>>>>>>>>>
>>>>>>>>>>> These funnels are static, and we will add the "label" to the DT
>>>>>>>>>>> to describe the
>>>>>>>>>>>
>>>>>>>>>>> multi-output ports for these funnels.
>>>>>>>>>>
>>>>>>>>>> I think there is still a bit of confusion. By "Dynamic" I mean,
>>>>>>>>>> the "dynamic funnel" (explicit port enablement via MMIO) vs
>>>>>>>>>> "static funnel" (no programming, always ON).
>>>>>>>>>>
>>>>>>>>>> So, coming to your example, do we need to "explicitly" enable
>>>>>>>>>> trace flow for an "input" and/or an "output" port in your 
>>>>>>>>>> "funnel" ?
>>>>>>>>>
>>>>>>>>> Sorry for my misunderstanding in the previous mails. Our funnels
>>>>>>>>> are programmable just like the common dynamic funnels.
>>>>>>>>>
>>>>>>>>> In our solution, we just make funnels have multiple output ports
>>>>>>>>> connected to different devices or ports. When we use it, we still
>>>>>>>>>
>>>>>>>>> enable the input port through programming. Our solution is to know
>>>>>>>>> which input port the expected data comes from based on the
>>>>>>>>>
>>>>>>>>> source label corresponding to the output port. This way we can
>>>>>>>>> build the expected trace path. In other respects, it is used the
>>>>>>>>> same
>>>>>>>>>
>>>>>>>>> as common dynamic funnels.
>>>>>>>>
>>>>>>>>
>>>>>>>> Ok. So, to summarise :
>>>>>>>>
>>>>>>>> 1. This is not a standard Funnel, but a trace link with 
>>>>>>>> multiple-input
>>>>>>>>        and multiple-output, with inputs hardwired to an outline at
>>>>>>>>        integration.
>>>>>>>> 2. The programming model is same as that of a "standard funnel".
>>>>>>>>
>>>>>>>> Now, we do have enough information in the coresight_connections to
>>>>>>>> traverse input/output ports. But we need additional logic to
>>>>>>>> "hardwire" the ports to each other and necessary logic to handle
>>>>>>>> the
>>>>>>>>
>>>>>>>> There are two options here :
>>>>>>>>
>>>>>>>> 1. Treat this as a new component and have its own driver, with
>>>>>>>>        additional logic to handle the input/output wiring.
>>>>>>>>
>>>>>>>> 2. Drive it using the funnel driver, with a a new compatible and
>>>>>>>>        add additional logic to handle the input/output wiring.
>>>>>>>>
>>>>>>>> My inclination is towards (2), we need to see how this works out.
>>>>>>>>
>>>>>>>> We need to irrespective of the options, we need special handling
>>>>>>>> for hardwired ports in 1) building path 2) walking back the path
>>>>>>>> (in TPDA driver)
>>>>>>>>
>>>>>>>> We also need some "DT" information to bind a given input port to an
>>>>>>>> output port. We must not use "any device" labels to hack this up,
>>>>>>>> like the approach in this series.
>>>>>>>>
>>>>>>>
>>>>>>> Given that the internal connections are static for the given device,
>>>>>>> then the compatible will imply these connections in just the same
>>>>>>> way as the arm,coresight-funnel implies that all inputs are
>>>>>>> connected to the single output.
>>>>>>
>>>>>> I am sorry, I couldn't follow the last part. We have two or more
>>>>>> output ports and we need a way to identify, which input port is
>>>>>> hardwired to
>>>>>> output-port0 and output-port1. Given we need special handling for
>>>>>> these anyway, I would like to avoid hard coding the input-output 
>>>>>> connection.
>>>>>> i.e., we do not want to assume that input-0  is always => output-0.
>>>>>>
>>>>>
>>>>> If we regard the current component as having compatible
>>>>> "qcom,coresight-compound-funnel-v1", then this identifies the
>>>>> relationship between the in-ports and out-ports.
>>>>> So the new driver / extension to the funnel driver that handles this
>>>>> compatible with know the static mapping between input and output so
>>>>> program it.
>>>>
>>>> Ok, but like I said, having one compatible may not be enough to know 
>>>> the "static"
>>>> mapping for all possible device instances on different SoCs.
>>>>
>>>
>>> The compatible name would have to change if the mapping changed.
>>> Using the compatible is simpler, but less flexible
>>>
>>>>>
>>>>> If however you want a more generic approach to handle future different
>>>>> versions of the component, then of course a method in DT of mapping
>>>>> in-ports to out-ports is useful.
>>>>>
>>>>> If did wonder if something along the lines of:-
>>>>>
>>>>> compound-funnel at 0x1234000 {
>>>>>        compatible = "compound-funnel"
>>>>>        regs = < 0x1234000 0x1000>
>>>>>         sub-funnel at 0 {
>>>>>                    in-ports {
>>>>>                           [some port definitions]
>>>>>                     }
>>>>>                    out-ports {
>>>>>                          [some port definitions]
>>>>>                     }
>>>>>          }
>>>>>         sub-funnel at 1 {
>>>>>                    in-ports {
>>>>>                           [some port definitions]
>>>>>                     }
>>>>>                    out-ports {
>>>>>                          [some port definitions]
>>>>>                    }
>>>>>           }
>>>>> }
>>>>
>>>> That would work, with "two" different coresight devices for each 
>>>> "embedded
>>>> funnel". And that also confuses the user with the topology.
>>>
>>> I wasn't suggesting two different coresight devices, but finding a 
>>> way to iterate the sub-nodes to create a single device with the 
>>> inputs mapped to outputs. Which may or may not be easily do-able.
>>>
>>> As to topology - no more confusing than a "funnel" with multiple 
>>> outputs, or phandle links between inputs and outputs. It does 
>>> visually represent what the device really is - multiple effective 
>>> funnels controlled by a single set of registers.
>>>
>>
>> Let me provide the hardware topology here to facilitate the discussion.
>>
>> |----------|     |---------|     |----------|   |---------|
>> |  TPDM 0  |     | Source0 |     | Source 1 |   | TPDM 1  |
>> |----------|     |---------|     |----------|   |---------|
>>       |                |                |             |
>>       |                |                |             |
>>       |      --------- |                |             |
>>       |      |                          |             |
>>       |      |                          |             |
>>       |      |                          |             |
>>    \-------------/ ----------------------             |
>>     \  Funnel 0 /  |                                  |
>>      -----------   |  ---------------------------------
>>           |        |  |
>>           |        |  |
>>         \ -------------/
>>          \  Funnel 1  /
>>           -----------/
>>              |  |---------------------
>>              |  |------------         |
>>              |               |TPDM0   |TPDM1
>>              |            \ ----------------/
>>              |             \   TPDA 0      /
>>              |              --------------/
>>              |                    |
>>              |                    |
>>              |Source0/1           |
>>           \-------------------------------/
>>            \     Funnel 2                /
>>              ---------------------------
>>
>> To describe this topology in device tree, we need to indicate input 
>> port0 of FUNNEL0 is static link to output port0 of FUNNEL0 which links 
>> to input port0 of TPDA0. When code builds the path, it can get the 
> 
> This is making things even worse. Hold on there. Please could you
> confirm the topology again via the "Funnel 1". You seemed to have
> skipped it in the path description.
> 
Funnel0 has two inputs and one output. Funnel1 has three inputs and 
three outputs.
> 
> How many outputs does the Funnel 1 have ? 2 or 3 ? How does the Funnel 1
> know to split the "data" from Funnel1:input0 (which could be either 
> Source0 or TPDM0) ?
> 
> 
>> static link information from topology and select correct path. As 
>> Suzuki has suggested, we can describe the topology like below.
> 
> No, I suggested hardwiring the output-input of "the same component". Not
> of the two different components. I guess we need to sort this out
> offline, (happy to setup a call to understand and clear things better).
I agree we could have a call to I can clarify things better. Let me get 
some data from hardware team on how funnel1 routes data from different 
source. Do you have preference time to have that call?
> 
> 
>>
>> funnel0 {
>>      ...
>>      in-ports {
>>          port at 0 {
>>              funnel0_in0: endpoint {
>>                  remote-endpoint = <&tpdm0_output>;
>>                  <hard-wired-to*>=
>>                    <&funnel1_out0>;
> 
> No, I meant. Not skipping the components.
> 
>          <&funnel0_out0>;
> 
> This leaves the question of how Funnel1 does the separation, unless
> it is a replicator and does the filtering based on the TraceID.
> 
> 
> Suzuki
> 
> 
>>              }
>>          }
>>      }
>> }
>>
>> funnel1 {
>>      ...
>>      out-ports {
>>          port at 0 {
>>              funnel1_out0: endpoint {
>>                  remote-endpoint= <&tpdm0_in0>;
>>                  <hard-wired-to*>=
>>                      <&funnel0_in0>;
>>              }
>>          }
>>      }
>> }
>>
>>
>>> Mike
>>>
>>>>
>>>>>
>>>>>
>>>>> might be made to work? not sure about the implications of having more
>>>>> that one set of in-ports and out-ports in a component in the device
>>>>> tree & would need specific handling in the driver to iterate
>>>>> sub-funnels.
>>>>>
>>>>>
>>>>>>
>>>>>>>
>>>>>>> Irrespective of if a new driver is used, or an extension to the
>>>>>>> current funnel driver to handle a new compatible - the mapping
>>>>>>> between input and output ports are created based on the compatible..
>>>>>>>
>>>>>>> As we are building a path from source to sink, what is then needed
>>>>>>> is a method in the generic path building code, to recognise these
>>>>>>> amppings and filter the output ports that are searched based on the
>>>>>>> input port in use.
>>>>>>
>>>>>> Agreed. We could mark this as a property of the
>>>>>> port/coresight_connection.
>>>>>>
>>>>>>>
>>>>>>> On standard components, where the mapping is not present, then the
>>>>>>> code will continue as it does now, for these compound funnels, the
>>>>>>> mappings will be present and the output filtering will occur.
>>>>>>
>>>>>> Agreed
>>>>>>
>>>>>>> This removes the need for the labels / extra connection attributes
>>>>>>> on devices other than the funnel, and also removes the need to
>>>>>>> specify the internal connections as part of the device tree.
>>>>>>
>>>>>> I am still not clear how we map the input-output ports. Rest is what
>>>>>> exactly I had in mind. So, once we sort out the port mapping we could
>>>>>> proceed to the prototyping.
>>>>>>
>>>>>
>>>>> given we iterate by output port index into an array of out ports, and
>>>>> have an array of in-ports by index, a third mapping array, same size
>>>>> as in-ports, determining the associated out port index should suffice.
>>>>> Mapping array should be optional - if not there, path discovery works
>>>>> as previously
>>>>
>>>> We could simply add a "(sticky)flag" to the
>>>> "coresight_connection".src_port/dest_port and extend the array to 
>>>> include the
>>>> sticky_port for src/dest port and use that flag to force the path 
>>>> traversal.
>>>>
>>>> Suzuki
>>>>
>>>>
>>>>
>>>>>
>>>>> Regards
>>>>>
>>>>> Mike
>>>>>
>>>>>> Kind regards
>>>>>> Suzuki
>>>>>>
>>>>>>
>>>>>>>
>>>>>>> Regards
>>>>>>>
>>>>>>> Mike
>>>>>>>
>>>>>>>> Rob/Krzysztof,
>>>>>>>>
>>>>>>>> Do you have any recommendations for describing the 'hard wired
>>>>>>>> ports' ?
>>>>>>>>
>>>>>>>> e.g:
>>>>>>>>
>>>>>>>> component {
>>>>>>>>        input_ports {
>>>>>>>>           component_input_port0: port at 0 {
>>>>>>>>               ...
>>>>>>>>               <hard-wired-to*> = &component_output_port0;
>>>>>>>>           };
>>>>>>>>           ...
>>>>>>>>       };
>>>>>>>>
>>>>>>>>       output_ports {
>>>>>>>>         componentne_output_port0: port at 0 {
>>>>>>>>             ...
>>>>>>>>             <hard-wired-to> = &component_input_port0;
>>>>>>>>         };
>>>>>>>>         ...
>>>>>>>>       };
>>>>>>>>
>>>>>>>> };
>>>>>>>>
>>>>>>>> *Need a better suitable property than "hard-wired-to".
>>>>>>>>
>>>>>>>>
>>>>>>>> Suzuki
>>>>>>>>
>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Best,
>>>>>>>>>
>>>>>>>>> Tao
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> "If they are simply acting as a "LINK" (or HWFIFO ?) " I'm not
>>>>>>>>>>> sure what's the meaning
>>>>>>>>>>
>>>>>>>>>> i.e, Like TMC-ETF in HWFIFO mode. In this mode, the TMC-ETF is
>>>>>>>>>> acting like a cache for easing ATB data load, by providing h/w 
>>>>>>>>>> buffering.
>>>>>>>>>> (In your case, it may not be providing any buffering, it doesn't
>>>>>>>>>> matter either way, as it is not visible to the driver).
>>>>>>>>>>
>>>>>>>>>> Suzuki
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> of this. Could you describe it in detail?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Best,
>>>>>>>>>>>
>>>>>>>>>>> Tao
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Suzuki
>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Signed-off-by: Tao Zhang <quic_taozha at quicinc.com>
>>>>>>>>>>>>> ---
>>>>>>>>>>>>>      drivers/hwtracing/coresight/coresight-core.c  | 81
>>>>>>>>>>>>> ++++++++++++++++---
>>>>>>>>>>>>>      .../hwtracing/coresight/coresight-platform.c  |  5 ++
>>>>>>>>>>>>>      include/linux/coresight.h                     |  2 +
>>>>>>>>>>>>>      3 files changed, 75 insertions(+), 13 deletions(-)
>>>>>>>>>>>>>
>>>>>>>>>>>>> diff --git a/drivers/hwtracing/coresight/coresight-core.c
>>>>>>>>>>>>> b/drivers/hwtracing/coresight/coresight-core.c
>>>>>>>>>>>>> index 5dde597403b3..b1b5e6d9ec7a 100644
>>>>>>>>>>>>> --- a/drivers/hwtracing/coresight/coresight-core.c
>>>>>>>>>>>>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>>>>>>>>>>>>> @@ -113,15 +113,63 @@ struct coresight_device
>>>>>>>>>>>>> *coresight_get_percpu_sink(int cpu)
>>>>>>>>>>>>>      }
>>>>>>>>>>>>>      EXPORT_SYMBOL_GPL(coresight_get_percpu_sink);
>>>>>>>>>>>>>      +static struct coresight_device
>>>>>>>>>>>>> *coresight_get_source(struct list_head *path)
>>>>>>>>>>>>> +{
>>>>>>>>>>>>> +    struct coresight_device *csdev;
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +    if (!path)
>>>>>>>>>>>>> +        return NULL;
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +    csdev = list_first_entry(path, struct coresight_node,
>>>>>>>>>>>>> link)->csdev;
>>>>>>>>>>>>> +    if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE)
>>>>>>>>>>>>> +        return NULL;
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +    return csdev;
>>>>>>>>>>>>> +}
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +/**
>>>>>>>>>>>>> + * coresight_source_filter - checks whether the connection
>>>>>>>>>>>>> +matches
>>>>>>>>>>>>> the source
>>>>>>>>>>>>> + * of path if connection is binded to specific source.
>>>>>>>>>>>>> + * @path:    The list of devices
>>>>>>>>>>>>> + * @conn:    The connection of one outport
>>>>>>>>>>>>> + *
>>>>>>>>>>>>> + * Return zero if the connection doesn't have a source binded
>>>>>>>>>>>>> + or
>>>>>>>>>>>>> source of the
>>>>>>>>>>>>> + * path matches the source binds to connection.
>>>>>>>>>>>>> + */
>>>>>>>>>>>>> +static int coresight_source_filter(struct list_head *path,
>>>>>>>>>>>>> +            struct coresight_connection *conn) {
>>>>>>>>>>>>> +    int ret = 0;
>>>>>>>>>>>>> +    struct coresight_device *source = NULL;
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +    if (conn->source_label == NULL)
>>>>>>>>>>>>> +        return ret;
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +    source = coresight_get_source(path);
>>>>>>>>>>>>> +    if (source == NULL)
>>>>>>>>>>>>> +        return ret;
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +    if (strstr(kobject_get_path(&source->dev.kobj, 
>>>>>>>>>>>>> GFP_KERNEL),
>>>>>>>>>>>>> +            conn->source_label))
>>>>>>>>>>>>> +        ret = 0;
>>>>>>>>>>>>> +    else
>>>>>>>>>>>>> +        ret = -1;
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +    return ret;
>>>>>>>>>>>>> +}
>>>>>>>>>>>>> +
>>>>>>>>>>>>>      static struct coresight_connection *
>>>>>>>>>>>>>      coresight_find_out_connection(struct coresight_device 
>>>>>>>>>>>>> *src_dev,
>>>>>>>>>>>>> -                  struct coresight_device *dest_dev)
>>>>>>>>>>>>> +                  struct coresight_device *dest_dev,
>>>>>>>>>>>>> +                  struct list_head *path)
>>>>>>>>>>>>>      {
>>>>>>>>>>>>>          int i;
>>>>>>>>>>>>>          struct coresight_connection *conn;
>>>>>>>>>>>>>            for (i = 0; i < src_dev->pdata->nr_outconns; i++) {
>>>>>>>>>>>>>              conn = src_dev->pdata->out_conns[i];
>>>>>>>>>>>>> +        if (coresight_source_filter(path, conn))
>>>>>>>>>>>>> +            continue;
>>>>>>>>>>>>>              if (conn->dest_dev == dest_dev)
>>>>>>>>>>>>>                  return conn;
>>>>>>>>>>>>>          }
>>>>>>>>>>>>> @@ -312,7 +360,8 @@ static void coresight_disable_sink(struct
>>>>>>>>>>>>> coresight_device *csdev)
>>>>>>>>>>>>>        static int coresight_enable_link(struct 
>>>>>>>>>>>>> coresight_device *csdev,
>>>>>>>>>>>>>                       struct coresight_device *parent,
>>>>>>>>>>>>> -                 struct coresight_device *child)
>>>>>>>>>>>>> +                 struct coresight_device *child,
>>>>>>>>>>>>> +                 struct list_head *path)
>>>>>>>>>>>>>      {
>>>>>>>>>>>>>          int ret = 0;
>>>>>>>>>>>>>          int link_subtype;
>>>>>>>>>>>>> @@ -321,8 +370,8 @@ static int coresight_enable_link(struct
>>>>>>>>>>>>> coresight_device *csdev,
>>>>>>>>>>>>>          if (!parent || !child)
>>>>>>>>>>>>>              return -EINVAL;
>>>>>>>>>>>>>      -    inconn = coresight_find_out_connection(parent, 
>>>>>>>>>>>>> csdev);
>>>>>>>>>>>>> -    outconn = coresight_find_out_connection(csdev, child);
>>>>>>>>>>>>> +    inconn = coresight_find_out_connection(parent, csdev, 
>>>>>>>>>>>>> path);
>>>>>>>>>>>>> +    outconn = coresight_find_out_connection(csdev, child,
>>>>>>>>>>>>> + path);
>>>>>>>>>>>>>          link_subtype = csdev->subtype.link_subtype;
>>>>>>>>>>>>>            if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG
>>>>>>>>>>>>> &&
>>>>>>>>>>>>> IS_ERR(inconn))
>>>>>>>>>>>>> @@ -341,7 +390,8 @@ static int coresight_enable_link(struct
>>>>>>>>>>>>> coresight_device *csdev,
>>>>>>>>>>>>>        static void coresight_disable_link(struct 
>>>>>>>>>>>>> coresight_device *csdev,
>>>>>>>>>>>>>                         struct coresight_device *parent,
>>>>>>>>>>>>> -                   struct coresight_device *child)
>>>>>>>>>>>>> +                   struct coresight_device *child,
>>>>>>>>>>>>> +                   struct list_head *path)
>>>>>>>>>>>>>      {
>>>>>>>>>>>>>          int i;
>>>>>>>>>>>>>          int link_subtype;
>>>>>>>>>>>>> @@ -350,8 +400,8 @@ static void coresight_disable_link(struct
>>>>>>>>>>>>> coresight_device *csdev,
>>>>>>>>>>>>>          if (!parent || !child)
>>>>>>>>>>>>>              return;
>>>>>>>>>>>>>      -    inconn = coresight_find_out_connection(parent, 
>>>>>>>>>>>>> csdev);
>>>>>>>>>>>>> -    outconn = coresight_find_out_connection(csdev, child);
>>>>>>>>>>>>> +    inconn = coresight_find_out_connection(parent, csdev, 
>>>>>>>>>>>>> path);
>>>>>>>>>>>>> +    outconn = coresight_find_out_connection(csdev, child,
>>>>>>>>>>>>> + path);
>>>>>>>>>>>>>          link_subtype = csdev->subtype.link_subtype;
>>>>>>>>>>>>>            if (link_ops(csdev)->disable) { @@ -507,7 +557,7 @@
>>>>>>>>>>>>> static void coresight_disable_path_from(struct
>>>>>>>>>>>>> list_head *path,
>>>>>>>>>>>>>              case CORESIGHT_DEV_TYPE_LINK:
>>>>>>>>>>>>>                  parent = list_prev_entry(nd, link)->csdev;
>>>>>>>>>>>>>                  child = list_next_entry(nd, link)->csdev;
>>>>>>>>>>>>> -            coresight_disable_link(csdev, parent, child);
>>>>>>>>>>>>> +            coresight_disable_link(csdev, parent, child,
>>>>>>>>>>>>> + path);
>>>>>>>>>>>>>                  break;
>>>>>>>>>>>>>              default:
>>>>>>>>>>>>>                  break;
>>>>>>>>>>>>> @@ -588,7 +638,7 @@ int coresight_enable_path(struct list_head
>>>>>>>>>>>>> *path, enum cs_mode mode,
>>>>>>>>>>>>>              case CORESIGHT_DEV_TYPE_LINK:
>>>>>>>>>>>>>                  parent = list_prev_entry(nd, link)->csdev;
>>>>>>>>>>>>>                  child = list_next_entry(nd, link)->csdev;
>>>>>>>>>>>>> -            ret = coresight_enable_link(csdev, parent, 
>>>>>>>>>>>>> child);
>>>>>>>>>>>>> +            ret = coresight_enable_link(csdev, parent, child,
>>>>>>>>>>>>> + path);
>>>>>>>>>>>>>                  if (ret)
>>>>>>>>>>>>>                      goto err;
>>>>>>>>>>>>>                  break;
>>>>>>>>>>>>> @@ -802,7 +852,8 @@ static void coresight_drop_device(struct
>>>>>>>>>>>>> coresight_device *csdev)
>>>>>>>>>>>>>       */
>>>>>>>>>>>>>      static int _coresight_build_path(struct 
>>>>>>>>>>>>> coresight_device *csdev,
>>>>>>>>>>>>>                       struct coresight_device *sink,
>>>>>>>>>>>>> -                 struct list_head *path)
>>>>>>>>>>>>> +                 struct list_head *path,
>>>>>>>>>>>>> +                 struct coresight_device *source)
>>>>>>>>>>>>>      {
>>>>>>>>>>>>>          int i, ret;
>>>>>>>>>>>>>          bool found = false;
>>>>>>>>>>>>> @@ -814,7 +865,7 @@ static int _coresight_build_path(struct
>>>>>>>>>>>>> coresight_device *csdev,
>>>>>>>>>>>>>            if (coresight_is_percpu_source(csdev) &&
>>>>>>>>>>>>> coresight_is_percpu_sink(sink) &&
>>>>>>>>>>>>>              sink == per_cpu(csdev_sink,
>>>>>>>>>>>>> source_ops(csdev)->cpu_id(csdev))) {
>>>>>>>>>>>>> -        if (_coresight_build_path(sink, sink, path) == 0) {
>>>>>>>>>>>>> +        if (_coresight_build_path(sink, sink, path, source)
>>>>>>>>>>>>> + == 0) {
>>>>>>>>>>>>>                  found = true;
>>>>>>>>>>>>>                  goto out;
>>>>>>>>>>>>>              }
>>>>>>>>>>>>> @@ -825,8 +876,12 @@ static int _coresight_build_path(struct
>>>>>>>>>>>>> coresight_device *csdev,
>>>>>>>>>>>>>              struct coresight_device *child_dev;
>>>>>>>>>>>>>                child_dev =
>>>>>>>>>>>>> csdev->pdata->out_conns[i]->dest_dev;
>>>>>>>>>>>>> +        if (csdev->pdata->out_conns[i]->source_label &&
>>>>>>>>>>>>> + !strstr(kobject_get_path(&source->dev.kobj, GFP_KERNEL),
>>>>>>>>>>>>> + csdev->pdata->out_conns[i]->source_label))
>>>>>>>>>>>>> +            continue;
>>>>>>>>>>>>>              if (child_dev &&
>>>>>>>>>>>>> -            _coresight_build_path(child_dev, sink, path) 
>>>>>>>>>>>>> == 0) {
>>>>>>>>>>>>> +            _coresight_build_path(child_dev, sink, path,
>>>>>>>>>>>>> + source)
>>>>>>>>>>>>> == 0) {
>>>>>>>>>>>>>                  found = true;
>>>>>>>>>>>>>                  break;
>>>>>>>>>>>>>              }
>>>>>>>>>>>>> @@ -871,7 +926,7 @@ struct list_head
>>>>>>>>>>>>> *coresight_build_path(struct coresight_device *source,
>>>>>>>>>>>>>            INIT_LIST_HEAD(path);
>>>>>>>>>>>>>      -    rc = _coresight_build_path(source, sink, path);
>>>>>>>>>>>>> +    rc = _coresight_build_path(source, sink, path, source);
>>>>>>>>>>>>>          if (rc) {
>>>>>>>>>>>>>              kfree(path);
>>>>>>>>>>>>>              return ERR_PTR(rc); diff --git
>>>>>>>>>>>>> a/drivers/hwtracing/coresight/coresight-platform.c
>>>>>>>>>>>>> b/drivers/hwtracing/coresight/coresight-platform.c
>>>>>>>>>>>>> index 9d550f5697fa..f553fb20966d 100644
>>>>>>>>>>>>> --- a/drivers/hwtracing/coresight/coresight-platform.c
>>>>>>>>>>>>> +++ b/drivers/hwtracing/coresight/coresight-platform.c
>>>>>>>>>>>>> @@ -205,6 +205,7 @@ static int
>>>>>>>>>>>>> of_coresight_parse_endpoint(struct
>>>>>>>>>>>>> device *dev,
>>>>>>>>>>>>>          struct fwnode_handle *rdev_fwnode;
>>>>>>>>>>>>>          struct coresight_connection conn = {};
>>>>>>>>>>>>>          struct coresight_connection *new_conn;
>>>>>>>>>>>>> +    const char *label;
>>>>>>>>>>>>>            do {
>>>>>>>>>>>>>              /* Parse the local port details */ @@ -243,6
>>>>>>>>>>>>> +244,10 @@ static int of_coresight_parse_endpoint(struct
>>>>>>>>>>>>> device *dev,
>>>>>>>>>>>>>              conn.dest_fwnode = 
>>>>>>>>>>>>> fwnode_handle_get(rdev_fwnode);
>>>>>>>>>>>>>              conn.dest_port = rendpoint.port;
>>>>>>>>>>>>>      +        conn.source_label = NULL;
>>>>>>>>>>>>> +        if (!of_property_read_string(ep, "label", &label))
>>>>>>>>>>>>> +            conn.source_label = label;
>>>>>>>>>>>>> +
>>>>>>>>>>>>>              new_conn = coresight_add_out_conn(dev, pdata, 
>>>>>>>>>>>>> &conn);
>>>>>>>>>>>>>              if (IS_ERR_VALUE(new_conn)) {
>>>>>>>>>>>>>                  fwnode_handle_put(conn.dest_fwnode);
>>>>>>>>>>>>> diff --git a/include/linux/coresight.h
>>>>>>>>>>>>> b/include/linux/coresight.h index e8b6e388218c..a9c06ef9bbb2
>>>>>>>>>>>>> 100644
>>>>>>>>>>>>> --- a/include/linux/coresight.h
>>>>>>>>>>>>> +++ b/include/linux/coresight.h
>>>>>>>>>>>>> @@ -167,6 +167,7 @@ struct coresight_desc {
>>>>>>>>>>>>>       * struct coresight_connection - representation of a
>>>>>>>>>>>>> single connection
>>>>>>>>>>>>>       * @src_port:    a connection's output port number.
>>>>>>>>>>>>>       * @dest_port:    destination's input port number 
>>>>>>>>>>>>> @src_port is
>>>>>>>>>>>>> connected to.
>>>>>>>>>>>>> + * @source_label: source component's label.
>>>>>>>>>>>>>       * @dest_fwnode: destination component's fwnode handle.
>>>>>>>>>>>>>       * @dest_dev:    a @coresight_device representation of 
>>>>>>>>>>>>> the
>>>> component
>>>>>>>>>>>>>              connected to @src_port. NULL until the device is
>>>>>>>>>>>>> created @@ -195,6 +196,7 @@ struct coresight_desc {
>>>>>>>>>>>>>      struct coresight_connection {
>>>>>>>>>>>>>          int src_port;
>>>>>>>>>>>>>          int dest_port;
>>>>>>>>>>>>> +    const char *source_label;
>>>>>>>>>>>>>          struct fwnode_handle *dest_fwnode;
>>>>>>>>>>>>>          struct coresight_device *dest_dev;
>>>>>>>>>>>>>          struct coresight_sysfs_link *link;
>>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>
>>>> _______________________________________________
>>>> CoreSight mailing list -- coresight at lists.linaro.org To unsubscribe 
>>>> send an email to
>>>> coresight-leave at lists.linaro.org
>>> _______________________________________________
>>> CoreSight mailing list -- coresight at lists.linaro.org
>>> To unsubscribe send an email to coresight-leave at lists.linaro.org
>>
> 

-- 
Thanks,
Tingwei




More information about the linux-arm-kernel mailing list