/*
 *  pm.c - Power management interface
 *
 *  Copyright (C) 2000 Andrew Henroid
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/pm.h>
#include <linux/interrupt.h>

int pm_active;

/*
 *	Locking notes:
 *		pm_devs_lock can be a semaphore providing pm ops are not called
 *	from an interrupt handler (already a bad idea so no change here). Each
 *	change must be protected so that an unlink of an entry doesn't clash
 *	with a pm send - which is permitted to sleep in the current architecture
 *
 *	Module unloads clashing with pm events now work out safely, the module 
 *	unload path will block until the event has been sent. It may well block
 *	until a resume but that will be fine.
 */
 
static DECLARE_MUTEX(pm_devs_lock);
static LIST_HEAD(pm_devs);

/**
 *	pm_register - register a device with power management
 *	@type: device type 
 *	@id: device ID
 *	@callback: callback function
 *
 *	Add a device to the list of devices that wish to be notified about
 *	power management events. A &pm_dev structure is returned on success,
 *	on failure the return is %NULL.
 *
 *      The callback function will be called in process context and
 *      it may sleep.
 */
 
struct pm_dev *pm_register(pm_dev_t type,
			   unsigned long id,
			   pm_callback callback)
{
	struct pm_dev *dev = kmalloc(sizeof(struct pm_dev), GFP_KERNEL);
	if (dev) {
		memset(dev, 0, sizeof(*dev));
		dev->type = type;
		dev->id = id;
		dev->callback = callback;

		down(&pm_devs_lock);
		list_add(&dev->entry, &pm_devs);
		up(&pm_devs_lock);
	}
	return dev;
}

/**
 *	pm_unregister -  unregister a device with power management
 *	@dev: device to unregister
 *
 *	Remove a device from the power management notification lists. The
 *	dev passed must be a handle previously returned by pm_register.
 */
 
void pm_unregister(struct pm_dev *dev)
{
	if (dev) {
		down(&pm_devs_lock);
		list_del(&dev->entry);
		up(&pm_devs_lock);

		kfree(dev);
	}
}

static void __pm_unregister(struct pm_dev *dev)
{
	if (dev) {
		list_del(&dev->entry);
		kfree(dev);
	}
}

/**
 *	pm_unregister_all - unregister all devices with matching callback
 *	@callback: callback function pointer
 *
 *	Unregister every device that would call the callback passed. This
 *	is primarily meant as a helper function for loadable modules. It
 *	enables a module to give up all its managed devices without keeping
 *	its own private list.
 */
 
void pm_unregister_all(pm_callback callback)
{
	struct list_head *entry;

	if (!callback)
		return;

	down(&pm_devs_lock);
	entry = pm_devs.next;
	while (entry != &pm_devs) {
		struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
		entry = entry->next;
		if (dev->callback == callback)
			__pm_unregister(dev);
	}
	up(&pm_devs_lock);
}

/**
 *	pm_send - send request to a single device
 *	@dev: device to send to
 *	@rqst: power management request
 *	@data: data for the callback
 *
 *	Issue a power management request to a given device. The 
 *	%PM_SUSPEND and %PM_RESUME events are handled specially. The
 *	data field must hold the intended next state. No call is made
 *	if the state matches.
 *
 *	BUGS: what stops two power management requests occurring in parallel
 *	and conflicting.
 *
 *	WARNING: Calling pm_send directly is not generally recommended, in
 *	particular there is no locking against the pm_dev going away. The
 *	caller must maintain all needed locking or have 'inside knowledge'
 *	on the safety. Also remember that this function is not locked against
 *	pm_unregister. This means that you must handle SMP races on callback
 *	execution and unload yourself.
 */
 
static int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data)
{
	int status = 0;
	unsigned long prev_state, next_state;

	if (in_interrupt())
		BUG();

	switch (rqst) {
	case PM_SUSPEND:
	case PM_RESUME:
		prev_state = dev->state;
		next_state = (unsigned long) data;
		if (prev_state != next_state) {
			if (dev->callback)
				status = (*dev->callback)(dev, rqst, data);
			if (!status) {
				dev->state = next_state;
				dev->prev_state = prev_state;
			}
		}
		else {
			dev->prev_state = prev_state;
		}
		break;
	default:
		if (dev->callback)
			status = (*dev->callback)(dev, rqst, data);
		break;
	}
	return status;
}

/*
 * Undo incomplete request
 */
static void pm_undo_all(struct pm_dev *last)
{
	struct list_head *entry = last->entry.prev;
	while (entry != &pm_devs) {
		struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
		if (dev->state != dev->prev_state) {
			/* previous state was zero (running) resume or
			 * previous state was non-zero (suspended) suspend
			 */
			pm_request_t undo = (dev->prev_state
					     ? PM_SUSPEND:PM_RESUME);
			pm_send(dev, undo, (void*) dev->prev_state);
		}
		entry = entry->prev;
	}
}

/**
 *	pm_send_all - send request to all managed devices
 *	@rqst: power management request
 *	@data: data for the callback
 *
 *	Issue a power management request to a all devices. The 
 *	%PM_SUSPEND events are handled specially. Any device is 
 *	permitted to fail a suspend by returning a non zero (error)
 *	value from its callback function. If any device vetoes a 
 *	suspend request then all other devices that have suspended 
 *	during the processing of this request are restored to their
 *	previous state.
 *
 *	WARNING:  This function takes the pm_devs_lock. The lock is not dropped until
 *	the callbacks have completed. This prevents races against pm locking
 *	functions, races against module unload pm_unregister code. It does
 *	mean however that you must not issue pm_ functions within the callback
 *	or you will deadlock and users will hate you.
 *
 *	Zero is returned on success. If a suspend fails then the status
 *	from the device that vetoes the suspend is returned.
 *
 *	BUGS: what stops two power management requests occurring in parallel
 *	and conflicting.
 */
 
int pm_send_all(pm_request_t rqst, void *data)
{
	struct list_head *entry;
	
	down(&pm_devs_lock);
	entry = pm_devs.next;
	while (entry != &pm_devs) {
		struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
		if (dev->callback) {
			int status = pm_send(dev, rqst, data);
			if (status) {
				/* return devices to previous state on
				 * failed suspend request
				 */
				if (rqst == PM_SUSPEND)
					pm_undo_all(dev);
				up(&pm_devs_lock);
				return status;
			}
		}
		entry = entry->next;
	}
	up(&pm_devs_lock);
	return 0;
}

EXPORT_SYMBOL(pm_register);
EXPORT_SYMBOL(pm_unregister);
EXPORT_SYMBOL(pm_unregister_all);
EXPORT_SYMBOL(pm_send_all);
EXPORT_SYMBOL(pm_active);


