Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cb3e0c10 authored by Len Brown's avatar Len Brown
Browse files

Pull d-states into release branch



Conflicts:

	drivers/acpi/sleep/main.c

Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parents 1e1f3f24 50ad147a
Loading
Loading
Loading
Loading
+127 −33
Original line number Diff line number Diff line
@@ -34,35 +34,55 @@ static u32 acpi_suspend_states[] = {

static int init_8259A_after_S1;

extern int acpi_sleep_prepare(u32 acpi_state);
extern void acpi_power_off(void);

static u32 acpi_target_sleep_state = ACPI_STATE_S0;

/**
 *	acpi_pm_set_target - Set the target system sleep state to the state
 *		associated with given @pm_state, if supported.
 */

static int acpi_pm_set_target(suspend_state_t pm_state)
{
	u32 acpi_state = acpi_suspend_states[pm_state];
	int error = 0;

	if (sleep_states[acpi_state]) {
		acpi_target_sleep_state = acpi_state;
	} else {
		printk(KERN_ERR "ACPI does not support this state: %d\n",
			pm_state);
		error = -ENOSYS;
	}
	return error;
}

/**
 *	acpi_pm_prepare - Do preliminary suspend work.
 *	@pm_state:		suspend state we're entering.
 *	@pm_state: ignored
 *
 *	Make sure we support the state. If we do, and we need it, set the
 *	firmware waking vector and do arch-specific nastiness to get the 
 *	wakeup code to the waking vector. 
 *	If necessary, set the firmware waking vector and do arch-specific
 *	nastiness to get the wakeup code to the waking vector.
 */

extern int acpi_sleep_prepare(u32 acpi_state);
extern void acpi_power_off(void);

static int acpi_pm_prepare(suspend_state_t pm_state)
{
	u32 acpi_state = acpi_suspend_states[pm_state];
	int error = acpi_sleep_prepare(acpi_target_sleep_state);

	if (!sleep_states[acpi_state]) {
		printk("acpi_pm_prepare does not support %d \n", pm_state);
		return -EPERM;
	}
	return acpi_sleep_prepare(acpi_state);
	if (error)
		acpi_target_sleep_state = ACPI_STATE_S0;

	return error;
}

/**
 *	acpi_pm_enter - Actually enter a sleep state.
 *	@pm_state:		State we're entering.
 *	@pm_state: ignored
 *
 *	Flush caches and go to sleep. For STR or STD, we have to call 
 *	arch-specific assembly, which in turn call acpi_enter_sleep_state().
 *	Flush caches and go to sleep. For STR we have to call arch-specific
 *	assembly, which in turn call acpi_enter_sleep_state().
 *	It's unfortunate, but it works. Please fix if you're feeling frisky.
 */

@@ -70,31 +90,31 @@ static int acpi_pm_enter(suspend_state_t pm_state)
{
	acpi_status status = AE_OK;
	unsigned long flags = 0;
	u32 acpi_state = acpi_suspend_states[pm_state];
	u32 acpi_state = acpi_target_sleep_state;

	ACPI_FLUSH_CPU_CACHE();

	/* Do arch specific saving of state. */
	if (pm_state > PM_SUSPEND_STANDBY) {
	if (acpi_state == ACPI_STATE_S3) {
		int error = acpi_save_state_mem();
		if (error)

		if (error) {
			acpi_target_sleep_state = ACPI_STATE_S0;
			return error;
		}
	}

	local_irq_save(flags);
	acpi_enable_wakeup_device(acpi_state);
	switch (pm_state) {
	case PM_SUSPEND_STANDBY:
	switch (acpi_state) {
	case ACPI_STATE_S1:
		barrier();
		status = acpi_enter_sleep_state(acpi_state);
		break;

	case PM_SUSPEND_MEM:
	case ACPI_STATE_S3:
		do_suspend_lowlevel();
		break;

	default:
		return -EINVAL;
	}

	/* ACPI 3.0 specs (P62) says that it's the responsabilty
@@ -107,12 +127,8 @@ static int acpi_pm_enter(suspend_state_t pm_state)
	local_irq_restore(flags);
	printk(KERN_DEBUG "Back to C!\n");

	/* restore processor state
	 * We should only be here if we're coming back from STR or STD.
	 * And, in the case of the latter, the memory image should have already
	 * been loaded from disk.
	 */
	if (pm_state > PM_SUSPEND_STANDBY)
	/* restore processor state */
	if (acpi_state == ACPI_STATE_S3)
		acpi_restore_state_mem();

	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
@@ -120,7 +136,7 @@ static int acpi_pm_enter(suspend_state_t pm_state)

/**
 *	acpi_pm_finish - Finish up suspend sequence.
 *	@pm_state:		State we're coming out of.
 *	@pm_state: ignored
 *
 *	This is called after we wake back up (or if entering the sleep state
 *	failed). 
@@ -128,7 +144,7 @@ static int acpi_pm_enter(suspend_state_t pm_state)

static int acpi_pm_finish(suspend_state_t pm_state)
{
	u32 acpi_state = acpi_suspend_states[pm_state];
	u32 acpi_state = acpi_target_sleep_state;

	acpi_leave_sleep_state(acpi_state);
	acpi_disable_wakeup_device(acpi_state);
@@ -136,6 +152,8 @@ static int acpi_pm_finish(suspend_state_t pm_state)
	/* reset firmware waking vector */
	acpi_set_firmware_waking_vector((acpi_physical_address) 0);

	acpi_target_sleep_state = ACPI_STATE_S0;

#ifdef CONFIG_X86
	if (init_8259A_after_S1) {
		printk("Broken toshiba laptop -> kicking interrupts\n");
@@ -178,6 +196,7 @@ static int acpi_pm_state_valid(suspend_state_t pm_state)

static struct pm_ops acpi_pm_ops = {
	.valid = acpi_pm_state_valid,
	.set_target = acpi_pm_set_target,
	.prepare = acpi_pm_prepare,
	.enter = acpi_pm_enter,
	.finish = acpi_pm_finish,
@@ -237,6 +256,81 @@ static struct hibernation_ops acpi_hibernation_ops = {
};
#endif				/* CONFIG_SOFTWARE_SUSPEND */

/**
 *	acpi_pm_device_sleep_state - return preferred power state of ACPI device
 *		in the system sleep state given by %acpi_target_sleep_state
 *	@dev: device to examine
 *	@wake: if set, the device should be able to wake up the system
 *	@d_min_p: used to store the upper limit of allowed states range
 *	Return value: preferred power state of the device on success, -ENODEV on
 *		failure (ie. if there's no 'struct acpi_device' for @dev)
 *
 *	Find the lowest power (highest number) ACPI device power state that
 *	device @dev can be in while the system is in the sleep state represented
 *	by %acpi_target_sleep_state.  If @wake is nonzero, the device should be
 *	able to wake up the system from this sleep state.  If @d_min_p is set,
 *	the highest power (lowest number) device power state of @dev allowed
 *	in this system sleep state is stored at the location pointed to by it.
 *
 *	The caller must ensure that @dev is valid before using this function.
 *	The caller is also responsible for figuring out if the device is
 *	supposed to be able to wake up the system and passing this information
 *	via @wake.
 */

int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p)
{
	acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
	struct acpi_device *adev;
	char acpi_method[] = "_SxD";
	unsigned long d_min, d_max;

	if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
		printk(KERN_ERR "ACPI handle has no context!\n");
		return -ENODEV;
	}

	acpi_method[2] = '0' + acpi_target_sleep_state;
	/*
	 * If the sleep state is S0, we will return D3, but if the device has
	 * _S0W, we will use the value from _S0W
	 */
	d_min = ACPI_STATE_D0;
	d_max = ACPI_STATE_D3;

	/*
	 * If present, _SxD methods return the minimum D-state (highest power
	 * state) we can use for the corresponding S-states.  Otherwise, the
	 * minimum D-state is D0 (ACPI 3.x).
	 *
	 * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer
	 * provided -- that's our fault recovery, we ignore retval.
	 */
	if (acpi_target_sleep_state > ACPI_STATE_S0)
		acpi_evaluate_integer(handle, acpi_method, NULL, &d_min);

	/*
	 * If _PRW says we can wake up the system from the target sleep state,
	 * the D-state returned by _SxD is sufficient for that (we assume a
	 * wakeup-aware driver if wake is set).  Still, if _SxW exists
	 * (ACPI 3.x), it should return the maximum (lowest power) D-state that
	 * can wake the system.  _S0W may be valid, too.
	 */
	if (acpi_target_sleep_state == ACPI_STATE_S0 ||
	    (wake && adev->wakeup.state.enabled &&
	     adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
		acpi_method[3] = 'W';
		acpi_evaluate_integer(handle, acpi_method, NULL, &d_max);
		/* Sanity check */
		if (d_max < d_min)
			d_min = d_max;
	}

	if (d_min_p)
		*d_min_p = d_min;
	return d_max;
}

/*
 * Toshiba fails to preserve interrupts over S1, reinitialization
 * of 8259 is needed after S1 resume.
+24 −4
Original line number Diff line number Diff line
@@ -245,16 +245,33 @@ EXPORT_SYMBOL(pci_osc_control_set);
 * currently we simply return _SxD, if present.
 */

static int acpi_pci_choose_state(struct pci_dev *pdev, pm_message_t state)
static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev,
	pm_message_t state)
{
	/* TBD */

	return -ENODEV;
	int acpi_state;

	acpi_state = acpi_pm_device_sleep_state(&pdev->dev,
		device_may_wakeup(&pdev->dev), NULL);
	if (acpi_state < 0)
		return PCI_POWER_ERROR;

	switch (acpi_state) {
	case ACPI_STATE_D0:
		return PCI_D0;
	case ACPI_STATE_D1:
		return PCI_D1;
	case ACPI_STATE_D2:
		return PCI_D2;
	case ACPI_STATE_D3:
		return PCI_D3hot;
	}
	return PCI_POWER_ERROR;
}

static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
{
	acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
	acpi_handle tmp;
	static int state_conv[] = {
		[0] = 0,
		[1] = 1,
@@ -266,6 +283,9 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)

	if (!handle)
		return -ENODEV;
	/* If the ACPI device has _EJ0, ignore the device */
	if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
		return 0;
	return acpi_bus_set_power(handle, acpi_state);
}

+4 −4
Original line number Diff line number Diff line
@@ -499,7 +499,7 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
	return 0;
}

int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
 
/**
 * pci_choose_state - Choose the power state of a PCI device
@@ -513,15 +513,15 @@ int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);

pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
{
	int ret;
	pci_power_t ret;

	if (!pci_find_capability(dev, PCI_CAP_ID_PM))
		return PCI_D0;

	if (platform_pci_choose_state) {
		ret = platform_pci_choose_state(dev, state);
		if (ret >= 0)
			state.event = ret;
		if (ret != PCI_POWER_ERROR)
			return ret;
	}

	switch (state.event) {
+1 −1
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@ extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
					      resource_size_t, resource_size_t),
				  void *alignf_data);
/* Firmware callbacks */
extern int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);

extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
+5 −0
Original line number Diff line number Diff line
@@ -167,6 +167,8 @@ static int pnp_bus_suspend(struct device *dev, pm_message_t state)
	    		return error;
	}

	if (pnp_dev->protocol && pnp_dev->protocol->suspend)
		pnp_dev->protocol->suspend(pnp_dev, state);
	return 0;
}

@@ -179,6 +181,9 @@ static int pnp_bus_resume(struct device *dev)
	if (!pnp_drv)
		return 0;

	if (pnp_dev->protocol && pnp_dev->protocol->resume)
		pnp_dev->protocol->resume(pnp_dev);

	if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
		error = pnp_start_dev(pnp_dev);
		if (error)
Loading