提交 ec220be7 编写于 作者: L Linus Torvalds

Merge tag 'pm+acpi-3.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI and power management fixes from Rafael Wysocki:
 "These fix one recent cpufreq regression, a few older bugs that may
  harm users and a kerneldoc typo.

  Specifics:

   1) After the recent locking changes in the cpufreq core it is
      possible to trigger BUG_ON(!policy) in lock_policy_rwsem_read() if
      cpufreq_get() is called before registering a cpufreq driver.  Fix
      from Viresh Kumar.

   2) If intel_pstate has been loaded already, it doesn't make sense to
      do anything in acpi_cpufreq_init() and moreover doing something in
      there in that case may be harmful, so make that function return
      immediately if another cpufreq driver is already present.  From
      Yinghai Lu.

   3) The ACPI IPMI driver sometimes attempts to acquire a mutex from
      interrupt context, which can be avoided by replacing that mutex
      with a spinlock.  From Lv Zheng.

   4) A NULL pointer may be dereferenced by the exynos5440 cpufreq
      driver if a memory allocation made by it fails.  Fix from Sachin
      Kamat.

   5) Hanjun Guo's commit fixes a typo in the kerneldoc comment
      documenting acpi_bus_unregister_driver()"

* tag 'pm+acpi-3.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI / scan: fix typo in comments of acpi_bus_unregister_driver()
  cpufreq: exynos5440: Fix potential NULL pointer dereference
  cpufreq: check cpufreq driver is valid and cpufreq isn't disabled in cpufreq_get()
  acpi-cpufreq: skip loading acpi_cpufreq after intel_pstate
  ACPI / IPMI: Fix atomic context requirement of ipmi_msg_handler()
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/ipmi.h> #include <linux/ipmi.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/pnp.h> #include <linux/pnp.h>
#include <linux/spinlock.h>
MODULE_AUTHOR("Zhao Yakui"); MODULE_AUTHOR("Zhao Yakui");
MODULE_DESCRIPTION("ACPI IPMI Opregion driver"); MODULE_DESCRIPTION("ACPI IPMI Opregion driver");
...@@ -57,7 +58,7 @@ struct acpi_ipmi_device { ...@@ -57,7 +58,7 @@ struct acpi_ipmi_device {
struct list_head head; struct list_head head;
/* the IPMI request message list */ /* the IPMI request message list */
struct list_head tx_msg_list; struct list_head tx_msg_list;
struct mutex tx_msg_lock; spinlock_t tx_msg_lock;
acpi_handle handle; acpi_handle handle;
struct pnp_dev *pnp_dev; struct pnp_dev *pnp_dev;
ipmi_user_t user_interface; ipmi_user_t user_interface;
...@@ -147,6 +148,7 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, ...@@ -147,6 +148,7 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
struct kernel_ipmi_msg *msg; struct kernel_ipmi_msg *msg;
struct acpi_ipmi_buffer *buffer; struct acpi_ipmi_buffer *buffer;
struct acpi_ipmi_device *device; struct acpi_ipmi_device *device;
unsigned long flags;
msg = &tx_msg->tx_message; msg = &tx_msg->tx_message;
/* /*
...@@ -177,10 +179,10 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, ...@@ -177,10 +179,10 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
/* Get the msgid */ /* Get the msgid */
device = tx_msg->device; device = tx_msg->device;
mutex_lock(&device->tx_msg_lock); spin_lock_irqsave(&device->tx_msg_lock, flags);
device->curr_msgid++; device->curr_msgid++;
tx_msg->tx_msgid = device->curr_msgid; tx_msg->tx_msgid = device->curr_msgid;
mutex_unlock(&device->tx_msg_lock); spin_unlock_irqrestore(&device->tx_msg_lock, flags);
} }
static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
...@@ -242,6 +244,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) ...@@ -242,6 +244,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
int msg_found = 0; int msg_found = 0;
struct acpi_ipmi_msg *tx_msg; struct acpi_ipmi_msg *tx_msg;
struct pnp_dev *pnp_dev = ipmi_device->pnp_dev; struct pnp_dev *pnp_dev = ipmi_device->pnp_dev;
unsigned long flags;
if (msg->user != ipmi_device->user_interface) { if (msg->user != ipmi_device->user_interface) {
dev_warn(&pnp_dev->dev, "Unexpected response is returned. " dev_warn(&pnp_dev->dev, "Unexpected response is returned. "
...@@ -250,7 +253,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) ...@@ -250,7 +253,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
ipmi_free_recv_msg(msg); ipmi_free_recv_msg(msg);
return; return;
} }
mutex_lock(&ipmi_device->tx_msg_lock); spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) { list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) {
if (msg->msgid == tx_msg->tx_msgid) { if (msg->msgid == tx_msg->tx_msgid) {
msg_found = 1; msg_found = 1;
...@@ -258,7 +261,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) ...@@ -258,7 +261,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
} }
} }
mutex_unlock(&ipmi_device->tx_msg_lock); spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
if (!msg_found) { if (!msg_found) {
dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is " dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is "
"returned.\n", msg->msgid); "returned.\n", msg->msgid);
...@@ -378,6 +381,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, ...@@ -378,6 +381,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
struct acpi_ipmi_device *ipmi_device = handler_context; struct acpi_ipmi_device *ipmi_device = handler_context;
int err, rem_time; int err, rem_time;
acpi_status status; acpi_status status;
unsigned long flags;
/* /*
* IPMI opregion message. * IPMI opregion message.
* IPMI message is firstly written to the BMC and system software * IPMI message is firstly written to the BMC and system software
...@@ -395,9 +399,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, ...@@ -395,9 +399,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
return AE_NO_MEMORY; return AE_NO_MEMORY;
acpi_format_ipmi_msg(tx_msg, address, value); acpi_format_ipmi_msg(tx_msg, address, value);
mutex_lock(&ipmi_device->tx_msg_lock); spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list); list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list);
mutex_unlock(&ipmi_device->tx_msg_lock); spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
err = ipmi_request_settime(ipmi_device->user_interface, err = ipmi_request_settime(ipmi_device->user_interface,
&tx_msg->addr, &tx_msg->addr,
tx_msg->tx_msgid, tx_msg->tx_msgid,
...@@ -413,9 +417,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, ...@@ -413,9 +417,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
status = AE_OK; status = AE_OK;
end_label: end_label:
mutex_lock(&ipmi_device->tx_msg_lock); spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
list_del(&tx_msg->head); list_del(&tx_msg->head);
mutex_unlock(&ipmi_device->tx_msg_lock); spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
kfree(tx_msg); kfree(tx_msg);
return status; return status;
} }
...@@ -457,7 +461,7 @@ static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device) ...@@ -457,7 +461,7 @@ static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device)
INIT_LIST_HEAD(&ipmi_device->head); INIT_LIST_HEAD(&ipmi_device->head);
mutex_init(&ipmi_device->tx_msg_lock); spin_lock_init(&ipmi_device->tx_msg_lock);
INIT_LIST_HEAD(&ipmi_device->tx_msg_list); INIT_LIST_HEAD(&ipmi_device->tx_msg_list);
ipmi_install_space_handler(ipmi_device); ipmi_install_space_handler(ipmi_device);
......
...@@ -1121,7 +1121,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver) ...@@ -1121,7 +1121,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver)
EXPORT_SYMBOL(acpi_bus_register_driver); EXPORT_SYMBOL(acpi_bus_register_driver);
/** /**
* acpi_bus_unregister_driver - unregisters a driver with the APIC bus * acpi_bus_unregister_driver - unregisters a driver with the ACPI bus
* @driver: driver to unregister * @driver: driver to unregister
* *
* Unregisters a driver with the ACPI bus. Searches the namespace for all * Unregisters a driver with the ACPI bus. Searches the namespace for all
......
...@@ -986,6 +986,10 @@ static int __init acpi_cpufreq_init(void) ...@@ -986,6 +986,10 @@ static int __init acpi_cpufreq_init(void)
{ {
int ret; int ret;
/* don't keep reloading if cpufreq_driver exists */
if (cpufreq_get_current_driver())
return 0;
if (acpi_disabled) if (acpi_disabled)
return 0; return 0;
......
...@@ -1460,6 +1460,9 @@ unsigned int cpufreq_get(unsigned int cpu) ...@@ -1460,6 +1460,9 @@ unsigned int cpufreq_get(unsigned int cpu)
{ {
unsigned int ret_freq = 0; unsigned int ret_freq = 0;
if (cpufreq_disabled() || !cpufreq_driver)
return -ENOENT;
if (!down_read_trylock(&cpufreq_rwsem)) if (!down_read_trylock(&cpufreq_rwsem))
return 0; return 0;
......
...@@ -457,7 +457,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) ...@@ -457,7 +457,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table); opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
err_put_node: err_put_node:
of_node_put(np); of_node_put(np);
dev_err(dvfs_info->dev, "%s: failed initialization\n", __func__); dev_err(&pdev->dev, "%s: failed initialization\n", __func__);
return ret; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册