lkml.org 
[lkml]   [2010]   [Dec]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH 3/5] x86: avoid PNP resources when allocating address space
    From
    Date

    Remove PNP resources from "available space" used by allocate_resource().
    This would be better done by putting the PNP resources directly in the
    resource maps (iomem_resource, etc), but there are some issues that
    keep us from doing that yet.

    This patch keeps us from handing out PNP device address space to other
    callers of allocate_resource().

    Reference: https://bugzilla.kernel.org/show_bug.cgi?id=23332
    Reference: https://bugzilla.kernel.org/show_bug.cgi?id=23542
    Reference: https://bugzilla.kernel.org/show_bug.cgi?id=23802
    Reported-by: Matthew Garrett <mjg@redhat.com>
    Reported-by: Dan Williams <dcbw@redhat.com>
    Reported-by: Jiri Slaby <jirislaby@gmail.com>
    Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
    ---

    arch/x86/kernel/resource.c | 78 ++++++++++++++++++++++++++++++++++++++++++++
    1 files changed, 78 insertions(+), 0 deletions(-)


    diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c
    index 5dd6473..1daee92 100644
    --- a/arch/x86/kernel/resource.c
    +++ b/arch/x86/kernel/resource.c
    @@ -1,6 +1,80 @@
    #include <linux/ioport.h>
    +#include <linux/pnp.h>
    #include <asm/e820.h>

    +#ifdef CONFIG_PNP
    +static bool resource_conflict(struct resource *res, resource_size_t start,
    + resource_size_t end)
    +{
    + /*
    + * Return true if and only if "res" conflicts with the [start-end]
    + * range.
    + */
    + return res->start <= end && res->end >= start;
    +}
    +
    +static void resource_split(struct resource *res, resource_size_t start,
    + resource_size_t end, struct resource *low,
    + struct resource *high)
    +{
    + /*
    + * If "res" conflicts with [start-end], split "res" into the
    + * part below "start" (low) and the part above "end" (high),
    + * either (or both) of which may be empty.
    + *
    + * If there's no conflict, return the entire "res" as "low".
    + */
    + *low = *res;
    + low->start = res->start;
    + low->end = res->start - 1; /* default to empty (size 0) */
    +
    + *high = *res;
    + high->end = res->end;
    + high->start = res->end + 1; /* default to empty (size 0) */
    +
    + if (!resource_conflict(res, start, end)) {
    + low->end = res->end;
    + return;
    + }
    +
    + if (res->start < start)
    + low->end = start - 1;
    +
    + if (res->end > end)
    + high->start = end + 1;
    +}
    +
    +static void pnp_remove_reservations(struct resource *avail)
    +{
    + unsigned long type = resource_type(avail);
    + struct pnp_dev *dev;
    + int i;
    + struct resource *res, low, high;
    +
    + /*
    + * Clip the available region to avoid PNP devices. The PNP
    + * resources really should be in the resource map to begin with,
    + * but there are still some issues preventing that.
    + */
    + pnp_for_each_dev(dev) {
    + i = 0;
    + res = pnp_get_resource(dev, type, i++);
    + while (res) {
    + if (!(res->flags & IORESOURCE_WINDOW)) {
    + resource_split(avail, res->start, res->end,
    + &low, &high);
    + if (resource_size(&low) > resource_size(&high))
    + *avail = low;
    + else
    + *avail = high;
    + }
    +
    + res = pnp_get_resource(dev, type, i++);
    + }
    + }
    +}
    +#endif
    +
    void arch_remove_reservations(struct resource *avail)
    {
    /*
    @@ -11,4 +85,8 @@ void arch_remove_reservations(struct resource *avail)
    if (avail->start < BIOS_END)
    avail->start = BIOS_END;
    }
    +
    +#ifdef CONFIG_PNP
    + pnp_remove_reservations(avail);
    +#endif
    }


    \
     
     \ /
      Last update: 2010-12-08 22:41    [W:0.030 / U:31.504 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site