drivers/cxl/core/port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
If a switch port has more than one decoder that is using the same
downstream port, the enumeration of the target lists may fail with:
# dmesg | grep target.list
update_decoder_targets: cxl decoder1.0: dport3 found in target list, index 3
update_decoder_targets: cxl decoder1.0: dport2 found in target list, index 2
update_decoder_targets: cxl decoder1.0: dport0 found in target list, index 0
update_decoder_targets: cxl decoder2.0: dport3 found in target list, index 1
update_decoder_targets: cxl decoder4.0: dport3 found in target list, index 1
cxl_mem mem6: failed to find endpoint12:0000:00:01.4 in target list of decoder2.1
cxl_mem mem8: failed to find endpoint13:0000:20:01.4 in target list of decoder4.1
The case, that the same downstream port can be used in multiple target
lists, is allowed and possible.
Fix the update of the target list. Enumerate all children of the
switch port and do not stop the iteration after the first matching
target was found.
With the fix applied:
# dmesg | grep target.list
update_decoder_targets: cxl decoder1.0: dport2 found in target list, index 2
update_decoder_targets: cxl decoder1.0: dport0 found in target list, index 0
update_decoder_targets: cxl decoder1.0: dport3 found in target list, index 3
update_decoder_targets: cxl decoder2.0: dport3 found in target list, index 1
update_decoder_targets: cxl decoder2.1: dport3 found in target list, index 1
update_decoder_targets: cxl decoder4.0: dport3 found in target list, index 1
update_decoder_targets: cxl decoder4.1: dport3 found in target list, index 1
Analyzing the conditions when this happens:
1) A dport is shared by multiple decoders.
2) The decoders have interleaving configured (ways > 1).
The configuration above has the following hierarchy details (fixed
version):
root0
|_
| |
| decoder0.1
| ways: 2
| target_list: 0,1
|_______________________________________
| |
| dport0 | dport1
| |
port2 port4
| |
|___________________ |_____________________
| | | | | |
| decoder2.0 decoder2.1 | decoder4.0 decoder4.1
| ways: 2 ways: 2 | ways: 2 ways: 2
| target_list: 2,3 target_list: 2,3 | target_list: 2,3 target_list: 2,3
|___________________ |___________________
| | | |
| dport2 | dport3 | dport2 | dport3
| | | |
endpoint7 endpoint12 endpoint9 endpoint13
|_ |_ |_ |_
| | | | | | | |
| decoder7.0 | decoder12.0 | decoder9.0 | decoder13.0
| decoder7.2 | decoder12.2 | decoder9.2 | decoder13.2
| | | |
mem3 mem5 mem6 mem8
Note: Device numbers vary for every boot.
Current kernel fails to enumerate endpoint12 and endpoint13 as the
target list is not updated for the second decoder.
Fixes: 4f06d81e7c6a ("cxl: Defer dport allocation for switch ports")
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Signed-off-by: Robert Richter <rrichter@amd.com>
---
v2:
* updated sob-chain,
* added fixes tag (Dave).
---
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 fef3aa0c6680..3310dbfae9d6 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -1590,7 +1590,7 @@ static int update_decoder_targets(struct device *dev, void *data)
cxlsd->target[i] = dport;
dev_dbg(dev, "dport%d found in target list, index %d\n",
dport->port_id, i);
- return 1;
+ return 0;
}
}
base-commit: 88c72bab77aaf389beccf762e112828253ca0564
prerequisite-patch-id: f44102a7b095afa1588a5cac012ec2e0d852c021
--
2.47.3
On 1/8/26 3:13 AM, Robert Richter wrote:
> If a switch port has more than one decoder that is using the same
> downstream port, the enumeration of the target lists may fail with:
>
> # dmesg | grep target.list
> update_decoder_targets: cxl decoder1.0: dport3 found in target list, index 3
> update_decoder_targets: cxl decoder1.0: dport2 found in target list, index 2
> update_decoder_targets: cxl decoder1.0: dport0 found in target list, index 0
> update_decoder_targets: cxl decoder2.0: dport3 found in target list, index 1
> update_decoder_targets: cxl decoder4.0: dport3 found in target list, index 1
> cxl_mem mem6: failed to find endpoint12:0000:00:01.4 in target list of decoder2.1
> cxl_mem mem8: failed to find endpoint13:0000:20:01.4 in target list of decoder4.1
>
> The case, that the same downstream port can be used in multiple target
> lists, is allowed and possible.
>
> Fix the update of the target list. Enumerate all children of the
> switch port and do not stop the iteration after the first matching
> target was found.
>
> With the fix applied:
>
> # dmesg | grep target.list
> update_decoder_targets: cxl decoder1.0: dport2 found in target list, index 2
> update_decoder_targets: cxl decoder1.0: dport0 found in target list, index 0
> update_decoder_targets: cxl decoder1.0: dport3 found in target list, index 3
> update_decoder_targets: cxl decoder2.0: dport3 found in target list, index 1
> update_decoder_targets: cxl decoder2.1: dport3 found in target list, index 1
> update_decoder_targets: cxl decoder4.0: dport3 found in target list, index 1
> update_decoder_targets: cxl decoder4.1: dport3 found in target list, index 1
>
> Analyzing the conditions when this happens:
>
> 1) A dport is shared by multiple decoders.
>
> 2) The decoders have interleaving configured (ways > 1).
>
> The configuration above has the following hierarchy details (fixed
> version):
>
> root0
> |_
> | |
> | decoder0.1
> | ways: 2
> | target_list: 0,1
> |_______________________________________
> | |
> | dport0 | dport1
> | |
> port2 port4
> | |
> |___________________ |_____________________
> | | | | | |
> | decoder2.0 decoder2.1 | decoder4.0 decoder4.1
> | ways: 2 ways: 2 | ways: 2 ways: 2
> | target_list: 2,3 target_list: 2,3 | target_list: 2,3 target_list: 2,3
> |___________________ |___________________
> | | | |
> | dport2 | dport3 | dport2 | dport3
> | | | |
> endpoint7 endpoint12 endpoint9 endpoint13
> |_ |_ |_ |_
> | | | | | | | |
> | decoder7.0 | decoder12.0 | decoder9.0 | decoder13.0
> | decoder7.2 | decoder12.2 | decoder9.2 | decoder13.2
> | | | |
> mem3 mem5 mem6 mem8
>
> Note: Device numbers vary for every boot.
>
> Current kernel fails to enumerate endpoint12 and endpoint13 as the
> target list is not updated for the second decoder.
>
> Fixes: 4f06d81e7c6a ("cxl: Defer dport allocation for switch ports")
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Alison Schofield <alison.schofield@intel.com>
> Signed-off-by: Robert Richter <rrichter@amd.com>
Applied to cxl/fixes
3e8aaacdad4f66641f87ab441fe644b45f8ebdff
> ---
> v2:
> * updated sob-chain,
> * added fixes tag (Dave).
> ---
> 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 fef3aa0c6680..3310dbfae9d6 100644
> --- a/drivers/cxl/core/port.c
> +++ b/drivers/cxl/core/port.c
> @@ -1590,7 +1590,7 @@ static int update_decoder_targets(struct device *dev, void *data)
> cxlsd->target[i] = dport;
> dev_dbg(dev, "dport%d found in target list, index %d\n",
> dport->port_id, i);
> - return 1;
> + return 0;
> }
> }
>
>
> base-commit: 88c72bab77aaf389beccf762e112828253ca0564
> prerequisite-patch-id: f44102a7b095afa1588a5cac012ec2e0d852c021
On Thu, 8 Jan 2026 11:13:23 +0100
Robert Richter <rrichter@amd.com> wrote:
> If a switch port has more than one decoder that is using the same
> downstream port, the enumeration of the target lists may fail with:
>
> # dmesg | grep target.list
> update_decoder_targets: cxl decoder1.0: dport3 found in target list, index 3
> update_decoder_targets: cxl decoder1.0: dport2 found in target list, index 2
> update_decoder_targets: cxl decoder1.0: dport0 found in target list, index 0
> update_decoder_targets: cxl decoder2.0: dport3 found in target list, index 1
> update_decoder_targets: cxl decoder4.0: dport3 found in target list, index 1
> cxl_mem mem6: failed to find endpoint12:0000:00:01.4 in target list of decoder2.1
> cxl_mem mem8: failed to find endpoint13:0000:20:01.4 in target list of decoder4.1
>
> The case, that the same downstream port can be used in multiple target
> lists, is allowed and possible.
>
> Fix the update of the target list. Enumerate all children of the
> switch port and do not stop the iteration after the first matching
> target was found.
>
> With the fix applied:
>
> # dmesg | grep target.list
> update_decoder_targets: cxl decoder1.0: dport2 found in target list, index 2
> update_decoder_targets: cxl decoder1.0: dport0 found in target list, index 0
> update_decoder_targets: cxl decoder1.0: dport3 found in target list, index 3
> update_decoder_targets: cxl decoder2.0: dport3 found in target list, index 1
> update_decoder_targets: cxl decoder2.1: dport3 found in target list, index 1
> update_decoder_targets: cxl decoder4.0: dport3 found in target list, index 1
> update_decoder_targets: cxl decoder4.1: dport3 found in target list, index 1
>
> Analyzing the conditions when this happens:
>
> 1) A dport is shared by multiple decoders.
>
> 2) The decoders have interleaving configured (ways > 1).
>
> The configuration above has the following hierarchy details (fixed
> version):
>
> root0
> |_
> | |
> | decoder0.1
Hi Robert,
I'm struggling a bit to align this with the above prints. Where is
decoder1.0 for example? As it's below the root port, I think it's the
host bridge decoder, which might be this one on your diagram?
Fix makes sense to me.
Jonathan
> | ways: 2
> | target_list: 0,1
> |_______________________________________
> | |
> | dport0 | dport1
> | |
> port2 port4
> | |
> |___________________ |_____________________
> | | | | | |
> | decoder2.0 decoder2.1 | decoder4.0 decoder4.1
> | ways: 2 ways: 2 | ways: 2 ways: 2
> | target_list: 2,3 target_list: 2,3 | target_list: 2,3 target_list: 2,3
> |___________________ |___________________
> | | | |
> | dport2 | dport3 | dport2 | dport3
> | | | |
> endpoint7 endpoint12 endpoint9 endpoint13
> |_ |_ |_ |_
> | | | | | | | |
> | decoder7.0 | decoder12.0 | decoder9.0 | decoder13.0
> | decoder7.2 | decoder12.2 | decoder9.2 | decoder13.2
> | | | |
> mem3 mem5 mem6 mem8
>
> Note: Device numbers vary for every boot.
>
> Current kernel fails to enumerate endpoint12 and endpoint13 as the
> target list is not updated for the second decoder.
>
> Fixes: 4f06d81e7c6a ("cxl: Defer dport allocation for switch ports")
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Alison Schofield <alison.schofield@intel.com>
> Signed-off-by: Robert Richter <rrichter@amd.com>
> ---
> v2:
> * updated sob-chain,
> * added fixes tag (Dave).
> ---
> 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 fef3aa0c6680..3310dbfae9d6 100644
> --- a/drivers/cxl/core/port.c
> +++ b/drivers/cxl/core/port.c
> @@ -1590,7 +1590,7 @@ static int update_decoder_targets(struct device *dev, void *data)
> cxlsd->target[i] = dport;
> dev_dbg(dev, "dport%d found in target list, index %d\n",
> dport->port_id, i);
> - return 1;
> + return 0;
> }
> }
>
>
> base-commit: 88c72bab77aaf389beccf762e112828253ca0564
> prerequisite-patch-id: f44102a7b095afa1588a5cac012ec2e0d852c021
On Thu, Jan 08, 2026 at 04:08:35PM +0000, Jonathan Cameron wrote:
> On Thu, 8 Jan 2026 11:13:23 +0100
> Robert Richter <rrichter@amd.com> wrote:
>
> > If a switch port has more than one decoder that is using the same
> > downstream port, the enumeration of the target lists may fail with:
> >
> > # dmesg | grep target.list
> > update_decoder_targets: cxl decoder1.0: dport3 found in target list, index 3
> > update_decoder_targets: cxl decoder1.0: dport2 found in target list, index 2
> > update_decoder_targets: cxl decoder1.0: dport0 found in target list, index 0
> > update_decoder_targets: cxl decoder2.0: dport3 found in target list, index 1
> > update_decoder_targets: cxl decoder4.0: dport3 found in target list, index 1
> > cxl_mem mem6: failed to find endpoint12:0000:00:01.4 in target list of decoder2.1
> > cxl_mem mem8: failed to find endpoint13:0000:20:01.4 in target list of decoder4.1
> >
> > The case, that the same downstream port can be used in multiple target
> > lists, is allowed and possible.
> >
> > Fix the update of the target list. Enumerate all children of the
> > switch port and do not stop the iteration after the first matching
> > target was found.
> >
> > With the fix applied:
> >
> > # dmesg | grep target.list
> > update_decoder_targets: cxl decoder1.0: dport2 found in target list, index 2
> > update_decoder_targets: cxl decoder1.0: dport0 found in target list, index 0
> > update_decoder_targets: cxl decoder1.0: dport3 found in target list, index 3
> > update_decoder_targets: cxl decoder2.0: dport3 found in target list, index 1
> > update_decoder_targets: cxl decoder2.1: dport3 found in target list, index 1
> > update_decoder_targets: cxl decoder4.0: dport3 found in target list, index 1
> > update_decoder_targets: cxl decoder4.1: dport3 found in target list, index 1
> >
> > Analyzing the conditions when this happens:
> >
> > 1) A dport is shared by multiple decoders.
> >
> > 2) The decoders have interleaving configured (ways > 1).
> >
> > The configuration above has the following hierarchy details (fixed
> > version):
> >
> > root0
> > |_
> > | |
> > | decoder0.1
>
> Hi Robert,
>
> I'm struggling a bit to align this with the above prints. Where is
> decoder1.0 for example? As it's below the root port, I think it's the
> host bridge decoder, which might be this one on your diagram?
I only showed the detail of the setup that was failing. There is
additional a 4-way config (port1/decoder1.0) and (not visible) some
1-way configs. Function update_decoder_targets() is not called for
those.
Thanks for review,
-Robert
>
> Fix makes sense to me.
>
> Jonathan
>
>
> > | ways: 2
> > | target_list: 0,1
> > |_______________________________________
> > | |
> > | dport0 | dport1
> > | |
> > port2 port4
> > | |
> > |___________________ |_____________________
> > | | | | | |
> > | decoder2.0 decoder2.1 | decoder4.0 decoder4.1
> > | ways: 2 ways: 2 | ways: 2 ways: 2
> > | target_list: 2,3 target_list: 2,3 | target_list: 2,3 target_list: 2,3
> > |___________________ |___________________
> > | | | |
> > | dport2 | dport3 | dport2 | dport3
> > | | | |
> > endpoint7 endpoint12 endpoint9 endpoint13
> > |_ |_ |_ |_
> > | | | | | | | |
> > | decoder7.0 | decoder12.0 | decoder9.0 | decoder13.0
> > | decoder7.2 | decoder12.2 | decoder9.2 | decoder13.2
> > | | | |
> > mem3 mem5 mem6 mem8
> >
> > Note: Device numbers vary for every boot.
> >
> > Current kernel fails to enumerate endpoint12 and endpoint13 as the
> > target list is not updated for the second decoder.
> >
> > Fixes: 4f06d81e7c6a ("cxl: Defer dport allocation for switch ports")
> > Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> > Reviewed-by: Alison Schofield <alison.schofield@intel.com>
> > Signed-off-by: Robert Richter <rrichter@amd.com>
> > ---
> > v2:
> > * updated sob-chain,
> > * added fixes tag (Dave).
> > ---
> > 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 fef3aa0c6680..3310dbfae9d6 100644
> > --- a/drivers/cxl/core/port.c
> > +++ b/drivers/cxl/core/port.c
> > @@ -1590,7 +1590,7 @@ static int update_decoder_targets(struct device *dev, void *data)
> > cxlsd->target[i] = dport;
> > dev_dbg(dev, "dport%d found in target list, index %d\n",
> > dport->port_id, i);
> > - return 1;
> > + return 0;
> > }
> > }
> >
> >
> > base-commit: 88c72bab77aaf389beccf762e112828253ca0564
> > prerequisite-patch-id: f44102a7b095afa1588a5cac012ec2e0d852c021
>
On Fri, 9 Jan 2026 08:28:56 +0100
Robert Richter <rrichter@amd.com> wrote:
> On Thu, Jan 08, 2026 at 04:08:35PM +0000, Jonathan Cameron wrote:
> > On Thu, 8 Jan 2026 11:13:23 +0100
> > Robert Richter <rrichter@amd.com> wrote:
> >
> > > If a switch port has more than one decoder that is using the same
> > > downstream port, the enumeration of the target lists may fail with:
> > >
> > > # dmesg | grep target.list
> > > update_decoder_targets: cxl decoder1.0: dport3 found in target list, index 3
> > > update_decoder_targets: cxl decoder1.0: dport2 found in target list, index 2
> > > update_decoder_targets: cxl decoder1.0: dport0 found in target list, index 0
> > > update_decoder_targets: cxl decoder2.0: dport3 found in target list, index 1
> > > update_decoder_targets: cxl decoder4.0: dport3 found in target list, index 1
> > > cxl_mem mem6: failed to find endpoint12:0000:00:01.4 in target list of decoder2.1
> > > cxl_mem mem8: failed to find endpoint13:0000:20:01.4 in target list of decoder4.1
> > >
> > > The case, that the same downstream port can be used in multiple target
> > > lists, is allowed and possible.
> > >
> > > Fix the update of the target list. Enumerate all children of the
> > > switch port and do not stop the iteration after the first matching
> > > target was found.
> > >
> > > With the fix applied:
> > >
> > > # dmesg | grep target.list
> > > update_decoder_targets: cxl decoder1.0: dport2 found in target list, index 2
> > > update_decoder_targets: cxl decoder1.0: dport0 found in target list, index 0
> > > update_decoder_targets: cxl decoder1.0: dport3 found in target list, index 3
> > > update_decoder_targets: cxl decoder2.0: dport3 found in target list, index 1
> > > update_decoder_targets: cxl decoder2.1: dport3 found in target list, index 1
> > > update_decoder_targets: cxl decoder4.0: dport3 found in target list, index 1
> > > update_decoder_targets: cxl decoder4.1: dport3 found in target list, index 1
> > >
> > > Analyzing the conditions when this happens:
> > >
> > > 1) A dport is shared by multiple decoders.
> > >
> > > 2) The decoders have interleaving configured (ways > 1).
> > >
> > > The configuration above has the following hierarchy details (fixed
> > > version):
> > >
> > > root0
> > > |_
> > > | |
> > > | decoder0.1
> >
> > Hi Robert,
> >
> > I'm struggling a bit to align this with the above prints. Where is
> > decoder1.0 for example? As it's below the root port, I think it's the
> > host bridge decoder, which might be this one on your diagram?
>
> I only showed the detail of the setup that was failing. There is
> additional a 4-way config (port1/decoder1.0) and (not visible) some
> 1-way configs. Function update_decoder_targets() is not called for
> those.
>
Ah. Ok.
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
> Thanks for review,
>
> -Robert
>
> >
> > Fix makes sense to me.
> >
> > Jonathan
> >
> >
> > > | ways: 2
> > > | target_list: 0,1
> > > |_______________________________________
> > > | |
> > > | dport0 | dport1
> > > | |
> > > port2 port4
> > > | |
> > > |___________________ |_____________________
> > > | | | | | |
> > > | decoder2.0 decoder2.1 | decoder4.0 decoder4.1
> > > | ways: 2 ways: 2 | ways: 2 ways: 2
> > > | target_list: 2,3 target_list: 2,3 | target_list: 2,3 target_list: 2,3
> > > |___________________ |___________________
> > > | | | |
> > > | dport2 | dport3 | dport2 | dport3
> > > | | | |
> > > endpoint7 endpoint12 endpoint9 endpoint13
> > > |_ |_ |_ |_
> > > | | | | | | | |
> > > | decoder7.0 | decoder12.0 | decoder9.0 | decoder13.0
> > > | decoder7.2 | decoder12.2 | decoder9.2 | decoder13.2
> > > | | | |
> > > mem3 mem5 mem6 mem8
> > >
> > > Note: Device numbers vary for every boot.
> > >
> > > Current kernel fails to enumerate endpoint12 and endpoint13 as the
> > > target list is not updated for the second decoder.
> > >
> > > Fixes: 4f06d81e7c6a ("cxl: Defer dport allocation for switch ports")
> > > Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> > > Reviewed-by: Alison Schofield <alison.schofield@intel.com>
> > > Signed-off-by: Robert Richter <rrichter@amd.com>
> > > ---
> > > v2:
> > > * updated sob-chain,
> > > * added fixes tag (Dave).
> > > ---
> > > 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 fef3aa0c6680..3310dbfae9d6 100644
> > > --- a/drivers/cxl/core/port.c
> > > +++ b/drivers/cxl/core/port.c
> > > @@ -1590,7 +1590,7 @@ static int update_decoder_targets(struct device *dev, void *data)
> > > cxlsd->target[i] = dport;
> > > dev_dbg(dev, "dport%d found in target list, index %d\n",
> > > dport->port_id, i);
> > > - return 1;
> > > + return 0;
> > > }
> > > }
> > >
> > >
> > > base-commit: 88c72bab77aaf389beccf762e112828253ca0564
> > > prerequisite-patch-id: f44102a7b095afa1588a5cac012ec2e0d852c021
> >
>
© 2016 - 2026 Red Hat, Inc.