linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Bjorn Helgaas <bhelgaas@google.com>
To: Yinghai Lu <yinghai@kernel.org>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>,
	Benjamin Herrenschmidt <benh@kernel.crashing.org>,
	Tony Luck <tony.luck@intel.com>,
	David Miller <davem@davemloft.net>, x86 <x86@kernel.org>,
	Dominik Brodowski <linux@dominikbrodowski.net>,
	Andrew Morton <akpm@linux-foundation.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-arch@vger.kernel.org
Subject: Re: [PATCH -v11 17/30] resources: Add probe_resource()
Date: Tue, 1 May 2012 17:57:58 -0600	[thread overview]
Message-ID: <CAErSpo4BZAf_i3ojXpg5WSFJ00G5i_vscVTu2va_Z3WJ0UHg=g@mail.gmail.com> (raw)
In-Reply-To: <1332135781-13695-18-git-send-email-yinghai@kernel.org>

On Sun, Mar 18, 2012 at 11:42 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> It is changed from busn_res only version, because Bjorn found that version
> was not holding resource_lock.
> Even it may be ok for busn_res not holding resource_lock.
> It would be better to have it to be generic and use lock and we would
> use it for other resources.
>
> probe_resource() will try to find specified size or more in parent bus.
> If can not find current parent resource, and it will try to expand parents
> top.
> If still can not find that specified on top, it will try to reduce target size
> until find one.
>
> It will return 0, if it find any resource that it could use.
>
> Returned resource already register in the tree.
>
> So caller may still need call resource_replace to put real resource in
> the tree.
>
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> ---
>  include/linux/ioport.h |    7 ++
>  kernel/resource.c      |  160 ++++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 162 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/ioport.h b/include/linux/ioport.h
> index e885ba2..20a30df 100644
> --- a/include/linux/ioport.h
> +++ b/include/linux/ioport.h
> @@ -156,6 +156,13 @@ extern int allocate_resource(struct resource *root, struct resource *new,
>                                                       resource_size_t,
>                                                       resource_size_t),
>                             void *alignf_data);
> +void resource_shrink_parents_top(struct resource *b_res,
> +                                long size, struct resource *parent_res);
> +struct device;
> +int probe_resource(struct resource *b_res,
> +                       struct device *dev, struct resource *busn_res,
> +                       resource_size_t needed_size, struct resource **p,
> +                       int skip_nr, int limit, char *name);

This interface is a mess.  I have a vague impression that this is
supposed to figure out whether a resource can be expanded, but why
does it need a struct device *?  (I can read the code and see how you
use it, but it just doesn't fit in the resource abstraction.)
Supplying one struct resource * makes sense, but you have three.  A
char * name?  What's skip_nr?  This just doesn't make sense to me.

I think you need a simpler, more general interface.  update_resource()
seems OK to me -- it's pretty straightforward and has an obvious
meaning.  Maybe you can make a resource_expand() or something that
just expands a resource in both directions as far as possible (until
it hits a sibling or the parent limits).  Then you would know the
maximum possible size, and you could use update_resource() to shrink
it again and give up anything you don't need.

I spent most of the day merging the patches up to this point, and they
mostly make sense, but this one and the following ones are beyond my
ken, so I gave up.

>  struct resource *lookup_resource(struct resource *root, resource_size_t start);
>  int adjust_resource(struct resource *res, resource_size_t start,
>                    resource_size_t size);
> diff --git a/kernel/resource.c b/kernel/resource.c
> index 7640b3a..0c9616f 100644
> --- a/kernel/resource.c
> +++ b/kernel/resource.c
> @@ -521,14 +521,14 @@ out:
>  * @alignf: alignment function, optional, called if not NULL
>  * @alignf_data: arbitrary data to pass to the @alignf function
>  */
> -int allocate_resource(struct resource *root, struct resource *new,
> +static int __allocate_resource(struct resource *root, struct resource *new,
>                      resource_size_t size, resource_size_t min,
>                      resource_size_t max, resource_size_t align,
>                      resource_size_t (*alignf)(void *,
>                                                const struct resource *,
>                                                resource_size_t,
>                                                resource_size_t),
> -                     void *alignf_data)
> +                     void *alignf_data, bool lock)
>  {
>        int err;
>        struct resource_constraint constraint;
> @@ -542,19 +542,33 @@ int allocate_resource(struct resource *root, struct resource *new,
>        constraint.alignf = alignf;
>        constraint.alignf_data = alignf_data;
>
> -       if ( new->parent ) {
> +       if (new->parent && lock) {
>                /* resource is already allocated, try reallocating with
>                   the new constraints */
>                return reallocate_resource(root, new, size, &constraint);
>        }
>
> -       write_lock(&resource_lock);
> +       if (lock)
> +               write_lock(&resource_lock);
>        err = find_resource(root, new, size, &constraint);
>        if (err >= 0 && __request_resource(root, new))
>                err = -EBUSY;
> -       write_unlock(&resource_lock);
> +       if (lock)
> +               write_unlock(&resource_lock);
>        return err;
>  }
> +int allocate_resource(struct resource *root, struct resource *new,
> +                     resource_size_t size, resource_size_t min,
> +                     resource_size_t max, resource_size_t align,
> +                     resource_size_t (*alignf)(void *,
> +                                               const struct resource *,
> +                                               resource_size_t,
> +                                               resource_size_t),
> +                     void *alignf_data)
> +{
> +       return __allocate_resource(root, new, size, min, max, align,
> +                                  alignf, alignf_data, true);
> +}
>
>  EXPORT_SYMBOL(allocate_resource);
>
> @@ -962,6 +976,142 @@ void __release_region(struct resource *parent, resource_size_t start,
>  }
>  EXPORT_SYMBOL(__release_region);
>
> +static void __resource_update_parents_top(struct resource *b_res,
> +                long size, struct resource *parent_res)
> +{
> +       struct resource *res = b_res;
> +
> +       if (!size)
> +               return;
> +
> +       while (res) {
> +               if (res == parent_res)
> +                       break;
> +               res->end += size;
> +               res = res->parent;
> +       }
> +}
> +
> +static void __resource_extend_parents_top(struct resource *b_res,
> +                long size, struct resource *parent_res)
> +{
> +       __resource_update_parents_top(b_res, size, parent_res);
> +}
> +
> +void resource_shrink_parents_top(struct resource *b_res,
> +                long size, struct resource *parent_res)
> +{
> +       write_lock(&resource_lock);
> +       __resource_update_parents_top(b_res, -size, parent_res);
> +       write_unlock(&resource_lock);
> +}
> +
> +static resource_size_t __find_res_top_free_size(struct resource *res)
> +{
> +       resource_size_t n_size;
> +       struct resource tmp_res;
> +
> +       /*
> +        *   find out number below res->end, that we can use at first
> +        *      res->start can not be used.
> +        */
> +       n_size = resource_size(res) - 1;
> +       memset(&tmp_res, 0, sizeof(struct resource));
> +       while (n_size > 0) {
> +               int ret;
> +
> +               ret = __allocate_resource(res, &tmp_res, n_size,
> +                       res->end - n_size + 1, res->end,
> +                       1, NULL, NULL, false);
> +               if (ret == 0) {
> +                       __release_resource(&tmp_res);
> +                       break;
> +               }
> +               n_size--;
> +       }
> +
> +       return n_size;
> +}
> +
> +int probe_resource(struct resource *b_res,
> +                        struct device *dev, struct resource *busn_res,
> +                        resource_size_t needed_size, struct resource **p,
> +                        int skip_nr, int limit, char *name)
> +{
> +       int ret = -ENOMEM;
> +       resource_size_t n_size;
> +       struct resource *parent_res = NULL;
> +       resource_size_t tmp = b_res->end + 1;
> +
> +again:
> +       /*
> +        * find biggest range in b_res that we can use in the middle
> +        *  and we can not use some spots from start of b_res.
> +        */
> +       n_size = resource_size(b_res);
> +       if (n_size > skip_nr)
> +               n_size -= skip_nr;
> +       else
> +               n_size = 0;
> +
> +       memset(busn_res, 0, sizeof(struct resource));
> +       dev_printk(KERN_DEBUG, dev, "find free %s in res: %pR\n", name, b_res);
> +       while (n_size >= needed_size) {
> +               ret = allocate_resource(b_res, busn_res, n_size,
> +                               b_res->start + skip_nr, b_res->end,
> +                               1, NULL, NULL);
> +               if (!ret)
> +                       return ret;
> +               n_size--;
> +       }
> +
> +       /* try extend the top of parent bus, find free under top at first */
> +       write_lock(&resource_lock);
> +       n_size = __find_res_top_free_size(b_res);
> +       dev_printk(KERN_DEBUG, dev, "found free %s %ld in res: %pR top\n",
> +                       name, (unsigned long)n_size, b_res);
> +
> +       /* can not extend cross local boundary */
> +       if ((limit - b_res->end) < (needed_size - n_size))
> +               goto reduce_needed_size;
> +
> +       /* find extended range */
> +       memset(busn_res, 0, sizeof(struct resource));
> +       parent_res = b_res;
> +       while (parent_res) {
> +               ret = __allocate_resource(parent_res, busn_res,
> +                        needed_size - n_size,
> +                        tmp, tmp + needed_size - n_size - 1,
> +                        1, NULL, NULL, false);
> +               if (!ret) {
> +                       /* save parent_res, we need it as stopper later */
> +                       *p = parent_res;
> +
> +                       /* prepare busn_res for return */
> +                       __release_resource(busn_res);
> +                       busn_res->start -= n_size;
> +
> +                       /* extend parent bus top*/
> +                       __resource_extend_parents_top(b_res,
> +                                        needed_size - n_size, parent_res);
> +                       __request_resource(b_res, busn_res);
> +
> +                       write_unlock(&resource_lock);
> +                       return ret;
> +               }
> +               parent_res = parent_res->parent;
> +       }
> +
> +reduce_needed_size:
> +       write_unlock(&resource_lock);
> +       /* ret must not be 0 here */
> +       needed_size--;
> +       if (needed_size)
> +               goto again;
> +
> +       return ret;
> +}
> +
>  /*
>  * Managed region resource
>  */
> --
> 1.7.7
>

  reply	other threads:[~2012-05-01 23:58 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-19  5:42 [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 01/30] x86, PCI: Add print all root info for not using _CRS path Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 02/30] x86, PCI: Allocate temp range array in amd_bus pci_root_info probing Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 03/30] x86, PCI: Merge pcibios_scan_root and pci_scan_bus_on_node Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 04/30] PCI: Add busn_res into struct pci_bus Yinghai Lu
2012-04-30 23:25   ` Bjorn Helgaas
2012-05-01  0:32     ` Yinghai Lu
2012-05-01  4:02       ` Bjorn Helgaas
2012-05-01  6:27         ` Yinghai Lu
2012-05-01 15:40           ` Bjorn Helgaas
2012-05-01 19:28             ` Yinghai Lu
2012-05-02  5:07               ` Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 05/30] PCI: Add busn_res operation functions Yinghai Lu
2012-04-30 23:29   ` Bjorn Helgaas
2012-05-01  0:34     ` Yinghai Lu
2012-05-01  7:19       ` Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 06/30] PCI: Release busn_res when removing bus Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 07/30] PCI: Insert busn_res in pci_create_root_bus() Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 08/30] PCI: Checking busn_res in pci_scan_root_bus() Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 09/30] PCI: Add default busn_resource Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 10/30] PCI: Add default busn_res for pci_scan_bus() Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 11/30] x86, PCI: Add busn_res into resources list for acpi path Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 12/30] x86, PCI: Put busn resource in pci_root_info for not using _CRS path Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 13/30] PCI, ia64: Register busn_res for root buses Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 14/30] PCI, sparc: " Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 15/30] PCI, powerpc: " Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 16/30] PCI, parisc: " Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 17/30] resources: Add probe_resource() Yinghai Lu
2012-05-01 23:57   ` Bjorn Helgaas [this message]
2012-05-02  5:19     ` Yinghai Lu
2012-05-02  7:01       ` Yinghai Lu
2012-05-02 15:14         ` Bjorn Helgaas
2012-03-19  5:42 ` [PATCH -v11 18/30] resources: Replace registered resource in tree Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 19/30] PCI: Add pci_bus_extend/shrink_top() Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 20/30] PCI: Probe safe range that we can use for unassigned bridge Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 21/30] PCI: Add pci_bus_replace_busn_res() Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 22/30] PCI: Allocate bus range instead of use max blindly Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 23/30] PCI: Strict checking of valid range for bridge Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 24/30] PCI: Kill pci_fixup_parent_subordinate_busnr() Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 25/30] PCI: Seperate child bus scanning to two passes overall Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 26/30] pcmcia: Remove workaround for fixing pci parent bus subordinate Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 27/30] PCI: Double checking setting for bus register and bus struct Yinghai Lu
2012-03-19  5:42 ` [PATCH -v11 28/30] PCI, pciehp: Remove not needed bus number range checking Yinghai Lu
2012-03-19  5:43 ` [PATCH -v11 29/30] PCI: More strict checking of valid range for bridge Yinghai Lu
2012-03-19  5:43 ` [PATCH -v11 30/30] PCI: Don't shrink too much for hotplug bridge Yinghai Lu
2012-05-02 21:22 ` [PATCH -v11 00/30] PCI: allocate pci bus num range for unassigned bridge busn Bjorn Helgaas
2012-05-03  9:08   ` Yinghai Lu
2012-05-03 23:47     ` Bjorn Helgaas
2012-05-04 20:07       ` Yinghai Lu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAErSpo4BZAf_i3ojXpg5WSFJ00G5i_vscVTu2va_Z3WJ0UHg=g@mail.gmail.com' \
    --to=bhelgaas@google.com \
    --cc=akpm@linux-foundation.org \
    --cc=benh@kernel.crashing.org \
    --cc=davem@davemloft.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=jbarnes@virtuousgeek.org \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux@dominikbrodowski.net \
    --cc=tony.luck@intel.com \
    --cc=torvalds@linux-foundation.org \
    --cc=x86@kernel.org \
    --cc=yinghai@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).