0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/export.h>
0010 #include <linux/acpi.h>
0011 #include <linux/pnp.h>
0012 #include <linux/slab.h>
0013 #include <linux/mod_devicetable.h>
0014
0015 #include "../base.h"
0016 #include "pnpacpi.h"
0017
0018 static int num;
0019
0020
0021
0022
0023 #define TEST_HEX(c) \
0024 if (!(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'F'))) \
0025 return 0
0026 #define TEST_ALPHA(c) \
0027 if (!('A' <= (c) && (c) <= 'Z')) \
0028 return 0
0029 static int __init ispnpidacpi(const char *id)
0030 {
0031 TEST_ALPHA(id[0]);
0032 TEST_ALPHA(id[1]);
0033 TEST_ALPHA(id[2]);
0034 TEST_HEX(id[3]);
0035 TEST_HEX(id[4]);
0036 TEST_HEX(id[5]);
0037 TEST_HEX(id[6]);
0038 if (id[7] != '\0')
0039 return 0;
0040 return 1;
0041 }
0042
0043 static int pnpacpi_get_resources(struct pnp_dev *dev)
0044 {
0045 pnp_dbg(&dev->dev, "get resources\n");
0046 return pnpacpi_parse_allocated_resource(dev);
0047 }
0048
0049 static int pnpacpi_set_resources(struct pnp_dev *dev)
0050 {
0051 struct acpi_device *acpi_dev;
0052 acpi_handle handle;
0053 int ret = 0;
0054
0055 pnp_dbg(&dev->dev, "set resources\n");
0056
0057 acpi_dev = ACPI_COMPANION(&dev->dev);
0058 if (!acpi_dev) {
0059 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
0060 return -ENODEV;
0061 }
0062
0063 if (WARN_ON_ONCE(acpi_dev != dev->data))
0064 dev->data = acpi_dev;
0065
0066 handle = acpi_dev->handle;
0067 if (acpi_has_method(handle, METHOD_NAME__SRS)) {
0068 struct acpi_buffer buffer;
0069
0070 ret = pnpacpi_build_resource_template(dev, &buffer);
0071 if (ret)
0072 return ret;
0073
0074 ret = pnpacpi_encode_resources(dev, &buffer);
0075 if (!ret) {
0076 acpi_status status;
0077
0078 status = acpi_set_current_resources(handle, &buffer);
0079 if (ACPI_FAILURE(status))
0080 ret = -EIO;
0081 }
0082 kfree(buffer.pointer);
0083 }
0084 if (!ret && acpi_device_power_manageable(acpi_dev))
0085 ret = acpi_device_set_power(acpi_dev, ACPI_STATE_D0);
0086
0087 return ret;
0088 }
0089
0090 static int pnpacpi_disable_resources(struct pnp_dev *dev)
0091 {
0092 struct acpi_device *acpi_dev;
0093 acpi_status status;
0094
0095 dev_dbg(&dev->dev, "disable resources\n");
0096
0097 acpi_dev = ACPI_COMPANION(&dev->dev);
0098 if (!acpi_dev) {
0099 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
0100 return 0;
0101 }
0102
0103
0104 if (acpi_device_power_manageable(acpi_dev))
0105 acpi_device_set_power(acpi_dev, ACPI_STATE_D3_COLD);
0106
0107
0108 status = acpi_evaluate_object(acpi_dev->handle, "_DIS", NULL, NULL);
0109 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
0110 return -ENODEV;
0111
0112 return 0;
0113 }
0114
0115 #ifdef CONFIG_ACPI_SLEEP
0116 static bool pnpacpi_can_wakeup(struct pnp_dev *dev)
0117 {
0118 struct acpi_device *acpi_dev = ACPI_COMPANION(&dev->dev);
0119
0120 if (!acpi_dev) {
0121 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
0122 return false;
0123 }
0124
0125 return acpi_bus_can_wakeup(acpi_dev->handle);
0126 }
0127
0128 static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
0129 {
0130 struct acpi_device *acpi_dev = ACPI_COMPANION(&dev->dev);
0131 int error = 0;
0132
0133 if (!acpi_dev) {
0134 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
0135 return 0;
0136 }
0137
0138 if (device_can_wakeup(&dev->dev)) {
0139 error = acpi_pm_set_device_wakeup(&dev->dev,
0140 device_may_wakeup(&dev->dev));
0141 if (error)
0142 return error;
0143 }
0144
0145 if (acpi_device_power_manageable(acpi_dev)) {
0146 int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL,
0147 ACPI_STATE_D3_COLD);
0148 if (power_state < 0)
0149 power_state = (state.event == PM_EVENT_ON) ?
0150 ACPI_STATE_D0 : ACPI_STATE_D3_COLD;
0151
0152
0153
0154
0155
0156
0157
0158 error = acpi_device_set_power(acpi_dev, power_state);
0159 }
0160
0161 return error;
0162 }
0163
0164 static int pnpacpi_resume(struct pnp_dev *dev)
0165 {
0166 struct acpi_device *acpi_dev = ACPI_COMPANION(&dev->dev);
0167 int error = 0;
0168
0169 if (!acpi_dev) {
0170 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
0171 return -ENODEV;
0172 }
0173
0174 if (device_may_wakeup(&dev->dev))
0175 acpi_pm_set_device_wakeup(&dev->dev, false);
0176
0177 if (acpi_device_power_manageable(acpi_dev))
0178 error = acpi_device_set_power(acpi_dev, ACPI_STATE_D0);
0179
0180 return error;
0181 }
0182 #endif
0183
0184 struct pnp_protocol pnpacpi_protocol = {
0185 .name = "Plug and Play ACPI",
0186 .get = pnpacpi_get_resources,
0187 .set = pnpacpi_set_resources,
0188 .disable = pnpacpi_disable_resources,
0189 #ifdef CONFIG_ACPI_SLEEP
0190 .can_wakeup = pnpacpi_can_wakeup,
0191 .suspend = pnpacpi_suspend,
0192 .resume = pnpacpi_resume,
0193 #endif
0194 };
0195 EXPORT_SYMBOL(pnpacpi_protocol);
0196
0197 static const char *__init pnpacpi_get_id(struct acpi_device *device)
0198 {
0199 struct acpi_hardware_id *id;
0200
0201 list_for_each_entry(id, &device->pnp.ids, list) {
0202 if (ispnpidacpi(id->id))
0203 return id->id;
0204 }
0205
0206 return NULL;
0207 }
0208
0209 static int __init pnpacpi_add_device(struct acpi_device *device)
0210 {
0211 struct pnp_dev *dev;
0212 const char *pnpid;
0213 struct acpi_hardware_id *id;
0214 int error;
0215
0216
0217 if (device->physical_node_count)
0218 return 0;
0219
0220
0221
0222
0223
0224 if (!acpi_has_method(device->handle, "_CRS"))
0225 return 0;
0226
0227 pnpid = pnpacpi_get_id(device);
0228 if (!pnpid)
0229 return 0;
0230
0231 if (!device->status.present)
0232 return 0;
0233
0234 dev = pnp_alloc_dev(&pnpacpi_protocol, num, pnpid);
0235 if (!dev)
0236 return -ENOMEM;
0237
0238 ACPI_COMPANION_SET(&dev->dev, device);
0239 dev->data = device;
0240
0241 dev->active = device->status.enabled;
0242 if (acpi_has_method(device->handle, "_SRS"))
0243 dev->capabilities |= PNP_CONFIGURABLE;
0244 dev->capabilities |= PNP_READ;
0245 if (device->flags.dynamic_status && (dev->capabilities & PNP_CONFIGURABLE))
0246 dev->capabilities |= PNP_WRITE;
0247 if (device->flags.removable)
0248 dev->capabilities |= PNP_REMOVABLE;
0249 if (acpi_has_method(device->handle, "_DIS"))
0250 dev->capabilities |= PNP_DISABLE;
0251
0252 if (strlen(acpi_device_name(device)))
0253 strncpy(dev->name, acpi_device_name(device), sizeof(dev->name));
0254 else
0255 strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name));
0256
0257 if (dev->active)
0258 pnpacpi_parse_allocated_resource(dev);
0259
0260 if (dev->capabilities & PNP_CONFIGURABLE)
0261 pnpacpi_parse_resource_option_data(dev);
0262
0263 list_for_each_entry(id, &device->pnp.ids, list) {
0264 if (!strcmp(id->id, pnpid))
0265 continue;
0266 if (!ispnpidacpi(id->id))
0267 continue;
0268 pnp_add_id(dev, id->id);
0269 }
0270
0271
0272 if (!dev->active)
0273 pnp_init_resources(dev);
0274
0275 error = pnp_add_device(dev);
0276 if (error) {
0277 put_device(&dev->dev);
0278 return error;
0279 }
0280
0281 num++;
0282
0283 return 0;
0284 }
0285
0286 static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle,
0287 u32 lvl, void *context,
0288 void **rv)
0289 {
0290 struct acpi_device *device = acpi_fetch_acpi_dev(handle);
0291
0292 if (!device)
0293 return AE_CTRL_DEPTH;
0294 if (acpi_is_pnp_device(device))
0295 pnpacpi_add_device(device);
0296 return AE_OK;
0297 }
0298
0299 int pnpacpi_disabled __initdata;
0300 static int __init pnpacpi_init(void)
0301 {
0302 if (acpi_disabled || pnpacpi_disabled) {
0303 printk(KERN_INFO "pnp: PnP ACPI: disabled\n");
0304 return 0;
0305 }
0306 printk(KERN_INFO "pnp: PnP ACPI init\n");
0307 pnp_register_protocol(&pnpacpi_protocol);
0308 acpi_get_devices(NULL, pnpacpi_add_device_handler, NULL, NULL);
0309 printk(KERN_INFO "pnp: PnP ACPI: found %d devices\n", num);
0310 pnp_platform_devices = 1;
0311 return 0;
0312 }
0313
0314 fs_initcall(pnpacpi_init);
0315
0316 static int __init pnpacpi_setup(char *str)
0317 {
0318 if (str == NULL)
0319 return 1;
0320 if (!strncmp(str, "off", 3))
0321 pnpacpi_disabled = 1;
0322 return 1;
0323 }
0324
0325 __setup("pnpacpi=", pnpacpi_setup);