linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Bjorn Helgaas <bhelgaas@google.com>
To: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: LKML <linux-kernel@vger.kernel.org>,
	ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
	linux-pci@vger.kernel.org, Yinghai Lu <yinghai@kernel.org>,
	Toshi Kani <toshi.kani@hp.com>,
	Myron Stowe <myron.stowe@redhat.com>
Subject: Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
Date: Wed, 12 Dec 2012 18:00:03 -0700	[thread overview]
Message-ID: <CAErSpo7=2WUbNgtFHT6Sm6h6OKfXkSH99qSoD0n73Tga0=XpTA@mail.gmail.com> (raw)
In-Reply-To: <4002729.BbipMAJtM0@vostro.rjw.lan>

On Sun, Dec 9, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Currently, as soon as an ACPI device node object (struct acpi_device)
> is created, the driver core attempts to probe ACPI drivers against
> it.  That leads to some unpleasant side effects, like the fact that
> the boot code path for ACPI namespace scanning is different from the
> analogous hot-plug code path (during boot ACPI drivers are not
> present when ACPI device node objects are registered, so they are
> guaranteed not to be probed, which is not the case during hot-plug).
> That, in turn, leads to unnecessary complications in the PCI
> enumeration algorithm.

Can you elaborate a bit on the complications in PCI enumeration?
Hopefully this will lead to some simplification in PCI enumeration,
but these patches don't go that far (yet).

> Reduce the differences between the boot and hot-plug cases by
> splitting the ACPI namespace scanning for devices into two passes,
> such that struct acpi_device objects are registerd in the first
> patch without probing ACPI drivers and the drivers are probed
> against them directly in the second pass.  This way ACPI drivers
> can assume that all of the ACPI device node objects in the given
> scope will be registered when their .add() routines run and the
> hot-plug case becomes the same as the boot case from their
> perspective.

If I understand correctly, you're talking about a hierarchical
topology where a device, e.g., a bridge, can have subordinate devices
below it.

In general terms, if a driver claims X, and the driver's add() method
can assume that every device below X has already been registered, I
guess that means any bridge drivers must be integrated into the core,
so the core can enumerate things below the bridge without the driver's
help.  The PCI core effectively has the P2P bridge driver integrated
into it, so that's the way it is already for PCI.  I can imagine
scenarios, e.g., NTBs, where it's not practical to integrate the
bridge driver, so I'm not 100% comfortable with this assumption.  But
I admit that's a totally hypothetical situation, and there are lots of
other obstacles to non-integrated bridge drivers, like the fact that
we can't do dynamic resource assignment.

s/registerd/registered/ above

> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/acpi/scan.c     |   96 +++++++++++++++++++++++++++++++++---------------
>  include/acpi/acpi_bus.h |    1
>  2 files changed, 68 insertions(+), 29 deletions(-)
>
> Index: linux/include/acpi/acpi_bus.h
> ===================================================================
> --- linux.orig/include/acpi/acpi_bus.h
> +++ linux/include/acpi/acpi_bus.h
> @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a
>  struct acpi_bus_ops {
>         u32 acpi_op_add:1;
>         u32 acpi_op_start:1;
> +       u32 acpi_op_match:1;
>  };
>
>  struct acpi_device_ops {
> Index: linux/drivers/acpi/scan.c
> ===================================================================
> --- linux.orig/drivers/acpi/scan.c
> +++ linux/drivers/acpi/scan.c
> @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
>         struct acpi_device *acpi_dev = to_acpi_device(dev);
>         struct acpi_driver *acpi_drv = to_acpi_driver(drv);
>
> -       return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> +       return acpi_dev->bus_ops.acpi_op_match
> +               && !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
>  }
>
>  static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
> @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d
>         return 0;
>  }
>
> +/*
> + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
> + * @device: ACPI device node to bind.
> + */
> +static void acpi_hot_add_bind(struct acpi_device *device)
> +{
> +       if (device->flags.bus_address
> +           && device->parent && device->parent->ops.bind)
> +               device->parent->ops.bind(device);
> +}
> +
>  static int acpi_add_single_object(struct acpi_device **child,
>                                   acpi_handle handle, int type,
>                                   unsigned long long sta,
> @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct
>
>         result = acpi_device_register(device);
>
> -       /*
> -        * Bind _ADR-Based Devices when hot add
> -        */
> -       if (device->flags.bus_address) {
> -               if (device->parent && device->parent->ops.bind)
> -                       device->parent->ops.bind(device);
> -       }
> +       if (device->bus_ops.acpi_op_match)
> +               acpi_hot_add_bind(device);
>
>  end:
>         if (!result) {
> @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(
>         struct acpi_bus_ops ops = {
>                 .acpi_op_add = 1,
>                 .acpi_op_start = 1,
> +               .acpi_op_match = 1,
>         };
>         struct acpi_device *device = NULL;
>
> @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac
>                                       void *context, void **return_value)
>  {
>         struct acpi_bus_ops *ops = context;
> +       struct acpi_device *device = NULL;
>         int type;
>         unsigned long long sta;
> -       struct acpi_device *device;
>         acpi_status status;
>         int result;
>
> @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac
>          * We may already have an acpi_device from a previous enumeration.  If
>          * so, we needn't add it again, but we may still have to start it.
>          */
> -       device = NULL;
>         acpi_bus_get_device(handle, &device);
>         if (ops->acpi_op_add && !device) {
> -               acpi_add_single_object(&device, handle, type, sta, ops);
> -               /* Is the device a known good platform device? */
> -               if (device
> -                   && !acpi_match_device_ids(device, acpi_platform_device_ids))
> -                       acpi_create_platform_device(device);
> -       }
> +               struct acpi_bus_ops add_ops = *ops;
>
> -       if (!device)
> -               return AE_CTRL_DEPTH;
> -
> -       if (ops->acpi_op_start && !(ops->acpi_op_add)) {
> -               status = acpi_start_single_object(device);
> -               if (ACPI_FAILURE(status))
> +               add_ops.acpi_op_match = 0;
> +               acpi_add_single_object(&device, handle, type, sta, &add_ops);
> +               if (!device)
>                         return AE_CTRL_DEPTH;
> +
> +               device->bus_ops.acpi_op_match = 1;
>         }
>
>         if (!*return_value)
>                 *return_value = device;
> +
>         return AE_OK;
>  }
>
> +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
> +                                       void *context, void **not_used)
> +{
> +       struct acpi_bus_ops *ops = context;
> +       struct acpi_device *device;
> +       acpi_status status = AE_OK;
> +
> +       if (acpi_bus_get_device(handle, &device))
> +               return AE_CTRL_DEPTH;
> +
> +       if (ops->acpi_op_add) {
> +               if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
> +                       /* This is a known good platform device. */
> +                       acpi_create_platform_device(device);
> +               } else {
> +                       int ret = device_attach(&device->dev);
> +                       acpi_hot_add_bind(device);
> +                       if (ret)
> +                               status = AE_CTRL_DEPTH;
> +               }
> +       } else if (ops->acpi_op_start) {
> +               if (ACPI_FAILURE(acpi_start_single_object(device)))
> +                       status = AE_CTRL_DEPTH;
> +       }
> +       return status;
> +}
> +
>  static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
>                          struct acpi_device **child)
>  {
> -       acpi_status status;
>         void *device = NULL;
> +       acpi_status status;
> +       int ret = 0;
>
>         status = acpi_bus_check_add(handle, 0, ops, &device);
> -       if (ACPI_SUCCESS(status))
> +       if (ACPI_FAILURE(status)) {
> +               ret = -ENODEV;
> +               goto out;
> +       }
> +
> +       acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> +                           acpi_bus_check_add, NULL, ops, &device);
> +       if (device)
>                 acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> -                                   acpi_bus_check_add, NULL, ops, &device);
> +                                   acpi_bus_probe_start, NULL, ops, NULL);
> +       else
> +               ret = -ENODEV;
>
> + out:
>         if (child)
>                 *child = device;
>
> -       if (device)
> -               return 0;
> -       else
> -               return -ENODEV;
> +       return ret;
>  }
>
>  /*
> @@ -1752,6 +1789,7 @@ static int acpi_bus_scan_fixed(void)
>         memset(&ops, 0, sizeof(ops));
>         ops.acpi_op_add = 1;
>         ops.acpi_op_start = 1;
> +       ops.acpi_op_match = 1;
>
>         /*
>          * Enumerate all fixed-feature devices.
>

  parent reply	other threads:[~2012-12-13  1:00 UTC|newest]

Thread overview: 88+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki
2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
2012-12-12 15:50   ` Jiang Liu
2012-12-12 22:34     ` Rafael J. Wysocki
2012-12-12 16:38   ` Jiang Liu
2012-12-12 22:32     ` Rafael J. Wysocki
2012-12-12 23:43       ` [update][PATCH " Rafael J. Wysocki
2012-12-13 13:05       ` [PATCH " Jiang Liu
2012-12-13 19:40         ` Rafael J. Wysocki
2012-12-13  1:00   ` Bjorn Helgaas [this message]
2012-12-13 11:41     ` Rafael J. Wysocki
2012-12-09 23:00 ` [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
2012-12-13  1:00   ` Bjorn Helgaas
2012-12-13 12:19     ` Rafael J. Wysocki
2012-12-09 23:01 ` [PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
2012-12-13  0:11   ` [Update][PATCH " Rafael J. Wysocki
2012-12-09 23:02 ` [PATCH 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki
2012-12-09 23:03 ` [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
2012-12-10  5:34   ` Yinghai Lu
2012-12-10 14:46     ` Rafael J. Wysocki
2012-12-10 17:07       ` Yinghai Lu
2012-12-10 22:47         ` Rafael J. Wysocki
2012-12-10 23:09           ` Rafael J. Wysocki
2012-12-10 23:14             ` Yinghai Lu
2012-12-11  1:02               ` Rafael J. Wysocki
2012-12-11  1:28                 ` Rafael J. Wysocki
2012-12-11  2:26                   ` Yinghai Lu
2012-12-11 12:45                     ` Rafael J. Wysocki
2012-12-11 15:09                     ` Jiang Liu
2012-12-11 18:30                       ` Rafael J. Wysocki
2012-12-12 14:34                         ` Yijing Wang
2012-12-12 15:05                           ` Jiang Liu
2012-12-12 22:39                             ` Rafael J. Wysocki
2012-12-10 23:22           ` Yinghai Lu
2012-12-11  0:48             ` Rafael J. Wysocki
2012-12-09 23:04 ` [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
2012-12-13  1:00   ` Bjorn Helgaas
2012-12-13 12:20     ` Rafael J. Wysocki
2012-12-13 11:45 ` [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang
2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki
2012-12-13 22:17   ` [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
2012-12-18  0:08     ` Toshi Kani
2012-12-18  1:48       ` Rafael J. Wysocki
2012-12-18 16:10         ` Toshi Kani
2012-12-18 18:59           ` Yinghai Lu
2012-12-18 20:48             ` Toshi Kani
2012-12-18 21:11               ` Yinghai Lu
2012-12-18 22:05             ` Rafael J. Wysocki
2012-12-19  1:57               ` Yinghai Lu
2012-12-18 21:57           ` Rafael J. Wysocki
2012-12-18 22:15             ` Toshi Kani
2012-12-18 23:00               ` Rafael J. Wysocki
2012-12-18 23:19                 ` Bjorn Helgaas
2012-12-19 11:13                   ` Rafael J. Wysocki
2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
2012-12-20  1:47           ` [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
2013-01-11 20:00             ` Mika Westerberg
2013-01-11 20:31               ` Rafael J. Wysocki
2013-01-11 20:37                 ` Mika Westerberg
2013-01-11 20:58                   ` Rafael J. Wysocki
2013-01-11 20:59                     ` Mika Westerberg
2012-12-20  1:48           ` [PATCH 2/16] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
2012-12-20  1:49           ` [PATCH 3/16] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
2012-12-20  1:50           ` [PATCH 4/16] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki
2012-12-20  1:50           ` [PATCH 5/16] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
2012-12-20  1:51           ` [PATCH 6/16] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
2012-12-20  1:52           ` [PATCH 7/16] ACPI / PCI: Fold acpi_pci_root_start() into acpi_pci_root_add() Rafael J. Wysocki
2012-12-20  1:53           ` [PATCH 8/16] ACPI: Remove acpi_start_single_object() and acpi_bus_start() Rafael J. Wysocki
2012-12-20  1:54           ` [PATCH 9/16] ACPI: Remove the arguments of acpi_bus_add() that are not used Rafael J. Wysocki
2012-12-20  1:54           ` [PATCH 10/16] ACPI: Drop the second argument of acpi_bus_scan() Rafael J. Wysocki
2012-12-20  1:55           ` [PATCH 11/16] ACPI: Replace ACPI device add_type field with a match_driver flag Rafael J. Wysocki
2012-12-20  1:56           ` [PATCH 12/16] ACPI: Make acpi_bus_scan() and acpi_bus_add() take only one argument Rafael J. Wysocki
2012-12-20  1:57           ` [PATCH 13/16] ACPI: Add .setup() and .cleanup() callbacks to struct acpi_bus_type Rafael J. Wysocki
2012-12-20  1:58           ` [PATCH 14/16] ACPI / PCI: Rework the setup and cleanup of device wakeup Rafael J. Wysocki
2012-12-20  1:59           ` [PATCH 15/16] ACPI / PCI: Move the _PRT setup and cleanup code to pci-acpi.c Rafael J. Wysocki
2012-12-20  2:06           ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Yinghai Lu
2012-12-21  0:09             ` Rafael J. Wysocki
2012-12-21  3:59               ` Yinghai Lu
2012-12-21 22:23                 ` Rafael J. Wysocki
2012-12-20 21:07           ` Toshi Kani
2012-12-20 23:20             ` Rafael J. Wysocki
2012-12-13 22:18   ` [PATCH rev.2 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
2012-12-13 22:21   ` [PATCH rev.2 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
2012-12-13 22:21   ` [PATCH rev.2 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki
2012-12-13 22:22   ` [PATCH rev.2 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
2012-12-13 22:23   ` [PATCH rev.2 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
2012-12-14  9:56   ` [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang
2012-12-14 22:59     ` Rafael J. Wysocki

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='CAErSpo7=2WUbNgtFHT6Sm6h6OKfXkSH99qSoD0n73Tga0=XpTA@mail.gmail.com' \
    --to=bhelgaas@google.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=myron.stowe@redhat.com \
    --cc=rjw@sisk.pl \
    --cc=toshi.kani@hp.com \
    --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).