[PATCH RFC v4 17/21] PCI: Calculate boundaries for bridge windows
Bjorn Helgaas
helgaas at kernel.org
Wed Mar 27 08:01:28 AEDT 2019
On Mon, Mar 11, 2019 at 04:31:18PM +0300, Sergey Miroshnichenko wrote:
> If a bridge window contains fixed areas (there are PCIe devices with
> immovable BARs located on this bus),
I think what you mean by "immovable BARs" is "drivers that don't
support moving BARs". I want to keep the concept of legacy and EA
resources separate because those are immovable in principle, but
drivers can always be improved.
> this window must be allocated
> within the bound memory area, limited by windows size and by address
> range of fixed resources, calculated as follows:
>
> | <-- bus's fixed_range_hard --> |
> | <-- fixed_range_hard.end - window size --> |
> | <-- fixed_range_hard.start + window size --> |
> | <-- bus's fixed_range_soft --> |
>
> Signed-off-by: Sergey Miroshnichenko <s.miroshnichenko at yadro.com>
> ---
> drivers/pci/setup-bus.c | 56 +++++++++++++++++++++++++++++++++++++++++
> include/linux/pci.h | 4 ++-
> 2 files changed, 59 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
> index a1fd7f3c5ea8..f4737339d5ec 100644
> --- a/drivers/pci/setup-bus.c
> +++ b/drivers/pci/setup-bus.c
> @@ -1809,6 +1809,61 @@ static enum enable_type pci_realloc_detect(struct pci_bus *bus,
> }
> #endif
>
> +static void pci_bus_update_fixed_range_soft(struct pci_bus *bus)
> +{
> + struct pci_dev *dev;
> + struct pci_bus *parent = bus->parent;
> + int idx;
> +
> + list_for_each_entry(dev, &bus->devices, bus_list)
> + if (dev->subordinate)
> + pci_bus_update_fixed_range_soft(dev->subordinate);
> +
> + if (!parent || !bus->self)
> + return;
> +
> + for (idx = 0; idx < ARRAY_SIZE(bus->fixed_range_hard); ++idx) {
> + struct resource *r;
> + resource_size_t soft_start, soft_end;
> + resource_size_t hard_start = bus->fixed_range_hard[idx].start;
> + resource_size_t hard_end = bus->fixed_range_hard[idx].end;
> +
> + if (hard_start > hard_end)
> + continue;
> +
> + r = bus->resource[idx];
> +
> + soft_start = hard_end - resource_size(r) + 1;
> + soft_end = hard_start + resource_size(r) - 1;
> +
> + if (soft_start > hard_start)
> + soft_start = hard_start;
> +
> + if (soft_end < hard_end)
> + soft_end = hard_end;
> +
> + list_for_each_entry(dev, &parent->devices, bus_list) {
> + struct pci_bus *sibling = dev->subordinate;
> + resource_size_t s_start, s_end;
> +
> + if (!sibling || sibling == bus)
> + continue;
> +
> + s_start = sibling->fixed_range_hard[idx].start;
> + s_end = sibling->fixed_range_hard[idx].end;
> +
> + if (s_start > s_end)
> + continue;
> +
> + if (s_end < hard_start && s_end > soft_start)
> + soft_start = s_end;
> + }
> +
> + bus->fixed_range_soft[idx].start = soft_start;
> + bus->fixed_range_soft[idx].end = soft_end;
> + }
> +}
> +
> /*
> * first try will not touch pci bridge res
> * second and later try will clear small leaf bridge res
> @@ -1847,6 +1902,7 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
> /* Depth first, calculate sizes and alignments of all
> subordinate buses. */
> __pci_bus_size_bridges(bus, add_list);
> + pci_bus_update_fixed_range_soft(bus);
>
> /* Depth last, allocate resources and update the hardware. */
> __pci_bus_assign_resources(bus, add_list, &fail_head);
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 7a4d62d84bc1..75a56db73ad4 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -574,9 +574,11 @@ struct pci_bus {
>
> /*
> * If there are fixed resources in the bridge window, the hard range
> - * contains the lowest and the highest addresses of them.
> + * contains the lowest and the highest addresses of them, and this
> + * bridge window must reside within the soft range.
> */
> struct resource fixed_range_hard[PCI_BRIDGE_RESOURCE_NUM];
> + struct resource fixed_range_soft[PCI_BRIDGE_RESOURCE_NUM];
>
> struct pci_ops *ops; /* Configuration access functions */
> struct msi_controller *msi; /* MSI controller */
> --
> 2.20.1
>
More information about the Linuxppc-dev
mailing list