Re: [PATCH v4 1/3] of: address: Add parent_bus_addr to struct of_pci_range

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Oct 10, 2024 at 04:57:45PM -0500, Bjorn Helgaas wrote:
> On Tue, Oct 08, 2024 at 03:53:58PM -0400, Frank Li wrote:
> > Introduce field 'parent_bus_addr' in of_pci_range to retrieve untranslated
> > CPU address information.
>
> s/in of_pci_range/in struct of_pci_range/
>
> s/CPU address information/parent bus information/ ?
>
> This patch adds "parent_bus_addr" (not "cpu_addr", which already
> exists), and if I understand the example below correctly, it says
> parent_bus_addr will be 0x8..._.... (an internal address), not a CPU
> address, which would be 0x7..._....

It is "untranslated CPU address", previous patch use cpu_untranslate_addr.
Rob suggest change to parent_bus_addr.

Is it better change to "to retrieve the address at bus fabric port" instead
of *untranslated* CPU address

>
> I guess "parent_bus_addr" would be a CPU address for the bus@5f000000
> ranges, but an IA address for the pcie@5f010000 ranges?

simple said "parent_bus_addr" should be address under pcie dt node.
5f000000 should be 1:1 map.
Only 80000000 range is not 1:1 map.

>
> > Refer to the diagram below to understand that the bus fabric in some
> > systems (like i.MX8QXP) does not use a 1:1 address map between input and
> > output.
> >
> > Currently, many controller drivers use .cpu_addr_fixup() callback hardcodes
> > that translation in the code, e.g., "cpu_addr & CDNS_PLAT_CPU_TO_BUS_ADDR"
> > (drivers/pci/controller/cadence/pcie-cadence-plat.c),
> > "cpu_addr + BUS_IATU_OFFSET"(drivers/pci/controller/dwc/pcie-intel-gw.c),
> > etc, even though those translations *should* be described via DT.
> >
> > The .cpu_addr_fixup() can be eliminated if DT correct reflect hardware
> > behavior and driver use 'parent_bus_addr' in of_pci_range.
> >
> >             ┌─────────┐                    ┌────────────┐
> >  ┌─────┐    │         │ IA: 0x8ff0_0000    │            │
> >  │ CPU ├───►│   ┌────►├─────────────────┐  │ PCI        │
> >  └─────┘    │   │     │ IA: 0x8ff8_0000 │  │            │
> >   CPU Addr  │   │  ┌─►├─────────────┐   │  │ Controller │
> > 0x7ff0_0000─┼───┘  │  │             │   │  │            │
> >             │      │  │             │   │  │            │   PCI Addr
> > 0x7ff8_0000─┼──────┘  │             │   └──► CfgSpace  ─┼────────────►
> >             │         │             │      │            │    0
> > 0x7000_0000─┼────────►├─────────┐   │      │            │
> >             └─────────┘         │   └──────► IOSpace   ─┼────────────►
> >              BUS Fabric         │          │            │    0
> >                                 │          │            │
> >                                 └──────────► MemSpace  ─┼────────────►
> >                         IA: 0x8000_0000    │            │  0x8000_0000
> >                                            └────────────┘
>
> Thanks for this diagram.  I think it would be nice if the ranges were
> in address order, e.g.,
>
>   0x7000_0000
>   0x7ff0_0000
>   0x7ff8_0000
>
> (or the reverse).  But it's a little confusing that 0x7ff8_0000 is in
> the middle because that's the highest address range of the picture.

Okay, reverse should be simple.

>
> > bus@5f000000 {
> >         compatible = "simple-bus";
> >         #address-cells = <1>;
> >         #size-cells = <1>;
> >         ranges = <0x5f000000 0x0 0x5f000000 0x21000000>,
> >                  <0x80000000 0x0 0x70000000 0x10000000>;
> >
> >         pcie@5f010000 {
> >                 compatible = "fsl,imx8q-pcie";
> >                 reg = <0x5f010000 0x10000>, <0x8ff00000 0x80000>;
> >                 reg-names = "dbi", "config";
> >                 #address-cells = <3>;
> >                 #size-cells = <2>;
> >                 device_type = "pci";
> >                 bus-range = <0x00 0xff>;
> >                 ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
> >                          <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;
>
> I'm still learning to interpret "ranges", so bear with me and help me
> out a bit.
>
> IIUC, "ranges" consists of (child-bus-address, parent-bus-address,
> length) triplets.  child-bus-address requires #address-cells of THIS
> node, parent-bus-address requires #address-cells of the PARENT, and
> length requires #size-cells of THIS node.
>
> I guess bus@5f000000 "ranges" describes the translation from CPU to IA
> addresses, so the triplet format would be:
>
>   (1-cell IA child addr, 2-cell CPU parent addr, 1-cell IA length)
> m
> and this "ranges":
>
>   ranges = <0x5f000000 0x0 0x5f000000 0x21000000>,
>            <0x80000000 0x0 0x70000000 0x10000000>;
>
> means:
>
>   (IA 0x5f000000, CPU 0x0 0x5f000000, length 0x21000000)
>   (IA 0x80000000, CPU 0x0 0x70000000, length 0x10000000)
>
> which would mean:
>
>   CPU 0x0_5f000000-0x0_7fffffff -> IA 0x5f000000-0x7fffffff
>   CPU 0x0_70000000-0x0_7fffffff -> IA 0x80000000-0x8fffffff

Yes,

>
> I must be misunderstanding something because this would mean CPU addr
> 0x70000000 would translate to IA addr 0x70000000 via the first range
> and to IA addr 0x80000000 via the second range, which doesn't make
> sense.

Yes, it is my mistake, first length should reduce to 0x0100_0000 from
0x21000000. It works because dt convert IA to CPU, instead of CPU to
IA.  for example, input IA: 0x80000000, match second one, convert to
CPU address 0x0_70000000.

>
> 0x0_5f000000 doesn't appear in the diagram.  If it's not relevant, can
> you just omit it from the bus@5f000000 "ranges" and just say something
> like this?
>
>   ranges = <0x80000000 0x0 0x70000000 0x10000000>, ...;

Yes.

>
> Then pcie@5f010000 describes the translations from IA to PCI bus
> address?  These triplets would be:
>
>   (3-cell PCI child addr, 1-cell IA parent addr, 2-cell PCI length)
>
>   ranges = <0x81000000 0 0x00000000 0x8ff80000 0 0x00010000>,
>            <0x82000000 0 0x80000000 0x80000000 0 0x0ff00000>;
>
> which would mean:
>
>   (IA 0x8ff80000, PCI 0x81000000 0 0x00000000, length 0 0x00010000)
>   (IA 0x80000000, PCI 0x82000000 0 0x80000000, length 0 0x0ff00000)
>
>   IA 0x8ff80000-0x8ff8ffff -> PCI 0x0_00000000-0x0_0x0008ffff (I/O)
>   IA 0x80000000-0x8fefffff -> PCI 0x0_80000000-0x0_0x8fefffff (32-bit mem)
>
> The diagram shows the address translations for all three address
> spaces (config, I/O, memory).  If we ignore the 0x5f000000 range, the
> mem and I/O paths through the diagram make sense to me:
>
>   CPU 0x0_7ff80000 -> IA 0x8ff80000 -> PCI   0x00000000 I/O
>   CPU 0x0_70000000 -> IA 0x80000000 -> PCI 0x0_80000000 mem
>
> I guess config space handled separately from "ranges"?  The diagram
> suggests that it's something like this:

Yes, history reason, dwc's config space is not in ranges.

>
>   CPU 0x0_7ff00000 -> IA 0x8ff00000 -> PCI 0x00000000 config
>
> which looks like it would match the "reg" property.

regname = "config"

Frank
>
> > 	};
> > };
> >
> > 'parent_bus_addr' in of_pci_range can indicate above diagram internal
> > address (IA) address information.
> >
> > Reviewed-by: Rob Herring (Arm) <robh@xxxxxxxxxx>
> > Signed-off-by: Frank Li <Frank.Li@xxxxxxx>
> > ---
> > Change from v3 to v4
> > - improve commit message by driver source code path.
> >
> > Change from v2 to v3
> > - cpu_untranslate_addr -> parent_bus_addr
> > - Add Rob's review tag
> >   I changed commit message base on Bjorn, if you have concern about review
> > added tag, let me know.
> >
> > Change from v1 to v2
> > - add parent_bus_addr in of_pci_range, instead adding new API.
> > ---
> >  drivers/of/address.c       | 2 ++
> >  include/linux/of_address.h | 1 +
> >  2 files changed, 3 insertions(+)
> >
> > diff --git a/drivers/of/address.c b/drivers/of/address.c
> > index 286f0c161e332..1a0229ee4e0b2 100644
> > --- a/drivers/of/address.c
> > +++ b/drivers/of/address.c
> > @@ -811,6 +811,8 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
> >  	else
> >  		range->cpu_addr = of_translate_address(parser->node,
> >  				parser->range + na);
> > +
> > +	range->parent_bus_addr = of_read_number(parser->range + na, parser->pna);
> >  	range->size = of_read_number(parser->range + parser->pna + na, ns);
> >
> >  	parser->range += np;
> > diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> > index 26a19daf0d092..13dd79186d02c 100644
> > --- a/include/linux/of_address.h
> > +++ b/include/linux/of_address.h
> > @@ -26,6 +26,7 @@ struct of_pci_range {
> >  		u64 bus_addr;
> >  	};
> >  	u64 cpu_addr;
> > +	u64 parent_bus_addr;
> >  	u64 size;
> >  	u32 flags;
> >  };
> >
> > --
> > 2.34.1
> >




[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux