aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-14 20:21:54 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-14 20:21:54 -0700
commit2481bc75283ea10e75d5fb1a8b42af363fc4b45c (patch)
tree42dd659a23041a08955aceebab859b616164c2f6 /drivers/pnp
parent8691c130fae136bb2b7d0554422a2dff4c6ac169 (diff)
parent518b4e272d99dcb13699b229ea480bc845c141f6 (diff)
Merge tag 'pm+acpi-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management and ACPI updates from Rafael Wysocki: "These are mostly fixes and cleanups all over, although there are a few items that sort of fall into the new feature category. First off, we have new callbacks for PM domains that should help us to handle some issues related to device initialization in a better way. There also is some consolidation in the unified device properties API area allowing us to use that inferface for accessing data coming from platform initialization code in addition to firmware-provided data. We have some new device/CPU IDs in a few drivers, support for new chips and a new cpufreq driver too. Specifics: - Generic PM domains support update including new PM domain callbacks to handle device initialization better (Russell King, Rafael J Wysocki, Kevin Hilman) - Unified device properties API update including a new mechanism for accessing data provided by platform initialization code (Rafael J Wysocki, Adrian Hunter) - ARM cpuidle update including ARM32/ARM64 handling consolidation (Daniel Lezcano) - intel_idle update including support for the Silvermont Core in the Baytrail SOC and for the Airmont Core in the Cherrytrail and Braswell SOCs (Len Brown, Mathias Krause) - New cpufreq driver for Hisilicon ACPU (Leo Yan) - intel_pstate update including support for the Knights Landing chip (Dasaratharaman Chandramouli, Kristen Carlson Accardi) - QorIQ cpufreq driver update (Tang Yuantian, Arnd Bergmann) - powernv cpufreq driver update (Shilpasri G Bhat) - devfreq update including Tegra support changes (Tomeu Vizoso, MyungJoo Ham, Chanwoo Choi) - powercap RAPL (Running-Average Power Limit) driver update including support for Intel Broadwell server chips (Jacob Pan, Mathias Krause) - ACPI device enumeration update related to the handling of the special PRP0001 device ID allowing DT-style 'compatible' property to be used for ACPI device identification (Rafael J Wysocki) - ACPI EC driver update including limited _DEP support (Lan Tianyu, Lv Zheng) - ACPI backlight driver update including a new mechanism to allow native backlight handling to be forced on non-Windows 8 systems and a new quirk for Lenovo Ideapad Z570 (Aaron Lu, Hans de Goede) - New Windows Vista compatibility quirk for Sony VGN-SR19XN (Chen Yu) - Assorted ACPI fixes and cleanups (Aaron Lu, Martin Kepplinger, Masanari Iida, Mika Westerberg, Nan Li, Rafael J Wysocki) - Fixes related to suspend-to-idle for the iTCO watchdog driver and the ACPI core system suspend/resume code (Rafael J Wysocki, Chen Yu) - PM tracing support for the suspend phase of system suspend/resume transitions (Zhonghui Fu) - Configurable delay for the system suspend/resume testing facility (Brian Norris) - PNP subsystem cleanups (Peter Huewe, Rafael J Wysocki)" * tag 'pm+acpi-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (74 commits) ACPI / scan: Fix NULL pointer dereference in acpi_companion_match() ACPI / scan: Rework modalias creation when "compatible" is present intel_idle: mark cpu id array as __initconst powercap / RAPL: mark rapl_ids array as __initconst powercap / RAPL: add ID for Broadwell server intel_pstate: Knights Landing support intel_pstate: remove MSR test cpufreq: fix qoriq uniprocessor build ACPI / scan: Take the PRP0001 position in the list of IDs into account ACPI / scan: Simplify acpi_match_device() ACPI / scan: Generalize of_compatible matching device property: Introduce firmware node type for platform data device property: Make it possible to use secondary firmware nodes PM / watchdog: iTCO: stop watchdog during system suspend cpufreq: hisilicon: add acpu driver ACPI / EC: Call acpi_walk_dep_device_list() after installing EC opregion handler cpufreq: powernv: Report cpu frequency throttling intel_idle: Add support for the Airmont Core in the Cherrytrail and Braswell SOCs intel_idle: Update support for Silvermont Core in Baytrail SOC PM / devfreq: tegra: Register governor on module init ...
Diffstat (limited to 'drivers/pnp')
-rw-r--r--drivers/pnp/base.h2
-rw-r--r--drivers/pnp/card.c25
-rw-r--r--drivers/pnp/core.c64
-rw-r--r--drivers/pnp/driver.c10
-rw-r--r--drivers/pnp/pnpacpi/core.c5
5 files changed, 67 insertions, 39 deletions
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index c8873b0ca551..3151fd164614 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -3,7 +3,7 @@
* Bjorn Helgaas <bjorn.helgaas@hp.com>
*/
-extern spinlock_t pnp_lock;
+extern struct mutex pnp_lock;
extern const struct attribute_group *pnp_dev_groups[];
void *pnp_alloc(long size);
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index 874c236ac1a7..31ad9fc3f701 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -5,6 +5,7 @@
*/
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/ctype.h>
#include <linux/slab.h>
#include <linux/pnp.h>
@@ -244,10 +245,10 @@ int pnp_add_card(struct pnp_card *card)
}
pnp_interface_attach_card(card);
- spin_lock(&pnp_lock);
+ mutex_lock(&pnp_lock);
list_add_tail(&card->global_list, &pnp_cards);
list_add_tail(&card->protocol_list, &card->protocol->cards);
- spin_unlock(&pnp_lock);
+ mutex_unlock(&pnp_lock);
/* we wait until now to add devices in order to ensure the drivers
* will be able to use all of the related devices on the card
@@ -276,10 +277,10 @@ void pnp_remove_card(struct pnp_card *card)
struct list_head *pos, *temp;
device_unregister(&card->dev);
- spin_lock(&pnp_lock);
+ mutex_lock(&pnp_lock);
list_del(&card->global_list);
list_del(&card->protocol_list);
- spin_unlock(&pnp_lock);
+ mutex_unlock(&pnp_lock);
list_for_each_safe(pos, temp, &card->devices) {
struct pnp_dev *dev = card_to_pnp_dev(pos);
pnp_remove_card_device(dev);
@@ -297,10 +298,10 @@ int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev)
dev->card_link = NULL;
dev_set_name(&dev->dev, "%02x:%02x.%02x",
dev->protocol->number, card->number, dev->number);
- spin_lock(&pnp_lock);
+ mutex_lock(&pnp_lock);
dev->card = card;
list_add_tail(&dev->card_list, &card->devices);
- spin_unlock(&pnp_lock);
+ mutex_unlock(&pnp_lock);
return 0;
}
@@ -310,10 +311,10 @@ int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev)
*/
void pnp_remove_card_device(struct pnp_dev *dev)
{
- spin_lock(&pnp_lock);
+ mutex_lock(&pnp_lock);
dev->card = NULL;
list_del(&dev->card_list);
- spin_unlock(&pnp_lock);
+ mutex_unlock(&pnp_lock);
__pnp_remove_device(dev);
}
@@ -426,9 +427,9 @@ int pnp_register_card_driver(struct pnp_card_driver *drv)
if (error < 0)
return error;
- spin_lock(&pnp_lock);
+ mutex_lock(&pnp_lock);
list_add_tail(&drv->global_list, &pnp_card_drivers);
- spin_unlock(&pnp_lock);
+ mutex_unlock(&pnp_lock);
list_for_each_safe(pos, temp, &pnp_cards) {
struct pnp_card *card =
@@ -444,9 +445,9 @@ int pnp_register_card_driver(struct pnp_card_driver *drv)
*/
void pnp_unregister_card_driver(struct pnp_card_driver *drv)
{
- spin_lock(&pnp_lock);
+ mutex_lock(&pnp_lock);
list_del(&drv->global_list);
- spin_unlock(&pnp_lock);
+ mutex_unlock(&pnp_lock);
pnp_unregister_driver(&drv->link);
}
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index cb6ce42f8e77..b54620e53830 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -9,6 +9,7 @@
#include <linux/list.h>
#include <linux/device.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
@@ -19,7 +20,7 @@
static LIST_HEAD(pnp_protocols);
LIST_HEAD(pnp_global);
-DEFINE_SPINLOCK(pnp_lock);
+DEFINE_MUTEX(pnp_lock);
/*
* ACPI or PNPBIOS should tell us about all platform devices, so we can
@@ -41,6 +42,13 @@ void *pnp_alloc(long size)
return result;
}
+static void pnp_remove_protocol(struct pnp_protocol *protocol)
+{
+ mutex_lock(&pnp_lock);
+ list_del(&protocol->protocol_list);
+ mutex_unlock(&pnp_lock);
+}
+
/**
* pnp_protocol_register - adds a pnp protocol to the pnp layer
* @protocol: pointer to the corresponding pnp_protocol structure
@@ -49,13 +57,14 @@ void *pnp_alloc(long size)
*/
int pnp_register_protocol(struct pnp_protocol *protocol)
{
- int nodenum;
struct list_head *pos;
+ int nodenum, ret;
INIT_LIST_HEAD(&protocol->devices);
INIT_LIST_HEAD(&protocol->cards);
nodenum = 0;
- spin_lock(&pnp_lock);
+
+ mutex_lock(&pnp_lock);
/* assign the lowest unused number */
list_for_each(pos, &pnp_protocols) {
@@ -66,12 +75,18 @@ int pnp_register_protocol(struct pnp_protocol *protocol)
}
}
- list_add_tail(&protocol->protocol_list, &pnp_protocols);
- spin_unlock(&pnp_lock);
-
protocol->number = nodenum;
dev_set_name(&protocol->dev, "pnp%d", nodenum);
- return device_register(&protocol->dev);
+
+ list_add_tail(&protocol->protocol_list, &pnp_protocols);
+
+ mutex_unlock(&pnp_lock);
+
+ ret = device_register(&protocol->dev);
+ if (ret)
+ pnp_remove_protocol(protocol);
+
+ return ret;
}
/**
@@ -80,9 +95,7 @@ int pnp_register_protocol(struct pnp_protocol *protocol)
*/
void pnp_unregister_protocol(struct pnp_protocol *protocol)
{
- spin_lock(&pnp_lock);
- list_del(&protocol->protocol_list);
- spin_unlock(&pnp_lock);
+ pnp_remove_protocol(protocol);
device_unregister(&protocol->dev);
}
@@ -157,18 +170,36 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id,
return dev;
}
+static void pnp_delist_device(struct pnp_dev *dev)
+{
+ mutex_lock(&pnp_lock);
+ list_del(&dev->global_list);
+ list_del(&dev->protocol_list);
+ mutex_unlock(&pnp_lock);
+}
+
int __pnp_add_device(struct pnp_dev *dev)
{
+ int ret;
+
pnp_fixup_device(dev);
dev->status = PNP_READY;
- spin_lock(&pnp_lock);
+
+ mutex_lock(&pnp_lock);
+
list_add_tail(&dev->global_list, &pnp_global);
list_add_tail(&dev->protocol_list, &dev->protocol->devices);
- spin_unlock(&pnp_lock);
- if (dev->protocol->can_wakeup)
+
+ mutex_unlock(&pnp_lock);
+
+ ret = device_register(&dev->dev);
+ if (ret)
+ pnp_delist_device(dev);
+ else if (dev->protocol->can_wakeup)
device_set_wakeup_capable(&dev->dev,
dev->protocol->can_wakeup(dev));
- return device_register(&dev->dev);
+
+ return ret;
}
/*
@@ -203,10 +234,7 @@ int pnp_add_device(struct pnp_dev *dev)
void __pnp_remove_device(struct pnp_dev *dev)
{
- spin_lock(&pnp_lock);
- list_del(&dev->global_list);
- list_del(&dev->protocol_list);
- spin_unlock(&pnp_lock);
+ pnp_delist_device(dev);
device_unregister(&dev->dev);
}
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index 4e57d3370368..153a493b5413 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -58,22 +58,22 @@ static const struct pnp_device_id *match_device(struct pnp_driver *drv,
int pnp_device_attach(struct pnp_dev *pnp_dev)
{
- spin_lock(&pnp_lock);
+ mutex_lock(&pnp_lock);
if (pnp_dev->status != PNP_READY) {
- spin_unlock(&pnp_lock);
+ mutex_unlock(&pnp_lock);
return -EBUSY;
}
pnp_dev->status = PNP_ATTACHED;
- spin_unlock(&pnp_lock);
+ mutex_unlock(&pnp_lock);
return 0;
}
void pnp_device_detach(struct pnp_dev *pnp_dev)
{
- spin_lock(&pnp_lock);
+ mutex_lock(&pnp_lock);
if (pnp_dev->status == PNP_ATTACHED)
pnp_dev->status = PNP_READY;
- spin_unlock(&pnp_lock);
+ mutex_unlock(&pnp_lock);
pnp_disable_dev(pnp_dev);
}
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index d2b780aade89..5153d1d69aee 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -248,6 +248,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
if (!dev)
return -ENOMEM;
+ ACPI_COMPANION_SET(&dev->dev, device);
dev->data = device;
/* .enabled means the device can decode the resources */
dev->active = device->status.enabled;
@@ -290,11 +291,9 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
return error;
}
- error = acpi_bind_one(&dev->dev, device);
-
num++;
- return error;
+ return 0;
}
static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle,

Privacy Policy