All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Cc: ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
	Bjorn Helgaas <bhelgaas@google.com>,
	LKML <linux-kernel@vger.kernel.org>,
	Yinghai Lu <yinghai@kernel.org>, Toshi Kani <toshi.kani@hp.com>,
	Jiang Liu <liuj97@gmail.com>
Subject: Re: [PATCH 2/7] ACPI / scan: Introduce common code for ACPI-based device hotplug
Date: Wed, 20 Feb 2013 14:23:44 +0100	[thread overview]
Message-ID: <2868646.oscSukR6ks@vostro.rjw.lan> (raw)
In-Reply-To: <51231EFC.5080006@jp.fujitsu.com>

On Tuesday, February 19, 2013 03:43:08 PM Yasuaki Ishimatsu wrote:
> Hi Rafael,
> 
> I have comments. Please see below.
> 
> 2013/02/18 0:21, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Multiple drivers handling hotplug-capable ACPI device nodes install
> > notify handlers covering the same types of events in a very similar
> > way.  Moreover, those handlers are installed in separate namespace
> > walks, although that really should be done during namespace scans
> > carried out by acpi_bus_scan().  This leads to substantial code
> > duplication, unnecessary overhead and behavior that is hard to
> > follow.
> >
> > For this reason, introduce common code in drivers/acpi/scan.c for
> > handling hotplug-related notification and carrying out device
> > insertion and eject operations in a generic fashion, such that it
> > may be used by all of the relevant drivers in the future.  To cover
> > the existing differences between those drivers introduce struct
> > acpi_hotplug_profile for representing collections of hotplug
> > settings associated with different ACPI scan handlers that can be
> > used by the drivers to make the common code reflect their current
> > behavior.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >   drivers/acpi/scan.c     |  271 +++++++++++++++++++++++++++++++++++++-----------
> >   include/acpi/acpi_bus.h |    7 +
> >   2 files changed, 220 insertions(+), 58 deletions(-)
> >
> > Index: test/include/acpi/acpi_bus.h
> > ===================================================================
> > --- test.orig/include/acpi/acpi_bus.h
> > +++ test/include/acpi/acpi_bus.h
> > @@ -88,11 +88,18 @@ struct acpi_device;
> >    * -----------------
> >    */
> >
> > +struct acpi_hotplug_profile {
> > +	bool enabled:1;
> > +	bool uevents:1;
> > +	bool autoeject:1;
> > +};
> > +
> >   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);
> > +	struct acpi_hotplug_profile hotplug;
> >   };
> >
> >   /*
> > Index: test/drivers/acpi/scan.c
> > ===================================================================
> > --- test.orig/drivers/acpi/scan.c
> > +++ test/drivers/acpi/scan.c
> > @@ -107,32 +107,19 @@ acpi_device_modalias_show(struct device
> >   }
> >   static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
> >
> > -/**
> > - * acpi_bus_hot_remove_device: hot-remove a device and its children
> > - * @context: struct acpi_eject_event pointer (freed in this func)
> > - *
> > - * Hot-remove a device and its children. This function frees up the
> > - * memory space passed by arg context, so that the caller may call
> > - * this function asynchronously through acpi_os_hotplug_execute().
> > - */
> > -void acpi_bus_hot_remove_device(void *context)
> > +static int acpi_scan_hot_remove(struct acpi_device *device)
> >   {
> > -	struct acpi_eject_event *ej_event = context;
> > -	struct acpi_device *device = ej_event->device;
> >   	acpi_handle handle = device->handle;
> > -	acpi_handle temp;
> > +	acpi_handle not_used;
> >   	struct acpi_object_list arg_list;
> >   	union acpi_object arg;
> > -	acpi_status status = AE_OK;
> > -	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
> > -
> > -	mutex_lock(&acpi_scan_lock);
> > +	acpi_status status;
> >
> >   	/* If there is no handle, the device node has been unregistered. */
> > -	if (!device->handle) {
> > +	if (!handle) {
> >   		dev_dbg(&device->dev, "ACPI handle missing\n");
> >   		put_device(&device->dev);
> > -		goto out;
> > +		return -EINVAL;
> >   	}
> >
> >   	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
> > @@ -143,7 +130,7 @@ void acpi_bus_hot_remove_device(void *co
> >   	put_device(&device->dev);
> >   	device = NULL;
> >
> > -	if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) {
> > +	if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &not_used))) {
> >   		arg_list.count = 1;
> >   		arg_list.pointer = &arg;
> >   		arg.type = ACPI_TYPE_INTEGER;
> > @@ -161,18 +148,162 @@ 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)
> > +		if (status == AE_NOT_FOUND) {
> > +			return -ENODEV;
> > +		} else {
> >   			acpi_handle_warn(handle, "Eject failed\n");
> > +			return -EIO;
> > +		}
> > +	}
> > +	return 0;
> > +}
> > +
> > +static void acpi_bus_device_eject(void *context)
> > +{
> > +	acpi_handle handle = context;
> > +	struct acpi_device *device = NULL;
> > +	struct acpi_scan_handler *handler;
> > +	u32 ost_source = ACPI_NOTIFY_EJECT_REQUEST;
> > +	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
> > +
> > +	mutex_lock(&acpi_scan_lock);
> >
> > -		/* Tell the firmware the hot-remove operation has failed. */
> > -		acpi_evaluate_hotplug_ost(handle, ej_event->event,
> > -					  ost_code, NULL);
> > +	acpi_bus_get_device(handle, &device);
> > +	if (!device)
> > +		goto out;
> > +
> > +	handler = device->handler;
> > +	if (!handler || !handler->hotplug.enabled) {
> > +		ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
> > +		goto out;
> >   	}
> > +	acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
> > +				  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
> 
> > +	if (handler->hotplug.uevents)
> > +		kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
> > +
> > +	if (handler->hotplug.autoeject) {
> > +		int error;
> > +
> > +		ost_source = ACPI_OST_EC_OSPM_EJECT;
> > +		get_device(&device->dev);
> > +		error = acpi_scan_hot_remove(device);
> > +		if (!error)
> > +			ost_code = ACPI_OST_SC_SUCCESS;
> > +	} else {
> > +		device->flags.eject_pending = true;
> > +		goto out_unlock;
> > +	}
> 
> I want you to change the order of uevents and autoeject.
> When user caught OFFLINE event, user thinks devices were removed.
> But it is not guaranteed in this code since acpi_scan_hot_remove() may
> be running.

Sure, I can do that.

> > +
> > + out:
> > +	acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL);
> > +
> > + out_unlock:
> > +	mutex_unlock(&acpi_scan_lock);
> > +}
> > +
> > +static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
> > +{
> > +	struct acpi_device *device = NULL;
> > +	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
> > +	int error;
> > +
> > +	mutex_lock(&acpi_scan_lock);
> > +
> > +	acpi_bus_get_device(handle, &device);
> > +	if (device) {
> > +		dev_warn(&device->dev, "Attempt to re-insert\n");
> > +		goto out;
> > +	}
> > +	acpi_evaluate_hotplug_ost(handle, ost_source,
> > +				  ACPI_OST_SC_INSERT_IN_PROGRESS, NULL);
> > +	ost_source = ACPI_OST_EC_OSPM_INSERTION;
> > +	error = acpi_bus_scan(handle);
> > +	if (error) {
> > +		acpi_handle_warn(handle, "Namespace scan failure\n");
> > +		goto out;
> > +	}
> > +	error = acpi_bus_get_device(handle, &device);
> > +	if (error) {
> > +		acpi_handle_warn(handle, "Missing device node object\n");
> > +		goto out;
> > +	}
> > +	ost_code = ACPI_OST_SC_SUCCESS;
> > +	if (device->handler && device->handler->hotplug.uevents)
> > +		kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
> >
> >    out:
> > +	acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL);
> > +	mutex_unlock(&acpi_scan_lock);
> > +}
> > +
> > +static void acpi_scan_bus_check(void *context)
> > +{
> > +	acpi_scan_bus_device_check((acpi_handle)context,
> > +				   ACPI_NOTIFY_BUS_CHECK);
> > +}
> > +
> > +static void acpi_scan_device_check(void *context)
> > +{
> > +	acpi_scan_bus_device_check((acpi_handle)context,
> > +				   ACPI_NOTIFY_DEVICE_CHECK);
> > +}
> > +
> > +static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *not_used)
> > +{
> > +	acpi_osd_exec_callback callback;
> > +	acpi_status status;
> > +
> > +	switch (type) {
> > +	case ACPI_NOTIFY_BUS_CHECK:
> > +		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
> > +		callback = acpi_scan_bus_check;
> > +		break;
> > +	case ACPI_NOTIFY_DEVICE_CHECK:
> > +		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
> > +		callback = acpi_scan_device_check;
> > +		break;
> > +	case ACPI_NOTIFY_EJECT_REQUEST:
> > +		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
> > +		callback = acpi_bus_device_eject;
> > +		break;
> > +	default:
> > +		/* non-hotplug event; possibly handled by other handler */
> > +		return;
> > +	}
> > +	status = acpi_os_hotplug_execute(callback, handle);
> > +	if (ACPI_FAILURE(status))
> > +		acpi_evaluate_hotplug_ost(handle, type,
> > +					  ACPI_OST_SC_NON_SPECIFIC_FAILURE,
> > +					  NULL);
> > +}
> > +
> > +/**
> > + * acpi_bus_hot_remove_device: hot-remove a device and its children
> > + * @context: struct acpi_eject_event pointer (freed in this func)
> > + *
> > + * Hot-remove a device and its children. This function frees up the
> > + * memory space passed by arg context, so that the caller may call
> > + * this function asynchronously through acpi_os_hotplug_execute().
> > + */
> > +void acpi_bus_hot_remove_device(void *context)
> > +{
> > +	struct acpi_eject_event *ej_event = context;
> > +	struct acpi_device *device = ej_event->device;
> > +	acpi_handle handle = device->handle;
> > +	u32 ost_code = ACPI_OST_SC_SUCCESS;
> > +	int error;
> > +
> > +	mutex_lock(&acpi_scan_lock);
> > +
> > +	error = acpi_scan_hot_remove(device);
> > +	if (error)
> > +		ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
> > +
> > +	acpi_evaluate_hotplug_ost(handle, ej_event->event, ost_code, NULL);
> > +
> >   	mutex_unlock(&acpi_scan_lock);
> >   	kfree(context);
> > -	return;
> >   }
> >   EXPORT_SYMBOL(acpi_bus_hot_remove_device);
> >
> > @@ -206,50 +337,48 @@ static ssize_t
> >   acpi_eject_store(struct device *d, struct device_attribute *attr,
> >   		const char *buf, size_t count)
> >   {
> > -	int ret = count;
> > -	acpi_status status;
> > -	acpi_object_type type = 0;
> >   	struct acpi_device *acpi_device = to_acpi_device(d);
> > -	struct acpi_eject_event *ej_event;
> > +	acpi_object_type not_used;
> > +	acpi_status status;
> > +	u32 ost_source;
> > +	u32 ost_code;
> > +	int ret;
> >
> > -	if ((!count) || (buf[0] != '1')) {
> > +	if (!count || buf[0] != '1')
> >   		return -EINVAL;
> > -	}
> > -	if (!acpi_device->driver && !acpi_device->handler) {
> > -		ret = -ENODEV;
> > -		goto err;
> > -	}
> > -	status = acpi_get_type(acpi_device->handle, &type);
> > -	if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) {
> > -		ret = -ENODEV;
> > -		goto err;
> > -	}
> >
> > -	ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
> > -	if (!ej_event) {
> > -		ret = -ENOMEM;
> > -		goto err;
> > -	}
> > +	if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)
> > +	    && !acpi_device->driver)
> > +		return -ENODEV;
> > +
> > +	status = acpi_get_type(acpi_device->handle, &not_used);
> > +	if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
> > +		return -ENODEV;
> > +
> > +	mutex_lock(&acpi_scan_lock);
> >
> > -	get_device(&acpi_device->dev);
> > -	ej_event->device = acpi_device;
> >   	if (acpi_device->flags.eject_pending) {
> > -		/* event originated from ACPI eject notification */
> > -		ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
> > +		/* ACPI eject notification event. */
> > +		ost_source = ACPI_NOTIFY_EJECT_REQUEST;
> >   		acpi_device->flags.eject_pending = 0;
> >   	} else {
> > -		/* event originated from user */
> > -		ej_event->event = ACPI_OST_EC_OSPM_EJECT;
> > -		(void) acpi_evaluate_hotplug_ost(acpi_device->handle,
> > -			ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
> > +		/* Eject initiated by user space. */
> > +		ost_source = ACPI_OST_EC_OSPM_EJECT;
> >   	}
> > -
> 
> > -	status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
> > -	if (ACPI_FAILURE(status)) {
> > -		put_device(&acpi_device->dev);
> > -		kfree(ej_event);
> > +	acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source,
> > +				  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
> > +	get_device(&acpi_device->dev);
> > +	ret = acpi_scan_hot_remove(acpi_device);
> 
> Why don't you use acpi_os_hotplug_execute()? Do you have some reason?

Yes, I do.  acpi_eject_store() is run in a separate thread anyway (started by
user space), so there's no need to use the workqueue for delayed execution here
and we are under acpi_scan_lock anyway, so there shouldn't be any concurrency
issues.

Thanks,
Rafael


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

  parent reply	other threads:[~2013-02-20 13:17 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-17 15:18 [PATCH 0/7] ACPI / hotplug: Common code for ACPI-based hotplug Rafael J. Wysocki
2013-02-17 15:20 ` [PATCH 1/7] ACPI / scan: Introduce acpi_scan_match_handler() Rafael J. Wysocki
2013-02-19  6:48   ` Yasuaki Ishimatsu
2013-02-17 15:21 ` [PATCH 2/7] ACPI / scan: Introduce common code for ACPI-based device hotplug Rafael J. Wysocki
2013-02-19  6:43   ` Yasuaki Ishimatsu
2013-02-19  7:10     ` Yasuaki Ishimatsu
2013-02-20 13:27       ` Rafael J. Wysocki
2013-02-20 13:23     ` Rafael J. Wysocki [this message]
2013-02-20 20:23       ` Toshi Kani
2013-02-20 21:17         ` Rafael J. Wysocki
2013-02-20 22:49   ` [Update][PATCH " Rafael J. Wysocki
2013-02-21  1:17     ` Toshi Kani
2013-02-21 15:44       ` Rafael J. Wysocki
2013-02-21 15:52     ` [Update 2][PATCH " Rafael J. Wysocki
2013-02-21 17:39       ` Toshi Kani
2013-02-21 22:57         ` Rafael J. Wysocki
2013-02-21 23:06       ` [Update 3][PATCH " Rafael J. Wysocki
2013-02-22  1:12         ` Toshi Kani
2013-02-22  1:50           ` Rafael J. Wysocki
2013-02-22  8:51             ` Yasuaki Ishimatsu
2013-02-22 12:37               ` Rafael J. Wysocki
2013-02-22 15:54                 ` Toshi Kani
2013-02-22 20:59                   ` Rafael J. Wysocki
2013-02-23 22:38         ` [Update 4][PATCH " Rafael J. Wysocki
2013-02-25 18:07           ` Toshi Kani
2013-02-25 23:39             ` Rafael J. Wysocki
2013-02-25 23:32               ` Toshi Kani
2013-02-26  0:40               ` Yasuaki Ishimatsu
2013-02-26  1:09                 ` Toshi Kani
2013-02-26  2:02                   ` Yasuaki Ishimatsu
2013-02-26  3:11                     ` Rafael J. Wysocki
2013-02-26  3:40                       ` Yasuaki Ishimatsu
2013-02-26  3:50                         ` Rafael J. Wysocki
2013-03-04 13:10               ` Vasilis Liaskovitis
2013-03-14 17:16                 ` Rafael J. Wysocki
2013-03-15 10:47                   ` Vasilis Liaskovitis
2013-03-25 20:45                     ` Toshi Kani
2013-03-25 22:29                       ` Rafael J. Wysocki
2013-03-25 22:57                         ` Toshi Kani
2013-03-26 12:22                           ` Rafael J. Wysocki
2013-03-26 20:10                             ` Toshi Kani
2013-02-17 15:22 ` [PATCH 3/7] ACPI / container: Use common hotplug code Rafael J. Wysocki
2013-02-17 15:23 ` [PATCH 4/7] ACPI / scan: Introduce acpi_scan_handler_matching() Rafael J. Wysocki
2013-02-19  8:05   ` Yasuaki Ishimatsu
2013-02-17 15:24 ` [PATCH 5/7] ACPI / hotplug: Introduce user space interface for hotplug profiles Rafael J. Wysocki
2013-02-25 18:13   ` Toshi Kani
2013-02-25 23:25     ` Rafael J. Wysocki
2013-02-17 15:25 ` [PATCH 6/7] ACPI / container: Use hotplug profile user space interface Rafael J. Wysocki
2013-02-17 15:27 ` [PATCH 7/7] ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler Rafael J. Wysocki
2013-02-19 18:11   ` Vasilis Liaskovitis
2013-02-20  3:35     ` Yasuaki Ishimatsu
2013-02-20 10:42       ` Vasilis Liaskovitis
2013-02-20 21:50         ` Toshi Kani
2013-02-20 22:29           ` Rafael J. Wysocki
2013-02-20 22:39             ` Toshi Kani
2013-02-21  6:58         ` Yasuaki Ishimatsu
2013-02-26 22:41 ` [PATCH v2, 0/7] ACPI / hotplug: Common code for ACPI-based hotplug Rafael J. Wysocki
2013-02-26 22:44   ` [PATCH v2, 1/7] ACPI / scan: Introduce acpi_scan_match_handler() Rafael J. Wysocki
2013-02-26 22:46   ` [PATCH v2, 2/7] ACPI / scan: Introduce common code for ACPI-based device hotplug Rafael J. Wysocki
2013-02-26 22:46   ` [PATCH v2, 3/7] ACPI / container: Use common hotplug code Rafael J. Wysocki
2013-02-26 23:13     ` Toshi Kani
2013-02-26 23:13       ` Toshi Kani
2013-02-27  0:06       ` Rafael J. Wysocki
2013-02-27  0:09     ` [Update][PATCH " Rafael J. Wysocki
2013-02-26 22:47   ` [PATCH v2, 4/7] ACPI / scan: Introduce acpi_scan_handler_matching() Rafael J. Wysocki
2013-02-26 22:48   ` [PATCH v2, 5/7] ACPI / hotplug: Introduce user space interface for hotplug profiles Rafael J. Wysocki
2013-02-26 22:49   ` [PATCH v2, 6/7] ACPI / container: Use hotplug profile user space interface Rafael J. Wysocki
2013-02-26 22:50   ` [PATCH v2, 7/7] ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler Rafael J. Wysocki
2013-02-27  0:51   ` [PATCH v2, 0/7] ACPI / hotplug: Common code for ACPI-based hotplug Toshi Kani

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=2868646.oscSukR6ks@vostro.rjw.lan \
    --to=rjw@sisk.pl \
    --cc=bhelgaas@google.com \
    --cc=isimatu.yasuaki@jp.fujitsu.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liuj97@gmail.com \
    --cc=toshi.kani@hp.com \
    --cc=yinghai@kernel.org \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.