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

Commit b67db9d5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull ACPI and power management fixes from Rafael Wysocki:
 "These are a few regression fixes for ACPI device enumeration and
  resources management, intel_pstate and cpufreq, a revert of an ACPI
  commit removing user space interfaces in /proc that we incorrectly
  thought were not used any more, fixes for some long-standing
  concurrency issues in the ACPI EC driver, two ACPI battery driver
  fixes, stable-candidate fixes for intel_pstate, an ACPI-related fix
  for i915 and two new ACPI video blacklist entries for Win8-oriented
  BIOSes.

  Specifics:

   - Missing device ID for ACPI enumeration of PNP devices that we
     overlooked during the recent rework of that code from Zhang Rui.

   - Fix for a problem introduced during the 3.14 cycle in the ACPI
     device resources management code and causing it to reject all
     resources of length 0 although some of them are actually valid
     which affects serial ports detection on a number of systems.  From
     Andy Whitcroft.

   - intel_pstate fix for a boot problem on some BayTrail-based systems
     introduced by a previous fix related to that platform during the
     3.13 cycle from Dirk Brandewie.

   - Revert of a 3.13 commit that removed the ACPI AC /proc interface
     which turns out to be still needed by some old utilities
     (kpowersave from kde 3.5.10 in particular) from Lan Tianyu.

   - cpufreq build fix for the davinci ARM platform from Prabhakar Lad
     (the breakage was introduced during the 3.10 cycle).

   - ACPI-related i915 fix preventing firmware on some Thinkpad laptops
     from setting backlight levels incorrectly during AC plug/unplug.
     From Aaron Lu.

   - Fixes for two nasty race conditions in the ACPI embedded controller
     driver that may be responsible for a number of past bug reports
     related to the EC from Lv Zhang and a fix for two memory leaks in
     error code paths in that driver from Colin Ian King.

   - Fixes for a couple of corner-case issues in the intel_pstate driver
     (all candidates for -stable) from Dirk Brandewie and Vincent Minet.

   - Fixes for two corner-case issues in the ACPI battery driver from
     Josef Gajdusek and Lan Tianyu.

   - Two new ACPI video blacklist entries for Acer TravelMate B113 and
     Dell Inspiron 5737 from Edward Lin and Martin Kepplinger"

* tag 'pm+acpi-3.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI / PNP: add soc_button_array device ID to PNP IDs list
  cpufreq: Makefile: fix compilation for davinci platform
  ACPI / video: Add Acer TravelMate B113 to native backlight blacklist
  ACPI / video: Add Dell Inspiron 5737 to the blacklist
  ACPI / i915: ignore firmware requests for backlight change
  ACPI / battery: fix wrong value of capacity_now reported when fully charged
  ACPI / resources: only reject zero length resources based at address zero
  ACPI / battery: Retry to get battery information if failed during probing
  ACPI / EC: Free saved_ec on error exit path
  ACPI / EC: Add detailed fields debugging support of EC_SC(R).
  ACPI / EC: Update revision due to recent changes
  ACPI / EC: Fix race condition in ec_transaction_completed()
  ACPI / EC: Remove duplicated ec_wait_ibf0() waiter
  ACPI / EC: Add asynchronous command byte write support
  ACPI / EC: Avoid race condition related to advance_transaction()
  intel_pstate: Set CPU number before accessing MSRs
  intel_pstate: Update documentation of {max,min}_perf_pct sysfs files
  intel_pstate: don't touch turbo bit if turbo disabled or unavailable.
  intel_pstate: Fix setting VID
  Revert "ACPI / AC: Remove AC's proc directory."
parents 4c718423 20910442
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -15,10 +15,13 @@ New sysfs files for controlling P state selection have been added to
/sys/devices/system/cpu/intel_pstate/

      max_perf_pct: limits the maximum P state that will be requested by
      the driver stated as a percentage of the available performance.
      the driver stated as a percentage of the available performance. The
      available (P states) performance may be reduced by the no_turbo
      setting described below.

      min_perf_pct: limits the minimum P state that will be  requested by
      the driver stated as a percentage of the available performance.
      the driver stated as a percentage of the max (non-turbo)
      performance level.

      no_turbo: limits the driver to selecting P states below the turbo
      frequency range.
+128 −2
Original line number Diff line number Diff line
@@ -30,6 +30,10 @@
#include <linux/types.h>
#include <linux/dmi.h>
#include <linux/delay.h>
#ifdef CONFIG_ACPI_PROCFS_POWER
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#endif
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/acpi.h>
@@ -52,6 +56,7 @@ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION("ACPI AC Adapter Driver");
MODULE_LICENSE("GPL");


static int acpi_ac_add(struct acpi_device *device);
static int acpi_ac_remove(struct acpi_device *device);
static void acpi_ac_notify(struct acpi_device *device, u32 event);
@@ -67,6 +72,13 @@ static int acpi_ac_resume(struct device *dev);
#endif
static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);

#ifdef CONFIG_ACPI_PROCFS_POWER
extern struct proc_dir_entry *acpi_lock_ac_dir(void);
extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
static int acpi_ac_open_fs(struct inode *inode, struct file *file);
#endif


static int ac_sleep_before_get_state_ms;

static struct acpi_driver acpi_ac_driver = {
@@ -91,6 +103,16 @@ struct acpi_ac {

#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger)

#ifdef CONFIG_ACPI_PROCFS_POWER
static const struct file_operations acpi_ac_fops = {
	.owner = THIS_MODULE,
	.open = acpi_ac_open_fs,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
};
#endif

/* --------------------------------------------------------------------------
                               AC Adapter Management
   -------------------------------------------------------------------------- */
@@ -143,6 +165,83 @@ static enum power_supply_property ac_props[] = {
	POWER_SUPPLY_PROP_ONLINE,
};

#ifdef CONFIG_ACPI_PROCFS_POWER
/* --------------------------------------------------------------------------
                              FS Interface (/proc)
   -------------------------------------------------------------------------- */

static struct proc_dir_entry *acpi_ac_dir;

static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
{
	struct acpi_ac *ac = seq->private;


	if (!ac)
		return 0;

	if (acpi_ac_get_state(ac)) {
		seq_puts(seq, "ERROR: Unable to read AC Adapter state\n");
		return 0;
	}

	seq_puts(seq, "state:                   ");
	switch (ac->state) {
	case ACPI_AC_STATUS_OFFLINE:
		seq_puts(seq, "off-line\n");
		break;
	case ACPI_AC_STATUS_ONLINE:
		seq_puts(seq, "on-line\n");
		break;
	default:
		seq_puts(seq, "unknown\n");
		break;
	}

	return 0;
}

static int acpi_ac_open_fs(struct inode *inode, struct file *file)
{
	return single_open(file, acpi_ac_seq_show, PDE_DATA(inode));
}

static int acpi_ac_add_fs(struct acpi_ac *ac)
{
	struct proc_dir_entry *entry = NULL;

	printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded,"
			" please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
	if (!acpi_device_dir(ac->device)) {
		acpi_device_dir(ac->device) =
			proc_mkdir(acpi_device_bid(ac->device), acpi_ac_dir);
		if (!acpi_device_dir(ac->device))
			return -ENODEV;
	}

	/* 'state' [R] */
	entry = proc_create_data(ACPI_AC_FILE_STATE,
				 S_IRUGO, acpi_device_dir(ac->device),
				 &acpi_ac_fops, ac);
	if (!entry)
		return -ENODEV;
	return 0;
}

static int acpi_ac_remove_fs(struct acpi_ac *ac)
{

	if (acpi_device_dir(ac->device)) {
		remove_proc_entry(ACPI_AC_FILE_STATE,
				  acpi_device_dir(ac->device));
		remove_proc_entry(acpi_device_bid(ac->device), acpi_ac_dir);
		acpi_device_dir(ac->device) = NULL;
	}

	return 0;
}
#endif

/* --------------------------------------------------------------------------
                                   Driver Model
   -------------------------------------------------------------------------- */
@@ -243,6 +342,11 @@ static int acpi_ac_add(struct acpi_device *device)
		goto end;

	ac->charger.name = acpi_device_bid(device);
#ifdef CONFIG_ACPI_PROCFS_POWER
	result = acpi_ac_add_fs(ac);
	if (result)
		goto end;
#endif
	ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
	ac->charger.properties = ac_props;
	ac->charger.num_properties = ARRAY_SIZE(ac_props);
@@ -258,8 +362,12 @@ static int acpi_ac_add(struct acpi_device *device)
	ac->battery_nb.notifier_call = acpi_ac_battery_notify;
	register_acpi_notifier(&ac->battery_nb);
end:
	if (result)
	if (result) {
#ifdef CONFIG_ACPI_PROCFS_POWER
		acpi_ac_remove_fs(ac);
#endif
		kfree(ac);
	}

	dmi_check_system(ac_dmi_table);
	return result;
@@ -303,6 +411,10 @@ static int acpi_ac_remove(struct acpi_device *device)
		power_supply_unregister(&ac->charger);
	unregister_acpi_notifier(&ac->battery_nb);

#ifdef CONFIG_ACPI_PROCFS_POWER
	acpi_ac_remove_fs(ac);
#endif

	kfree(ac);

	return 0;
@@ -315,9 +427,20 @@ static int __init acpi_ac_init(void)
	if (acpi_disabled)
		return -ENODEV;

#ifdef CONFIG_ACPI_PROCFS_POWER
	acpi_ac_dir = acpi_lock_ac_dir();
	if (!acpi_ac_dir)
		return -ENODEV;
#endif


	result = acpi_bus_register_driver(&acpi_ac_driver);
	if (result < 0)
	if (result < 0) {
#ifdef CONFIG_ACPI_PROCFS_POWER
		acpi_unlock_ac_dir(acpi_ac_dir);
#endif
		return -ENODEV;
	}

	return 0;
}
@@ -325,6 +448,9 @@ static int __init acpi_ac_init(void)
static void __exit acpi_ac_exit(void)
{
	acpi_bus_unregister_driver(&acpi_ac_driver);
#ifdef CONFIG_ACPI_PROCFS_POWER
	acpi_unlock_ac_dir(acpi_ac_dir);
#endif
}
module_init(acpi_ac_init);
module_exit(acpi_ac_exit);
+2 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
#include <linux/module.h>

static const struct acpi_device_id acpi_pnp_device_ids[] = {
	/* soc_button_array */
	{"PNP0C40"},
	/* pata_isapnp */
	{"PNP0600"},		/* Generic ESDI/IDE/ATA compatible hard disk controller */
	/* floppy */
+40 −1
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/suspend.h>
#include <linux/delay.h>
#include <asm/unaligned.h>

#ifdef CONFIG_ACPI_PROCFS_POWER
@@ -534,6 +535,20 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
			" invalid.\n");
	}

	/*
	 * When fully charged, some batteries wrongly report
	 * capacity_now = design_capacity instead of = full_charge_capacity
	 */
	if (battery->capacity_now > battery->full_charge_capacity
	    && battery->full_charge_capacity != ACPI_BATTERY_VALUE_UNKNOWN) {
		battery->capacity_now = battery->full_charge_capacity;
		if (battery->capacity_now != battery->design_capacity)
			printk_once(KERN_WARNING FW_BUG
				"battery: reported current charge level (%d) "
				"is higher than reported maximum charge level (%d).\n",
				battery->capacity_now, battery->full_charge_capacity);
	}

	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
	    && battery->capacity_now >= 0 && battery->capacity_now <= 100)
		battery->capacity_now = (battery->capacity_now *
@@ -1151,6 +1166,28 @@ static struct dmi_system_id bat_dmi_table[] = {
	{},
};

/*
 * Some machines'(E,G Lenovo Z480) ECs are not stable
 * during boot up and this causes battery driver fails to be
 * probed due to failure of getting battery information
 * from EC sometimes. After several retries, the operation
 * may work. So add retry code here and 20ms sleep between
 * every retries.
 */
static int acpi_battery_update_retry(struct acpi_battery *battery)
{
	int retry, ret;

	for (retry = 5; retry; retry--) {
		ret = acpi_battery_update(battery, false);
		if (!ret)
			break;

		msleep(20);
	}
	return ret;
}

static int acpi_battery_add(struct acpi_device *device)
{
	int result = 0;
@@ -1169,9 +1206,11 @@ static int acpi_battery_add(struct acpi_device *device)
	mutex_init(&battery->sysfs_lock);
	if (acpi_has_method(battery->device->handle, "_BIX"))
		set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
	result = acpi_battery_update(battery, false);

	result = acpi_battery_update_retry(battery);
	if (result)
		goto fail;

#ifdef CONFIG_ACPI_PROCFS_POWER
	result = acpi_battery_add_fs(device);
#endif
+85 −79
Original line number Diff line number Diff line
/*
 *  ec.c - ACPI Embedded Controller Driver (v2.1)
 *  ec.c - ACPI Embedded Controller Driver (v2.2)
 *
 *  Copyright (C) 2006-2008 Alexey Starikovskiy <astarikovskiy@suse.de>
 *  Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com>
 *  Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
 *  Copyright (C) 2001-2014 Intel Corporation
 *    Author: 2014       Lv Zheng <lv.zheng@intel.com>
 *            2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
 *            2006       Denis Sadykov <denis.m.sadykov@intel.com>
 *            2004       Luming Yu <luming.yu@intel.com>
 *            2001, 2002 Andy Grover <andrew.grover@intel.com>
 *            2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
 *  Copyright (C) 2008      Alexey Starikovskiy <astarikovskiy@suse.de>
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
@@ -52,6 +55,7 @@
/* EC status register */
#define ACPI_EC_FLAG_OBF	0x01	/* Output buffer full */
#define ACPI_EC_FLAG_IBF	0x02	/* Input buffer full */
#define ACPI_EC_FLAG_CMD	0x08	/* Input buffer contains a command */
#define ACPI_EC_FLAG_BURST	0x10	/* burst mode */
#define ACPI_EC_FLAG_SCI	0x20	/* EC-SCI occurred */

@@ -78,6 +82,9 @@ enum {
	EC_FLAGS_BLOCKED,		/* Transactions are blocked */
};

#define ACPI_EC_COMMAND_POLL		0x01 /* Available for command byte */
#define ACPI_EC_COMMAND_COMPLETE	0x02 /* Completed last byte */

/* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */
static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
module_param(ec_delay, uint, 0644);
@@ -109,7 +116,7 @@ struct transaction {
	u8 ri;
	u8 wlen;
	u8 rlen;
	bool done;
	u8 flags;
};

struct acpi_ec *boot_ec, *first_ec;
@@ -127,83 +134,104 @@ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
{
	u8 x = inb(ec->command_addr);
	pr_debug("---> status = 0x%2.2x\n", x);
	pr_debug("EC_SC(R) = 0x%2.2x "
		 "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d\n",
		 x,
		 !!(x & ACPI_EC_FLAG_SCI),
		 !!(x & ACPI_EC_FLAG_BURST),
		 !!(x & ACPI_EC_FLAG_CMD),
		 !!(x & ACPI_EC_FLAG_IBF),
		 !!(x & ACPI_EC_FLAG_OBF));
	return x;
}

static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
{
	u8 x = inb(ec->data_addr);
	pr_debug("---> data = 0x%2.2x\n", x);
	pr_debug("EC_DATA(R) = 0x%2.2x\n", x);
	return x;
}

static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
{
	pr_debug("<--- command = 0x%2.2x\n", command);
	pr_debug("EC_SC(W) = 0x%2.2x\n", command);
	outb(command, ec->command_addr);
}

static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
{
	pr_debug("<--- data = 0x%2.2x\n", data);
	pr_debug("EC_DATA(W) = 0x%2.2x\n", data);
	outb(data, ec->data_addr);
}

static int ec_transaction_done(struct acpi_ec *ec)
static int ec_transaction_completed(struct acpi_ec *ec)
{
	unsigned long flags;
	int ret = 0;
	spin_lock_irqsave(&ec->lock, flags);
	if (!ec->curr || ec->curr->done)
	if (ec->curr && (ec->curr->flags & ACPI_EC_COMMAND_COMPLETE))
		ret = 1;
	spin_unlock_irqrestore(&ec->lock, flags);
	return ret;
}

static void start_transaction(struct acpi_ec *ec)
{
	ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0;
	ec->curr->done = false;
	acpi_ec_write_cmd(ec, ec->curr->command);
}

static void advance_transaction(struct acpi_ec *ec, u8 status)
static bool advance_transaction(struct acpi_ec *ec)
{
	unsigned long flags;
	struct transaction *t;
	u8 status;
	bool wakeup = false;

	spin_lock_irqsave(&ec->lock, flags);
	pr_debug("===== %s =====\n", in_interrupt() ? "IRQ" : "TASK");
	status = acpi_ec_read_status(ec);
	t = ec->curr;
	if (!t)
		goto unlock;
		goto err;
	if (t->flags & ACPI_EC_COMMAND_POLL) {
		if (t->wlen > t->wi) {
			if ((status & ACPI_EC_FLAG_IBF) == 0)
			acpi_ec_write_data(ec,
				t->wdata[t->wi++]);
				acpi_ec_write_data(ec, t->wdata[t->wi++]);
			else
				goto err;
		} else if (t->rlen > t->ri) {
			if ((status & ACPI_EC_FLAG_OBF) == 1) {
				t->rdata[t->ri++] = acpi_ec_read_data(ec);
			if (t->rlen == t->ri)
				t->done = true;
				if (t->rlen == t->ri) {
					t->flags |= ACPI_EC_COMMAND_COMPLETE;
					wakeup = true;
				}
			} else
				goto err;
		} else if (t->wlen == t->wi &&
		   (status & ACPI_EC_FLAG_IBF) == 0)
		t->done = true;
	goto unlock;
			   (status & ACPI_EC_FLAG_IBF) == 0) {
			t->flags |= ACPI_EC_COMMAND_COMPLETE;
			wakeup = true;
		}
		return wakeup;
	} else {
		if ((status & ACPI_EC_FLAG_IBF) == 0) {
			acpi_ec_write_cmd(ec, t->command);
			t->flags |= ACPI_EC_COMMAND_POLL;
		} else
			goto err;
		return wakeup;
	}
err:
	/*
	 * If SCI bit is set, then don't think it's a false IRQ
	 * otherwise will take a not handled IRQ as a false one.
	 */
	if (in_interrupt() && !(status & ACPI_EC_FLAG_SCI))
	if (!(status & ACPI_EC_FLAG_SCI)) {
		if (in_interrupt() && t)
			++t->irq_count;
	}
	return wakeup;
}

unlock:
	spin_unlock_irqrestore(&ec->lock, flags);
static void start_transaction(struct acpi_ec *ec)
{
	ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0;
	ec->curr->flags = 0;
	(void)advance_transaction(ec);
}

static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data);
@@ -228,15 +256,17 @@ static int ec_poll(struct acpi_ec *ec)
			/* don't sleep with disabled interrupts */
			if (EC_FLAGS_MSI || irqs_disabled()) {
				udelay(ACPI_EC_MSI_UDELAY);
				if (ec_transaction_done(ec))
				if (ec_transaction_completed(ec))
					return 0;
			} else {
				if (wait_event_timeout(ec->wait,
						ec_transaction_done(ec),
						ec_transaction_completed(ec),
						msecs_to_jiffies(1)))
					return 0;
			}
			advance_transaction(ec, acpi_ec_read_status(ec));
			spin_lock_irqsave(&ec->lock, flags);
			(void)advance_transaction(ec);
			spin_unlock_irqrestore(&ec->lock, flags);
		} while (time_before(jiffies, delay));
		pr_debug("controller reset, restart transaction\n");
		spin_lock_irqsave(&ec->lock, flags);
@@ -268,23 +298,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
	return ret;
}

static int ec_check_ibf0(struct acpi_ec *ec)
{
	u8 status = acpi_ec_read_status(ec);
	return (status & ACPI_EC_FLAG_IBF) == 0;
}

static int ec_wait_ibf0(struct acpi_ec *ec)
{
	unsigned long delay = jiffies + msecs_to_jiffies(ec_delay);
	/* interrupt wait manually if GPE mode is not active */
	while (time_before(jiffies, delay))
		if (wait_event_timeout(ec->wait, ec_check_ibf0(ec),
					msecs_to_jiffies(1)))
			return 0;
	return -ETIME;
}

static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
{
	int status;
@@ -305,12 +318,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
			goto unlock;
		}
	}
	if (ec_wait_ibf0(ec)) {
		pr_err("input buffer is not empty, "
				"aborting transaction\n");
		status = -ETIME;
		goto end;
	}
	pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n",
			t->command, t->wdata ? t->wdata[0] : 0);
	/* disable GPE during transaction if storm is detected */
@@ -334,7 +341,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
		set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
	}
	pr_debug("transaction end\n");
end:
	if (ec->global_lock)
		acpi_release_global_lock(glk);
unlock:
@@ -634,17 +640,14 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state)
static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
	u32 gpe_number, void *data)
{
	unsigned long flags;
	struct acpi_ec *ec = data;
	u8 status = acpi_ec_read_status(ec);

	pr_debug("~~~> interrupt, status:0x%02x\n", status);

	advance_transaction(ec, status);
	if (ec_transaction_done(ec) &&
	    (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {
	spin_lock_irqsave(&ec->lock, flags);
	if (advance_transaction(ec))
		wake_up(&ec->wait);
	spin_unlock_irqrestore(&ec->lock, flags);
	ec_check_sci(ec, acpi_ec_read_status(ec));
	}
	return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
}

@@ -1066,8 +1069,10 @@ int __init acpi_ec_ecdt_probe(void)
	/* fall through */
	}

	if (EC_FLAGS_SKIP_DSDT_SCAN)
	if (EC_FLAGS_SKIP_DSDT_SCAN) {
		kfree(saved_ec);
		return -ENODEV;
	}

	/* This workaround is needed only on some broken machines,
	 * which require early EC, but fail to provide ECDT */
@@ -1105,6 +1110,7 @@ int __init acpi_ec_ecdt_probe(void)
	}
error:
	kfree(boot_ec);
	kfree(saved_ec);
	boot_ec = NULL;
	return -ENODEV;
}
Loading