aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/pnpacpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pnp/pnpacpi')
-rw-r--r--drivers/pnp/pnpacpi/core.c124
1 files changed, 92 insertions, 32 deletions
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index dc4e32e031e9..ca84d5099ce7 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -28,7 +28,7 @@
28#include "../base.h" 28#include "../base.h"
29#include "pnpacpi.h" 29#include "pnpacpi.h"
30 30
31static int num = 0; 31static int num;
32 32
33/* We need only to blacklist devices that have already an acpi driver that 33/* We need only to blacklist devices that have already an acpi driver that
34 * can't use pnp layer. We don't need to blacklist device that are directly 34 * can't use pnp layer. We don't need to blacklist device that are directly
@@ -59,7 +59,7 @@ static inline int __init is_exclusive_device(struct acpi_device *dev)
59#define TEST_ALPHA(c) \ 59#define TEST_ALPHA(c) \
60 if (!('@' <= (c) || (c) <= 'Z')) \ 60 if (!('@' <= (c) || (c) <= 'Z')) \
61 return 0 61 return 0
62static int __init ispnpidacpi(char *id) 62static int __init ispnpidacpi(const char *id)
63{ 63{
64 TEST_ALPHA(id[0]); 64 TEST_ALPHA(id[0]);
65 TEST_ALPHA(id[1]); 65 TEST_ALPHA(id[1]);
@@ -81,12 +81,19 @@ static int pnpacpi_get_resources(struct pnp_dev *dev)
81 81
82static int pnpacpi_set_resources(struct pnp_dev *dev) 82static int pnpacpi_set_resources(struct pnp_dev *dev)
83{ 83{
84 struct acpi_device *acpi_dev = dev->data; 84 struct acpi_device *acpi_dev;
85 acpi_handle handle = acpi_dev->handle; 85 acpi_handle handle;
86 struct acpi_buffer buffer; 86 struct acpi_buffer buffer;
87 int ret; 87 int ret;
88 88
89 pnp_dbg(&dev->dev, "set resources\n"); 89 pnp_dbg(&dev->dev, "set resources\n");
90
91 handle = DEVICE_ACPI_HANDLE(&dev->dev);
92 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) {
93 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
94 return -ENODEV;
95 }
96
90 ret = pnpacpi_build_resource_template(dev, &buffer); 97 ret = pnpacpi_build_resource_template(dev, &buffer);
91 if (ret) 98 if (ret)
92 return ret; 99 return ret;
@@ -105,12 +112,18 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
105 112
106static int pnpacpi_disable_resources(struct pnp_dev *dev) 113static int pnpacpi_disable_resources(struct pnp_dev *dev)
107{ 114{
108 struct acpi_device *acpi_dev = dev->data; 115 struct acpi_device *acpi_dev;
109 acpi_handle handle = acpi_dev->handle; 116 acpi_handle handle;
110 int ret; 117 int ret;
111 118
112 dev_dbg(&dev->dev, "disable resources\n"); 119 dev_dbg(&dev->dev, "disable resources\n");
113 120
121 handle = DEVICE_ACPI_HANDLE(&dev->dev);
122 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) {
123 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
124 return 0;
125 }
126
114 /* acpi_unregister_gsi(pnp_irq(dev, 0)); */ 127 /* acpi_unregister_gsi(pnp_irq(dev, 0)); */
115 ret = 0; 128 ret = 0;
116 if (acpi_bus_power_manageable(handle)) 129 if (acpi_bus_power_manageable(handle))
@@ -124,46 +137,74 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
124#ifdef CONFIG_ACPI_SLEEP 137#ifdef CONFIG_ACPI_SLEEP
125static bool pnpacpi_can_wakeup(struct pnp_dev *dev) 138static bool pnpacpi_can_wakeup(struct pnp_dev *dev)
126{ 139{
127 struct acpi_device *acpi_dev = dev->data; 140 struct acpi_device *acpi_dev;
128 acpi_handle handle = acpi_dev->handle; 141 acpi_handle handle;
142
143 handle = DEVICE_ACPI_HANDLE(&dev->dev);
144 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) {
145 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
146 return false;
147 }
129 148
130 return acpi_bus_can_wakeup(handle); 149 return acpi_bus_can_wakeup(handle);
131} 150}
132 151
133static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) 152static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
134{ 153{
135 struct acpi_device *acpi_dev = dev->data; 154 struct acpi_device *acpi_dev;
136 acpi_handle handle = acpi_dev->handle; 155 acpi_handle handle;
137 int power_state; 156 int error = 0;
157
158 handle = DEVICE_ACPI_HANDLE(&dev->dev);
159 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) {
160 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
161 return 0;
162 }
138 163
139 if (device_can_wakeup(&dev->dev)) { 164 if (device_can_wakeup(&dev->dev)) {
140 int rc = acpi_pm_device_sleep_wake(&dev->dev, 165 error = acpi_pm_device_sleep_wake(&dev->dev,
141 device_may_wakeup(&dev->dev)); 166 device_may_wakeup(&dev->dev));
167 if (error)
168 return error;
169 }
170
171 if (acpi_bus_power_manageable(handle)) {
172 int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL);
142 173
143 if (rc) 174 if (power_state < 0)
144 return rc; 175 power_state = (state.event == PM_EVENT_ON) ?
176 ACPI_STATE_D0 : ACPI_STATE_D3;
177
178 /*
179 * acpi_bus_set_power() often fails (keyboard port can't be
180 * powered-down?), and in any case, our return value is ignored
181 * by pnp_bus_suspend(). Hence we don't revert the wakeup
182 * setting if the set_power fails.
183 */
184 error = acpi_bus_set_power(handle, power_state);
145 } 185 }
146 power_state = acpi_pm_device_sleep_state(&dev->dev, NULL); 186
147 if (power_state < 0) 187 return error;
148 power_state = (state.event == PM_EVENT_ON) ?
149 ACPI_STATE_D0 : ACPI_STATE_D3;
150
151 /* acpi_bus_set_power() often fails (keyboard port can't be
152 * powered-down?), and in any case, our return value is ignored
153 * by pnp_bus_suspend(). Hence we don't revert the wakeup
154 * setting if the set_power fails.
155 */
156 return acpi_bus_set_power(handle, power_state);
157} 188}
158 189
159static int pnpacpi_resume(struct pnp_dev *dev) 190static int pnpacpi_resume(struct pnp_dev *dev)
160{ 191{
161 struct acpi_device *acpi_dev = dev->data; 192 struct acpi_device *acpi_dev;
162 acpi_handle handle = acpi_dev->handle; 193 acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
194 int error = 0;
195
196 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) {
197 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
198 return -ENODEV;
199 }
163 200
164 if (device_may_wakeup(&dev->dev)) 201 if (device_may_wakeup(&dev->dev))
165 acpi_pm_device_sleep_wake(&dev->dev, false); 202 acpi_pm_device_sleep_wake(&dev->dev, false);
166 return acpi_bus_set_power(handle, ACPI_STATE_D0); 203
204 if (acpi_bus_power_manageable(handle))
205 error = acpi_bus_set_power(handle, ACPI_STATE_D0);
206
207 return error;
167} 208}
168#endif 209#endif
169 210
@@ -180,11 +221,24 @@ struct pnp_protocol pnpacpi_protocol = {
180}; 221};
181EXPORT_SYMBOL(pnpacpi_protocol); 222EXPORT_SYMBOL(pnpacpi_protocol);
182 223
224static char *__init pnpacpi_get_id(struct acpi_device *device)
225{
226 struct acpi_hardware_id *id;
227
228 list_for_each_entry(id, &device->pnp.ids, list) {
229 if (ispnpidacpi(id->id))
230 return id->id;
231 }
232
233 return NULL;
234}
235
183static int __init pnpacpi_add_device(struct acpi_device *device) 236static int __init pnpacpi_add_device(struct acpi_device *device)
184{ 237{
185 acpi_handle temp = NULL; 238 acpi_handle temp = NULL;
186 acpi_status status; 239 acpi_status status;
187 struct pnp_dev *dev; 240 struct pnp_dev *dev;
241 char *pnpid;
188 struct acpi_hardware_id *id; 242 struct acpi_hardware_id *id;
189 243
190 /* 244 /*
@@ -192,11 +246,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
192 * driver should not be loaded. 246 * driver should not be loaded.
193 */ 247 */
194 status = acpi_get_handle(device->handle, "_CRS", &temp); 248 status = acpi_get_handle(device->handle, "_CRS", &temp);
195 if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) || 249 if (ACPI_FAILURE(status))
196 is_exclusive_device(device) || (!device->status.present)) 250 return 0;
251
252 pnpid = pnpacpi_get_id(device);
253 if (!pnpid)
254 return 0;
255
256 if (is_exclusive_device(device) || !device->status.present)
197 return 0; 257 return 0;
198 258
199 dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device)); 259 dev = pnp_alloc_dev(&pnpacpi_protocol, num, pnpid);
200 if (!dev) 260 if (!dev)
201 return -ENOMEM; 261 return -ENOMEM;
202 262
@@ -227,7 +287,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
227 pnpacpi_parse_resource_option_data(dev); 287 pnpacpi_parse_resource_option_data(dev);
228 288
229 list_for_each_entry(id, &device->pnp.ids, list) { 289 list_for_each_entry(id, &device->pnp.ids, list) {
230 if (!strcmp(id->id, acpi_device_hid(device))) 290 if (!strcmp(id->id, pnpid))
231 continue; 291 continue;
232 if (!ispnpidacpi(id->id)) 292 if (!ispnpidacpi(id->id))
233 continue; 293 continue;