diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-10 18:36:30 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-10 18:36:30 -0700 | 
| commit | b67db9d5e1294ddcd7f9bea43736a897132f4df7 (patch) | |
| tree | d0ac50692253158ad0889a37021e839fefe3cc07 | |
| parent | 4c71842375f52dc8a8a6097ffcd625243e153649 (diff) | |
| parent | 2091044299e9bc3340d845301b13bd92d6c10993 (diff) | |
Merge tag 'pm+acpi-3.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
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."
| -rw-r--r-- | Documentation/cpu-freq/intel-pstate.txt | 7 | ||||
| -rw-r--r-- | drivers/acpi/ac.c | 130 | ||||
| -rw-r--r-- | drivers/acpi/acpi_pnp.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/battery.c | 41 | ||||
| -rw-r--r-- | drivers/acpi/ec.c | 164 | ||||
| -rw-r--r-- | drivers/acpi/resource.c | 10 | ||||
| -rw-r--r-- | drivers/acpi/video.c | 11 | ||||
| -rw-r--r-- | drivers/acpi/video_detect.c | 8 | ||||
| -rw-r--r-- | drivers/cpufreq/Makefile | 2 | ||||
| -rw-r--r-- | drivers/cpufreq/intel_pstate.c | 35 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_opregion.c | 9 | ||||
| -rw-r--r-- | include/acpi/video.h | 2 | 
12 files changed, 317 insertions, 104 deletions
| diff --git a/Documentation/cpu-freq/intel-pstate.txt b/Documentation/cpu-freq/intel-pstate.txt index e742d21dbd96..a69ffe1d54d5 100644 --- a/Documentation/cpu-freq/intel-pstate.txt +++ b/Documentation/cpu-freq/intel-pstate.txt @@ -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. diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index c67f6f5ad611..36b0e61f9c09 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -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); diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 6703c1fd993a..4ddb0dca56f6 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -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 */ diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 0d7116f34b95..130f513e08c9 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -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 diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ad11ba4a412d..a66ab658abbc 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1,11 +1,14 @@  /* - *  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) +static bool advance_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) -{ -	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; -	if (t->wlen > t->wi) { -		if ((status & ACPI_EC_FLAG_IBF) == 0) -			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; +		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++]); +			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->flags |= ACPI_EC_COMMAND_COMPLETE; +					wakeup = true; +				} +			} else +				goto err; +		} else if (t->wlen == t->wi && +			   (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; -	} else if (t->wlen == t->wi && -		   (status & ACPI_EC_FLAG_IBF) == 0) -		t->done = true; -	goto unlock; +		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)) -		++t->irq_count; +	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); -		ec_check_sci(ec, acpi_ec_read_status(ec)); -	} +	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 @@ install:  	}  error:  	kfree(boot_ec); +	kfree(saved_ec);  	boot_ec = NULL;  	return -ENODEV;  } diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 0bdacc5e26a3..2ba8f02ced36 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -77,7 +77,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)  	switch (ares->type) {  	case ACPI_RESOURCE_TYPE_MEMORY24:  		memory24 = &ares->data.memory24; -		if (!memory24->address_length) +		if (!memory24->minimum && !memory24->address_length)  			return false;  		acpi_dev_get_memresource(res, memory24->minimum,  					 memory24->address_length, @@ -85,7 +85,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)  		break;  	case ACPI_RESOURCE_TYPE_MEMORY32:  		memory32 = &ares->data.memory32; -		if (!memory32->address_length) +		if (!memory32->minimum && !memory32->address_length)  			return false;  		acpi_dev_get_memresource(res, memory32->minimum,  					 memory32->address_length, @@ -93,7 +93,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)  		break;  	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:  		fixed_memory32 = &ares->data.fixed_memory32; -		if (!fixed_memory32->address_length) +		if (!fixed_memory32->address && !fixed_memory32->address_length)  			return false;  		acpi_dev_get_memresource(res, fixed_memory32->address,  					 fixed_memory32->address_length, @@ -150,7 +150,7 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)  	switch (ares->type) {  	case ACPI_RESOURCE_TYPE_IO:  		io = &ares->data.io; -		if (!io->address_length) +		if (!io->minimum && !io->address_length)  			return false;  		acpi_dev_get_ioresource(res, io->minimum,  					io->address_length, @@ -158,7 +158,7 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)  		break;  	case ACPI_RESOURCE_TYPE_FIXED_IO:  		fixed_io = &ares->data.fixed_io; -		if (!fixed_io->address_length) +		if (!fixed_io->address && !fixed_io->address_length)  			return false;  		acpi_dev_get_ioresource(res, fixed_io->address,  					fixed_io->address_length, diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index fb9ffe9adc64..071c1dfb93f3 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -241,13 +241,14 @@ static bool acpi_video_use_native_backlight(void)  		return use_native_backlight_dmi;  } -static bool acpi_video_verify_backlight_support(void) +bool acpi_video_verify_backlight_support(void)  {  	if (acpi_osi_is_win8() && acpi_video_use_native_backlight() &&  	    backlight_device_registered(BACKLIGHT_RAW))  		return false;  	return acpi_video_backlight_support();  } +EXPORT_SYMBOL_GPL(acpi_video_verify_backlight_support);  /* backlight device sysfs support */  static int acpi_video_get_brightness(struct backlight_device *bd) @@ -563,6 +564,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {  		},  	},  	{ +	 .callback = video_set_use_native_backlight, +	 .ident = "Acer TravelMate B113", +	 .matches = { +		DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +		DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate B113"), +		}, +	}, +	{  	.callback = video_set_use_native_backlight,  	.ident = "HP ProBook 4340s",  	.matches = { diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 33e3db548a29..c42feb2bacd0 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -166,6 +166,14 @@ static struct dmi_system_id video_detect_dmi_table[] = {  		DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),  		},  	}, +	{ +	.callback = video_detect_force_vendor, +	.ident = "Dell Inspiron 5737", +	.matches = { +		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +		DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5737"), +		}, +	},  	{ },  }; diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 738c8b7b17dc..db6d9a2fea4d 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -49,7 +49,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ)	+= arm_big_little.o  # LITTLE drivers, so that it is probed last.  obj-$(CONFIG_ARM_DT_BL_CPUFREQ)		+= arm_big_little_dt.o -obj-$(CONFIG_ARCH_DAVINCI_DA850)	+= davinci-cpufreq.o +obj-$(CONFIG_ARCH_DAVINCI)		+= davinci-cpufreq.o  obj-$(CONFIG_UX500_SOC_DB8500)		+= dbx500-cpufreq.o  obj-$(CONFIG_ARM_EXYNOS_CPUFREQ)	+= exynos-cpufreq.o  obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ)	+= exynos4210-cpufreq.o diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 924bb2d42b1c..86631cb6f7de 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -128,6 +128,7 @@ static struct pstate_funcs pstate_funcs;  struct perf_limits {  	int no_turbo; +	int turbo_disabled;  	int max_perf_pct;  	int min_perf_pct;  	int32_t max_perf; @@ -287,7 +288,10 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,  	if (ret != 1)  		return -EINVAL;  	limits.no_turbo = clamp_t(int, input, 0 , 1); - +	if (limits.turbo_disabled) { +		pr_warn("Turbo disabled by BIOS or unavailable on processor\n"); +		limits.no_turbo = limits.turbo_disabled; +	}  	return count;  } @@ -357,21 +361,21 @@ static int byt_get_min_pstate(void)  {  	u64 value;  	rdmsrl(BYT_RATIOS, value); -	return (value >> 8) & 0x3F; +	return (value >> 8) & 0x7F;  }  static int byt_get_max_pstate(void)  {  	u64 value;  	rdmsrl(BYT_RATIOS, value); -	return (value >> 16) & 0x3F; +	return (value >> 16) & 0x7F;  }  static int byt_get_turbo_pstate(void)  {  	u64 value;  	rdmsrl(BYT_TURBO_RATIOS, value); -	return value & 0x3F; +	return value & 0x7F;  }  static void byt_set_pstate(struct cpudata *cpudata, int pstate) @@ -381,7 +385,7 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate)  	u32 vid;  	val = pstate << 8; -	if (limits.no_turbo) +	if (limits.no_turbo && !limits.turbo_disabled)  		val |= (u64)1 << 32;  	vid_fp = cpudata->vid.min + mul_fp( @@ -405,8 +409,8 @@ static void byt_get_vid(struct cpudata *cpudata)  	rdmsrl(BYT_VIDS, value); -	cpudata->vid.min = int_tofp((value >> 8) & 0x3f); -	cpudata->vid.max = int_tofp((value >> 16) & 0x3f); +	cpudata->vid.min = int_tofp((value >> 8) & 0x7f); +	cpudata->vid.max = int_tofp((value >> 16) & 0x7f);  	cpudata->vid.ratio = div_fp(  		cpudata->vid.max - cpudata->vid.min,  		int_tofp(cpudata->pstate.max_pstate - @@ -448,7 +452,7 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate)  	u64 val;  	val = pstate << 8; -	if (limits.no_turbo) +	if (limits.no_turbo && !limits.turbo_disabled)  		val |= (u64)1 << 32;  	wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); @@ -696,9 +700,8 @@ static int intel_pstate_init_cpu(unsigned int cpunum)  	cpu = all_cpu_data[cpunum]; -	intel_pstate_get_cpu_pstates(cpu); -  	cpu->cpu = cpunum; +	intel_pstate_get_cpu_pstates(cpu);  	init_timer_deferrable(&cpu->timer);  	cpu->timer.function = intel_pstate_timer_func; @@ -741,7 +744,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)  		limits.min_perf = int_tofp(1);  		limits.max_perf_pct = 100;  		limits.max_perf = int_tofp(1); -		limits.no_turbo = 0; +		limits.no_turbo = limits.turbo_disabled;  		return 0;  	}  	limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; @@ -784,6 +787,7 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)  {  	struct cpudata *cpu;  	int rc; +	u64 misc_en;  	rc = intel_pstate_init_cpu(policy->cpu);  	if (rc) @@ -791,8 +795,13 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)  	cpu = all_cpu_data[policy->cpu]; -	if (!limits.no_turbo && -		limits.min_perf_pct == 100 && limits.max_perf_pct == 100) +	rdmsrl(MSR_IA32_MISC_ENABLE, misc_en); +	if (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE || +		cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) { +		limits.turbo_disabled = 1; +		limits.no_turbo = 1; +	} +	if (limits.min_perf_pct == 100 && limits.max_perf_pct == 100)  		policy->policy = CPUFREQ_POLICY_PERFORMANCE;  	else  		policy->policy = CPUFREQ_POLICY_POWERSAVE; diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 2e2c71fcc9ed..4f6b53998d79 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -403,6 +403,15 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)  	DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp); +	/* +	 * If the acpi_video interface is not supposed to be used, don't +	 * bother processing backlight level change requests from firmware. +	 */ +	if (!acpi_video_verify_backlight_support()) { +		DRM_DEBUG_KMS("opregion backlight request ignored\n"); +		return 0; +	} +  	if (!(bclp & ASLE_BCLP_VALID))  		return ASLC_BACKLIGHT_FAILED; diff --git a/include/acpi/video.h b/include/acpi/video.h index ea4c7bbded4d..843ef1adfbfa 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h @@ -22,6 +22,7 @@ extern void acpi_video_unregister(void);  extern void acpi_video_unregister_backlight(void);  extern int acpi_video_get_edid(struct acpi_device *device, int type,  			       int device_id, void **edid); +extern bool acpi_video_verify_backlight_support(void);  #else  static inline int acpi_video_register(void) { return 0; }  static inline void acpi_video_unregister(void) { return; } @@ -31,6 +32,7 @@ static inline int acpi_video_get_edid(struct acpi_device *device, int type,  {  	return -ENODEV;  } +static inline bool acpi_video_verify_backlight_support(void) { return false; }  #endif  #endif | 
