Re: [PATCH] Fixups to ATA ACPI hotplug

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 20 May 2008 15:58:30 +0200
Holger Macht <hmacht@xxxxxxx> wrote:

> On Tue 20. May - 14:22:17, Matthew Garrett wrote:
> > On Tue, May 20, 2008 at 03:18:32PM +0200, Holger Macht wrote:
> > 
> > > +	if (kobj && !is_dock_event) {
> > > +		sprintf(event_string, "BAY_EVENT=%d", event);
> > > +		kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
> > 
> > I think we want to do the _EJ0 checking before this, otherwise we'll 
> > generate two uevents for the same removal on some hardware. Otherwise, 
> > looks good.
> 
> So once again:
> 
> Handle bay devices in dock stations
> 
> * Differentiate between bay devices in dock stations and others:
> 
>  - When an ACPI_NOTIFY_EJECT_REQUEST appears, just signal uevent to
>    userspace (that is when the optional eject button on a bay device is
>    pressed/pulled) giving the possibility to unmount file systems and to
>    clean up. Also, only send uevent in case we get an EJECT_REQUEST
>    without doing anything else. In other cases, you'll get an add/remove
>    event because libata attaches/detaches the device.
> 
>  - In case of a dock event, which in turn signals an
>    ACPI_NOTIFY_EJECT_REQUEST, immediately detach the device, because it
>    may already have been gone
> 
> * In case of an ACPI_NOTIFY_DEVICE/BUS_CHECK, evaluate _STA to check if
>   the device has been plugged or unplugged. If plugged, hotplug it, if
>   unplugged, just signal event to userspace
>   (initial patch by Matthew Garrett <mjg59@xxxxxxxxxxxxx>)
> 
> Signed-off-by: Holger Macht <hmacht@xxxxxxx>
> ---
> 
> --- linux-2.6.25/drivers/ata/libata-acpi.c.orig	2008-05-20 13:25:50.000000000 +0200
> +++ linux-2.6.25/drivers/ata/libata-acpi.c	2008-05-20 15:56:38.000000000 +0200
> @@ -118,8 +118,25 @@ static void ata_acpi_associate_ide_port(
>  		ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
>  }
>  
> +static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
> +{
> +	if (dev)
> +		dev->flags |= ATA_DFLAG_DETACH;
> +	else {
> +		struct ata_link *tlink;
> +		struct ata_device *tdev;
> +
> +		ata_port_for_each_link(tlink, ap)
> +			ata_link_for_each_dev(tdev, tlink)
> +			tdev->flags |= ATA_DFLAG_DETACH;

Looks odd.   I guess this:

--- a/drivers/ata/libata-acpi.c~ata-acpi-hotplug-handle-bay-devices-in-dock-stations-cleanup
+++ a/drivers/ata/libata-acpi.c
@@ -128,7 +128,7 @@ static void ata_acpi_detach_device(struc
 
 		ata_port_for_each_link(tlink, ap)
 			ata_link_for_each_dev(tdev, tlink)
-			tdev->flags |= ATA_DFLAG_DETACH;
+				tdev->flags |= ATA_DFLAG_DETACH;
 	}
 
 	ata_port_freeze(ap);
_

was intended.

> +	}
> +
> +	ata_port_freeze(ap);
> +	ata_port_schedule_eh(ap);
> +}
> +
>  static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device
> -				    *dev, u32 event)
> +				    *dev, u32 event, int is_dock_event)
>  {
>  	char event_string[12];
>  	char *envp[] = { event_string, NULL };
> @@ -135,83 +152,92 @@ static void ata_acpi_handle_hotplug(stru
>  		ap = dev->link->ap;
>  	ehi = &ap->link.eh_info;
>  
> -	spin_lock_irqsave(ap->lock, flags);
> -
> -	if (dev)
> +	if (dev) {
> +		if (dev->sdev)
> +			kobj = &dev->sdev->sdev_gendev.kobj;
>  		handle = dev->acpi_handle;
> -	else
> +	} else {
> +		kobj = &ap->dev->kobj;
>  		handle = ap->acpi_handle;
> +	}
>  
>  	status = acpi_get_handle(handle, "_EJ0", &tmphandle);
>  	if (ACPI_FAILURE(status)) {
> -		/* This device is not ejectable */
> -		spin_unlock_irqrestore(ap->lock, flags);
> +		/* This device does not support hotplug */
>  		return;
>  	}
>  
> -	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
> -	if (ACPI_FAILURE(status)) {
> -		printk ("Unable to determine bay status\n");
> -		spin_unlock_irqrestore(ap->lock, flags);
> -		return;
> +	if (kobj && !is_dock_event) {
> +		sprintf(event_string, "BAY_EVENT=%d", event);
> +		kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
>  	}
>  
> +	spin_lock_irqsave(ap->lock, flags);

Wow, lots of stuff happening under spinlock here, but it all looks OK to me.

>  	switch (event) {
>  	case ACPI_NOTIFY_BUS_CHECK:
>  	case ACPI_NOTIFY_DEVICE_CHECK:
>  		ata_ehi_push_desc(ehi, "ACPI event");
> -		if (!sta) {
> -                /* Device has been unplugged */
> -			if (dev)
> -				dev->flags |= ATA_DFLAG_DETACH;
> -			else {
> -				struct ata_link *tlink;
> -				struct ata_device *tdev;
> -
> -				ata_port_for_each_link(tlink, ap) {
> -					ata_link_for_each_dev(tdev, tlink) {
> -						tdev->flags |=
> -							ATA_DFLAG_DETACH;
> -					}
> -				}

The old code was less odd ;)


--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux