diff mbox series

[RFC,v2,09/28] cxl/acpi: Map single port host bridge component registers

Message ID 20211022183709.1199701-10-ben.widawsky@intel.com
State New, archived
Headers show
Series CXL Region Creation / HDM decoder programming | expand

Commit Message

Ben Widawsky Oct. 22, 2021, 6:36 p.m. UTC
Now that the port driver exists and is able to do proper decoder
enumeration of the component registers, it becomes trivial to use that
for host bridge uports. For reasons out of scope, a functional change
would be visible if the HDM decoder was programmed by BIOS to values
other than the full address range. Similarly if a type2 device was
connected to this root port and programmed by BIOS, that can now be
acted upon accordingly.

Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
---
 drivers/cxl/acpi.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

Comments

Dan Williams Oct. 31, 2021, 6:03 p.m. UTC | #1
On Fri, Oct 22, 2021 at 11:37 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
>
> Now that the port driver exists and is able to do proper decoder
> enumeration of the component registers, it becomes trivial to use that

This is the second occurrence of "becomes trivial" in this series,
it's distracting because it immediately sets off alarm bells that the
changelog is not in:

Background
Problem
Solution

...format.

> for host bridge uports. For reasons out of scope, a functional change
> would be visible if the HDM decoder was programmed by BIOS to values
> other than the full address range. Similarly if a type2 device was
> connected to this root port and programmed by BIOS, that can now be
> acted upon accordingly.

I would reserve discussion of "no functional change" for patches that
are pure cleanup. In this case this patch will cause the kernel to
behave differently when other conditions are met.

>
> Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
> ---
>  drivers/cxl/acpi.c | 25 ++++++++++++++++++++++++-
>  1 file changed, 24 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
> index d61397055e9f..8cca0814dfb8 100644
> --- a/drivers/cxl/acpi.c
> +++ b/drivers/cxl/acpi.c
> @@ -280,12 +280,14 @@ static int add_host_bridge_uport(struct device *match, void *arg)
>         struct cxl_port *root_port = arg;
>         struct device *host = root_port->dev.parent;
>         struct acpi_device *bridge = to_cxl_host_bridge(host, match);
> +       struct cxl_component_reg_map map;
>         struct acpi_pci_root *pci_root;
>         struct cxl_walk_context ctx;
>         int single_port_map[1], rc;
>         struct cxl_decoder *cxld;
>         struct cxl_dport *dport;
>         struct cxl_port *port;
> +       void __iomem *crb;
>
>         if (!bridge)
>                 return 0;
> @@ -318,10 +320,31 @@ static int add_host_bridge_uport(struct device *match, void *arg)
>                 return -ENODEV;
>         if (ctx.error)
>                 return ctx.error;
> +       /*
> +        * If the host bridge has more than 1 root port, it must have registers
> +        * controlling the HDM decoders. Those will be enumerated by the port
> +        * driver.
> +        */
>         if (ctx.count > 1)
>                 return 0;
>
> -       /* TODO: Scan CHBCR for HDM Decoder resources */
> +       /*
> +        * If the single ported host bridge has a component register block,
> +        * simply let the port driver handle the decoder enumeration.
> +        *
> +        * Host bridge component registers live in the system's physical address
> +        * space.
> +        */
> +       crb = ioremap(dport->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE);

This looks broken, the driver for the port should be mapping dport
component registers to offer services to upper layers.

There's also a missing iounmap.

> +       if (crb) {
> +               cxl_probe_component_regs(&root_port->dev, crb, &map);
> +               iounmap(crb);
> +               if (map.hdm_decoder.valid) {
> +                       dev_dbg(host,
> +                               "Found single port host bridge with component registers\n");
> +                       return 0;
> +               }
> +       }
>
>         /*
>          * Per the CXL specification (8.2.5.12 CXL HDM Decoder Capability
> --
> 2.33.1
>
Ben Widawsky Nov. 1, 2021, 5:07 p.m. UTC | #2
On 21-10-31 11:03:37, Dan Williams wrote:
> On Fri, Oct 22, 2021 at 11:37 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> >
> > Now that the port driver exists and is able to do proper decoder
> > enumeration of the component registers, it becomes trivial to use that
> 
> This is the second occurrence of "becomes trivial" in this series,
> it's distracting because it immediately sets off alarm bells that the
> changelog is not in:
> 
> Background
> Problem
> Solution
> 
> ...format.

Let me make sure I understand.

Background: Now that the port driver exists...
Problem: host bridge uports can use the port driver [but don't yet]
Solution: This patch (the description is indeed missing).

Is your point that I didn't document a solution, or something else?


> 
> > for host bridge uports. For reasons out of scope, a functional change
> > would be visible if the HDM decoder was programmed by BIOS to values
> > other than the full address range. Similarly if a type2 device was
> > connected to this root port and programmed by BIOS, that can now be
> > acted upon accordingly.
> 
> I would reserve discussion of "no functional change" for patches that
> are pure cleanup. In this case this patch will cause the kernel to
> behave differently when other conditions are met.

True. I will remove that.

> 
> >
> > Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
> > ---
> >  drivers/cxl/acpi.c | 25 ++++++++++++++++++++++++-
> >  1 file changed, 24 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
> > index d61397055e9f..8cca0814dfb8 100644
> > --- a/drivers/cxl/acpi.c
> > +++ b/drivers/cxl/acpi.c
> > @@ -280,12 +280,14 @@ static int add_host_bridge_uport(struct device *match, void *arg)
> >         struct cxl_port *root_port = arg;
> >         struct device *host = root_port->dev.parent;
> >         struct acpi_device *bridge = to_cxl_host_bridge(host, match);
> > +       struct cxl_component_reg_map map;
> >         struct acpi_pci_root *pci_root;
> >         struct cxl_walk_context ctx;
> >         int single_port_map[1], rc;
> >         struct cxl_decoder *cxld;
> >         struct cxl_dport *dport;
> >         struct cxl_port *port;
> > +       void __iomem *crb;
> >
> >         if (!bridge)
> >                 return 0;
> > @@ -318,10 +320,31 @@ static int add_host_bridge_uport(struct device *match, void *arg)
> >                 return -ENODEV;
> >         if (ctx.error)
> >                 return ctx.error;
> > +       /*
> > +        * If the host bridge has more than 1 root port, it must have registers
> > +        * controlling the HDM decoders. Those will be enumerated by the port
> > +        * driver.
> > +        */
> >         if (ctx.count > 1)
> >                 return 0;
> >
> > -       /* TODO: Scan CHBCR for HDM Decoder resources */
> > +       /*
> > +        * If the single ported host bridge has a component register block,
> > +        * simply let the port driver handle the decoder enumeration.
> > +        *
> > +        * Host bridge component registers live in the system's physical address
> > +        * space.
> > +        */
> > +       crb = ioremap(dport->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE);
> 
> This looks broken, the driver for the port should be mapping dport
> component registers to offer services to upper layers.
> 
> There's also a missing iounmap.
> 

Where's the missing iounmap? The port driver does what you say, but I need a way
to shortcircuit the case where the root port doesn't have component registers
which you've previously documented as allowed by spec. How would you recommend
doing that?

> > +       if (crb) {
> > +               cxl_probe_component_regs(&root_port->dev, crb, &map);
> > +               iounmap(crb);
> > +               if (map.hdm_decoder.valid) {
> > +                       dev_dbg(host,
> > +                               "Found single port host bridge with component registers\n");
> > +                       return 0;
> > +               }
> > +       }
> >
> >         /*
> >          * Per the CXL specification (8.2.5.12 CXL HDM Decoder Capability
> > --
> > 2.33.1
> >
Dan Williams Nov. 2, 2021, 2:15 a.m. UTC | #3
On Mon, Nov 1, 2021 at 10:08 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
>
> On 21-10-31 11:03:37, Dan Williams wrote:
> > On Fri, Oct 22, 2021 at 11:37 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > >
> > > Now that the port driver exists and is able to do proper decoder
> > > enumeration of the component registers, it becomes trivial to use that
> >
> > This is the second occurrence of "becomes trivial" in this series,
> > it's distracting because it immediately sets off alarm bells that the
> > changelog is not in:
> >
> > Background
> > Problem
> > Solution
> >
> > ...format.
>
> Let me make sure I understand.
>
> Background: Now that the port driver exists...
> Problem: host bridge uports can use the port driver [but don't yet]
> Solution: This patch (the description is indeed missing).
>
> Is your point that I didn't document a solution, or something else?

Why do single port host bridge registers need to be mapped?

Why does the cxl_acpi driver need to do it and not the just introduced
port driver?

This patch seems to be saying, map these because they can be mapped.

>
>
> >
> > > for host bridge uports. For reasons out of scope, a functional change
> > > would be visible if the HDM decoder was programmed by BIOS to values
> > > other than the full address range. Similarly if a type2 device was
> > > connected to this root port and programmed by BIOS, that can now be
> > > acted upon accordingly.
> >
> > I would reserve discussion of "no functional change" for patches that
> > are pure cleanup. In this case this patch will cause the kernel to
> > behave differently when other conditions are met.
>
> True. I will remove that.
>
> >
> > >
> > > Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
> > > ---
> > >  drivers/cxl/acpi.c | 25 ++++++++++++++++++++++++-
> > >  1 file changed, 24 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
> > > index d61397055e9f..8cca0814dfb8 100644
> > > --- a/drivers/cxl/acpi.c
> > > +++ b/drivers/cxl/acpi.c
> > > @@ -280,12 +280,14 @@ static int add_host_bridge_uport(struct device *match, void *arg)
> > >         struct cxl_port *root_port = arg;
> > >         struct device *host = root_port->dev.parent;
> > >         struct acpi_device *bridge = to_cxl_host_bridge(host, match);
> > > +       struct cxl_component_reg_map map;
> > >         struct acpi_pci_root *pci_root;
> > >         struct cxl_walk_context ctx;
> > >         int single_port_map[1], rc;
> > >         struct cxl_decoder *cxld;
> > >         struct cxl_dport *dport;
> > >         struct cxl_port *port;
> > > +       void __iomem *crb;
> > >
> > >         if (!bridge)
> > >                 return 0;
> > > @@ -318,10 +320,31 @@ static int add_host_bridge_uport(struct device *match, void *arg)
> > >                 return -ENODEV;
> > >         if (ctx.error)
> > >                 return ctx.error;
> > > +       /*
> > > +        * If the host bridge has more than 1 root port, it must have registers
> > > +        * controlling the HDM decoders. Those will be enumerated by the port
> > > +        * driver.
> > > +        */
> > >         if (ctx.count > 1)
> > >                 return 0;
> > >
> > > -       /* TODO: Scan CHBCR for HDM Decoder resources */
> > > +       /*
> > > +        * If the single ported host bridge has a component register block,
> > > +        * simply let the port driver handle the decoder enumeration.
> > > +        *
> > > +        * Host bridge component registers live in the system's physical address
> > > +        * space.
> > > +        */
> > > +       crb = ioremap(dport->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE);
> >
> > This looks broken, the driver for the port should be mapping dport
> > component registers to offer services to upper layers.
> >
> > There's also a missing iounmap.
> >
>
> Where's the missing iounmap?

Oops, sorry, don't know why I missed that. Forgive the noise.

> The port driver does what you say, but I need a way
> to shortcircuit the case where the root port doesn't have component registers
> which you've previously documented as allowed by spec. How would you recommend
> doing that?

Perhaps cxl_port_probe() needs to special case the single dport case
and just say, "no registers needed, single port == HDM passthrough".

Until there's a need to look at non-HDM registers I'd hold off on
enabling this case. Probably that comes soon when considering IDE
support, but no need to pre-enable that yet.
Ben Widawsky Nov. 2, 2021, 4:31 p.m. UTC | #4
On 21-11-01 19:15:33, Dan Williams wrote:
> On Mon, Nov 1, 2021 at 10:08 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> >
> > On 21-10-31 11:03:37, Dan Williams wrote:
> > > On Fri, Oct 22, 2021 at 11:37 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > > >
> > > > Now that the port driver exists and is able to do proper decoder
> > > > enumeration of the component registers, it becomes trivial to use that
> > >
> > > This is the second occurrence of "becomes trivial" in this series,
> > > it's distracting because it immediately sets off alarm bells that the
> > > changelog is not in:
> > >
> > > Background
> > > Problem
> > > Solution
> > >
> > > ...format.
> >
> > Let me make sure I understand.
> >
> > Background: Now that the port driver exists...
> > Problem: host bridge uports can use the port driver [but don't yet]
> > Solution: This patch (the description is indeed missing).
> >
> > Is your point that I didn't document a solution, or something else?
> 
> Why do single port host bridge registers need to be mapped?
> 
> Why does the cxl_acpi driver need to do it and not the just introduced
> port driver?
> 
> This patch seems to be saying, map these because they can be mapped.
> 
> >
> >
> > >
> > > > for host bridge uports. For reasons out of scope, a functional change
> > > > would be visible if the HDM decoder was programmed by BIOS to values
> > > > other than the full address range. Similarly if a type2 device was
> > > > connected to this root port and programmed by BIOS, that can now be
> > > > acted upon accordingly.
> > >
> > > I would reserve discussion of "no functional change" for patches that
> > > are pure cleanup. In this case this patch will cause the kernel to
> > > behave differently when other conditions are met.
> >
> > True. I will remove that.
> >
> > >
> > > >
> > > > Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
> > > > ---
> > > >  drivers/cxl/acpi.c | 25 ++++++++++++++++++++++++-
> > > >  1 file changed, 24 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
> > > > index d61397055e9f..8cca0814dfb8 100644
> > > > --- a/drivers/cxl/acpi.c
> > > > +++ b/drivers/cxl/acpi.c
> > > > @@ -280,12 +280,14 @@ static int add_host_bridge_uport(struct device *match, void *arg)
> > > >         struct cxl_port *root_port = arg;
> > > >         struct device *host = root_port->dev.parent;
> > > >         struct acpi_device *bridge = to_cxl_host_bridge(host, match);
> > > > +       struct cxl_component_reg_map map;
> > > >         struct acpi_pci_root *pci_root;
> > > >         struct cxl_walk_context ctx;
> > > >         int single_port_map[1], rc;
> > > >         struct cxl_decoder *cxld;
> > > >         struct cxl_dport *dport;
> > > >         struct cxl_port *port;
> > > > +       void __iomem *crb;
> > > >
> > > >         if (!bridge)
> > > >                 return 0;
> > > > @@ -318,10 +320,31 @@ static int add_host_bridge_uport(struct device *match, void *arg)
> > > >                 return -ENODEV;
> > > >         if (ctx.error)
> > > >                 return ctx.error;
> > > > +       /*
> > > > +        * If the host bridge has more than 1 root port, it must have registers
> > > > +        * controlling the HDM decoders. Those will be enumerated by the port
> > > > +        * driver.
> > > > +        */
> > > >         if (ctx.count > 1)
> > > >                 return 0;
> > > >
> > > > -       /* TODO: Scan CHBCR for HDM Decoder resources */
> > > > +       /*
> > > > +        * If the single ported host bridge has a component register block,
> > > > +        * simply let the port driver handle the decoder enumeration.
> > > > +        *
> > > > +        * Host bridge component registers live in the system's physical address
> > > > +        * space.
> > > > +        */
> > > > +       crb = ioremap(dport->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE);
> > >
> > > This looks broken, the driver for the port should be mapping dport
> > > component registers to offer services to upper layers.
> > >
> > > There's also a missing iounmap.
> > >
> >
> > Where's the missing iounmap?
> 
> Oops, sorry, don't know why I missed that. Forgive the noise.
> 
> > The port driver does what you say, but I need a way
> > to shortcircuit the case where the root port doesn't have component registers
> > which you've previously documented as allowed by spec. How would you recommend
> > doing that?
> 
> Perhaps cxl_port_probe() needs to special case the single dport case
> and just say, "no registers needed, single port == HDM passthrough".
> 
> Until there's a need to look at non-HDM registers I'd hold off on
> enabling this case. Probably that comes soon when considering IDE
> support, but no need to pre-enable that yet.

It seemed like a very simple thing to support given the port driver's existence
so it was added to remove a TODO. However, I will drop it as you request.
Dan Williams Nov. 2, 2021, 5:46 p.m. UTC | #5
On Tue, Nov 2, 2021 at 9:31 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
[..]
> It seemed like a very simple thing to support given the port driver's existence
> so it was added to remove a TODO. However, I will drop it as you request.

I'm honestly asking the question why this is needed and more
specifically why this is needed in this location?

In other words, how is this case different than typical component
register probing that is done in the port driver itself? I would
expect the TODO just gets deleted by the port driver addition.
Ben Widawsky Nov. 2, 2021, 5:57 p.m. UTC | #6
On 21-11-02 10:46:41, Dan Williams wrote:
> On Tue, Nov 2, 2021 at 9:31 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> [..]
> > It seemed like a very simple thing to support given the port driver's existence
> > so it was added to remove a TODO. However, I will drop it as you request.
> 
> I'm honestly asking the question why this is needed and more
> specifically why this is needed in this location?
> 
> In other words, how is this case different than typical component
> register probing that is done in the port driver itself? I would
> expect the TODO just gets deleted by the port driver addition.

Without this code, a decoder is added for the full address range regardless if
there is an existing programmed HDM decoder. With this code when the port driver
probes this host bridge HDM component registers, everything will be enumerated
by the normal flow.

This seemed easier than trying to have the port driver determine what cxl_acpi
driver did and unwind that if there is a programmed decoder.

But now you're making me think I've missed something big...
Dan Williams Nov. 2, 2021, 6:10 p.m. UTC | #7
On Tue, Nov 2, 2021 at 10:57 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
>
> On 21-11-02 10:46:41, Dan Williams wrote:
> > On Tue, Nov 2, 2021 at 9:31 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > [..]
> > > It seemed like a very simple thing to support given the port driver's existence
> > > so it was added to remove a TODO. However, I will drop it as you request.
> >
> > I'm honestly asking the question why this is needed and more
> > specifically why this is needed in this location?
> >
> > In other words, how is this case different than typical component
> > register probing that is done in the port driver itself? I would
> > expect the TODO just gets deleted by the port driver addition.
>
> Without this code, a decoder is added for the full address range regardless if
> there is an existing programmed HDM decoder. With this code when the port driver
> probes this host bridge HDM component registers, everything will be enumerated
> by the normal flow.
>
> This seemed easier than trying to have the port driver determine what cxl_acpi
> driver did and unwind that if there is a programmed decoder.

I think this is more an argument to unify all decoder creation in the
port driver. When the port driver sees a single dport with no HDM
decoder registers it can create the passthrough decoder, if it sees
single dport with HDM decoder registers then it can create a
programmable decoder.
Ben Widawsky Nov. 2, 2021, 6:27 p.m. UTC | #8
On 21-11-02 11:10:05, Dan Williams wrote:
> On Tue, Nov 2, 2021 at 10:57 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> >
> > On 21-11-02 10:46:41, Dan Williams wrote:
> > > On Tue, Nov 2, 2021 at 9:31 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > > [..]
> > > > It seemed like a very simple thing to support given the port driver's existence
> > > > so it was added to remove a TODO. However, I will drop it as you request.
> > >
> > > I'm honestly asking the question why this is needed and more
> > > specifically why this is needed in this location?
> > >
> > > In other words, how is this case different than typical component
> > > register probing that is done in the port driver itself? I would
> > > expect the TODO just gets deleted by the port driver addition.
> >
> > Without this code, a decoder is added for the full address range regardless if
> > there is an existing programmed HDM decoder. With this code when the port driver
> > probes this host bridge HDM component registers, everything will be enumerated
> > by the normal flow.
> >
> > This seemed easier than trying to have the port driver determine what cxl_acpi
> > driver did and unwind that if there is a programmed decoder.
> 
> I think this is more an argument to unify all decoder creation in the
> port driver. When the port driver sees a single dport with no HDM
> decoder registers it can create the passthrough decoder, if it sees
> single dport with HDM decoder registers then it can create a
> programmable decoder.

That too, though I'm not sure how useful that will be for us. I think the more
likely case is BIOS is trying to hide some device (or switch) address space.
Dan Williams Nov. 2, 2021, 6:49 p.m. UTC | #9
On Tue, Nov 2, 2021 at 11:27 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
>
> On 21-11-02 11:10:05, Dan Williams wrote:
> > On Tue, Nov 2, 2021 at 10:57 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > >
> > > On 21-11-02 10:46:41, Dan Williams wrote:
> > > > On Tue, Nov 2, 2021 at 9:31 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > > > [..]
> > > > > It seemed like a very simple thing to support given the port driver's existence
> > > > > so it was added to remove a TODO. However, I will drop it as you request.
> > > >
> > > > I'm honestly asking the question why this is needed and more
> > > > specifically why this is needed in this location?
> > > >
> > > > In other words, how is this case different than typical component
> > > > register probing that is done in the port driver itself? I would
> > > > expect the TODO just gets deleted by the port driver addition.
> > >
> > > Without this code, a decoder is added for the full address range regardless if
> > > there is an existing programmed HDM decoder. With this code when the port driver
> > > probes this host bridge HDM component registers, everything will be enumerated
> > > by the normal flow.
> > >
> > > This seemed easier than trying to have the port driver determine what cxl_acpi
> > > driver did and unwind that if there is a programmed decoder.
> >
> > I think this is more an argument to unify all decoder creation in the
> > port driver. When the port driver sees a single dport with no HDM
> > decoder registers it can create the passthrough decoder, if it sees
> > single dport with HDM decoder registers then it can create a
> > programmable decoder.
>
> That too, though I'm not sure how useful that will be for us.

?

This is about the proper place to enumerate decoders. The proposal in
this patch is to do some part of the enumeration in cxl_acpi and some
part in cxl_port, I'm saying push it all to cxl_port. I.e. it was a
layering violation in retrospect to create a default passthrough
decoder from cxl_acpi.

> I think the more
> likely case is BIOS is trying to hide some device (or switch) address space.

Not sure why that is relevant for the decision about where to place
component register probing and passthrough decoder creation?
Ben Widawsky Nov. 2, 2021, 9:15 p.m. UTC | #10
On 21-11-02 11:49:14, Dan Williams wrote:
> On Tue, Nov 2, 2021 at 11:27 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> >
> > On 21-11-02 11:10:05, Dan Williams wrote:
> > > On Tue, Nov 2, 2021 at 10:57 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > > >
> > > > On 21-11-02 10:46:41, Dan Williams wrote:
> > > > > On Tue, Nov 2, 2021 at 9:31 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > > > > [..]
> > > > > > It seemed like a very simple thing to support given the port driver's existence
> > > > > > so it was added to remove a TODO. However, I will drop it as you request.
> > > > >
> > > > > I'm honestly asking the question why this is needed and more
> > > > > specifically why this is needed in this location?
> > > > >
> > > > > In other words, how is this case different than typical component
> > > > > register probing that is done in the port driver itself? I would
> > > > > expect the TODO just gets deleted by the port driver addition.
> > > >
> > > > Without this code, a decoder is added for the full address range regardless if
> > > > there is an existing programmed HDM decoder. With this code when the port driver
> > > > probes this host bridge HDM component registers, everything will be enumerated
> > > > by the normal flow.
> > > >
> > > > This seemed easier than trying to have the port driver determine what cxl_acpi
> > > > driver did and unwind that if there is a programmed decoder.
> > >
> > > I think this is more an argument to unify all decoder creation in the
> > > port driver. When the port driver sees a single dport with no HDM
> > > decoder registers it can create the passthrough decoder, if it sees
> > > single dport with HDM decoder registers then it can create a
> > > programmable decoder.
> >
> > That too, though I'm not sure how useful that will be for us.
> 
> ?
> 
> This is about the proper place to enumerate decoders. The proposal in
> this patch is to do some part of the enumeration in cxl_acpi and some
> part in cxl_port, I'm saying push it all to cxl_port. I.e. it was a
> layering violation in retrospect to create a default passthrough
> decoder from cxl_acpi.

I think it makes sense to have cxl_decoder_add() not called from anything but
the port driver. So long as there's a way to determine it's a CXL 2.0 Root Port,
which, it seems we'll have, it should be straight forward.

> 
> > I think the more
> > likely case is BIOS is trying to hide some device (or switch) address space.
> 
> Not sure why that is relevant for the decision about where to place
> component register probing and passthrough decoder creation?

The comment wasn't about where, it was just a response as to how there's more
motivation than just having a programmable decoder, you might find a locked
decoder that has unexpected constraints.
Dan Williams Nov. 2, 2021, 9:34 p.m. UTC | #11
On Tue, Nov 2, 2021 at 2:16 PM Ben Widawsky <ben.widawsky@intel.com> wrote:
>
> On 21-11-02 11:49:14, Dan Williams wrote:
> > On Tue, Nov 2, 2021 at 11:27 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > >
> > > On 21-11-02 11:10:05, Dan Williams wrote:
> > > > On Tue, Nov 2, 2021 at 10:57 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > > > >
> > > > > On 21-11-02 10:46:41, Dan Williams wrote:
> > > > > > On Tue, Nov 2, 2021 at 9:31 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > > > > > [..]
> > > > > > > It seemed like a very simple thing to support given the port driver's existence
> > > > > > > so it was added to remove a TODO. However, I will drop it as you request.
> > > > > >
> > > > > > I'm honestly asking the question why this is needed and more
> > > > > > specifically why this is needed in this location?
> > > > > >
> > > > > > In other words, how is this case different than typical component
> > > > > > register probing that is done in the port driver itself? I would
> > > > > > expect the TODO just gets deleted by the port driver addition.
> > > > >
> > > > > Without this code, a decoder is added for the full address range regardless if
> > > > > there is an existing programmed HDM decoder. With this code when the port driver
> > > > > probes this host bridge HDM component registers, everything will be enumerated
> > > > > by the normal flow.
> > > > >
> > > > > This seemed easier than trying to have the port driver determine what cxl_acpi
> > > > > driver did and unwind that if there is a programmed decoder.
> > > >
> > > > I think this is more an argument to unify all decoder creation in the
> > > > port driver. When the port driver sees a single dport with no HDM
> > > > decoder registers it can create the passthrough decoder, if it sees
> > > > single dport with HDM decoder registers then it can create a
> > > > programmable decoder.
> > >
> > > That too, though I'm not sure how useful that will be for us.
> >
> > ?
> >
> > This is about the proper place to enumerate decoders. The proposal in
> > this patch is to do some part of the enumeration in cxl_acpi and some
> > part in cxl_port, I'm saying push it all to cxl_port. I.e. it was a
> > layering violation in retrospect to create a default passthrough
> > decoder from cxl_acpi.
>
> I think it makes sense to have cxl_decoder_add() not called from anything but
> the port driver. So long as there's a way to determine it's a CXL 2.0 Root Port,
> which, it seems we'll have, it should be straight forward.

Does it need to be root port aware? I expect any single ported switch
is treated the same, not that I expect single-ported switches to be a
real thing, but I don't expect our port driver would care.
Ben Widawsky Nov. 2, 2021, 9:47 p.m. UTC | #12
On 21-11-02 14:34:19, Dan Williams wrote:
> On Tue, Nov 2, 2021 at 2:16 PM Ben Widawsky <ben.widawsky@intel.com> wrote:
> >
> > On 21-11-02 11:49:14, Dan Williams wrote:
> > > On Tue, Nov 2, 2021 at 11:27 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > > >
> > > > On 21-11-02 11:10:05, Dan Williams wrote:
> > > > > On Tue, Nov 2, 2021 at 10:57 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > > > > >
> > > > > > On 21-11-02 10:46:41, Dan Williams wrote:
> > > > > > > On Tue, Nov 2, 2021 at 9:31 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
> > > > > > > [..]
> > > > > > > > It seemed like a very simple thing to support given the port driver's existence
> > > > > > > > so it was added to remove a TODO. However, I will drop it as you request.
> > > > > > >
> > > > > > > I'm honestly asking the question why this is needed and more
> > > > > > > specifically why this is needed in this location?
> > > > > > >
> > > > > > > In other words, how is this case different than typical component
> > > > > > > register probing that is done in the port driver itself? I would
> > > > > > > expect the TODO just gets deleted by the port driver addition.
> > > > > >
> > > > > > Without this code, a decoder is added for the full address range regardless if
> > > > > > there is an existing programmed HDM decoder. With this code when the port driver
> > > > > > probes this host bridge HDM component registers, everything will be enumerated
> > > > > > by the normal flow.
> > > > > >
> > > > > > This seemed easier than trying to have the port driver determine what cxl_acpi
> > > > > > driver did and unwind that if there is a programmed decoder.
> > > > >
> > > > > I think this is more an argument to unify all decoder creation in the
> > > > > port driver. When the port driver sees a single dport with no HDM
> > > > > decoder registers it can create the passthrough decoder, if it sees
> > > > > single dport with HDM decoder registers then it can create a
> > > > > programmable decoder.
> > > >
> > > > That too, though I'm not sure how useful that will be for us.
> > >
> > > ?
> > >
> > > This is about the proper place to enumerate decoders. The proposal in
> > > this patch is to do some part of the enumeration in cxl_acpi and some
> > > part in cxl_port, I'm saying push it all to cxl_port. I.e. it was a
> > > layering violation in retrospect to create a default passthrough
> > > decoder from cxl_acpi.
> >
> > I think it makes sense to have cxl_decoder_add() not called from anything but
> > the port driver. So long as there's a way to determine it's a CXL 2.0 Root Port,
> > which, it seems we'll have, it should be straight forward.
> 
> Does it need to be root port aware? I expect any single ported switch
> is treated the same, not that I expect single-ported switches to be a
> real thing, but I don't expect our port driver would care.

You're correct... I thought switch ports required HDM decoder registers even if
single port, but I just checked and they are the same as the host bridge. So
indeed the enumeration should only be special cased for the endpoint.
diff mbox series

Patch

diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
index d61397055e9f..8cca0814dfb8 100644
--- a/drivers/cxl/acpi.c
+++ b/drivers/cxl/acpi.c
@@ -280,12 +280,14 @@  static int add_host_bridge_uport(struct device *match, void *arg)
 	struct cxl_port *root_port = arg;
 	struct device *host = root_port->dev.parent;
 	struct acpi_device *bridge = to_cxl_host_bridge(host, match);
+	struct cxl_component_reg_map map;
 	struct acpi_pci_root *pci_root;
 	struct cxl_walk_context ctx;
 	int single_port_map[1], rc;
 	struct cxl_decoder *cxld;
 	struct cxl_dport *dport;
 	struct cxl_port *port;
+	void __iomem *crb;
 
 	if (!bridge)
 		return 0;
@@ -318,10 +320,31 @@  static int add_host_bridge_uport(struct device *match, void *arg)
 		return -ENODEV;
 	if (ctx.error)
 		return ctx.error;
+	/*
+	 * If the host bridge has more than 1 root port, it must have registers
+	 * controlling the HDM decoders. Those will be enumerated by the port
+	 * driver.
+	 */
 	if (ctx.count > 1)
 		return 0;
 
-	/* TODO: Scan CHBCR for HDM Decoder resources */
+	/*
+	 * If the single ported host bridge has a component register block,
+	 * simply let the port driver handle the decoder enumeration.
+	 *
+	 * Host bridge component registers live in the system's physical address
+	 * space.
+	 */
+	crb = ioremap(dport->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE);
+	if (crb) {
+		cxl_probe_component_regs(&root_port->dev, crb, &map);
+		iounmap(crb);
+		if (map.hdm_decoder.valid) {
+			dev_dbg(host,
+				"Found single port host bridge with component registers\n");
+			return 0;
+		}
+	}
 
 	/*
 	 * Per the CXL specification (8.2.5.12 CXL HDM Decoder Capability