Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.27-rc3 372 lines 8.9 kB view raw
1/* 2 * Link physical devices with ACPI devices support 3 * 4 * Copyright (c) 2005 David Shaohua Li <shaohua.li@intel.com> 5 * Copyright (c) 2005 Intel Corp. 6 * 7 * This file is released under the GPLv2. 8 */ 9#include <linux/init.h> 10#include <linux/list.h> 11#include <linux/device.h> 12#include <linux/rwsem.h> 13#include <linux/acpi.h> 14 15#define ACPI_GLUE_DEBUG 0 16#if ACPI_GLUE_DEBUG 17#define DBG(x...) printk(PREFIX x) 18#else 19#define DBG(x...) do { } while(0) 20#endif 21static LIST_HEAD(bus_type_list); 22static DECLARE_RWSEM(bus_type_sem); 23 24int register_acpi_bus_type(struct acpi_bus_type *type) 25{ 26 if (acpi_disabled) 27 return -ENODEV; 28 if (type && type->bus && type->find_device) { 29 down_write(&bus_type_sem); 30 list_add_tail(&type->list, &bus_type_list); 31 up_write(&bus_type_sem); 32 printk(KERN_INFO PREFIX "bus type %s registered\n", 33 type->bus->name); 34 return 0; 35 } 36 return -ENODEV; 37} 38 39int unregister_acpi_bus_type(struct acpi_bus_type *type) 40{ 41 if (acpi_disabled) 42 return 0; 43 if (type) { 44 down_write(&bus_type_sem); 45 list_del_init(&type->list); 46 up_write(&bus_type_sem); 47 printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n", 48 type->bus->name); 49 return 0; 50 } 51 return -ENODEV; 52} 53 54static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) 55{ 56 struct acpi_bus_type *tmp, *ret = NULL; 57 58 down_read(&bus_type_sem); 59 list_for_each_entry(tmp, &bus_type_list, list) { 60 if (tmp->bus == type) { 61 ret = tmp; 62 break; 63 } 64 } 65 up_read(&bus_type_sem); 66 return ret; 67} 68 69static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle) 70{ 71 struct acpi_bus_type *tmp; 72 int ret = -ENODEV; 73 74 down_read(&bus_type_sem); 75 list_for_each_entry(tmp, &bus_type_list, list) { 76 if (tmp->find_bridge && !tmp->find_bridge(dev, handle)) { 77 ret = 0; 78 break; 79 } 80 } 81 up_read(&bus_type_sem); 82 return ret; 83} 84 85/* Get device's handler per its address under its parent */ 86struct acpi_find_child { 87 acpi_handle handle; 88 acpi_integer address; 89}; 90 91static acpi_status 92do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv) 93{ 94 acpi_status status; 95 struct acpi_device_info *info; 96 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 97 struct acpi_find_child *find = context; 98 99 status = acpi_get_object_info(handle, &buffer); 100 if (ACPI_SUCCESS(status)) { 101 info = buffer.pointer; 102 if (info->address == find->address) 103 find->handle = handle; 104 kfree(buffer.pointer); 105 } 106 return AE_OK; 107} 108 109acpi_handle acpi_get_child(acpi_handle parent, acpi_integer address) 110{ 111 struct acpi_find_child find = { NULL, address }; 112 113 if (!parent) 114 return NULL; 115 acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 116 1, do_acpi_find_child, &find, NULL); 117 return find.handle; 118} 119 120EXPORT_SYMBOL(acpi_get_child); 121 122/* Link ACPI devices with physical devices */ 123static void acpi_glue_data_handler(acpi_handle handle, 124 u32 function, void *context) 125{ 126 /* we provide an empty handler */ 127} 128 129/* Note: a success call will increase reference count by one */ 130struct device *acpi_get_physical_device(acpi_handle handle) 131{ 132 acpi_status status; 133 struct device *dev; 134 135 status = acpi_get_data(handle, acpi_glue_data_handler, (void **)&dev); 136 if (ACPI_SUCCESS(status)) 137 return get_device(dev); 138 return NULL; 139} 140 141EXPORT_SYMBOL(acpi_get_physical_device); 142 143static int acpi_bind_one(struct device *dev, acpi_handle handle) 144{ 145 struct acpi_device *acpi_dev; 146 acpi_status status; 147 148 if (dev->archdata.acpi_handle) { 149 dev_warn(dev, "Drivers changed 'acpi_handle'\n"); 150 return -EINVAL; 151 } 152 get_device(dev); 153 status = acpi_attach_data(handle, acpi_glue_data_handler, dev); 154 if (ACPI_FAILURE(status)) { 155 put_device(dev); 156 return -EINVAL; 157 } 158 dev->archdata.acpi_handle = handle; 159 160 status = acpi_bus_get_device(handle, &acpi_dev); 161 if (!ACPI_FAILURE(status)) { 162 int ret; 163 164 ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj, 165 "firmware_node"); 166 ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, 167 "physical_node"); 168 if (acpi_dev->wakeup.flags.valid) 169 device_set_wakeup_capable(dev, true); 170 } 171 172 return 0; 173} 174 175static int acpi_unbind_one(struct device *dev) 176{ 177 if (!dev->archdata.acpi_handle) 178 return 0; 179 if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) { 180 struct acpi_device *acpi_dev; 181 182 /* acpi_get_physical_device increase refcnt by one */ 183 put_device(dev); 184 185 if (!acpi_bus_get_device(dev->archdata.acpi_handle, 186 &acpi_dev)) { 187 sysfs_remove_link(&dev->kobj, "firmware_node"); 188 sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node"); 189 } 190 191 acpi_detach_data(dev->archdata.acpi_handle, 192 acpi_glue_data_handler); 193 dev->archdata.acpi_handle = NULL; 194 /* acpi_bind_one increase refcnt by one */ 195 put_device(dev); 196 } else { 197 dev_err(dev, "Oops, 'acpi_handle' corrupt\n"); 198 } 199 return 0; 200} 201 202static int acpi_platform_notify(struct device *dev) 203{ 204 struct acpi_bus_type *type; 205 acpi_handle handle; 206 int ret = -EINVAL; 207 208 if (!dev->bus || !dev->parent) { 209 /* bridge devices genernally haven't bus or parent */ 210 ret = acpi_find_bridge_device(dev, &handle); 211 goto end; 212 } 213 type = acpi_get_bus_type(dev->bus); 214 if (!type) { 215 DBG("No ACPI bus support for %s\n", dev->bus_id); 216 ret = -EINVAL; 217 goto end; 218 } 219 if ((ret = type->find_device(dev, &handle)) != 0) 220 DBG("Can't get handler for %s\n", dev->bus_id); 221 end: 222 if (!ret) 223 acpi_bind_one(dev, handle); 224 225#if ACPI_GLUE_DEBUG 226 if (!ret) { 227 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 228 229 acpi_get_name(dev->archdata.acpi_handle, 230 ACPI_FULL_PATHNAME, &buffer); 231 DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer); 232 kfree(buffer.pointer); 233 } else 234 DBG("Device %s -> No ACPI support\n", dev->bus_id); 235#endif 236 237 return ret; 238} 239 240static int acpi_platform_notify_remove(struct device *dev) 241{ 242 acpi_unbind_one(dev); 243 return 0; 244} 245 246static int __init init_acpi_device_notify(void) 247{ 248 if (acpi_disabled) 249 return 0; 250 if (platform_notify || platform_notify_remove) { 251 printk(KERN_ERR PREFIX "Can't use platform_notify\n"); 252 return 0; 253 } 254 platform_notify = acpi_platform_notify; 255 platform_notify_remove = acpi_platform_notify_remove; 256 return 0; 257} 258 259arch_initcall(init_acpi_device_notify); 260 261 262#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) 263 264#ifdef CONFIG_PM 265static u32 rtc_handler(void *context) 266{ 267 acpi_clear_event(ACPI_EVENT_RTC); 268 acpi_disable_event(ACPI_EVENT_RTC, 0); 269 return ACPI_INTERRUPT_HANDLED; 270} 271 272static inline void rtc_wake_setup(void) 273{ 274 acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); 275 /* 276 * After the RTC handler is installed, the Fixed_RTC event should 277 * be disabled. Only when the RTC alarm is set will it be enabled. 278 */ 279 acpi_clear_event(ACPI_EVENT_RTC); 280 acpi_disable_event(ACPI_EVENT_RTC, 0); 281} 282 283static void rtc_wake_on(struct device *dev) 284{ 285 acpi_clear_event(ACPI_EVENT_RTC); 286 acpi_enable_event(ACPI_EVENT_RTC, 0); 287} 288 289static void rtc_wake_off(struct device *dev) 290{ 291 acpi_disable_event(ACPI_EVENT_RTC, 0); 292} 293#else 294#define rtc_wake_setup() do{}while(0) 295#define rtc_wake_on NULL 296#define rtc_wake_off NULL 297#endif 298 299/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find 300 * its device node and pass extra config data. This helps its driver use 301 * capabilities that the now-obsolete mc146818 didn't have, and informs it 302 * that this board's RTC is wakeup-capable (per ACPI spec). 303 */ 304#include <linux/mc146818rtc.h> 305 306static struct cmos_rtc_board_info rtc_info; 307 308 309/* PNP devices are registered in a subsys_initcall(); 310 * ACPI specifies the PNP IDs to use. 311 */ 312#include <linux/pnp.h> 313 314static int __init pnp_match(struct device *dev, void *data) 315{ 316 static const char *ids[] = { "PNP0b00", "PNP0b01", "PNP0b02", }; 317 struct pnp_dev *pnp = to_pnp_dev(dev); 318 int i; 319 320 for (i = 0; i < ARRAY_SIZE(ids); i++) { 321 if (compare_pnp_id(pnp->id, ids[i]) != 0) 322 return 1; 323 } 324 return 0; 325} 326 327static struct device *__init get_rtc_dev(void) 328{ 329 return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match); 330} 331 332static int __init acpi_rtc_init(void) 333{ 334 struct device *dev = get_rtc_dev(); 335 336 if (acpi_disabled) 337 return 0; 338 339 if (dev) { 340 rtc_wake_setup(); 341 rtc_info.wake_on = rtc_wake_on; 342 rtc_info.wake_off = rtc_wake_off; 343 344 /* workaround bug in some ACPI tables */ 345 if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) { 346 DBG("bogus FADT month_alarm\n"); 347 acpi_gbl_FADT.month_alarm = 0; 348 } 349 350 rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm; 351 rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm; 352 rtc_info.rtc_century = acpi_gbl_FADT.century; 353 354 /* NOTE: S4_RTC_WAKE is NOT currently useful to Linux */ 355 if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE) 356 printk(PREFIX "RTC can wake from S4\n"); 357 358 359 dev->platform_data = &rtc_info; 360 361 /* RTC always wakes from S1/S2/S3, and often S4/STD */ 362 device_init_wakeup(dev, 1); 363 364 put_device(dev); 365 } else 366 DBG("RTC unavailable?\n"); 367 return 0; 368} 369/* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */ 370fs_initcall(acpi_rtc_init); 371 372#endif