linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC] ACPI scan handlers
@ 2013-01-24  0:26 Rafael J. Wysocki
  2013-01-25 16:52 ` Toshi Kani
                   ` (2 more replies)
  0 siblings, 3 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-24  0:26 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

Hi All,

There is a considerable amount of confusion in the ACPI subsystem about what
ACPI drivers are used for.  Namely, some of them are used as "normal" device
drivers that bind to devices and handle them using ACPI control methods (like
the fan or battery drivers), but some of them are just used for handling
namespace events, such as the creation or removal of device nodes (I guess it
would be fair to call that an abuse of the driver core).  These two roles are
quite distinct, which is particularly visible from the confusion about the role
of the .remove() callback.

For the "normal" drivers this callback is simply used to handle situations in
which the driver needs to be unbound from the device, because one of them
(either the device or the driver) is going away.  That operation can't really
fail, it just needs to do the necessary cleanup.

However, for the namespace events handling "drivers" .remove() means that not
only the device node in question, but generally also the whole subtree below it
needs to be prepared for removal, which may involve deleting multiple device
objects belonging to different bus types and so on and which very well may fail
(for example, those devices may be used for such things like swap or they may be
memory banks used by the kernel and it may not be safe to remove them at the
moment etc.).  Moreover, for these things the removal of the "driver" doesn't
really make sense, because it has to be there to handle the namespace events it
is designed to handle or else things will go remarkably awry in some places.

To resolve all that mess I'd like to do the following, which in part is inspired
by the recent Toshi Kani's hotplug framework proposal and in part is based on
some discussions I had with Bjorn and others (the code references made below are
based on the current contens of linux-pm.git/linux-next).

1) Introduce a special data type for "ACPI namespace event handlers" like:

struct acpi_scan_handler {
	const struct acpi_device_id *ids;
	struct list_head list_node;
	int (*attach)(struct acpi_device *adev);
	int (*untie)(struct acpi_device *adev);
	int (*reclaim)(struct acpi_device *adev);
	void (*detach)(struct acpi_device *adev);
};

  an additional ACPI device flag:

struct acpi_device_flags {
...
	u32 untied:1;
...
};

  and an additioanl field in struc acpi_device:

struct acpi_device {
...
	struct acpi_scan_handler *scan_handler;
...
};

  (the roles of these things are described below).

2) Introduce a list of struct acpi_scan_handler objects within the ACPI
   subsystem such that acpi_bus_device_attach() will search that list first and
   if there's a matching object (one whose ids match the device node), it will
   run that object's .attach() callback.

  If that returns 1, it will mean that the handler has claimed the device node
  and is now responsible for it until its .detach() callback is run.  Thus no
  driver can be bound to that device node and no other handler can claim it.
  Then, the device node's scan_handler field will be set to point to the handler
  that's claimed it and its untied flag will be cleared.

  If .attach() returns 0, it will mean that the handler has not recognized the
  device node and some other scan handlers and/or drivers may be tried for it.

  If an error code is returned, it will mean a hard error in which case the
  scanning of the namespace will have to be aborted.

  This way ACPI drivers will only be bound to device nodes that haven't been
  claimed by any scan handlers.

3) Introduce an additional function following the format of acpi_bus_trim(),
   say acpi_bus_untie(), that will walk the namespace starting at the given
   device node and execute the .untie() callbacks from the scan handlers of
   all devices as post-order callbacks.

   If the .untie() callback for the given device node returns 0, it will mean
   that it is now safe to delete that node as long as its scan handler's
   .detach() callback is executed before the deletion.  In that case, the device
   node's untied flag will be set.

   Otherwise (i.e. if an error code is returned), it will mean that the scan
   handler has vetoed the untying and the whole operation should be reversed.
   Then, acpi_bus_untie() will walk the namespace again and execute the
   .reclaim() callbacks from the scan handlers of the device nodes whose untied
   flags are set as pre-order callbacks.

   If .reclaim() returns 0, the device node's untied flag will be cleared, and
   if an error code is returned, it will remain set.

   This will allow us to prepare the subtree below the given device node for
   removal in a reversible way, if needed.  Still, though, it will be possible
   to carry out a forcible removal calling acpi_bus_trim() after
   acpi_bus_untie() even if that has returned an error code (or even
   acpi_bus_trim() without acpi_bus_untie()).

4) Make acpi_bus_device_detach() execute the .detach() callback from the
   scan handler of the device node (if the scan handler is present) and clear
   its scan_handler field along with its untied flag.  However, the untied flags
   will only be cleared after executing the .detach() callbacks, so that those
   callbacks can see whether or not the scan handlers have been successfully
   "untied" from the device nodes.

5) Make acpi_bus_hot_remove_device() (and other pieces of code where that is
   convenient) call acpi_bus_untie() before acpi_bus_trim() and bail out
   cleanly if the untying fails (i.e. is vetoed by one of the scan handlers).

That should take care of the removal problem nicely and as far as I can say
the majority of the ACPI drivers used only for handling namespace events can
be readily converted to struct acpi_scan_handler objects.

I wonder if anyone is seeing any major problems with this at the high level.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [RFC] ACPI scan handlers
  2013-01-24  0:26 [RFC] ACPI scan handlers Rafael J. Wysocki
@ 2013-01-25 16:52 ` Toshi Kani
  2013-01-25 22:11   ` Rafael J. Wysocki
  2013-01-26 18:42 ` Jiang Liu
  2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
  2 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-01-25 16:52 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Thu, 2013-01-24 at 01:26 +0100, Rafael J. Wysocki wrote:
> Hi All,
> 
> There is a considerable amount of confusion in the ACPI subsystem about what
> ACPI drivers are used for.  Namely, some of them are used as "normal" device
> drivers that bind to devices and handle them using ACPI control methods (like
> the fan or battery drivers), but some of them are just used for handling
> namespace events, such as the creation or removal of device nodes (I guess it
> would be fair to call that an abuse of the driver core).  These two roles are
> quite distinct, which is particularly visible from the confusion about the role
> of the .remove() callback.
> 
> For the "normal" drivers this callback is simply used to handle situations in
> which the driver needs to be unbound from the device, because one of them
> (either the device or the driver) is going away.  That operation can't really
> fail, it just needs to do the necessary cleanup.
> 
> However, for the namespace events handling "drivers" .remove() means that not
> only the device node in question, but generally also the whole subtree below it
> needs to be prepared for removal, which may involve deleting multiple device
> objects belonging to different bus types and so on and which very well may fail
> (for example, those devices may be used for such things like swap or they may be
> memory banks used by the kernel and it may not be safe to remove them at the
> moment etc.).  Moreover, for these things the removal of the "driver" doesn't
> really make sense, because it has to be there to handle the namespace events it
> is designed to handle or else things will go remarkably awry in some places.
> 
> To resolve all that mess I'd like to do the following, which in part is inspired
> by the recent Toshi Kani's hotplug framework proposal and in part is based on
> some discussions I had with Bjorn and others (the code references made below are
> based on the current contens of linux-pm.git/linux-next).
> 
> 1) Introduce a special data type for "ACPI namespace event handlers" like:
> 
> struct acpi_scan_handler {
> 	const struct acpi_device_id *ids;
> 	struct list_head list_node;
> 	int (*attach)(struct acpi_device *adev);
> 	int (*untie)(struct acpi_device *adev);
> 	int (*reclaim)(struct acpi_device *adev);
> 	void (*detach)(struct acpi_device *adev);
> };
> 
>   an additional ACPI device flag:
> 
> struct acpi_device_flags {
> ...
> 	u32 untied:1;
> ...
> };
> 
>   and an additioanl field in struc acpi_device:
> 
> struct acpi_device {
> ...
> 	struct acpi_scan_handler *scan_handler;
> ...
> };
> 
>   (the roles of these things are described below).
> 
> 2) Introduce a list of struct acpi_scan_handler objects within the ACPI
>    subsystem such that acpi_bus_device_attach() will search that list first and
>    if there's a matching object (one whose ids match the device node), it will
>    run that object's .attach() callback.
> 
>   If that returns 1, it will mean that the handler has claimed the device node
>   and is now responsible for it until its .detach() callback is run.  Thus no
>   driver can be bound to that device node and no other handler can claim it.
>   Then, the device node's scan_handler field will be set to point to the handler
>   that's claimed it and its untied flag will be cleared.
> 
>   If .attach() returns 0, it will mean that the handler has not recognized the
>   device node and some other scan handlers and/or drivers may be tried for it.
> 
>   If an error code is returned, it will mean a hard error in which case the
>   scanning of the namespace will have to be aborted.
> 
>   This way ACPI drivers will only be bound to device nodes that haven't been
>   claimed by any scan handlers.
> 
> 3) Introduce an additional function following the format of acpi_bus_trim(),
>    say acpi_bus_untie(), that will walk the namespace starting at the given
>    device node and execute the .untie() callbacks from the scan handlers of
>    all devices as post-order callbacks.
> 
>    If the .untie() callback for the given device node returns 0, it will mean
>    that it is now safe to delete that node as long as its scan handler's
>    .detach() callback is executed before the deletion.  In that case, the device
>    node's untied flag will be set.
> 
>    Otherwise (i.e. if an error code is returned), it will mean that the scan
>    handler has vetoed the untying and the whole operation should be reversed.
>    Then, acpi_bus_untie() will walk the namespace again and execute the
>    .reclaim() callbacks from the scan handlers of the device nodes whose untied
>    flags are set as pre-order callbacks.
> 
>    If .reclaim() returns 0, the device node's untied flag will be cleared, and
>    if an error code is returned, it will remain set.
> 
>    This will allow us to prepare the subtree below the given device node for
>    removal in a reversible way, if needed.  Still, though, it will be possible
>    to carry out a forcible removal calling acpi_bus_trim() after
>    acpi_bus_untie() even if that has returned an error code (or even
>    acpi_bus_trim() without acpi_bus_untie()).
> 
> 4) Make acpi_bus_device_detach() execute the .detach() callback from the
>    scan handler of the device node (if the scan handler is present) and clear
>    its scan_handler field along with its untied flag.  However, the untied flags
>    will only be cleared after executing the .detach() callbacks, so that those
>    callbacks can see whether or not the scan handlers have been successfully
>    "untied" from the device nodes.
> 
> 5) Make acpi_bus_hot_remove_device() (and other pieces of code where that is
>    convenient) call acpi_bus_untie() before acpi_bus_trim() and bail out
>    cleanly if the untying fails (i.e. is vetoed by one of the scan handlers).
> 
> That should take care of the removal problem nicely and as far as I can say
> the majority of the ACPI drivers used only for handling namespace events can
> be readily converted to struct acpi_scan_handler objects.
> 
> I wonder if anyone is seeing any major problems with this at the high level.

I agree that the current model is mess.  As shown below, it requires
that .add() at boot-time only performs acpi dev init, and .add() at
hot-add needs both acpi dev init and device on-lining.  It then
requires .remove() to perform both off-lining and acpi dev
delete.  .remove() must succeed, but off-lining can fail.  

 acpi dev   online
|========|=========|

   add @ boot
-------->
   add @ hot-add
------------------>
<------------------
     remove

Your proposal seems to introduce the following new model.  If so, I do
not think it addresses all the issues.  .attach() still needs to behave
differently between boot and hot-add.  The model is also asymmetric
since the destructor of .attach() at hot-add is the combination
of .detach() and .untie().
.
 attach @ boot
-------->
 attach @ hot-add
----------------->
 detach    untie
<-------<---------
        --------->
           reclaim

I believe device on-lining and off-lining steps should not be performed
in .add() and .remove().  With this clarification, the current .add()
& .remove() model works fine as follows.  That is, .add() only performs
acpi dev init, and .remove() only perform acpi dev delete (which is same
as your .detach()).  My system device hot-plug framework is designed to
work with this model.

   add
-------->
<--------
  remove


Thanks,
-Toshi







^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [RFC] ACPI scan handlers
  2013-01-25 16:52 ` Toshi Kani
@ 2013-01-25 22:11   ` Rafael J. Wysocki
  2013-01-25 23:07     ` Toshi Kani
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-25 22:11 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Friday, January 25, 2013 09:52:21 AM Toshi Kani wrote:
> On Thu, 2013-01-24 at 01:26 +0100, Rafael J. Wysocki wrote:
> > Hi All,
> > 
> > There is a considerable amount of confusion in the ACPI subsystem about what
> > ACPI drivers are used for.  Namely, some of them are used as "normal" device
> > drivers that bind to devices and handle them using ACPI control methods (like
> > the fan or battery drivers), but some of them are just used for handling
> > namespace events, such as the creation or removal of device nodes (I guess it
> > would be fair to call that an abuse of the driver core).  These two roles are
> > quite distinct, which is particularly visible from the confusion about the role
> > of the .remove() callback.
> > 
> > For the "normal" drivers this callback is simply used to handle situations in
> > which the driver needs to be unbound from the device, because one of them
> > (either the device or the driver) is going away.  That operation can't really
> > fail, it just needs to do the necessary cleanup.
> > 
> > However, for the namespace events handling "drivers" .remove() means that not
> > only the device node in question, but generally also the whole subtree below it
> > needs to be prepared for removal, which may involve deleting multiple device
> > objects belonging to different bus types and so on and which very well may fail
> > (for example, those devices may be used for such things like swap or they may be
> > memory banks used by the kernel and it may not be safe to remove them at the
> > moment etc.).  Moreover, for these things the removal of the "driver" doesn't
> > really make sense, because it has to be there to handle the namespace events it
> > is designed to handle or else things will go remarkably awry in some places.
> > 
> > To resolve all that mess I'd like to do the following, which in part is inspired
> > by the recent Toshi Kani's hotplug framework proposal and in part is based on
> > some discussions I had with Bjorn and others (the code references made below are
> > based on the current contens of linux-pm.git/linux-next).
> > 
> > 1) Introduce a special data type for "ACPI namespace event handlers" like:
> > 
> > struct acpi_scan_handler {
> > 	const struct acpi_device_id *ids;
> > 	struct list_head list_node;
> > 	int (*attach)(struct acpi_device *adev);
> > 	int (*untie)(struct acpi_device *adev);
> > 	int (*reclaim)(struct acpi_device *adev);
> > 	void (*detach)(struct acpi_device *adev);
> > };
> > 
> >   an additional ACPI device flag:
> > 
> > struct acpi_device_flags {
> > ...
> > 	u32 untied:1;
> > ...
> > };
> > 
> >   and an additioanl field in struc acpi_device:
> > 
> > struct acpi_device {
> > ...
> > 	struct acpi_scan_handler *scan_handler;
> > ...
> > };
> > 
> >   (the roles of these things are described below).
> > 
> > 2) Introduce a list of struct acpi_scan_handler objects within the ACPI
> >    subsystem such that acpi_bus_device_attach() will search that list first and
> >    if there's a matching object (one whose ids match the device node), it will
> >    run that object's .attach() callback.
> > 
> >   If that returns 1, it will mean that the handler has claimed the device node
> >   and is now responsible for it until its .detach() callback is run.  Thus no
> >   driver can be bound to that device node and no other handler can claim it.
> >   Then, the device node's scan_handler field will be set to point to the handler
> >   that's claimed it and its untied flag will be cleared.
> > 
> >   If .attach() returns 0, it will mean that the handler has not recognized the
> >   device node and some other scan handlers and/or drivers may be tried for it.
> > 
> >   If an error code is returned, it will mean a hard error in which case the
> >   scanning of the namespace will have to be aborted.
> > 
> >   This way ACPI drivers will only be bound to device nodes that haven't been
> >   claimed by any scan handlers.
> > 
> > 3) Introduce an additional function following the format of acpi_bus_trim(),
> >    say acpi_bus_untie(), that will walk the namespace starting at the given
> >    device node and execute the .untie() callbacks from the scan handlers of
> >    all devices as post-order callbacks.
> > 
> >    If the .untie() callback for the given device node returns 0, it will mean
> >    that it is now safe to delete that node as long as its scan handler's
> >    .detach() callback is executed before the deletion.  In that case, the device
> >    node's untied flag will be set.
> > 
> >    Otherwise (i.e. if an error code is returned), it will mean that the scan
> >    handler has vetoed the untying and the whole operation should be reversed.
> >    Then, acpi_bus_untie() will walk the namespace again and execute the
> >    .reclaim() callbacks from the scan handlers of the device nodes whose untied
> >    flags are set as pre-order callbacks.
> > 
> >    If .reclaim() returns 0, the device node's untied flag will be cleared, and
> >    if an error code is returned, it will remain set.
> > 
> >    This will allow us to prepare the subtree below the given device node for
> >    removal in a reversible way, if needed.  Still, though, it will be possible
> >    to carry out a forcible removal calling acpi_bus_trim() after
> >    acpi_bus_untie() even if that has returned an error code (or even
> >    acpi_bus_trim() without acpi_bus_untie()).
> > 
> > 4) Make acpi_bus_device_detach() execute the .detach() callback from the
> >    scan handler of the device node (if the scan handler is present) and clear
> >    its scan_handler field along with its untied flag.  However, the untied flags
> >    will only be cleared after executing the .detach() callbacks, so that those
> >    callbacks can see whether or not the scan handlers have been successfully
> >    "untied" from the device nodes.
> > 
> > 5) Make acpi_bus_hot_remove_device() (and other pieces of code where that is
> >    convenient) call acpi_bus_untie() before acpi_bus_trim() and bail out
> >    cleanly if the untying fails (i.e. is vetoed by one of the scan handlers).
> > 
> > That should take care of the removal problem nicely and as far as I can say
> > the majority of the ACPI drivers used only for handling namespace events can
> > be readily converted to struct acpi_scan_handler objects.
> > 
> > I wonder if anyone is seeing any major problems with this at the high level.

First of all, thanks for the response. :-)

> I agree that the current model is mess.  As shown below, it requires
> that .add() at boot-time only performs acpi dev init, and .add() at
> hot-add needs both acpi dev init and device on-lining.

I'm not sure what you're talking about, though.

You seem to be confusing ACPI device nodes (i.e. things represented by struct
acpi_device objects) with devices, but they are different things.  They are
just used to store static information extracted from device objects in the
ACPI namespace and to expose those objects (and possibly some of their
properties) via sysfs.  Device objects in the ACPI namespace are not devices,
however, and they don't even need to represent devices (for example, the
_SB thing, which is represented by struct acpi_device, is hardly a device).

So the role of struct acpi_device things is analogous to the role of
struct device_node things in the Device Trees world.  In fact, no drivers
should ever bind to them and in my opinion it was a grievous mistake to
let them do that.  But I'm digressing.

So, when you're saying "acpi dev", I'm not sure if you think about a device node
or a device (possibly) represented by that node.  If you mean device node, then
I'm not sure what "acpi dev init" means, because device nodes by definition
don't require any initialization beyond what acpi_add_single_object() does
(and they don't require any off-lining beyod what acpi_device_unregister()
does, for that matter).  In turn, if you mean "device represented by the given
device node", then you can't even say "ACPI device" about it, because it very
well may be a PCI device, or a USB device, or a SATA device etc.

That's part of the whole confusion, by the way.

If the device represented by an ACPI device node is on a natively enumerated
bus, like PCI, then its native bus' init code initializes the device and
creates a "physical" device object for it, like struct pci_dev, which is then
"glued" to the corresponding struct acpi_device by acpi_bind_one().  Then, it
is clear which is which and there's no confusion.  The confusion starts when
there's no native enumeration and we only have the struct acpi_device thing,
because then everybody seems to think "oh, there's no physical device object
now, so this must be something different", but the *only* difference is that
there is no native bus' init code now and we should still be creating a
"physical device" object for the device and we should "glue" it to the
existing struct acpi_device like in the natively enumerated case.

> It then requires .remove() to perform both off-lining and acpi dev
> delete.  .remove() must succeed, but off-lining can fail.  
>
>  acpi dev   online
> |========|=========|
> 
>    add @ boot
> -------->
>    add @ hot-add
> ------------------>
> <------------------
>      remove

That assumes that the "driver" is present during boot (i.e. when acpi_bus_scan()
is run for the first time), but what if it is not?

> Your proposal seems to introduce the following new model.  If so, I do
> not think it addresses all the issues.

It is not supposed to address *all* issues (whatever "all" means).  It is meant
to address precisely *one* problem, which is the abuse of the driver core by
the ACPI subsystem (please see below).

> .attach() still needs to behave differently between boot and hot-add.

Why does it?  I don't see any reason for that.

> The model is also asymmetric since the destructor of .attach() at hot-add
> is the combination of .detach() and .untie().
> .
>  attach @ boot
> -------->
>  attach @ hot-add
> ----------------->
>  detach    untie
> <-------<---------
>         --------->
>            reclaim
> 
> I believe device on-lining and off-lining steps should not be performed
> in .add() and .remove().  With this clarification, the current .add()
> & .remove() model works fine as follows.  That is, .add() only performs
> acpi dev init, and .remove() only perform acpi dev delete (which is same
> as your .detach()).  My system device hot-plug framework is designed to
> work with this model.

Well, if I understand the above correctly, you're basically saying that if we
add a layer on top of the ACPI subsystem, we can separate "online" from "add"
and "offline" from "remove" in such a way that the "add" and "remove" will be
handled by the ACPI subsystem and "online" and "offline" will be done by the
extra layer.

That quite precisely is what we should be doing, but the "add" operation should
include the creation of a "physical device" object, like for example struct
platform_device, and the additional layer should be a proper driver (a platform
driver for example) that will bind to that "physical device" object and
initialize the device (i.e. hardware).

Analogously, the "remove" operation should include the removal of the "physical
device" object from which the driver will have to be unbound first.

That I believe is what Greg meant when he was discussing your earlier proposal
with you.

Now, however, the problem is what kind of a device object we should create
during the "add" phase (struct platform_device may not be suitable in some
cases) and whether that needs to be a single object or a whole bunch of them
(e.g. when the given struct acpi_device represents a bus or bridge, like in the
PCI host bridge case).  That's what the ACPI scan handlers I'm proposing are
for.

So, an ACPI scan handler's .attach() is supposed to recognize what kind of
hardware is there to handle and to create whatever device objects (based on
struct device) are there to create etc.  Then, there should be drivers that
will bind to those objects and so on.  .detach(), in turn, is supposed to
reverse whatever .attach() has done.  There is an additional complication,
though, that there may be an eject request between .attach() and .detach()
and it needs to be responded to.

This really is about responding to three types of events related to the ACPI
namespace.  Those events are, essentially:

(1) Device node (i.e. struct acpi_device) has been registered.
(2) Eject has been requested for a device node.
(3) Device node goes away (i.e. it is going to be unregistered).

Whatever the "model", we have to respond to the above events, this way or
another.

Of course, (2) need not be the same as (3) in general, because one may envision
a refusal to carry out the eject.  Currently, though, there is no distinction
between (2) and (3).

The purpose of ACPI scan handlers I'm proposing is precisely to handle these
three types of events without abusing the driver core.  How exactly they are
going to be handled will depend on the implementation of those handlers.

The idea is that .attach(), .untie(), and .detach() will be called to handle
(1), (2), and (3), respectively, with the additional twist that after an eject
refusal .reclaim() needs to be called to do the cleanup.

Well, perhaps the names .untie() and .reclaim() are not the best ones and it's
better to use names like .eject_requested() and .eject_refused() explicitly
for those callbacks?  And analogously for the flag indicating that
.eject_requested() has succeeded for the given device?

So, this is not about creating any new "model", it's just about doing what
needs to be done in a possibly straightforward way.

Now, perhaps I should just post some code so that it's more clear what I mean. :-)

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [RFC] ACPI scan handlers
  2013-01-25 22:11   ` Rafael J. Wysocki
@ 2013-01-25 23:07     ` Toshi Kani
  2013-01-26  1:49       ` Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-01-25 23:07 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Fri, 2013-01-25 at 23:11 +0100, Rafael J. Wysocki wrote:
> On Friday, January 25, 2013 09:52:21 AM Toshi Kani wrote:
> > On Thu, 2013-01-24 at 01:26 +0100, Rafael J. Wysocki wrote:
 :
> > > 
> > > I wonder if anyone is seeing any major problems with this at the high level.
> 
> First of all, thanks for the response. :-)
> 
> > I agree that the current model is mess.  As shown below, it requires
> > that .add() at boot-time only performs acpi dev init, and .add() at
> > hot-add needs both acpi dev init and device on-lining.
> 
> I'm not sure what you're talking about, though.
> 
> You seem to be confusing ACPI device nodes (i.e. things represented by struct
> acpi_device objects) with devices, but they are different things.  They are
> just used to store static information extracted from device objects in the
> ACPI namespace and to expose those objects (and possibly some of their
> properties) via sysfs.  Device objects in the ACPI namespace are not devices,
> however, and they don't even need to represent devices (for example, the
> _SB thing, which is represented by struct acpi_device, is hardly a device).
> 
> So the role of struct acpi_device things is analogous to the role of
> struct device_node things in the Device Trees world.  In fact, no drivers
> should ever bind to them and in my opinion it was a grievous mistake to
> let them do that.  But I'm digressing.
> 
> So, when you're saying "acpi dev", I'm not sure if you think about a device node
> or a device (possibly) represented by that node.  If you mean device node, then
> I'm not sure what "acpi dev init" means, because device nodes by definition
> don't require any initialization beyond what acpi_add_single_object() does
> (and they don't require any off-lining beyod what acpi_device_unregister()
> does, for that matter).  In turn, if you mean "device represented by the given
> device node", then you can't even say "ACPI device" about it, because it very
> well may be a PCI device, or a USB device, or a SATA device etc.

Let me clarify my point with the ACPI memory driver as an example since
it is the one that has caused a problem in .remove().

acpi_memory_device_add() implements .add() and does two things below.

 1. Call _CRS and initialize a list of struct acpi_memory_info that is
attached to acpi_device->driver_data.  This step is what I described as
"acpi dev init".  ACPI drivers perform driver-specific initialization to
ACPI device objects.

 2. Call add_memory() to add a target memory range to the mm module.
This step is what I described as "on-lining".  This step is not
necessary at boot-time since the mm module has already on-lined the
memory ranges at early boot-time.  At hot-add, however, it needs to call
add_memory() with the current framework.

Similarly, acpi_memory_device_remove() implements .remove() and does two
things below.

 1. Call remove_memory() to offline a target memory range.  This step,
"off-lining", can fail since the mm module may or may not be able to
delete non-movable ranges.  This failure cannot be handled properly and
causes the system to crash at this point.

 2. Free up the list of struct acpi_memory_info.  This step deletes
driver-specific data from an ACPI device object.


> That's part of the whole confusion, by the way.
> 
> If the device represented by an ACPI device node is on a natively enumerated
> bus, like PCI, then its native bus' init code initializes the device and
> creates a "physical" device object for it, like struct pci_dev, which is then
> "glued" to the corresponding struct acpi_device by acpi_bind_one().  Then, it
> is clear which is which and there's no confusion.  The confusion starts when
> there's no native enumeration and we only have the struct acpi_device thing,
> because then everybody seems to think "oh, there's no physical device object
> now, so this must be something different", but the *only* difference is that
> there is no native bus' init code now and we should still be creating a
> "physical device" object for the device and we should "glue" it to the
> existing struct acpi_device like in the natively enumerated case.
> 
> > It then requires .remove() to perform both off-lining and acpi dev
> > delete.  .remove() must succeed, but off-lining can fail.  
> >
> >  acpi dev   online
> > |========|=========|
> > 
> >    add @ boot
> > -------->
> >    add @ hot-add
> > ------------------>
> > <------------------
> >      remove
> 
> That assumes that the "driver" is present during boot (i.e. when acpi_bus_scan()
> is run for the first time), but what if it is not?

With memory's example, the mm module must be present at boot.  The
system does not boot without it.

> > Your proposal seems to introduce the following new model.  If so, I do
> > not think it addresses all the issues.
> 
> It is not supposed to address *all* issues (whatever "all" means).  It is meant
> to address precisely *one* problem, which is the abuse of the driver core by
> the ACPI subsystem (please see below).
> 
> > .attach() still needs to behave differently between boot and hot-add.
> 
> Why does it?  I don't see any reason for that.

With memory's example, calling add_memory() at boot is not necessary
(which just fails and this failure cannot cause an error), but is
necessary at hot-add (which should succeed in this case). 

> > The model is also asymmetric since the destructor of .attach() at hot-add
> > is the combination of .detach() and .untie().
> > .
> >  attach @ boot
> > -------->
> >  attach @ hot-add
> > ----------------->
> >  detach    untie
> > <-------<---------
> >         --------->
> >            reclaim
> > 
> > I believe device on-lining and off-lining steps should not be performed
> > in .add() and .remove().  With this clarification, the current .add()
> > & .remove() model works fine as follows.  That is, .add() only performs
> > acpi dev init, and .remove() only perform acpi dev delete (which is same
> > as your .detach()).  My system device hot-plug framework is designed to
> > work with this model.
> 
> Well, if I understand the above correctly, you're basically saying that if we
> add a layer on top of the ACPI subsystem, we can separate "online" from "add"
> and "offline" from "remove" in such a way that the "add" and "remove" will be
> handled by the ACPI subsystem and "online" and "offline" will be done by the
> extra layer.

Right.  In memory's example, the "online" part should be done by the mm
module itself.

> That quite precisely is what we should be doing, but the "add" operation should
> include the creation of a "physical device" object, like for example struct
> platform_device, and the additional layer should be a proper driver (a platform
> driver for example) that will bind to that "physical device" object and
> initialize the device (i.e. hardware).
>
> Analogously, the "remove" operation should include the removal of the "physical
> device" object from which the driver will have to be unbound first.

Agreed.  With memory's example, the "remove" is also required to do
"off-lining" (i.e. call remove_memory), which should not be the role of
ACPI driver.

> That I believe is what Greg meant when he was discussing your earlier proposal
> with you.
> 
> Now, however, the problem is what kind of a device object we should create
> during the "add" phase (struct platform_device may not be suitable in some
> cases) and whether that needs to be a single object or a whole bunch of them
> (e.g. when the given struct acpi_device represents a bus or bridge, like in the
> PCI host bridge case).  That's what the ACPI scan handlers I'm proposing are
> for.

OK, so, we are thinking of different issues... :-)

> So, an ACPI scan handler's .attach() is supposed to recognize what kind of
> hardware is there to handle and to create whatever device objects (based on
> struct device) are there to create etc.  Then, there should be drivers that
> will bind to those objects and so on.  .detach(), in turn, is supposed to
> reverse whatever .attach() has done.  There is an additional complication,
> though, that there may be an eject request between .attach() and .detach()
> and it needs to be responded to.
> 
> This really is about responding to three types of events related to the ACPI
> namespace.  Those events are, essentially:
> 
> (1) Device node (i.e. struct acpi_device) has been registered.
> (2) Eject has been requested for a device node.
> (3) Device node goes away (i.e. it is going to be unregistered).
> 
> Whatever the "model", we have to respond to the above events, this way or
> another.
> 
> Of course, (2) need not be the same as (3) in general, because one may envision
> a refusal to carry out the eject.  Currently, though, there is no distinction
> between (2) and (3).
> 
> The purpose of ACPI scan handlers I'm proposing is precisely to handle these
> three types of events without abusing the driver core.  How exactly they are
> going to be handled will depend on the implementation of those handlers.
> 
> The idea is that .attach(), .untie(), and .detach() will be called to handle
> (1), (2), and (3), respectively, with the additional twist that after an eject
> refusal .reclaim() needs to be called to do the cleanup.
> 
> Well, perhaps the names .untie() and .reclaim() are not the best ones and it's
> better to use names like .eject_requested() and .eject_refused() explicitly
> for those callbacks?  And analogously for the flag indicating that
> .eject_requested() has succeeded for the given device?
> 
> So, this is not about creating any new "model", it's just about doing what
> needs to be done in a possibly straightforward way.
> 
> Now, perhaps I should just post some code so that it's more clear what I mean. :-)

Sounds like I did confuse completely!

Anyway, even we have .untie() or .eject_requested(), I think all the
hot-delete procedure may not be done within this function since an ACPI
driver is not responsible for managing/controlling actual device.


Thanks,
-Toshi



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [RFC] ACPI scan handlers
  2013-01-25 23:07     ` Toshi Kani
@ 2013-01-26  1:49       ` Rafael J. Wysocki
  2013-01-26 14:03         ` Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-26  1:49 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Friday, January 25, 2013 04:07:38 PM Toshi Kani wrote:
> On Fri, 2013-01-25 at 23:11 +0100, Rafael J. Wysocki wrote:
> > On Friday, January 25, 2013 09:52:21 AM Toshi Kani wrote:
> > > On Thu, 2013-01-24 at 01:26 +0100, Rafael J. Wysocki wrote:
>  :
> > > > 
> > > > I wonder if anyone is seeing any major problems with this at the high level.
> > 
> > First of all, thanks for the response. :-)
> > 
> > > I agree that the current model is mess.  As shown below, it requires
> > > that .add() at boot-time only performs acpi dev init, and .add() at
> > > hot-add needs both acpi dev init and device on-lining.
> > 
> > I'm not sure what you're talking about, though.
> > 
> > You seem to be confusing ACPI device nodes (i.e. things represented by struct
> > acpi_device objects) with devices, but they are different things.  They are
> > just used to store static information extracted from device objects in the
> > ACPI namespace and to expose those objects (and possibly some of their
> > properties) via sysfs.  Device objects in the ACPI namespace are not devices,
> > however, and they don't even need to represent devices (for example, the
> > _SB thing, which is represented by struct acpi_device, is hardly a device).
> > 
> > So the role of struct acpi_device things is analogous to the role of
> > struct device_node things in the Device Trees world.  In fact, no drivers
> > should ever bind to them and in my opinion it was a grievous mistake to
> > let them do that.  But I'm digressing.
> > 
> > So, when you're saying "acpi dev", I'm not sure if you think about a device node
> > or a device (possibly) represented by that node.  If you mean device node, then
> > I'm not sure what "acpi dev init" means, because device nodes by definition
> > don't require any initialization beyond what acpi_add_single_object() does
> > (and they don't require any off-lining beyod what acpi_device_unregister()
> > does, for that matter).  In turn, if you mean "device represented by the given
> > device node", then you can't even say "ACPI device" about it, because it very
> > well may be a PCI device, or a USB device, or a SATA device etc.
> 
> Let me clarify my point with the ACPI memory driver as an example since
> it is the one that has caused a problem in .remove().
> 
> acpi_memory_device_add() implements .add() and does two things below.
> 
>  1. Call _CRS and initialize a list of struct acpi_memory_info that is
> attached to acpi_device->driver_data.  This step is what I described as
> "acpi dev init".  ACPI drivers perform driver-specific initialization to
> ACPI device objects.
>
>  2. Call add_memory() to add a target memory range to the mm module.
> This step is what I described as "on-lining".  This step is not
> necessary at boot-time since the mm module has already on-lined the
> memory ranges at early boot-time.  At hot-add, however, it needs to call
> add_memory() with the current framework.

I see.

OK, so that does handle the "struct acpi_device has been registered" event,
both on boot and hot-add.  The interactions with mm are tricky, I agree, but
that's not what I want to address at this point.

> Similarly, acpi_memory_device_remove() implements .remove() and does two
> things below.
> 
>  1. Call remove_memory() to offline a target memory range.  This step,
> "off-lining", can fail since the mm module may or may not be able to
> delete non-movable ranges.  This failure cannot be handled properly and
> causes the system to crash at this point.

Well, if the system administrator wants to crash the system this way, it's
basically up to him.  So that should be done by .detach() anyway in that case.

>  2. Free up the list of struct acpi_memory_info.  This step deletes
> driver-specific data from an ACPI device object.

OK

> > That's part of the whole confusion, by the way.
> > 
> > If the device represented by an ACPI device node is on a natively enumerated
> > bus, like PCI, then its native bus' init code initializes the device and
> > creates a "physical" device object for it, like struct pci_dev, which is then
> > "glued" to the corresponding struct acpi_device by acpi_bind_one().  Then, it
> > is clear which is which and there's no confusion.  The confusion starts when
> > there's no native enumeration and we only have the struct acpi_device thing,
> > because then everybody seems to think "oh, there's no physical device object
> > now, so this must be something different", but the *only* difference is that
> > there is no native bus' init code now and we should still be creating a
> > "physical device" object for the device and we should "glue" it to the
> > existing struct acpi_device like in the natively enumerated case.
> > 
> > > It then requires .remove() to perform both off-lining and acpi dev
> > > delete.  .remove() must succeed, but off-lining can fail.  
> > >
> > >  acpi dev   online
> > > |========|=========|
> > > 
> > >    add @ boot
> > > -------->
> > >    add @ hot-add
> > > ------------------>
> > > <------------------
> > >      remove
> > 
> > That assumes that the "driver" is present during boot (i.e. when acpi_bus_scan()
> > is run for the first time), but what if it is not?
> 
> With memory's example, the mm module must be present at boot.  The
> system does not boot without it.

OK

> > > Your proposal seems to introduce the following new model.  If so, I do
> > > not think it addresses all the issues.
> > 
> > It is not supposed to address *all* issues (whatever "all" means).  It is meant
> > to address precisely *one* problem, which is the abuse of the driver core by
> > the ACPI subsystem (please see below).
> > 
> > > .attach() still needs to behave differently between boot and hot-add.
> > 
> > Why does it?  I don't see any reason for that.
> 
> With memory's example, calling add_memory() at boot is not necessary
> (which just fails and this failure cannot cause an error), but is
> necessary at hot-add (which should succeed in this case). 

But essentially it's not a bug to call add_memory() during boot too, but the
problem seems to be how to distinguish the benign failure when the memory range
has been accounted for already earlier.  I suppose that add_memory() should
return error codes allowing you to tell the difference?

> > > The model is also asymmetric since the destructor of .attach() at hot-add
> > > is the combination of .detach() and .untie().
> > > .
> > >  attach @ boot
> > > -------->
> > >  attach @ hot-add
> > > ----------------->
> > >  detach    untie
> > > <-------<---------
> > >         --------->
> > >            reclaim
> > > 
> > > I believe device on-lining and off-lining steps should not be performed
> > > in .add() and .remove().  With this clarification, the current .add()
> > > & .remove() model works fine as follows.  That is, .add() only performs
> > > acpi dev init, and .remove() only perform acpi dev delete (which is same
> > > as your .detach()).  My system device hot-plug framework is designed to
> > > work with this model.
> > 
> > Well, if I understand the above correctly, you're basically saying that if we
> > add a layer on top of the ACPI subsystem, we can separate "online" from "add"
> > and "offline" from "remove" in such a way that the "add" and "remove" will be
> > handled by the ACPI subsystem and "online" and "offline" will be done by the
> > extra layer.
> 
> Right.  In memory's example, the "online" part should be done by the mm
> module itself.

That still would be tricky, but I believe it is specific to the memory case,
because memory ranges don't need any special enumeration to happen to be seen
by the early boot code.  The result of that is that the memory subsystem
doesn't know whether or not the given range is removable upfront.  However, we
find that out from the ACPI namespace scan and we should be able to tell the
memory subsystem "this range is removable" somehow.  So instead of add_memory()
there should be something like add_removable_memory_range() that would succeed
if the memory range has already been found.  In that case it should just cause
the memory subsystem to record the fact that the given range has the capability
of being removed, which indeed may be good to know to it.

> > That quite precisely is what we should be doing, but the "add" operation should
> > include the creation of a "physical device" object, like for example struct
> > platform_device, and the additional layer should be a proper driver (a platform
> > driver for example) that will bind to that "physical device" object and
> > initialize the device (i.e. hardware).
> >
> > Analogously, the "remove" operation should include the removal of the "physical
> > device" object from which the driver will have to be unbound first.
> 
> Agreed.  With memory's example, the "remove" is also required to do
> "off-lining" (i.e. call remove_memory), which should not be the role of
> ACPI driver.

Well, it kind of has to be initiated by the ACPI subsystem, because that's
where the event happens.  And I'm not talking about the event that the BIOS
signals, but an event that may happen as a result of an eject event from the
BIOS for *another* device node upper in the hierarchy (e.g. a processor
package).

> > That I believe is what Greg meant when he was discussing your earlier proposal
> > with you.
> > 
> > Now, however, the problem is what kind of a device object we should create
> > during the "add" phase (struct platform_device may not be suitable in some
> > cases) and whether that needs to be a single object or a whole bunch of them
> > (e.g. when the given struct acpi_device represents a bus or bridge, like in the
> > PCI host bridge case).  That's what the ACPI scan handlers I'm proposing are
> > for.
> 
> OK, so, we are thinking of different issues... :-)
> 
> > So, an ACPI scan handler's .attach() is supposed to recognize what kind of
> > hardware is there to handle and to create whatever device objects (based on
> > struct device) are there to create etc.  Then, there should be drivers that
> > will bind to those objects and so on.  .detach(), in turn, is supposed to
> > reverse whatever .attach() has done.  There is an additional complication,
> > though, that there may be an eject request between .attach() and .detach()
> > and it needs to be responded to.
> > 
> > This really is about responding to three types of events related to the ACPI
> > namespace.  Those events are, essentially:
> > 
> > (1) Device node (i.e. struct acpi_device) has been registered.
> > (2) Eject has been requested for a device node.
> > (3) Device node goes away (i.e. it is going to be unregistered).
> > 
> > Whatever the "model", we have to respond to the above events, this way or
> > another.
> > 
> > Of course, (2) need not be the same as (3) in general, because one may envision
> > a refusal to carry out the eject.  Currently, though, there is no distinction
> > between (2) and (3).
> > 
> > The purpose of ACPI scan handlers I'm proposing is precisely to handle these
> > three types of events without abusing the driver core.  How exactly they are
> > going to be handled will depend on the implementation of those handlers.
> > 
> > The idea is that .attach(), .untie(), and .detach() will be called to handle
> > (1), (2), and (3), respectively, with the additional twist that after an eject
> > refusal .reclaim() needs to be called to do the cleanup.
> > 
> > Well, perhaps the names .untie() and .reclaim() are not the best ones and it's
> > better to use names like .eject_requested() and .eject_refused() explicitly
> > for those callbacks?  And analogously for the flag indicating that
> > .eject_requested() has succeeded for the given device?
> > 
> > So, this is not about creating any new "model", it's just about doing what
> > needs to be done in a possibly straightforward way.
> > 
> > Now, perhaps I should just post some code so that it's more clear what I mean. :-)
> 
> Sounds like I did confuse completely!
> 
> Anyway, even we have .untie() or .eject_requested(), I think all the
> hot-delete procedure may not be done within this function since an ACPI
> driver is not responsible for managing/controlling actual device.

No, it is not, but it may propagate the event to the code that is responsible
for that.

The problem is that sometimes the only way we learn that there's a request to
remove certain device is through the ACPI namespace.  Suppose that there is
device object CONT in the namespace and there's another device object MEMR
that is a direct child of CONT.  We have struct acpi_device objects for both.

Now, say that we have an eject request for CONT.  Obviously, we are supposed to
remove both struct acpi_device objects for CONT and MEMR, but we don't know
if the removal of MEMR is safe.  To address this we need to ask the code that
handles the device represented by MEMR if removing it will be safe.  That's
what .eject_requested() is supposed to be for.

So the idea is that when the BIOS signals "eject" for CONT, the ACPI subsystem
will call handler->eject_requested() for all struct acpi_device objects below
and including the CONT's one.  That call doesn't actually need to remove
anything, but it is supposed to (a) check if the removal will be safe and (b)
if so, make sure that that doesn't change after it has returned.  If it can't
do both (a) and (b), it should return an error code and that will cause the
ACPI subsystem to fail the eject.

In the case of memory, it may call something like "disable memory" at this
point that will try to move everything out of the memory range and mark it
as "don't use".  That, if successful, will ensure both (a) and (b).  No
physical removal, though, the memory module is still there.

Now suppose that there are two memory modules under CONT in the ACPI namespace,
MEMA and MEMB.  Again, the BIOS signals "eject" for CONT and say that
.eject_requested() calls "disable memory" for MEMA which succeeds and the
same is done for MEMB, but this time "disable memory" fails, so its
.eject_requested() returns an error code.

In that case the ACPI namespace needs to tell the handler of MEMA that the
eject is not going to happen after all, so it may tell the memory subsystem
to re-enable the relevant memory range.  This is the purpose of the
.eject_canceled() (previously .reclaim()) call.  [If the re-enabling fails,
the memory range will be permanently disabled, but we only care so much as it
means that we can just safely remove that memory module going forward at any
time.]

On the other hand, if .eject_requested() for both MEMA and MEMB succeed,
the ACPI subsystem can simply call acpi_bus_trim() for the whole subtree
starting at CONT.  In that case .detach() callbacks will be executed for both
MEMA and MEMB and they will actually do the teardown of everything.

Still, someone sometimes may want to force an eject of CONT, even though
that will crash the system outright.  For this reason, it has to be possible
to do the acpi_bus_trim() for the CONT's subtree directly and that should still
remove everything without failing and that's where the "untied" flag may be
useful (I will call it eject_accepted in future).  Namely, .detach() may
look at it and see whether or not .eject_requested() was called successfully
for its device and decide what to do on this basis.

Thus the .eject_requested()/.eject_canceled() phase is kind of advisory for
situations in which we are allowed to fail an eject request and generally
.detach() is still supposed to be the reverse of .attach().

And again, those are simply events related to the ACPI namespace,
"struct acpi_device has been registered", "eject has been requested for a
struct acpi_device", and "unregister struct acpi_device now" that the ACPI
subsystem needs to react to and possibly propagate them to the upper code
layers (device drivers etc.).

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [RFC] ACPI scan handlers
  2013-01-26  1:49       ` Rafael J. Wysocki
@ 2013-01-26 14:03         ` Rafael J. Wysocki
  0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-26 14:03 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Saturday, January 26, 2013 02:49:30 AM Rafael J. Wysocki wrote:
> On Friday, January 25, 2013 04:07:38 PM Toshi Kani wrote:
> > On Fri, 2013-01-25 at 23:11 +0100, Rafael J. Wysocki wrote:
> > > On Friday, January 25, 2013 09:52:21 AM Toshi Kani wrote:
> > > > On Thu, 2013-01-24 at 01:26 +0100, Rafael J. Wysocki wrote:
> >  :
> > > > > 
> > > > > I wonder if anyone is seeing any major problems with this at the high level.
> > > 
> > > First of all, thanks for the response. :-)
> > > 
> > > > I agree that the current model is mess.  As shown below, it requires
> > > > that .add() at boot-time only performs acpi dev init, and .add() at
> > > > hot-add needs both acpi dev init and device on-lining.
> > > 
> > > I'm not sure what you're talking about, though.
> > > 
> > > You seem to be confusing ACPI device nodes (i.e. things represented by struct
> > > acpi_device objects) with devices, but they are different things.  They are
> > > just used to store static information extracted from device objects in the
> > > ACPI namespace and to expose those objects (and possibly some of their
> > > properties) via sysfs.  Device objects in the ACPI namespace are not devices,
> > > however, and they don't even need to represent devices (for example, the
> > > _SB thing, which is represented by struct acpi_device, is hardly a device).
> > > 
> > > So the role of struct acpi_device things is analogous to the role of
> > > struct device_node things in the Device Trees world.  In fact, no drivers
> > > should ever bind to them and in my opinion it was a grievous mistake to
> > > let them do that.  But I'm digressing.
> > > 
> > > So, when you're saying "acpi dev", I'm not sure if you think about a device node
> > > or a device (possibly) represented by that node.  If you mean device node, then
> > > I'm not sure what "acpi dev init" means, because device nodes by definition
> > > don't require any initialization beyond what acpi_add_single_object() does
> > > (and they don't require any off-lining beyod what acpi_device_unregister()
> > > does, for that matter).  In turn, if you mean "device represented by the given
> > > device node", then you can't even say "ACPI device" about it, because it very
> > > well may be a PCI device, or a USB device, or a SATA device etc.
> > 
> > Let me clarify my point with the ACPI memory driver as an example since
> > it is the one that has caused a problem in .remove().
> > 
> > acpi_memory_device_add() implements .add() and does two things below.
> > 
> >  1. Call _CRS and initialize a list of struct acpi_memory_info that is
> > attached to acpi_device->driver_data.  This step is what I described as
> > "acpi dev init".  ACPI drivers perform driver-specific initialization to
> > ACPI device objects.
> >
> >  2. Call add_memory() to add a target memory range to the mm module.
> > This step is what I described as "on-lining".  This step is not
> > necessary at boot-time since the mm module has already on-lined the
> > memory ranges at early boot-time.  At hot-add, however, it needs to call
> > add_memory() with the current framework.
> 
> I see.
> 
> OK, so that does handle the "struct acpi_device has been registered" event,
> both on boot and hot-add.  The interactions with mm are tricky, I agree, but
> that's not what I want to address at this point.
> 
> > Similarly, acpi_memory_device_remove() implements .remove() and does two
> > things below.
> > 
> >  1. Call remove_memory() to offline a target memory range.  This step,
> > "off-lining", can fail since the mm module may or may not be able to
> > delete non-movable ranges.  This failure cannot be handled properly and
> > causes the system to crash at this point.
> 
> Well, if the system administrator wants to crash the system this way, it's
> basically up to him.  So that should be done by .detach() anyway in that case.
> 
> >  2. Free up the list of struct acpi_memory_info.  This step deletes
> > driver-specific data from an ACPI device object.
> 
> OK
> 
> > > That's part of the whole confusion, by the way.
> > > 
> > > If the device represented by an ACPI device node is on a natively enumerated
> > > bus, like PCI, then its native bus' init code initializes the device and
> > > creates a "physical" device object for it, like struct pci_dev, which is then
> > > "glued" to the corresponding struct acpi_device by acpi_bind_one().  Then, it
> > > is clear which is which and there's no confusion.  The confusion starts when
> > > there's no native enumeration and we only have the struct acpi_device thing,
> > > because then everybody seems to think "oh, there's no physical device object
> > > now, so this must be something different", but the *only* difference is that
> > > there is no native bus' init code now and we should still be creating a
> > > "physical device" object for the device and we should "glue" it to the
> > > existing struct acpi_device like in the natively enumerated case.
> > > 
> > > > It then requires .remove() to perform both off-lining and acpi dev
> > > > delete.  .remove() must succeed, but off-lining can fail.  
> > > >
> > > >  acpi dev   online
> > > > |========|=========|
> > > > 
> > > >    add @ boot
> > > > -------->
> > > >    add @ hot-add
> > > > ------------------>
> > > > <------------------
> > > >      remove
> > > 
> > > That assumes that the "driver" is present during boot (i.e. when acpi_bus_scan()
> > > is run for the first time), but what if it is not?
> > 
> > With memory's example, the mm module must be present at boot.  The
> > system does not boot without it.
> 
> OK
> 
> > > > Your proposal seems to introduce the following new model.  If so, I do
> > > > not think it addresses all the issues.
> > > 
> > > It is not supposed to address *all* issues (whatever "all" means).  It is meant
> > > to address precisely *one* problem, which is the abuse of the driver core by
> > > the ACPI subsystem (please see below).
> > > 
> > > > .attach() still needs to behave differently between boot and hot-add.
> > > 
> > > Why does it?  I don't see any reason for that.
> > 
> > With memory's example, calling add_memory() at boot is not necessary
> > (which just fails and this failure cannot cause an error), but is
> > necessary at hot-add (which should succeed in this case). 
> 
> But essentially it's not a bug to call add_memory() during boot too, but the
> problem seems to be how to distinguish the benign failure when the memory range
> has been accounted for already earlier.  I suppose that add_memory() should
> return error codes allowing you to tell the difference?
> 
> > > > The model is also asymmetric since the destructor of .attach() at hot-add
> > > > is the combination of .detach() and .untie().
> > > > .
> > > >  attach @ boot
> > > > -------->
> > > >  attach @ hot-add
> > > > ----------------->
> > > >  detach    untie
> > > > <-------<---------
> > > >         --------->
> > > >            reclaim
> > > > 
> > > > I believe device on-lining and off-lining steps should not be performed
> > > > in .add() and .remove().  With this clarification, the current .add()
> > > > & .remove() model works fine as follows.  That is, .add() only performs
> > > > acpi dev init, and .remove() only perform acpi dev delete (which is same
> > > > as your .detach()).  My system device hot-plug framework is designed to
> > > > work with this model.
> > > 
> > > Well, if I understand the above correctly, you're basically saying that if we
> > > add a layer on top of the ACPI subsystem, we can separate "online" from "add"
> > > and "offline" from "remove" in such a way that the "add" and "remove" will be
> > > handled by the ACPI subsystem and "online" and "offline" will be done by the
> > > extra layer.
> > 
> > Right.  In memory's example, the "online" part should be done by the mm
> > module itself.
> 
> That still would be tricky, but I believe it is specific to the memory case,
> because memory ranges don't need any special enumeration to happen to be seen
> by the early boot code.  The result of that is that the memory subsystem
> doesn't know whether or not the given range is removable upfront.  However, we
> find that out from the ACPI namespace scan and we should be able to tell the
> memory subsystem "this range is removable" somehow.  So instead of add_memory()
> there should be something like add_removable_memory_range() that would succeed
> if the memory range has already been found.  In that case it should just cause
> the memory subsystem to record the fact that the given range has the capability
> of being removed, which indeed may be good to know to it.
> 
> > > That quite precisely is what we should be doing, but the "add" operation should
> > > include the creation of a "physical device" object, like for example struct
> > > platform_device, and the additional layer should be a proper driver (a platform
> > > driver for example) that will bind to that "physical device" object and
> > > initialize the device (i.e. hardware).
> > >
> > > Analogously, the "remove" operation should include the removal of the "physical
> > > device" object from which the driver will have to be unbound first.
> > 
> > Agreed.  With memory's example, the "remove" is also required to do
> > "off-lining" (i.e. call remove_memory), which should not be the role of
> > ACPI driver.
> 
> Well, it kind of has to be initiated by the ACPI subsystem, because that's
> where the event happens.  And I'm not talking about the event that the BIOS
> signals, but an event that may happen as a result of an eject event from the
> BIOS for *another* device node upper in the hierarchy (e.g. a processor
> package).
> 
> > > That I believe is what Greg meant when he was discussing your earlier proposal
> > > with you.
> > > 
> > > Now, however, the problem is what kind of a device object we should create
> > > during the "add" phase (struct platform_device may not be suitable in some
> > > cases) and whether that needs to be a single object or a whole bunch of them
> > > (e.g. when the given struct acpi_device represents a bus or bridge, like in the
> > > PCI host bridge case).  That's what the ACPI scan handlers I'm proposing are
> > > for.
> > 
> > OK, so, we are thinking of different issues... :-)
> > 
> > > So, an ACPI scan handler's .attach() is supposed to recognize what kind of
> > > hardware is there to handle and to create whatever device objects (based on
> > > struct device) are there to create etc.  Then, there should be drivers that
> > > will bind to those objects and so on.  .detach(), in turn, is supposed to
> > > reverse whatever .attach() has done.  There is an additional complication,
> > > though, that there may be an eject request between .attach() and .detach()
> > > and it needs to be responded to.
> > > 
> > > This really is about responding to three types of events related to the ACPI
> > > namespace.  Those events are, essentially:
> > > 
> > > (1) Device node (i.e. struct acpi_device) has been registered.
> > > (2) Eject has been requested for a device node.
> > > (3) Device node goes away (i.e. it is going to be unregistered).
> > > 
> > > Whatever the "model", we have to respond to the above events, this way or
> > > another.
> > > 
> > > Of course, (2) need not be the same as (3) in general, because one may envision
> > > a refusal to carry out the eject.  Currently, though, there is no distinction
> > > between (2) and (3).
> > > 
> > > The purpose of ACPI scan handlers I'm proposing is precisely to handle these
> > > three types of events without abusing the driver core.  How exactly they are
> > > going to be handled will depend on the implementation of those handlers.
> > > 
> > > The idea is that .attach(), .untie(), and .detach() will be called to handle
> > > (1), (2), and (3), respectively, with the additional twist that after an eject
> > > refusal .reclaim() needs to be called to do the cleanup.
> > > 
> > > Well, perhaps the names .untie() and .reclaim() are not the best ones and it's
> > > better to use names like .eject_requested() and .eject_refused() explicitly
> > > for those callbacks?  And analogously for the flag indicating that
> > > .eject_requested() has succeeded for the given device?
> > > 
> > > So, this is not about creating any new "model", it's just about doing what
> > > needs to be done in a possibly straightforward way.
> > > 
> > > Now, perhaps I should just post some code so that it's more clear what I mean. :-)
> > 
> > Sounds like I did confuse completely!
> > 
> > Anyway, even we have .untie() or .eject_requested(), I think all the
> > hot-delete procedure may not be done within this function since an ACPI
> > driver is not responsible for managing/controlling actual device.
> 
> No, it is not, but it may propagate the event to the code that is responsible
> for that.
> 
> The problem is that sometimes the only way we learn that there's a request to
> remove certain device is through the ACPI namespace.  Suppose that there is
> device object CONT in the namespace and there's another device object MEMR
> that is a direct child of CONT.  We have struct acpi_device objects for both.
> 
> Now, say that we have an eject request for CONT.  Obviously, we are supposed to
> remove both struct acpi_device objects for CONT and MEMR, but we don't know
> if the removal of MEMR is safe.  To address this we need to ask the code that
> handles the device represented by MEMR if removing it will be safe.  That's
> what .eject_requested() is supposed to be for.
> 
> So the idea is that when the BIOS signals "eject" for CONT, the ACPI subsystem
> will call handler->eject_requested() for all struct acpi_device objects below
> and including the CONT's one.  That call doesn't actually need to remove
> anything, but it is supposed to (a) check if the removal will be safe and (b)
> if so, make sure that that doesn't change after it has returned.  If it can't
> do both (a) and (b), it should return an error code and that will cause the
> ACPI subsystem to fail the eject.
> 
> In the case of memory, it may call something like "disable memory" at this
> point that will try to move everything out of the memory range and mark it
> as "don't use".  That, if successful, will ensure both (a) and (b).  No
> physical removal, though, the memory module is still there.
> 
> Now suppose that there are two memory modules under CONT in the ACPI namespace,
> MEMA and MEMB.  Again, the BIOS signals "eject" for CONT and say that
> .eject_requested() calls "disable memory" for MEMA which succeeds and the
> same is done for MEMB, but this time "disable memory" fails, so its
> .eject_requested() returns an error code.
> 
> In that case the ACPI namespace needs to tell the handler of MEMA that the
> eject is not going to happen after all, so it may tell the memory subsystem
> to re-enable the relevant memory range.  This is the purpose of the
> .eject_canceled() (previously .reclaim()) call.  [If the re-enabling fails,
> the memory range will be permanently disabled, but we only care so much as it
> means that we can just safely remove that memory module going forward at any
> time.]
> 
> On the other hand, if .eject_requested() for both MEMA and MEMB succeed,
> the ACPI subsystem can simply call acpi_bus_trim() for the whole subtree
> starting at CONT.  In that case .detach() callbacks will be executed for both
> MEMA and MEMB and they will actually do the teardown of everything.
> 
> Still, someone sometimes may want to force an eject of CONT, even though
> that will crash the system outright.  For this reason, it has to be possible
> to do the acpi_bus_trim() for the CONT's subtree directly and that should still
> remove everything without failing and that's where the "untied" flag may be
> useful (I will call it eject_accepted in future).  Namely, .detach() may
> look at it and see whether or not .eject_requested() was called successfully
> for its device and decide what to do on this basis.
> 
> Thus the .eject_requested()/.eject_canceled() phase is kind of advisory for
> situations in which we are allowed to fail an eject request and generally
> .detach() is still supposed to be the reverse of .attach().
> 
> And again, those are simply events related to the ACPI namespace,
> "struct acpi_device has been registered", "eject has been requested for a
> struct acpi_device", and "unregister struct acpi_device now" that the ACPI
> subsystem needs to react to and possibly propagate them to the upper code
> layers (device drivers etc.).

That made me think about the eject problem in general (that is, how to get
information on whether or not the removal of a given set of devices is going to
be safe) which lead to the realization that it really is not limited to memory
and that the .eject_requested()/.eject_canceled() mechanism above may not be
sufficient in general.  I'll describe that in a separate message, though.

As far as the scan handlers are concerned, it looks like I wanted to do too
much at a time, because what I need for now is only things that will do
.attach()/.detach() without involving the driver core.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [RFC] ACPI scan handlers
  2013-01-24  0:26 [RFC] ACPI scan handlers Rafael J. Wysocki
  2013-01-25 16:52 ` Toshi Kani
@ 2013-01-26 18:42 ` Jiang Liu
  2013-01-26 21:46   ` Rafael J. Wysocki
  2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
  2 siblings, 1 reply; 71+ messages in thread
From: Jiang Liu @ 2013-01-26 18:42 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Toshi Kani, LKML

On 01/24/2013 08:26 AM, Rafael J. Wysocki wrote:
> Hi All,
> 
> There is a considerable amount of confusion in the ACPI subsystem about what
> ACPI drivers are used for.  Namely, some of them are used as "normal" device
> drivers that bind to devices and handle them using ACPI control methods (like
> the fan or battery drivers), but some of them are just used for handling
> namespace events, such as the creation or removal of device nodes (I guess it
> would be fair to call that an abuse of the driver core).  These two roles are
> quite distinct, which is particularly visible from the confusion about the role
> of the .remove() callback.
> 
> For the "normal" drivers this callback is simply used to handle situations in
> which the driver needs to be unbound from the device, because one of them
> (either the device or the driver) is going away.  That operation can't really
> fail, it just needs to do the necessary cleanup.
> 
> However, for the namespace events handling "drivers" .remove() means that not
> only the device node in question, but generally also the whole subtree below it
> needs to be prepared for removal, which may involve deleting multiple device
> objects belonging to different bus types and so on and which very well may fail
> (for example, those devices may be used for such things like swap or they may be
> memory banks used by the kernel and it may not be safe to remove them at the
> moment etc.).  Moreover, for these things the removal of the "driver" doesn't
> really make sense, because it has to be there to handle the namespace events it
> is designed to handle or else things will go remarkably awry in some places.
> 
> To resolve all that mess I'd like to do the following, which in part is inspired
> by the recent Toshi Kani's hotplug framework proposal and in part is based on
> some discussions I had with Bjorn and others (the code references made below are
> based on the current contens of linux-pm.git/linux-next).
Hi Rafael,
	Great to know that you plan to clean up these messes. We are working on
the same topic too.

> 
> 1) Introduce a special data type for "ACPI namespace event handlers" like:
> 
> struct acpi_scan_handler {
> 	const struct acpi_device_id *ids;
> 	struct list_head list_node;
> 	int (*attach)(struct acpi_device *adev);
> 	int (*untie)(struct acpi_device *adev);
> 	int (*reclaim)(struct acpi_device *adev);
> 	void (*detach)(struct acpi_device *adev);
> };
> 
>   an additional ACPI device flag:
> 
> struct acpi_device_flags {
> ...
> 	u32 untied:1;
> ...
> };
> 
>   and an additioanl field in struc acpi_device:
> 
> struct acpi_device {
> ...
> 	struct acpi_scan_handler *scan_handler;
> ...
> };
> 
>   (the roles of these things are described below).
> 
> 2) Introduce a list of struct acpi_scan_handler objects within the ACPI
>    subsystem such that acpi_bus_device_attach() will search that list first and
>    if there's a matching object (one whose ids match the device node), it will
>    run that object's .attach() callback.
> 
>   If that returns 1, it will mean that the handler has claimed the device node
>   and is now responsible for it until its .detach() callback is run.  Thus no
>   driver can be bound to that device node and no other handler can claim it.
>   Then, the device node's scan_handler field will be set to point to the handler
>   that's claimed it and its untied flag will be cleared.
> 
>   If .attach() returns 0, it will mean that the handler has not recognized the
>   device node and some other scan handlers and/or drivers may be tried for it.
This doesn't seem perfect. The device enumeration logic still interferes with
device drivers. Should we totally separate device enumeration logic from device
drivers?

> 
>   If an error code is returned, it will mean a hard error in which case the
>   scanning of the namespace will have to be aborted.
> 
>   This way ACPI drivers will only be bound to device nodes that haven't been
>   claimed by any scan handlers.
> 
> 3) Introduce an additional function following the format of acpi_bus_trim(),
>    say acpi_bus_untie(), that will walk the namespace starting at the given
>    device node and execute the .untie() callbacks from the scan handlers of
>    all devices as post-order callbacks.
> 
>    If the .untie() callback for the given device node returns 0, it will mean
>    that it is now safe to delete that node as long as its scan handler's
>    .detach() callback is executed before the deletion.  In that case, the device
>    node's untied flag will be set.
> 
>    Otherwise (i.e. if an error code is returned), it will mean that the scan
>    handler has vetoed the untying and the whole operation should be reversed.
>    Then, acpi_bus_untie() will walk the namespace again and execute the
>    .reclaim() callbacks from the scan handlers of the device nodes whose untied
>    flags are set as pre-order callbacks.
> 
>    If .reclaim() returns 0, the device node's untied flag will be cleared, and
>    if an error code is returned, it will remain set.
> 
>    This will allow us to prepare the subtree below the given device node for
>    removal in a reversible way, if needed.  Still, though, it will be possible
>    to carry out a forcible removal calling acpi_bus_trim() after
>    acpi_bus_untie() even if that has returned an error code (or even
>    acpi_bus_trim() without acpi_bus_untie()).
> 
> 4) Make acpi_bus_device_detach() execute the .detach() callback from the
>    scan handler of the device node (if the scan handler is present) and clear
>    its scan_handler field along with its untied flag.  However, the untied flags
>    will only be cleared after executing the .detach() callbacks, so that those
>    callbacks can see whether or not the scan handlers have been successfully
>    "untied" from the device nodes.
> 
> 5) Make acpi_bus_hot_remove_device() (and other pieces of code where that is
>    convenient) call acpi_bus_untie() before acpi_bus_trim() and bail out
>    cleanly if the untying fails (i.e. is vetoed by one of the scan handlers).
> 
> That should take care of the removal problem nicely and as far as I can say
> the majority of the ACPI drivers used only for handling namespace events can
> be readily converted to struct acpi_scan_handler objects.
> 
> I wonder if anyone is seeing any major problems with this at the high level.
This design has some conflicts with our ongoing work to provide a system device
hotplug framework. I will send out the draft framework for comments soon.

Thanks!
Gerry

> 
> Thanks,
> Rafael
> 
> 


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [RFC] ACPI scan handlers
  2013-01-26 18:42 ` Jiang Liu
@ 2013-01-26 21:46   ` Rafael J. Wysocki
  0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-26 21:46 UTC (permalink / raw)
  To: Jiang Liu
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Toshi Kani, LKML

On Sunday, January 27, 2013 02:42:38 AM Jiang Liu wrote:
> On 01/24/2013 08:26 AM, Rafael J. Wysocki wrote:
> > Hi All,
> > 
> > There is a considerable amount of confusion in the ACPI subsystem about what
> > ACPI drivers are used for.  Namely, some of them are used as "normal" device
> > drivers that bind to devices and handle them using ACPI control methods (like
> > the fan or battery drivers), but some of them are just used for handling
> > namespace events, such as the creation or removal of device nodes (I guess it
> > would be fair to call that an abuse of the driver core).  These two roles are
> > quite distinct, which is particularly visible from the confusion about the role
> > of the .remove() callback.
> > 
> > For the "normal" drivers this callback is simply used to handle situations in
> > which the driver needs to be unbound from the device, because one of them
> > (either the device or the driver) is going away.  That operation can't really
> > fail, it just needs to do the necessary cleanup.
> > 
> > However, for the namespace events handling "drivers" .remove() means that not
> > only the device node in question, but generally also the whole subtree below it
> > needs to be prepared for removal, which may involve deleting multiple device
> > objects belonging to different bus types and so on and which very well may fail
> > (for example, those devices may be used for such things like swap or they may be
> > memory banks used by the kernel and it may not be safe to remove them at the
> > moment etc.).  Moreover, for these things the removal of the "driver" doesn't
> > really make sense, because it has to be there to handle the namespace events it
> > is designed to handle or else things will go remarkably awry in some places.
> > 
> > To resolve all that mess I'd like to do the following, which in part is inspired
> > by the recent Toshi Kani's hotplug framework proposal and in part is based on
> > some discussions I had with Bjorn and others (the code references made below are
> > based on the current contens of linux-pm.git/linux-next).
> Hi Rafael,
> 	Great to know that you plan to clean up these messes. We are working on
> the same topic too.
> 
> > 
> > 1) Introduce a special data type for "ACPI namespace event handlers" like:
> > 
> > struct acpi_scan_handler {
> > 	const struct acpi_device_id *ids;
> > 	struct list_head list_node;
> > 	int (*attach)(struct acpi_device *adev);
> > 	int (*untie)(struct acpi_device *adev);
> > 	int (*reclaim)(struct acpi_device *adev);
> > 	void (*detach)(struct acpi_device *adev);
> > };
> > 
> >   an additional ACPI device flag:
> > 
> > struct acpi_device_flags {
> > ...
> > 	u32 untied:1;
> > ...
> > };
> > 
> >   and an additioanl field in struc acpi_device:
> > 
> > struct acpi_device {
> > ...
> > 	struct acpi_scan_handler *scan_handler;
> > ...
> > };
> > 
> >   (the roles of these things are described below).
> > 
> > 2) Introduce a list of struct acpi_scan_handler objects within the ACPI
> >    subsystem such that acpi_bus_device_attach() will search that list first and
> >    if there's a matching object (one whose ids match the device node), it will
> >    run that object's .attach() callback.
> > 
> >   If that returns 1, it will mean that the handler has claimed the device node
> >   and is now responsible for it until its .detach() callback is run.  Thus no
> >   driver can be bound to that device node and no other handler can claim it.
> >   Then, the device node's scan_handler field will be set to point to the handler
> >   that's claimed it and its untied flag will be cleared.
> > 
> >   If .attach() returns 0, it will mean that the handler has not recognized the
> >   device node and some other scan handlers and/or drivers may be tried for it.
> This doesn't seem perfect. The device enumeration logic still interferes with
> device drivers. Should we totally separate device enumeration logic from device
> drivers?

Yes, that's the ultimate plan, but we can't do that at the moment for practical
reasons (there are many ACPI drivers already in existence and we don't want to
introduce regressions gratuitously).

Introducing scan handlers more-or-less as described would be a step in that
direction, though.

> > 
> >   If an error code is returned, it will mean a hard error in which case the
> >   scanning of the namespace will have to be aborted.
> > 
> >   This way ACPI drivers will only be bound to device nodes that haven't been
> >   claimed by any scan handlers.
> > 
> > 3) Introduce an additional function following the format of acpi_bus_trim(),
> >    say acpi_bus_untie(), that will walk the namespace starting at the given
> >    device node and execute the .untie() callbacks from the scan handlers of
> >    all devices as post-order callbacks.
> > 
> >    If the .untie() callback for the given device node returns 0, it will mean
> >    that it is now safe to delete that node as long as its scan handler's
> >    .detach() callback is executed before the deletion.  In that case, the device
> >    node's untied flag will be set.
> > 
> >    Otherwise (i.e. if an error code is returned), it will mean that the scan
> >    handler has vetoed the untying and the whole operation should be reversed.
> >    Then, acpi_bus_untie() will walk the namespace again and execute the
> >    .reclaim() callbacks from the scan handlers of the device nodes whose untied
> >    flags are set as pre-order callbacks.
> > 
> >    If .reclaim() returns 0, the device node's untied flag will be cleared, and
> >    if an error code is returned, it will remain set.
> > 
> >    This will allow us to prepare the subtree below the given device node for
> >    removal in a reversible way, if needed.  Still, though, it will be possible
> >    to carry out a forcible removal calling acpi_bus_trim() after
> >    acpi_bus_untie() even if that has returned an error code (or even
> >    acpi_bus_trim() without acpi_bus_untie()).
> > 
> > 4) Make acpi_bus_device_detach() execute the .detach() callback from the
> >    scan handler of the device node (if the scan handler is present) and clear
> >    its scan_handler field along with its untied flag.  However, the untied flags
> >    will only be cleared after executing the .detach() callbacks, so that those
> >    callbacks can see whether or not the scan handlers have been successfully
> >    "untied" from the device nodes.
> > 
> > 5) Make acpi_bus_hot_remove_device() (and other pieces of code where that is
> >    convenient) call acpi_bus_untie() before acpi_bus_trim() and bail out
> >    cleanly if the untying fails (i.e. is vetoed by one of the scan handlers).
> > 
> > That should take care of the removal problem nicely and as far as I can say
> > the majority of the ACPI drivers used only for handling namespace events can
> > be readily converted to struct acpi_scan_handler objects.
> > 
> > I wonder if anyone is seeing any major problems with this at the high level.
> This design has some conflicts with our ongoing work to provide a system device
> hotplug framework. I will send out the draft framework for comments soon.

Well, I'd prefer it if you were more specific.  That is, please tell me what
conflicts and why exactly.

It also would be good if you looked at the Toshi Kani's latest proposal and
said what's wrong with it from your perspective.  You'll need to do that
anyway if you want to convince anyone that your proposal is better, so why
don't you do that now?  Moreover, sending yet another "system devices hotplug
framework" proposal at this point won't increase the chance that any of them
will be accepted.  Odds are to the contrary, I'm afraid.

Besides, I'm starting to think that such frameworks covering "system devices"
only are insufficient, because nowadays it is quite difficult to say what
devices are "system devices" in the first place and there is no reason why
those devices should require a special framework while the other devices
don't.  Quite frankly, it seems to me that either we need some additional
hotplug-related handling for all devices, or we don't need anything like that
at all.

I'm seeing reasons why it may be necessary, but that will need to be discussed
at the concept level, not within the context of any specific proposal.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 0/4] ACPI scan handlers
  2013-01-24  0:26 [RFC] ACPI scan handlers Rafael J. Wysocki
  2013-01-25 16:52 ` Toshi Kani
  2013-01-26 18:42 ` Jiang Liu
@ 2013-01-28 12:58 ` Rafael J. Wysocki
  2013-01-28 12:59   ` [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler Rafael J. Wysocki
                     ` (7 more replies)
  2 siblings, 8 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-28 12:58 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

On Thursday, January 24, 2013 01:26:56 AM Rafael J. Wysocki wrote:
> Hi All,
> 
> There is a considerable amount of confusion in the ACPI subsystem about what
> ACPI drivers are used for.  Namely, some of them are used as "normal" device
> drivers that bind to devices and handle them using ACPI control methods (like
> the fan or battery drivers), but some of them are just used for handling
> namespace events, such as the creation or removal of device nodes (I guess it
> would be fair to call that an abuse of the driver core).  These two roles are
> quite distinct, which is particularly visible from the confusion about the role
> of the .remove() callback.
> 
> For the "normal" drivers this callback is simply used to handle situations in
> which the driver needs to be unbound from the device, because one of them
> (either the device or the driver) is going away.  That operation can't really
> fail, it just needs to do the necessary cleanup.
> 
> However, for the namespace events handling "drivers" .remove() means that not
> only the device node in question, but generally also the whole subtree below it
> needs to be prepared for removal, which may involve deleting multiple device
> objects belonging to different bus types and so on and which very well may fail
> (for example, those devices may be used for such things like swap or they may be
> memory banks used by the kernel and it may not be safe to remove them at the
> moment etc.).  Moreover, for these things the removal of the "driver" doesn't
> really make sense, because it has to be there to handle the namespace events it
> is designed to handle or else things will go remarkably awry in some places.
> 
> To resolve all that mess I'd like to do the following, which in part is inspired
> by the recent Toshi Kani's hotplug framework proposal and in part is based on
> some discussions I had with Bjorn and others (the code references made below are
> based on the current contens of linux-pm.git/linux-next).
> 
> 1) Introduce a special data type for "ACPI namespace event handlers" like:
> 
> struct acpi_scan_handler {
> 	const struct acpi_device_id *ids;
> 	struct list_head list_node;
> 	int (*attach)(struct acpi_device *adev);
> 	int (*untie)(struct acpi_device *adev);
> 	int (*reclaim)(struct acpi_device *adev);
> 	void (*detach)(struct acpi_device *adev);
> };

After some reconsideration I think that the "untie" and "reclaim" things won't
be really useful at this level.  This means that I only need ACPI scan handlers
to do .attach() and .detach() and all of that becomes really simple, so I don't
see reason to wait with that change.

The following patches introduce ACPI scan handlers and make some use of them.

[1/4] Introduce struct acpi_scan_handler for configuration tasks depending on
      device IDs.

[2/4] Make ACPI PCI root driver use struct acpi_scan_handler.

[3/4] Make ACPI PCI IRQ link driver use struct acpi_scan_handler.

[4/4] Use struct acpi_scan_handler for creating platform devices enumerated via ACPI.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
  2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
@ 2013-01-28 12:59   ` Rafael J. Wysocki
  2013-01-29  2:04     ` Yasuaki Ishimatsu
  2013-01-29  2:35     ` Toshi Kani
  2013-01-28 13:00   ` [PATCH 2/4] ACPI / PCI: Make PCI root driver use struct acpi_scan_handler Rafael J. Wysocki
                     ` (6 subsequent siblings)
  7 siblings, 2 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-28 12:59 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Introduce struct acpi_scan_handler for representing objects that
will do configuration tasks depending on ACPI device nodes'
hardware IDs (HIDs).

Currently, those tasks are done either directly by the ACPI namespace
scanning code or by ACPI device drivers designed specifically for
this purpose.  None of the above is desirable, however, because
doing that directly in the namespace scanning code makes that code
overly complicated and difficult to follow and doing that in
"special" device drivers leads to a great deal of confusion about
their role and to confusing interactions with the driver core (for
example, sysfs directories are created for those drivers, but they
are completely unnecessary and only increase the kernel's memory
footprint in vain).

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 Documentation/acpi/scan_handlers.txt |   77 +++++++++++++++++++++++++++++++++++
 drivers/acpi/scan.c                  |   60 ++++++++++++++++++++++++---
 include/acpi/acpi_bus.h              |   14 ++++++
 3 files changed, 144 insertions(+), 7 deletions(-)

Index: test/include/acpi/acpi_bus.h
===================================================================
--- test.orig/include/acpi/acpi_bus.h
+++ test/include/acpi/acpi_bus.h
@@ -84,6 +84,18 @@ struct acpi_driver;
 struct acpi_device;
 
 /*
+ * ACPI Scan Handler
+ * -----------------
+ */
+
+struct acpi_scan_handler {
+	const struct acpi_device_id *ids;
+	struct list_head list_node;
+	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
+	void (*detach)(struct acpi_device *dev);
+};
+
+/*
  * ACPI Driver
  * -----------
  */
@@ -269,6 +281,7 @@ struct acpi_device {
 	struct acpi_device_wakeup wakeup;
 	struct acpi_device_perf performance;
 	struct acpi_device_dir dir;
+	struct acpi_scan_handler *handler;
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
@@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
 static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
 	{ return 0; }
 #endif
+int acpi_scan_add_handler(struct acpi_scan_handler *handler);
 int acpi_bus_register_driver(struct acpi_driver *driver);
 void acpi_bus_unregister_driver(struct acpi_driver *driver);
 int acpi_bus_scan(acpi_handle handle);
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
 static LIST_HEAD(acpi_device_list);
 static LIST_HEAD(acpi_bus_id_list);
 static DEFINE_MUTEX(acpi_scan_lock);
+static LIST_HEAD(acpi_scan_handlers_list);
 DEFINE_MUTEX(acpi_device_lock);
 LIST_HEAD(acpi_wakeup_device_list);
 
@@ -62,6 +63,15 @@ struct acpi_device_bus_id{
 	struct list_head node;
 };
 
+int acpi_scan_add_handler(struct acpi_scan_handler *handler)
+{
+	if (!handler || !handler->attach)
+		return -EINVAL;
+
+	list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
+	return 0;
+}
+
 /*
  * Creates hid/cid(s) string needed for modalias and uevent
  * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
@@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
 	return AE_OK;
 }
 
+static int acpi_scan_attach_handler(struct acpi_device *device)
+{
+	struct acpi_scan_handler *handler;
+	int ret = 0;
+
+	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
+		const struct acpi_device_id *id;
+
+		id = __acpi_match_device(device, handler->ids);
+		if (!id)
+			continue;
+
+		ret = handler->attach(device, id);
+		if (ret > 0) {
+			device->handler = handler;
+			break;
+		} else if (ret < 0) {
+			break;
+		}
+	}
+	return ret;
+}
+
 static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
 					  void *not_used, void **ret_not_used)
 {
 	const struct acpi_device_id *id;
-	acpi_status status = AE_OK;
 	struct acpi_device *device;
 	unsigned long long sta_not_used;
-	int type_not_used;
+	int ret;
 
 	/*
 	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
 	 * namespace walks prematurely.
 	 */
-	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+	if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
 		return AE_OK;
 
 	if (acpi_bus_get_device(handle, &device))
@@ -1593,10 +1625,15 @@ static acpi_status acpi_bus_device_attac
 	if (id) {
 		/* This is a known good platform device. */
 		acpi_create_platform_device(device, id->driver_data);
-	} else if (device_attach(&device->dev) < 0) {
-		status = AE_CTRL_DEPTH;
+		return AE_OK;
 	}
-	return status;
+
+	ret = acpi_scan_attach_handler(device);
+	if (ret)
+		return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
+
+	ret = device_attach(&device->dev);
+	return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
 }
 
 /**
@@ -1639,8 +1676,17 @@ static acpi_status acpi_bus_device_detac
 	struct acpi_device *device = NULL;
 
 	if (!acpi_bus_get_device(handle, &device)) {
+		struct acpi_scan_handler *dev_handler = device->handler;
+
 		device->removal_type = ACPI_BUS_REMOVAL_EJECT;
-		device_release_driver(&device->dev);
+		if (dev_handler) {
+			if (dev_handler->detach)
+				dev_handler->detach(device);
+
+			device->handler = NULL;
+		} else {
+			device_release_driver(&device->dev);
+		}
 	}
 	return AE_OK;
 }
Index: test/Documentation/acpi/scan_handlers.txt
===================================================================
--- /dev/null
+++ test/Documentation/acpi/scan_handlers.txt
@@ -0,0 +1,77 @@
+ACPI Scan Handlers
+
+Copyright (C) 2012, Intel Corporation
+Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+During system initialization and ACPI-based device hot-add, the ACPI namespace
+is scanned in search of device objects that generally represent various pieces
+of hardware.  This causes a struct acpi_device object to be created and
+registered with the driver core for every device object in the ACPI namespace
+and the hierarchy of those struct acpi_device objects reflects the namespace
+layout (i.e. parent device objects in the namespace are represented by parent
+struct acpi_device objects and analogously for their children).  Those struct
+acpi_device objects are referred to as "device nodes" in what follows, but they
+should not be confused with struct device_node objects used by the Device Trees
+parsing code (although their role is analogous to the role of those objects).
+
+During ACPI-based device hot-remove device nodes representing pieces of hardware
+being removed are unregistered and deleted.
+
+The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic
+initialization of device nodes, such as retrieving common configuration
+information from the device objects represented by them and populating them with
+appropriate data, but some of them require additional handling after they have
+been registered.  For example, if the given device node represents a PCI host
+bridge, its registration should cause the PCI bus under that bridge to be
+enumerated and PCI devices on that bus to be registered with the driver core.
+Similarly, if the device node represents a PCI interrupt link, it is necessary
+to configure that link so that the kernel can use it.
+
+Those additional configuration tasks usually depend on the type of the hardware
+component represented by the given device node which can be determined on the
+basis of the device node's hardware ID (HID).  They are performed by objects
+called ACPI scan handlers represented by the following structure:
+
+struct acpi_scan_handler {
+	const struct acpi_device_id *ids;
+	struct list_head list_node;
+	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
+	void (*detach)(struct acpi_device *dev);
+};
+
+where ids is the list of IDs of device nodes the given handler is supposed to
+take care of, list_node is the hook to the global list of ACPI scan handlers
+maintained by the ACPI core and the .attach() and .detach() callbacks are
+executed, respectively, after registration of new device nodes and before
+unregistration of device nodes the handler attached to previously.
+
+The namespace scanning function, acpi_bus_scan(), first registers all of the
+device nodes in the given namespace scope with the driver core.  Then, it tries
+to match a scan handler against each of them using the ids arrays of the
+available scan handlers.  If a matching scan handler is found, its .attach()
+callback is executed for the given device node.  If that callback returns 1,
+that means that the handler has claimed the device node and is now responsible
+for carrying out any additional configuration tasks related to it.  It also will
+be responsible for preparing the device node for unregistration in that case.
+The device node's handler field is then populated with the address of the scan
+handler that has claimed it.
+
+If the .attach() callback returns 0, it means that the device node is not
+interesting to the given scan handler and may be matched against the next scan
+handler in the list.  If it returns a (negative) error code, that means that
+the namespace scan should be terminated due to a serious error.  The error code
+returned should then reflect the type of the error.
+
+The namespace trimming function, acpi_bus_trim(), first executes .detach()
+callbacks from the scan handlers of all device nodes in the given namespace
+scope (if they have scan handlers).  Next, it unregisters all of the device
+nodes in that scope.
+
+ACPI scan handlers can be added to the list maintained by the ACPI core with the
+help of the acpi_scan_add_handler() function taking a pointer to the new scan
+handler as an argument.  The order in which scan handlers are added to the list
+is the order in which they are matched against device nodes during namespace
+scans.
+
+All scan handles must be added to the list before acpi_bus_scan() is run for the
+first time and they cannot be removed from it.


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 2/4] ACPI / PCI: Make PCI root driver use struct acpi_scan_handler
  2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
  2013-01-28 12:59   ` [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler Rafael J. Wysocki
@ 2013-01-28 13:00   ` Rafael J. Wysocki
  2013-01-28 13:00   ` [PATCH 3/4] ACPI / PCI: Make PCI IRQ link " Rafael J. Wysocki
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-28 13:00 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Make the ACPI PCI root bridge driver use struct acpi_scan_handler
for representing the object used to enumerate the PCI busses under
PCI host bridges found in the ACPI namespace (and to tear down data
structures representing the bus and devices on it before
unregistering the host bridges' ACPI device nodes).

This simplifies the code slightly and reduces the kernel's memory
footprint by avoiding the registration of a struct device_driver
object with the driver core and creation of its sysfs directory
which is unnecessary.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/internal.h |    2 +-
 drivers/acpi/pci_root.c |   38 +++++++++++++++-----------------------
 2 files changed, 16 insertions(+), 24 deletions(-)

Index: test/drivers/acpi/pci_root.c
===================================================================
--- test.orig/drivers/acpi/pci_root.c
+++ test/drivers/acpi/pci_root.c
@@ -45,8 +45,9 @@
 ACPI_MODULE_NAME("pci_root");
 #define ACPI_PCI_ROOT_CLASS		"pci_bridge"
 #define ACPI_PCI_ROOT_DEVICE_NAME	"PCI Root Bridge"
-static int acpi_pci_root_add(struct acpi_device *device);
-static int acpi_pci_root_remove(struct acpi_device *device);
+static int acpi_pci_root_add(struct acpi_device *device,
+			     const struct acpi_device_id *not_used);
+static void acpi_pci_root_remove(struct acpi_device *device);
 
 #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \
 				| OSC_ACTIVE_STATE_PWR_SUPPORT \
@@ -57,16 +58,11 @@ static const struct acpi_device_id root_
 	{"PNP0A03", 0},
 	{"", 0},
 };
-MODULE_DEVICE_TABLE(acpi, root_device_ids);
 
-static struct acpi_driver acpi_pci_root_driver = {
-	.name = "pci_root",
-	.class = ACPI_PCI_ROOT_CLASS,
+static struct acpi_scan_handler pci_root_handler = {
 	.ids = root_device_ids,
-	.ops = {
-		.add = acpi_pci_root_add,
-		.remove = acpi_pci_root_remove,
-		},
+	.attach = acpi_pci_root_add,
+	.detach = acpi_pci_root_remove,
 };
 
 /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */
@@ -428,7 +424,8 @@ out:
 }
 EXPORT_SYMBOL(acpi_pci_osc_control_set);
 
-static int acpi_pci_root_add(struct acpi_device *device)
+static int acpi_pci_root_add(struct acpi_device *device,
+			     const struct acpi_device_id *not_used)
 {
 	unsigned long long segment, bus;
 	acpi_status status;
@@ -614,7 +611,7 @@ static int acpi_pci_root_add(struct acpi
 		pci_enable_bridges(root->bus);
 
 	pci_bus_add_devices(root->bus);
-	return 0;
+	return 1;
 
 out_del_root:
 	mutex_lock(&acpi_pci_root_lock);
@@ -627,7 +624,7 @@ end:
 	return result;
 }
 
-static int acpi_pci_root_remove(struct acpi_device *device)
+static void acpi_pci_root_remove(struct acpi_device *device)
 {
 	acpi_status status;
 	acpi_handle handle;
@@ -655,19 +652,14 @@ static int acpi_pci_root_remove(struct a
 	list_del(&root->node);
 	mutex_unlock(&acpi_pci_root_lock);
 	kfree(root);
-	return 0;
 }
 
-int __init acpi_pci_root_init(void)
+void __init acpi_pci_root_init(void)
 {
 	acpi_hest_init();
 
-	if (acpi_pci_disabled)
-		return 0;
-
-	pci_acpi_crs_quirks();
-	if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
-		return -ENODEV;
-
-	return 0;
+	if (!acpi_pci_disabled) {
+		pci_acpi_crs_quirks();
+		acpi_scan_add_handler(&pci_root_handler);
+	}
 }
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -25,6 +25,7 @@
 
 int init_acpi_device_notify(void);
 int acpi_scan_init(void);
+void acpi_pci_root_init(void);
 int acpi_sysfs_init(void);
 void acpi_csrt_init(void);
 
@@ -86,7 +87,6 @@ struct acpi_ec {
 
 extern struct acpi_ec *first_ec;
 
-int acpi_pci_root_init(void);
 int acpi_ec_init(void);
 int acpi_ec_ecdt_probe(void);
 int acpi_boot_ec_enable(void);


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 3/4] ACPI / PCI: Make PCI IRQ link driver use struct acpi_scan_handler
  2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
  2013-01-28 12:59   ` [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler Rafael J. Wysocki
  2013-01-28 13:00   ` [PATCH 2/4] ACPI / PCI: Make PCI root driver use struct acpi_scan_handler Rafael J. Wysocki
@ 2013-01-28 13:00   ` Rafael J. Wysocki
  2013-01-28 13:01   ` [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices Rafael J. Wysocki
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-28 13:00 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Make the ACPI PCI IRQ link driver use struct acpi_scan_handler
for representing the object used to set up ACPI interrupt links and
to remove data structures used for this purpose before unregistering
the corresponding ACPI device nodes.

This simplifies the code slightly and reduces the kernel's memory
footprint by avoiding the registration of a struct device_driver
object with the driver core and creation of its sysfs directory
which is unnecessary.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/internal.h |    1 +
 drivers/acpi/pci_link.c |   47 ++++++++++++++---------------------------------
 drivers/acpi/scan.c     |    1 +
 3 files changed, 16 insertions(+), 33 deletions(-)

Index: test/drivers/acpi/pci_link.c
===================================================================
--- test.orig/drivers/acpi/pci_link.c
+++ test/drivers/acpi/pci_link.c
@@ -53,23 +53,19 @@ ACPI_MODULE_NAME("pci_link");
 #define ACPI_PCI_LINK_FILE_STATUS	"state"
 #define ACPI_PCI_LINK_MAX_POSSIBLE	16
 
-static int acpi_pci_link_add(struct acpi_device *device);
-static int acpi_pci_link_remove(struct acpi_device *device);
+static int acpi_pci_link_add(struct acpi_device *device,
+			     const struct acpi_device_id *not_used);
+static void acpi_pci_link_remove(struct acpi_device *device);
 
 static const struct acpi_device_id link_device_ids[] = {
 	{"PNP0C0F", 0},
 	{"", 0},
 };
-MODULE_DEVICE_TABLE(acpi, link_device_ids);
 
-static struct acpi_driver acpi_pci_link_driver = {
-	.name = "pci_link",
-	.class = ACPI_PCI_LINK_CLASS,
+static struct acpi_scan_handler pci_link_handler = {
 	.ids = link_device_ids,
-	.ops = {
-		.add = acpi_pci_link_add,
-		.remove = acpi_pci_link_remove,
-	},
+	.attach = acpi_pci_link_add,
+	.detach = acpi_pci_link_remove,
 };
 
 /*
@@ -692,7 +688,8 @@ int acpi_pci_link_free_irq(acpi_handle h
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
-static int acpi_pci_link_add(struct acpi_device *device)
+static int acpi_pci_link_add(struct acpi_device *device,
+			     const struct acpi_device_id *not_used)
 {
 	int result;
 	struct acpi_pci_link *link;
@@ -746,7 +743,7 @@ static int acpi_pci_link_add(struct acpi
 	if (result)
 		kfree(link);
 
-	return result;
+	return result < 0 ? result : 1;
 }
 
 static int acpi_pci_link_resume(struct acpi_pci_link *link)
@@ -766,7 +763,7 @@ static void irqrouter_resume(void)
 	}
 }
 
-static int acpi_pci_link_remove(struct acpi_device *device)
+static void acpi_pci_link_remove(struct acpi_device *device)
 {
 	struct acpi_pci_link *link;
 
@@ -777,7 +774,6 @@ static int acpi_pci_link_remove(struct a
 	mutex_unlock(&acpi_link_lock);
 
 	kfree(link);
-	return 0;
 }
 
 /*
@@ -874,20 +870,10 @@ static struct syscore_ops irqrouter_sysc
 	.resume = irqrouter_resume,
 };
 
-static int __init irqrouter_init_ops(void)
-{
-	if (!acpi_disabled && !acpi_noirq)
-		register_syscore_ops(&irqrouter_syscore_ops);
-
-	return 0;
-}
-
-device_initcall(irqrouter_init_ops);
-
-static int __init acpi_pci_link_init(void)
+void __init acpi_pci_link_init(void)
 {
 	if (acpi_noirq)
-		return 0;
+		return;
 
 	if (acpi_irq_balance == -1) {
 		/* no command line switch: enable balancing in IOAPIC mode */
@@ -896,11 +882,6 @@ static int __init acpi_pci_link_init(voi
 		else
 			acpi_irq_balance = 0;
 	}
-
-	if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0)
-		return -ENODEV;
-
-	return 0;
+	register_syscore_ops(&irqrouter_syscore_ops);
+	acpi_scan_add_handler(&pci_link_handler);
 }
-
-subsys_initcall(acpi_pci_link_init);
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -26,6 +26,7 @@
 int init_acpi_device_notify(void);
 int acpi_scan_init(void);
 void acpi_pci_root_init(void);
+void acpi_pci_link_init(void);
 int acpi_sysfs_init(void);
 void acpi_csrt_init(void);
 
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -1774,6 +1774,7 @@ int __init acpi_scan_init(void)
 	}
 
 	acpi_pci_root_init();
+	acpi_pci_link_init();
 	acpi_csrt_init();
 
 	/*


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
  2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
                     ` (2 preceding siblings ...)
  2013-01-28 13:00   ` [PATCH 3/4] ACPI / PCI: Make PCI IRQ link " Rafael J. Wysocki
@ 2013-01-28 13:01   ` Rafael J. Wysocki
  2013-01-29  2:20     ` Yasuaki Ishimatsu
                       ` (2 more replies)
  2013-01-28 21:54   ` [PATCH 0/4] ACPI scan handlers Yinghai Lu
                     ` (3 subsequent siblings)
  7 siblings, 3 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-28 13:01 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Currently, the ACPI namespace scanning code creates platform device
objects for ACPI device nodes whose IDs match the contents of the
acpi_platform_device_ids[] table.  However, this adds a superfluous
special case into acpi_bus_device_attach() and makes it more
difficult to follow than it has to be.  It also will make it more
difficult to implement removal code for those platform device objects
in the future.

For the above reasons, introduce a struct acpi_scan_handler object
for creating platform devices and move the code related to that from
acpi_bus_device_attach() to the .attach() callback of that object.
Also move the acpi_platform_device_ids[] table to acpi_platform.c.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/acpi_platform.c |   55 +++++++++++++++++++++++++++++++++++--------
 drivers/acpi/internal.h      |    7 -----
 drivers/acpi/scan.c          |   30 -----------------------
 3 files changed, 47 insertions(+), 45 deletions(-)

Index: test/drivers/acpi/acpi_platform.c
===================================================================
--- test.orig/drivers/acpi/acpi_platform.c
+++ test/drivers/acpi/acpi_platform.c
@@ -22,6 +22,30 @@
 
 ACPI_MODULE_NAME("platform");
 
+/* Flags for acpi_create_platform_device */
+#define ACPI_PLATFORM_CLK	BIT(0)
+
+/*
+ * The following ACPI IDs are known to be suitable for representing as
+ * platform devices.
+ */
+static const struct acpi_device_id acpi_platform_device_ids[] = {
+
+	{ "PNP0D40" },
+
+	/* Haswell LPSS devices */
+	{ "INT33C0", ACPI_PLATFORM_CLK },
+	{ "INT33C1", ACPI_PLATFORM_CLK },
+	{ "INT33C2", ACPI_PLATFORM_CLK },
+	{ "INT33C3", ACPI_PLATFORM_CLK },
+	{ "INT33C4", ACPI_PLATFORM_CLK },
+	{ "INT33C5", ACPI_PLATFORM_CLK },
+	{ "INT33C6", ACPI_PLATFORM_CLK },
+	{ "INT33C7", ACPI_PLATFORM_CLK },
+
+	{ }
+};
+
 static int acpi_create_platform_clks(struct acpi_device *adev)
 {
 	static struct platform_device *pdev;
@@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
 /**
  * acpi_create_platform_device - Create platform device for ACPI device node
  * @adev: ACPI device node to create a platform device for.
- * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
- *	   devices.
+ * @id: ACPI device ID used to match @adev.
  *
  * Check if the given @adev can be represented as a platform device and, if
  * that's the case, create and register a platform device, populate its common
@@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
  *
  * Name of the platform device will be the same as @adev's.
  */
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
-						    unsigned long flags)
+static int acpi_create_platform_device(struct acpi_device *adev,
+				       const struct acpi_device_id *id)
 {
+	unsigned long flags = id->driver_data;
 	struct platform_device *pdev = NULL;
 	struct acpi_device *acpi_parent;
 	struct platform_device_info pdevinfo;
@@ -59,25 +83,26 @@ struct platform_device *acpi_create_plat
 	struct resource *resources;
 	int count;
 
-	if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
+	if (flags & ACPI_PLATFORM_CLK) {
+		int ret = acpi_create_platform_clks(adev);
 		dev_err(&adev->dev, "failed to create clocks\n");
-		return NULL;
+		return ret;
 	}
 
 	/* If the ACPI node already has a physical device attached, skip it. */
 	if (adev->physical_node_count)
-		return NULL;
+		return 0;
 
 	INIT_LIST_HEAD(&resource_list);
 	count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
 	if (count <= 0)
-		return NULL;
+		return 0;
 
 	resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
 	if (!resources) {
 		dev_err(&adev->dev, "No memory for resources\n");
 		acpi_dev_free_resource_list(&resource_list);
-		return NULL;
+		return -ENOMEM;
 	}
 	count = 0;
 	list_for_each_entry(rentry, &resource_list, node)
@@ -123,5 +148,15 @@ struct platform_device *acpi_create_plat
 	}
 
 	kfree(resources);
-	return pdev;
+	return 1;
+}
+
+static struct acpi_scan_handler platform_handler = {
+	.ids = acpi_platform_device_ids,
+	.attach = acpi_create_platform_device,
+};
+
+void __init acpi_platform_init(void)
+{
+	acpi_scan_add_handler(&platform_handler);
 }
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -27,6 +27,7 @@ int init_acpi_device_notify(void);
 int acpi_scan_init(void);
 void acpi_pci_root_init(void);
 void acpi_pci_link_init(void);
+void acpi_platform_init(void);
 int acpi_sysfs_init(void);
 void acpi_csrt_init(void);
 
@@ -119,10 +120,4 @@ static inline void suspend_nvs_restore(v
   -------------------------------------------------------------------------- */
 struct platform_device;
 
-/* Flags for acpi_create_platform_device */
-#define ACPI_PLATFORM_CLK	BIT(0)
-
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
-						    unsigned long flags);
-
 #endif /* _ACPI_INTERNAL_H_ */
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -29,27 +29,6 @@ extern struct acpi_device *acpi_root;
 
 static const char *dummy_hid = "device";
 
-/*
- * The following ACPI IDs are known to be suitable for representing as
- * platform devices.
- */
-static const struct acpi_device_id acpi_platform_device_ids[] = {
-
-	{ "PNP0D40" },
-
-	/* Haswell LPSS devices */
-	{ "INT33C0", ACPI_PLATFORM_CLK },
-	{ "INT33C1", ACPI_PLATFORM_CLK },
-	{ "INT33C2", ACPI_PLATFORM_CLK },
-	{ "INT33C3", ACPI_PLATFORM_CLK },
-	{ "INT33C4", ACPI_PLATFORM_CLK },
-	{ "INT33C5", ACPI_PLATFORM_CLK },
-	{ "INT33C6", ACPI_PLATFORM_CLK },
-	{ "INT33C7", ACPI_PLATFORM_CLK },
-
-	{ }
-};
-
 static LIST_HEAD(acpi_device_list);
 static LIST_HEAD(acpi_bus_id_list);
 static DEFINE_MUTEX(acpi_scan_lock);
@@ -1606,7 +1585,6 @@ static int acpi_scan_attach_handler(stru
 static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
 					  void *not_used, void **ret_not_used)
 {
-	const struct acpi_device_id *id;
 	struct acpi_device *device;
 	unsigned long long sta_not_used;
 	int ret;
@@ -1621,13 +1599,6 @@ static acpi_status acpi_bus_device_attac
 	if (acpi_bus_get_device(handle, &device))
 		return AE_CTRL_DEPTH;
 
-	id = __acpi_match_device(device, acpi_platform_device_ids);
-	if (id) {
-		/* This is a known good platform device. */
-		acpi_create_platform_device(device, id->driver_data);
-		return AE_OK;
-	}
-
 	ret = acpi_scan_attach_handler(device);
 	if (ret)
 		return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
@@ -1775,6 +1746,7 @@ int __init acpi_scan_init(void)
 
 	acpi_pci_root_init();
 	acpi_pci_link_init();
+	acpi_platform_init();
 	acpi_csrt_init();
 
 	/*


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 0/4] ACPI scan handlers
  2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
                     ` (3 preceding siblings ...)
  2013-01-28 13:01   ` [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices Rafael J. Wysocki
@ 2013-01-28 21:54   ` Yinghai Lu
  2013-01-29  0:38     ` Rafael J. Wysocki
  2013-01-29  2:33   ` Toshi Kani
                     ` (2 subsequent siblings)
  7 siblings, 1 reply; 71+ messages in thread
From: Yinghai Lu @ 2013-01-28 21:54 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Jiang Liu, Toshi Kani, LKML

On Mon, Jan 28, 2013 at 4:58 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Thursday, January 24, 2013 01:26:56 AM Rafael J. Wysocki wrote:
>> Hi All,
>>
>> There is a considerable amount of confusion in the ACPI subsystem about what
>> ACPI drivers are used for.  Namely, some of them are used as "normal" device
>> drivers that bind to devices and handle them using ACPI control methods (like
>> the fan or battery drivers), but some of them are just used for handling
>> namespace events, such as the creation or removal of device nodes (I guess it
>> would be fair to call that an abuse of the driver core).  These two roles are
>> quite distinct, which is particularly visible from the confusion about the role
>> of the .remove() callback.
>>
>> For the "normal" drivers this callback is simply used to handle situations in
>> which the driver needs to be unbound from the device, because one of them
>> (either the device or the driver) is going away.  That operation can't really
>> fail, it just needs to do the necessary cleanup.
>>
>> However, for the namespace events handling "drivers" .remove() means that not
>> only the device node in question, but generally also the whole subtree below it
>> needs to be prepared for removal, which may involve deleting multiple device
>> objects belonging to different bus types and so on and which very well may fail
>> (for example, those devices may be used for such things like swap or they may be
>> memory banks used by the kernel and it may not be safe to remove them at the
>> moment etc.).  Moreover, for these things the removal of the "driver" doesn't
>> really make sense, because it has to be there to handle the namespace events it
>> is designed to handle or else things will go remarkably awry in some places.
>>
>> To resolve all that mess I'd like to do the following, which in part is inspired
>> by the recent Toshi Kani's hotplug framework proposal and in part is based on
>> some discussions I had with Bjorn and others (the code references made below are
>> based on the current contens of linux-pm.git/linux-next).
>>
>> 1) Introduce a special data type for "ACPI namespace event handlers" like:
>>
>> struct acpi_scan_handler {
>>       const struct acpi_device_id *ids;
>>       struct list_head list_node;
>>       int (*attach)(struct acpi_device *adev);
>>       int (*untie)(struct acpi_device *adev);
>>       int (*reclaim)(struct acpi_device *adev);
>>       void (*detach)(struct acpi_device *adev);
>> };
>
> After some reconsideration I think that the "untie" and "reclaim" things won't
> be really useful at this level.  This means that I only need ACPI scan handlers
> to do .attach() and .detach() and all of that becomes really simple, so I don't
> see reason to wait with that change.
>
> The following patches introduce ACPI scan handlers and make some use of them.
>
> [1/4] Introduce struct acpi_scan_handler for configuration tasks depending on
>       device IDs.
>
> [2/4] Make ACPI PCI root driver use struct acpi_scan_handler.
>
> [3/4] Make ACPI PCI IRQ link driver use struct acpi_scan_handler.
>
> [4/4] Use struct acpi_scan_handler for creating platform devices enumerated via ACPI.

Good, esp you move away hard code in scan.c for platform devices.

Test with pci root bus hotplug, and it works well.

So for all 4,

Acked-by: Yinghai Lu <yinghai@kernel.org>

It will have some merging conflicts change in drivers/acpi/internel.h
in pci/next for pci root bus hotplug support.
But it should be very simple to solve it.

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 0/4] ACPI scan handlers
  2013-01-28 21:54   ` [PATCH 0/4] ACPI scan handlers Yinghai Lu
@ 2013-01-29  0:38     ` Rafael J. Wysocki
  0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29  0:38 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Jiang Liu, Toshi Kani, LKML

On Monday, January 28, 2013 01:54:30 PM Yinghai Lu wrote:
> On Mon, Jan 28, 2013 at 4:58 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > On Thursday, January 24, 2013 01:26:56 AM Rafael J. Wysocki wrote:
> >> Hi All,
> >>
> >> There is a considerable amount of confusion in the ACPI subsystem about what
> >> ACPI drivers are used for.  Namely, some of them are used as "normal" device
> >> drivers that bind to devices and handle them using ACPI control methods (like
> >> the fan or battery drivers), but some of them are just used for handling
> >> namespace events, such as the creation or removal of device nodes (I guess it
> >> would be fair to call that an abuse of the driver core).  These two roles are
> >> quite distinct, which is particularly visible from the confusion about the role
> >> of the .remove() callback.
> >>
> >> For the "normal" drivers this callback is simply used to handle situations in
> >> which the driver needs to be unbound from the device, because one of them
> >> (either the device or the driver) is going away.  That operation can't really
> >> fail, it just needs to do the necessary cleanup.
> >>
> >> However, for the namespace events handling "drivers" .remove() means that not
> >> only the device node in question, but generally also the whole subtree below it
> >> needs to be prepared for removal, which may involve deleting multiple device
> >> objects belonging to different bus types and so on and which very well may fail
> >> (for example, those devices may be used for such things like swap or they may be
> >> memory banks used by the kernel and it may not be safe to remove them at the
> >> moment etc.).  Moreover, for these things the removal of the "driver" doesn't
> >> really make sense, because it has to be there to handle the namespace events it
> >> is designed to handle or else things will go remarkably awry in some places.
> >>
> >> To resolve all that mess I'd like to do the following, which in part is inspired
> >> by the recent Toshi Kani's hotplug framework proposal and in part is based on
> >> some discussions I had with Bjorn and others (the code references made below are
> >> based on the current contens of linux-pm.git/linux-next).
> >>
> >> 1) Introduce a special data type for "ACPI namespace event handlers" like:
> >>
> >> struct acpi_scan_handler {
> >>       const struct acpi_device_id *ids;
> >>       struct list_head list_node;
> >>       int (*attach)(struct acpi_device *adev);
> >>       int (*untie)(struct acpi_device *adev);
> >>       int (*reclaim)(struct acpi_device *adev);
> >>       void (*detach)(struct acpi_device *adev);
> >> };
> >
> > After some reconsideration I think that the "untie" and "reclaim" things won't
> > be really useful at this level.  This means that I only need ACPI scan handlers
> > to do .attach() and .detach() and all of that becomes really simple, so I don't
> > see reason to wait with that change.
> >
> > The following patches introduce ACPI scan handlers and make some use of them.
> >
> > [1/4] Introduce struct acpi_scan_handler for configuration tasks depending on
> >       device IDs.
> >
> > [2/4] Make ACPI PCI root driver use struct acpi_scan_handler.
> >
> > [3/4] Make ACPI PCI IRQ link driver use struct acpi_scan_handler.
> >
> > [4/4] Use struct acpi_scan_handler for creating platform devices enumerated via ACPI.
> 
> Good, esp you move away hard code in scan.c for platform devices.
> 
> Test with pci root bus hotplug, and it works well.
> 
> So for all 4,
> 
> Acked-by: Yinghai Lu <yinghai@kernel.org>

Thanks for the review!

> It will have some merging conflicts change in drivers/acpi/internel.h
> in pci/next for pci root bus hotplug support.
> But it should be very simple to solve it.

Yes, it shouldn't be too difficult to resolve them.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
  2013-01-28 12:59   ` [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler Rafael J. Wysocki
@ 2013-01-29  2:04     ` Yasuaki Ishimatsu
  2013-01-29  2:29       ` Yasuaki Ishimatsu
  2013-01-29  2:35     ` Toshi Kani
  1 sibling, 1 reply; 71+ messages in thread
From: Yasuaki Ishimatsu @ 2013-01-29  2:04 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML

Hi Rafael,

2013/01/28 21:59, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Introduce struct acpi_scan_handler for representing objects that
> will do configuration tasks depending on ACPI device nodes'
> hardware IDs (HIDs).
>
> Currently, those tasks are done either directly by the ACPI namespace
> scanning code or by ACPI device drivers designed specifically for
> this purpose.  None of the above is desirable, however, because
> doing that directly in the namespace scanning code makes that code
> overly complicated and difficult to follow and doing that in
> "special" device drivers leads to a great deal of confusion about
> their role and to confusing interactions with the driver core (for
> example, sysfs directories are created for those drivers, but they
> are completely unnecessary and only increase the kernel's memory
> footprint in vain).
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
Acked-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>

I have a comment. Please see below.

>   Documentation/acpi/scan_handlers.txt |   77 +++++++++++++++++++++++++++++++++++
>   drivers/acpi/scan.c                  |   60 ++++++++++++++++++++++++---
>   include/acpi/acpi_bus.h              |   14 ++++++
>   3 files changed, 144 insertions(+), 7 deletions(-)
>
> Index: test/include/acpi/acpi_bus.h
> ===================================================================
> --- test.orig/include/acpi/acpi_bus.h
> +++ test/include/acpi/acpi_bus.h
> @@ -84,6 +84,18 @@ struct acpi_driver;
>   struct acpi_device;
>
>   /*
> + * ACPI Scan Handler
> + * -----------------
> + */
> +
> +struct acpi_scan_handler {
> +	const struct acpi_device_id *ids;
> +	struct list_head list_node;
> +	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> +	void (*detach)(struct acpi_device *dev);
> +};
> +
> +/*
>    * ACPI Driver
>    * -----------
>    */
> @@ -269,6 +281,7 @@ struct acpi_device {
>   	struct acpi_device_wakeup wakeup;
>   	struct acpi_device_perf performance;
>   	struct acpi_device_dir dir;
> +	struct acpi_scan_handler *handler;
>   	struct acpi_driver *driver;
>   	void *driver_data;
>   	struct device dev;
> @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
>   static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
>   	{ return 0; }
>   #endif
> +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
>   int acpi_bus_register_driver(struct acpi_driver *driver);
>   void acpi_bus_unregister_driver(struct acpi_driver *driver);
>   int acpi_bus_scan(acpi_handle handle);
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
>   static LIST_HEAD(acpi_device_list);
>   static LIST_HEAD(acpi_bus_id_list);
>   static DEFINE_MUTEX(acpi_scan_lock);
> +static LIST_HEAD(acpi_scan_handlers_list);
>   DEFINE_MUTEX(acpi_device_lock);
>   LIST_HEAD(acpi_wakeup_device_list);
>
> @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
>   	struct list_head node;
>   };
>
> +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> +{
> +	if (!handler || !handler->attach)
> +		return -EINVAL;
> +
> +	list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> +	return 0;
> +}
> +
>   /*
>    * Creates hid/cid(s) string needed for modalias and uevent
>    * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
>   	return AE_OK;
>   }
>
> +static int acpi_scan_attach_handler(struct acpi_device *device)
> +{
> +	struct acpi_scan_handler *handler;
> +	int ret = 0;
> +
> +	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> +		const struct acpi_device_id *id;
> +
> +		id = __acpi_match_device(device, handler->ids);
> +		if (!id)
> +			continue;
> +
> +		ret = handler->attach(device, id);
> +		if (ret > 0) {
> +			device->handler = handler;
> +			break;
> +		} else if (ret < 0) {
> +			break;
> +		}
> +	}
> +	return ret;
> +}
> +
>   static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
>   					  void *not_used, void **ret_not_used)
>   {
>   	const struct acpi_device_id *id;
> -	acpi_status status = AE_OK;
>   	struct acpi_device *device;
>   	unsigned long long sta_not_used;
> -	int type_not_used;
> +	int ret;
>
>   	/*
>   	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
>   	 * namespace walks prematurely.
>   	 */
> -	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
> +	if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
>   		return AE_OK;
>
>   	if (acpi_bus_get_device(handle, &device))
> @@ -1593,10 +1625,15 @@ static acpi_status acpi_bus_device_attac
>   	if (id) {
>   		/* This is a known good platform device. */
>   		acpi_create_platform_device(device, id->driver_data);
> -	} else if (device_attach(&device->dev) < 0) {
> -		status = AE_CTRL_DEPTH;
> +		return AE_OK;
>   	}
> -	return status;
> +

> +	ret = acpi_scan_attach_handler(device);
> +	if (ret)
> +		return ret > 0 ? AE_OK : AE_CTRL_DEPTH;

acpi_scan_attach_hanlder() returns only 0 or -EINVAL.
How about just return AE_CTRL_DEPTH?

Thanks,
Yasuaki Ishimatsu

> +
> +	ret = device_attach(&device->dev);
> +	return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
>   }
>
>   /**
> @@ -1639,8 +1676,17 @@ static acpi_status acpi_bus_device_detac
>   	struct acpi_device *device = NULL;
>
>   	if (!acpi_bus_get_device(handle, &device)) {
> +		struct acpi_scan_handler *dev_handler = device->handler;
> +
>   		device->removal_type = ACPI_BUS_REMOVAL_EJECT;
> -		device_release_driver(&device->dev);
> +		if (dev_handler) {
> +			if (dev_handler->detach)
> +				dev_handler->detach(device);
> +
> +			device->handler = NULL;
> +		} else {
> +			device_release_driver(&device->dev);
> +		}
>   	}
>   	return AE_OK;
>   }
> Index: test/Documentation/acpi/scan_handlers.txt
> ===================================================================
> --- /dev/null
> +++ test/Documentation/acpi/scan_handlers.txt
> @@ -0,0 +1,77 @@
> +ACPI Scan Handlers
> +
> +Copyright (C) 2012, Intel Corporation
> +Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> +
> +During system initialization and ACPI-based device hot-add, the ACPI namespace
> +is scanned in search of device objects that generally represent various pieces
> +of hardware.  This causes a struct acpi_device object to be created and
> +registered with the driver core for every device object in the ACPI namespace
> +and the hierarchy of those struct acpi_device objects reflects the namespace
> +layout (i.e. parent device objects in the namespace are represented by parent
> +struct acpi_device objects and analogously for their children).  Those struct
> +acpi_device objects are referred to as "device nodes" in what follows, but they
> +should not be confused with struct device_node objects used by the Device Trees
> +parsing code (although their role is analogous to the role of those objects).
> +
> +During ACPI-based device hot-remove device nodes representing pieces of hardware
> +being removed are unregistered and deleted.
> +
> +The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic
> +initialization of device nodes, such as retrieving common configuration
> +information from the device objects represented by them and populating them with
> +appropriate data, but some of them require additional handling after they have
> +been registered.  For example, if the given device node represents a PCI host
> +bridge, its registration should cause the PCI bus under that bridge to be
> +enumerated and PCI devices on that bus to be registered with the driver core.
> +Similarly, if the device node represents a PCI interrupt link, it is necessary
> +to configure that link so that the kernel can use it.
> +
> +Those additional configuration tasks usually depend on the type of the hardware
> +component represented by the given device node which can be determined on the
> +basis of the device node's hardware ID (HID).  They are performed by objects
> +called ACPI scan handlers represented by the following structure:
> +
> +struct acpi_scan_handler {
> +	const struct acpi_device_id *ids;
> +	struct list_head list_node;
> +	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> +	void (*detach)(struct acpi_device *dev);
> +};
> +
> +where ids is the list of IDs of device nodes the given handler is supposed to
> +take care of, list_node is the hook to the global list of ACPI scan handlers
> +maintained by the ACPI core and the .attach() and .detach() callbacks are
> +executed, respectively, after registration of new device nodes and before
> +unregistration of device nodes the handler attached to previously.
> +
> +The namespace scanning function, acpi_bus_scan(), first registers all of the
> +device nodes in the given namespace scope with the driver core.  Then, it tries
> +to match a scan handler against each of them using the ids arrays of the
> +available scan handlers.  If a matching scan handler is found, its .attach()
> +callback is executed for the given device node.  If that callback returns 1,
> +that means that the handler has claimed the device node and is now responsible
> +for carrying out any additional configuration tasks related to it.  It also will
> +be responsible for preparing the device node for unregistration in that case.
> +The device node's handler field is then populated with the address of the scan
> +handler that has claimed it.
> +
> +If the .attach() callback returns 0, it means that the device node is not
> +interesting to the given scan handler and may be matched against the next scan
> +handler in the list.  If it returns a (negative) error code, that means that
> +the namespace scan should be terminated due to a serious error.  The error code
> +returned should then reflect the type of the error.
> +
> +The namespace trimming function, acpi_bus_trim(), first executes .detach()
> +callbacks from the scan handlers of all device nodes in the given namespace
> +scope (if they have scan handlers).  Next, it unregisters all of the device
> +nodes in that scope.
> +
> +ACPI scan handlers can be added to the list maintained by the ACPI core with the
> +help of the acpi_scan_add_handler() function taking a pointer to the new scan
> +handler as an argument.  The order in which scan handlers are added to the list
> +is the order in which they are matched against device nodes during namespace
> +scans.
> +
> +All scan handles must be added to the list before acpi_bus_scan() is run for the
> +first time and they cannot be removed from it.
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
  2013-01-28 13:01   ` [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices Rafael J. Wysocki
@ 2013-01-29  2:20     ` Yasuaki Ishimatsu
  2013-01-29 11:36       ` Rafael J. Wysocki
  2013-01-29  7:35     ` [PATCH " Mika Westerberg
  2013-01-29  8:05     ` Mika Westerberg
  2 siblings, 1 reply; 71+ messages in thread
From: Yasuaki Ishimatsu @ 2013-01-29  2:20 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML

Hi Rafael,

2013/01/28 22:01, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Currently, the ACPI namespace scanning code creates platform device
> objects for ACPI device nodes whose IDs match the contents of the
> acpi_platform_device_ids[] table.  However, this adds a superfluous
> special case into acpi_bus_device_attach() and makes it more
> difficult to follow than it has to be.  It also will make it more
> difficult to implement removal code for those platform device objects
> in the future.
>
> For the above reasons, introduce a struct acpi_scan_handler object
> for creating platform devices and move the code related to that from
> acpi_bus_device_attach() to the .attach() callback of that object.
> Also move the acpi_platform_device_ids[] table to acpi_platform.c.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>   drivers/acpi/acpi_platform.c |   55 +++++++++++++++++++++++++++++++++++--------
>   drivers/acpi/internal.h      |    7 -----
>   drivers/acpi/scan.c          |   30 -----------------------
>   3 files changed, 47 insertions(+), 45 deletions(-)
>
> Index: test/drivers/acpi/acpi_platform.c
> ===================================================================
> --- test.orig/drivers/acpi/acpi_platform.c
> +++ test/drivers/acpi/acpi_platform.c
> @@ -22,6 +22,30 @@
>
>   ACPI_MODULE_NAME("platform");
>
> +/* Flags for acpi_create_platform_device */
> +#define ACPI_PLATFORM_CLK	BIT(0)
> +
> +/*
> + * The following ACPI IDs are known to be suitable for representing as
> + * platform devices.
> + */
> +static const struct acpi_device_id acpi_platform_device_ids[] = {
> +
> +	{ "PNP0D40" },
> +
> +	/* Haswell LPSS devices */
> +	{ "INT33C0", ACPI_PLATFORM_CLK },
> +	{ "INT33C1", ACPI_PLATFORM_CLK },
> +	{ "INT33C2", ACPI_PLATFORM_CLK },
> +	{ "INT33C3", ACPI_PLATFORM_CLK },
> +	{ "INT33C4", ACPI_PLATFORM_CLK },
> +	{ "INT33C5", ACPI_PLATFORM_CLK },
> +	{ "INT33C6", ACPI_PLATFORM_CLK },
> +	{ "INT33C7", ACPI_PLATFORM_CLK },
> +
> +	{ }
> +};
> +
>   static int acpi_create_platform_clks(struct acpi_device *adev)
>   {
>   	static struct platform_device *pdev;
> @@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
>   /**
>    * acpi_create_platform_device - Create platform device for ACPI device node
>    * @adev: ACPI device node to create a platform device for.
> - * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
> - *	   devices.
> + * @id: ACPI device ID used to match @adev.
>    *
>    * Check if the given @adev can be represented as a platform device and, if
>    * that's the case, create and register a platform device, populate its common
> @@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
>    *
>    * Name of the platform device will be the same as @adev's.
>    */
> -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
> -						    unsigned long flags)
> +static int acpi_create_platform_device(struct acpi_device *adev,
> +				       const struct acpi_device_id *id)
>   {
> +	unsigned long flags = id->driver_data;
>   	struct platform_device *pdev = NULL;
>   	struct acpi_device *acpi_parent;
>   	struct platform_device_info pdevinfo;
> @@ -59,25 +83,26 @@ struct platform_device *acpi_create_plat
>   	struct resource *resources;
>   	int count;
>

> -	if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
> +	if (flags & ACPI_PLATFORM_CLK) {
> +		int ret = acpi_create_platform_clks(adev);
>   		dev_err(&adev->dev, "failed to create clocks\n");
> -		return NULL;
> +		return ret;
>   	}

If (flag & ACPI_PLATFORM_CLK) is true, the acpi_create_platform_device()
always retruns with dev_err() messages. Why?

Thanks,
Yasuaki Ishimatsu

>
>   	/* If the ACPI node already has a physical device attached, skip it. */
>   	if (adev->physical_node_count)
> -		return NULL;
> +		return 0;
>
>   	INIT_LIST_HEAD(&resource_list);
>   	count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
>   	if (count <= 0)
> -		return NULL;
> +		return 0;
>
>   	resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
>   	if (!resources) {
>   		dev_err(&adev->dev, "No memory for resources\n");
>   		acpi_dev_free_resource_list(&resource_list);
> -		return NULL;
> +		return -ENOMEM;
>   	}
>   	count = 0;
>   	list_for_each_entry(rentry, &resource_list, node)
> @@ -123,5 +148,15 @@ struct platform_device *acpi_create_plat
>   	}
>
>   	kfree(resources);
> -	return pdev;
> +	return 1;
> +}
> +
> +static struct acpi_scan_handler platform_handler = {
> +	.ids = acpi_platform_device_ids,
> +	.attach = acpi_create_platform_device,
> +};
> +
> +void __init acpi_platform_init(void)
> +{
> +	acpi_scan_add_handler(&platform_handler);
>   }
> Index: test/drivers/acpi/internal.h
> ===================================================================
> --- test.orig/drivers/acpi/internal.h
> +++ test/drivers/acpi/internal.h
> @@ -27,6 +27,7 @@ int init_acpi_device_notify(void);
>   int acpi_scan_init(void);
>   void acpi_pci_root_init(void);
>   void acpi_pci_link_init(void);
> +void acpi_platform_init(void);
>   int acpi_sysfs_init(void);
>   void acpi_csrt_init(void);
>
> @@ -119,10 +120,4 @@ static inline void suspend_nvs_restore(v
>     -------------------------------------------------------------------------- */
>   struct platform_device;
>
> -/* Flags for acpi_create_platform_device */
> -#define ACPI_PLATFORM_CLK	BIT(0)
> -
> -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
> -						    unsigned long flags);
> -
>   #endif /* _ACPI_INTERNAL_H_ */
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -29,27 +29,6 @@ extern struct acpi_device *acpi_root;
>
>   static const char *dummy_hid = "device";
>
> -/*
> - * The following ACPI IDs are known to be suitable for representing as
> - * platform devices.
> - */
> -static const struct acpi_device_id acpi_platform_device_ids[] = {
> -
> -	{ "PNP0D40" },
> -
> -	/* Haswell LPSS devices */
> -	{ "INT33C0", ACPI_PLATFORM_CLK },
> -	{ "INT33C1", ACPI_PLATFORM_CLK },
> -	{ "INT33C2", ACPI_PLATFORM_CLK },
> -	{ "INT33C3", ACPI_PLATFORM_CLK },
> -	{ "INT33C4", ACPI_PLATFORM_CLK },
> -	{ "INT33C5", ACPI_PLATFORM_CLK },
> -	{ "INT33C6", ACPI_PLATFORM_CLK },
> -	{ "INT33C7", ACPI_PLATFORM_CLK },
> -
> -	{ }
> -};
> -
>   static LIST_HEAD(acpi_device_list);
>   static LIST_HEAD(acpi_bus_id_list);
>   static DEFINE_MUTEX(acpi_scan_lock);
> @@ -1606,7 +1585,6 @@ static int acpi_scan_attach_handler(stru
>   static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
>   					  void *not_used, void **ret_not_used)
>   {
> -	const struct acpi_device_id *id;
>   	struct acpi_device *device;
>   	unsigned long long sta_not_used;
>   	int ret;
> @@ -1621,13 +1599,6 @@ static acpi_status acpi_bus_device_attac
>   	if (acpi_bus_get_device(handle, &device))
>   		return AE_CTRL_DEPTH;
>
> -	id = __acpi_match_device(device, acpi_platform_device_ids);
> -	if (id) {
> -		/* This is a known good platform device. */
> -		acpi_create_platform_device(device, id->driver_data);
> -		return AE_OK;
> -	}
> -
>   	ret = acpi_scan_attach_handler(device);
>   	if (ret)
>   		return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
> @@ -1775,6 +1746,7 @@ int __init acpi_scan_init(void)
>
>   	acpi_pci_root_init();
>   	acpi_pci_link_init();
> +	acpi_platform_init();
>   	acpi_csrt_init();
>
>   	/*
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
  2013-01-29  2:04     ` Yasuaki Ishimatsu
@ 2013-01-29  2:29       ` Yasuaki Ishimatsu
  0 siblings, 0 replies; 71+ messages in thread
From: Yasuaki Ishimatsu @ 2013-01-29  2:29 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML

2013/01/29 11:04, Yasuaki Ishimatsu wrote:
> Hi Rafael,
>
> 2013/01/28 21:59, Rafael J. Wysocki wrote:
>> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>
>> Introduce struct acpi_scan_handler for representing objects that
>> will do configuration tasks depending on ACPI device nodes'
>> hardware IDs (HIDs).
>>
>> Currently, those tasks are done either directly by the ACPI namespace
>> scanning code or by ACPI device drivers designed specifically for
>> this purpose.  None of the above is desirable, however, because
>> doing that directly in the namespace scanning code makes that code
>> overly complicated and difficult to follow and doing that in
>> "special" device drivers leads to a great deal of confusion about
>> their role and to confusing interactions with the driver core (for
>> example, sysfs directories are created for those drivers, but they
>> are completely unnecessary and only increase the kernel's memory
>> footprint in vain).
>>
>> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>> ---
> Acked-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
>
> I have a comment. Please see below.
>
>>   Documentation/acpi/scan_handlers.txt |   77 +++++++++++++++++++++++++++++++++++
>>   drivers/acpi/scan.c                  |   60 ++++++++++++++++++++++++---
>>   include/acpi/acpi_bus.h              |   14 ++++++
>>   3 files changed, 144 insertions(+), 7 deletions(-)
>>
>> Index: test/include/acpi/acpi_bus.h
>> ===================================================================
>> --- test.orig/include/acpi/acpi_bus.h
>> +++ test/include/acpi/acpi_bus.h
>> @@ -84,6 +84,18 @@ struct acpi_driver;
>>   struct acpi_device;
>>
>>   /*
>> + * ACPI Scan Handler
>> + * -----------------
>> + */
>> +
>> +struct acpi_scan_handler {
>> +    const struct acpi_device_id *ids;
>> +    struct list_head list_node;
>> +    int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
>> +    void (*detach)(struct acpi_device *dev);
>> +};
>> +
>> +/*
>>    * ACPI Driver
>>    * -----------
>>    */
>> @@ -269,6 +281,7 @@ struct acpi_device {
>>       struct acpi_device_wakeup wakeup;
>>       struct acpi_device_perf performance;
>>       struct acpi_device_dir dir;
>> +    struct acpi_scan_handler *handler;
>>       struct acpi_driver *driver;
>>       void *driver_data;
>>       struct device dev;
>> @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
>>   static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
>>       { return 0; }
>>   #endif
>> +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
>>   int acpi_bus_register_driver(struct acpi_driver *driver);
>>   void acpi_bus_unregister_driver(struct acpi_driver *driver);
>>   int acpi_bus_scan(acpi_handle handle);
>> Index: test/drivers/acpi/scan.c
>> ===================================================================
>> --- test.orig/drivers/acpi/scan.c
>> +++ test/drivers/acpi/scan.c
>> @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
>>   static LIST_HEAD(acpi_device_list);
>>   static LIST_HEAD(acpi_bus_id_list);
>>   static DEFINE_MUTEX(acpi_scan_lock);
>> +static LIST_HEAD(acpi_scan_handlers_list);
>>   DEFINE_MUTEX(acpi_device_lock);
>>   LIST_HEAD(acpi_wakeup_device_list);
>>
>> @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
>>       struct list_head node;
>>   };
>>
>> +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
>> +{
>> +    if (!handler || !handler->attach)
>> +        return -EINVAL;
>> +
>> +    list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
>> +    return 0;
>> +}
>> +
>>   /*
>>    * Creates hid/cid(s) string needed for modalias and uevent
>>    * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
>> @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
>>       return AE_OK;
>>   }
>>
>> +static int acpi_scan_attach_handler(struct acpi_device *device)
>> +{
>> +    struct acpi_scan_handler *handler;
>> +    int ret = 0;
>> +
>> +    list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
>> +        const struct acpi_device_id *id;
>> +
>> +        id = __acpi_match_device(device, handler->ids);
>> +        if (!id)
>> +            continue;
>> +
>> +        ret = handler->attach(device, id);
>> +        if (ret > 0) {
>> +            device->handler = handler;
>> +            break;
>> +        } else if (ret < 0) {
>> +            break;
>> +        }
>> +    }
>> +    return ret;
>> +}
>> +
>>   static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
>>                         void *not_used, void **ret_not_used)
>>   {
>>       const struct acpi_device_id *id;
>> -    acpi_status status = AE_OK;
>>       struct acpi_device *device;
>>       unsigned long long sta_not_used;
>> -    int type_not_used;
>> +    int ret;
>>
>>       /*
>>        * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
>>        * namespace walks prematurely.
>>        */
>> -    if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
>> +    if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
>>           return AE_OK;
>>
>>       if (acpi_bus_get_device(handle, &device))
>> @@ -1593,10 +1625,15 @@ static acpi_status acpi_bus_device_attac
>>       if (id) {
>>           /* This is a known good platform device. */
>>           acpi_create_platform_device(device, id->driver_data);
>> -    } else if (device_attach(&device->dev) < 0) {
>> -        status = AE_CTRL_DEPTH;
>> +        return AE_OK;
>>       }
>> -    return status;
>> +
>
>> +    ret = acpi_scan_attach_handler(device);
>> +    if (ret)
>> +        return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
>
> acpi_scan_attach_hanlder() returns only 0 or -EINVAL.
> How about just return AE_CTRL_DEPTH?

I am wrong. Please forget it.

Thanks,
Yasuaki Ishimatsu

>
> Thanks,
> Yasuaki Ishimatsu
>
>> +
>> +    ret = device_attach(&device->dev);
>> +    return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
>>   }
>>
>>   /**
>> @@ -1639,8 +1676,17 @@ static acpi_status acpi_bus_device_detac
>>       struct acpi_device *device = NULL;
>>
>>       if (!acpi_bus_get_device(handle, &device)) {
>> +        struct acpi_scan_handler *dev_handler = device->handler;
>> +
>>           device->removal_type = ACPI_BUS_REMOVAL_EJECT;
>> -        device_release_driver(&device->dev);
>> +        if (dev_handler) {
>> +            if (dev_handler->detach)
>> +                dev_handler->detach(device);
>> +
>> +            device->handler = NULL;
>> +        } else {
>> +            device_release_driver(&device->dev);
>> +        }
>>       }
>>       return AE_OK;
>>   }
>> Index: test/Documentation/acpi/scan_handlers.txt
>> ===================================================================
>> --- /dev/null
>> +++ test/Documentation/acpi/scan_handlers.txt
>> @@ -0,0 +1,77 @@
>> +ACPI Scan Handlers
>> +
>> +Copyright (C) 2012, Intel Corporation
>> +Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>> +
>> +During system initialization and ACPI-based device hot-add, the ACPI namespace
>> +is scanned in search of device objects that generally represent various pieces
>> +of hardware.  This causes a struct acpi_device object to be created and
>> +registered with the driver core for every device object in the ACPI namespace
>> +and the hierarchy of those struct acpi_device objects reflects the namespace
>> +layout (i.e. parent device objects in the namespace are represented by parent
>> +struct acpi_device objects and analogously for their children).  Those struct
>> +acpi_device objects are referred to as "device nodes" in what follows, but they
>> +should not be confused with struct device_node objects used by the Device Trees
>> +parsing code (although their role is analogous to the role of those objects).
>> +
>> +During ACPI-based device hot-remove device nodes representing pieces of hardware
>> +being removed are unregistered and deleted.
>> +
>> +The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic
>> +initialization of device nodes, such as retrieving common configuration
>> +information from the device objects represented by them and populating them with
>> +appropriate data, but some of them require additional handling after they have
>> +been registered.  For example, if the given device node represents a PCI host
>> +bridge, its registration should cause the PCI bus under that bridge to be
>> +enumerated and PCI devices on that bus to be registered with the driver core.
>> +Similarly, if the device node represents a PCI interrupt link, it is necessary
>> +to configure that link so that the kernel can use it.
>> +
>> +Those additional configuration tasks usually depend on the type of the hardware
>> +component represented by the given device node which can be determined on the
>> +basis of the device node's hardware ID (HID).  They are performed by objects
>> +called ACPI scan handlers represented by the following structure:
>> +
>> +struct acpi_scan_handler {
>> +    const struct acpi_device_id *ids;
>> +    struct list_head list_node;
>> +    int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
>> +    void (*detach)(struct acpi_device *dev);
>> +};
>> +
>> +where ids is the list of IDs of device nodes the given handler is supposed to
>> +take care of, list_node is the hook to the global list of ACPI scan handlers
>> +maintained by the ACPI core and the .attach() and .detach() callbacks are
>> +executed, respectively, after registration of new device nodes and before
>> +unregistration of device nodes the handler attached to previously.
>> +
>> +The namespace scanning function, acpi_bus_scan(), first registers all of the
>> +device nodes in the given namespace scope with the driver core.  Then, it tries
>> +to match a scan handler against each of them using the ids arrays of the
>> +available scan handlers.  If a matching scan handler is found, its .attach()
>> +callback is executed for the given device node.  If that callback returns 1,
>> +that means that the handler has claimed the device node and is now responsible
>> +for carrying out any additional configuration tasks related to it.  It also will
>> +be responsible for preparing the device node for unregistration in that case.
>> +The device node's handler field is then populated with the address of the scan
>> +handler that has claimed it.
>> +
>> +If the .attach() callback returns 0, it means that the device node is not
>> +interesting to the given scan handler and may be matched against the next scan
>> +handler in the list.  If it returns a (negative) error code, that means that
>> +the namespace scan should be terminated due to a serious error.  The error code
>> +returned should then reflect the type of the error.
>> +
>> +The namespace trimming function, acpi_bus_trim(), first executes .detach()
>> +callbacks from the scan handlers of all device nodes in the given namespace
>> +scope (if they have scan handlers).  Next, it unregisters all of the device
>> +nodes in that scope.
>> +
>> +ACPI scan handlers can be added to the list maintained by the ACPI core with the
>> +help of the acpi_scan_add_handler() function taking a pointer to the new scan
>> +handler as an argument.  The order in which scan handlers are added to the list
>> +is the order in which they are matched against device nodes during namespace
>> +scans.
>> +
>> +All scan handles must be added to the list before acpi_bus_scan() is run for the
>> +first time and they cannot be removed from it.
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 0/4] ACPI scan handlers
  2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
                     ` (4 preceding siblings ...)
  2013-01-28 21:54   ` [PATCH 0/4] ACPI scan handlers Yinghai Lu
@ 2013-01-29  2:33   ` Toshi Kani
  2013-01-30  1:58   ` Toshi Kani
  2013-02-03 23:45   ` [PATCH 0/2] ACPI scan handler for memory hotplug and container simplification Rafael J. Wysocki
  7 siblings, 0 replies; 71+ messages in thread
From: Toshi Kani @ 2013-01-29  2:33 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Mon, 2013-01-28 at 13:58 +0100, Rafael J. Wysocki wrote:
> On Thursday, January 24, 2013 01:26:56 AM Rafael J. Wysocki wrote:
> > Hi All,
> > 
> > There is a considerable amount of confusion in the ACPI subsystem about what
> > ACPI drivers are used for.  Namely, some of them are used as "normal" device
> > drivers that bind to devices and handle them using ACPI control methods (like
> > the fan or battery drivers), but some of them are just used for handling
> > namespace events, such as the creation or removal of device nodes (I guess it
> > would be fair to call that an abuse of the driver core).  These two roles are
> > quite distinct, which is particularly visible from the confusion about the role
> > of the .remove() callback.
> > 
> > For the "normal" drivers this callback is simply used to handle situations in
> > which the driver needs to be unbound from the device, because one of them
> > (either the device or the driver) is going away.  That operation can't really
> > fail, it just needs to do the necessary cleanup.
> > 
> > However, for the namespace events handling "drivers" .remove() means that not
> > only the device node in question, but generally also the whole subtree below it
> > needs to be prepared for removal, which may involve deleting multiple device
> > objects belonging to different bus types and so on and which very well may fail
> > (for example, those devices may be used for such things like swap or they may be
> > memory banks used by the kernel and it may not be safe to remove them at the
> > moment etc.).  Moreover, for these things the removal of the "driver" doesn't
> > really make sense, because it has to be there to handle the namespace events it
> > is designed to handle or else things will go remarkably awry in some places.
> > 
> > To resolve all that mess I'd like to do the following, which in part is inspired
> > by the recent Toshi Kani's hotplug framework proposal and in part is based on
> > some discussions I had with Bjorn and others (the code references made below are
> > based on the current contens of linux-pm.git/linux-next).
> > 
> > 1) Introduce a special data type for "ACPI namespace event handlers" like:
> > 
> > struct acpi_scan_handler {
> > 	const struct acpi_device_id *ids;
> > 	struct list_head list_node;
> > 	int (*attach)(struct acpi_device *adev);
> > 	int (*untie)(struct acpi_device *adev);
> > 	int (*reclaim)(struct acpi_device *adev);
> > 	void (*detach)(struct acpi_device *adev);
> > };
> 
> After some reconsideration I think that the "untie" and "reclaim" things won't
> be really useful at this level.  This means that I only need ACPI scan handlers
> to do .attach() and .detach() and all of that becomes really simple, so I don't
> see reason to wait with that change.

That's great.  I agree with you.  The name of attach/detach() also
clarifies the purpose of the interfaces well.  

Thanks,
-Toshi

ps.
I am tied up this week and will be somewhat slow to respond...


> 
> The following patches introduce ACPI scan handlers and make some use of them.
> 
> [1/4] Introduce struct acpi_scan_handler for configuration tasks depending on
>       device IDs.
> 
> [2/4] Make ACPI PCI root driver use struct acpi_scan_handler.
> 
> [3/4] Make ACPI PCI IRQ link driver use struct acpi_scan_handler.
> 
> [4/4] Use struct acpi_scan_handler for creating platform devices enumerated via ACPI.
> 
> Thanks,
> Rafael
> 
> 



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
  2013-01-28 12:59   ` [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler Rafael J. Wysocki
  2013-01-29  2:04     ` Yasuaki Ishimatsu
@ 2013-01-29  2:35     ` Toshi Kani
  2013-01-29 11:28       ` Rafael J. Wysocki
  1 sibling, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-01-29  2:35 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Introduce struct acpi_scan_handler for representing objects that
> will do configuration tasks depending on ACPI device nodes'
> hardware IDs (HIDs).
> 
> Currently, those tasks are done either directly by the ACPI namespace
> scanning code or by ACPI device drivers designed specifically for
> this purpose.  None of the above is desirable, however, because
> doing that directly in the namespace scanning code makes that code
> overly complicated and difficult to follow and doing that in
> "special" device drivers leads to a great deal of confusion about
> their role and to confusing interactions with the driver core (for
> example, sysfs directories are created for those drivers, but they
> are completely unnecessary and only increase the kernel's memory
> footprint in vain).
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  Documentation/acpi/scan_handlers.txt |   77 +++++++++++++++++++++++++++++++++++
>  drivers/acpi/scan.c                  |   60 ++++++++++++++++++++++++---
>  include/acpi/acpi_bus.h              |   14 ++++++
>  3 files changed, 144 insertions(+), 7 deletions(-)
> 
> Index: test/include/acpi/acpi_bus.h
> ===================================================================
> --- test.orig/include/acpi/acpi_bus.h
> +++ test/include/acpi/acpi_bus.h
> @@ -84,6 +84,18 @@ struct acpi_driver;
>  struct acpi_device;
>  
>  /*
> + * ACPI Scan Handler
> + * -----------------
> + */
> +
> +struct acpi_scan_handler {
> +	const struct acpi_device_id *ids;
> +	struct list_head list_node;
> +	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> +	void (*detach)(struct acpi_device *dev);
> +};
> +
> +/*
>   * ACPI Driver
>   * -----------
>   */
> @@ -269,6 +281,7 @@ struct acpi_device {
>  	struct acpi_device_wakeup wakeup;
>  	struct acpi_device_perf performance;
>  	struct acpi_device_dir dir;
> +	struct acpi_scan_handler *handler;
>  	struct acpi_driver *driver;
>  	void *driver_data;
>  	struct device dev;
> @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
>  static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
>  	{ return 0; }
>  #endif
> +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
>  int acpi_bus_register_driver(struct acpi_driver *driver);
>  void acpi_bus_unregister_driver(struct acpi_driver *driver);
>  int acpi_bus_scan(acpi_handle handle);
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
>  static LIST_HEAD(acpi_device_list);
>  static LIST_HEAD(acpi_bus_id_list);
>  static DEFINE_MUTEX(acpi_scan_lock);
> +static LIST_HEAD(acpi_scan_handlers_list);
>  DEFINE_MUTEX(acpi_device_lock);
>  LIST_HEAD(acpi_wakeup_device_list);
>  
> @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
>  	struct list_head node;
>  };
>  
> +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> +{
> +	if (!handler || !handler->attach)
> +		return -EINVAL;
> +
> +	list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> +	return 0;
> +}
> +
>  /*
>   * Creates hid/cid(s) string needed for modalias and uevent
>   * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
>  	return AE_OK;
>  }
>  
> +static int acpi_scan_attach_handler(struct acpi_device *device)
> +{
> +	struct acpi_scan_handler *handler;
> +	int ret = 0;
> +
> +	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> +		const struct acpi_device_id *id;
> +
> +		id = __acpi_match_device(device, handler->ids);
> +		if (!id)
> +			continue;
> +
> +		ret = handler->attach(device, id);
> +		if (ret > 0) {
> +			device->handler = handler;
> +			break;
> +		} else if (ret < 0) {
> +			break;
> +		}
> +	}
> +	return ret;
> +}

Now that we have full control over the attach logic, it would be great
if we can update it to match with the ACPI spec -- HID has priority over
CIDs, and CIDs are also listed in their priority.  For example, Device-X
has HID and CID.  In this case, this Device-X should be attached to
Handler-A since it supports HID.  The current logic simply chooses a
handler whichever registered before.  

Device-X: HID PNPID-A, CID PNPID-B
Handler-A: PNPID-A
Handler-B: PNPID-B

So, the attach logic should be something like:

list_for_each_entry(hwid, acpi_device->pnp.ids,) {
	list_for_each_entry(,&acpi_scan_handlers_list,)
		check if this handler supports a given hwid
}


Thanks,
-Toshi


> +
>  static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
>  					  void *not_used, void **ret_not_used)
>  {
>  	const struct acpi_device_id *id;
> -	acpi_status status = AE_OK;
>  	struct acpi_device *device;
>  	unsigned long long sta_not_used;
> -	int type_not_used;
> +	int ret;
>  
>  	/*
>  	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
>  	 * namespace walks prematurely.
>  	 */
> -	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
> +	if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
>  		return AE_OK;
>  
>  	if (acpi_bus_get_device(handle, &device))
> @@ -1593,10 +1625,15 @@ static acpi_status acpi_bus_device_attac
>  	if (id) {
>  		/* This is a known good platform device. */
>  		acpi_create_platform_device(device, id->driver_data);
> -	} else if (device_attach(&device->dev) < 0) {
> -		status = AE_CTRL_DEPTH;
> +		return AE_OK;
>  	}
> -	return status;
> +
> +	ret = acpi_scan_attach_handler(device);
> +	if (ret)
> +		return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
> +
> +	ret = device_attach(&device->dev);
> +	return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
>  }
>  
>  /**
> @@ -1639,8 +1676,17 @@ static acpi_status acpi_bus_device_detac
>  	struct acpi_device *device = NULL;
>  
>  	if (!acpi_bus_get_device(handle, &device)) {
> +		struct acpi_scan_handler *dev_handler = device->handler;
> +
>  		device->removal_type = ACPI_BUS_REMOVAL_EJECT;
> -		device_release_driver(&device->dev);
> +		if (dev_handler) {
> +			if (dev_handler->detach)
> +				dev_handler->detach(device);
> +
> +			device->handler = NULL;
> +		} else {
> +			device_release_driver(&device->dev);
> +		}
>  	}
>  	return AE_OK;
>  }
> Index: test/Documentation/acpi/scan_handlers.txt
> ===================================================================
> --- /dev/null
> +++ test/Documentation/acpi/scan_handlers.txt
> @@ -0,0 +1,77 @@
> +ACPI Scan Handlers
> +
> +Copyright (C) 2012, Intel Corporation
> +Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> +
> +During system initialization and ACPI-based device hot-add, the ACPI namespace
> +is scanned in search of device objects that generally represent various pieces
> +of hardware.  This causes a struct acpi_device object to be created and
> +registered with the driver core for every device object in the ACPI namespace
> +and the hierarchy of those struct acpi_device objects reflects the namespace
> +layout (i.e. parent device objects in the namespace are represented by parent
> +struct acpi_device objects and analogously for their children).  Those struct
> +acpi_device objects are referred to as "device nodes" in what follows, but they
> +should not be confused with struct device_node objects used by the Device Trees
> +parsing code (although their role is analogous to the role of those objects).
> +
> +During ACPI-based device hot-remove device nodes representing pieces of hardware
> +being removed are unregistered and deleted.
> +
> +The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic
> +initialization of device nodes, such as retrieving common configuration
> +information from the device objects represented by them and populating them with
> +appropriate data, but some of them require additional handling after they have
> +been registered.  For example, if the given device node represents a PCI host
> +bridge, its registration should cause the PCI bus under that bridge to be
> +enumerated and PCI devices on that bus to be registered with the driver core.
> +Similarly, if the device node represents a PCI interrupt link, it is necessary
> +to configure that link so that the kernel can use it.
> +
> +Those additional configuration tasks usually depend on the type of the hardware
> +component represented by the given device node which can be determined on the
> +basis of the device node's hardware ID (HID).  They are performed by objects
> +called ACPI scan handlers represented by the following structure:
> +
> +struct acpi_scan_handler {
> +	const struct acpi_device_id *ids;
> +	struct list_head list_node;
> +	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> +	void (*detach)(struct acpi_device *dev);
> +};
> +
> +where ids is the list of IDs of device nodes the given handler is supposed to
> +take care of, list_node is the hook to the global list of ACPI scan handlers
> +maintained by the ACPI core and the .attach() and .detach() callbacks are
> +executed, respectively, after registration of new device nodes and before
> +unregistration of device nodes the handler attached to previously.
> +
> +The namespace scanning function, acpi_bus_scan(), first registers all of the
> +device nodes in the given namespace scope with the driver core.  Then, it tries
> +to match a scan handler against each of them using the ids arrays of the
> +available scan handlers.  If a matching scan handler is found, its .attach()
> +callback is executed for the given device node.  If that callback returns 1,
> +that means that the handler has claimed the device node and is now responsible
> +for carrying out any additional configuration tasks related to it.  It also will
> +be responsible for preparing the device node for unregistration in that case.
> +The device node's handler field is then populated with the address of the scan
> +handler that has claimed it.
> +
> +If the .attach() callback returns 0, it means that the device node is not
> +interesting to the given scan handler and may be matched against the next scan
> +handler in the list.  If it returns a (negative) error code, that means that
> +the namespace scan should be terminated due to a serious error.  The error code
> +returned should then reflect the type of the error.
> +
> +The namespace trimming function, acpi_bus_trim(), first executes .detach()
> +callbacks from the scan handlers of all device nodes in the given namespace
> +scope (if they have scan handlers).  Next, it unregisters all of the device
> +nodes in that scope.
> +
> +ACPI scan handlers can be added to the list maintained by the ACPI core with the
> +help of the acpi_scan_add_handler() function taking a pointer to the new scan
> +handler as an argument.  The order in which scan handlers are added to the list
> +is the order in which they are matched against device nodes during namespace
> +scans.
> +
> +All scan handles must be added to the list before acpi_bus_scan() is run for the
> +first time and they cannot be removed from it.
> 



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
  2013-01-28 13:01   ` [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices Rafael J. Wysocki
  2013-01-29  2:20     ` Yasuaki Ishimatsu
@ 2013-01-29  7:35     ` Mika Westerberg
  2013-01-29 12:01       ` Rafael J. Wysocki
  2013-01-29  8:05     ` Mika Westerberg
  2 siblings, 1 reply; 71+ messages in thread
From: Mika Westerberg @ 2013-01-29  7:35 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

On Mon, Jan 28, 2013 at 02:01:14PM +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Currently, the ACPI namespace scanning code creates platform device
> objects for ACPI device nodes whose IDs match the contents of the
> acpi_platform_device_ids[] table.  However, this adds a superfluous
> special case into acpi_bus_device_attach() and makes it more
> difficult to follow than it has to be.  It also will make it more
> difficult to implement removal code for those platform device objects
> in the future.
> 
> For the above reasons, introduce a struct acpi_scan_handler object
> for creating platform devices and move the code related to that from
> acpi_bus_device_attach() to the .attach() callback of that object.
> Also move the acpi_platform_device_ids[] table to acpi_platform.c.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

I've tested this with Haswell machine and once you fix the problem pointed
out by Yasuaki Ishimat (returning always when ACPI_PLATFORM_CLK is set) the
platform device creation works well. This is a nice cleanup and localizes
the hard coded platform device table in one file making maintenance bit
easier.

Feel free to add:

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
  2013-01-28 13:01   ` [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices Rafael J. Wysocki
  2013-01-29  2:20     ` Yasuaki Ishimatsu
  2013-01-29  7:35     ` [PATCH " Mika Westerberg
@ 2013-01-29  8:05     ` Mika Westerberg
  2013-01-29 12:02       ` Rafael J. Wysocki
  2 siblings, 1 reply; 71+ messages in thread
From: Mika Westerberg @ 2013-01-29  8:05 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

On Mon, Jan 28, 2013 at 02:01:14PM +0100, Rafael J. Wysocki wrote:
> +/* Flags for acpi_create_platform_device */
> +#define ACPI_PLATFORM_CLK	BIT(0)
> +
> +/*
> + * The following ACPI IDs are known to be suitable for representing as
> + * platform devices.
> + */
> +static const struct acpi_device_id acpi_platform_device_ids[] = {
> +
> +	{ "PNP0D40" },
> +
> +	/* Haswell LPSS devices */
> +	{ "INT33C0", ACPI_PLATFORM_CLK },
> +	{ "INT33C1", ACPI_PLATFORM_CLK },
> +	{ "INT33C2", ACPI_PLATFORM_CLK },
> +	{ "INT33C3", ACPI_PLATFORM_CLK },
> +	{ "INT33C4", ACPI_PLATFORM_CLK },
> +	{ "INT33C5", ACPI_PLATFORM_CLK },
> +	{ "INT33C6", ACPI_PLATFORM_CLK },
> +	{ "INT33C7", ACPI_PLATFORM_CLK },
> +
> +	{ }
> +};

Now that we have everything the platform support code needs in a single
file, should we instead of setting flags and comparing strings like
"INT33C" to find out are we running on Lynxpoint, pass function pointer
that gets called when corresponding device gets created? Something like:

	{ "INT33C0", lpt_clks_init },
	...

Or do you think we need to keep the flags still?

I can prepare a patch if this turns out to be sensible thing to do.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
  2013-01-29  2:35     ` Toshi Kani
@ 2013-01-29 11:28       ` Rafael J. Wysocki
  2013-01-29 14:50         ` Toshi Kani
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 11:28 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> > Introduce struct acpi_scan_handler for representing objects that
> > will do configuration tasks depending on ACPI device nodes'
> > hardware IDs (HIDs).
> > 
> > Currently, those tasks are done either directly by the ACPI namespace
> > scanning code or by ACPI device drivers designed specifically for
> > this purpose.  None of the above is desirable, however, because
> > doing that directly in the namespace scanning code makes that code
> > overly complicated and difficult to follow and doing that in
> > "special" device drivers leads to a great deal of confusion about
> > their role and to confusing interactions with the driver core (for
> > example, sysfs directories are created for those drivers, but they
> > are completely unnecessary and only increase the kernel's memory
> > footprint in vain).
> > 
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >  Documentation/acpi/scan_handlers.txt |   77 +++++++++++++++++++++++++++++++++++
> >  drivers/acpi/scan.c                  |   60 ++++++++++++++++++++++++---
> >  include/acpi/acpi_bus.h              |   14 ++++++
> >  3 files changed, 144 insertions(+), 7 deletions(-)
> > 
> > Index: test/include/acpi/acpi_bus.h
> > ===================================================================
> > --- test.orig/include/acpi/acpi_bus.h
> > +++ test/include/acpi/acpi_bus.h
> > @@ -84,6 +84,18 @@ struct acpi_driver;
> >  struct acpi_device;
> >  
> >  /*
> > + * ACPI Scan Handler
> > + * -----------------
> > + */
> > +
> > +struct acpi_scan_handler {
> > +	const struct acpi_device_id *ids;
> > +	struct list_head list_node;
> > +	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > +	void (*detach)(struct acpi_device *dev);
> > +};
> > +
> > +/*
> >   * ACPI Driver
> >   * -----------
> >   */
> > @@ -269,6 +281,7 @@ struct acpi_device {
> >  	struct acpi_device_wakeup wakeup;
> >  	struct acpi_device_perf performance;
> >  	struct acpi_device_dir dir;
> > +	struct acpi_scan_handler *handler;
> >  	struct acpi_driver *driver;
> >  	void *driver_data;
> >  	struct device dev;
> > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> >  static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> >  	{ return 0; }
> >  #endif
> > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> >  int acpi_bus_register_driver(struct acpi_driver *driver);
> >  void acpi_bus_unregister_driver(struct acpi_driver *driver);
> >  int acpi_bus_scan(acpi_handle handle);
> > Index: test/drivers/acpi/scan.c
> > ===================================================================
> > --- test.orig/drivers/acpi/scan.c
> > +++ test/drivers/acpi/scan.c
> > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> >  static LIST_HEAD(acpi_device_list);
> >  static LIST_HEAD(acpi_bus_id_list);
> >  static DEFINE_MUTEX(acpi_scan_lock);
> > +static LIST_HEAD(acpi_scan_handlers_list);
> >  DEFINE_MUTEX(acpi_device_lock);
> >  LIST_HEAD(acpi_wakeup_device_list);
> >  
> > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> >  	struct list_head node;
> >  };
> >  
> > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > +{
> > +	if (!handler || !handler->attach)
> > +		return -EINVAL;
> > +
> > +	list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > +	return 0;
> > +}
> > +
> >  /*
> >   * Creates hid/cid(s) string needed for modalias and uevent
> >   * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> >  	return AE_OK;
> >  }
> >  
> > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > +{
> > +	struct acpi_scan_handler *handler;
> > +	int ret = 0;
> > +
> > +	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > +		const struct acpi_device_id *id;
> > +
> > +		id = __acpi_match_device(device, handler->ids);
> > +		if (!id)
> > +			continue;
> > +
> > +		ret = handler->attach(device, id);
> > +		if (ret > 0) {
> > +			device->handler = handler;
> > +			break;
> > +		} else if (ret < 0) {
> > +			break;
> > +		}
> > +	}
> > +	return ret;
> > +}
> 
> Now that we have full control over the attach logic, it would be great
> if we can update it to match with the ACPI spec -- HID has priority over
> CIDs, and CIDs are also listed in their priority.  For example, Device-X
> has HID and CID.  In this case, this Device-X should be attached to
> Handler-A since it supports HID.  The current logic simply chooses a
> handler whichever registered before.  
> 
> Device-X: HID PNPID-A, CID PNPID-B
> Handler-A: PNPID-A
> Handler-B: PNPID-B
> 
> So, the attach logic should be something like:
> 
> list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> 	list_for_each_entry(,&acpi_scan_handlers_list,)
> 		check if this handler supports a given hwid
> }

OK, I see the problem, but I think it's better to address it in a separate
patch on top of the current series.

I'm not sure what approach is best, though.  Do you think there should be two
passes the first of which will check HIDs only and the second one will check
CIDs?  Or do you have something different in mind?

Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
  2013-01-29  2:20     ` Yasuaki Ishimatsu
@ 2013-01-29 11:36       ` Rafael J. Wysocki
  2013-01-29 12:30         ` [Update][PATCH " Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 11:36 UTC (permalink / raw)
  To: Yasuaki Ishimatsu
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML

On Tuesday, January 29, 2013 11:20:44 AM Yasuaki Ishimatsu wrote:
> Hi Rafael,
> 
> 2013/01/28 22:01, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Currently, the ACPI namespace scanning code creates platform device
> > objects for ACPI device nodes whose IDs match the contents of the
> > acpi_platform_device_ids[] table.  However, this adds a superfluous
> > special case into acpi_bus_device_attach() and makes it more
> > difficult to follow than it has to be.  It also will make it more
> > difficult to implement removal code for those platform device objects
> > in the future.
> >
> > For the above reasons, introduce a struct acpi_scan_handler object
> > for creating platform devices and move the code related to that from
> > acpi_bus_device_attach() to the .attach() callback of that object.
> > Also move the acpi_platform_device_ids[] table to acpi_platform.c.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >   drivers/acpi/acpi_platform.c |   55 +++++++++++++++++++++++++++++++++++--------
> >   drivers/acpi/internal.h      |    7 -----
> >   drivers/acpi/scan.c          |   30 -----------------------
> >   3 files changed, 47 insertions(+), 45 deletions(-)
> >
> > Index: test/drivers/acpi/acpi_platform.c
> > ===================================================================
> > --- test.orig/drivers/acpi/acpi_platform.c
> > +++ test/drivers/acpi/acpi_platform.c
> > @@ -22,6 +22,30 @@
> >
> >   ACPI_MODULE_NAME("platform");
> >
> > +/* Flags for acpi_create_platform_device */
> > +#define ACPI_PLATFORM_CLK	BIT(0)
> > +
> > +/*
> > + * The following ACPI IDs are known to be suitable for representing as
> > + * platform devices.
> > + */
> > +static const struct acpi_device_id acpi_platform_device_ids[] = {
> > +
> > +	{ "PNP0D40" },
> > +
> > +	/* Haswell LPSS devices */
> > +	{ "INT33C0", ACPI_PLATFORM_CLK },
> > +	{ "INT33C1", ACPI_PLATFORM_CLK },
> > +	{ "INT33C2", ACPI_PLATFORM_CLK },
> > +	{ "INT33C3", ACPI_PLATFORM_CLK },
> > +	{ "INT33C4", ACPI_PLATFORM_CLK },
> > +	{ "INT33C5", ACPI_PLATFORM_CLK },
> > +	{ "INT33C6", ACPI_PLATFORM_CLK },
> > +	{ "INT33C7", ACPI_PLATFORM_CLK },
> > +
> > +	{ }
> > +};
> > +
> >   static int acpi_create_platform_clks(struct acpi_device *adev)
> >   {
> >   	static struct platform_device *pdev;
> > @@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
> >   /**
> >    * acpi_create_platform_device - Create platform device for ACPI device node
> >    * @adev: ACPI device node to create a platform device for.
> > - * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
> > - *	   devices.
> > + * @id: ACPI device ID used to match @adev.
> >    *
> >    * Check if the given @adev can be represented as a platform device and, if
> >    * that's the case, create and register a platform device, populate its common
> > @@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
> >    *
> >    * Name of the platform device will be the same as @adev's.
> >    */
> > -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
> > -						    unsigned long flags)
> > +static int acpi_create_platform_device(struct acpi_device *adev,
> > +				       const struct acpi_device_id *id)
> >   {
> > +	unsigned long flags = id->driver_data;
> >   	struct platform_device *pdev = NULL;
> >   	struct acpi_device *acpi_parent;
> >   	struct platform_device_info pdevinfo;
> > @@ -59,25 +83,26 @@ struct platform_device *acpi_create_plat
> >   	struct resource *resources;
> >   	int count;
> >
> 
> > -	if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
> > +	if (flags & ACPI_PLATFORM_CLK) {
> > +		int ret = acpi_create_platform_clks(adev);
> >   		dev_err(&adev->dev, "failed to create clocks\n");
> > -		return NULL;
> > +		return ret;
> >   	}
> 
> If (flag & ACPI_PLATFORM_CLK) is true, the acpi_create_platform_device()
> always retruns with dev_err() messages. Why?

Ah.  By mistake. :-)

Thanks for poiting this out!

Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
  2013-01-29  7:35     ` [PATCH " Mika Westerberg
@ 2013-01-29 12:01       ` Rafael J. Wysocki
  0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 12:01 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

On Tuesday, January 29, 2013 09:35:32 AM Mika Westerberg wrote:
> On Mon, Jan 28, 2013 at 02:01:14PM +0100, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> > Currently, the ACPI namespace scanning code creates platform device
> > objects for ACPI device nodes whose IDs match the contents of the
> > acpi_platform_device_ids[] table.  However, this adds a superfluous
> > special case into acpi_bus_device_attach() and makes it more
> > difficult to follow than it has to be.  It also will make it more
> > difficult to implement removal code for those platform device objects
> > in the future.
> > 
> > For the above reasons, introduce a struct acpi_scan_handler object
> > for creating platform devices and move the code related to that from
> > acpi_bus_device_attach() to the .attach() callback of that object.
> > Also move the acpi_platform_device_ids[] table to acpi_platform.c.
> > 
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> I've tested this with Haswell machine and once you fix the problem pointed
> out by Yasuaki Ishimat (returning always when ACPI_PLATFORM_CLK is set)

Well, yeah.  Fixed now.

> the platform device creation works well. This is a nice cleanup and localizes
> the hard coded platform device table in one file making maintenance bit
> easier.
> 
> Feel free to add:
> 
> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>

Thanks!


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
  2013-01-29  8:05     ` Mika Westerberg
@ 2013-01-29 12:02       ` Rafael J. Wysocki
  0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 12:02 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

On Tuesday, January 29, 2013 10:05:09 AM Mika Westerberg wrote:
> On Mon, Jan 28, 2013 at 02:01:14PM +0100, Rafael J. Wysocki wrote:
> > +/* Flags for acpi_create_platform_device */
> > +#define ACPI_PLATFORM_CLK	BIT(0)
> > +
> > +/*
> > + * The following ACPI IDs are known to be suitable for representing as
> > + * platform devices.
> > + */
> > +static const struct acpi_device_id acpi_platform_device_ids[] = {
> > +
> > +	{ "PNP0D40" },
> > +
> > +	/* Haswell LPSS devices */
> > +	{ "INT33C0", ACPI_PLATFORM_CLK },
> > +	{ "INT33C1", ACPI_PLATFORM_CLK },
> > +	{ "INT33C2", ACPI_PLATFORM_CLK },
> > +	{ "INT33C3", ACPI_PLATFORM_CLK },
> > +	{ "INT33C4", ACPI_PLATFORM_CLK },
> > +	{ "INT33C5", ACPI_PLATFORM_CLK },
> > +	{ "INT33C6", ACPI_PLATFORM_CLK },
> > +	{ "INT33C7", ACPI_PLATFORM_CLK },
> > +
> > +	{ }
> > +};
> 
> Now that we have everything the platform support code needs in a single
> file, should we instead of setting flags and comparing strings like
> "INT33C" to find out are we running on Lynxpoint, pass function pointer
> that gets called when corresponding device gets created? Something like:
> 
> 	{ "INT33C0", lpt_clks_init },
> 	...
> 
> Or do you think we need to keep the flags still?
> 
> I can prepare a patch if this turns out to be sensible thing to do.

Well, if we can reduce the code size this way, please send a patch.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [Update][PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
  2013-01-29 11:36       ` Rafael J. Wysocki
@ 2013-01-29 12:30         ` Rafael J. Wysocki
  2013-01-29 23:51           ` Yasuaki Ishimatsu
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 12:30 UTC (permalink / raw)
  To: Yasuaki Ishimatsu
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML

On Tuesday, January 29, 2013 12:36:35 PM Rafael J. Wysocki wrote:
> On Tuesday, January 29, 2013 11:20:44 AM Yasuaki Ishimatsu wrote:
> > Hi Rafael,
> > 
> > 2013/01/28 22:01, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > >
> > > Currently, the ACPI namespace scanning code creates platform device
> > > objects for ACPI device nodes whose IDs match the contents of the
> > > acpi_platform_device_ids[] table.  However, this adds a superfluous
> > > special case into acpi_bus_device_attach() and makes it more
> > > difficult to follow than it has to be.  It also will make it more
> > > difficult to implement removal code for those platform device objects
> > > in the future.
> > >
> > > For the above reasons, introduce a struct acpi_scan_handler object
> > > for creating platform devices and move the code related to that from
> > > acpi_bus_device_attach() to the .attach() callback of that object.
> > > Also move the acpi_platform_device_ids[] table to acpi_platform.c.
> > >
> > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > ---
> > >   drivers/acpi/acpi_platform.c |   55 +++++++++++++++++++++++++++++++++++--------
> > >   drivers/acpi/internal.h      |    7 -----
> > >   drivers/acpi/scan.c          |   30 -----------------------
> > >   3 files changed, 47 insertions(+), 45 deletions(-)
> > >
> > > Index: test/drivers/acpi/acpi_platform.c
> > > ===================================================================
> > > --- test.orig/drivers/acpi/acpi_platform.c
> > > +++ test/drivers/acpi/acpi_platform.c
> > > @@ -22,6 +22,30 @@
> > >
> > >   ACPI_MODULE_NAME("platform");
> > >
> > > +/* Flags for acpi_create_platform_device */
> > > +#define ACPI_PLATFORM_CLK	BIT(0)
> > > +
> > > +/*
> > > + * The following ACPI IDs are known to be suitable for representing as
> > > + * platform devices.
> > > + */
> > > +static const struct acpi_device_id acpi_platform_device_ids[] = {
> > > +
> > > +	{ "PNP0D40" },
> > > +
> > > +	/* Haswell LPSS devices */
> > > +	{ "INT33C0", ACPI_PLATFORM_CLK },
> > > +	{ "INT33C1", ACPI_PLATFORM_CLK },
> > > +	{ "INT33C2", ACPI_PLATFORM_CLK },
> > > +	{ "INT33C3", ACPI_PLATFORM_CLK },
> > > +	{ "INT33C4", ACPI_PLATFORM_CLK },
> > > +	{ "INT33C5", ACPI_PLATFORM_CLK },
> > > +	{ "INT33C6", ACPI_PLATFORM_CLK },
> > > +	{ "INT33C7", ACPI_PLATFORM_CLK },
> > > +
> > > +	{ }
> > > +};
> > > +
> > >   static int acpi_create_platform_clks(struct acpi_device *adev)
> > >   {
> > >   	static struct platform_device *pdev;
> > > @@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
> > >   /**
> > >    * acpi_create_platform_device - Create platform device for ACPI device node
> > >    * @adev: ACPI device node to create a platform device for.
> > > - * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
> > > - *	   devices.
> > > + * @id: ACPI device ID used to match @adev.
> > >    *
> > >    * Check if the given @adev can be represented as a platform device and, if
> > >    * that's the case, create and register a platform device, populate its common
> > > @@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
> > >    *
> > >    * Name of the platform device will be the same as @adev's.
> > >    */
> > > -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
> > > -						    unsigned long flags)
> > > +static int acpi_create_platform_device(struct acpi_device *adev,
> > > +				       const struct acpi_device_id *id)
> > >   {
> > > +	unsigned long flags = id->driver_data;
> > >   	struct platform_device *pdev = NULL;
> > >   	struct acpi_device *acpi_parent;
> > >   	struct platform_device_info pdevinfo;
> > > @@ -59,25 +83,26 @@ struct platform_device *acpi_create_plat
> > >   	struct resource *resources;
> > >   	int count;
> > >
> > 
> > > -	if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
> > > +	if (flags & ACPI_PLATFORM_CLK) {
> > > +		int ret = acpi_create_platform_clks(adev);
> > >   		dev_err(&adev->dev, "failed to create clocks\n");
> > > -		return NULL;
> > > +		return ret;
> > >   	}
> > 
> > If (flag & ACPI_PLATFORM_CLK) is true, the acpi_create_platform_device()
> > always retruns with dev_err() messages. Why?
> 
> Ah.  By mistake. :-)
> 
> Thanks for poiting this out!

Updated patch is appended.

Thanks,
Rafael

---
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Subject: ACPI / platform: Use struct acpi_scan_handler for creating devices

Currently, the ACPI namespace scanning code creates platform device
objects for ACPI device nodes whose IDs match the contents of the
acpi_platform_device_ids[] table.  However, this adds a superfluous
special case into acpi_bus_device_attach() and makes it more
difficult to follow than it has to be.  It also will make it more
difficult to implement removal code for those platform device objects
in the future.

For the above reasons, introduce a struct acpi_scan_handler object
for creating platform devices and move the code related to that from
acpi_bus_device_attach() to the .attach() callback of that object.
Also move the acpi_platform_device_ids[] table to acpi_platform.c.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/acpi_platform.c |   59 ++++++++++++++++++++++++++++++++++---------
 drivers/acpi/internal.h      |    7 -----
 drivers/acpi/scan.c          |   30 ---------------------
 3 files changed, 50 insertions(+), 46 deletions(-)

Index: test/drivers/acpi/acpi_platform.c
===================================================================
--- test.orig/drivers/acpi/acpi_platform.c
+++ test/drivers/acpi/acpi_platform.c
@@ -22,6 +22,30 @@
 
 ACPI_MODULE_NAME("platform");
 
+/* Flags for acpi_create_platform_device */
+#define ACPI_PLATFORM_CLK	BIT(0)
+
+/*
+ * The following ACPI IDs are known to be suitable for representing as
+ * platform devices.
+ */
+static const struct acpi_device_id acpi_platform_device_ids[] = {
+
+	{ "PNP0D40" },
+
+	/* Haswell LPSS devices */
+	{ "INT33C0", ACPI_PLATFORM_CLK },
+	{ "INT33C1", ACPI_PLATFORM_CLK },
+	{ "INT33C2", ACPI_PLATFORM_CLK },
+	{ "INT33C3", ACPI_PLATFORM_CLK },
+	{ "INT33C4", ACPI_PLATFORM_CLK },
+	{ "INT33C5", ACPI_PLATFORM_CLK },
+	{ "INT33C6", ACPI_PLATFORM_CLK },
+	{ "INT33C7", ACPI_PLATFORM_CLK },
+
+	{ }
+};
+
 static int acpi_create_platform_clks(struct acpi_device *adev)
 {
 	static struct platform_device *pdev;
@@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
 /**
  * acpi_create_platform_device - Create platform device for ACPI device node
  * @adev: ACPI device node to create a platform device for.
- * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
- *	   devices.
+ * @id: ACPI device ID used to match @adev.
  *
  * Check if the given @adev can be represented as a platform device and, if
  * that's the case, create and register a platform device, populate its common
@@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
  *
  * Name of the platform device will be the same as @adev's.
  */
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
-						    unsigned long flags)
+static int acpi_create_platform_device(struct acpi_device *adev,
+				       const struct acpi_device_id *id)
 {
+	unsigned long flags = id->driver_data;
 	struct platform_device *pdev = NULL;
 	struct acpi_device *acpi_parent;
 	struct platform_device_info pdevinfo;
@@ -59,25 +83,28 @@ struct platform_device *acpi_create_plat
 	struct resource *resources;
 	int count;
 
-	if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
-		dev_err(&adev->dev, "failed to create clocks\n");
-		return NULL;
+	if (flags & ACPI_PLATFORM_CLK) {
+		int ret = acpi_create_platform_clks(adev);
+		if (ret) {
+			dev_err(&adev->dev, "failed to create clocks\n");
+			return ret;
+		}
 	}
 
 	/* If the ACPI node already has a physical device attached, skip it. */
 	if (adev->physical_node_count)
-		return NULL;
+		return 0;
 
 	INIT_LIST_HEAD(&resource_list);
 	count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
 	if (count <= 0)
-		return NULL;
+		return 0;
 
 	resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
 	if (!resources) {
 		dev_err(&adev->dev, "No memory for resources\n");
 		acpi_dev_free_resource_list(&resource_list);
-		return NULL;
+		return -ENOMEM;
 	}
 	count = 0;
 	list_for_each_entry(rentry, &resource_list, node)
@@ -123,5 +150,15 @@ struct platform_device *acpi_create_plat
 	}
 
 	kfree(resources);
-	return pdev;
+	return 1;
+}
+
+static struct acpi_scan_handler platform_handler = {
+	.ids = acpi_platform_device_ids,
+	.attach = acpi_create_platform_device,
+};
+
+void __init acpi_platform_init(void)
+{
+	acpi_scan_add_handler(&platform_handler);
 }
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -27,6 +27,7 @@ int init_acpi_device_notify(void);
 int acpi_scan_init(void);
 void acpi_pci_root_init(void);
 void acpi_pci_link_init(void);
+void acpi_platform_init(void);
 int acpi_sysfs_init(void);
 void acpi_csrt_init(void);
 
@@ -119,10 +120,4 @@ static inline void suspend_nvs_restore(v
   -------------------------------------------------------------------------- */
 struct platform_device;
 
-/* Flags for acpi_create_platform_device */
-#define ACPI_PLATFORM_CLK	BIT(0)
-
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
-						    unsigned long flags);
-
 #endif /* _ACPI_INTERNAL_H_ */
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -29,27 +29,6 @@ extern struct acpi_device *acpi_root;
 
 static const char *dummy_hid = "device";
 
-/*
- * The following ACPI IDs are known to be suitable for representing as
- * platform devices.
- */
-static const struct acpi_device_id acpi_platform_device_ids[] = {
-
-	{ "PNP0D40" },
-
-	/* Haswell LPSS devices */
-	{ "INT33C0", ACPI_PLATFORM_CLK },
-	{ "INT33C1", ACPI_PLATFORM_CLK },
-	{ "INT33C2", ACPI_PLATFORM_CLK },
-	{ "INT33C3", ACPI_PLATFORM_CLK },
-	{ "INT33C4", ACPI_PLATFORM_CLK },
-	{ "INT33C5", ACPI_PLATFORM_CLK },
-	{ "INT33C6", ACPI_PLATFORM_CLK },
-	{ "INT33C7", ACPI_PLATFORM_CLK },
-
-	{ }
-};
-
 static LIST_HEAD(acpi_device_list);
 static LIST_HEAD(acpi_bus_id_list);
 static DEFINE_MUTEX(acpi_scan_lock);
@@ -1606,7 +1585,6 @@ static int acpi_scan_attach_handler(stru
 static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
 					  void *not_used, void **ret_not_used)
 {
-	const struct acpi_device_id *id;
 	struct acpi_device *device;
 	unsigned long long sta_not_used;
 	int ret;
@@ -1621,13 +1599,6 @@ static acpi_status acpi_bus_device_attac
 	if (acpi_bus_get_device(handle, &device))
 		return AE_CTRL_DEPTH;
 
-	id = __acpi_match_device(device, acpi_platform_device_ids);
-	if (id) {
-		/* This is a known good platform device. */
-		acpi_create_platform_device(device, id->driver_data);
-		return AE_OK;
-	}
-
 	ret = acpi_scan_attach_handler(device);
 	if (ret)
 		return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
@@ -1775,6 +1746,7 @@ int __init acpi_scan_init(void)
 
 	acpi_pci_root_init();
 	acpi_pci_link_init();
+	acpi_platform_init();
 	acpi_csrt_init();
 
 	/*



-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
  2013-01-29 11:28       ` Rafael J. Wysocki
@ 2013-01-29 14:50         ` Toshi Kani
  2013-01-29 21:32           ` Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-01-29 14:50 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Tue, 2013-01-29 at 12:28 +0100, Rafael J. Wysocki wrote:
> On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> > On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > 
> > > Introduce struct acpi_scan_handler for representing objects that
> > > will do configuration tasks depending on ACPI device nodes'
> > > hardware IDs (HIDs).
> > > 
> > > Currently, those tasks are done either directly by the ACPI namespace
> > > scanning code or by ACPI device drivers designed specifically for
> > > this purpose.  None of the above is desirable, however, because
> > > doing that directly in the namespace scanning code makes that code
> > > overly complicated and difficult to follow and doing that in
> > > "special" device drivers leads to a great deal of confusion about
> > > their role and to confusing interactions with the driver core (for
> > > example, sysfs directories are created for those drivers, but they
> > > are completely unnecessary and only increase the kernel's memory
> > > footprint in vain).
> > > 
> > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > ---
> > >  Documentation/acpi/scan_handlers.txt |   77 +++++++++++++++++++++++++++++++++++
> > >  drivers/acpi/scan.c                  |   60 ++++++++++++++++++++++++---
> > >  include/acpi/acpi_bus.h              |   14 ++++++
> > >  3 files changed, 144 insertions(+), 7 deletions(-)
> > > 
> > > Index: test/include/acpi/acpi_bus.h
> > > ===================================================================
> > > --- test.orig/include/acpi/acpi_bus.h
> > > +++ test/include/acpi/acpi_bus.h
> > > @@ -84,6 +84,18 @@ struct acpi_driver;
> > >  struct acpi_device;
> > >  
> > >  /*
> > > + * ACPI Scan Handler
> > > + * -----------------
> > > + */
> > > +
> > > +struct acpi_scan_handler {
> > > +	const struct acpi_device_id *ids;
> > > +	struct list_head list_node;
> > > +	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > > +	void (*detach)(struct acpi_device *dev);
> > > +};
> > > +
> > > +/*
> > >   * ACPI Driver
> > >   * -----------
> > >   */
> > > @@ -269,6 +281,7 @@ struct acpi_device {
> > >  	struct acpi_device_wakeup wakeup;
> > >  	struct acpi_device_perf performance;
> > >  	struct acpi_device_dir dir;
> > > +	struct acpi_scan_handler *handler;
> > >  	struct acpi_driver *driver;
> > >  	void *driver_data;
> > >  	struct device dev;
> > > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > >  static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > >  	{ return 0; }
> > >  #endif
> > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > >  int acpi_bus_register_driver(struct acpi_driver *driver);
> > >  void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > >  int acpi_bus_scan(acpi_handle handle);
> > > Index: test/drivers/acpi/scan.c
> > > ===================================================================
> > > --- test.orig/drivers/acpi/scan.c
> > > +++ test/drivers/acpi/scan.c
> > > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > >  static LIST_HEAD(acpi_device_list);
> > >  static LIST_HEAD(acpi_bus_id_list);
> > >  static DEFINE_MUTEX(acpi_scan_lock);
> > > +static LIST_HEAD(acpi_scan_handlers_list);
> > >  DEFINE_MUTEX(acpi_device_lock);
> > >  LIST_HEAD(acpi_wakeup_device_list);
> > >  
> > > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > >  	struct list_head node;
> > >  };
> > >  
> > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > > +{
> > > +	if (!handler || !handler->attach)
> > > +		return -EINVAL;
> > > +
> > > +	list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > > +	return 0;
> > > +}
> > > +
> > >  /*
> > >   * Creates hid/cid(s) string needed for modalias and uevent
> > >   * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > >  	return AE_OK;
> > >  }
> > >  
> > > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > > +{
> > > +	struct acpi_scan_handler *handler;
> > > +	int ret = 0;
> > > +
> > > +	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > > +		const struct acpi_device_id *id;
> > > +
> > > +		id = __acpi_match_device(device, handler->ids);
> > > +		if (!id)
> > > +			continue;
> > > +
> > > +		ret = handler->attach(device, id);
> > > +		if (ret > 0) {
> > > +			device->handler = handler;
> > > +			break;
> > > +		} else if (ret < 0) {
> > > +			break;
> > > +		}
> > > +	}
> > > +	return ret;
> > > +}
> > 
> > Now that we have full control over the attach logic, it would be great
> > if we can update it to match with the ACPI spec -- HID has priority over
> > CIDs, and CIDs are also listed in their priority.  For example, Device-X
> > has HID and CID.  In this case, this Device-X should be attached to
> > Handler-A since it supports HID.  The current logic simply chooses a
> > handler whichever registered before.  
> > 
> > Device-X: HID PNPID-A, CID PNPID-B
> > Handler-A: PNPID-A
> > Handler-B: PNPID-B
> > 
> > So, the attach logic should be something like:
> > 
> > list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> > 	list_for_each_entry(,&acpi_scan_handlers_list,)
> > 		check if this handler supports a given hwid
> > }
> 
> OK, I see the problem, but I think it's better to address it in a separate
> patch on top of the current series.

I agree.

> I'm not sure what approach is best, though.  Do you think there should be two
> passes the first of which will check HIDs only and the second one will check
> CIDs?  Or do you have something different in mind?

HID and CIDs are already listed in their priority order in
acpi_device->pnp.ids.  So, the single pass like I described above should
work.

Thanks,
-Toshi


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
  2013-01-29 14:50         ` Toshi Kani
@ 2013-01-29 21:32           ` Rafael J. Wysocki
  2013-01-29 22:57             ` Toshi Kani
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 21:32 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Tuesday, January 29, 2013 07:50:43 AM Toshi Kani wrote:
> On Tue, 2013-01-29 at 12:28 +0100, Rafael J. Wysocki wrote:
> > On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> > > On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > 
> > > > Introduce struct acpi_scan_handler for representing objects that
> > > > will do configuration tasks depending on ACPI device nodes'
> > > > hardware IDs (HIDs).
> > > > 
> > > > Currently, those tasks are done either directly by the ACPI namespace
> > > > scanning code or by ACPI device drivers designed specifically for
> > > > this purpose.  None of the above is desirable, however, because
> > > > doing that directly in the namespace scanning code makes that code
> > > > overly complicated and difficult to follow and doing that in
> > > > "special" device drivers leads to a great deal of confusion about
> > > > their role and to confusing interactions with the driver core (for
> > > > example, sysfs directories are created for those drivers, but they
> > > > are completely unnecessary and only increase the kernel's memory
> > > > footprint in vain).
> > > > 
> > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > ---
> > > >  Documentation/acpi/scan_handlers.txt |   77 +++++++++++++++++++++++++++++++++++
> > > >  drivers/acpi/scan.c                  |   60 ++++++++++++++++++++++++---
> > > >  include/acpi/acpi_bus.h              |   14 ++++++
> > > >  3 files changed, 144 insertions(+), 7 deletions(-)
> > > > 
> > > > Index: test/include/acpi/acpi_bus.h
> > > > ===================================================================
> > > > --- test.orig/include/acpi/acpi_bus.h
> > > > +++ test/include/acpi/acpi_bus.h
> > > > @@ -84,6 +84,18 @@ struct acpi_driver;
> > > >  struct acpi_device;
> > > >  
> > > >  /*
> > > > + * ACPI Scan Handler
> > > > + * -----------------
> > > > + */
> > > > +
> > > > +struct acpi_scan_handler {
> > > > +	const struct acpi_device_id *ids;
> > > > +	struct list_head list_node;
> > > > +	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > > > +	void (*detach)(struct acpi_device *dev);
> > > > +};
> > > > +
> > > > +/*
> > > >   * ACPI Driver
> > > >   * -----------
> > > >   */
> > > > @@ -269,6 +281,7 @@ struct acpi_device {
> > > >  	struct acpi_device_wakeup wakeup;
> > > >  	struct acpi_device_perf performance;
> > > >  	struct acpi_device_dir dir;
> > > > +	struct acpi_scan_handler *handler;
> > > >  	struct acpi_driver *driver;
> > > >  	void *driver_data;
> > > >  	struct device dev;
> > > > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > > >  static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > > >  	{ return 0; }
> > > >  #endif
> > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > > >  int acpi_bus_register_driver(struct acpi_driver *driver);
> > > >  void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > > >  int acpi_bus_scan(acpi_handle handle);
> > > > Index: test/drivers/acpi/scan.c
> > > > ===================================================================
> > > > --- test.orig/drivers/acpi/scan.c
> > > > +++ test/drivers/acpi/scan.c
> > > > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > > >  static LIST_HEAD(acpi_device_list);
> > > >  static LIST_HEAD(acpi_bus_id_list);
> > > >  static DEFINE_MUTEX(acpi_scan_lock);
> > > > +static LIST_HEAD(acpi_scan_handlers_list);
> > > >  DEFINE_MUTEX(acpi_device_lock);
> > > >  LIST_HEAD(acpi_wakeup_device_list);
> > > >  
> > > > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > > >  	struct list_head node;
> > > >  };
> > > >  
> > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > > > +{
> > > > +	if (!handler || !handler->attach)
> > > > +		return -EINVAL;
> > > > +
> > > > +	list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > > > +	return 0;
> > > > +}
> > > > +
> > > >  /*
> > > >   * Creates hid/cid(s) string needed for modalias and uevent
> > > >   * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > > > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > > >  	return AE_OK;
> > > >  }
> > > >  
> > > > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > > > +{
> > > > +	struct acpi_scan_handler *handler;
> > > > +	int ret = 0;
> > > > +
> > > > +	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > > > +		const struct acpi_device_id *id;
> > > > +
> > > > +		id = __acpi_match_device(device, handler->ids);
> > > > +		if (!id)
> > > > +			continue;
> > > > +
> > > > +		ret = handler->attach(device, id);
> > > > +		if (ret > 0) {
> > > > +			device->handler = handler;
> > > > +			break;
> > > > +		} else if (ret < 0) {
> > > > +			break;
> > > > +		}
> > > > +	}
> > > > +	return ret;
> > > > +}
> > > 
> > > Now that we have full control over the attach logic, it would be great
> > > if we can update it to match with the ACPI spec -- HID has priority over
> > > CIDs, and CIDs are also listed in their priority.  For example, Device-X
> > > has HID and CID.  In this case, this Device-X should be attached to
> > > Handler-A since it supports HID.  The current logic simply chooses a
> > > handler whichever registered before.  
> > > 
> > > Device-X: HID PNPID-A, CID PNPID-B
> > > Handler-A: PNPID-A
> > > Handler-B: PNPID-B
> > > 
> > > So, the attach logic should be something like:
> > > 
> > > list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> > > 	list_for_each_entry(,&acpi_scan_handlers_list,)
> > > 		check if this handler supports a given hwid
> > > }
> > 
> > OK, I see the problem, but I think it's better to address it in a separate
> > patch on top of the current series.
> 
> I agree.
> 
> > I'm not sure what approach is best, though.  Do you think there should be two
> > passes the first of which will check HIDs only and the second one will check
> > CIDs?  Or do you have something different in mind?
> 
> HID and CIDs are already listed in their priority order in
> acpi_device->pnp.ids.  So, the single pass like I described above should
> work.

Well, I'm not sure if I understand you correctly.

The device is given and we need to find a handler for it.  So, it looks like
we first should check if any handler matches the HID.  This has to be a pass
through all handlers.  If there's no match, we need to check if any handler
matches any of the device IDs.  That will be the second pass, won't it?

The difficulty is that the first item in pnp.ids need not be *the* HID.
It only will be the HID if ACPI_VALID_HID is set in the device info in
acpi_device_set_id().  So perhaps we need to add a hid_valid bit in
device->flags and only do the "HID pass" if that is set?

Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
  2013-01-29 21:32           ` Rafael J. Wysocki
@ 2013-01-29 22:57             ` Toshi Kani
  2013-01-29 23:19               ` Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-01-29 22:57 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Tue, 2013-01-29 at 22:32 +0100, Rafael J. Wysocki wrote:
> On Tuesday, January 29, 2013 07:50:43 AM Toshi Kani wrote:
> > On Tue, 2013-01-29 at 12:28 +0100, Rafael J. Wysocki wrote:
> > > On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> > > > On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > 
> > > > > Introduce struct acpi_scan_handler for representing objects that
> > > > > will do configuration tasks depending on ACPI device nodes'
> > > > > hardware IDs (HIDs).
> > > > > 
> > > > > Currently, those tasks are done either directly by the ACPI namespace
> > > > > scanning code or by ACPI device drivers designed specifically for
> > > > > this purpose.  None of the above is desirable, however, because
> > > > > doing that directly in the namespace scanning code makes that code
> > > > > overly complicated and difficult to follow and doing that in
> > > > > "special" device drivers leads to a great deal of confusion about
> > > > > their role and to confusing interactions with the driver core (for
> > > > > example, sysfs directories are created for those drivers, but they
> > > > > are completely unnecessary and only increase the kernel's memory
> > > > > footprint in vain).
> > > > > 
> > > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > ---
> > > > >  Documentation/acpi/scan_handlers.txt |   77 +++++++++++++++++++++++++++++++++++
> > > > >  drivers/acpi/scan.c                  |   60 ++++++++++++++++++++++++---
> > > > >  include/acpi/acpi_bus.h              |   14 ++++++
> > > > >  3 files changed, 144 insertions(+), 7 deletions(-)
> > > > > 
> > > > > Index: test/include/acpi/acpi_bus.h
> > > > > ===================================================================
> > > > > --- test.orig/include/acpi/acpi_bus.h
> > > > > +++ test/include/acpi/acpi_bus.h
> > > > > @@ -84,6 +84,18 @@ struct acpi_driver;
> > > > >  struct acpi_device;
> > > > >  
> > > > >  /*
> > > > > + * ACPI Scan Handler
> > > > > + * -----------------
> > > > > + */
> > > > > +
> > > > > +struct acpi_scan_handler {
> > > > > +	const struct acpi_device_id *ids;
> > > > > +	struct list_head list_node;
> > > > > +	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > > > > +	void (*detach)(struct acpi_device *dev);
> > > > > +};
> > > > > +
> > > > > +/*
> > > > >   * ACPI Driver
> > > > >   * -----------
> > > > >   */
> > > > > @@ -269,6 +281,7 @@ struct acpi_device {
> > > > >  	struct acpi_device_wakeup wakeup;
> > > > >  	struct acpi_device_perf performance;
> > > > >  	struct acpi_device_dir dir;
> > > > > +	struct acpi_scan_handler *handler;
> > > > >  	struct acpi_driver *driver;
> > > > >  	void *driver_data;
> > > > >  	struct device dev;
> > > > > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > > > >  static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > > > >  	{ return 0; }
> > > > >  #endif
> > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > > > >  int acpi_bus_register_driver(struct acpi_driver *driver);
> > > > >  void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > > > >  int acpi_bus_scan(acpi_handle handle);
> > > > > Index: test/drivers/acpi/scan.c
> > > > > ===================================================================
> > > > > --- test.orig/drivers/acpi/scan.c
> > > > > +++ test/drivers/acpi/scan.c
> > > > > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > > > >  static LIST_HEAD(acpi_device_list);
> > > > >  static LIST_HEAD(acpi_bus_id_list);
> > > > >  static DEFINE_MUTEX(acpi_scan_lock);
> > > > > +static LIST_HEAD(acpi_scan_handlers_list);
> > > > >  DEFINE_MUTEX(acpi_device_lock);
> > > > >  LIST_HEAD(acpi_wakeup_device_list);
> > > > >  
> > > > > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > > > >  	struct list_head node;
> > > > >  };
> > > > >  
> > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > > > > +{
> > > > > +	if (!handler || !handler->attach)
> > > > > +		return -EINVAL;
> > > > > +
> > > > > +	list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > > >  /*
> > > > >   * Creates hid/cid(s) string needed for modalias and uevent
> > > > >   * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > > > > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > > > >  	return AE_OK;
> > > > >  }
> > > > >  
> > > > > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > > > > +{
> > > > > +	struct acpi_scan_handler *handler;
> > > > > +	int ret = 0;
> > > > > +
> > > > > +	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > > > > +		const struct acpi_device_id *id;
> > > > > +
> > > > > +		id = __acpi_match_device(device, handler->ids);
> > > > > +		if (!id)
> > > > > +			continue;
> > > > > +
> > > > > +		ret = handler->attach(device, id);
> > > > > +		if (ret > 0) {
> > > > > +			device->handler = handler;
> > > > > +			break;
> > > > > +		} else if (ret < 0) {
> > > > > +			break;
> > > > > +		}
> > > > > +	}
> > > > > +	return ret;
> > > > > +}
> > > > 
> > > > Now that we have full control over the attach logic, it would be great
> > > > if we can update it to match with the ACPI spec -- HID has priority over
> > > > CIDs, and CIDs are also listed in their priority.  For example, Device-X
> > > > has HID and CID.  In this case, this Device-X should be attached to
> > > > Handler-A since it supports HID.  The current logic simply chooses a
> > > > handler whichever registered before.  
> > > > 
> > > > Device-X: HID PNPID-A, CID PNPID-B
> > > > Handler-A: PNPID-A
> > > > Handler-B: PNPID-B
> > > > 
> > > > So, the attach logic should be something like:
> > > > 
> > > > list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> > > > 	list_for_each_entry(,&acpi_scan_handlers_list,)
> > > > 		check if this handler supports a given hwid
> > > > }
> > > 
> > > OK, I see the problem, but I think it's better to address it in a separate
> > > patch on top of the current series.
> > 
> > I agree.
> > 
> > > I'm not sure what approach is best, though.  Do you think there should be two
> > > passes the first of which will check HIDs only and the second one will check
> > > CIDs?  Or do you have something different in mind?
> > 
> > HID and CIDs are already listed in their priority order in
> > acpi_device->pnp.ids.  So, the single pass like I described above should
> > work.
> 
> Well, I'm not sure if I understand you correctly.
> 
> The device is given and we need to find a handler for it.  So, it looks like
> we first should check if any handler matches the HID.  This has to be a pass
> through all handlers.  If there's no match, we need to check if any handler
> matches any of the device IDs.  That will be the second pass, won't it?

acpi_device->pnp.ids has a list of HID->CID[0]->CID[1]..CID[n] since
acpi_device_set_id() checks HID before CIDs.  So, the first pass is to
check with the first entry of pnp.ids.  If no handler is found, then
check the second entry, and so on.

> The difficulty is that the first item in pnp.ids need not be *the* HID.
> It only will be the HID if ACPI_VALID_HID is set in the device info in
> acpi_device_set_id().  So perhaps we need to add a hid_valid bit in
> device->flags and only do the "HID pass" if that is set?

I do not think such bit is necessary for this.  _HID is required (unless
it has _ADR), but _CID is optional.  So, the valid cases are that a
device object has HID only, has both HID and CID(s), or has none of them
(i.e. _ADR device).  If there is a device with CID only, this is a FW
bug and we just have to check with CID then.

Thanks,
-Toshi


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
  2013-01-29 22:57             ` Toshi Kani
@ 2013-01-29 23:19               ` Rafael J. Wysocki
  2013-01-29 23:27                 ` Toshi Kani
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 23:19 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Tuesday, January 29, 2013 03:57:10 PM Toshi Kani wrote:
> On Tue, 2013-01-29 at 22:32 +0100, Rafael J. Wysocki wrote:
> > On Tuesday, January 29, 2013 07:50:43 AM Toshi Kani wrote:
> > > On Tue, 2013-01-29 at 12:28 +0100, Rafael J. Wysocki wrote:
> > > > On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> > > > > On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > 
> > > > > > Introduce struct acpi_scan_handler for representing objects that
> > > > > > will do configuration tasks depending on ACPI device nodes'
> > > > > > hardware IDs (HIDs).
> > > > > > 
> > > > > > Currently, those tasks are done either directly by the ACPI namespace
> > > > > > scanning code or by ACPI device drivers designed specifically for
> > > > > > this purpose.  None of the above is desirable, however, because
> > > > > > doing that directly in the namespace scanning code makes that code
> > > > > > overly complicated and difficult to follow and doing that in
> > > > > > "special" device drivers leads to a great deal of confusion about
> > > > > > their role and to confusing interactions with the driver core (for
> > > > > > example, sysfs directories are created for those drivers, but they
> > > > > > are completely unnecessary and only increase the kernel's memory
> > > > > > footprint in vain).
> > > > > > 
> > > > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > ---
> > > > > >  Documentation/acpi/scan_handlers.txt |   77 +++++++++++++++++++++++++++++++++++
> > > > > >  drivers/acpi/scan.c                  |   60 ++++++++++++++++++++++++---
> > > > > >  include/acpi/acpi_bus.h              |   14 ++++++
> > > > > >  3 files changed, 144 insertions(+), 7 deletions(-)
> > > > > > 
> > > > > > Index: test/include/acpi/acpi_bus.h
> > > > > > ===================================================================
> > > > > > --- test.orig/include/acpi/acpi_bus.h
> > > > > > +++ test/include/acpi/acpi_bus.h
> > > > > > @@ -84,6 +84,18 @@ struct acpi_driver;
> > > > > >  struct acpi_device;
> > > > > >  
> > > > > >  /*
> > > > > > + * ACPI Scan Handler
> > > > > > + * -----------------
> > > > > > + */
> > > > > > +
> > > > > > +struct acpi_scan_handler {
> > > > > > +	const struct acpi_device_id *ids;
> > > > > > +	struct list_head list_node;
> > > > > > +	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > > > > > +	void (*detach)(struct acpi_device *dev);
> > > > > > +};
> > > > > > +
> > > > > > +/*
> > > > > >   * ACPI Driver
> > > > > >   * -----------
> > > > > >   */
> > > > > > @@ -269,6 +281,7 @@ struct acpi_device {
> > > > > >  	struct acpi_device_wakeup wakeup;
> > > > > >  	struct acpi_device_perf performance;
> > > > > >  	struct acpi_device_dir dir;
> > > > > > +	struct acpi_scan_handler *handler;
> > > > > >  	struct acpi_driver *driver;
> > > > > >  	void *driver_data;
> > > > > >  	struct device dev;
> > > > > > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > > > > >  static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > > > > >  	{ return 0; }
> > > > > >  #endif
> > > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > > > > >  int acpi_bus_register_driver(struct acpi_driver *driver);
> > > > > >  void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > > > > >  int acpi_bus_scan(acpi_handle handle);
> > > > > > Index: test/drivers/acpi/scan.c
> > > > > > ===================================================================
> > > > > > --- test.orig/drivers/acpi/scan.c
> > > > > > +++ test/drivers/acpi/scan.c
> > > > > > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > > > > >  static LIST_HEAD(acpi_device_list);
> > > > > >  static LIST_HEAD(acpi_bus_id_list);
> > > > > >  static DEFINE_MUTEX(acpi_scan_lock);
> > > > > > +static LIST_HEAD(acpi_scan_handlers_list);
> > > > > >  DEFINE_MUTEX(acpi_device_lock);
> > > > > >  LIST_HEAD(acpi_wakeup_device_list);
> > > > > >  
> > > > > > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > > > > >  	struct list_head node;
> > > > > >  };
> > > > > >  
> > > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > > > > > +{
> > > > > > +	if (!handler || !handler->attach)
> > > > > > +		return -EINVAL;
> > > > > > +
> > > > > > +	list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > > > > > +	return 0;
> > > > > > +}
> > > > > > +
> > > > > >  /*
> > > > > >   * Creates hid/cid(s) string needed for modalias and uevent
> > > > > >   * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > > > > > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > > > > >  	return AE_OK;
> > > > > >  }
> > > > > >  
> > > > > > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > > > > > +{
> > > > > > +	struct acpi_scan_handler *handler;
> > > > > > +	int ret = 0;
> > > > > > +
> > > > > > +	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > > > > > +		const struct acpi_device_id *id;
> > > > > > +
> > > > > > +		id = __acpi_match_device(device, handler->ids);
> > > > > > +		if (!id)
> > > > > > +			continue;
> > > > > > +
> > > > > > +		ret = handler->attach(device, id);
> > > > > > +		if (ret > 0) {
> > > > > > +			device->handler = handler;
> > > > > > +			break;
> > > > > > +		} else if (ret < 0) {
> > > > > > +			break;
> > > > > > +		}
> > > > > > +	}
> > > > > > +	return ret;
> > > > > > +}
> > > > > 
> > > > > Now that we have full control over the attach logic, it would be great
> > > > > if we can update it to match with the ACPI spec -- HID has priority over
> > > > > CIDs, and CIDs are also listed in their priority.  For example, Device-X
> > > > > has HID and CID.  In this case, this Device-X should be attached to
> > > > > Handler-A since it supports HID.  The current logic simply chooses a
> > > > > handler whichever registered before.  
> > > > > 
> > > > > Device-X: HID PNPID-A, CID PNPID-B
> > > > > Handler-A: PNPID-A
> > > > > Handler-B: PNPID-B
> > > > > 
> > > > > So, the attach logic should be something like:
> > > > > 
> > > > > list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> > > > > 	list_for_each_entry(,&acpi_scan_handlers_list,)
> > > > > 		check if this handler supports a given hwid
> > > > > }
> > > > 
> > > > OK, I see the problem, but I think it's better to address it in a separate
> > > > patch on top of the current series.
> > > 
> > > I agree.
> > > 
> > > > I'm not sure what approach is best, though.  Do you think there should be two
> > > > passes the first of which will check HIDs only and the second one will check
> > > > CIDs?  Or do you have something different in mind?
> > > 
> > > HID and CIDs are already listed in their priority order in
> > > acpi_device->pnp.ids.  So, the single pass like I described above should
> > > work.
> > 
> > Well, I'm not sure if I understand you correctly.
> > 
> > The device is given and we need to find a handler for it.  So, it looks like
> > we first should check if any handler matches the HID.  This has to be a pass
> > through all handlers.  If there's no match, we need to check if any handler
> > matches any of the device IDs.  That will be the second pass, won't it?
> 
> acpi_device->pnp.ids has a list of HID->CID[0]->CID[1]..CID[n] since
> acpi_device_set_id() checks HID before CIDs.  So, the first pass is to
> check with the first entry of pnp.ids.  If no handler is found, then
> check the second entry, and so on.

I'd prefer to check HID and then all CIDs at once in accordance with the
following rule:
1) Use the first handler that matches HID exactly.  If there's none:
2) Use the first handler compatible with the given device.

> > The difficulty is that the first item in pnp.ids need not be *the* HID.
> > It only will be the HID if ACPI_VALID_HID is set in the device info in
> > acpi_device_set_id().  So perhaps we need to add a hid_valid bit in
> > device->flags and only do the "HID pass" if that is set?
> 
> I do not think such bit is necessary for this.  _HID is required (unless
> it has _ADR), but _CID is optional.  So, the valid cases are that a
> device object has HID only, has both HID and CID(s), or has none of them
> (i.e. _ADR device).  If there is a device with CID only, this is a FW
> bug and we just have to check with CID then.

In addition to that there's a number of objects that we assign artificial HIDs.
I think we should treat them as CIDs rather than as real HIDs in this regard.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
  2013-01-29 23:19               ` Rafael J. Wysocki
@ 2013-01-29 23:27                 ` Toshi Kani
  2013-01-30 13:18                   ` Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-01-29 23:27 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Wed, 2013-01-30 at 00:19 +0100, Rafael J. Wysocki wrote:
> On Tuesday, January 29, 2013 03:57:10 PM Toshi Kani wrote:
> > On Tue, 2013-01-29 at 22:32 +0100, Rafael J. Wysocki wrote:
> > > On Tuesday, January 29, 2013 07:50:43 AM Toshi Kani wrote:
> > > > On Tue, 2013-01-29 at 12:28 +0100, Rafael J. Wysocki wrote:
> > > > > On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> > > > > > On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > > > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > > 
> > > > > > > Introduce struct acpi_scan_handler for representing objects that
> > > > > > > will do configuration tasks depending on ACPI device nodes'
> > > > > > > hardware IDs (HIDs).
> > > > > > > 
> > > > > > > Currently, those tasks are done either directly by the ACPI namespace
> > > > > > > scanning code or by ACPI device drivers designed specifically for
> > > > > > > this purpose.  None of the above is desirable, however, because
> > > > > > > doing that directly in the namespace scanning code makes that code
> > > > > > > overly complicated and difficult to follow and doing that in
> > > > > > > "special" device drivers leads to a great deal of confusion about
> > > > > > > their role and to confusing interactions with the driver core (for
> > > > > > > example, sysfs directories are created for those drivers, but they
> > > > > > > are completely unnecessary and only increase the kernel's memory
> > > > > > > footprint in vain).
> > > > > > > 
> > > > > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > > ---
> > > > > > >  Documentation/acpi/scan_handlers.txt |   77 +++++++++++++++++++++++++++++++++++
> > > > > > >  drivers/acpi/scan.c                  |   60 ++++++++++++++++++++++++---
> > > > > > >  include/acpi/acpi_bus.h              |   14 ++++++
> > > > > > >  3 files changed, 144 insertions(+), 7 deletions(-)
> > > > > > > 
> > > > > > > Index: test/include/acpi/acpi_bus.h
> > > > > > > ===================================================================
> > > > > > > --- test.orig/include/acpi/acpi_bus.h
> > > > > > > +++ test/include/acpi/acpi_bus.h
> > > > > > > @@ -84,6 +84,18 @@ struct acpi_driver;
> > > > > > >  struct acpi_device;
> > > > > > >  
> > > > > > >  /*
> > > > > > > + * ACPI Scan Handler
> > > > > > > + * -----------------
> > > > > > > + */
> > > > > > > +
> > > > > > > +struct acpi_scan_handler {
> > > > > > > +	const struct acpi_device_id *ids;
> > > > > > > +	struct list_head list_node;
> > > > > > > +	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > > > > > > +	void (*detach)(struct acpi_device *dev);
> > > > > > > +};
> > > > > > > +
> > > > > > > +/*
> > > > > > >   * ACPI Driver
> > > > > > >   * -----------
> > > > > > >   */
> > > > > > > @@ -269,6 +281,7 @@ struct acpi_device {
> > > > > > >  	struct acpi_device_wakeup wakeup;
> > > > > > >  	struct acpi_device_perf performance;
> > > > > > >  	struct acpi_device_dir dir;
> > > > > > > +	struct acpi_scan_handler *handler;
> > > > > > >  	struct acpi_driver *driver;
> > > > > > >  	void *driver_data;
> > > > > > >  	struct device dev;
> > > > > > > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > > > > > >  static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > > > > > >  	{ return 0; }
> > > > > > >  #endif
> > > > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > > > > > >  int acpi_bus_register_driver(struct acpi_driver *driver);
> > > > > > >  void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > > > > > >  int acpi_bus_scan(acpi_handle handle);
> > > > > > > Index: test/drivers/acpi/scan.c
> > > > > > > ===================================================================
> > > > > > > --- test.orig/drivers/acpi/scan.c
> > > > > > > +++ test/drivers/acpi/scan.c
> > > > > > > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > > > > > >  static LIST_HEAD(acpi_device_list);
> > > > > > >  static LIST_HEAD(acpi_bus_id_list);
> > > > > > >  static DEFINE_MUTEX(acpi_scan_lock);
> > > > > > > +static LIST_HEAD(acpi_scan_handlers_list);
> > > > > > >  DEFINE_MUTEX(acpi_device_lock);
> > > > > > >  LIST_HEAD(acpi_wakeup_device_list);
> > > > > > >  
> > > > > > > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > > > > > >  	struct list_head node;
> > > > > > >  };
> > > > > > >  
> > > > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > > > > > > +{
> > > > > > > +	if (!handler || !handler->attach)
> > > > > > > +		return -EINVAL;
> > > > > > > +
> > > > > > > +	list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > > > > > > +	return 0;
> > > > > > > +}
> > > > > > > +
> > > > > > >  /*
> > > > > > >   * Creates hid/cid(s) string needed for modalias and uevent
> > > > > > >   * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > > > > > > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > > > > > >  	return AE_OK;
> > > > > > >  }
> > > > > > >  
> > > > > > > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > > > > > > +{
> > > > > > > +	struct acpi_scan_handler *handler;
> > > > > > > +	int ret = 0;
> > > > > > > +
> > > > > > > +	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > > > > > > +		const struct acpi_device_id *id;
> > > > > > > +
> > > > > > > +		id = __acpi_match_device(device, handler->ids);
> > > > > > > +		if (!id)
> > > > > > > +			continue;
> > > > > > > +
> > > > > > > +		ret = handler->attach(device, id);
> > > > > > > +		if (ret > 0) {
> > > > > > > +			device->handler = handler;
> > > > > > > +			break;
> > > > > > > +		} else if (ret < 0) {
> > > > > > > +			break;
> > > > > > > +		}
> > > > > > > +	}
> > > > > > > +	return ret;
> > > > > > > +}
> > > > > > 
> > > > > > Now that we have full control over the attach logic, it would be great
> > > > > > if we can update it to match with the ACPI spec -- HID has priority over
> > > > > > CIDs, and CIDs are also listed in their priority.  For example, Device-X
> > > > > > has HID and CID.  In this case, this Device-X should be attached to
> > > > > > Handler-A since it supports HID.  The current logic simply chooses a
> > > > > > handler whichever registered before.  
> > > > > > 
> > > > > > Device-X: HID PNPID-A, CID PNPID-B
> > > > > > Handler-A: PNPID-A
> > > > > > Handler-B: PNPID-B
> > > > > > 
> > > > > > So, the attach logic should be something like:
> > > > > > 
> > > > > > list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> > > > > > 	list_for_each_entry(,&acpi_scan_handlers_list,)
> > > > > > 		check if this handler supports a given hwid
> > > > > > }
> > > > > 
> > > > > OK, I see the problem, but I think it's better to address it in a separate
> > > > > patch on top of the current series.
> > > > 
> > > > I agree.
> > > > 
> > > > > I'm not sure what approach is best, though.  Do you think there should be two
> > > > > passes the first of which will check HIDs only and the second one will check
> > > > > CIDs?  Or do you have something different in mind?
> > > > 
> > > > HID and CIDs are already listed in their priority order in
> > > > acpi_device->pnp.ids.  So, the single pass like I described above should
> > > > work.
> > > 
> > > Well, I'm not sure if I understand you correctly.
> > > 
> > > The device is given and we need to find a handler for it.  So, it looks like
> > > we first should check if any handler matches the HID.  This has to be a pass
> > > through all handlers.  If there's no match, we need to check if any handler
> > > matches any of the device IDs.  That will be the second pass, won't it?
> > 
> > acpi_device->pnp.ids has a list of HID->CID[0]->CID[1]..CID[n] since
> > acpi_device_set_id() checks HID before CIDs.  So, the first pass is to
> > check with the first entry of pnp.ids.  If no handler is found, then
> > check the second entry, and so on.
> 
> I'd prefer to check HID and then all CIDs at once in accordance with the
> following rule:
> 1) Use the first handler that matches HID exactly.  If there's none:
> 2) Use the first handler compatible with the given device.

What do you mean by all CIDs at once?  CIDs also have priority when
there are multiple CIDs.  That is, CID[0] takes priority over CID[1].
So, going down the pnp.ids list handles the ordering correctly.


> > > The difficulty is that the first item in pnp.ids need not be *the* HID.
> > > It only will be the HID if ACPI_VALID_HID is set in the device info in
> > > acpi_device_set_id().  So perhaps we need to add a hid_valid bit in
> > > device->flags and only do the "HID pass" if that is set?
> > 
> > I do not think such bit is necessary for this.  _HID is required (unless
> > it has _ADR), but _CID is optional.  So, the valid cases are that a
> > device object has HID only, has both HID and CID(s), or has none of them
> > (i.e. _ADR device).  If there is a device with CID only, this is a FW
> > bug and we just have to check with CID then.
> 
> In addition to that there's a number of objects that we assign artificial HIDs.
> I think we should treat them as CIDs rather than as real HIDs in this regard.

When an object does not support the _HID/_CID combination, it means that
this type of objects can only support a single characteristic, which is
the same as a device object with HID only.  Therefore, an artificial ID
should be considered as an HID.


Thanks,
-Toshi


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [Update][PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
  2013-01-29 12:30         ` [Update][PATCH " Rafael J. Wysocki
@ 2013-01-29 23:51           ` Yasuaki Ishimatsu
  0 siblings, 0 replies; 71+ messages in thread
From: Yasuaki Ishimatsu @ 2013-01-29 23:51 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML

2013/01/29 21:30, Rafael J. Wysocki wrote:
> On Tuesday, January 29, 2013 12:36:35 PM Rafael J. Wysocki wrote:
>> On Tuesday, January 29, 2013 11:20:44 AM Yasuaki Ishimatsu wrote:
>>> Hi Rafael,
>>>
>>> 2013/01/28 22:01, Rafael J. Wysocki wrote:
>>>> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>>>
>>>> Currently, the ACPI namespace scanning code creates platform device
>>>> objects for ACPI device nodes whose IDs match the contents of the
>>>> acpi_platform_device_ids[] table.  However, this adds a superfluous
>>>> special case into acpi_bus_device_attach() and makes it more
>>>> difficult to follow than it has to be.  It also will make it more
>>>> difficult to implement removal code for those platform device objects
>>>> in the future.
>>>>
>>>> For the above reasons, introduce a struct acpi_scan_handler object
>>>> for creating platform devices and move the code related to that from
>>>> acpi_bus_device_attach() to the .attach() callback of that object.
>>>> Also move the acpi_platform_device_ids[] table to acpi_platform.c.
>>>>
>>>> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>>> ---
>>>>    drivers/acpi/acpi_platform.c |   55 +++++++++++++++++++++++++++++++++++--------
>>>>    drivers/acpi/internal.h      |    7 -----
>>>>    drivers/acpi/scan.c          |   30 -----------------------
>>>>    3 files changed, 47 insertions(+), 45 deletions(-)
>>>>
>>>> Index: test/drivers/acpi/acpi_platform.c
>>>> ===================================================================
>>>> --- test.orig/drivers/acpi/acpi_platform.c
>>>> +++ test/drivers/acpi/acpi_platform.c
>>>> @@ -22,6 +22,30 @@
>>>>
>>>>    ACPI_MODULE_NAME("platform");
>>>>
>>>> +/* Flags for acpi_create_platform_device */
>>>> +#define ACPI_PLATFORM_CLK	BIT(0)
>>>> +
>>>> +/*
>>>> + * The following ACPI IDs are known to be suitable for representing as
>>>> + * platform devices.
>>>> + */
>>>> +static const struct acpi_device_id acpi_platform_device_ids[] = {
>>>> +
>>>> +	{ "PNP0D40" },
>>>> +
>>>> +	/* Haswell LPSS devices */
>>>> +	{ "INT33C0", ACPI_PLATFORM_CLK },
>>>> +	{ "INT33C1", ACPI_PLATFORM_CLK },
>>>> +	{ "INT33C2", ACPI_PLATFORM_CLK },
>>>> +	{ "INT33C3", ACPI_PLATFORM_CLK },
>>>> +	{ "INT33C4", ACPI_PLATFORM_CLK },
>>>> +	{ "INT33C5", ACPI_PLATFORM_CLK },
>>>> +	{ "INT33C6", ACPI_PLATFORM_CLK },
>>>> +	{ "INT33C7", ACPI_PLATFORM_CLK },
>>>> +
>>>> +	{ }
>>>> +};
>>>> +
>>>>    static int acpi_create_platform_clks(struct acpi_device *adev)
>>>>    {
>>>>    	static struct platform_device *pdev;
>>>> @@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
>>>>    /**
>>>>     * acpi_create_platform_device - Create platform device for ACPI device node
>>>>     * @adev: ACPI device node to create a platform device for.
>>>> - * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
>>>> - *	   devices.
>>>> + * @id: ACPI device ID used to match @adev.
>>>>     *
>>>>     * Check if the given @adev can be represented as a platform device and, if
>>>>     * that's the case, create and register a platform device, populate its common
>>>> @@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
>>>>     *
>>>>     * Name of the platform device will be the same as @adev's.
>>>>     */
>>>> -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
>>>> -						    unsigned long flags)
>>>> +static int acpi_create_platform_device(struct acpi_device *adev,
>>>> +				       const struct acpi_device_id *id)
>>>>    {
>>>> +	unsigned long flags = id->driver_data;
>>>>    	struct platform_device *pdev = NULL;
>>>>    	struct acpi_device *acpi_parent;
>>>>    	struct platform_device_info pdevinfo;
>>>> @@ -59,25 +83,26 @@ struct platform_device *acpi_create_plat
>>>>    	struct resource *resources;
>>>>    	int count;
>>>>
>>>
>>>> -	if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
>>>> +	if (flags & ACPI_PLATFORM_CLK) {
>>>> +		int ret = acpi_create_platform_clks(adev);
>>>>    		dev_err(&adev->dev, "failed to create clocks\n");
>>>> -		return NULL;
>>>> +		return ret;
>>>>    	}
>>>
>>> If (flag & ACPI_PLATFORM_CLK) is true, the acpi_create_platform_device()
>>> always retruns with dev_err() messages. Why?
>>
>> Ah.  By mistake. :-)
>>
>> Thanks for poiting this out!
>
> Updated patch is appended.
>
> Thanks,
> Rafael
>
> ---
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Subject: ACPI / platform: Use struct acpi_scan_handler for creating devices
>
> Currently, the ACPI namespace scanning code creates platform device
> objects for ACPI device nodes whose IDs match the contents of the
> acpi_platform_device_ids[] table.  However, this adds a superfluous
> special case into acpi_bus_device_attach() and makes it more
> difficult to follow than it has to be.  It also will make it more
> difficult to implement removal code for those platform device objects
> in the future.
>
> For the above reasons, introduce a struct acpi_scan_handler object
> for creating platform devices and move the code related to that from
> acpi_bus_device_attach() to the .attach() callback of that object.
> Also move the acpi_platform_device_ids[] table to acpi_platform.c.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---

Acked-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>

>   drivers/acpi/acpi_platform.c |   59 ++++++++++++++++++++++++++++++++++---------
>   drivers/acpi/internal.h      |    7 -----
>   drivers/acpi/scan.c          |   30 ---------------------
>   3 files changed, 50 insertions(+), 46 deletions(-)
>
> Index: test/drivers/acpi/acpi_platform.c
> ===================================================================
> --- test.orig/drivers/acpi/acpi_platform.c
> +++ test/drivers/acpi/acpi_platform.c
> @@ -22,6 +22,30 @@
>
>   ACPI_MODULE_NAME("platform");
>
> +/* Flags for acpi_create_platform_device */
> +#define ACPI_PLATFORM_CLK	BIT(0)
> +
> +/*
> + * The following ACPI IDs are known to be suitable for representing as
> + * platform devices.
> + */
> +static const struct acpi_device_id acpi_platform_device_ids[] = {
> +
> +	{ "PNP0D40" },
> +
> +	/* Haswell LPSS devices */
> +	{ "INT33C0", ACPI_PLATFORM_CLK },
> +	{ "INT33C1", ACPI_PLATFORM_CLK },
> +	{ "INT33C2", ACPI_PLATFORM_CLK },
> +	{ "INT33C3", ACPI_PLATFORM_CLK },
> +	{ "INT33C4", ACPI_PLATFORM_CLK },
> +	{ "INT33C5", ACPI_PLATFORM_CLK },
> +	{ "INT33C6", ACPI_PLATFORM_CLK },
> +	{ "INT33C7", ACPI_PLATFORM_CLK },
> +
> +	{ }
> +};
> +
>   static int acpi_create_platform_clks(struct acpi_device *adev)
>   {
>   	static struct platform_device *pdev;
> @@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
>   /**
>    * acpi_create_platform_device - Create platform device for ACPI device node
>    * @adev: ACPI device node to create a platform device for.
> - * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
> - *	   devices.
> + * @id: ACPI device ID used to match @adev.
>    *
>    * Check if the given @adev can be represented as a platform device and, if
>    * that's the case, create and register a platform device, populate its common
> @@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
>    *
>    * Name of the platform device will be the same as @adev's.
>    */
> -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
> -						    unsigned long flags)
> +static int acpi_create_platform_device(struct acpi_device *adev,
> +				       const struct acpi_device_id *id)
>   {
> +	unsigned long flags = id->driver_data;
>   	struct platform_device *pdev = NULL;
>   	struct acpi_device *acpi_parent;
>   	struct platform_device_info pdevinfo;
> @@ -59,25 +83,28 @@ struct platform_device *acpi_create_plat
>   	struct resource *resources;
>   	int count;
>
> -	if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
> -		dev_err(&adev->dev, "failed to create clocks\n");
> -		return NULL;
> +	if (flags & ACPI_PLATFORM_CLK) {
> +		int ret = acpi_create_platform_clks(adev);
> +		if (ret) {
> +			dev_err(&adev->dev, "failed to create clocks\n");
> +			return ret;
> +		}
>   	}
>
>   	/* If the ACPI node already has a physical device attached, skip it. */
>   	if (adev->physical_node_count)
> -		return NULL;
> +		return 0;
>
>   	INIT_LIST_HEAD(&resource_list);
>   	count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
>   	if (count <= 0)
> -		return NULL;
> +		return 0;
>
>   	resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
>   	if (!resources) {
>   		dev_err(&adev->dev, "No memory for resources\n");
>   		acpi_dev_free_resource_list(&resource_list);
> -		return NULL;
> +		return -ENOMEM;
>   	}
>   	count = 0;
>   	list_for_each_entry(rentry, &resource_list, node)
> @@ -123,5 +150,15 @@ struct platform_device *acpi_create_plat
>   	}
>
>   	kfree(resources);
> -	return pdev;
> +	return 1;
> +}
> +
> +static struct acpi_scan_handler platform_handler = {
> +	.ids = acpi_platform_device_ids,
> +	.attach = acpi_create_platform_device,
> +};
> +
> +void __init acpi_platform_init(void)
> +{
> +	acpi_scan_add_handler(&platform_handler);
>   }
> Index: test/drivers/acpi/internal.h
> ===================================================================
> --- test.orig/drivers/acpi/internal.h
> +++ test/drivers/acpi/internal.h
> @@ -27,6 +27,7 @@ int init_acpi_device_notify(void);
>   int acpi_scan_init(void);
>   void acpi_pci_root_init(void);
>   void acpi_pci_link_init(void);
> +void acpi_platform_init(void);
>   int acpi_sysfs_init(void);
>   void acpi_csrt_init(void);
>
> @@ -119,10 +120,4 @@ static inline void suspend_nvs_restore(v
>     -------------------------------------------------------------------------- */
>   struct platform_device;
>
> -/* Flags for acpi_create_platform_device */
> -#define ACPI_PLATFORM_CLK	BIT(0)
> -
> -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
> -						    unsigned long flags);
> -
>   #endif /* _ACPI_INTERNAL_H_ */
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -29,27 +29,6 @@ extern struct acpi_device *acpi_root;
>
>   static const char *dummy_hid = "device";
>
> -/*
> - * The following ACPI IDs are known to be suitable for representing as
> - * platform devices.
> - */
> -static const struct acpi_device_id acpi_platform_device_ids[] = {
> -
> -	{ "PNP0D40" },
> -
> -	/* Haswell LPSS devices */
> -	{ "INT33C0", ACPI_PLATFORM_CLK },
> -	{ "INT33C1", ACPI_PLATFORM_CLK },
> -	{ "INT33C2", ACPI_PLATFORM_CLK },
> -	{ "INT33C3", ACPI_PLATFORM_CLK },
> -	{ "INT33C4", ACPI_PLATFORM_CLK },
> -	{ "INT33C5", ACPI_PLATFORM_CLK },
> -	{ "INT33C6", ACPI_PLATFORM_CLK },
> -	{ "INT33C7", ACPI_PLATFORM_CLK },
> -
> -	{ }
> -};
> -
>   static LIST_HEAD(acpi_device_list);
>   static LIST_HEAD(acpi_bus_id_list);
>   static DEFINE_MUTEX(acpi_scan_lock);
> @@ -1606,7 +1585,6 @@ static int acpi_scan_attach_handler(stru
>   static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
>   					  void *not_used, void **ret_not_used)
>   {
> -	const struct acpi_device_id *id;
>   	struct acpi_device *device;
>   	unsigned long long sta_not_used;
>   	int ret;
> @@ -1621,13 +1599,6 @@ static acpi_status acpi_bus_device_attac
>   	if (acpi_bus_get_device(handle, &device))
>   		return AE_CTRL_DEPTH;
>
> -	id = __acpi_match_device(device, acpi_platform_device_ids);
> -	if (id) {
> -		/* This is a known good platform device. */
> -		acpi_create_platform_device(device, id->driver_data);
> -		return AE_OK;
> -	}
> -
>   	ret = acpi_scan_attach_handler(device);
>   	if (ret)
>   		return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
> @@ -1775,6 +1746,7 @@ int __init acpi_scan_init(void)
>
>   	acpi_pci_root_init();
>   	acpi_pci_link_init();
> +	acpi_platform_init();
>   	acpi_csrt_init();
>
>   	/*
>
>
>



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 0/4] ACPI scan handlers
  2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
                     ` (5 preceding siblings ...)
  2013-01-29  2:33   ` Toshi Kani
@ 2013-01-30  1:58   ` Toshi Kani
  2013-01-30 13:36     ` Rafael J. Wysocki
  2013-02-03 23:45   ` [PATCH 0/2] ACPI scan handler for memory hotplug and container simplification Rafael J. Wysocki
  7 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-01-30  1:58 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Mon, 2013-01-28 at 13:58 +0100, Rafael J. Wysocki wrote:
> On Thursday, January 24, 2013 01:26:56 AM Rafael J. Wysocki wrote:
> > Hi All,
> > 
> > There is a considerable amount of confusion in the ACPI subsystem about what
> > ACPI drivers are used for.  Namely, some of them are used as "normal" device
> > drivers that bind to devices and handle them using ACPI control methods (like
> > the fan or battery drivers), but some of them are just used for handling
> > namespace events, such as the creation or removal of device nodes (I guess it
> > would be fair to call that an abuse of the driver core).  These two roles are
> > quite distinct, which is particularly visible from the confusion about the role
> > of the .remove() callback.
> > 
> > For the "normal" drivers this callback is simply used to handle situations in
> > which the driver needs to be unbound from the device, because one of them
> > (either the device or the driver) is going away.  That operation can't really
> > fail, it just needs to do the necessary cleanup.
> > 
> > However, for the namespace events handling "drivers" .remove() means that not
> > only the device node in question, but generally also the whole subtree below it
> > needs to be prepared for removal, which may involve deleting multiple device
> > objects belonging to different bus types and so on and which very well may fail
> > (for example, those devices may be used for such things like swap or they may be
> > memory banks used by the kernel and it may not be safe to remove them at the
> > moment etc.).  Moreover, for these things the removal of the "driver" doesn't
> > really make sense, because it has to be there to handle the namespace events it
> > is designed to handle or else things will go remarkably awry in some places.
> > 
> > To resolve all that mess I'd like to do the following, which in part is inspired
> > by the recent Toshi Kani's hotplug framework proposal and in part is based on
> > some discussions I had with Bjorn and others (the code references made below are
> > based on the current contens of linux-pm.git/linux-next).
> > 
> > 1) Introduce a special data type for "ACPI namespace event handlers" like:
> > 
> > struct acpi_scan_handler {
> > 	const struct acpi_device_id *ids;
> > 	struct list_head list_node;
> > 	int (*attach)(struct acpi_device *adev);
> > 	int (*untie)(struct acpi_device *adev);
> > 	int (*reclaim)(struct acpi_device *adev);
> > 	void (*detach)(struct acpi_device *adev);
> > };
> 
> After some reconsideration I think that the "untie" and "reclaim" things won't
> be really useful at this level.  This means that I only need ACPI scan handlers
> to do .attach() and .detach() and all of that becomes really simple, so I don't
> see reason to wait with that change.
> 
> The following patches introduce ACPI scan handlers and make some use of them.
> 
> [1/4] Introduce struct acpi_scan_handler for configuration tasks depending on
>       device IDs.
> 
> [2/4] Make ACPI PCI root driver use struct acpi_scan_handler.
> 
> [3/4] Make ACPI PCI IRQ link driver use struct acpi_scan_handler.
> 
> [4/4] Use struct acpi_scan_handler for creating platform devices enumerated via ACPI.

For the series:

Acked-by: Toshi Kani <toshi.kani@hp.com>

Thanks,
-Toshi



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
  2013-01-29 23:27                 ` Toshi Kani
@ 2013-01-30 13:18                   ` Rafael J. Wysocki
  2013-02-03  0:52                     ` [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-30 13:18 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Tuesday, January 29, 2013 04:27:28 PM Toshi Kani wrote:
> On Wed, 2013-01-30 at 00:19 +0100, Rafael J. Wysocki wrote:
> > On Tuesday, January 29, 2013 03:57:10 PM Toshi Kani wrote:
> > > On Tue, 2013-01-29 at 22:32 +0100, Rafael J. Wysocki wrote:
> > > > On Tuesday, January 29, 2013 07:50:43 AM Toshi Kani wrote:
> > > > > On Tue, 2013-01-29 at 12:28 +0100, Rafael J. Wysocki wrote:
> > > > > > On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> > > > > > > On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > > > > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > > > 
> > > > > > > > Introduce struct acpi_scan_handler for representing objects that
> > > > > > > > will do configuration tasks depending on ACPI device nodes'
> > > > > > > > hardware IDs (HIDs).
> > > > > > > > 
> > > > > > > > Currently, those tasks are done either directly by the ACPI namespace
> > > > > > > > scanning code or by ACPI device drivers designed specifically for
> > > > > > > > this purpose.  None of the above is desirable, however, because
> > > > > > > > doing that directly in the namespace scanning code makes that code
> > > > > > > > overly complicated and difficult to follow and doing that in
> > > > > > > > "special" device drivers leads to a great deal of confusion about
> > > > > > > > their role and to confusing interactions with the driver core (for
> > > > > > > > example, sysfs directories are created for those drivers, but they
> > > > > > > > are completely unnecessary and only increase the kernel's memory
> > > > > > > > footprint in vain).
> > > > > > > > 
> > > > > > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > > > ---
> > > > > > > >  Documentation/acpi/scan_handlers.txt |   77 +++++++++++++++++++++++++++++++++++
> > > > > > > >  drivers/acpi/scan.c                  |   60 ++++++++++++++++++++++++---
> > > > > > > >  include/acpi/acpi_bus.h              |   14 ++++++
> > > > > > > >  3 files changed, 144 insertions(+), 7 deletions(-)
> > > > > > > > 
> > > > > > > > Index: test/include/acpi/acpi_bus.h
> > > > > > > > ===================================================================
> > > > > > > > --- test.orig/include/acpi/acpi_bus.h
> > > > > > > > +++ test/include/acpi/acpi_bus.h
> > > > > > > > @@ -84,6 +84,18 @@ struct acpi_driver;
> > > > > > > >  struct acpi_device;
> > > > > > > >  
> > > > > > > >  /*
> > > > > > > > + * ACPI Scan Handler
> > > > > > > > + * -----------------
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +struct acpi_scan_handler {
> > > > > > > > +	const struct acpi_device_id *ids;
> > > > > > > > +	struct list_head list_node;
> > > > > > > > +	int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > > > > > > > +	void (*detach)(struct acpi_device *dev);
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +/*
> > > > > > > >   * ACPI Driver
> > > > > > > >   * -----------
> > > > > > > >   */
> > > > > > > > @@ -269,6 +281,7 @@ struct acpi_device {
> > > > > > > >  	struct acpi_device_wakeup wakeup;
> > > > > > > >  	struct acpi_device_perf performance;
> > > > > > > >  	struct acpi_device_dir dir;
> > > > > > > > +	struct acpi_scan_handler *handler;
> > > > > > > >  	struct acpi_driver *driver;
> > > > > > > >  	void *driver_data;
> > > > > > > >  	struct device dev;
> > > > > > > > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > > > > > > >  static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > > > > > > >  	{ return 0; }
> > > > > > > >  #endif
> > > > > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > > > > > > >  int acpi_bus_register_driver(struct acpi_driver *driver);
> > > > > > > >  void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > > > > > > >  int acpi_bus_scan(acpi_handle handle);
> > > > > > > > Index: test/drivers/acpi/scan.c
> > > > > > > > ===================================================================
> > > > > > > > --- test.orig/drivers/acpi/scan.c
> > > > > > > > +++ test/drivers/acpi/scan.c
> > > > > > > > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > > > > > > >  static LIST_HEAD(acpi_device_list);
> > > > > > > >  static LIST_HEAD(acpi_bus_id_list);
> > > > > > > >  static DEFINE_MUTEX(acpi_scan_lock);
> > > > > > > > +static LIST_HEAD(acpi_scan_handlers_list);
> > > > > > > >  DEFINE_MUTEX(acpi_device_lock);
> > > > > > > >  LIST_HEAD(acpi_wakeup_device_list);
> > > > > > > >  
> > > > > > > > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > > > > > > >  	struct list_head node;
> > > > > > > >  };
> > > > > > > >  
> > > > > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > > > > > > > +{
> > > > > > > > +	if (!handler || !handler->attach)
> > > > > > > > +		return -EINVAL;
> > > > > > > > +
> > > > > > > > +	list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > > > > > > > +	return 0;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > >  /*
> > > > > > > >   * Creates hid/cid(s) string needed for modalias and uevent
> > > > > > > >   * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > > > > > > > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > > > > > > >  	return AE_OK;
> > > > > > > >  }
> > > > > > > >  
> > > > > > > > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > > > > > > > +{
> > > > > > > > +	struct acpi_scan_handler *handler;
> > > > > > > > +	int ret = 0;
> > > > > > > > +
> > > > > > > > +	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > > > > > > > +		const struct acpi_device_id *id;
> > > > > > > > +
> > > > > > > > +		id = __acpi_match_device(device, handler->ids);
> > > > > > > > +		if (!id)
> > > > > > > > +			continue;
> > > > > > > > +
> > > > > > > > +		ret = handler->attach(device, id);
> > > > > > > > +		if (ret > 0) {
> > > > > > > > +			device->handler = handler;
> > > > > > > > +			break;
> > > > > > > > +		} else if (ret < 0) {
> > > > > > > > +			break;
> > > > > > > > +		}
> > > > > > > > +	}
> > > > > > > > +	return ret;
> > > > > > > > +}
> > > > > > > 
> > > > > > > Now that we have full control over the attach logic, it would be great
> > > > > > > if we can update it to match with the ACPI spec -- HID has priority over
> > > > > > > CIDs, and CIDs are also listed in their priority.  For example, Device-X
> > > > > > > has HID and CID.  In this case, this Device-X should be attached to
> > > > > > > Handler-A since it supports HID.  The current logic simply chooses a
> > > > > > > handler whichever registered before.  
> > > > > > > 
> > > > > > > Device-X: HID PNPID-A, CID PNPID-B
> > > > > > > Handler-A: PNPID-A
> > > > > > > Handler-B: PNPID-B
> > > > > > > 
> > > > > > > So, the attach logic should be something like:
> > > > > > > 
> > > > > > > list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> > > > > > > 	list_for_each_entry(,&acpi_scan_handlers_list,)
> > > > > > > 		check if this handler supports a given hwid
> > > > > > > }
> > > > > > 
> > > > > > OK, I see the problem, but I think it's better to address it in a separate
> > > > > > patch on top of the current series.
> > > > > 
> > > > > I agree.
> > > > > 
> > > > > > I'm not sure what approach is best, though.  Do you think there should be two
> > > > > > passes the first of which will check HIDs only and the second one will check
> > > > > > CIDs?  Or do you have something different in mind?
> > > > > 
> > > > > HID and CIDs are already listed in their priority order in
> > > > > acpi_device->pnp.ids.  So, the single pass like I described above should
> > > > > work.
> > > > 
> > > > Well, I'm not sure if I understand you correctly.
> > > > 
> > > > The device is given and we need to find a handler for it.  So, it looks like
> > > > we first should check if any handler matches the HID.  This has to be a pass
> > > > through all handlers.  If there's no match, we need to check if any handler
> > > > matches any of the device IDs.  That will be the second pass, won't it?
> > > 
> > > acpi_device->pnp.ids has a list of HID->CID[0]->CID[1]..CID[n] since
> > > acpi_device_set_id() checks HID before CIDs.  So, the first pass is to
> > > check with the first entry of pnp.ids.  If no handler is found, then
> > > check the second entry, and so on.
> > 
> > I'd prefer to check HID and then all CIDs at once in accordance with the
> > following rule:
> > 1) Use the first handler that matches HID exactly.  If there's none:
> > 2) Use the first handler compatible with the given device.
> 
> What do you mean by all CIDs at once?  CIDs also have priority when
> there are multiple CIDs.  That is, CID[0] takes priority over CID[1].
> So, going down the pnp.ids list handles the ordering correctly.

OK, I see what you mean now.

> > > > The difficulty is that the first item in pnp.ids need not be *the* HID.
> > > > It only will be the HID if ACPI_VALID_HID is set in the device info in
> > > > acpi_device_set_id().  So perhaps we need to add a hid_valid bit in
> > > > device->flags and only do the "HID pass" if that is set?
> > > 
> > > I do not think such bit is necessary for this.  _HID is required (unless
> > > it has _ADR), but _CID is optional.  So, the valid cases are that a
> > > device object has HID only, has both HID and CID(s), or has none of them
> > > (i.e. _ADR device).  If there is a device with CID only, this is a FW
> > > bug and we just have to check with CID then.
> > 
> > In addition to that there's a number of objects that we assign artificial HIDs.
> > I think we should treat them as CIDs rather than as real HIDs in this regard.
> 
> When an object does not support the _HID/_CID combination, it means that
> this type of objects can only support a single characteristic, which is
> the same as a device object with HID only.  Therefore, an artificial ID
> should be considered as an HID.

I'm not sure about that, but it shouldn't really matter a lot anyway. :-)

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 0/4] ACPI scan handlers
  2013-01-30  1:58   ` Toshi Kani
@ 2013-01-30 13:36     ` Rafael J. Wysocki
  0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-30 13:36 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Tuesday, January 29, 2013 06:58:30 PM Toshi Kani wrote:
> On Mon, 2013-01-28 at 13:58 +0100, Rafael J. Wysocki wrote:
> > On Thursday, January 24, 2013 01:26:56 AM Rafael J. Wysocki wrote:
> > > Hi All,
> > > 
> > > There is a considerable amount of confusion in the ACPI subsystem about what
> > > ACPI drivers are used for.  Namely, some of them are used as "normal" device
> > > drivers that bind to devices and handle them using ACPI control methods (like
> > > the fan or battery drivers), but some of them are just used for handling
> > > namespace events, such as the creation or removal of device nodes (I guess it
> > > would be fair to call that an abuse of the driver core).  These two roles are
> > > quite distinct, which is particularly visible from the confusion about the role
> > > of the .remove() callback.
> > > 
> > > For the "normal" drivers this callback is simply used to handle situations in
> > > which the driver needs to be unbound from the device, because one of them
> > > (either the device or the driver) is going away.  That operation can't really
> > > fail, it just needs to do the necessary cleanup.
> > > 
> > > However, for the namespace events handling "drivers" .remove() means that not
> > > only the device node in question, but generally also the whole subtree below it
> > > needs to be prepared for removal, which may involve deleting multiple device
> > > objects belonging to different bus types and so on and which very well may fail
> > > (for example, those devices may be used for such things like swap or they may be
> > > memory banks used by the kernel and it may not be safe to remove them at the
> > > moment etc.).  Moreover, for these things the removal of the "driver" doesn't
> > > really make sense, because it has to be there to handle the namespace events it
> > > is designed to handle or else things will go remarkably awry in some places.
> > > 
> > > To resolve all that mess I'd like to do the following, which in part is inspired
> > > by the recent Toshi Kani's hotplug framework proposal and in part is based on
> > > some discussions I had with Bjorn and others (the code references made below are
> > > based on the current contens of linux-pm.git/linux-next).
> > > 
> > > 1) Introduce a special data type for "ACPI namespace event handlers" like:
> > > 
> > > struct acpi_scan_handler {
> > > 	const struct acpi_device_id *ids;
> > > 	struct list_head list_node;
> > > 	int (*attach)(struct acpi_device *adev);
> > > 	int (*untie)(struct acpi_device *adev);
> > > 	int (*reclaim)(struct acpi_device *adev);
> > > 	void (*detach)(struct acpi_device *adev);
> > > };
> > 
> > After some reconsideration I think that the "untie" and "reclaim" things won't
> > be really useful at this level.  This means that I only need ACPI scan handlers
> > to do .attach() and .detach() and all of that becomes really simple, so I don't
> > see reason to wait with that change.
> > 
> > The following patches introduce ACPI scan handlers and make some use of them.
> > 
> > [1/4] Introduce struct acpi_scan_handler for configuration tasks depending on
> >       device IDs.
> > 
> > [2/4] Make ACPI PCI root driver use struct acpi_scan_handler.
> > 
> > [3/4] Make ACPI PCI IRQ link driver use struct acpi_scan_handler.
> > 
> > [4/4] Use struct acpi_scan_handler for creating platform devices enumerated via ACPI.
> 
> For the series:
> 
> Acked-by: Toshi Kani <toshi.kani@hp.com>

Thanks!

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers
  2013-01-30 13:18                   ` Rafael J. Wysocki
@ 2013-02-03  0:52                     ` Rafael J. Wysocki
  2013-02-03  4:54                       ` Yinghai Lu
  2013-02-05 23:44                       ` Toshi Kani
  0 siblings, 2 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-03  0:52 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

The IDs of ACPI device nodes stored in their pnp.ids member arrays
are sorted by decreasing priority (i.e. the highest-priority ID is
the first entry).  This means that when matching scan handlers to
device nodes, the namespace scanning code should walk the list of
scan handlers for each device node ID instead of walking the list
of device node IDs for each handler (the latter causes the first
handler matching any of the device node IDs to be chosen, although
there may be another handler matching an ID of a higher priority
which should be preferred).  Make the code follow this observation.

This change has been suggested and justified by Toshi Kani.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c |   42 +++++++++++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 13 deletions(-)

Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -1556,26 +1556,42 @@ static acpi_status acpi_bus_check_add(ac
 	return AE_OK;
 }
 
-static int acpi_scan_attach_handler(struct acpi_device *device)
+static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id)
 {
 	struct acpi_scan_handler *handler;
-	int ret = 0;
 
 	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
-		const struct acpi_device_id *id;
+		const struct acpi_device_id *devid;
 
-		id = __acpi_match_device(device, handler->ids);
-		if (!id)
-			continue;
-
-		ret = handler->attach(device, id);
-		if (ret > 0) {
-			device->handler = handler;
-			break;
-		} else if (ret < 0) {
-			break;
+		for (devid = handler->ids; devid->id[0]; devid++) {
+			int ret;
+
+			if (strcmp((char *)devid->id, id))
+				continue;
+
+			ret = handler->attach(device, devid);
+			if (ret > 0) {
+				device->handler = handler;
+				return ret;
+			} else if (ret < 0) {
+				return ret;
+			}
 		}
 	}
+	return 0;
+}
+
+static int acpi_scan_attach_handler(struct acpi_device *device)
+{
+	struct acpi_hardware_id *hwid;
+	int ret = 0;
+
+	list_for_each_entry(hwid, &device->pnp.ids, list) {
+		ret = acpi_scan_do_attach_handler(device, hwid->id);
+		if (ret)
+			break;
+
+	}
 	return ret;
 }
 


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers
  2013-02-03  0:52                     ` [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers Rafael J. Wysocki
@ 2013-02-03  4:54                       ` Yinghai Lu
  2013-02-03 13:05                         ` Rafael J. Wysocki
  2013-02-05 23:44                       ` Toshi Kani
  1 sibling, 1 reply; 71+ messages in thread
From: Yinghai Lu @ 2013-02-03  4:54 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Toshi Kani, ACPI Devel Maling List, Greg Kroah-Hartman,
	Bjorn Helgaas, Mika Westerberg, Matthew Garrett, Jiang Liu, LKML

On Sat, Feb 2, 2013 at 4:52 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> The IDs of ACPI device nodes stored in their pnp.ids member arrays
> are sorted by decreasing priority (i.e. the highest-priority ID is
> the first entry).  This means that when matching scan handlers to
> device nodes, the namespace scanning code should walk the list of
> scan handlers for each device node ID instead of walking the list
> of device node IDs for each handler (the latter causes the first
> handler matching any of the device node IDs to be chosen, although
> there may be another handler matching an ID of a higher priority
> which should be preferred).  Make the code follow this observation.
>
> This change has been suggested and justified by Toshi Kani.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/acpi/scan.c |   42 +++++++++++++++++++++++++++++-------------
>  1 file changed, 29 insertions(+), 13 deletions(-)
>
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -1556,26 +1556,42 @@ static acpi_status acpi_bus_check_add(ac
>         return AE_OK;
>  }
>
> -static int acpi_scan_attach_handler(struct acpi_device *device)
> +static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id)
>  {
>         struct acpi_scan_handler *handler;
> -       int ret = 0;
>
>         list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> -               const struct acpi_device_id *id;
> +               const struct acpi_device_id *devid;
>
> -               id = __acpi_match_device(device, handler->ids);
> -               if (!id)
> -                       continue;
> -
> -               ret = handler->attach(device, id);
> -               if (ret > 0) {
> -                       device->handler = handler;
> -                       break;
> -               } else if (ret < 0) {
> -                       break;
> +               for (devid = handler->ids; devid->id[0]; devid++) {
> +                       int ret;
> +
> +                       if (strcmp((char *)devid->id, id))
> +                               continue;
> +
> +                       ret = handler->attach(device, devid);
> +                       if (ret > 0) {
> +                               device->handler = handler;
> +                               return ret;
> +                       } else if (ret < 0) {
> +                               return ret;
> +                       }
>                 }
>         }
> +       return 0;
> +}
> +
> +static int acpi_scan_attach_handler(struct acpi_device *device)
> +{
> +       struct acpi_hardware_id *hwid;
> +       int ret = 0;
> +
> +       list_for_each_entry(hwid, &device->pnp.ids, list) {
> +               ret = acpi_scan_do_attach_handler(device, hwid->id);
> +               if (ret)
> +                       break;
> +
> +       }
>         return ret;
>  }
>
>

Looks like right to honor the order in pnp.ids.

so there is same problem with acpi_bus_match/acpi_match_device_ids
that need to fixed?

Yinghai

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers
  2013-02-03  4:54                       ` Yinghai Lu
@ 2013-02-03 13:05                         ` Rafael J. Wysocki
  0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-03 13:05 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Toshi Kani, ACPI Devel Maling List, Greg Kroah-Hartman,
	Bjorn Helgaas, Mika Westerberg, Matthew Garrett, Jiang Liu, LKML

On Saturday, February 02, 2013 08:54:46 PM Yinghai Lu wrote:
> On Sat, Feb 2, 2013 at 4:52 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > The IDs of ACPI device nodes stored in their pnp.ids member arrays
> > are sorted by decreasing priority (i.e. the highest-priority ID is
> > the first entry).  This means that when matching scan handlers to
> > device nodes, the namespace scanning code should walk the list of
> > scan handlers for each device node ID instead of walking the list
> > of device node IDs for each handler (the latter causes the first
> > handler matching any of the device node IDs to be chosen, although
> > there may be another handler matching an ID of a higher priority
> > which should be preferred).  Make the code follow this observation.
> >
> > This change has been suggested and justified by Toshi Kani.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >  drivers/acpi/scan.c |   42 +++++++++++++++++++++++++++++-------------
> >  1 file changed, 29 insertions(+), 13 deletions(-)
> >
> > Index: test/drivers/acpi/scan.c
> > ===================================================================
> > --- test.orig/drivers/acpi/scan.c
> > +++ test/drivers/acpi/scan.c
> > @@ -1556,26 +1556,42 @@ static acpi_status acpi_bus_check_add(ac
> >         return AE_OK;
> >  }
> >
> > -static int acpi_scan_attach_handler(struct acpi_device *device)
> > +static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id)
> >  {
> >         struct acpi_scan_handler *handler;
> > -       int ret = 0;
> >
> >         list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > -               const struct acpi_device_id *id;
> > +               const struct acpi_device_id *devid;
> >
> > -               id = __acpi_match_device(device, handler->ids);
> > -               if (!id)
> > -                       continue;
> > -
> > -               ret = handler->attach(device, id);
> > -               if (ret > 0) {
> > -                       device->handler = handler;
> > -                       break;
> > -               } else if (ret < 0) {
> > -                       break;
> > +               for (devid = handler->ids; devid->id[0]; devid++) {
> > +                       int ret;
> > +
> > +                       if (strcmp((char *)devid->id, id))
> > +                               continue;
> > +
> > +                       ret = handler->attach(device, devid);
> > +                       if (ret > 0) {
> > +                               device->handler = handler;
> > +                               return ret;
> > +                       } else if (ret < 0) {
> > +                               return ret;
> > +                       }
> >                 }
> >         }
> > +       return 0;
> > +}
> > +
> > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > +{
> > +       struct acpi_hardware_id *hwid;
> > +       int ret = 0;
> > +
> > +       list_for_each_entry(hwid, &device->pnp.ids, list) {
> > +               ret = acpi_scan_do_attach_handler(device, hwid->id);
> > +               if (ret)
> > +                       break;
> > +
> > +       }
> >         return ret;
> >  }
> >
> >
> 
> Looks like right to honor the order in pnp.ids.
> 
> so there is same problem with acpi_bus_match/acpi_match_device_ids
> that need to fixed?

Yes, there is the same problem, but I'm not sure we can actually fix it.

The driver core walks the list of available drivers for the given bus just
once in bus_probe_device(), so it cannot check all drivers against each of
the given device IDs.  So it looks like acpi_bus_match() does all it can do
(one more reason to get rid of the ACPI bus type IMHO).

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 0/2] ACPI scan handler for memory hotplug and container simplification
  2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
                     ` (6 preceding siblings ...)
  2013-01-30  1:58   ` Toshi Kani
@ 2013-02-03 23:45   ` Rafael J. Wysocki
  2013-02-03 23:46     ` [PATCH 1/2] ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler Rafael J. Wysocki
  2013-02-03 23:47     ` [PATCH 2/2] ACPI / scan: Simplify container driver Rafael J. Wysocki
  7 siblings, 2 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-03 23:45 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

Hi All,

Patch [1/2] in this series makes the ACPI memory hotplug driver use struct
acpi_scan_handler instead of struct acpi_driver and changes the driver to
non-modular (as a consequence).

Patch [2/2] is a bit funny, though.  I though I'd make the container driver
use struct acpi_scan_handler instead of struct acpi_driver too, but then I
noticed that its struct acpi_driver and everything it does is just plain
garbage without any use whatsoever, so the patch simply drops that stuff.

Both on top of linux-pm.git/bleeding-edge.  Unfortunately, I don't have the
hardware to test those things, so if anyone can test them, I'll appreciate it
a lot.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 1/2] ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler
  2013-02-03 23:45   ` [PATCH 0/2] ACPI scan handler for memory hotplug and container simplification Rafael J. Wysocki
@ 2013-02-03 23:46     ` Rafael J. Wysocki
  2013-02-03 23:47     ` [PATCH 2/2] ACPI / scan: Simplify container driver Rafael J. Wysocki
  1 sibling, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-03 23:46 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Make the ACPI memory hotplug driver use struct acpi_scan_handler
for representing the object used to set up ACPI memory hotplug
functionality and to remove hotplug memory ranges and data
structures used by the driver before unregistering ACPI device
nodes representing memory.

This simplifies the code and reduces the kernel's memory footprint by
avoiding the registration of a struct device_driver object with the
driver core and creation of its sysfs directory which is unnecessary.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/Kconfig           |    3 
 drivers/acpi/acpi_memhotplug.c |  180 ++++++++++-------------------------------
 drivers/acpi/internal.h        |    5 +
 drivers/acpi/scan.c            |    1 
 4 files changed, 54 insertions(+), 135 deletions(-)

Index: test/drivers/acpi/Kconfig
===================================================================
--- test.orig/drivers/acpi/Kconfig
+++ test/drivers/acpi/Kconfig
@@ -347,9 +347,8 @@ config ACPI_CONTAINER
 	  the module will be called container.
 
 config ACPI_HOTPLUG_MEMORY
-	tristate "Memory Hotplug"
+	bool "Memory Hotplug"
 	depends on MEMORY_HOTPLUG
-	default n
 	help
 	  This driver supports ACPI memory hotplug.  The driver
 	  fields notifications on ACPI memory devices (PNP0C80),
Index: test/drivers/acpi/acpi_memhotplug.c
===================================================================
--- test.orig/drivers/acpi/acpi_memhotplug.c
+++ test/drivers/acpi/acpi_memhotplug.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2004 Intel Corporation <naveen.b.s@intel.com>
+ * Copyright (C) 2004 Intel Corporation
+ * Author: Naveen B S <naveen.b.s@intel.com>
  *
  * All rights reserved.
  *
@@ -44,17 +45,15 @@
 #define 	PREFIX		"ACPI:memory_hp:"
 
 ACPI_MODULE_NAME("acpi_memhotplug");
-MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
-MODULE_DESCRIPTION("Hotplug Mem Driver");
-MODULE_LICENSE("GPL");
 
 /* Memory Device States */
 #define MEMORY_INVALID_STATE	0
 #define MEMORY_POWER_ON_STATE	1
 #define MEMORY_POWER_OFF_STATE	2
 
-static int acpi_memory_device_add(struct acpi_device *device);
-static int acpi_memory_device_remove(struct acpi_device *device);
+static int acpi_memory_device_add(struct acpi_device *device,
+				  const struct acpi_device_id *not_used);
+static void acpi_memory_device_remove(struct acpi_device *device);
 
 static const struct acpi_device_id memory_device_ids[] = {
 	{ACPI_MEMORY_DEVICE_HID, 0},
@@ -62,14 +61,10 @@ static const struct acpi_device_id memor
 };
 MODULE_DEVICE_TABLE(acpi, memory_device_ids);
 
-static struct acpi_driver acpi_memory_device_driver = {
-	.name = "acpi_memhotplug",
-	.class = ACPI_MEMORY_DEVICE_CLASS,
+static struct acpi_scan_handler memory_device_handler = {
 	.ids = memory_device_ids,
-	.ops = {
-		.add = acpi_memory_device_add,
-		.remove = acpi_memory_device_remove,
-		},
+	.attach = acpi_memory_device_add,
+	.detach = acpi_memory_device_remove,
 };
 
 struct acpi_memory_info {
@@ -369,14 +364,15 @@ static void acpi_memory_device_free(stru
 		return;
 
 	acpi_memory_free_device_resources(mem_device);
+	mem_device->device->driver_data = NULL;
 	kfree(mem_device);
 }
 
-static int acpi_memory_device_add(struct acpi_device *device)
+static int acpi_memory_device_add(struct acpi_device *device,
+				  const struct acpi_device_id *not_used)
 {
+	struct acpi_memory_device *mem_device;
 	int result;
-	struct acpi_memory_device *mem_device = NULL;
-
 
 	if (!device)
 		return -EINVAL;
@@ -401,147 +397,65 @@ static int acpi_memory_device_add(struct
 	/* Set the device state */
 	mem_device->state = MEMORY_POWER_ON_STATE;
 
-	pr_debug("%s\n", acpi_device_name(device));
+	result = acpi_memory_check_device(mem_device);
+	if (result) {
+		acpi_memory_device_free(mem_device);
+		return 0;
+	}
 
-	if (!acpi_memory_check_device(mem_device)) {
-		/* call add_memory func */
-		result = acpi_memory_enable_device(mem_device);
-		if (result) {
-			dev_err(&device->dev,
-				"Error in acpi_memory_enable_device\n");
-			acpi_memory_device_free(mem_device);
-		}
+	result = acpi_memory_enable_device(mem_device);
+	if (result) {
+		dev_err(&device->dev, "acpi_memory_enable_device() error\n");
+		acpi_memory_device_free(mem_device);
+		return -ENODEV;
 	}
-	return result;
+
+	dev_dbg(&device->dev, "Memory device configured by ACPI\n");
+	return 1;
 }
 
-static int acpi_memory_device_remove(struct acpi_device *device)
+static void acpi_memory_device_remove(struct acpi_device *device)
 {
-	struct acpi_memory_device *mem_device = NULL;
-	int result;
+	struct acpi_memory_device *mem_device;
 
 	if (!device || !acpi_driver_data(device))
-		return -EINVAL;
+		return;
 
 	mem_device = acpi_driver_data(device);
-
-	result = acpi_memory_remove_memory(mem_device);
-	if (result)
-		return result;
-
+	acpi_memory_remove_memory(mem_device);
 	acpi_memory_device_free(mem_device);
-
-	return 0;
 }
 
-/*
- * Helper function to check for memory device
- */
-static acpi_status is_memory_device(acpi_handle handle)
+static bool is_memory_device(acpi_handle handle)
 {
-	char *hardware_id;
-	acpi_status status;
 	struct acpi_device_info *info;
+	bool ret = false;
 
-	status = acpi_get_object_info(handle, &info);
-	if (ACPI_FAILURE(status))
-		return status;
-
-	if (!(info->valid & ACPI_VALID_HID)) {
-		kfree(info);
-		return AE_ERROR;
-	}
+	if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
+		return false;
 
-	hardware_id = info->hardware_id.string;
-	if ((hardware_id == NULL) ||
-	    (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
-		status = AE_ERROR;
+	if (info->valid & ACPI_VALID_HID)
+		ret = !strcmp(info->hardware_id.string, ACPI_MEMORY_DEVICE_HID);
 
 	kfree(info);
-	return status;
+	return ret;
 }
 
-static acpi_status
-acpi_memory_register_notify_handler(acpi_handle handle,
-				    u32 level, void *ctxt, void **retv)
+static acpi_status acpi_memory_register_notify_handler(acpi_handle handle,
+						       u32 lvl, void *ctxt,
+						       void **retv)
 {
-	acpi_status status;
+	if (is_memory_device(handle))
+		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+					    acpi_memory_device_notify, NULL);
 
-
-	status = is_memory_device(handle);
-	if (ACPI_FAILURE(status))
-		return AE_OK;	/* continue */
-
-	status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					     acpi_memory_device_notify, NULL);
-	/* continue */
 	return AE_OK;
 }
 
-static acpi_status
-acpi_memory_deregister_notify_handler(acpi_handle handle,
-				      u32 level, void *ctxt, void **retv)
-{
-	acpi_status status;
-
-
-	status = is_memory_device(handle);
-	if (ACPI_FAILURE(status))
-		return AE_OK;	/* continue */
-
-	status = acpi_remove_notify_handler(handle,
-					    ACPI_SYSTEM_NOTIFY,
-					    acpi_memory_device_notify);
-
-	return AE_OK;	/* continue */
-}
-
-static int __init acpi_memory_device_init(void)
-{
-	int result;
-	acpi_status status;
-
-
-	result = acpi_bus_register_driver(&acpi_memory_device_driver);
-
-	if (result < 0)
-		return -ENODEV;
-
-	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-				     ACPI_UINT32_MAX,
-				     acpi_memory_register_notify_handler, NULL,
-				     NULL, NULL);
-
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed"));
-		acpi_bus_unregister_driver(&acpi_memory_device_driver);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static void __exit acpi_memory_device_exit(void)
+void __init acpi_memory_hotplug_init(void)
 {
-	acpi_status status;
-
-
-	/*
-	 * Adding this to un-install notification handlers for all the device
-	 * handles.
-	 */
-	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-				     ACPI_UINT32_MAX,
-				     acpi_memory_deregister_notify_handler, NULL,
-				     NULL, NULL);
-
-	if (ACPI_FAILURE(status))
-		ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed"));
-
-	acpi_bus_unregister_driver(&acpi_memory_device_driver);
-
-	return;
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+			    acpi_memory_register_notify_handler, NULL,
+			    NULL, NULL);
+	acpi_scan_add_handler(&memory_device_handler);
 }
-
-module_init(acpi_memory_device_init);
-module_exit(acpi_memory_device_exit);
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -35,6 +35,11 @@ void acpi_pci_slot_init(void);
 #else
 static inline void acpi_pci_slot_init(void) { }
 #endif
+#ifdef CONFIG_ACPI_HOTPLUG_MEMORY
+void acpi_memory_hotplug_init(void);
+#else
+static inline void acpi_memory_hotplug_init(void) {}
+#endif
 
 #ifdef CONFIG_DEBUG_FS
 extern struct dentry *acpi_debugfs_dir;
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -1762,6 +1762,7 @@ int __init acpi_scan_init(void)
 	acpi_pci_slot_init();
 	acpi_platform_init();
 	acpi_csrt_init();
+	acpi_memory_hotplug_init();
 
 	/*
 	 * Enumerate devices in the ACPI namespace.


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-03 23:45   ` [PATCH 0/2] ACPI scan handler for memory hotplug and container simplification Rafael J. Wysocki
  2013-02-03 23:46     ` [PATCH 1/2] ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler Rafael J. Wysocki
@ 2013-02-03 23:47     ` Rafael J. Wysocki
  2013-02-06 22:32       ` Toshi Kani
                         ` (2 more replies)
  1 sibling, 3 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-03 23:47 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

The only useful thing that the ACPI container driver does is to
install system notify handlers for all container and module device
objects it finds in the namespace.  The driver structure,
acpi_container_driver, and the data structures created by its
.add() callback are in fact not used by the driver, so remove
them entirely.

It also makes a little sense to build that driver as a module,
so make it non-modular and add its initialization to the
namespace scanning code.

In addition to that, make the namespace walk callback used for
installing the notify handlers more straightforward.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/Kconfig     |    2 
 drivers/acpi/container.c |  158 ++++++-----------------------------------------
 drivers/acpi/internal.h  |    5 +
 drivers/acpi/scan.c      |    1 
 4 files changed, 30 insertions(+), 136 deletions(-)

Index: test/drivers/acpi/container.c
===================================================================
--- test.orig/drivers/acpi/container.c
+++ test/drivers/acpi/container.c
@@ -38,41 +38,15 @@
 
 #define PREFIX "ACPI: "
 
-#define ACPI_CONTAINER_DEVICE_NAME	"ACPI container device"
-#define ACPI_CONTAINER_CLASS		"container"
-
-#define INSTALL_NOTIFY_HANDLER		1
-#define UNINSTALL_NOTIFY_HANDLER	2
-
 #define _COMPONENT			ACPI_CONTAINER_COMPONENT
 ACPI_MODULE_NAME("container");
 
-MODULE_AUTHOR("Anil S Keshavamurthy");
-MODULE_DESCRIPTION("ACPI container driver");
-MODULE_LICENSE("GPL");
-
-static int acpi_container_add(struct acpi_device *device);
-static int acpi_container_remove(struct acpi_device *device);
-
 static const struct acpi_device_id container_device_ids[] = {
 	{"ACPI0004", 0},
 	{"PNP0A05", 0},
 	{"PNP0A06", 0},
 	{"", 0},
 };
-MODULE_DEVICE_TABLE(acpi, container_device_ids);
-
-static struct acpi_driver acpi_container_driver = {
-	.name = "container",
-	.class = ACPI_CONTAINER_CLASS,
-	.ids = container_device_ids,
-	.ops = {
-		.add = acpi_container_add,
-		.remove = acpi_container_remove,
-		},
-};
-
-/*******************************************************************/
 
 static int is_device_present(acpi_handle handle)
 {
@@ -92,49 +66,6 @@ static int is_device_present(acpi_handle
 	return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
 }
 
-static bool is_container_device(const char *hid)
-{
-	const struct acpi_device_id *container_id;
-
-	for (container_id = container_device_ids;
-	     container_id->id[0]; container_id++) {
-		if (!strcmp((char *)container_id->id, hid))
-			return true;
-	}
-
-	return false;
-}
-
-/*******************************************************************/
-static int acpi_container_add(struct acpi_device *device)
-{
-	struct acpi_container *container;
-
-	container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
-	if (!container)
-		return -ENOMEM;
-
-	container->handle = device->handle;
-	strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
-	strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
-	device->driver_data = container;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
-			  acpi_device_name(device), acpi_device_bid(device)));
-
-	return 0;
-}
-
-static int acpi_container_remove(struct acpi_device *device)
-{
-	acpi_status status = AE_OK;
-	struct acpi_container *pc = NULL;
-
-	pc = acpi_driver_data(device);
-	kfree(pc);
-	return status;
-}
-
 static void container_notify_cb(acpi_handle handle, u32 type, void *context)
 {
 	struct acpi_device *device = NULL;
@@ -199,84 +130,41 @@ static void container_notify_cb(acpi_han
 	return;
 }
 
-static acpi_status
-container_walk_namespace_cb(acpi_handle handle,
-			    u32 lvl, void *context, void **rv)
+static bool is_container(acpi_handle handle)
 {
-	char *hid = NULL;
 	struct acpi_device_info *info;
-	acpi_status status;
-	int *action = context;
+	bool ret = false;
 
-	status = acpi_get_object_info(handle, &info);
-	if (ACPI_FAILURE(status)) {
-		return AE_OK;
-	}
-
-	if (info->valid & ACPI_VALID_HID)
-		hid = info->hardware_id.string;
-
-	if (hid == NULL) {
-		goto end;
-	}
+	if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
+		return false;
 
-	if (!is_container_device(hid))
-		goto end;
+	if (info->valid & ACPI_VALID_HID) {
+		const struct acpi_device_id *id;
 
-	switch (*action) {
-	case INSTALL_NOTIFY_HANDLER:
-		acpi_install_notify_handler(handle,
-					    ACPI_SYSTEM_NOTIFY,
-					    container_notify_cb, NULL);
-		break;
-	case UNINSTALL_NOTIFY_HANDLER:
-		acpi_remove_notify_handler(handle,
-					   ACPI_SYSTEM_NOTIFY,
-					   container_notify_cb);
-		break;
-	default:
-		break;
+		for (id = container_device_ids; id->id[0]; id++) {
+			ret = !strcmp((char *)id->id, info->hardware_id.string);
+			if (ret)
+				break;
+		}
 	}
-
-      end:
 	kfree(info);
-
-	return AE_OK;
+	return ret;
 }
 
-static int __init acpi_container_init(void)
+static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
+							  u32 lvl, void *ctxt,
+							  void **retv)
 {
-	int result = 0;
-	int action = INSTALL_NOTIFY_HANDLER;
-
-	result = acpi_bus_register_driver(&acpi_container_driver);
-	if (result < 0) {
-		return (result);
-	}
-
-	/* register notify handler to every container device */
-	acpi_walk_namespace(ACPI_TYPE_DEVICE,
-			    ACPI_ROOT_OBJECT,
-			    ACPI_UINT32_MAX,
-			    container_walk_namespace_cb, NULL, &action, NULL);
+	if (is_container(handle))
+		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+					    container_notify_cb, NULL);
 
-	return (0);
+	return AE_OK;
 }
 
-static void __exit acpi_container_exit(void)
+void __init acpi_container_init(void)
 {
-	int action = UNINSTALL_NOTIFY_HANDLER;
-
-
-	acpi_walk_namespace(ACPI_TYPE_DEVICE,
-			    ACPI_ROOT_OBJECT,
-			    ACPI_UINT32_MAX,
-			    container_walk_namespace_cb, NULL, &action, NULL);
-
-	acpi_bus_unregister_driver(&acpi_container_driver);
-
-	return;
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+			    acpi_container_register_notify_handler, NULL,
+			    NULL, NULL);
 }
-
-module_init(acpi_container_init);
-module_exit(acpi_container_exit);
Index: test/drivers/acpi/Kconfig
===================================================================
--- test.orig/drivers/acpi/Kconfig
+++ test/drivers/acpi/Kconfig
@@ -334,7 +334,7 @@ config X86_PM_TIMER
 	  systems require this timer. 
 
 config ACPI_CONTAINER
-	tristate "Container and Module Devices (EXPERIMENTAL)"
+	bool "Container and Module Devices (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
 	default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
 	help
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -40,6 +40,11 @@ void acpi_memory_hotplug_init(void);
 #else
 static inline void acpi_memory_hotplug_init(void) {}
 #endif
+#ifdef ACPI_CONTAINER
+void acpi_container_init(void);
+#else
+static inline void acpi_container_init(void) {}
+#endif
 
 #ifdef CONFIG_DEBUG_FS
 extern struct dentry *acpi_debugfs_dir;
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -1763,6 +1763,7 @@ int __init acpi_scan_init(void)
 	acpi_platform_init();
 	acpi_csrt_init();
 	acpi_memory_hotplug_init();
+	acpi_container_init();
 
 	/*
 	 * Enumerate devices in the ACPI namespace.


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers
  2013-02-03  0:52                     ` [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers Rafael J. Wysocki
  2013-02-03  4:54                       ` Yinghai Lu
@ 2013-02-05 23:44                       ` Toshi Kani
  1 sibling, 0 replies; 71+ messages in thread
From: Toshi Kani @ 2013-02-05 23:44 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Sun, 2013-02-03 at 01:52 +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> The IDs of ACPI device nodes stored in their pnp.ids member arrays
> are sorted by decreasing priority (i.e. the highest-priority ID is
> the first entry).  This means that when matching scan handlers to
> device nodes, the namespace scanning code should walk the list of
> scan handlers for each device node ID instead of walking the list
> of device node IDs for each handler (the latter causes the first
> handler matching any of the device node IDs to be chosen, although
> there may be another handler matching an ID of a higher priority
> which should be preferred).  Make the code follow this observation.
> 
> This change has been suggested and justified by Toshi Kani.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Looks good!  Thanks for making this change. :-)

Acked-by: Toshi Kani <toshi.kani@hp.com>

-Toshi


> ---
>  drivers/acpi/scan.c |   42 +++++++++++++++++++++++++++++-------------
>  1 file changed, 29 insertions(+), 13 deletions(-)
> 
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -1556,26 +1556,42 @@ static acpi_status acpi_bus_check_add(ac
>  	return AE_OK;
>  }
>  
> -static int acpi_scan_attach_handler(struct acpi_device *device)
> +static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id)
>  {
>  	struct acpi_scan_handler *handler;
> -	int ret = 0;
>  
>  	list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> -		const struct acpi_device_id *id;
> +		const struct acpi_device_id *devid;
>  
> -		id = __acpi_match_device(device, handler->ids);
> -		if (!id)
> -			continue;
> -
> -		ret = handler->attach(device, id);
> -		if (ret > 0) {
> -			device->handler = handler;
> -			break;
> -		} else if (ret < 0) {
> -			break;
> +		for (devid = handler->ids; devid->id[0]; devid++) {
> +			int ret;
> +
> +			if (strcmp((char *)devid->id, id))
> +				continue;
> +
> +			ret = handler->attach(device, devid);
> +			if (ret > 0) {
> +				device->handler = handler;
> +				return ret;
> +			} else if (ret < 0) {
> +				return ret;
> +			}
>  		}
>  	}
> +	return 0;
> +}
> +
> +static int acpi_scan_attach_handler(struct acpi_device *device)
> +{
> +	struct acpi_hardware_id *hwid;
> +	int ret = 0;
> +
> +	list_for_each_entry(hwid, &device->pnp.ids, list) {
> +		ret = acpi_scan_do_attach_handler(device, hwid->id);
> +		if (ret)
> +			break;
> +
> +	}
>  	return ret;
>  }
>  
> 



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-03 23:47     ` [PATCH 2/2] ACPI / scan: Simplify container driver Rafael J. Wysocki
@ 2013-02-06 22:32       ` Toshi Kani
  2013-02-07  0:55         ` Rafael J. Wysocki
  2013-02-07  8:32       ` Yasuaki Ishimatsu
  2013-02-08  0:24       ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
  2 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-02-06 22:32 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> The only useful thing that the ACPI container driver does is to
> install system notify handlers for all container and module device
> objects it finds in the namespace.  The driver structure,
> acpi_container_driver, and the data structures created by its
> .add() callback are in fact not used by the driver, so remove
> them entirely.
> 
> It also makes a little sense to build that driver as a module,
> so make it non-modular and add its initialization to the
> namespace scanning code.
> 
> In addition to that, make the namespace walk callback used for
> installing the notify handlers more straightforward.

I think the container driver needs to be registered as an ACPI scan
driver so that sysfs eject will continue to work for container devices,
such as ACPI0004:XX/eject.  Since the container driver does not support
ACPI eject notification (and we have been discussing how system device
hot-plug should work), this sysfs eject is the only way to eject a
container device at this point.  I will send an update patchset that
applies on top of this patch.

With the update in my patchset:
Reviewed-by: Toshi Kani <toshi.kani@hp.com>

Thanks,
-Toshi

> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/acpi/Kconfig     |    2 
>  drivers/acpi/container.c |  158 ++++++-----------------------------------------
>  drivers/acpi/internal.h  |    5 +
>  drivers/acpi/scan.c      |    1 
>  4 files changed, 30 insertions(+), 136 deletions(-)
> 
> Index: test/drivers/acpi/container.c
> ===================================================================
> --- test.orig/drivers/acpi/container.c
> +++ test/drivers/acpi/container.c
> @@ -38,41 +38,15 @@
>  
>  #define PREFIX "ACPI: "
>  
> -#define ACPI_CONTAINER_DEVICE_NAME	"ACPI container device"
> -#define ACPI_CONTAINER_CLASS		"container"
> -
> -#define INSTALL_NOTIFY_HANDLER		1
> -#define UNINSTALL_NOTIFY_HANDLER	2
> -
>  #define _COMPONENT			ACPI_CONTAINER_COMPONENT
>  ACPI_MODULE_NAME("container");
>  
> -MODULE_AUTHOR("Anil S Keshavamurthy");
> -MODULE_DESCRIPTION("ACPI container driver");
> -MODULE_LICENSE("GPL");
> -
> -static int acpi_container_add(struct acpi_device *device);
> -static int acpi_container_remove(struct acpi_device *device);
> -
>  static const struct acpi_device_id container_device_ids[] = {
>  	{"ACPI0004", 0},
>  	{"PNP0A05", 0},
>  	{"PNP0A06", 0},
>  	{"", 0},
>  };
> -MODULE_DEVICE_TABLE(acpi, container_device_ids);
> -
> -static struct acpi_driver acpi_container_driver = {
> -	.name = "container",
> -	.class = ACPI_CONTAINER_CLASS,
> -	.ids = container_device_ids,
> -	.ops = {
> -		.add = acpi_container_add,
> -		.remove = acpi_container_remove,
> -		},
> -};
> -
> -/*******************************************************************/
>  
>  static int is_device_present(acpi_handle handle)
>  {
> @@ -92,49 +66,6 @@ static int is_device_present(acpi_handle
>  	return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
>  }
>  
> -static bool is_container_device(const char *hid)
> -{
> -	const struct acpi_device_id *container_id;
> -
> -	for (container_id = container_device_ids;
> -	     container_id->id[0]; container_id++) {
> -		if (!strcmp((char *)container_id->id, hid))
> -			return true;
> -	}
> -
> -	return false;
> -}
> -
> -/*******************************************************************/
> -static int acpi_container_add(struct acpi_device *device)
> -{
> -	struct acpi_container *container;
> -
> -	container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
> -	if (!container)
> -		return -ENOMEM;
> -
> -	container->handle = device->handle;
> -	strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
> -	strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
> -	device->driver_data = container;
> -
> -	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
> -			  acpi_device_name(device), acpi_device_bid(device)));
> -
> -	return 0;
> -}
> -
> -static int acpi_container_remove(struct acpi_device *device)
> -{
> -	acpi_status status = AE_OK;
> -	struct acpi_container *pc = NULL;
> -
> -	pc = acpi_driver_data(device);
> -	kfree(pc);
> -	return status;
> -}
> -
>  static void container_notify_cb(acpi_handle handle, u32 type, void *context)
>  {
>  	struct acpi_device *device = NULL;
> @@ -199,84 +130,41 @@ static void container_notify_cb(acpi_han
>  	return;
>  }
>  
> -static acpi_status
> -container_walk_namespace_cb(acpi_handle handle,
> -			    u32 lvl, void *context, void **rv)
> +static bool is_container(acpi_handle handle)
>  {
> -	char *hid = NULL;
>  	struct acpi_device_info *info;
> -	acpi_status status;
> -	int *action = context;
> +	bool ret = false;
>  
> -	status = acpi_get_object_info(handle, &info);
> -	if (ACPI_FAILURE(status)) {
> -		return AE_OK;
> -	}
> -
> -	if (info->valid & ACPI_VALID_HID)
> -		hid = info->hardware_id.string;
> -
> -	if (hid == NULL) {
> -		goto end;
> -	}
> +	if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
> +		return false;
>  
> -	if (!is_container_device(hid))
> -		goto end;
> +	if (info->valid & ACPI_VALID_HID) {
> +		const struct acpi_device_id *id;
>  
> -	switch (*action) {
> -	case INSTALL_NOTIFY_HANDLER:
> -		acpi_install_notify_handler(handle,
> -					    ACPI_SYSTEM_NOTIFY,
> -					    container_notify_cb, NULL);
> -		break;
> -	case UNINSTALL_NOTIFY_HANDLER:
> -		acpi_remove_notify_handler(handle,
> -					   ACPI_SYSTEM_NOTIFY,
> -					   container_notify_cb);
> -		break;
> -	default:
> -		break;
> +		for (id = container_device_ids; id->id[0]; id++) {
> +			ret = !strcmp((char *)id->id, info->hardware_id.string);
> +			if (ret)
> +				break;
> +		}
>  	}
> -
> -      end:
>  	kfree(info);
> -
> -	return AE_OK;
> +	return ret;
>  }
>  
> -static int __init acpi_container_init(void)
> +static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
> +							  u32 lvl, void *ctxt,
> +							  void **retv)
>  {
> -	int result = 0;
> -	int action = INSTALL_NOTIFY_HANDLER;
> -
> -	result = acpi_bus_register_driver(&acpi_container_driver);
> -	if (result < 0) {
> -		return (result);
> -	}
> -
> -	/* register notify handler to every container device */
> -	acpi_walk_namespace(ACPI_TYPE_DEVICE,
> -			    ACPI_ROOT_OBJECT,
> -			    ACPI_UINT32_MAX,
> -			    container_walk_namespace_cb, NULL, &action, NULL);
> +	if (is_container(handle))
> +		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
> +					    container_notify_cb, NULL);
>  
> -	return (0);
> +	return AE_OK;
>  }
>  
> -static void __exit acpi_container_exit(void)
> +void __init acpi_container_init(void)
>  {
> -	int action = UNINSTALL_NOTIFY_HANDLER;
> -
> -
> -	acpi_walk_namespace(ACPI_TYPE_DEVICE,
> -			    ACPI_ROOT_OBJECT,
> -			    ACPI_UINT32_MAX,
> -			    container_walk_namespace_cb, NULL, &action, NULL);
> -
> -	acpi_bus_unregister_driver(&acpi_container_driver);
> -
> -	return;
> +	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
> +			    acpi_container_register_notify_handler, NULL,
> +			    NULL, NULL);
>  }
> -
> -module_init(acpi_container_init);
> -module_exit(acpi_container_exit);
> Index: test/drivers/acpi/Kconfig
> ===================================================================
> --- test.orig/drivers/acpi/Kconfig
> +++ test/drivers/acpi/Kconfig
> @@ -334,7 +334,7 @@ config X86_PM_TIMER
>  	  systems require this timer. 
>  
>  config ACPI_CONTAINER
> -	tristate "Container and Module Devices (EXPERIMENTAL)"
> +	bool "Container and Module Devices (EXPERIMENTAL)"
>  	depends on EXPERIMENTAL
>  	default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
>  	help
> Index: test/drivers/acpi/internal.h
> ===================================================================
> --- test.orig/drivers/acpi/internal.h
> +++ test/drivers/acpi/internal.h
> @@ -40,6 +40,11 @@ void acpi_memory_hotplug_init(void);
>  #else
>  static inline void acpi_memory_hotplug_init(void) {}
>  #endif
> +#ifdef ACPI_CONTAINER
> +void acpi_container_init(void);
> +#else
> +static inline void acpi_container_init(void) {}
> +#endif
>  
>  #ifdef CONFIG_DEBUG_FS
>  extern struct dentry *acpi_debugfs_dir;
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -1763,6 +1763,7 @@ int __init acpi_scan_init(void)
>  	acpi_platform_init();
>  	acpi_csrt_init();
>  	acpi_memory_hotplug_init();
> +	acpi_container_init();
>  
>  	/*
>  	 * Enumerate devices in the ACPI namespace.
> 



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-07  0:55         ` Rafael J. Wysocki
@ 2013-02-07  0:51           ` Toshi Kani
  2013-02-07  1:32             ` Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-02-07  0:51 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > 
> > > The only useful thing that the ACPI container driver does is to
> > > install system notify handlers for all container and module device
> > > objects it finds in the namespace.  The driver structure,
> > > acpi_container_driver, and the data structures created by its
> > > .add() callback are in fact not used by the driver, so remove
> > > them entirely.
> > > 
> > > It also makes a little sense to build that driver as a module,
> > > so make it non-modular and add its initialization to the
> > > namespace scanning code.
> > > 
> > > In addition to that, make the namespace walk callback used for
> > > installing the notify handlers more straightforward.
> > 
> > I think the container driver needs to be registered as an ACPI scan
> > driver so that sysfs eject will continue to work for container devices,
> > such as ACPI0004:XX/eject.  Since the container driver does not support
> > ACPI eject notification (and we have been discussing how system device
> > hot-plug should work), this sysfs eject is the only way to eject a
> > container device at this point.  I will send an update patchset that
> > applies on top of this patch.
> > 
> > With the update in my patchset:
> > Reviewed-by: Toshi Kani <toshi.kani@hp.com>
> 
> Thanks, but I'd like to (1) apply your patch from
> https://patchwork.kernel.org/patch/2108851/ first and then (2) fold your [2/2]
> into my [2/2], if you don't mind, and apply that next.

That's fine by me.

> Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> actually makes sense after the recent changes to acpi_bus_trim(), because that
> can't fail now, so the eject will always be carried out.  So perhaps we can
> simply remove the acpi_device->driver check from there entirely in the first
> place?
>
> If we really want to be able to prevent ejects from happening in some cases,
> we need to implement something along the lines discussed with Greg.

acpi_bus_trim() cannot fail, but sysfs eject can fail.  So, I think it
makes sense to do some validation before calling acpi_bus_trim().  If we
are to implement the no_eject flag thing, that check needs to be made
before calling acpi_bus_trim().

Thanks,
-Toshi





^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-06 22:32       ` Toshi Kani
@ 2013-02-07  0:55         ` Rafael J. Wysocki
  2013-02-07  0:51           ` Toshi Kani
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-07  0:55 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> > The only useful thing that the ACPI container driver does is to
> > install system notify handlers for all container and module device
> > objects it finds in the namespace.  The driver structure,
> > acpi_container_driver, and the data structures created by its
> > .add() callback are in fact not used by the driver, so remove
> > them entirely.
> > 
> > It also makes a little sense to build that driver as a module,
> > so make it non-modular and add its initialization to the
> > namespace scanning code.
> > 
> > In addition to that, make the namespace walk callback used for
> > installing the notify handlers more straightforward.
> 
> I think the container driver needs to be registered as an ACPI scan
> driver so that sysfs eject will continue to work for container devices,
> such as ACPI0004:XX/eject.  Since the container driver does not support
> ACPI eject notification (and we have been discussing how system device
> hot-plug should work), this sysfs eject is the only way to eject a
> container device at this point.  I will send an update patchset that
> applies on top of this patch.
> 
> With the update in my patchset:
> Reviewed-by: Toshi Kani <toshi.kani@hp.com>

Thanks, but I'd like to (1) apply your patch from
https://patchwork.kernel.org/patch/2108851/ first and then (2) fold your [2/2]
into my [2/2], if you don't mind, and apply that next.

Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
actually makes sense after the recent changes to acpi_bus_trim(), because that
can't fail now, so the eject will always be carried out.  So perhaps we can
simply remove the acpi_device->driver check from there entirely in the first
place?

If we really want to be able to prevent ejects from happening in some cases,
we need to implement something along the lines discussed with Greg.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-07  0:51           ` Toshi Kani
@ 2013-02-07  1:32             ` Rafael J. Wysocki
  2013-02-07 14:32               ` Toshi Kani
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-07  1:32 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Wednesday, February 06, 2013 05:51:42 PM Toshi Kani wrote:
> On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> > On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > 
> > > > The only useful thing that the ACPI container driver does is to
> > > > install system notify handlers for all container and module device
> > > > objects it finds in the namespace.  The driver structure,
> > > > acpi_container_driver, and the data structures created by its
> > > > .add() callback are in fact not used by the driver, so remove
> > > > them entirely.
> > > > 
> > > > It also makes a little sense to build that driver as a module,
> > > > so make it non-modular and add its initialization to the
> > > > namespace scanning code.
> > > > 
> > > > In addition to that, make the namespace walk callback used for
> > > > installing the notify handlers more straightforward.
> > > 
> > > I think the container driver needs to be registered as an ACPI scan
> > > driver so that sysfs eject will continue to work for container devices,
> > > such as ACPI0004:XX/eject.  Since the container driver does not support
> > > ACPI eject notification (and we have been discussing how system device
> > > hot-plug should work), this sysfs eject is the only way to eject a
> > > container device at this point.  I will send an update patchset that
> > > applies on top of this patch.
> > > 
> > > With the update in my patchset:
> > > Reviewed-by: Toshi Kani <toshi.kani@hp.com>
> > 
> > Thanks, but I'd like to (1) apply your patch from
> > https://patchwork.kernel.org/patch/2108851/ first and then (2) fold your [2/2]
> > into my [2/2], if you don't mind, and apply that next.
> 
> That's fine by me.
> 
> > Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> > actually makes sense after the recent changes to acpi_bus_trim(), because that
> > can't fail now, so the eject will always be carried out.  So perhaps we can
> > simply remove the acpi_device->driver check from there entirely in the first
> > place?
> >
> > If we really want to be able to prevent ejects from happening in some cases,
> > we need to implement something along the lines discussed with Greg.
> 
> acpi_bus_trim() cannot fail, but sysfs eject can fail.  So, I think it
> makes sense to do some validation before calling acpi_bus_trim().  If we
> are to implement the no_eject flag thing, that check needs to be made
> before calling acpi_bus_trim().

Sure, but now the logic seems to be "if FORCE_EJECT is not set, don't eject
devices that have no ACPI drivers", so I'm wondering what the purpose of this
is.  It definitely isn't too obvious. :-)

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-03 23:47     ` [PATCH 2/2] ACPI / scan: Simplify container driver Rafael J. Wysocki
  2013-02-06 22:32       ` Toshi Kani
@ 2013-02-07  8:32       ` Yasuaki Ishimatsu
  2013-02-07 11:43         ` Rafael J. Wysocki
  2013-02-08  0:24       ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
  2 siblings, 1 reply; 71+ messages in thread
From: Yasuaki Ishimatsu @ 2013-02-07  8:32 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML

Hi Rafael,

Sorry for late reply.

2013/02/04 8:47, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> The only useful thing that the ACPI container driver does is to
> install system notify handlers for all container and module device
> objects it finds in the namespace.  The driver structure,
> acpi_container_driver, and the data structures created by its
> .add() callback are in fact not used by the driver, so remove
> them entirely.
>
> It also makes a little sense to build that driver as a module,
> so make it non-modular and add its initialization to the
> namespace scanning code.
>
> In addition to that, make the namespace walk callback used for
> installing the notify handlers more straightforward.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>   drivers/acpi/Kconfig     |    2
>   drivers/acpi/container.c |  158 ++++++-----------------------------------------
>   drivers/acpi/internal.h  |    5 +
>   drivers/acpi/scan.c      |    1
>   4 files changed, 30 insertions(+), 136 deletions(-)
>
> Index: test/drivers/acpi/container.c
> ===================================================================
> --- test.orig/drivers/acpi/container.c
> +++ test/drivers/acpi/container.c
> @@ -38,41 +38,15 @@
>
>   #define PREFIX "ACPI: "
>
> -#define ACPI_CONTAINER_DEVICE_NAME	"ACPI container device"
> -#define ACPI_CONTAINER_CLASS		"container"
> -
> -#define INSTALL_NOTIFY_HANDLER		1
> -#define UNINSTALL_NOTIFY_HANDLER	2
> -
>   #define _COMPONENT			ACPI_CONTAINER_COMPONENT
>   ACPI_MODULE_NAME("container");
>
> -MODULE_AUTHOR("Anil S Keshavamurthy");
> -MODULE_DESCRIPTION("ACPI container driver");
> -MODULE_LICENSE("GPL");
> -
> -static int acpi_container_add(struct acpi_device *device);
> -static int acpi_container_remove(struct acpi_device *device);
> -
>   static const struct acpi_device_id container_device_ids[] = {
>   	{"ACPI0004", 0},
>   	{"PNP0A05", 0},
>   	{"PNP0A06", 0},
>   	{"", 0},
>   };
> -MODULE_DEVICE_TABLE(acpi, container_device_ids);
> -
> -static struct acpi_driver acpi_container_driver = {
> -	.name = "container",
> -	.class = ACPI_CONTAINER_CLASS,
> -	.ids = container_device_ids,
> -	.ops = {
> -		.add = acpi_container_add,
> -		.remove = acpi_container_remove,
> -		},
> -};
> -
> -/*******************************************************************/
>
>   static int is_device_present(acpi_handle handle)
>   {
> @@ -92,49 +66,6 @@ static int is_device_present(acpi_handle
>   	return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
>   }
>
> -static bool is_container_device(const char *hid)
> -{
> -	const struct acpi_device_id *container_id;
> -
> -	for (container_id = container_device_ids;
> -	     container_id->id[0]; container_id++) {
> -		if (!strcmp((char *)container_id->id, hid))
> -			return true;
> -	}
> -
> -	return false;
> -}
> -
> -/*******************************************************************/
> -static int acpi_container_add(struct acpi_device *device)
> -{
> -	struct acpi_container *container;
> -
> -	container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
> -	if (!container)
> -		return -ENOMEM;
> -
> -	container->handle = device->handle;
> -	strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
> -	strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
> -	device->driver_data = container;
> -
> -	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
> -			  acpi_device_name(device), acpi_device_bid(device)));
> -
> -	return 0;
> -}
> -
> -static int acpi_container_remove(struct acpi_device *device)
> -{
> -	acpi_status status = AE_OK;
> -	struct acpi_container *pc = NULL;
> -
> -	pc = acpi_driver_data(device);
> -	kfree(pc);
> -	return status;
> -}
> -
>   static void container_notify_cb(acpi_handle handle, u32 type, void *context)
>   {
>   	struct acpi_device *device = NULL;
> @@ -199,84 +130,41 @@ static void container_notify_cb(acpi_han
>   	return;
>   }
>
> -static acpi_status
> -container_walk_namespace_cb(acpi_handle handle,
> -			    u32 lvl, void *context, void **rv)
> +static bool is_container(acpi_handle handle)
>   {
> -	char *hid = NULL;
>   	struct acpi_device_info *info;
> -	acpi_status status;
> -	int *action = context;
> +	bool ret = false;
>
> -	status = acpi_get_object_info(handle, &info);
> -	if (ACPI_FAILURE(status)) {
> -		return AE_OK;
> -	}
> -
> -	if (info->valid & ACPI_VALID_HID)
> -		hid = info->hardware_id.string;
> -
> -	if (hid == NULL) {
> -		goto end;
> -	}
> +	if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
> +		return false;
>
> -	if (!is_container_device(hid))
> -		goto end;
> +	if (info->valid & ACPI_VALID_HID) {
> +		const struct acpi_device_id *id;
>
> -	switch (*action) {
> -	case INSTALL_NOTIFY_HANDLER:
> -		acpi_install_notify_handler(handle,
> -					    ACPI_SYSTEM_NOTIFY,
> -					    container_notify_cb, NULL);
> -		break;
> -	case UNINSTALL_NOTIFY_HANDLER:
> -		acpi_remove_notify_handler(handle,
> -					   ACPI_SYSTEM_NOTIFY,
> -					   container_notify_cb);
> -		break;
> -	default:
> -		break;
> +		for (id = container_device_ids; id->id[0]; id++) {
> +			ret = !strcmp((char *)id->id, info->hardware_id.string);
> +			if (ret)
> +				break;
> +		}
>   	}
> -
> -      end:
>   	kfree(info);
> -
> -	return AE_OK;
> +	return ret;
>   }
>
> -static int __init acpi_container_init(void)
> +static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
> +							  u32 lvl, void *ctxt,
> +							  void **retv)
>   {
> -	int result = 0;
> -	int action = INSTALL_NOTIFY_HANDLER;
> -
> -	result = acpi_bus_register_driver(&acpi_container_driver);
> -	if (result < 0) {
> -		return (result);
> -	}
> -
> -	/* register notify handler to every container device */
> -	acpi_walk_namespace(ACPI_TYPE_DEVICE,
> -			    ACPI_ROOT_OBJECT,
> -			    ACPI_UINT32_MAX,
> -			    container_walk_namespace_cb, NULL, &action, NULL);
> +	if (is_container(handle))
> +		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
> +					    container_notify_cb, NULL);
>
> -	return (0);
> +	return AE_OK;
>   }
>
> -static void __exit acpi_container_exit(void)
> +void __init acpi_container_init(void)
>   {
> -	int action = UNINSTALL_NOTIFY_HANDLER;
> -
> -
> -	acpi_walk_namespace(ACPI_TYPE_DEVICE,
> -			    ACPI_ROOT_OBJECT,
> -			    ACPI_UINT32_MAX,
> -			    container_walk_namespace_cb, NULL, &action, NULL);
> -
> -	acpi_bus_unregister_driver(&acpi_container_driver);
> -
> -	return;
> +	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
> +			    acpi_container_register_notify_handler, NULL,
> +			    NULL, NULL);
>   }
> -
> -module_init(acpi_container_init);
> -module_exit(acpi_container_exit);
> Index: test/drivers/acpi/Kconfig
> ===================================================================
> --- test.orig/drivers/acpi/Kconfig
> +++ test/drivers/acpi/Kconfig
> @@ -334,7 +334,7 @@ config X86_PM_TIMER
>   	  systems require this timer.
>
>   config ACPI_CONTAINER
> -	tristate "Container and Module Devices (EXPERIMENTAL)"
> +	bool "Container and Module Devices (EXPERIMENTAL)"
>   	depends on EXPERIMENTAL
>   	default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
>   	help
> Index: test/drivers/acpi/internal.h
> ===================================================================
> --- test.orig/drivers/acpi/internal.h
> +++ test/drivers/acpi/internal.h
> @@ -40,6 +40,11 @@ void acpi_memory_hotplug_init(void);
>   #else
>   static inline void acpi_memory_hotplug_init(void) {}
>   #endif

> +#ifdef ACPI_CONTAINER

It should be CONFIG_ACPI_CONTAINER. By this, acpi_container_init()
do nothing. When I fix it and test the patch, the patch goes well.

If you update the patch, I'll test again.

Thanks,
Yasuaki Ishimatsu

> +void acpi_container_init(void);
> +#else
> +static inline void acpi_container_init(void) {}
> +#endif
>
>   #ifdef CONFIG_DEBUG_FS
>   extern struct dentry *acpi_debugfs_dir;
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -1763,6 +1763,7 @@ int __init acpi_scan_init(void)
>   	acpi_platform_init();
>   	acpi_csrt_init();
>   	acpi_memory_hotplug_init();
> +	acpi_container_init();
>
>   	/*
>   	 * Enumerate devices in the ACPI namespace.
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-07  8:32       ` Yasuaki Ishimatsu
@ 2013-02-07 11:43         ` Rafael J. Wysocki
  2013-02-07 14:38           ` Toshi Kani
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-07 11:43 UTC (permalink / raw)
  To: Yasuaki Ishimatsu
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML

On Thursday, February 07, 2013 05:32:15 PM Yasuaki Ishimatsu wrote:
> Hi Rafael,
> 
> Sorry for late reply.

No problem, thank you for the review.

> 2013/02/04 8:47, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > The only useful thing that the ACPI container driver does is to
> > install system notify handlers for all container and module device
> > objects it finds in the namespace.  The driver structure,
> > acpi_container_driver, and the data structures created by its
> > .add() callback are in fact not used by the driver, so remove
> > them entirely.
> >
> > It also makes a little sense to build that driver as a module,
> > so make it non-modular and add its initialization to the
> > namespace scanning code.
> >
> > In addition to that, make the namespace walk callback used for
> > installing the notify handlers more straightforward.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >   drivers/acpi/Kconfig     |    2
> >   drivers/acpi/container.c |  158 ++++++-----------------------------------------
> >   drivers/acpi/internal.h  |    5 +
> >   drivers/acpi/scan.c      |    1
> >   4 files changed, 30 insertions(+), 136 deletions(-)
> >
> > Index: test/drivers/acpi/container.c
> > ===================================================================
> > --- test.orig/drivers/acpi/container.c
> > +++ test/drivers/acpi/container.c
> > @@ -38,41 +38,15 @@
> >
> >   #define PREFIX "ACPI: "
> >
> > -#define ACPI_CONTAINER_DEVICE_NAME	"ACPI container device"
> > -#define ACPI_CONTAINER_CLASS		"container"
> > -
> > -#define INSTALL_NOTIFY_HANDLER		1
> > -#define UNINSTALL_NOTIFY_HANDLER	2
> > -
> >   #define _COMPONENT			ACPI_CONTAINER_COMPONENT
> >   ACPI_MODULE_NAME("container");
> >
> > -MODULE_AUTHOR("Anil S Keshavamurthy");
> > -MODULE_DESCRIPTION("ACPI container driver");
> > -MODULE_LICENSE("GPL");
> > -
> > -static int acpi_container_add(struct acpi_device *device);
> > -static int acpi_container_remove(struct acpi_device *device);
> > -
> >   static const struct acpi_device_id container_device_ids[] = {
> >   	{"ACPI0004", 0},
> >   	{"PNP0A05", 0},
> >   	{"PNP0A06", 0},
> >   	{"", 0},
> >   };
> > -MODULE_DEVICE_TABLE(acpi, container_device_ids);
> > -
> > -static struct acpi_driver acpi_container_driver = {
> > -	.name = "container",
> > -	.class = ACPI_CONTAINER_CLASS,
> > -	.ids = container_device_ids,
> > -	.ops = {
> > -		.add = acpi_container_add,
> > -		.remove = acpi_container_remove,
> > -		},
> > -};
> > -
> > -/*******************************************************************/
> >
> >   static int is_device_present(acpi_handle handle)
> >   {
> > @@ -92,49 +66,6 @@ static int is_device_present(acpi_handle
> >   	return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
> >   }
> >
> > -static bool is_container_device(const char *hid)
> > -{
> > -	const struct acpi_device_id *container_id;
> > -
> > -	for (container_id = container_device_ids;
> > -	     container_id->id[0]; container_id++) {
> > -		if (!strcmp((char *)container_id->id, hid))
> > -			return true;
> > -	}
> > -
> > -	return false;
> > -}
> > -
> > -/*******************************************************************/
> > -static int acpi_container_add(struct acpi_device *device)
> > -{
> > -	struct acpi_container *container;
> > -
> > -	container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
> > -	if (!container)
> > -		return -ENOMEM;
> > -
> > -	container->handle = device->handle;
> > -	strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
> > -	strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
> > -	device->driver_data = container;
> > -
> > -	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
> > -			  acpi_device_name(device), acpi_device_bid(device)));
> > -
> > -	return 0;
> > -}
> > -
> > -static int acpi_container_remove(struct acpi_device *device)
> > -{
> > -	acpi_status status = AE_OK;
> > -	struct acpi_container *pc = NULL;
> > -
> > -	pc = acpi_driver_data(device);
> > -	kfree(pc);
> > -	return status;
> > -}
> > -
> >   static void container_notify_cb(acpi_handle handle, u32 type, void *context)
> >   {
> >   	struct acpi_device *device = NULL;
> > @@ -199,84 +130,41 @@ static void container_notify_cb(acpi_han
> >   	return;
> >   }
> >
> > -static acpi_status
> > -container_walk_namespace_cb(acpi_handle handle,
> > -			    u32 lvl, void *context, void **rv)
> > +static bool is_container(acpi_handle handle)
> >   {
> > -	char *hid = NULL;
> >   	struct acpi_device_info *info;
> > -	acpi_status status;
> > -	int *action = context;
> > +	bool ret = false;
> >
> > -	status = acpi_get_object_info(handle, &info);
> > -	if (ACPI_FAILURE(status)) {
> > -		return AE_OK;
> > -	}
> > -
> > -	if (info->valid & ACPI_VALID_HID)
> > -		hid = info->hardware_id.string;
> > -
> > -	if (hid == NULL) {
> > -		goto end;
> > -	}
> > +	if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
> > +		return false;
> >
> > -	if (!is_container_device(hid))
> > -		goto end;
> > +	if (info->valid & ACPI_VALID_HID) {
> > +		const struct acpi_device_id *id;
> >
> > -	switch (*action) {
> > -	case INSTALL_NOTIFY_HANDLER:
> > -		acpi_install_notify_handler(handle,
> > -					    ACPI_SYSTEM_NOTIFY,
> > -					    container_notify_cb, NULL);
> > -		break;
> > -	case UNINSTALL_NOTIFY_HANDLER:
> > -		acpi_remove_notify_handler(handle,
> > -					   ACPI_SYSTEM_NOTIFY,
> > -					   container_notify_cb);
> > -		break;
> > -	default:
> > -		break;
> > +		for (id = container_device_ids; id->id[0]; id++) {
> > +			ret = !strcmp((char *)id->id, info->hardware_id.string);
> > +			if (ret)
> > +				break;
> > +		}
> >   	}
> > -
> > -      end:
> >   	kfree(info);
> > -
> > -	return AE_OK;
> > +	return ret;
> >   }
> >
> > -static int __init acpi_container_init(void)
> > +static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
> > +							  u32 lvl, void *ctxt,
> > +							  void **retv)
> >   {
> > -	int result = 0;
> > -	int action = INSTALL_NOTIFY_HANDLER;
> > -
> > -	result = acpi_bus_register_driver(&acpi_container_driver);
> > -	if (result < 0) {
> > -		return (result);
> > -	}
> > -
> > -	/* register notify handler to every container device */
> > -	acpi_walk_namespace(ACPI_TYPE_DEVICE,
> > -			    ACPI_ROOT_OBJECT,
> > -			    ACPI_UINT32_MAX,
> > -			    container_walk_namespace_cb, NULL, &action, NULL);
> > +	if (is_container(handle))
> > +		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
> > +					    container_notify_cb, NULL);
> >
> > -	return (0);
> > +	return AE_OK;
> >   }
> >
> > -static void __exit acpi_container_exit(void)
> > +void __init acpi_container_init(void)
> >   {
> > -	int action = UNINSTALL_NOTIFY_HANDLER;
> > -
> > -
> > -	acpi_walk_namespace(ACPI_TYPE_DEVICE,
> > -			    ACPI_ROOT_OBJECT,
> > -			    ACPI_UINT32_MAX,
> > -			    container_walk_namespace_cb, NULL, &action, NULL);
> > -
> > -	acpi_bus_unregister_driver(&acpi_container_driver);
> > -
> > -	return;
> > +	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
> > +			    acpi_container_register_notify_handler, NULL,
> > +			    NULL, NULL);
> >   }
> > -
> > -module_init(acpi_container_init);
> > -module_exit(acpi_container_exit);
> > Index: test/drivers/acpi/Kconfig
> > ===================================================================
> > --- test.orig/drivers/acpi/Kconfig
> > +++ test/drivers/acpi/Kconfig
> > @@ -334,7 +334,7 @@ config X86_PM_TIMER
> >   	  systems require this timer.
> >
> >   config ACPI_CONTAINER
> > -	tristate "Container and Module Devices (EXPERIMENTAL)"
> > +	bool "Container and Module Devices (EXPERIMENTAL)"
> >   	depends on EXPERIMENTAL
> >   	default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
> >   	help
> > Index: test/drivers/acpi/internal.h
> > ===================================================================
> > --- test.orig/drivers/acpi/internal.h
> > +++ test/drivers/acpi/internal.h
> > @@ -40,6 +40,11 @@ void acpi_memory_hotplug_init(void);
> >   #else
> >   static inline void acpi_memory_hotplug_init(void) {}
> >   #endif
> 
> > +#ifdef ACPI_CONTAINER
> 
> It should be CONFIG_ACPI_CONTAINER.

Totally correct.

> By this, acpi_container_init() do nothing. When I fix it and test the patch,
> the patch goes well.
> 
> If you update the patch, I'll test again.

This fix from Toshi Kani is necessary in addition to it, though

https://patchwork.kernel.org/patch/2108851/

because FORCE_EJECT is never set as far as I can say.

Thanks,
Rafael



-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-07  1:32             ` Rafael J. Wysocki
@ 2013-02-07 14:32               ` Toshi Kani
  2013-02-07 22:42                 ` Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-02-07 14:32 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Thu, 2013-02-07 at 02:32 +0100, Rafael J. Wysocki wrote:
> On Wednesday, February 06, 2013 05:51:42 PM Toshi Kani wrote:
> > On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> > > On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > > > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > 
> > > > > The only useful thing that the ACPI container driver does is to
> > > > > install system notify handlers for all container and module device
> > > > > objects it finds in the namespace.  The driver structure,
> > > > > acpi_container_driver, and the data structures created by its
> > > > > .add() callback are in fact not used by the driver, so remove
> > > > > them entirely.
> > > > > 
> > > > > It also makes a little sense to build that driver as a module,
> > > > > so make it non-modular and add its initialization to the
> > > > > namespace scanning code.
> > > > > 
> > > > > In addition to that, make the namespace walk callback used for
> > > > > installing the notify handlers more straightforward.
> > > > 
> > > > I think the container driver needs to be registered as an ACPI scan
> > > > driver so that sysfs eject will continue to work for container devices,
> > > > such as ACPI0004:XX/eject.  Since the container driver does not support
> > > > ACPI eject notification (and we have been discussing how system device
> > > > hot-plug should work), this sysfs eject is the only way to eject a
> > > > container device at this point.  I will send an update patchset that
> > > > applies on top of this patch.
> > > > 
> > > > With the update in my patchset:
> > > > Reviewed-by: Toshi Kani <toshi.kani@hp.com>
> > > 
> > > Thanks, but I'd like to (1) apply your patch from
> > > https://patchwork.kernel.org/patch/2108851/ first and then (2) fold your [2/2]
> > > into my [2/2], if you don't mind, and apply that next.
> > 
> > That's fine by me.
> > 
> > > Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> > > actually makes sense after the recent changes to acpi_bus_trim(), because that
> > > can't fail now, so the eject will always be carried out.  So perhaps we can
> > > simply remove the acpi_device->driver check from there entirely in the first
> > > place?
> > >
> > > If we really want to be able to prevent ejects from happening in some cases,
> > > we need to implement something along the lines discussed with Greg.
> > 
> > acpi_bus_trim() cannot fail, but sysfs eject can fail.  So, I think it
> > makes sense to do some validation before calling acpi_bus_trim().  If we
> > are to implement the no_eject flag thing, that check needs to be made
> > before calling acpi_bus_trim().
> 
> Sure, but now the logic seems to be "if FORCE_EJECT is not set, don't eject
> devices that have no ACPI drivers", so I'm wondering what the purpose of this
> is.  It definitely isn't too obvious. :-)

The check sounds odd for container, but is necessary for CPU and memory
for now.  CPU and memory go online without their ACPI drivers at boot.
So, without this check (i.e. FORCE_EJECT is set), it simply ejects them
without attempting to offline when the ACPI drivers are not bound.  Of
course, we have the issue of a failure in offline be ignored, so this
offlining part needs to be moved out from acpi_bus_trim() in one way or
the other.

Thanks,
-Toshi


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-07 11:43         ` Rafael J. Wysocki
@ 2013-02-07 14:38           ` Toshi Kani
  0 siblings, 0 replies; 71+ messages in thread
From: Toshi Kani @ 2013-02-07 14:38 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Yasuaki Ishimatsu, ACPI Devel Maling List, Greg Kroah-Hartman,
	Bjorn Helgaas, Mika Westerberg, Matthew Garrett, Yinghai Lu,
	Jiang Liu, LKML

On Thu, 2013-02-07 at 12:43 +0100, Rafael J. Wysocki wrote:
> On Thursday, February 07, 2013 05:32:15 PM Yasuaki Ishimatsu wrote:
 :
> > > Index: test/drivers/acpi/internal.h
> > > ===================================================================
> > > --- test.orig/drivers/acpi/internal.h
> > > +++ test/drivers/acpi/internal.h
> > > @@ -40,6 +40,11 @@ void acpi_memory_hotplug_init(void);
> > >   #else
> > >   static inline void acpi_memory_hotplug_init(void) {}
> > >   #endif
> > 
> > > +#ifdef ACPI_CONTAINER
> > 
> > It should be CONFIG_ACPI_CONTAINER.
> 
> Totally correct.

Just FYI, this change is included in my patch 2/2 as well.
https://patchwork.kernel.org/patch/2108881/

Thanks,
-Toshi


> > By this, acpi_container_init() do nothing. When I fix it and test the patch,
> > the patch goes well.
> > 
> > If you update the patch, I'll test again.
> 
> This fix from Toshi Kani is necessary in addition to it, though
> 
> https://patchwork.kernel.org/patch/2108851/
> 
> because FORCE_EJECT is never set as far as I can say.
> 
> Thanks,
> Rafael
> 
> 
> 



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-07 14:32               ` Toshi Kani
@ 2013-02-07 22:42                 ` Rafael J. Wysocki
  2013-02-08  1:05                   ` Toshi Kani
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-07 22:42 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Thursday, February 07, 2013 07:32:07 AM Toshi Kani wrote:
> On Thu, 2013-02-07 at 02:32 +0100, Rafael J. Wysocki wrote:
> > On Wednesday, February 06, 2013 05:51:42 PM Toshi Kani wrote:
> > > On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> > > > On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > > > > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> > > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > 
> > > > > > The only useful thing that the ACPI container driver does is to
> > > > > > install system notify handlers for all container and module device
> > > > > > objects it finds in the namespace.  The driver structure,
> > > > > > acpi_container_driver, and the data structures created by its
> > > > > > .add() callback are in fact not used by the driver, so remove
> > > > > > them entirely.
> > > > > > 
> > > > > > It also makes a little sense to build that driver as a module,
> > > > > > so make it non-modular and add its initialization to the
> > > > > > namespace scanning code.
> > > > > > 
> > > > > > In addition to that, make the namespace walk callback used for
> > > > > > installing the notify handlers more straightforward.
> > > > > 
> > > > > I think the container driver needs to be registered as an ACPI scan
> > > > > driver so that sysfs eject will continue to work for container devices,
> > > > > such as ACPI0004:XX/eject.  Since the container driver does not support
> > > > > ACPI eject notification (and we have been discussing how system device
> > > > > hot-plug should work), this sysfs eject is the only way to eject a
> > > > > container device at this point.  I will send an update patchset that
> > > > > applies on top of this patch.
> > > > > 
> > > > > With the update in my patchset:
> > > > > Reviewed-by: Toshi Kani <toshi.kani@hp.com>
> > > > 
> > > > Thanks, but I'd like to (1) apply your patch from
> > > > https://patchwork.kernel.org/patch/2108851/ first and then (2) fold your [2/2]
> > > > into my [2/2], if you don't mind, and apply that next.
> > > 
> > > That's fine by me.
> > > 
> > > > Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> > > > actually makes sense after the recent changes to acpi_bus_trim(), because that
> > > > can't fail now, so the eject will always be carried out.  So perhaps we can
> > > > simply remove the acpi_device->driver check from there entirely in the first
> > > > place?
> > > >
> > > > If we really want to be able to prevent ejects from happening in some cases,
> > > > we need to implement something along the lines discussed with Greg.
> > > 
> > > acpi_bus_trim() cannot fail, but sysfs eject can fail.  So, I think it
> > > makes sense to do some validation before calling acpi_bus_trim().  If we
> > > are to implement the no_eject flag thing, that check needs to be made
> > > before calling acpi_bus_trim().
> > 
> > Sure, but now the logic seems to be "if FORCE_EJECT is not set, don't eject
> > devices that have no ACPI drivers", so I'm wondering what the purpose of this
> > is.  It definitely isn't too obvious. :-)
> 
> The check sounds odd for container, but is necessary for CPU and memory
> for now.  CPU and memory go online without their ACPI drivers at boot.
> So, without this check (i.e. FORCE_EJECT is set), it simply ejects them
> without attempting to offline when the ACPI drivers are not bound.  Of
> course, we have the issue of a failure in offline be ignored, so this
> offlining part needs to be moved out from acpi_bus_trim() in one way or
> the other.

That was my point.

I'm going to add that change for now, but I think we need to take a step back
and talk about how we want the whole eject machinery to work, regardless of
the offline/online problem.

I think that it should work in the same way for all things that may be ejected
or inserted.  Namely, they all should use the same notify handler, for example,
and if we generate a uevent for one, we should do that for all of them.
Question is how that notify handler should work and here there are two chices
in my view: Either we'll always emit a uevent and wait for user space to start
the eject procedure via sysfs, or we won't emit uevents at all and rely on the
"no_eject" flag to trigger if something is not ready.  I'm basically fine with
any of them (the "no_eject" flag may be useful even if we rely on user space
to offline stuff before triggering the eject in my opinion), but if we're going
to rely on user space, then there needs to be a timeout for letting the BIOS
know that the eject has failed.

[There may be a flag for the common code telling it whether to emit a uevent
and wait for user space to trigger eject or to trigger eject by itself.]

Next, I think there needs to be a global list of IDs for which we'll install
hot-plug notify handlers and which we'll allow to be ejected via /sys/.../eject.
So, if a device ID is on that list, we'll install the (common) hot-plug notify
handler for its ACPI handle and we'll set an "eject_possible" flag in its
struct acpi_device (when created).  That will need to be done for every scan
of the ACPI namespace and not just once, BTW.  And we'll check the
"eject_possible" flag in acpi_eject_store() instead of the "does it have a
driver or scan handler" check.

Then, the scan handlers for hot-plug devices will be able to add their IDs to
that global list instead of walking the namespace and installing notify handlers
by themselves (which as I said has a problem that it's done once, while it
should be done every time acpi_bus_scan() runs).

I wonder what you think.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver
  2013-02-03 23:47     ` [PATCH 2/2] ACPI / scan: Simplify container driver Rafael J. Wysocki
  2013-02-06 22:32       ` Toshi Kani
  2013-02-07  8:32       ` Yasuaki Ishimatsu
@ 2013-02-08  0:24       ` Rafael J. Wysocki
  2013-02-08  0:25         ` [PATCH 1/2] ACPI / scan: Remove useless #ifndef from acpi_eject_store() Rafael J. Wysocki
                           ` (4 more replies)
  2 siblings, 5 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08  0:24 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML,
	Yasuaki Ishimatsu

On Monday, February 04, 2013 12:47:31 AM Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> The only useful thing that the ACPI container driver does is to
> install system notify handlers for all container and module device
> objects it finds in the namespace.  The driver structure,
> acpi_container_driver, and the data structures created by its
> .add() callback are in fact not used by the driver, so remove
> them entirely.
> 
> It also makes a little sense to build that driver as a module,
> so make it non-modular and add its initialization to the
> namespace scanning code.
> 
> In addition to that, make the namespace walk callback used for
> installing the notify handlers more straightforward.

As pointed out by Toshi Kani, the above changes would make acpi_eject_store()
fail for containers and it is the only way to eject them currently, so patch
[2/2] is an improved version of this (with Toshi's changes folded in).

Patch [1/2] is just a cleanup removing a useless #ifndef from acpi_eject_store().

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 1/2] ACPI / scan: Remove useless #ifndef from acpi_eject_store()
  2013-02-08  0:24       ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
@ 2013-02-08  0:25         ` Rafael J. Wysocki
  2013-02-08  0:27         ` [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler Rafael J. Wysocki
                           ` (3 subsequent siblings)
  4 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08  0:25 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML,
	Yasuaki Ishimatsu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Since the FORCE_EJECT symbol is never defined, the
#ifndef FORCE_EJECT in acpi_eject_store() is always true, so drop it.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c |    2 --
 1 file changed, 2 deletions(-)

Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -202,12 +202,10 @@ acpi_eject_store(struct device *d, struc
 	if ((!count) || (buf[0] != '1')) {
 		return -EINVAL;
 	}
-#ifndef FORCE_EJECT
 	if (!acpi_device->driver && !acpi_device->handler) {
 		ret = -ENODEV;
 		goto err;
 	}
-#endif
 	status = acpi_get_type(acpi_device->handle, &type);
 	if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) {
 		ret = -ENODEV;


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler
  2013-02-08  0:24       ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
  2013-02-08  0:25         ` [PATCH 1/2] ACPI / scan: Remove useless #ifndef from acpi_eject_store() Rafael J. Wysocki
@ 2013-02-08  0:27         ` Rafael J. Wysocki
  2013-02-08  3:32           ` Yinghai Lu
  2013-02-08  3:19         ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver Yasuaki Ishimatsu
                           ` (2 subsequent siblings)
  4 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08  0:27 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML,
	Yasuaki Ishimatsu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Make the ACPI container driver use struct acpi_scan_handler for
representing the object used to initialize ACPI containers and remove
the ACPI driver structure used previously and the data structures
created by it, since in fact they were not used for any purpose.

This simplifies the code and reduces the kernel's memory footprint by
avoiding the registration of a struct device_driver object with the
driver core and creation of its sysfs directory which is unnecessary.

In addition to that, make the namespace walk callback used for
installing the notify handlers for ACPI containers more
straightforward.

This change includes fixes from Toshi Kani.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/Kconfig     |    2 
 drivers/acpi/container.c |  167 ++++++++++-------------------------------------
 drivers/acpi/internal.h  |    5 +
 drivers/acpi/scan.c      |    1 
 4 files changed, 43 insertions(+), 132 deletions(-)

Index: test/drivers/acpi/container.c
===================================================================
--- test.orig/drivers/acpi/container.c
+++ test/drivers/acpi/container.c
@@ -38,42 +38,31 @@
 
 #define PREFIX "ACPI: "
 
-#define ACPI_CONTAINER_DEVICE_NAME	"ACPI container device"
-#define ACPI_CONTAINER_CLASS		"container"
-
-#define INSTALL_NOTIFY_HANDLER		1
-#define UNINSTALL_NOTIFY_HANDLER	2
-
 #define _COMPONENT			ACPI_CONTAINER_COMPONENT
 ACPI_MODULE_NAME("container");
 
-MODULE_AUTHOR("Anil S Keshavamurthy");
-MODULE_DESCRIPTION("ACPI container driver");
-MODULE_LICENSE("GPL");
-
-static int acpi_container_add(struct acpi_device *device);
-static int acpi_container_remove(struct acpi_device *device);
-
 static const struct acpi_device_id container_device_ids[] = {
 	{"ACPI0004", 0},
 	{"PNP0A05", 0},
 	{"PNP0A06", 0},
 	{"", 0},
 };
-MODULE_DEVICE_TABLE(acpi, container_device_ids);
 
-static struct acpi_driver acpi_container_driver = {
-	.name = "container",
-	.class = ACPI_CONTAINER_CLASS,
+static int container_device_attach(struct acpi_device *device,
+				   const struct acpi_device_id *not_used)
+{
+	/*
+	 * FIXME: This is necessary, so that acpi_eject_store() doesn't return
+	 * -ENODEV for containers.
+	 */
+	return 1;
+}
+
+static struct acpi_scan_handler container_device_handler = {
 	.ids = container_device_ids,
-	.ops = {
-		.add = acpi_container_add,
-		.remove = acpi_container_remove,
-		},
+	.attach = container_device_attach,
 };
 
-/*******************************************************************/
-
 static int is_device_present(acpi_handle handle)
 {
 	acpi_handle temp;
@@ -92,49 +81,6 @@ static int is_device_present(acpi_handle
 	return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
 }
 
-static bool is_container_device(const char *hid)
-{
-	const struct acpi_device_id *container_id;
-
-	for (container_id = container_device_ids;
-	     container_id->id[0]; container_id++) {
-		if (!strcmp((char *)container_id->id, hid))
-			return true;
-	}
-
-	return false;
-}
-
-/*******************************************************************/
-static int acpi_container_add(struct acpi_device *device)
-{
-	struct acpi_container *container;
-
-	container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
-	if (!container)
-		return -ENOMEM;
-
-	container->handle = device->handle;
-	strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
-	strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
-	device->driver_data = container;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
-			  acpi_device_name(device), acpi_device_bid(device)));
-
-	return 0;
-}
-
-static int acpi_container_remove(struct acpi_device *device)
-{
-	acpi_status status = AE_OK;
-	struct acpi_container *pc = NULL;
-
-	pc = acpi_driver_data(device);
-	kfree(pc);
-	return status;
-}
-
 static void container_notify_cb(acpi_handle handle, u32 type, void *context)
 {
 	struct acpi_device *device = NULL;
@@ -199,84 +145,43 @@ static void container_notify_cb(acpi_han
 	return;
 }
 
-static acpi_status
-container_walk_namespace_cb(acpi_handle handle,
-			    u32 lvl, void *context, void **rv)
+static bool is_container(acpi_handle handle)
 {
-	char *hid = NULL;
 	struct acpi_device_info *info;
-	acpi_status status;
-	int *action = context;
-
-	status = acpi_get_object_info(handle, &info);
-	if (ACPI_FAILURE(status)) {
-		return AE_OK;
-	}
+	bool ret = false;
 
-	if (info->valid & ACPI_VALID_HID)
-		hid = info->hardware_id.string;
+	if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
+		return false;
 
-	if (hid == NULL) {
-		goto end;
-	}
-
-	if (!is_container_device(hid))
-		goto end;
+	if (info->valid & ACPI_VALID_HID) {
+		const struct acpi_device_id *id;
 
-	switch (*action) {
-	case INSTALL_NOTIFY_HANDLER:
-		acpi_install_notify_handler(handle,
-					    ACPI_SYSTEM_NOTIFY,
-					    container_notify_cb, NULL);
-		break;
-	case UNINSTALL_NOTIFY_HANDLER:
-		acpi_remove_notify_handler(handle,
-					   ACPI_SYSTEM_NOTIFY,
-					   container_notify_cb);
-		break;
-	default:
-		break;
+		for (id = container_device_ids; id->id[0]; id++) {
+			ret = !strcmp((char *)id->id, info->hardware_id.string);
+			if (ret)
+				break;
+		}
 	}
-
-      end:
 	kfree(info);
-
-	return AE_OK;
+	return ret;
 }
 
-static int __init acpi_container_init(void)
+static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
+							  u32 lvl, void *ctxt,
+							  void **retv)
 {
-	int result = 0;
-	int action = INSTALL_NOTIFY_HANDLER;
-
-	result = acpi_bus_register_driver(&acpi_container_driver);
-	if (result < 0) {
-		return (result);
-	}
-
-	/* register notify handler to every container device */
-	acpi_walk_namespace(ACPI_TYPE_DEVICE,
-			    ACPI_ROOT_OBJECT,
-			    ACPI_UINT32_MAX,
-			    container_walk_namespace_cb, NULL, &action, NULL);
+	if (is_container(handle))
+		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+					    container_notify_cb, NULL);
 
-	return (0);
+	return AE_OK;
 }
 
-static void __exit acpi_container_exit(void)
+void __init acpi_container_init(void)
 {
-	int action = UNINSTALL_NOTIFY_HANDLER;
-
-
-	acpi_walk_namespace(ACPI_TYPE_DEVICE,
-			    ACPI_ROOT_OBJECT,
-			    ACPI_UINT32_MAX,
-			    container_walk_namespace_cb, NULL, &action, NULL);
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+			    acpi_container_register_notify_handler, NULL,
+			    NULL, NULL);
 
-	acpi_bus_unregister_driver(&acpi_container_driver);
-
-	return;
+	acpi_scan_add_handler(&container_device_handler);
 }
-
-module_init(acpi_container_init);
-module_exit(acpi_container_exit);
Index: test/drivers/acpi/Kconfig
===================================================================
--- test.orig/drivers/acpi/Kconfig
+++ test/drivers/acpi/Kconfig
@@ -334,7 +334,7 @@ config X86_PM_TIMER
 	  systems require this timer. 
 
 config ACPI_CONTAINER
-	tristate "Container and Module Devices (EXPERIMENTAL)"
+	bool "Container and Module Devices (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
 	default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
 	help
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -35,6 +35,11 @@ void acpi_pci_slot_init(void);
 #else
 static inline void acpi_pci_slot_init(void) { }
 #endif
+#ifdef CONFIG_ACPI_CONTAINER
+void acpi_container_init(void);
+#else
+static inline void acpi_container_init(void) {}
+#endif
 
 #ifdef CONFIG_DEBUG_FS
 extern struct dentry *acpi_debugfs_dir;
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -1762,6 +1762,7 @@ int __init acpi_scan_init(void)
 	acpi_pci_slot_init();
 	acpi_platform_init();
 	acpi_csrt_init();
+	acpi_container_init();
 
 	/*
 	 * Enumerate devices in the ACPI namespace.


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-07 22:42                 ` Rafael J. Wysocki
@ 2013-02-08  1:05                   ` Toshi Kani
  2013-02-08 12:52                     ` Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-02-08  1:05 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Thu, 2013-02-07 at 23:42 +0100, Rafael J. Wysocki wrote:
> On Thursday, February 07, 2013 07:32:07 AM Toshi Kani wrote:
> > On Thu, 2013-02-07 at 02:32 +0100, Rafael J. Wysocki wrote:
> > > On Wednesday, February 06, 2013 05:51:42 PM Toshi Kani wrote:
> > > > On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> > > > > On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > > > > > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
 :
> > > > > Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> > > > > actually makes sense after the recent changes to acpi_bus_trim(), because that
> > > > > can't fail now, so the eject will always be carried out.  So perhaps we can
> > > > > simply remove the acpi_device->driver check from there entirely in the first
> > > > > place?
> > > > >
> > > > > If we really want to be able to prevent ejects from happening in some cases,
> > > > > we need to implement something along the lines discussed with Greg.
> > > > 
> > > > acpi_bus_trim() cannot fail, but sysfs eject can fail.  So, I think it
> > > > makes sense to do some validation before calling acpi_bus_trim().  If we
> > > > are to implement the no_eject flag thing, that check needs to be made
> > > > before calling acpi_bus_trim().
> > > 
> > > Sure, but now the logic seems to be "if FORCE_EJECT is not set, don't eject
> > > devices that have no ACPI drivers", so I'm wondering what the purpose of this
> > > is.  It definitely isn't too obvious. :-)
> > 
> > The check sounds odd for container, but is necessary for CPU and memory
> > for now.  CPU and memory go online without their ACPI drivers at boot.
> > So, without this check (i.e. FORCE_EJECT is set), it simply ejects them
> > without attempting to offline when the ACPI drivers are not bound.  Of
> > course, we have the issue of a failure in offline be ignored, so this
> > offlining part needs to be moved out from acpi_bus_trim() in one way or
> > the other.
> 
> That was my point.
> 
> I'm going to add that change for now, but I think we need to take a step back
> and talk about how we want the whole eject machinery to work, regardless of
> the offline/online problem.

Right.

> I think that it should work in the same way for all things that may be ejected
> or inserted.  Namely, they all should use the same notify handler, for example,
> and if we generate a uevent for one, we should do that for all of them.

Agreed.

> Question is how that notify handler should work and here there are two chices
> in my view: Either we'll always emit a uevent and wait for user space to start
> the eject procedure via sysfs, or we won't emit uevents at all and rely on the
> "no_eject" flag to trigger if something is not ready.  I'm basically fine with
> any of them (the "no_eject" flag may be useful even if we rely on user space
> to offline stuff before triggering the eject in my opinion), but if we're going
> to rely on user space, then there needs to be a timeout for letting the BIOS
> know that the eject has failed.
> 
> [There may be a flag for the common code telling it whether to emit a uevent
> and wait for user space to trigger eject or to trigger eject by itself.]

IMHO, the kernel waiting for a user program to complete is a recipe for
future problems.  So, I think two possible implementation choices are:

1. Upon an eject request, off-line all devices and eject
 => Implement a kernel sequencer (my RFC patchset)

2. Upon an eject request, eject if all devices are off-lined beforehand 
 => Implement the "no_eject" approach

Since we are heading to the user space approach, we need to go with #2.
There are some challenges with #2, ex. if sysfs memory online/offline
interfaces can correspond with ACPI memory objects, which we will also
need to look into.

> Next, I think there needs to be a global list of IDs for which we'll install
> hot-plug notify handlers and which we'll allow to be ejected via /sys/.../eject.
> So, if a device ID is on that list, we'll install the (common) hot-plug notify
> handler for its ACPI handle and we'll set an "eject_possible" flag in its
> struct acpi_device (when created).  That will need to be done for every scan
> of the ACPI namespace and not just once, BTW.  And we'll check the
> "eject_possible" flag in acpi_eject_store() instead of the "does it have a
> driver or scan handler" check.
>
> Then, the scan handlers for hot-plug devices will be able to add their IDs to
> that global list instead of walking the namespace and installing notify handlers
> by themselves (which as I said has a problem that it's done once, while it
> should be done every time acpi_bus_scan() runs).

I agree.  I think we can use the global notify handler (as the common
notify handler) to look up the eject_possible ID list, instead of
installing a notify handler to each device.


Thanks,
-Toshi



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver
  2013-02-08  0:24       ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
  2013-02-08  0:25         ` [PATCH 1/2] ACPI / scan: Remove useless #ifndef from acpi_eject_store() Rafael J. Wysocki
  2013-02-08  0:27         ` [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler Rafael J. Wysocki
@ 2013-02-08  3:19         ` Yasuaki Ishimatsu
  2013-02-08 12:46           ` Rafael J. Wysocki
  2013-02-08 16:57         ` Toshi Kani
  2013-02-09 14:26         ` [PATCH 0/2] ACPI / scan: Two fixes for device hot-removal Rafael J. Wysocki
  4 siblings, 1 reply; 71+ messages in thread
From: Yasuaki Ishimatsu @ 2013-02-08  3:19 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML

Hi Rafael,

2013/02/08 9:24, Rafael J. Wysocki wrote:
> On Monday, February 04, 2013 12:47:31 AM Rafael J. Wysocki wrote:
>> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>
>> The only useful thing that the ACPI container driver does is to
>> install system notify handlers for all container and module device
>> objects it finds in the namespace.  The driver structure,
>> acpi_container_driver, and the data structures created by its
>> .add() callback are in fact not used by the driver, so remove
>> them entirely.
>>
>> It also makes a little sense to build that driver as a module,
>> so make it non-modular and add its initialization to the
>> namespace scanning code.
>>
>> In addition to that, make the namespace walk callback used for
>> installing the notify handlers more straightforward.
>
> As pointed out by Toshi Kani, the above changes would make acpi_eject_store()
> fail for containers and it is the only way to eject them currently, so patch
> [2/2] is an improved version of this (with Toshi's changes folded in).
>
> Patch [1/2] is just a cleanup removing a useless #ifndef from acpi_eject_store().

I confimed the patch series works well.

Acked-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Tested-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>

Thanks,
Yasuaki Ishimatsu

>
> Thanks,
> Rafael
>
>



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler
  2013-02-08  0:27         ` [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler Rafael J. Wysocki
@ 2013-02-08  3:32           ` Yinghai Lu
  2013-02-08 12:45             ` Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Yinghai Lu @ 2013-02-08  3:32 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Jiang Liu, Toshi Kani, LKML,
	Yasuaki Ishimatsu

On Thu, Feb 7, 2013 at 4:27 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Make the ACPI container driver use struct acpi_scan_handler for
> representing the object used to initialize ACPI containers and remove
> the ACPI driver structure used previously and the data structures
> created by it, since in fact they were not used for any purpose.
>
> This simplifies the code and reduces the kernel's memory footprint by
> avoiding the registration of a struct device_driver object with the
> driver core and creation of its sysfs directory which is unnecessary.
>
> In addition to that, make the namespace walk callback used for
> installing the notify handlers for ACPI containers more
> straightforward.
>
> This change includes fixes from Toshi Kani.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Yes, container support should be built-in by nature.

Acked-by: Yinghai Lu <yinghai@kernel.org>

What is the next?

dock?

Hope someone with access of dock that have pcie devices could help
sorting it out...

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler
  2013-02-08  3:32           ` Yinghai Lu
@ 2013-02-08 12:45             ` Rafael J. Wysocki
  0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 12:45 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Jiang Liu, Toshi Kani, LKML,
	Yasuaki Ishimatsu

On Thursday, February 07, 2013 07:32:22 PM Yinghai Lu wrote:
> On Thu, Feb 7, 2013 at 4:27 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Make the ACPI container driver use struct acpi_scan_handler for
> > representing the object used to initialize ACPI containers and remove
> > the ACPI driver structure used previously and the data structures
> > created by it, since in fact they were not used for any purpose.
> >
> > This simplifies the code and reduces the kernel's memory footprint by
> > avoiding the registration of a struct device_driver object with the
> > driver core and creation of its sysfs directory which is unnecessary.
> >
> > In addition to that, make the namespace walk callback used for
> > installing the notify handlers for ACPI containers more
> > straightforward.
> >
> > This change includes fixes from Toshi Kani.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Yes, container support should be built-in by nature.
> 
> Acked-by: Yinghai Lu <yinghai@kernel.org>

Thanks!

> What is the next?

I've sent a patch for memory hotplug already, but I'm a little concerned about
it, because after my patch users wouldn't have an option to turn memory eject
off (now they can remove the module, which is suboptimal, but at least it kind
kind of works).  So I think there needs to be some sysfs-based switch for that
or something.

> dock?

It is on the radar, but it also is kind of a can of worms. :-)

> Hope someone with access of dock that have pcie devices could help
> sorting it out...

Someone having a system like that told me he was willing to test patches,
but I got distracted by something.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver
  2013-02-08  3:19         ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver Yasuaki Ishimatsu
@ 2013-02-08 12:46           ` Rafael J. Wysocki
  0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 12:46 UTC (permalink / raw)
  To: Yasuaki Ishimatsu
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML

On Friday, February 08, 2013 12:19:35 PM Yasuaki Ishimatsu wrote:
> Hi Rafael,
> 
> 2013/02/08 9:24, Rafael J. Wysocki wrote:
> > On Monday, February 04, 2013 12:47:31 AM Rafael J. Wysocki wrote:
> >> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >>
> >> The only useful thing that the ACPI container driver does is to
> >> install system notify handlers for all container and module device
> >> objects it finds in the namespace.  The driver structure,
> >> acpi_container_driver, and the data structures created by its
> >> .add() callback are in fact not used by the driver, so remove
> >> them entirely.
> >>
> >> It also makes a little sense to build that driver as a module,
> >> so make it non-modular and add its initialization to the
> >> namespace scanning code.
> >>
> >> In addition to that, make the namespace walk callback used for
> >> installing the notify handlers more straightforward.
> >
> > As pointed out by Toshi Kani, the above changes would make acpi_eject_store()
> > fail for containers and it is the only way to eject them currently, so patch
> > [2/2] is an improved version of this (with Toshi's changes folded in).
> >
> > Patch [1/2] is just a cleanup removing a useless #ifndef from acpi_eject_store().
> 
> I confimed the patch series works well.
> 
> Acked-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
> Tested-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>

Thanks a lot!

Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-08  1:05                   ` Toshi Kani
@ 2013-02-08 12:52                     ` Rafael J. Wysocki
  2013-02-08 16:24                       ` Toshi Kani
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 12:52 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Thursday, February 07, 2013 06:05:19 PM Toshi Kani wrote:
> On Thu, 2013-02-07 at 23:42 +0100, Rafael J. Wysocki wrote:
> > On Thursday, February 07, 2013 07:32:07 AM Toshi Kani wrote:
> > > On Thu, 2013-02-07 at 02:32 +0100, Rafael J. Wysocki wrote:
> > > > On Wednesday, February 06, 2013 05:51:42 PM Toshi Kani wrote:
> > > > > On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> > > > > > On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > > > > > > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
>  :
> > > > > > Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> > > > > > actually makes sense after the recent changes to acpi_bus_trim(), because that
> > > > > > can't fail now, so the eject will always be carried out.  So perhaps we can
> > > > > > simply remove the acpi_device->driver check from there entirely in the first
> > > > > > place?
> > > > > >
> > > > > > If we really want to be able to prevent ejects from happening in some cases,
> > > > > > we need to implement something along the lines discussed with Greg.
> > > > > 
> > > > > acpi_bus_trim() cannot fail, but sysfs eject can fail.  So, I think it
> > > > > makes sense to do some validation before calling acpi_bus_trim().  If we
> > > > > are to implement the no_eject flag thing, that check needs to be made
> > > > > before calling acpi_bus_trim().
> > > > 
> > > > Sure, but now the logic seems to be "if FORCE_EJECT is not set, don't eject
> > > > devices that have no ACPI drivers", so I'm wondering what the purpose of this
> > > > is.  It definitely isn't too obvious. :-)
> > > 
> > > The check sounds odd for container, but is necessary for CPU and memory
> > > for now.  CPU and memory go online without their ACPI drivers at boot.
> > > So, without this check (i.e. FORCE_EJECT is set), it simply ejects them
> > > without attempting to offline when the ACPI drivers are not bound.  Of
> > > course, we have the issue of a failure in offline be ignored, so this
> > > offlining part needs to be moved out from acpi_bus_trim() in one way or
> > > the other.
> > 
> > That was my point.
> > 
> > I'm going to add that change for now, but I think we need to take a step back
> > and talk about how we want the whole eject machinery to work, regardless of
> > the offline/online problem.
> 
> Right.
> 
> > I think that it should work in the same way for all things that may be ejected
> > or inserted.  Namely, they all should use the same notify handler, for example,
> > and if we generate a uevent for one, we should do that for all of them.
> 
> Agreed.
> 
> > Question is how that notify handler should work and here there are two chices
> > in my view: Either we'll always emit a uevent and wait for user space to start
> > the eject procedure via sysfs, or we won't emit uevents at all and rely on the
> > "no_eject" flag to trigger if something is not ready.  I'm basically fine with
> > any of them (the "no_eject" flag may be useful even if we rely on user space
> > to offline stuff before triggering the eject in my opinion), but if we're going
> > to rely on user space, then there needs to be a timeout for letting the BIOS
> > know that the eject has failed.
> > 
> > [There may be a flag for the common code telling it whether to emit a uevent
> > and wait for user space to trigger eject or to trigger eject by itself.]
> 
> IMHO, the kernel waiting for a user program to complete is a recipe for
> future problems.  So, I think two possible implementation choices are:
> 
> 1. Upon an eject request, off-line all devices and eject
>  => Implement a kernel sequencer (my RFC patchset)
> 
> 2. Upon an eject request, eject if all devices are off-lined beforehand 
>  => Implement the "no_eject" approach
> 
> Since we are heading to the user space approach, we need to go with #2.
> There are some challenges with #2, ex. if sysfs memory online/offline
> interfaces can correspond with ACPI memory objects, which we will also
> need to look into.

Sure.

> > Next, I think there needs to be a global list of IDs for which we'll install
> > hot-plug notify handlers and which we'll allow to be ejected via /sys/.../eject.
> > So, if a device ID is on that list, we'll install the (common) hot-plug notify
> > handler for its ACPI handle and we'll set an "eject_possible" flag in its
> > struct acpi_device (when created).  That will need to be done for every scan
> > of the ACPI namespace and not just once, BTW.  And we'll check the
> > "eject_possible" flag in acpi_eject_store() instead of the "does it have a
> > driver or scan handler" check.
> >
> > Then, the scan handlers for hot-plug devices will be able to add their IDs to
> > that global list instead of walking the namespace and installing notify handlers
> > by themselves (which as I said has a problem that it's done once, while it
> > should be done every time acpi_bus_scan() runs).
> 
> I agree.  I think we can use the global notify handler (as the common
> notify handler) to look up the eject_possible ID list, instead of
> installing a notify handler to each device.

Actually installing notify handlers for individual devices may be more
efficient, because then we'll know what device the notification is for without
looking it up.

OK, so it looks like I need to sit down and cut some more patches. :-)

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
  2013-02-08 12:52                     ` Rafael J. Wysocki
@ 2013-02-08 16:24                       ` Toshi Kani
  0 siblings, 0 replies; 71+ messages in thread
From: Toshi Kani @ 2013-02-08 16:24 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML

On Fri, 2013-02-08 at 13:52 +0100, Rafael J. Wysocki wrote:
> On Thursday, February 07, 2013 06:05:19 PM Toshi Kani wrote:
> > On Thu, 2013-02-07 at 23:42 +0100, Rafael J. Wysocki wrote:
> > > On Thursday, February 07, 2013 07:32:07 AM Toshi Kani wrote:
> > > > On Thu, 2013-02-07 at 02:32 +0100, Rafael J. Wysocki wrote:
> > > > > On Wednesday, February 06, 2013 05:51:42 PM Toshi Kani wrote:
> > > > > > On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> > > > > > > On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > > > > > > > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> >  :
> > > > > > > Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> > > > > > > actually makes sense after the recent changes to acpi_bus_trim(), because that
> > > > > > > can't fail now, so the eject will always be carried out.  So perhaps we can
> > > > > > > simply remove the acpi_device->driver check from there entirely in the first
> > > > > > > place?
> > > > > > >
> > > > > > > If we really want to be able to prevent ejects from happening in some cases,
> > > > > > > we need to implement something along the lines discussed with Greg.
> > > > > > 
> > > > > > acpi_bus_trim() cannot fail, but sysfs eject can fail.  So, I think it
> > > > > > makes sense to do some validation before calling acpi_bus_trim().  If we
> > > > > > are to implement the no_eject flag thing, that check needs to be made
> > > > > > before calling acpi_bus_trim().
> > > > > 
> > > > > Sure, but now the logic seems to be "if FORCE_EJECT is not set, don't eject
> > > > > devices that have no ACPI drivers", so I'm wondering what the purpose of this
> > > > > is.  It definitely isn't too obvious. :-)
> > > > 
> > > > The check sounds odd for container, but is necessary for CPU and memory
> > > > for now.  CPU and memory go online without their ACPI drivers at boot.
> > > > So, without this check (i.e. FORCE_EJECT is set), it simply ejects them
> > > > without attempting to offline when the ACPI drivers are not bound.  Of
> > > > course, we have the issue of a failure in offline be ignored, so this
> > > > offlining part needs to be moved out from acpi_bus_trim() in one way or
> > > > the other.
> > > 
> > > That was my point.
> > > 
> > > I'm going to add that change for now, but I think we need to take a step back
> > > and talk about how we want the whole eject machinery to work, regardless of
> > > the offline/online problem.
> > 
> > Right.
> > 
> > > I think that it should work in the same way for all things that may be ejected
> > > or inserted.  Namely, they all should use the same notify handler, for example,
> > > and if we generate a uevent for one, we should do that for all of them.
> > 
> > Agreed.
> > 
> > > Question is how that notify handler should work and here there are two chices
> > > in my view: Either we'll always emit a uevent and wait for user space to start
> > > the eject procedure via sysfs, or we won't emit uevents at all and rely on the
> > > "no_eject" flag to trigger if something is not ready.  I'm basically fine with
> > > any of them (the "no_eject" flag may be useful even if we rely on user space
> > > to offline stuff before triggering the eject in my opinion), but if we're going
> > > to rely on user space, then there needs to be a timeout for letting the BIOS
> > > know that the eject has failed.
> > > 
> > > [There may be a flag for the common code telling it whether to emit a uevent
> > > and wait for user space to trigger eject or to trigger eject by itself.]
> > 
> > IMHO, the kernel waiting for a user program to complete is a recipe for
> > future problems.  So, I think two possible implementation choices are:
> > 
> > 1. Upon an eject request, off-line all devices and eject
> >  => Implement a kernel sequencer (my RFC patchset)
> > 
> > 2. Upon an eject request, eject if all devices are off-lined beforehand 
> >  => Implement the "no_eject" approach
> > 
> > Since we are heading to the user space approach, we need to go with #2.
> > There are some challenges with #2, ex. if sysfs memory online/offline
> > interfaces can correspond with ACPI memory objects, which we will also
> > need to look into.
> 
> Sure.
> 
> > > Next, I think there needs to be a global list of IDs for which we'll install
> > > hot-plug notify handlers and which we'll allow to be ejected via /sys/.../eject.
> > > So, if a device ID is on that list, we'll install the (common) hot-plug notify
> > > handler for its ACPI handle and we'll set an "eject_possible" flag in its
> > > struct acpi_device (when created).  That will need to be done for every scan
> > > of the ACPI namespace and not just once, BTW.  And we'll check the
> > > "eject_possible" flag in acpi_eject_store() instead of the "does it have a
> > > driver or scan handler" check.
> > >
> > > Then, the scan handlers for hot-plug devices will be able to add their IDs to
> > > that global list instead of walking the namespace and installing notify handlers
> > > by themselves (which as I said has a problem that it's done once, while it
> > > should be done every time acpi_bus_scan() runs).
> > 
> > I agree.  I think we can use the global notify handler (as the common
> > notify handler) to look up the eject_possible ID list, instead of
> > installing a notify handler to each device.
> 
> Actually installing notify handlers for individual devices may be more
> efficient, because then we'll know what device the notification is for without
> looking it up.

Right.  I am fine with either way as long as we can get rid of the
scanning from each driver and support dynamic ACPI namespace.

> OK, so it looks like I need to sit down and cut some more patches. :-)

Cool!

Thanks,
-Toshi


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver
  2013-02-08  0:24       ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
                           ` (2 preceding siblings ...)
  2013-02-08  3:19         ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver Yasuaki Ishimatsu
@ 2013-02-08 16:57         ` Toshi Kani
  2013-02-08 19:59           ` Rafael J. Wysocki
  2013-02-09 14:26         ` [PATCH 0/2] ACPI / scan: Two fixes for device hot-removal Rafael J. Wysocki
  4 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-02-08 16:57 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML,
	Yasuaki Ishimatsu

On Fri, 2013-02-08 at 01:24 +0100, Rafael J. Wysocki wrote:
> On Monday, February 04, 2013 12:47:31 AM Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> > The only useful thing that the ACPI container driver does is to
> > install system notify handlers for all container and module device
> > objects it finds in the namespace.  The driver structure,
> > acpi_container_driver, and the data structures created by its
> > .add() callback are in fact not used by the driver, so remove
> > them entirely.
> > 
> > It also makes a little sense to build that driver as a module,
> > so make it non-modular and add its initialization to the
> > namespace scanning code.
> > 
> > In addition to that, make the namespace walk callback used for
> > installing the notify handlers more straightforward.
> 
> As pointed out by Toshi Kani, the above changes would make acpi_eject_store()
> fail for containers and it is the only way to eject them currently, so patch
> [2/2] is an improved version of this (with Toshi's changes folded in).
> 
> Patch [1/2] is just a cleanup removing a useless #ifndef from acpi_eject_store().

Thanks for the update!  They look good.  For the series:

Reviewed-by: Toshi Kani <toshi.kani@hp.com>
Tested-by: Toshi Kani <toshi.kani@hp.com>

BTW, did you intentionally keep the struct acpi_container definition in
<acpi/container.h>?  I deleted that one in my patch.

-Toshi


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver
  2013-02-08 16:57         ` Toshi Kani
@ 2013-02-08 19:59           ` Rafael J. Wysocki
  2013-02-08 22:41             ` Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 19:59 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML,
	Yasuaki Ishimatsu

On Friday, February 08, 2013 09:57:18 AM Toshi Kani wrote:
> On Fri, 2013-02-08 at 01:24 +0100, Rafael J. Wysocki wrote:
> > On Monday, February 04, 2013 12:47:31 AM Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > 
> > > The only useful thing that the ACPI container driver does is to
> > > install system notify handlers for all container and module device
> > > objects it finds in the namespace.  The driver structure,
> > > acpi_container_driver, and the data structures created by its
> > > .add() callback are in fact not used by the driver, so remove
> > > them entirely.
> > > 
> > > It also makes a little sense to build that driver as a module,
> > > so make it non-modular and add its initialization to the
> > > namespace scanning code.
> > > 
> > > In addition to that, make the namespace walk callback used for
> > > installing the notify handlers more straightforward.
> > 
> > As pointed out by Toshi Kani, the above changes would make acpi_eject_store()
> > fail for containers and it is the only way to eject them currently, so patch
> > [2/2] is an improved version of this (with Toshi's changes folded in).
> > 
> > Patch [1/2] is just a cleanup removing a useless #ifndef from acpi_eject_store().
> 
> Thanks for the update!  They look good.  For the series:
> 
> Reviewed-by: Toshi Kani <toshi.kani@hp.com>
> Tested-by: Toshi Kani <toshi.kani@hp.com>
> 
> BTW, did you intentionally keep the struct acpi_container definition in
> <acpi/container.h>?  I deleted that one in my patch.

No, I overlooked that part.  I'll apply that part of your patch as a separate
patch on top of this one.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver
  2013-02-08 19:59           ` Rafael J. Wysocki
@ 2013-02-08 22:41             ` Rafael J. Wysocki
  2013-02-08 23:18               ` [PATCH] ACPI: Drop the container.h header file Rafael J. Wysocki
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 22:41 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML,
	Yasuaki Ishimatsu

On Friday, February 08, 2013 08:59:44 PM Rafael J. Wysocki wrote:
> On Friday, February 08, 2013 09:57:18 AM Toshi Kani wrote:
> > On Fri, 2013-02-08 at 01:24 +0100, Rafael J. Wysocki wrote:
> > > On Monday, February 04, 2013 12:47:31 AM Rafael J. Wysocki wrote:
> > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > 
> > > > The only useful thing that the ACPI container driver does is to
> > > > install system notify handlers for all container and module device
> > > > objects it finds in the namespace.  The driver structure,
> > > > acpi_container_driver, and the data structures created by its
> > > > .add() callback are in fact not used by the driver, so remove
> > > > them entirely.
> > > > 
> > > > It also makes a little sense to build that driver as a module,
> > > > so make it non-modular and add its initialization to the
> > > > namespace scanning code.
> > > > 
> > > > In addition to that, make the namespace walk callback used for
> > > > installing the notify handlers more straightforward.
> > > 
> > > As pointed out by Toshi Kani, the above changes would make acpi_eject_store()
> > > fail for containers and it is the only way to eject them currently, so patch
> > > [2/2] is an improved version of this (with Toshi's changes folded in).
> > > 
> > > Patch [1/2] is just a cleanup removing a useless #ifndef from acpi_eject_store().
> > 
> > Thanks for the update!  They look good.  For the series:
> > 
> > Reviewed-by: Toshi Kani <toshi.kani@hp.com>
> > Tested-by: Toshi Kani <toshi.kani@hp.com>
> > 
> > BTW, did you intentionally keep the struct acpi_container definition in
> > <acpi/container.h>?  I deleted that one in my patch.
> 
> No, I overlooked that part.  I'll apply that part of your patch as a separate
> patch on top of this one.

Actually, I prefer to remove container.h entirely.  I'll post a patch for that
shortly.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH] ACPI: Drop the container.h header file
  2013-02-08 22:41             ` Rafael J. Wysocki
@ 2013-02-08 23:18               ` Rafael J. Wysocki
  2013-02-08 23:27                 ` Toshi Kani
  0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 23:18 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
	Matthew Garrett, Yinghai Lu, Jiang Liu, LKML, Yasuaki Ishimatsu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

The include/acpi/container.h only contains a definition of a
structure that is not used any more, so drop it entirely.

Similar change was proposed earlier by Toshi Kani.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---

On top of current linux-pm.git/bleeding-edge.

Thanks,
Rafael

---
 drivers/acpi/container.c |    1 -
 include/acpi/container.h |   12 ------------
 2 files changed, 13 deletions(-)

Index: test/include/acpi/container.h
===================================================================
--- test.orig/include/acpi/container.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __ACPI_CONTAINER_H
-#define __ACPI_CONTAINER_H
-
-#include <linux/kernel.h>
-
-struct acpi_container {
-	acpi_handle handle;
-	unsigned long sun;
-	int state;
-};
-
-#endif				/* __ACPI_CONTAINER_H */
Index: test/drivers/acpi/container.c
===================================================================
--- test.orig/drivers/acpi/container.c
+++ test/drivers/acpi/container.c
@@ -34,7 +34,6 @@
 #include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
-#include <acpi/container.h>
 
 #define PREFIX "ACPI: "
 


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH] ACPI: Drop the container.h header file
  2013-02-08 23:18               ` [PATCH] ACPI: Drop the container.h header file Rafael J. Wysocki
@ 2013-02-08 23:27                 ` Toshi Kani
  0 siblings, 0 replies; 71+ messages in thread
From: Toshi Kani @ 2013-02-08 23:27 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
	Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML,
	Yasuaki Ishimatsu

On Sat, 2013-02-09 at 00:18 +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> The include/acpi/container.h only contains a definition of a
> structure that is not used any more, so drop it entirely.
> 
> Similar change was proposed earlier by Toshi Kani.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Acked-by: Toshi Kani <toshi.kani@hp.com>

Thanks,
-Toshi


> ---
> 
> On top of current linux-pm.git/bleeding-edge.
> 
> Thanks,
> Rafael
> 
> ---
>  drivers/acpi/container.c |    1 -
>  include/acpi/container.h |   12 ------------
>  2 files changed, 13 deletions(-)
> 
> Index: test/include/acpi/container.h
> ===================================================================
> --- test.orig/include/acpi/container.h
> +++ /dev/null
> @@ -1,12 +0,0 @@
> -#ifndef __ACPI_CONTAINER_H
> -#define __ACPI_CONTAINER_H
> -
> -#include <linux/kernel.h>
> -
> -struct acpi_container {
> -	acpi_handle handle;
> -	unsigned long sun;
> -	int state;
> -};
> -
> -#endif				/* __ACPI_CONTAINER_H */
> Index: test/drivers/acpi/container.c
> ===================================================================
> --- test.orig/drivers/acpi/container.c
> +++ test/drivers/acpi/container.c
> @@ -34,7 +34,6 @@
>  #include <linux/acpi.h>
>  #include <acpi/acpi_bus.h>
>  #include <acpi/acpi_drivers.h>
> -#include <acpi/container.h>
>  
>  #define PREFIX "ACPI: "
>  
> 



^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 0/2] ACPI / scan: Two fixes for device hot-removal
  2013-02-08  0:24       ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
                           ` (3 preceding siblings ...)
  2013-02-08 16:57         ` Toshi Kani
@ 2013-02-09 14:26         ` Rafael J. Wysocki
  2013-02-09 14:29           ` [PATCH 1/2] ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock Rafael J. Wysocki
  2013-02-09 14:31           ` [PATCH 2/2] ACPI / scan: Full transition to D3cold in acpi_device_unregister() Rafael J. Wysocki
  4 siblings, 2 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-09 14:26 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Mika Westerberg, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML, Yasuaki Ishimatsu

Hi,

The following two patches fix issues I've found revently in the ACPI device
hot-removal code.

Patch [1/2] makes acpi_bus_hot_remove_device() hold acpi_scan_lock around the
whole removal procedure to prevent potential race condition between
acpi_bus_scan() and a conflicting evaluation of _EJ0 from happening.

Patch [2/2] makes acpi_device_unregister() put devices (supporting that) into
D3cold to prevent potential problems with removing power from them without
preparation from happening and removes the totally wrong evaluation of _PS3
from acpi_bus_hot_remove_device().

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 1/2] ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock
  2013-02-09 14:26         ` [PATCH 0/2] ACPI / scan: Two fixes for device hot-removal Rafael J. Wysocki
@ 2013-02-09 14:29           ` Rafael J. Wysocki
  2013-02-11 23:42             ` Toshi Kani
  2013-02-09 14:31           ` [PATCH 2/2] ACPI / scan: Full transition to D3cold in acpi_device_unregister() Rafael J. Wysocki
  1 sibling, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-09 14:29 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Mika Westerberg, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML, Yasuaki Ishimatsu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

The ACPI scan lock has been introduced to prevent acpi_bus_scan()
and acpi_bus_trim() from running in parallel with each other for
overlapping ACPI namespace scopes.  However, it is not sufficient
to do that, because if acpi_bus_scan() is run (for an overlapping
namespace scope) right after the acpi_bus_trim() in
acpi_bus_hot_remove_device(), the subsequent eject will remove
devices without removing the corresponding struct acpi_device
objects (and possibly companion "physical" device objects).
Therefore acpi_bus_hot_remove_device() has to acquire the scan
lock before carrying out the bus trimming and hold it through
the evaluation of _EJ0, so make that happen.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c |   31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -95,6 +95,8 @@ acpi_device_modalias_show(struct device
 }
 static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
 
+static void __acpi_bus_trim(struct acpi_device *start);
+
 /**
  * acpi_bus_hot_remove_device: hot-remove a device and its children
  * @context: struct acpi_eject_event pointer (freed in this func)
@@ -114,10 +116,12 @@ void acpi_bus_hot_remove_device(void *co
 	acpi_status status = AE_OK;
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
 
+	mutex_lock(&acpi_scan_lock);
+
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 		"Hot-removing device %s...\n", dev_name(&device->dev)));
 
-	acpi_bus_trim(device);
+	__acpi_bus_trim(device);
 	/* Device node has been released. */
 	device = NULL;
 
@@ -146,18 +150,14 @@ void acpi_bus_hot_remove_device(void *co
 	status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
 	if (ACPI_FAILURE(status)) {
 		if (status != AE_NOT_FOUND)
-			printk(KERN_WARNING PREFIX
-					"Eject device failed\n");
-		goto err_out;
-	}
+			acpi_handle_warn(handle, "Eject failed\n");
 
-	kfree(context);
-	return;
+		/* Tell the firmware the hot-remove operation has failed. */
+		acpi_evaluate_hotplug_ost(handle, ej_event->event,
+					  ost_code, NULL);
+	}
 
-err_out:
-	/* Inform firmware the hot-remove operation has completed w/ error */
-	(void) acpi_evaluate_hotplug_ost(handle,
-				ej_event->event, ost_code, NULL);
+	mutex_unlock(&acpi_scan_lock);
 	kfree(context);
 	return;
 }
@@ -1686,10 +1686,8 @@ static acpi_status acpi_bus_remove(acpi_
 	return AE_OK;
 }
 
-void acpi_bus_trim(struct acpi_device *start)
+static void __acpi_bus_trim(struct acpi_device *start)
 {
-	mutex_lock(&acpi_scan_lock);
-
 	/*
 	 * Execute acpi_bus_device_detach() as a post-order callback to detach
 	 * all ACPI drivers from the device nodes being removed.
@@ -1704,7 +1702,12 @@ void acpi_bus_trim(struct acpi_device *s
 	acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
 			    acpi_bus_remove, NULL, NULL);
 	acpi_bus_remove(start->handle, 0, NULL, NULL);
+}
 
+void acpi_bus_trim(struct acpi_device *start)
+{
+	mutex_lock(&acpi_scan_lock);
+	__acpi_bus_trim(start);
 	mutex_unlock(&acpi_scan_lock);
 }
 EXPORT_SYMBOL_GPL(acpi_bus_trim);


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 2/2] ACPI / scan: Full transition to D3cold in acpi_device_unregister()
  2013-02-09 14:26         ` [PATCH 0/2] ACPI / scan: Two fixes for device hot-removal Rafael J. Wysocki
  2013-02-09 14:29           ` [PATCH 1/2] ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock Rafael J. Wysocki
@ 2013-02-09 14:31           ` Rafael J. Wysocki
  1 sibling, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-09 14:31 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Mika Westerberg, Yinghai Lu, Jiang Liu,
	Toshi Kani, LKML, Yasuaki Ishimatsu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

In order to drop reference counts of all power resources used by an
ACPI device node being removed, acpi_device_unregister() calls
acpi_power_transition(device, ACPI_STATE_D3_COLD), which effectively
transitions the device node into D3cold if it uses any power
resources.  However, for some device nodes it may not be appropriate
to remove power from them entirely before putting them into D3hot 
before.  On the other hand, executing _PS3 for devices that don't
use power resources before removing them shouldn't really hurt.
In fact, that is done by acpi_bus_hot_remove_device(), but this is
not the right place to do it, because the bus trimming may have
caused power to be removed from the device node in question already
before.

For these reasons, make acpi_device_unregister() carry out full
power-off transition for all device nodes supporting that and remove
the direct evaluation of _PS3 from acpi_bus_hot_remove_device().

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c |   13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -125,12 +125,6 @@ void acpi_bus_hot_remove_device(void *co
 	/* Device node has been released. */
 	device = NULL;
 
-	/* power off device */
-	status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
-	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
-		printk(KERN_WARNING PREFIX
-				"Power-off device failed\n");
-
 	if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) {
 		arg_list.count = 1;
 		arg_list.pointer = &arg;
@@ -780,10 +774,11 @@ static void acpi_device_unregister(struc
 
 	device_del(&device->dev);
 	/*
-	 * Drop the reference counts of all power resources the device depends
-	 * on and turn off the ones that have no more references.
+	 * Transition the device to D3cold to drop the reference counts of all
+	 * power resources the device depends on and turn off the ones that have
+	 * no more references.
 	 */
-	acpi_power_transition(device, ACPI_STATE_D3_COLD);
+	acpi_device_set_power(device, ACPI_STATE_D3_COLD);
 	put_device(&device->dev);
 }
 


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 1/2] ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock
  2013-02-09 14:29           ` [PATCH 1/2] ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock Rafael J. Wysocki
@ 2013-02-11 23:42             ` Toshi Kani
  0 siblings, 0 replies; 71+ messages in thread
From: Toshi Kani @ 2013-02-11 23:42 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Mika Westerberg,
	Yinghai Lu, Jiang Liu, LKML, Yasuaki Ishimatsu

On Sat, 2013-02-09 at 15:29 +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> The ACPI scan lock has been introduced to prevent acpi_bus_scan()
> and acpi_bus_trim() from running in parallel with each other for
> overlapping ACPI namespace scopes.  However, it is not sufficient
> to do that, because if acpi_bus_scan() is run (for an overlapping
> namespace scope) right after the acpi_bus_trim() in
> acpi_bus_hot_remove_device(), the subsequent eject will remove
> devices without removing the corresponding struct acpi_device
> objects (and possibly companion "physical" device objects).
> Therefore acpi_bus_hot_remove_device() has to acquire the scan
> lock before carrying out the bus trimming and hold it through
> the evaluation of _EJ0, so make that happen.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Looks good.

Acked-by: Toshi Kani <toshi.kani@hp.com>

Thanks,
-Toshi


> ---
>  drivers/acpi/scan.c |   31 +++++++++++++++++--------------
>  1 file changed, 17 insertions(+), 14 deletions(-)
> 
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -95,6 +95,8 @@ acpi_device_modalias_show(struct device
>  }
>  static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
>  
> +static void __acpi_bus_trim(struct acpi_device *start);
> +
>  /**
>   * acpi_bus_hot_remove_device: hot-remove a device and its children
>   * @context: struct acpi_eject_event pointer (freed in this func)
> @@ -114,10 +116,12 @@ void acpi_bus_hot_remove_device(void *co
>  	acpi_status status = AE_OK;
>  	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
>  
> +	mutex_lock(&acpi_scan_lock);
> +
>  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
>  		"Hot-removing device %s...\n", dev_name(&device->dev)));
>  
> -	acpi_bus_trim(device);
> +	__acpi_bus_trim(device);
>  	/* Device node has been released. */
>  	device = NULL;
>  
> @@ -146,18 +150,14 @@ void acpi_bus_hot_remove_device(void *co
>  	status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
>  	if (ACPI_FAILURE(status)) {
>  		if (status != AE_NOT_FOUND)
> -			printk(KERN_WARNING PREFIX
> -					"Eject device failed\n");
> -		goto err_out;
> -	}
> +			acpi_handle_warn(handle, "Eject failed\n");
>  
> -	kfree(context);
> -	return;
> +		/* Tell the firmware the hot-remove operation has failed. */
> +		acpi_evaluate_hotplug_ost(handle, ej_event->event,
> +					  ost_code, NULL);
> +	}
>  
> -err_out:
> -	/* Inform firmware the hot-remove operation has completed w/ error */
> -	(void) acpi_evaluate_hotplug_ost(handle,
> -				ej_event->event, ost_code, NULL);
> +	mutex_unlock(&acpi_scan_lock);
>  	kfree(context);
>  	return;
>  }
> @@ -1686,10 +1686,8 @@ static acpi_status acpi_bus_remove(acpi_
>  	return AE_OK;
>  }
>  
> -void acpi_bus_trim(struct acpi_device *start)
> +static void __acpi_bus_trim(struct acpi_device *start)
>  {
> -	mutex_lock(&acpi_scan_lock);
> -
>  	/*
>  	 * Execute acpi_bus_device_detach() as a post-order callback to detach
>  	 * all ACPI drivers from the device nodes being removed.
> @@ -1704,7 +1702,12 @@ void acpi_bus_trim(struct acpi_device *s
>  	acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
>  			    acpi_bus_remove, NULL, NULL);
>  	acpi_bus_remove(start->handle, 0, NULL, NULL);
> +}
>  
> +void acpi_bus_trim(struct acpi_device *start)
> +{
> +	mutex_lock(&acpi_scan_lock);
> +	__acpi_bus_trim(start);
>  	mutex_unlock(&acpi_scan_lock);
>  }
>  EXPORT_SYMBOL_GPL(acpi_bus_trim);
> 



^ permalink raw reply	[flat|nested] 71+ messages in thread

end of thread, other threads:[~2013-02-11 23:53 UTC | newest]

Thread overview: 71+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-24  0:26 [RFC] ACPI scan handlers Rafael J. Wysocki
2013-01-25 16:52 ` Toshi Kani
2013-01-25 22:11   ` Rafael J. Wysocki
2013-01-25 23:07     ` Toshi Kani
2013-01-26  1:49       ` Rafael J. Wysocki
2013-01-26 14:03         ` Rafael J. Wysocki
2013-01-26 18:42 ` Jiang Liu
2013-01-26 21:46   ` Rafael J. Wysocki
2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
2013-01-28 12:59   ` [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler Rafael J. Wysocki
2013-01-29  2:04     ` Yasuaki Ishimatsu
2013-01-29  2:29       ` Yasuaki Ishimatsu
2013-01-29  2:35     ` Toshi Kani
2013-01-29 11:28       ` Rafael J. Wysocki
2013-01-29 14:50         ` Toshi Kani
2013-01-29 21:32           ` Rafael J. Wysocki
2013-01-29 22:57             ` Toshi Kani
2013-01-29 23:19               ` Rafael J. Wysocki
2013-01-29 23:27                 ` Toshi Kani
2013-01-30 13:18                   ` Rafael J. Wysocki
2013-02-03  0:52                     ` [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers Rafael J. Wysocki
2013-02-03  4:54                       ` Yinghai Lu
2013-02-03 13:05                         ` Rafael J. Wysocki
2013-02-05 23:44                       ` Toshi Kani
2013-01-28 13:00   ` [PATCH 2/4] ACPI / PCI: Make PCI root driver use struct acpi_scan_handler Rafael J. Wysocki
2013-01-28 13:00   ` [PATCH 3/4] ACPI / PCI: Make PCI IRQ link " Rafael J. Wysocki
2013-01-28 13:01   ` [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices Rafael J. Wysocki
2013-01-29  2:20     ` Yasuaki Ishimatsu
2013-01-29 11:36       ` Rafael J. Wysocki
2013-01-29 12:30         ` [Update][PATCH " Rafael J. Wysocki
2013-01-29 23:51           ` Yasuaki Ishimatsu
2013-01-29  7:35     ` [PATCH " Mika Westerberg
2013-01-29 12:01       ` Rafael J. Wysocki
2013-01-29  8:05     ` Mika Westerberg
2013-01-29 12:02       ` Rafael J. Wysocki
2013-01-28 21:54   ` [PATCH 0/4] ACPI scan handlers Yinghai Lu
2013-01-29  0:38     ` Rafael J. Wysocki
2013-01-29  2:33   ` Toshi Kani
2013-01-30  1:58   ` Toshi Kani
2013-01-30 13:36     ` Rafael J. Wysocki
2013-02-03 23:45   ` [PATCH 0/2] ACPI scan handler for memory hotplug and container simplification Rafael J. Wysocki
2013-02-03 23:46     ` [PATCH 1/2] ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler Rafael J. Wysocki
2013-02-03 23:47     ` [PATCH 2/2] ACPI / scan: Simplify container driver Rafael J. Wysocki
2013-02-06 22:32       ` Toshi Kani
2013-02-07  0:55         ` Rafael J. Wysocki
2013-02-07  0:51           ` Toshi Kani
2013-02-07  1:32             ` Rafael J. Wysocki
2013-02-07 14:32               ` Toshi Kani
2013-02-07 22:42                 ` Rafael J. Wysocki
2013-02-08  1:05                   ` Toshi Kani
2013-02-08 12:52                     ` Rafael J. Wysocki
2013-02-08 16:24                       ` Toshi Kani
2013-02-07  8:32       ` Yasuaki Ishimatsu
2013-02-07 11:43         ` Rafael J. Wysocki
2013-02-07 14:38           ` Toshi Kani
2013-02-08  0:24       ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
2013-02-08  0:25         ` [PATCH 1/2] ACPI / scan: Remove useless #ifndef from acpi_eject_store() Rafael J. Wysocki
2013-02-08  0:27         ` [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler Rafael J. Wysocki
2013-02-08  3:32           ` Yinghai Lu
2013-02-08 12:45             ` Rafael J. Wysocki
2013-02-08  3:19         ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver Yasuaki Ishimatsu
2013-02-08 12:46           ` Rafael J. Wysocki
2013-02-08 16:57         ` Toshi Kani
2013-02-08 19:59           ` Rafael J. Wysocki
2013-02-08 22:41             ` Rafael J. Wysocki
2013-02-08 23:18               ` [PATCH] ACPI: Drop the container.h header file Rafael J. Wysocki
2013-02-08 23:27                 ` Toshi Kani
2013-02-09 14:26         ` [PATCH 0/2] ACPI / scan: Two fixes for device hot-removal Rafael J. Wysocki
2013-02-09 14:29           ` [PATCH 1/2] ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock Rafael J. Wysocki
2013-02-11 23:42             ` Toshi Kani
2013-02-09 14:31           ` [PATCH 2/2] ACPI / scan: Full transition to D3cold in acpi_device_unregister() Rafael J. Wysocki

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).