blob: 97979901c1496f077b6a3a355293086bc9b346c0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
11#include <linux/config.h>
12#include <linux/device.h>
13#include <asm/semaphore.h>
14
15#include "power.h"
16
17#define to_dev(node) container_of(node, struct device, kobj.entry)
18
19extern struct subsystem devices_subsys;
20
21
22int device_detach_shutdown(struct device * dev)
23{
24 if (!dev->detach_state)
25 return 0;
26
27 if (dev->detach_state == DEVICE_PM_OFF) {
David Brownell82428b62005-05-09 08:07:00 -070028 if (dev->driver && dev->driver->shutdown) {
29 dev_dbg(dev, "shutdown\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 dev->driver->shutdown(dev);
David Brownell82428b62005-05-09 08:07:00 -070031 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070032 return 0;
33 }
34 return dpm_runtime_suspend(dev, dev->detach_state);
35}
36
37
38/**
39 * We handle system devices differently - we suspend and shut them
40 * down last and resume them first. That way, we don't do anything stupid like
41 * shutting down the interrupt controller before any devices..
42 *
43 * Note that there are not different stages for power management calls -
44 * they only get one called once when interrupts are disabled.
45 */
46
47extern int sysdev_shutdown(void);
48
49/**
50 * device_shutdown - call ->shutdown() on each device to shutdown.
51 */
52void device_shutdown(void)
53{
54 struct device * dev;
55
56 down_write(&devices_subsys.rwsem);
David Brownell82428b62005-05-09 08:07:00 -070057 list_for_each_entry_reverse(dev, &devices_subsys.kset.list,
58 kobj.entry) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070059 if (dev->driver && dev->driver->shutdown) {
David Brownell82428b62005-05-09 08:07:00 -070060 dev_dbg(dev, "shutdown\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 dev->driver->shutdown(dev);
David Brownell82428b62005-05-09 08:07:00 -070062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 }
64 up_write(&devices_subsys.rwsem);
65
66 sysdev_shutdown();
67}
68