mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-10 15:10:38 +00:00
ACPI and power management fixes for 3.12-rc3
1) After 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(). / -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABCAAGBQJSRg7lAAoJEKhOf7ml8uNsxaMP/1unuxyaCIrvCrrzx5ku5VmB Bw0g7bf1qjwJJJm75oUJNaCGOirsczYe2CvFs9KpXCCt1gyf9LgWoVjIR5Qhcp9A wOPfs1XqAzuagTr7AHzxUpJFwnd1XjPpkhjbCy3tDeJMIcBALfwEBVHMVQpUyiBe +oNgGbkI424ffyhhdGUTGrKTQYLa78/Ydz15gwaWBbmjlCpagb25o7unOt/Ia7l/ m0rFMvXEPW/n1dygnKvig2MkjrGiOpamwpKV9xGYRhARK9J/9PcDXObGm2EOlSrY 7kFQ5U8i8359uljfZF7V2NOcfkGdHL82J9+cqkbIaFusdJ2iAOMdLJp9n5YhuKOV DI32Ad+7PqXdUSz9r6L+Yw14/8Svn27JvIsCh9rCTZyaD0oL4g1zBrLimz+XNljC Y6AEj8DA1vHCqcxfZaCg6VEZHubfEZNWD/+s6Da5CtYnU2QH5utGtcinRVukyB+v mHReW+ZMNNJDGCiUvTNis7RL5YKkVXtZLkO2vLlBbSMQg4tGRmhSvKfxRr4G2ndZ g+VKIOdPZ8otjb2/QVWXwGKAjFfwVNUaZl2w4nWKAcwCeebN9h6jjbtcpexWr6Qe N1hh14YVoemamax4Sxks93LBXXK+/8zoXDY3OajcMepnSIvuAvGCwqOx3B6U+4iX mda1PVzHLkauCDYrciGl =WvF8 -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
ec220be785
@ -39,6 +39,7 @@
|
||||
#include <linux/ipmi.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/pnp.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
MODULE_AUTHOR("Zhao Yakui");
|
||||
MODULE_DESCRIPTION("ACPI IPMI Opregion driver");
|
||||
@ -57,7 +58,7 @@ struct acpi_ipmi_device {
|
||||
struct list_head head;
|
||||
/* the IPMI request message list */
|
||||
struct list_head tx_msg_list;
|
||||
struct mutex tx_msg_lock;
|
||||
spinlock_t tx_msg_lock;
|
||||
acpi_handle handle;
|
||||
struct pnp_dev *pnp_dev;
|
||||
ipmi_user_t user_interface;
|
||||
@ -147,6 +148,7 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
|
||||
struct kernel_ipmi_msg *msg;
|
||||
struct acpi_ipmi_buffer *buffer;
|
||||
struct acpi_ipmi_device *device;
|
||||
unsigned long flags;
|
||||
|
||||
msg = &tx_msg->tx_message;
|
||||
/*
|
||||
@ -177,10 +179,10 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
|
||||
|
||||
/* Get the msgid */
|
||||
device = tx_msg->device;
|
||||
mutex_lock(&device->tx_msg_lock);
|
||||
spin_lock_irqsave(&device->tx_msg_lock, flags);
|
||||
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,
|
||||
@ -242,6 +244,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
|
||||
int msg_found = 0;
|
||||
struct acpi_ipmi_msg *tx_msg;
|
||||
struct pnp_dev *pnp_dev = ipmi_device->pnp_dev;
|
||||
unsigned long flags;
|
||||
|
||||
if (msg->user != ipmi_device->user_interface) {
|
||||
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)
|
||||
ipmi_free_recv_msg(msg);
|
||||
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) {
|
||||
if (msg->msgid == tx_msg->tx_msgid) {
|
||||
msg_found = 1;
|
||||
@ -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) {
|
||||
dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is "
|
||||
"returned.\n", msg->msgid);
|
||||
@ -378,6 +381,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
|
||||
struct acpi_ipmi_device *ipmi_device = handler_context;
|
||||
int err, rem_time;
|
||||
acpi_status status;
|
||||
unsigned long flags;
|
||||
/*
|
||||
* IPMI opregion message.
|
||||
* 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,
|
||||
return AE_NO_MEMORY;
|
||||
|
||||
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);
|
||||
mutex_unlock(&ipmi_device->tx_msg_lock);
|
||||
spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
|
||||
err = ipmi_request_settime(ipmi_device->user_interface,
|
||||
&tx_msg->addr,
|
||||
tx_msg->tx_msgid,
|
||||
@ -413,9 +417,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
|
||||
status = AE_OK;
|
||||
|
||||
end_label:
|
||||
mutex_lock(&ipmi_device->tx_msg_lock);
|
||||
spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
|
||||
list_del(&tx_msg->head);
|
||||
mutex_unlock(&ipmi_device->tx_msg_lock);
|
||||
spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
|
||||
kfree(tx_msg);
|
||||
return status;
|
||||
}
|
||||
@ -457,7 +461,7 @@ static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device)
|
||||
|
||||
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);
|
||||
ipmi_install_space_handler(ipmi_device);
|
||||
|
||||
|
@ -1121,7 +1121,7 @@ int acpi_bus_register_driver(struct acpi_driver *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
|
||||
*
|
||||
* Unregisters a driver with the ACPI bus. Searches the namespace for all
|
||||
|
@ -986,6 +986,10 @@ static int __init acpi_cpufreq_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* don't keep reloading if cpufreq_driver exists */
|
||||
if (cpufreq_get_current_driver())
|
||||
return 0;
|
||||
|
||||
if (acpi_disabled)
|
||||
return 0;
|
||||
|
||||
|
@ -1460,6 +1460,9 @@ unsigned int cpufreq_get(unsigned int cpu)
|
||||
{
|
||||
unsigned int ret_freq = 0;
|
||||
|
||||
if (cpufreq_disabled() || !cpufreq_driver)
|
||||
return -ENOENT;
|
||||
|
||||
if (!down_read_trylock(&cpufreq_rwsem))
|
||||
return 0;
|
||||
|
||||
|
@ -457,7 +457,7 @@ err_free_table:
|
||||
opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
|
||||
err_put_node:
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user