* [PATCH 1/2] cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates()
@ 2024-02-29 0:25 Dave Jiang
2024-02-29 0:25 ` [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data Dave Jiang
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Dave Jiang @ 2024-02-29 0:25 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave
The while() loop in cxl_endpoint_get_perf_coordinates() checks to see if
'iter' is valid as part of the condition breaking out of the loop. However,
iter is being used before the check at the end of the while loop before
the next iteration starts. Given that the loop doesn't expect the iter to
be NULL because it stops before the root port, remove the iter check.
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
drivers/cxl/core/port.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index e59d9d37aa65..e1d30a885700 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -2142,7 +2142,7 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
* port each iteration. If the parent is cxl root then there is
* nothing to gather.
*/
- while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) {
+ while (!is_cxl_root(to_cxl_port(iter->dev.parent))) {
combine_coordinates(&c, &dport->sw_coord);
c.write_latency += dport->link_latency;
c.read_latency += dport->link_latency;
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data
2024-02-29 0:25 [PATCH 1/2] cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates() Dave Jiang
@ 2024-02-29 0:25 ` Dave Jiang
2024-02-29 0:35 ` Dan Williams
2024-02-29 17:44 ` Jonathan Cameron
2024-02-29 0:32 ` [PATCH 1/2] cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates() Dan Williams
2024-02-29 17:45 ` Jonathan Cameron
2 siblings, 2 replies; 12+ messages in thread
From: Dave Jiang @ 2024-02-29 0:25 UTC (permalink / raw)
To: linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave
Jonathan noted that when the coordinates for host bridge and switches
can be 0s if no actual data are retrieved and the calculation continues.
The resulting number would be inaccurate. Add checks to ensure that the
calculation would complete only if the numbers are valid.
Reported-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
drivers/cxl/core/port.c | 31 +++++++++++++++++++++++++++----
1 file changed, 27 insertions(+), 4 deletions(-)
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index e1d30a885700..2c82fe24b789 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -2110,6 +2110,20 @@ static void combine_coordinates(struct access_coordinate *c1,
c1->read_latency += c2->read_latency;
}
+static bool coordinates_invalid(struct access_coordinate *c)
+{
+ if (!c->read_bandwidth && !c->write_bandwidth &&
+ !c->read_latency && !c->write_latency)
+ return true;
+
+ return false;
+}
+
+static bool parent_port_is_cxl_root(struct cxl_port *port)
+{
+ return is_cxl_root(to_cxl_port(port->dev.parent));
+}
+
/**
* cxl_endpoint_get_perf_coordinates - Retrieve performance numbers stored in dports
* of CXL path
@@ -2142,16 +2156,25 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
* port each iteration. If the parent is cxl root then there is
* nothing to gather.
*/
- while (!is_cxl_root(to_cxl_port(iter->dev.parent))) {
- combine_coordinates(&c, &dport->sw_coord);
+ while (!parent_port_is_cxl_root(iter)) {
+ iter = to_cxl_port(iter->dev.parent);
+
+ /* There's no CDAT for the host bridge, so skip if so. */
+ if (!parent_port_is_cxl_root(iter)) {
+ if (coordinates_invalid(&dport->sw_coord))
+ return -EINVAL;
+
+ combine_coordinates(&c, &dport->sw_coord);
+ }
+
c.write_latency += dport->link_latency;
c.read_latency += dport->link_latency;
-
- iter = to_cxl_port(iter->dev.parent);
dport = iter->parent_dport;
}
/* Augment with the generic port (host bridge) perf data */
+ if (coordinates_invalid(&dport->hb_coord))
+ return -EINVAL;
combine_coordinates(&c, &dport->hb_coord);
/* Get the calculated PCI paths bandwidth */
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* RE: [PATCH 1/2] cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates()
2024-02-29 0:25 [PATCH 1/2] cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates() Dave Jiang
2024-02-29 0:25 ` [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data Dave Jiang
@ 2024-02-29 0:32 ` Dan Williams
2024-02-29 0:36 ` Dave Jiang
2024-02-29 17:45 ` Jonathan Cameron
2 siblings, 1 reply; 12+ messages in thread
From: Dan Williams @ 2024-02-29 0:32 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave
Dave Jiang wrote:
> The while() loop in cxl_endpoint_get_perf_coordinates() checks to see if
> 'iter' is valid as part of the condition breaking out of the loop. However,
> iter is being used before the check at the end of the while loop before
> the next iteration starts. Given that the loop doesn't expect the iter to
> be NULL because it stops before the root port, remove the iter check.
This smells like a fix, but no "Fix" in the title or "Fixes" tag. So, is
this a cleanup or a fix, and if it a fix what are the user visible
effects of the bug?
^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data
2024-02-29 0:25 ` [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data Dave Jiang
@ 2024-02-29 0:35 ` Dan Williams
2024-02-29 0:39 ` Dave Jiang
2024-02-29 17:44 ` Jonathan Cameron
1 sibling, 1 reply; 12+ messages in thread
From: Dan Williams @ 2024-02-29 0:35 UTC (permalink / raw)
To: Dave Jiang, linux-cxl
Cc: dan.j.williams, ira.weiny, vishal.l.verma, alison.schofield,
Jonathan.Cameron, dave
Dave Jiang wrote:
> Jonathan noted that when the coordinates for host bridge and switches
> can be 0s if no actual data are retrieved and the calculation continues.
> The resulting number would be inaccurate. Add checks to ensure that the
> calculation would complete only if the numbers are valid.
Similar comment as patch1. This smells like a fix, is this an urgent
thing to get into v6.8, i.e. most configurations are busted without
this, or is a nice to have fixup for a QEMU effect that may or may not
show up in physical systems?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates()
2024-02-29 0:32 ` [PATCH 1/2] cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates() Dan Williams
@ 2024-02-29 0:36 ` Dave Jiang
0 siblings, 0 replies; 12+ messages in thread
From: Dave Jiang @ 2024-02-29 0:36 UTC (permalink / raw)
To: Dan Williams, linux-cxl
Cc: ira.weiny, vishal.l.verma, alison.schofield, Jonathan.Cameron,
dave
On 2/28/24 5:32 PM, Dan Williams wrote:
> Dave Jiang wrote:
>> The while() loop in cxl_endpoint_get_perf_coordinates() checks to see if
>> 'iter' is valid as part of the condition breaking out of the loop. However,
>> iter is being used before the check at the end of the while loop before
>> the next iteration starts. Given that the loop doesn't expect the iter to
>> be NULL because it stops before the root port, remove the iter check.
>
> This smells like a fix, but no "Fix" in the title or "Fixes" tag. So, is
> this a cleanup or a fix, and if it a fix what are the user visible
> effects of the bug?
I debated on this and in the end decided that it doesn't need to be a fix because there is no impact whether we check the iter or not in the loop since iter should not ever be NULL.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data
2024-02-29 0:35 ` Dan Williams
@ 2024-02-29 0:39 ` Dave Jiang
2024-02-29 0:44 ` Dan Williams
0 siblings, 1 reply; 12+ messages in thread
From: Dave Jiang @ 2024-02-29 0:39 UTC (permalink / raw)
To: Dan Williams, linux-cxl
Cc: ira.weiny, vishal.l.verma, alison.schofield, Jonathan.Cameron,
dave
On 2/28/24 5:35 PM, Dan Williams wrote:
> Dave Jiang wrote:
>> Jonathan noted that when the coordinates for host bridge and switches
>> can be 0s if no actual data are retrieved and the calculation continues.
>> The resulting number would be inaccurate. Add checks to ensure that the
>> calculation would complete only if the numbers are valid.
>
> Similar comment as patch1. This smells like a fix, is this an urgent
> thing to get into v6.8, i.e. most configurations are busted without
> this, or is a nice to have fixup for a QEMU effect that may or may not
> show up in physical systems?
This would only be an issue if the switches do not supply a proper CDAT and/or if BIOS does not provide proper ACPI tables. I think it is only experienced on QEMU currently. I'll add a fix tag if you think it should be a fix.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data
2024-02-29 0:39 ` Dave Jiang
@ 2024-02-29 0:44 ` Dan Williams
2024-02-29 17:25 ` Jonathan Cameron
0 siblings, 1 reply; 12+ messages in thread
From: Dan Williams @ 2024-02-29 0:44 UTC (permalink / raw)
To: Dave Jiang, Dan Williams, linux-cxl
Cc: ira.weiny, vishal.l.verma, alison.schofield, Jonathan.Cameron,
dave
Dave Jiang wrote:
>
>
> On 2/28/24 5:35 PM, Dan Williams wrote:
> > Dave Jiang wrote:
> >> Jonathan noted that when the coordinates for host bridge and switches
> >> can be 0s if no actual data are retrieved and the calculation continues.
> >> The resulting number would be inaccurate. Add checks to ensure that the
> >> calculation would complete only if the numbers are valid.
> >
> > Similar comment as patch1. This smells like a fix, is this an urgent
> > thing to get into v6.8, i.e. most configurations are busted without
> > this, or is a nice to have fixup for a QEMU effect that may or may not
> > show up in physical systems?
>
> This would only be an issue if the switches do not supply a proper
> CDAT and/or if BIOS does not provide proper ACPI tables. I think it is
> only experienced on QEMU currently. I'll add a fix tag if you think it
> should be a fix.
No, but please add that relevant clarification of impact to the
changelog. It would have made it clear this is a nice to have thing for
v6.9, nothing to worry about for v6.8.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data
2024-02-29 0:44 ` Dan Williams
@ 2024-02-29 17:25 ` Jonathan Cameron
0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2024-02-29 17:25 UTC (permalink / raw)
To: Dan Williams
Cc: Dave Jiang, linux-cxl, ira.weiny, vishal.l.verma,
alison.schofield, dave
On Wed, 28 Feb 2024 16:44:29 -0800
Dan Williams <dan.j.williams@intel.com> wrote:
> Dave Jiang wrote:
> >
> >
> > On 2/28/24 5:35 PM, Dan Williams wrote:
> > > Dave Jiang wrote:
> > >> Jonathan noted that when the coordinates for host bridge and switches
> > >> can be 0s if no actual data are retrieved and the calculation continues.
> > >> The resulting number would be inaccurate. Add checks to ensure that the
> > >> calculation would complete only if the numbers are valid.
> > >
> > > Similar comment as patch1. This smells like a fix, is this an urgent
> > > thing to get into v6.8, i.e. most configurations are busted without
> > > this, or is a nice to have fixup for a QEMU effect that may or may not
> > > show up in physical systems?
> >
> > This would only be an issue if the switches do not supply a proper
> > CDAT and/or if BIOS does not provide proper ACPI tables. I think it is
> > only experienced on QEMU currently. I'll add a fix tag if you think it
> > should be a fix.
>
> No, but please add that relevant clarification of impact to the
> changelog. It would have made it clear this is a nice to have thing for
> v6.9, nothing to worry about for v6.8.
Not seen in wild, but it might show up with a BIOS that reported
CXL root ports via Generic Ports (via a PCI handle in the SRAT entry)
rather than CXL Host Bridge (via an ACPI Handle int he SRAT entry).
The code doesn't yet support this case (which is fine) but it should
cleanly not support it rather than giving wrong numbers. There
are other fun corners like embedded CXL switches in the host where
the reporting will also be more 'creative'. I expect we will see
these eventually but not in first generation or two.
I 'think' this would be a reasonable system choice as there is nothing
to say that a CXL hostbridge doesn't have a bunch of root ports
(potentially on different dies) that have different host initiator
to port exit latency and bandwidth characteristics.
Whilst no known hardware. I don't think this is a FW bug case only.
Not a rush job though, fixes tag + 6.9 will be fine.
Jonathan
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data
2024-02-29 0:25 ` [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data Dave Jiang
2024-02-29 0:35 ` Dan Williams
@ 2024-02-29 17:44 ` Jonathan Cameron
2024-03-05 22:36 ` Dave Jiang
1 sibling, 1 reply; 12+ messages in thread
From: Jonathan Cameron @ 2024-02-29 17:44 UTC (permalink / raw)
To: Dave Jiang
Cc: linux-cxl, dan.j.williams, ira.weiny, vishal.l.verma,
alison.schofield, dave
On Wed, 28 Feb 2024 17:25:42 -0700
Dave Jiang <dave.jiang@intel.com> wrote:
> Jonathan noted that when the coordinates for host bridge and switches
> can be 0s if no actual data are retrieved and the calculation continues.
> The resulting number would be inaccurate. Add checks to ensure that the
> calculation would complete only if the numbers are valid.
>
> Reported-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Hi Dave,
Whilst I think the fix is right, it is getting hard to read. Maybe
a rethink is needed on how that iteration works?
> ---
> drivers/cxl/core/port.c | 31 +++++++++++++++++++++++++++----
> 1 file changed, 27 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
> index e1d30a885700..2c82fe24b789 100644
> --- a/drivers/cxl/core/port.c
> +++ b/drivers/cxl/core/port.c
> @@ -2110,6 +2110,20 @@ static void combine_coordinates(struct access_coordinate *c1,
> c1->read_latency += c2->read_latency;
> }
>
> +static bool coordinates_invalid(struct access_coordinate *c)
> +{
> + if (!c->read_bandwidth && !c->write_bandwidth &&
> + !c->read_latency && !c->write_latency)
> + return true;
> +
> + return false;
> +}
> +
> +static bool parent_port_is_cxl_root(struct cxl_port *port)
> +{
> + return is_cxl_root(to_cxl_port(port->dev.parent));
> +}
> +
> /**
> * cxl_endpoint_get_perf_coordinates - Retrieve performance numbers stored in dports
> * of CXL path
> @@ -2142,16 +2156,25 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
> * port each iteration. If the parent is cxl root then there is
> * nothing to gather.
> */
> - while (!is_cxl_root(to_cxl_port(iter->dev.parent))) {
> - combine_coordinates(&c, &dport->sw_coord);
> + while (!parent_port_is_cxl_root(iter)) {
> + iter = to_cxl_port(iter->dev.parent);
> +
> + /* There's no CDAT for the host bridge, so skip if so. */
Comment refers to skipping whereas code is 'doing more' for the other case
so this is confusing to me.
The inverse of this only occurs on the last iteration I think.
Possibly a do / while instead of a while will do it.
I'm far from confident though as all the levels of look up have
me too confused.
do {
if (coordinates_invalid(&dport->sw_coord))
return -EINVAL;
combine_coordinates(&c, &dport->sw_coord);
iter = to_cxl_port(iter->dev.parent);
dport = iter->parent_dport;
} while (!parent_port_is_cxl_root(iter));
/* Do final link updates */
c.write_latency += dport->link_latency;
c.read_latency += dport->link_latency;
> + if (!parent_port_is_cxl_root(iter)) {
> + if (coordinates_invalid(&dport->sw_coord))
> + return -EINVAL;
> +
> + combine_coordinates(&c, &dport->sw_coord);
> + }
> +
> c.write_latency += dport->link_latency;
> c.read_latency += dport->link_latency;
> -
> - iter = to_cxl_port(iter->dev.parent);
> dport = iter->parent_dport;
> }
>
> /* Augment with the generic port (host bridge) perf data */
> + if (coordinates_invalid(&dport->hb_coord))
> + return -EINVAL;
> combine_coordinates(&c, &dport->hb_coord);
>
> /* Get the calculated PCI paths bandwidth */
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates()
2024-02-29 0:25 [PATCH 1/2] cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates() Dave Jiang
2024-02-29 0:25 ` [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data Dave Jiang
2024-02-29 0:32 ` [PATCH 1/2] cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates() Dan Williams
@ 2024-02-29 17:45 ` Jonathan Cameron
2 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2024-02-29 17:45 UTC (permalink / raw)
To: Dave Jiang
Cc: linux-cxl, dan.j.williams, ira.weiny, vishal.l.verma,
alison.schofield, dave
On Wed, 28 Feb 2024 17:25:41 -0700
Dave Jiang <dave.jiang@intel.com> wrote:
> The while() loop in cxl_endpoint_get_perf_coordinates() checks to see if
> 'iter' is valid as part of the condition breaking out of the loop. However,
> iter is being used before the check at the end of the while loop before
> the next iteration starts. Given that the loop doesn't expect the iter to
> be NULL because it stops before the root port, remove the iter check.
>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> drivers/cxl/core/port.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
> index e59d9d37aa65..e1d30a885700 100644
> --- a/drivers/cxl/core/port.c
> +++ b/drivers/cxl/core/port.c
> @@ -2142,7 +2142,7 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
> * port each iteration. If the parent is cxl root then there is
> * nothing to gather.
> */
> - while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) {
> + while (!is_cxl_root(to_cxl_port(iter->dev.parent))) {
> combine_coordinates(&c, &dport->sw_coord);
> c.write_latency += dport->link_latency;
> c.read_latency += dport->link_latency;
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data
2024-02-29 17:44 ` Jonathan Cameron
@ 2024-03-05 22:36 ` Dave Jiang
2024-03-06 0:18 ` Dave Jiang
0 siblings, 1 reply; 12+ messages in thread
From: Dave Jiang @ 2024-03-05 22:36 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-cxl, dan.j.williams, ira.weiny, vishal.l.verma,
alison.schofield, dave
On 2/29/24 10:44 AM, Jonathan Cameron wrote:
> On Wed, 28 Feb 2024 17:25:42 -0700
> Dave Jiang <dave.jiang@intel.com> wrote:
>
>> Jonathan noted that when the coordinates for host bridge and switches
>> can be 0s if no actual data are retrieved and the calculation continues.
>> The resulting number would be inaccurate. Add checks to ensure that the
>> calculation would complete only if the numbers are valid.
>>
>> Reported-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
>
> Hi Dave,
>
> Whilst I think the fix is right, it is getting hard to read. Maybe
> a rethink is needed on how that iteration works?
>
>> ---
>> drivers/cxl/core/port.c | 31 +++++++++++++++++++++++++++----
>> 1 file changed, 27 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
>> index e1d30a885700..2c82fe24b789 100644
>> --- a/drivers/cxl/core/port.c
>> +++ b/drivers/cxl/core/port.c
>> @@ -2110,6 +2110,20 @@ static void combine_coordinates(struct access_coordinate *c1,
>> c1->read_latency += c2->read_latency;
>> }
>>
>> +static bool coordinates_invalid(struct access_coordinate *c)
>> +{
>> + if (!c->read_bandwidth && !c->write_bandwidth &&
>> + !c->read_latency && !c->write_latency)
>> + return true;
>> +
>> + return false;
>> +}
>> +
>> +static bool parent_port_is_cxl_root(struct cxl_port *port)
>> +{
>> + return is_cxl_root(to_cxl_port(port->dev.parent));
>> +}
>> +
>> /**
>> * cxl_endpoint_get_perf_coordinates - Retrieve performance numbers stored in dports
>> * of CXL path
>> @@ -2142,16 +2156,25 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
>> * port each iteration. If the parent is cxl root then there is
>> * nothing to gather.
>> */
>> - while (!is_cxl_root(to_cxl_port(iter->dev.parent))) {
>> - combine_coordinates(&c, &dport->sw_coord);
>> + while (!parent_port_is_cxl_root(iter)) {
>> + iter = to_cxl_port(iter->dev.parent);
>> +
>> + /* There's no CDAT for the host bridge, so skip if so. */
>
> Comment refers to skipping whereas code is 'doing more' for the other case
> so this is confusing to me.
>
> The inverse of this only occurs on the last iteration I think.
>
> Possibly a do / while instead of a while will do it.
> I'm far from confident though as all the levels of look up have
> me too confused.
So this is somewhat tricky. For example:
devices/pci0000:35/0000:35:01.0/0000:37:00.0/mem5
In this case the endpoint is attached to the host bridge without any switches. The endpoint is 0000:37:00.0 and the host bridge down stream port is 0000:35:01.0. In this instance there is no switch and therefore switch CDAT, but there is a valid dport. So we would skip the dport->sw_coord. However, we do need to pick up the link_latency between endpoint and downstream port. So we spend 1 iteration in the loop and skips the dport->sw_coord.
devices/pci0000:bf/0000:bf:00.0/0000:c0:00.0/0000:c1:00.0/0000:c2:00.0/mem8
Now in this case there's a CXL switch in between. So in first iteration, we pick up the dport->sw_coord. And in second iteration, we skip the dport->sw_coord. However, we would be adding two link_latency. For the link between 0000:c2:00.0 (endpoint) and 0000:c1:00.0 (switch downstream port), and the link between 0000:c0:00.0 (switch upstream port) and 0000:bf:00.0 (host bridge down stream port). So therefore we can't put the sum of link_latency outside of the loop.
Not sure how much better this is:
do {
struct cxl_port *parent_port = to_cxl_port(iter->dev.parent);
dport = iter->parent_dport;
if (!parent_port_is_cxl_root(parent_port)) {
if (coordinates_invalid(&dport->sw_coord))
return -EINVAL;
combine_coordinates(&c, &dport->sw_coord);
}
c.write_latency += dport->link_latency;
c.read_latency += dport->link_latency;
iter = to_cxl_port(iter->dev.parent);
} while (!parent_port_is_cxl_root(iter));
or:
do {
struct cxl_port *parent_port = to_cxl_port(iter->dev.parent);
dport = iter->parent_dport;
c.write_latency += dport->link_latency;
c.read_latency += dport->link_latency;
if (parent_port_is_cxl_root(parent_port))
break;
if (coordinates_invalid(&dport->sw_coord))
return -EINVAL;
combine_coordinates(&c, &dport->sw_coord);
iter = to_cxl_port(iter->dev.parent);
} while (!parent_port_is_cxl_root(iter));
>
>
> do {
> if (coordinates_invalid(&dport->sw_coord))
> return -EINVAL;
>
> combine_coordinates(&c, &dport->sw_coord);
> iter = to_cxl_port(iter->dev.parent);
> dport = iter->parent_dport;
> } while (!parent_port_is_cxl_root(iter));
> /* Do final link updates */
> c.write_latency += dport->link_latency;
> c.read_latency += dport->link_latency;
>
>> + if (!parent_port_is_cxl_root(iter)) {
>> + if (coordinates_invalid(&dport->sw_coord))
>> + return -EINVAL;
>> +
>> + combine_coordinates(&c, &dport->sw_coord);
>> + }
>> +
>> c.write_latency += dport->link_latency;
>> c.read_latency += dport->link_latency;
>> -
>> - iter = to_cxl_port(iter->dev.parent);
>> dport = iter->parent_dport;
>> }
>>
>> /* Augment with the generic port (host bridge) perf data */
>> + if (coordinates_invalid(&dport->hb_coord))
>> + return -EINVAL;
>> combine_coordinates(&c, &dport->hb_coord);
>>
>> /* Get the calculated PCI paths bandwidth */
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data
2024-03-05 22:36 ` Dave Jiang
@ 2024-03-06 0:18 ` Dave Jiang
0 siblings, 0 replies; 12+ messages in thread
From: Dave Jiang @ 2024-03-06 0:18 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-cxl, dan.j.williams, ira.weiny, vishal.l.verma,
alison.schofield, dave
On 3/5/24 3:36 PM, Dave Jiang wrote:
>
>
> On 2/29/24 10:44 AM, Jonathan Cameron wrote:
>> On Wed, 28 Feb 2024 17:25:42 -0700
>> Dave Jiang <dave.jiang@intel.com> wrote:
>>
>>> Jonathan noted that when the coordinates for host bridge and switches
>>> can be 0s if no actual data are retrieved and the calculation continues.
>>> The resulting number would be inaccurate. Add checks to ensure that the
>>> calculation would complete only if the numbers are valid.
>>>
>>> Reported-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
>>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
>>
>> Hi Dave,
>>
>> Whilst I think the fix is right, it is getting hard to read. Maybe
>> a rethink is needed on how that iteration works?
>>
>>> ---
>>> drivers/cxl/core/port.c | 31 +++++++++++++++++++++++++++----
>>> 1 file changed, 27 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
>>> index e1d30a885700..2c82fe24b789 100644
>>> --- a/drivers/cxl/core/port.c
>>> +++ b/drivers/cxl/core/port.c
>>> @@ -2110,6 +2110,20 @@ static void combine_coordinates(struct access_coordinate *c1,
>>> c1->read_latency += c2->read_latency;
>>> }
>>>
>>> +static bool coordinates_invalid(struct access_coordinate *c)
>>> +{
>>> + if (!c->read_bandwidth && !c->write_bandwidth &&
>>> + !c->read_latency && !c->write_latency)
>>> + return true;
>>> +
>>> + return false;
>>> +}
>>> +
>>> +static bool parent_port_is_cxl_root(struct cxl_port *port)
>>> +{
>>> + return is_cxl_root(to_cxl_port(port->dev.parent));
>>> +}
>>> +
>>> /**
>>> * cxl_endpoint_get_perf_coordinates - Retrieve performance numbers stored in dports
>>> * of CXL path
>>> @@ -2142,16 +2156,25 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
>>> * port each iteration. If the parent is cxl root then there is
>>> * nothing to gather.
>>> */
>>> - while (!is_cxl_root(to_cxl_port(iter->dev.parent))) {
>>> - combine_coordinates(&c, &dport->sw_coord);
>>> + while (!parent_port_is_cxl_root(iter)) {
>>> + iter = to_cxl_port(iter->dev.parent);
>>> +
>>> + /* There's no CDAT for the host bridge, so skip if so. */
>>
>> Comment refers to skipping whereas code is 'doing more' for the other case
>> so this is confusing to me.
>>
>> The inverse of this only occurs on the last iteration I think.
>>
>> Possibly a do / while instead of a while will do it.
>> I'm far from confident though as all the levels of look up have
>> me too confused.
>
> So this is somewhat tricky. For example:
> devices/pci0000:35/0000:35:01.0/0000:37:00.0/mem5
>
> In this case the endpoint is attached to the host bridge without any switches. The endpoint is 0000:37:00.0 and the host bridge down stream port is 0000:35:01.0. In this instance there is no switch and therefore switch CDAT, but there is a valid dport. So we would skip the dport->sw_coord. However, we do need to pick up the link_latency between endpoint and downstream port. So we spend 1 iteration in the loop and skips the dport->sw_coord.
>
> devices/pci0000:bf/0000:bf:00.0/0000:c0:00.0/0000:c1:00.0/0000:c2:00.0/mem8
>
> Now in this case there's a CXL switch in between. So in first iteration, we pick up the dport->sw_coord. And in second iteration, we skip the dport->sw_coord. However, we would be adding two link_latency. For the link between 0000:c2:00.0 (endpoint) and 0000:c1:00.0 (switch downstream port), and the link between 0000:c0:00.0 (switch upstream port) and 0000:bf:00.0 (host bridge down stream port). So therefore we can't put the sum of link_latency outside of the loop.
>
> Not sure how much better this is:
>
> do {
> struct cxl_port *parent_port = to_cxl_port(iter->dev.parent);
>
> dport = iter->parent_dport;
> if (!parent_port_is_cxl_root(parent_port)) {
> if (coordinates_invalid(&dport->sw_coord))
> return -EINVAL;
>
> combine_coordinates(&c, &dport->sw_coord);
> }
>
> c.write_latency += dport->link_latency;
> c.read_latency += dport->link_latency;
> iter = to_cxl_port(iter->dev.parent);
> } while (!parent_port_is_cxl_root(iter));
>
> or:
>
> do {
> struct cxl_port *parent_port = to_cxl_port(iter->dev.parent);
>
> dport = iter->parent_dport;
> c.write_latency += dport->link_latency;
> c.read_latency += dport->link_latency;
>
> if (parent_port_is_cxl_root(parent_port))
> break;
>
> if (coordinates_invalid(&dport->sw_coord))
> return -EINVAL;
>
> combine_coordinates(&c, &dport->sw_coord);
> iter = to_cxl_port(iter->dev.parent);
> } while (!parent_port_is_cxl_root(iter));
Actually, I think if we just make it dport->coord instead of dport->sw_coord and dport->hb_coord, we can remove the check and everything should work out properly.
>
>
>>
>>
>> do {
>> if (coordinates_invalid(&dport->sw_coord))
>> return -EINVAL;
>>
>> combine_coordinates(&c, &dport->sw_coord);
>> iter = to_cxl_port(iter->dev.parent);
>> dport = iter->parent_dport;
>> } while (!parent_port_is_cxl_root(iter));
>> /* Do final link updates */
>> c.write_latency += dport->link_latency;
>> c.read_latency += dport->link_latency;
>>
>>> + if (!parent_port_is_cxl_root(iter)) {
>>> + if (coordinates_invalid(&dport->sw_coord))
>>> + return -EINVAL;
>>> +
>>> + combine_coordinates(&c, &dport->sw_coord);
>>> + }
>>> +
>>> c.write_latency += dport->link_latency;
>>> c.read_latency += dport->link_latency;
>>> -
>>> - iter = to_cxl_port(iter->dev.parent);
>>> dport = iter->parent_dport;
>>> }
>>>
>>> /* Augment with the generic port (host bridge) perf data */
>>> + if (coordinates_invalid(&dport->hb_coord))
>>> + return -EINVAL;
>>> combine_coordinates(&c, &dport->hb_coord);
>>>
>>> /* Get the calculated PCI paths bandwidth */
>>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-03-06 0:19 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-29 0:25 [PATCH 1/2] cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates() Dave Jiang
2024-02-29 0:25 ` [PATCH 2/2] cxl: Add checks to access_coordinate calculation to fail missing data Dave Jiang
2024-02-29 0:35 ` Dan Williams
2024-02-29 0:39 ` Dave Jiang
2024-02-29 0:44 ` Dan Williams
2024-02-29 17:25 ` Jonathan Cameron
2024-02-29 17:44 ` Jonathan Cameron
2024-03-05 22:36 ` Dave Jiang
2024-03-06 0:18 ` Dave Jiang
2024-02-29 0:32 ` [PATCH 1/2] cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates() Dan Williams
2024-02-29 0:36 ` Dave Jiang
2024-02-29 17:45 ` Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox