]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Pull bugfix into test branch
authorLen Brown <len.brown@intel.com>
Sat, 16 Dec 2006 06:01:18 +0000 (01:01 -0500)
committerLen Brown <len.brown@intel.com>
Sat, 16 Dec 2006 06:01:18 +0000 (01:01 -0500)
Conflicts:

kernel/power/disk.c

1  2 
drivers/acpi/dock.c
kernel/power/disk.c
kernel/power/main.c

diff --combined drivers/acpi/dock.c
index 215f5b30a1f1993f5fa2dab51be452d6e90b3e92,c7df2a1ea9d75e7787ec9cd244a41559ddda41f5..54ce12ab43d786680c275a3629de0227b1a13df1
@@@ -27,8 -27,6 +27,8 @@@
  #include <linux/init.h>
  #include <linux/types.h>
  #include <linux/notifier.h>
 +#include <linux/platform_device.h>
 +#include <linux/jiffies.h>
  #include <acpi/acpi_bus.h>
  #include <acpi/acpi_drivers.h>
  
@@@ -40,15 -38,13 +40,15 @@@ MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAM
  MODULE_LICENSE("GPL");
  
  static struct atomic_notifier_head dock_notifier_list;
 +static struct platform_device dock_device;
 +static char dock_device_name[] = "dock";
  
  struct dock_station {
        acpi_handle handle;
        unsigned long last_dock_time;
        u32 flags;
        spinlock_t dd_lock;
-       spinlock_t hp_lock;
+       struct mutex hp_lock;
        struct list_head dependent_devices;
        struct list_head hotplug_devices;
  };
@@@ -118,9 -114,9 +118,9 @@@ static voi
  dock_add_hotplug_device(struct dock_station *ds,
                        struct dock_dependent_device *dd)
  {
-       spin_lock(&ds->hp_lock);
+       mutex_lock(&ds->hp_lock);
        list_add_tail(&dd->hotplug_list, &ds->hotplug_devices);
-       spin_unlock(&ds->hp_lock);
+       mutex_unlock(&ds->hp_lock);
  }
  
  /**
@@@ -134,9 -130,9 +134,9 @@@ static voi
  dock_del_hotplug_device(struct dock_station *ds,
                        struct dock_dependent_device *dd)
  {
-       spin_lock(&ds->hp_lock);
+       mutex_lock(&ds->hp_lock);
        list_del(&dd->hotplug_list);
-       spin_unlock(&ds->hp_lock);
+       mutex_unlock(&ds->hp_lock);
  }
  
  /**
@@@ -299,7 -295,7 +299,7 @@@ static void hotplug_dock_devices(struc
  {
        struct dock_dependent_device *dd;
  
-       spin_lock(&ds->hp_lock);
+       mutex_lock(&ds->hp_lock);
  
        /*
         * First call driver specific hotplug functions
                else
                        dock_create_acpi_device(dd->handle);
        }
-       spin_unlock(&ds->hp_lock);
+       mutex_unlock(&ds->hp_lock);
  }
  
  static void dock_event(struct dock_station *ds, u32 event, int num)
  {
 +      struct device *dev = &dock_device.dev;
        /*
 -       * we don't do events until someone tells me that
 -       * they would like to have them.
 +       * Indicate that the status of the dock station has
 +       * changed.
         */
 +      kobject_uevent(&dev->kobj, KOBJ_CHANGE);
  }
  
  /**
@@@ -446,9 -440,6 +446,9 @@@ static int dock_in_progress(struct dock
   */
  int register_dock_notifier(struct notifier_block *nb)
  {
 +      if (!dock_station)
 +              return -ENODEV;
 +
        return atomic_notifier_chain_register(&dock_notifier_list, nb);
  }
  
@@@ -460,9 -451,6 +460,9 @@@ EXPORT_SYMBOL_GPL(register_dock_notifie
   */
  void unregister_dock_notifier(struct notifier_block *nb)
  {
 +      if (!dock_station)
 +              return;
 +
        atomic_notifier_chain_unregister(&dock_notifier_list, nb);
  }
  
@@@ -522,37 -510,6 +522,37 @@@ void unregister_hotplug_dock_device(acp
  
  EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
  
 +/**
 + * handle_eject_request - handle an undock request checking for error conditions
 + *
 + * Check to make sure the dock device is still present, then undock and
 + * hotremove all the devices that may need removing.
 + */
 +static int handle_eject_request(struct dock_station *ds, u32 event)
 +{
 +      if (!dock_present(ds))
 +              return -ENODEV;
 +
 +      if (dock_in_progress(ds))
 +              return -EBUSY;
 +
 +      /*
 +       * here we need to generate the undock
 +       * event prior to actually doing the undock
 +       * so that the device struct still exists.
 +       */
 +      dock_event(ds, event, UNDOCK_EVENT);
 +      hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
 +      undock(ds);
 +      eject_dock(ds);
 +      if (dock_present(ds)) {
 +              printk(KERN_ERR PREFIX "Unable to undock!\n");
 +              return -EBUSY;
 +      }
 +
 +      return 0;
 +}
 +
  /**
   * dock_notify - act upon an acpi dock notification
   * @handle: the dock station handle
   *
   * If we are notified to dock, then check to see if the dock is
   * present and then dock.  Notify all drivers of the dock event,
 - * and then hotplug and devices that may need hotplugging.  For undock
 - * check to make sure the dock device is still present, then undock
 - * and hotremove all the devices that may need removing.
 + * and then hotplug and devices that may need hotplugging.
   */
  static void dock_notify(acpi_handle handle, u32 event, void *data)
  {
         * to the driver who wish to hotplug.
           */
        case ACPI_NOTIFY_EJECT_REQUEST:
 -              if (!dock_in_progress(ds) && dock_present(ds)) {
 -                      /*
 -                       * here we need to generate the undock
 -                       * event prior to actually doing the undock
 -                       * so that the device struct still exists.
 -                       */
 -                      dock_event(ds, event, UNDOCK_EVENT);
 -                      hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
 -                      undock(ds);
 -                      eject_dock(ds);
 -                      if (dock_present(ds))
 -                              printk(KERN_ERR PREFIX "Unable to undock!\n");
 -              }
 +              handle_eject_request(ds, event);
                break;
        default:
                printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
@@@ -632,33 -603,6 +632,33 @@@ find_dock_devices(acpi_handle handle, u
        return AE_OK;
  }
  
 +/*
 + * show_docked - read method for "docked" file in sysfs
 + */
 +static ssize_t show_docked(struct device *dev,
 +                         struct device_attribute *attr, char *buf)
 +{
 +      return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
 +
 +}
 +DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
 +
 +/*
 + * write_undock - write method for "undock" file in sysfs
 + */
 +static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
 +                         const char *buf, size_t count)
 +{
 +      int ret;
 +
 +      if (!count)
 +              return -EINVAL;
 +
 +      ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
 +      return ret ? ret: count;
 +}
 +DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
 +
  /**
   * dock_add - add a new dock station
   * @handle: the dock station handle
@@@ -681,33 -625,9 +681,33 @@@ static int dock_add(acpi_handle handle
        INIT_LIST_HEAD(&dock_station->dependent_devices);
        INIT_LIST_HEAD(&dock_station->hotplug_devices);
        spin_lock_init(&dock_station->dd_lock);
-       spin_lock_init(&dock_station->hp_lock);
+       mutex_init(&dock_station->hp_lock);
        ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
  
 +      /* initialize platform device stuff */
 +      dock_device.name = dock_device_name;
 +      ret = platform_device_register(&dock_device);
 +      if (ret) {
 +              printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret);
 +              kfree(dock_station);
 +              return ret;
 +      }
 +      ret = device_create_file(&dock_device.dev, &dev_attr_docked);
 +      if (ret) {
 +              printk("Error %d adding sysfs file\n", ret);
 +              platform_device_unregister(&dock_device);
 +              kfree(dock_station);
 +              return ret;
 +      }
 +      ret = device_create_file(&dock_device.dev, &dev_attr_undock);
 +      if (ret) {
 +              printk("Error %d adding sysfs file\n", ret);
 +              device_remove_file(&dock_device.dev, &dev_attr_docked);
 +              platform_device_unregister(&dock_device);
 +              kfree(dock_station);
 +              return ret;
 +      }
 +
        /* Find dependent devices */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX, find_dock_devices, dock_station,
        dd = alloc_dock_dependent_device(handle);
        if (!dd) {
                kfree(dock_station);
 -              return -ENOMEM;
 +              ret = -ENOMEM;
 +              goto dock_add_err_unregister;
        }
        add_dock_dependent_device(dock_station, dd);
  
        return 0;
  
  dock_add_err:
 -      kfree(dock_station);
        kfree(dd);
 +dock_add_err_unregister:
 +      device_remove_file(&dock_device.dev, &dev_attr_docked);
 +      device_remove_file(&dock_device.dev, &dev_attr_undock);
 +      platform_device_unregister(&dock_device);
 +      kfree(dock_station);
        return ret;
  }
  
@@@ -770,11 -685,6 +770,11 @@@ static int dock_remove(void
        if (ACPI_FAILURE(status))
                printk(KERN_ERR "Error removing notify handler\n");
  
 +      /* cleanup sysfs */
 +      device_remove_file(&dock_device.dev, &dev_attr_docked);
 +      device_remove_file(&dock_device.dev, &dev_attr_undock);
 +      platform_device_unregister(&dock_device);
 +
        /* free dock station memory */
        kfree(dock_station);
        return 0;
@@@ -815,7 -725,7 +815,7 @@@ static int __init dock_init(void
                            ACPI_UINT32_MAX, find_dock, &num, NULL);
  
        if (!num)
 -              return -ENODEV;
 +              printk(KERN_INFO "No dock devices found.\n");
  
        return 0;
  }
diff --combined kernel/power/disk.c
index 0b00f56c2ad0ad369fdaa42d40e24c6f56720881,ae6bbc903b7d1993577375a7b7e77faf184c33a9..88fc5d7ac737402c18db0306049b5873effeed55
@@@ -20,7 -20,6 +20,7 @@@
  #include <linux/pm.h>
  #include <linux/console.h>
  #include <linux/cpu.h>
 +#include <linux/freezer.h>
  
  #include "power.h"
  
  static int noresume = 0;
  char resume_file[256] = CONFIG_PM_STD_PARTITION;
  dev_t swsusp_resume_device;
 +sector_t swsusp_resume_block;
 +
 +/**
 + *    platform_prepare - prepare the machine for hibernation using the
 + *    platform driver if so configured and return an error code if it fails
 + */
 +
 +static inline int platform_prepare(void)
 +{
 +      int error = 0;
 +
 +      if (pm_disk_mode == PM_DISK_PLATFORM) {
 +              if (pm_ops && pm_ops->prepare)
 +                      error = pm_ops->prepare(PM_SUSPEND_DISK);
 +      }
 +      return error;
 +}
  
  /**
   *    power_down - Shut machine down for hibernate.
  
  static void power_down(suspend_disk_method_t mode)
  {
 -      int error = 0;
 -
        switch(mode) {
        case PM_DISK_PLATFORM:
-               kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
-               pm_ops->enter(PM_SUSPEND_DISK);
-               break;
+               if (pm_ops && pm_ops->enter) {
+                       kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
 -                      error = pm_ops->enter(PM_SUSPEND_DISK);
++                      pm_ops->enter(PM_SUSPEND_DISK);
+                       break;
+               }
        case PM_DISK_SHUTDOWN:
                kernel_power_off();
                break;
@@@ -87,7 -73,7 +89,7 @@@ static inline void platform_finish(void
  
  static int prepare_processes(void)
  {
 -      int error;
 +      int error = 0;
  
        pm_prepare_console();
  
                goto thaw;
        }
  
 +      if (pm_disk_mode == PM_DISK_TESTPROC) {
 +              printk("swsusp debug: Waiting for 5 seconds.\n");
 +              mdelay(5000);
 +              goto thaw;
 +      }
 +
 +      error = platform_prepare();
 +      if (error)
 +              goto thaw;
 +
        /* Free memory before shutting down devices. */
        if (!(error = swsusp_shrink_memory()))
                return 0;
 -thaw:
 +
 +      platform_finish();
 + thaw:
        thaw_processes();
 -enable_cpus:
 + enable_cpus:
        enable_nonboot_cpus();
        pm_restore_console();
        return error;
@@@ -148,21 -122,13 +150,21 @@@ int pm_suspend_disk(void
        if (error)
                return error;
  
 +      if (pm_disk_mode == PM_DISK_TESTPROC)
 +              return 0;
 +
        suspend_console();
        error = device_suspend(PMSG_FREEZE);
        if (error) {
                resume_console();
                printk("Some devices failed to suspend\n");
 -              unprepare_processes();
 -              return error;
 +              goto Thaw;
 +      }
 +
 +      if (pm_disk_mode == PM_DISK_TEST) {
 +              printk("swsusp debug: Waiting for 5 seconds.\n");
 +              mdelay(5000);
 +              goto Done;
        }
  
        pr_debug("PM: snapshotting memory.\n");
                        power_down(pm_disk_mode);
                else {
                        swsusp_free();
 -                      unprepare_processes();
 -                      return error;
 +                      goto Thaw;
                }
 -      } else
 +      } else {
                pr_debug("PM: Image restored successfully.\n");
 +      }
  
        swsusp_free();
   Done:
        device_resume();
        resume_console();
 + Thaw:
        unprepare_processes();
        return error;
  }
@@@ -211,10 -176,10 +213,10 @@@ static int software_resume(void
  {
        int error;
  
 -      down(&pm_sem);
 +      mutex_lock(&pm_mutex);
        if (!swsusp_resume_device) {
                if (!strlen(resume_file)) {
 -                      up(&pm_sem);
 +                      mutex_unlock(&pm_mutex);
                        return -ENOENT;
                }
                swsusp_resume_device = name_to_dev_t(resume_file);
                 * FIXME: If noresume is specified, we need to find the partition
                 * and reset it back to normal swap space.
                 */
 -              up(&pm_sem);
 +              mutex_unlock(&pm_mutex);
                return 0;
        }
  
        unprepare_processes();
   Done:
        /* For success case, the suspend path will release the lock */
 -      up(&pm_sem);
 +      mutex_unlock(&pm_mutex);
        pr_debug("PM: Resume from disk failed.\n");
        return 0;
  }
@@@ -286,8 -251,6 +288,8 @@@ static const char * const pm_disk_modes
        [PM_DISK_PLATFORM]      = "platform",
        [PM_DISK_SHUTDOWN]      = "shutdown",
        [PM_DISK_REBOOT]        = "reboot",
 +      [PM_DISK_TEST]          = "test",
 +      [PM_DISK_TESTPROC]      = "testproc",
  };
  
  /**
@@@ -334,7 -297,7 +336,7 @@@ static ssize_t disk_store(struct subsys
        p = memchr(buf, '\n', n);
        len = p ? p - buf : n;
  
 -      down(&pm_sem);
 +      mutex_lock(&pm_mutex);
        for (i = PM_DISK_FIRMWARE; i < PM_DISK_MAX; i++) {
                if (!strncmp(buf, pm_disk_modes[i], len)) {
                        mode = i;
                }
        }
        if (mode) {
 -              if (mode == PM_DISK_SHUTDOWN || mode == PM_DISK_REBOOT)
 +              if (mode == PM_DISK_SHUTDOWN || mode == PM_DISK_REBOOT ||
 +                   mode == PM_DISK_TEST || mode == PM_DISK_TESTPROC) {
                        pm_disk_mode = mode;
 -              else {
 +              else {
                        if (pm_ops && pm_ops->enter &&
                            (mode == pm_ops->pm_disk_mode))
                                pm_disk_mode = mode;
                        else
                                error = -EINVAL;
                }
 -      } else
 +      } else {
                error = -EINVAL;
 +      }
  
        pr_debug("PM: suspend-to-disk mode set to '%s'\n",
                 pm_disk_modes[mode]);
 -      up(&pm_sem);
 +      mutex_unlock(&pm_mutex);
        return error ? error : n;
  }
  
@@@ -383,14 -344,14 +385,14 @@@ static ssize_t resume_store(struct subs
        if (maj != MAJOR(res) || min != MINOR(res))
                goto out;
  
 -      down(&pm_sem);
 +      mutex_lock(&pm_mutex);
        swsusp_resume_device = res;
 -      up(&pm_sem);
 +      mutex_unlock(&pm_mutex);
        printk("Attempting manual resume\n");
        noresume = 0;
        software_resume();
        ret = n;
 -out:
 + out:
        return ret;
  }
  
@@@ -445,19 -406,6 +447,19 @@@ static int __init resume_setup(char *st
        return 1;
  }
  
 +static int __init resume_offset_setup(char *str)
 +{
 +      unsigned long long offset;
 +
 +      if (noresume)
 +              return 1;
 +
 +      if (sscanf(str, "%llu", &offset) == 1)
 +              swsusp_resume_block = offset;
 +
 +      return 1;
 +}
 +
  static int __init noresume_setup(char *str)
  {
        noresume = 1;
  }
  
  __setup("noresume", noresume_setup);
 +__setup("resume_offset=", resume_offset_setup);
  __setup("resume=", resume_setup);
diff --combined kernel/power/main.c
index 500eb87f643dd9ff56d08079a29c506e7140b777,1210961a5aa7de09561fa06a33b6d7dd5846d3fe..ff3a6182f5f0df3fb479cbd56092dd0ee8e1ff2e
@@@ -8,7 -8,6 +8,7 @@@
   *
   */
  
 +#include <linux/module.h>
  #include <linux/suspend.h>
  #include <linux/kobject.h>
  #include <linux/string.h>
  #include <linux/console.h>
  #include <linux/cpu.h>
  #include <linux/resume-trace.h>
 +#include <linux/freezer.h>
  
  #include "power.h"
  
  /*This is just an arbitrary number */
  #define FREE_PAGE_NUMBER (100)
  
 -DECLARE_MUTEX(pm_sem);
 +DEFINE_MUTEX(pm_mutex);
  
  struct pm_ops *pm_ops;
- suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN;
+ suspend_disk_method_t pm_disk_mode = PM_DISK_PLATFORM;
  
  /**
   *    pm_set_ops - Set the global power method table. 
@@@ -38,9 -36,9 +38,9 @@@
  
  void pm_set_ops(struct pm_ops * ops)
  {
 -      down(&pm_sem);
 +      mutex_lock(&pm_mutex);
        pm_ops = ops;
 -      up(&pm_sem);
 +      mutex_unlock(&pm_mutex);
  }
  
  
@@@ -184,7 -182,7 +184,7 @@@ static int enter_state(suspend_state_t 
  
        if (!valid_state(state))
                return -ENODEV;
 -      if (down_trylock(&pm_sem))
 +      if (!mutex_trylock(&pm_mutex))
                return -EBUSY;
  
        if (state == PM_SUSPEND_DISK) {
        pr_debug("PM: Finishing wakeup.\n");
        suspend_finish(state);
   Unlock:
 -      up(&pm_sem);
 +      mutex_unlock(&pm_mutex);
        return error;
  }
  
@@@ -231,7 -229,7 +231,7 @@@ int pm_suspend(suspend_state_t state
        return -EINVAL;
  }
  
 -
 +EXPORT_SYMBOL(pm_suspend);
  
  decl_subsys(power,NULL,NULL);