shutdown.c 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /*
  2. * shutdown.c - power management functions for the device tree.
  3. *
  4. * Copyright (c) 2002-3 Patrick Mochel
  5. * 2002-3 Open Source Development Lab
  6. *
  7. * This file is released under the GPLv2
  8. *
  9. */
  10. #include <linux/config.h>
  11. #include <linux/device.h>
  12. #include <asm/semaphore.h>
  13. #include "power.h"
  14. #define to_dev(node) container_of(node, struct device, kobj.entry)
  15. extern struct subsystem devices_subsys;
  16. int device_detach_shutdown(struct device * dev)
  17. {
  18. if (!dev->detach_state)
  19. return 0;
  20. if (dev->detach_state == DEVICE_PM_OFF) {
  21. if (dev->driver && dev->driver->shutdown) {
  22. dev_dbg(dev, "shutdown\n");
  23. dev->driver->shutdown(dev);
  24. }
  25. return 0;
  26. }
  27. return dpm_runtime_suspend(dev, dev->detach_state);
  28. }
  29. /**
  30. * We handle system devices differently - we suspend and shut them
  31. * down last and resume them first. That way, we don't do anything stupid like
  32. * shutting down the interrupt controller before any devices..
  33. *
  34. * Note that there are not different stages for power management calls -
  35. * they only get one called once when interrupts are disabled.
  36. */
  37. extern int sysdev_shutdown(void);
  38. /**
  39. * device_shutdown - call ->shutdown() on each device to shutdown.
  40. */
  41. void device_shutdown(void)
  42. {
  43. struct device * dev;
  44. down_write(&devices_subsys.rwsem);
  45. list_for_each_entry_reverse(dev, &devices_subsys.kset.list,
  46. kobj.entry) {
  47. if (dev->driver && dev->driver->shutdown) {
  48. dev_dbg(dev, "shutdown\n");
  49. dev->driver->shutdown(dev);
  50. }
  51. }
  52. up_write(&devices_subsys.rwsem);
  53. sysdev_shutdown();
  54. }