[PATCH] PCI: generic: map config window in one go

Ard Biesheuvel ard.biesheuvel at linaro.org
Fri Jan 29 06:19:36 PST 2016


On 29 January 2016 at 15:17, Ard Biesheuvel <ard.biesheuvel at linaro.org> wrote:
> Instead of iterating over the PCI config window and performing individual
> ioremap() calls on all the adjacent slices, perform a single ioremap() to
> map the entire region, and divvy it up later. This not only prevents
> leaving some of it mapped if we fail half way through, it also ensures that
> archs that support huge-vmap can use section mappings to perform the
> mapping.
>
> On my Seattle A0 box, this transforms 128 separate 1 MB mappings that are
> mapped down to 4 KB pages into a single 128 MB mapping using 2 MB sections,
> saving 512 KB worth of page tables.
>

OK, this math is slightly off: 4 KB for each 2 MB section == 64 * 4 == 128 KB

> Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> ---
>
> huge-vmap for arm64 proposed here:
> http://article.gmane.org/gmane.linux.kernel.hardened.devel/1661
>
>  drivers/pci/host/pci-host-generic.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
> index 1652bc70b145..3251cd779278 100644
> --- a/drivers/pci/host/pci-host-generic.c
> +++ b/drivers/pci/host/pci-host-generic.c
> @@ -161,6 +161,7 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
>         struct device *dev = pci->host.dev.parent;
>         struct device_node *np = dev->of_node;
>         u32 sz = 1 << pci->cfg.ops->bus_shift;
> +       void *window;
>
>         err = of_address_to_resource(np, 0, &pci->cfg.res);
>         if (err) {
> @@ -186,14 +187,15 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
>                 return -ENOMEM;
>
>         bus_range = pci->cfg.bus_range;
> +       window = devm_ioremap(dev, pci->cfg.res.start,
> +                             (bus_range->end - bus_range->start + 1) * sz);
> +       if (!window)
> +               return -ENOMEM;
> +
>         for (busn = bus_range->start; busn <= bus_range->end; ++busn) {
>                 u32 idx = busn - bus_range->start;
>
> -               pci->cfg.win[idx] = devm_ioremap(dev,
> -                                                pci->cfg.res.start + idx * sz,
> -                                                sz);
> -               if (!pci->cfg.win[idx])
> -                       return -ENOMEM;
> +               pci->cfg.win[idx] = window + idx * sz;
>         }
>
>         return 0;
> --
> 2.5.0
>



More information about the linux-arm-kernel mailing list