Re: [patch]change a spinlock to mutex

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

 



On Fri, Dec 19, 2008 at 06:03:10PM +0800, Len Brown wrote:
> Shaohua,
> 
> This one failed b/c it put a mutex into the irqs_disabled
> part of suspend:
Maybe just delete the lock in wakeup.c. It's not correct in theory, but
in theory it should be ok.

Thanks,
Shaohua

> ...
> CPU1 is down
> Extended CMOS year: 2000
> BUG: sleeping function called from invalid context at kernel/mutex.c:88
> in_atomic(): 0, irqs_disabled(): 1, pid: 3872, name: bash
> Pid: 3872, comm: bash Not tainted 2.6.28-rc9-09771-gbe5a7e4 #79
> Call Trace:
>  [<ffffffff8022c0e4>] __might_sleep+0xcf/0xd1
>  [<ffffffff80584a34>] mutex_lock+0x1d/0x33
>  [<ffffffff803b1f91>] acpi_enable_wakeup_device+0x19/0x9e
>  [<ffffffff803b253b>] acpi_suspend_enter+0x37/0xd2
>  [<ffffffff8025bedd>] suspend_devices_and_enter+0x120/0x1b3
>  [<ffffffff8025c199>] enter_state+0x200/0x290
>  [<ffffffff8025c2e0>] state_store+0xb7/0xd8
>  [<ffffffff80371b9b>] kobj_attr_store+0x17/0x19
>  [<ffffffff802d8c75>] sysfs_write_file+0xdf/0x114
>  [<ffffffff8029518d>] vfs_write+0xae/0x137
>  [<ffffffff802952da>] sys_write+0x47/0x70
>  [<ffffffff8020b3db>] system_call_fastpath+0x16/0x1b
> Back to C!
> 
> -- Len Brown, Intel Open Source Technology Center
> 
> 
> > On Tue, 9 Dec 2008, Shaohua Li wrote:
> >
> > > Change acpi_device_lock to a mutex to avoid race in wakeup device
> > > read/write. Found by Linus.
> > >
> > > Signed-off-by: Shaohua Li <shaohua.li@xxxxxxxxx>
> > > ---
> > >  drivers/acpi/scan.c         |   14 +++++++-------
> > >  drivers/acpi/sleep/proc.c   |   13 ++++---------
> > >  drivers/acpi/sleep/sleep.h  |    3 +++
> > >  drivers/acpi/sleep/wakeup.c |   31 ++++++++-----------------------
> > >  4 files changed, 22 insertions(+), 39 deletions(-)
> > >
> > > Index: linux/drivers/acpi/scan.c
> > > ===================================================================
> > > --- linux.orig/drivers/acpi/scan.c  2008-12-09 10:34:00.000000000 +0800
> > > +++ linux/drivers/acpi/scan.c       2008-12-09 10:36:07.000000000 +0800
> > > @@ -23,7 +23,7 @@ extern struct acpi_device *acpi_root;
> > >
> > >  static LIST_HEAD(acpi_device_list);
> > >  static LIST_HEAD(acpi_bus_id_list);
> > > -DEFINE_SPINLOCK(acpi_device_lock);
> > > +DEFINE_MUTEX(acpi_device_lock);
> > >  LIST_HEAD(acpi_wakeup_device_list);
> > >
> > >  struct acpi_device_bus_id{
> > > @@ -440,7 +440,7 @@ static int acpi_device_register(struct a
> > >             return -ENOMEM;
> > >     }
> > >
> > > -   spin_lock(&acpi_device_lock);
> > > +   mutex_lock(&acpi_device_lock);
> > >     /*
> > >      * Find suitable bus_id and instance number in acpi_bus_id_list
> > >      * If failed, create one and link it into acpi_bus_id_list
> > > @@ -468,7 +468,7 @@ static int acpi_device_register(struct a
> > >             list_add_tail(&device->g_list, &acpi_device_list);
> > >     if (device->wakeup.flags.valid)
> > >             list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
> > > -   spin_unlock(&acpi_device_lock);
> > > +   mutex_unlock(&acpi_device_lock);
> > >
> > >     if (device->parent)
> > >             device->dev.parent = &parent->dev;
> > > @@ -489,20 +489,20 @@ static int acpi_device_register(struct a
> > >     device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
> > >     return 0;
> > >    end:
> > > -   spin_lock(&acpi_device_lock);
> > > +   mutex_lock(&acpi_device_lock);
> > >     if (device->parent) {
> > >             list_del(&device->node);
> > >             list_del(&device->g_list);
> > >     } else
> > >             list_del(&device->g_list);
> > >     list_del(&device->wakeup_list);
> > > -   spin_unlock(&acpi_device_lock);
> > > +   mutex_unlock(&acpi_device_lock);
> > >     return result;
> > >  }
> > >
> > >  static void acpi_device_unregister(struct acpi_device *device, int type)
> > >  {
> > > -   spin_lock(&acpi_device_lock);
> > > +   mutex_lock(&acpi_device_lock);
> > >     if (device->parent) {
> > >             list_del(&device->node);
> > >             list_del(&device->g_list);
> > > @@ -510,7 +510,7 @@ static void acpi_device_unregister(struc
> > >             list_del(&device->g_list);
> > >
> > >     list_del(&device->wakeup_list);
> > > -   spin_unlock(&acpi_device_lock);
> > > +   mutex_unlock(&acpi_device_lock);
> > >
> > >     acpi_detach_data(device->handle, acpi_bus_data_handler);
> > >
> > > Index: linux/drivers/acpi/sleep/proc.c
> > > ===================================================================
> > > --- linux.orig/drivers/acpi/sleep/proc.c    2008-12-09 10:34:18.000000000 +0800
> > > +++ linux/drivers/acpi/sleep/proc.c 2008-12-09 10:40:10.000000000 +0800
> > > @@ -338,9 +338,6 @@ acpi_system_write_alarm(struct file *fil
> > >  }
> > >  #endif                             /* HAVE_ACPI_LEGACY_ALARM */
> > >
> > > -extern struct list_head acpi_wakeup_device_list;
> > > -extern spinlock_t acpi_device_lock;
> > > -
> > >  static int
> > >  acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
> > >  {
> > > @@ -348,7 +345,7 @@ acpi_system_wakeup_device_seq_show(struc
> > >
> > >     seq_printf(seq, "Device\tS-state\t  Status   Sysfs node\n");
> > >
> > > -   spin_lock(&acpi_device_lock);
> > > +   mutex_lock(&acpi_device_lock);
> > >     list_for_each_safe(node, next, &acpi_wakeup_device_list) {
> > >             struct acpi_device *dev =
> > >                 container_of(node, struct acpi_device, wakeup_list);
> > > @@ -356,7 +353,6 @@ acpi_system_wakeup_device_seq_show(struc
> > >
> > >             if (!dev->wakeup.flags.valid)
> > >                     continue;
> > > -           spin_unlock(&acpi_device_lock);
> > >
> > >             ldev = acpi_get_physical_device(dev->handle);
> > >             seq_printf(seq, "%s\t  S%d\t%c%-8s  ",
> > > @@ -371,9 +367,8 @@ acpi_system_wakeup_device_seq_show(struc
> > >             seq_printf(seq, "\n");
> > >             put_device(ldev);
> > >
> > > -           spin_lock(&acpi_device_lock);
> > >     }
> > > -   spin_unlock(&acpi_device_lock);
> > > +   mutex_unlock(&acpi_device_lock);
> > >     return 0;
> > >  }
> > >
> > > @@ -404,7 +399,7 @@ acpi_system_write_wakeup_device(struct f
> > >     strbuf[len] = '\0';
> > >     sscanf(strbuf, "%s", str);
> > >
> > > -   spin_lock(&acpi_device_lock);
> > > +   mutex_lock(&acpi_device_lock);
> > >     list_for_each_safe(node, next, &acpi_wakeup_device_list) {
> > >             struct acpi_device *dev =
> > >                 container_of(node, struct acpi_device, wakeup_list);
> > > @@ -441,7 +436,7 @@ acpi_system_write_wakeup_device(struct f
> > >                     }
> > >             }
> > >     }
> > > -   spin_unlock(&acpi_device_lock);
> > > +   mutex_unlock(&acpi_device_lock);
> > >     return count;
> > >  }
> > >
> > > Index: linux/drivers/acpi/sleep/sleep.h
> > > ===================================================================
> > > --- linux.orig/drivers/acpi/sleep/sleep.h   2008-12-09 10:37:22.000000000 +0800
> > > +++ linux/drivers/acpi/sleep/sleep.h        2008-12-09 10:37:50.000000000 +0800
> > > @@ -5,3 +5,6 @@ extern int acpi_suspend (u32 state);
> > >  extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
> > >  extern void acpi_enable_wakeup_device(u8 sleep_state);
> > >  extern void acpi_disable_wakeup_device(u8 sleep_state);
> > > +
> > > +extern struct list_head acpi_wakeup_device_list;
> > > +extern struct mutex acpi_device_lock;
> > > Index: linux/drivers/acpi/sleep/wakeup.c
> > > ===================================================================
> > > --- linux.orig/drivers/acpi/sleep/wakeup.c  2008-12-09 10:34:08.000000000 +0800
> > > +++ linux/drivers/acpi/sleep/wakeup.c       2008-12-09 10:39:18.000000000 +0800
> > > @@ -14,9 +14,6 @@
> > >  #define _COMPONENT         ACPI_SYSTEM_COMPONENT
> > >  ACPI_MODULE_NAME("wakeup_devices")
> > >
> > > -extern struct list_head acpi_wakeup_device_list;
> > > -extern spinlock_t acpi_device_lock;
> > > -
> > >  /**
> > >   * acpi_enable_wakeup_device_prep - prepare wakeup devices
> > >   * @sleep_state:   ACPI state
> > > @@ -30,7 +27,7 @@ void acpi_enable_wakeup_device_prep(u8 s
> > >
> > >     ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_prep");
> > >
> > > -   spin_lock(&acpi_device_lock);
> > > +   mutex_lock(&acpi_device_lock);
> > >     list_for_each_safe(node, next, &acpi_wakeup_device_list) {
> > >             struct acpi_device *dev = container_of(node,
> > >                                                    struct acpi_device,
> > > @@ -41,11 +38,9 @@ void acpi_enable_wakeup_device_prep(u8 s
> > >                 (sleep_state > (u32) dev->wakeup.sleep_state))
> > >                     continue;
> > >
> > > -           spin_unlock(&acpi_device_lock);
> > >             acpi_enable_wakeup_device_power(dev, sleep_state);
> > > -           spin_lock(&acpi_device_lock);
> > >     }
> > > -   spin_unlock(&acpi_device_lock);
> > > +   mutex_unlock(&acpi_device_lock);
> > >  }
> > >
> > >  /**
> > > @@ -62,7 +57,7 @@ void acpi_enable_wakeup_device(u8 sleep_
> > >      * Refer ACPI2.0: P212
> > >      */
> > >     ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
> > > -   spin_lock(&acpi_device_lock);
> > > +   mutex_lock(&acpi_device_lock);
> > >     list_for_each_safe(node, next, &acpi_wakeup_device_list) {
> > >             struct acpi_device *dev =
> > >                     container_of(node, struct acpi_device, wakeup_list);
> > > @@ -76,22 +71,18 @@ void acpi_enable_wakeup_device(u8 sleep_
> > >             if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
> > >                 || sleep_state > (u32) dev->wakeup.sleep_state) {
> > >                     if (dev->wakeup.flags.run_wake) {
> > > -                           spin_unlock(&acpi_device_lock);
> > >                             /* set_gpe_type will disable GPE, leave it like that */
> > >                             acpi_set_gpe_type(dev->wakeup.gpe_device,
> > >                                               dev->wakeup.gpe_number,
> > >                                               ACPI_GPE_TYPE_RUNTIME);
> > > -                           spin_lock(&acpi_device_lock);
> > >                     }
> > >                     continue;
> > >             }
> > > -           spin_unlock(&acpi_device_lock);
> > >             if (!dev->wakeup.flags.run_wake)
> > >                     acpi_enable_gpe(dev->wakeup.gpe_device,
> > >                                     dev->wakeup.gpe_number);
> > > -           spin_lock(&acpi_device_lock);
> > >     }
> > > -   spin_unlock(&acpi_device_lock);
> > > +   mutex_unlock(&acpi_device_lock);
> > >  }
> > >
> > >  /**
> > > @@ -105,7 +96,7 @@ void acpi_disable_wakeup_device(u8 sleep
> > >
> > >     ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device");
> > >
> > > -   spin_lock(&acpi_device_lock);
> > > +   mutex_lock(&acpi_device_lock);
> > >     list_for_each_safe(node, next, &acpi_wakeup_device_list) {
> > >             struct acpi_device *dev =
> > >                     container_of(node, struct acpi_device, wakeup_list);
> > > @@ -116,19 +107,16 @@ void acpi_disable_wakeup_device(u8 sleep
> > >             if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
> > >                 || sleep_state > (u32) dev->wakeup.sleep_state) {
> > >                     if (dev->wakeup.flags.run_wake) {
> > > -                           spin_unlock(&acpi_device_lock);
> > >                             acpi_set_gpe_type(dev->wakeup.gpe_device,
> > >                                               dev->wakeup.gpe_number,
> > >                                               ACPI_GPE_TYPE_WAKE_RUN);
> > >                             /* Re-enable it, since set_gpe_type will disable it */
> > >                             acpi_enable_gpe(dev->wakeup.gpe_device,
> > >                                             dev->wakeup.gpe_number);
> > > -                           spin_lock(&acpi_device_lock);
> > >                     }
> > >                     continue;
> > >             }
> > >
> > > -           spin_unlock(&acpi_device_lock);
> > >             acpi_disable_wakeup_device_power(dev);
> > >             /* Never disable run-wake GPE */
> > >             if (!dev->wakeup.flags.run_wake) {
> > > @@ -137,9 +125,8 @@ void acpi_disable_wakeup_device(u8 sleep
> > >                     acpi_clear_gpe(dev->wakeup.gpe_device,
> > >                                    dev->wakeup.gpe_number, ACPI_NOT_ISR);
> > >             }
> > > -           spin_lock(&acpi_device_lock);
> > >     }
> > > -   spin_unlock(&acpi_device_lock);
> > > +   mutex_unlock(&acpi_device_lock);
> > >  }
> > >
> > >  static int __init acpi_wakeup_device_init(void)
> > > @@ -149,7 +136,7 @@ static int __init acpi_wakeup_device_ini
> > >     if (acpi_disabled)
> > >             return 0;
> > >
> > > -   spin_lock(&acpi_device_lock);
> > > +   mutex_lock(&acpi_device_lock);
> > >     list_for_each_safe(node, next, &acpi_wakeup_device_list) {
> > >             struct acpi_device *dev = container_of(node,
> > >                                                    struct acpi_device,
> > > @@ -157,16 +144,14 @@ static int __init acpi_wakeup_device_ini
> > >             /* In case user doesn't load button driver */
> > >             if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled)
> > >                     continue;
> > > -           spin_unlock(&acpi_device_lock);
> > >             acpi_set_gpe_type(dev->wakeup.gpe_device,
> > >                               dev->wakeup.gpe_number,
> > >                               ACPI_GPE_TYPE_WAKE_RUN);
> > >             acpi_enable_gpe(dev->wakeup.gpe_device,
> > >                             dev->wakeup.gpe_number);
> > >             dev->wakeup.state.enabled = 1;
> > > -           spin_lock(&acpi_device_lock);
> > >     }
> > > -   spin_unlock(&acpi_device_lock);
> > > +   mutex_unlock(&acpi_device_lock);
> > >     return 0;
> > >  }
> > >
> > >
> > >
> > > --
> > > 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
> > >
> > --
> > 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
> >
> --
> 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
--
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