Blame view
drivers/acpi/acpi_memhotplug.c
14.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/* * Copyright (C) 2004 Intel Corporation <naveen.b.s@intel.com> * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * ACPI based HotPlug driver that supports Memory Hotplug |
c7060d9e9 trivial: Fix miss... |
23 |
* This driver fields notifications from firmware for memory add |
1da177e4c Linux-2.6.12-rc2 |
24 25 26 27 28 29 30 31 32 |
* and remove operations and alerts the VM of the affected memory * ranges. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> #include <linux/memory_hotplug.h> |
5a0e3ad6a include cleanup: ... |
33 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
34 |
#include <acpi/acpi_drivers.h> |
1da177e4c Linux-2.6.12-rc2 |
35 36 |
#define ACPI_MEMORY_DEVICE_CLASS "memory" #define ACPI_MEMORY_DEVICE_HID "PNP0C80" |
1da177e4c Linux-2.6.12-rc2 |
37 38 39 |
#define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device" #define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT |
aa7b2b2e9 ACPI: Don't treat... |
40 41 |
#undef PREFIX #define PREFIX "ACPI:memory_hp:" |
f52fd66d2 ACPI: clean up AC... |
42 43 |
ACPI_MODULE_NAME("acpi_memhotplug"); MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>"); |
7cda93e00 ACPI: delete extr... |
44 |
MODULE_DESCRIPTION("Hotplug Mem Driver"); |
1da177e4c Linux-2.6.12-rc2 |
45 |
MODULE_LICENSE("GPL"); |
1da177e4c Linux-2.6.12-rc2 |
46 47 48 49 |
/* Memory Device States */ #define MEMORY_INVALID_STATE 0 #define MEMORY_POWER_ON_STATE 1 #define MEMORY_POWER_OFF_STATE 2 |
4be44fcd3 [ACPI] Lindent al... |
50 51 |
static int acpi_memory_device_add(struct acpi_device *device); static int acpi_memory_device_remove(struct acpi_device *device, int type); |
1da177e4c Linux-2.6.12-rc2 |
52 |
|
1ba90e3a8 ACPI: autoload mo... |
53 54 55 56 57 |
static const struct acpi_device_id memory_device_ids[] = { {ACPI_MEMORY_DEVICE_HID, 0}, {"", 0}, }; MODULE_DEVICE_TABLE(acpi, memory_device_ids); |
1da177e4c Linux-2.6.12-rc2 |
58 |
static struct acpi_driver acpi_memory_device_driver = { |
c2b6705b7 ACPI: fix acpi_dr... |
59 |
.name = "acpi_memhotplug", |
4be44fcd3 [ACPI] Lindent al... |
60 |
.class = ACPI_MEMORY_DEVICE_CLASS, |
1ba90e3a8 ACPI: autoload mo... |
61 |
.ids = memory_device_ids, |
4be44fcd3 [ACPI] Lindent al... |
62 63 64 65 |
.ops = { .add = acpi_memory_device_add, .remove = acpi_memory_device_remove, }, |
1da177e4c Linux-2.6.12-rc2 |
66 |
}; |
9ac023989 [PATCH] acpi memo... |
67 68 69 70 71 72 73 74 |
struct acpi_memory_info { struct list_head list; u64 start_addr; /* Memory Range start physical addr */ u64 length; /* Memory Range length */ unsigned short caching; /* memory cache attribute */ unsigned short write_protect; /* memory read/write attribute */ unsigned int enabled:1; }; |
1da177e4c Linux-2.6.12-rc2 |
75 |
struct acpi_memory_device { |
3b74863df ACPI: acpi_memhot... |
76 |
struct acpi_device * device; |
4be44fcd3 [ACPI] Lindent al... |
77 |
unsigned int state; /* State of the memory device */ |
9ac023989 [PATCH] acpi memo... |
78 |
struct list_head res_list; |
1da177e4c Linux-2.6.12-rc2 |
79 |
}; |
887b95931 [PATCH] acpi memo... |
80 |
static int acpi_hotmem_initialized; |
9ac023989 [PATCH] acpi memo... |
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
static acpi_status acpi_memory_get_resource(struct acpi_resource *resource, void *context) { struct acpi_memory_device *mem_device = context; struct acpi_resource_address64 address64; struct acpi_memory_info *info, *new; acpi_status status; status = acpi_resource_to_address64(resource, &address64); if (ACPI_FAILURE(status) || (address64.resource_type != ACPI_MEMORY_RANGE)) return AE_OK; list_for_each_entry(info, &mem_device->res_list, list) { /* Can we combine the resource range information? */ if ((info->caching == address64.info.mem.caching) && (info->write_protect == address64.info.mem.write_protect) && (info->start_addr + info->length == address64.minimum)) { info->length += address64.address_length; return AE_OK; } } new = kzalloc(sizeof(struct acpi_memory_info), GFP_KERNEL); if (!new) return AE_ERROR; INIT_LIST_HEAD(&new->list); new->caching = address64.info.mem.caching; new->write_protect = address64.info.mem.write_protect; new->start_addr = address64.minimum; new->length = address64.address_length; list_add_tail(&new->list, &mem_device->res_list); return AE_OK; } |
1da177e4c Linux-2.6.12-rc2 |
117 118 119 120 |
static int acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) { acpi_status status; |
9ac023989 [PATCH] acpi memo... |
121 |
struct acpi_memory_info *info, *n; |
1da177e4c Linux-2.6.12-rc2 |
122 |
|
1da177e4c Linux-2.6.12-rc2 |
123 |
|
5d2870faa [PATCH] memory ho... |
124 125 |
if (!list_empty(&mem_device->res_list)) return 0; |
b86327852 ACPI: acpi_memhot... |
126 |
status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS, |
9ac023989 [PATCH] acpi memo... |
127 128 129 130 |
acpi_memory_get_resource, mem_device); if (ACPI_FAILURE(status)) { list_for_each_entry_safe(info, n, &mem_device->res_list, list) kfree(info); |
5d2870faa [PATCH] memory ho... |
131 |
INIT_LIST_HEAD(&mem_device->res_list); |
d550d98d3 ACPI: delete trac... |
132 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
133 |
} |
d550d98d3 ACPI: delete trac... |
134 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
135 136 137 138 |
} static int acpi_memory_get_device(acpi_handle handle, |
4be44fcd3 [ACPI] Lindent al... |
139 |
struct acpi_memory_device **mem_device) |
1da177e4c Linux-2.6.12-rc2 |
140 141 142 143 144 |
{ acpi_status status; acpi_handle phandle; struct acpi_device *device = NULL; struct acpi_device *pdevice = NULL; |
aa7b2b2e9 ACPI: Don't treat... |
145 |
int result; |
1da177e4c Linux-2.6.12-rc2 |
146 |
|
1da177e4c Linux-2.6.12-rc2 |
147 148 149 150 151 152 |
if (!acpi_bus_get_device(handle, &device) && device) goto end; status = acpi_get_parent(handle, &phandle); if (ACPI_FAILURE(status)) { |
a6fc67202 ACPI: Enable ACPI... |
153 |
ACPI_EXCEPTION((AE_INFO, status, "Cannot find acpi parent")); |
d550d98d3 ACPI: delete trac... |
154 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
155 156 157 |
} /* Get the parent device */ |
aa7b2b2e9 ACPI: Don't treat... |
158 159 160 |
result = acpi_bus_get_device(phandle, &pdevice); if (result) { printk(KERN_WARNING PREFIX "Cannot get acpi bus device"); |
d550d98d3 ACPI: delete trac... |
161 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
162 163 164 165 166 167 |
} /* * Now add the notified device. This creates the acpi_device * and invokes .add function */ |
aa7b2b2e9 ACPI: Don't treat... |
168 169 170 |
result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); if (result) { printk(KERN_WARNING PREFIX "Cannot add acpi bus"); |
d550d98d3 ACPI: delete trac... |
171 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
172 |
} |
4be44fcd3 [ACPI] Lindent al... |
173 |
end: |
1da177e4c Linux-2.6.12-rc2 |
174 175 |
*mem_device = acpi_driver_data(device); if (!(*mem_device)) { |
4be44fcd3 [ACPI] Lindent al... |
176 177 |
printk(KERN_ERR " driver data not found"); |
d550d98d3 ACPI: delete trac... |
178 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
179 |
} |
d550d98d3 ACPI: delete trac... |
180 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
181 |
} |
4be44fcd3 [ACPI] Lindent al... |
182 |
static int acpi_memory_check_device(struct acpi_memory_device *mem_device) |
1da177e4c Linux-2.6.12-rc2 |
183 |
{ |
27663c585 ACPI: Change acpi... |
184 |
unsigned long long current_status; |
1da177e4c Linux-2.6.12-rc2 |
185 186 |
/* Get device present/absent information from the _STA */ |
b86327852 ACPI: acpi_memhot... |
187 |
if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, "_STA", |
4be44fcd3 [ACPI] Lindent al... |
188 |
NULL, ¤t_status))) |
d550d98d3 ACPI: delete trac... |
189 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
190 191 192 193 |
/* * Check for device status. Device should be * present/enabled/functioning. */ |
a0bd4ac49 ACPI: Remove dupl... |
194 195 196 |
if (!((current_status & ACPI_STA_DEVICE_PRESENT) && (current_status & ACPI_STA_DEVICE_ENABLED) && (current_status & ACPI_STA_DEVICE_FUNCTIONING))) |
d550d98d3 ACPI: delete trac... |
197 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
198 |
|
d550d98d3 ACPI: delete trac... |
199 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
200 |
} |
4be44fcd3 [ACPI] Lindent al... |
201 |
static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) |
1da177e4c Linux-2.6.12-rc2 |
202 |
{ |
9ac023989 [PATCH] acpi memo... |
203 204 |
int result, num_enabled = 0; struct acpi_memory_info *info; |
1e3590e2e [PATCH] pgdat all... |
205 |
int node; |
1da177e4c Linux-2.6.12-rc2 |
206 |
|
1da177e4c Linux-2.6.12-rc2 |
207 208 209 210 |
/* Get the range from the _CRS */ result = acpi_memory_get_device_resources(mem_device); if (result) { |
6468463ab ACPI: un-export A... |
211 212 |
printk(KERN_ERR PREFIX "get_device_resources failed "); |
1da177e4c Linux-2.6.12-rc2 |
213 214 215 |
mem_device->state = MEMORY_INVALID_STATE; return result; } |
b86327852 ACPI: acpi_memhot... |
216 |
node = acpi_get_node(mem_device->device->handle); |
1da177e4c Linux-2.6.12-rc2 |
217 218 219 |
/* * Tell the VM there is more memory here... * Note: Assume that this function returns zero on success |
9ac023989 [PATCH] acpi memo... |
220 221 |
* We don't have memory-hot-add rollback function,now. * (i.e. memory-hot-remove function) |
1da177e4c Linux-2.6.12-rc2 |
222 |
*/ |
9ac023989 [PATCH] acpi memo... |
223 |
list_for_each_entry(info, &mem_device->res_list, list) { |
fa25d8d6d [PATCH] memory ho... |
224 |
if (info->enabled) { /* just sanity check...*/ |
dd56a8e36 [PATCH] Catch not... |
225 226 227 |
num_enabled++; continue; } |
5d2619fca ACPI: Ingore the ... |
228 229 230 231 232 233 |
/* * If the memory block size is zero, please ignore it. * Don't try to do the following memory hotplug flowchart. */ if (!info->length) continue; |
8c2676a58 [PATCH] hot-add-m... |
234 235 |
if (node < 0) node = memory_add_physaddr_to_nid(info->start_addr); |
bc02af93d [PATCH] pgdat all... |
236 |
result = add_memory(node, info->start_addr, info->length); |
9ac023989 [PATCH] acpi memo... |
237 238 239 240 241 242 |
if (result) continue; info->enabled = 1; num_enabled++; } if (!num_enabled) { |
0a1f1ab8d ACPI: fixup memho... |
243 244 |
printk(KERN_ERR PREFIX "add_memory failed "); |
1da177e4c Linux-2.6.12-rc2 |
245 |
mem_device->state = MEMORY_INVALID_STATE; |
9ac023989 [PATCH] acpi memo... |
246 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
247 |
} |
5d2619fca ACPI: Ingore the ... |
248 249 250 251 252 253 254 255 256 |
/* * Sometimes the memory device will contain several memory blocks. * When one memory block is hot-added to the system memory, it will * be regarded as a success. * Otherwise if the last memory block can't be hot-added to the system * memory, it will be failure and the memory device can't be bound with * driver. */ return 0; |
1da177e4c Linux-2.6.12-rc2 |
257 |
} |
4be44fcd3 [ACPI] Lindent al... |
258 |
static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device) |
1da177e4c Linux-2.6.12-rc2 |
259 260 |
{ acpi_status status; |
4be44fcd3 [ACPI] Lindent al... |
261 |
struct acpi_object_list arg_list; |
1da177e4c Linux-2.6.12-rc2 |
262 |
union acpi_object arg; |
27663c585 ACPI: Change acpi... |
263 |
unsigned long long current_status; |
1da177e4c Linux-2.6.12-rc2 |
264 |
|
1da177e4c Linux-2.6.12-rc2 |
265 266 267 268 269 270 |
/* Issue the _EJ0 command */ arg_list.count = 1; arg_list.pointer = &arg; arg.type = ACPI_TYPE_INTEGER; arg.integer.value = 1; |
b86327852 ACPI: acpi_memhot... |
271 |
status = acpi_evaluate_object(mem_device->device->handle, |
4be44fcd3 [ACPI] Lindent al... |
272 |
"_EJ0", &arg_list, NULL); |
1da177e4c Linux-2.6.12-rc2 |
273 274 |
/* Return on _EJ0 failure */ if (ACPI_FAILURE(status)) { |
a6fc67202 ACPI: Enable ACPI... |
275 |
ACPI_EXCEPTION((AE_INFO, status, "_EJ0 failed")); |
d550d98d3 ACPI: delete trac... |
276 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
277 278 279 |
} /* Evalute _STA to check if the device is disabled */ |
b86327852 ACPI: acpi_memhot... |
280 |
status = acpi_evaluate_integer(mem_device->device->handle, "_STA", |
4be44fcd3 [ACPI] Lindent al... |
281 |
NULL, ¤t_status); |
1da177e4c Linux-2.6.12-rc2 |
282 |
if (ACPI_FAILURE(status)) |
d550d98d3 ACPI: delete trac... |
283 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
284 285 |
/* Check for device status. Device should be disabled */ |
a0bd4ac49 ACPI: Remove dupl... |
286 |
if (current_status & ACPI_STA_DEVICE_ENABLED) |
d550d98d3 ACPI: delete trac... |
287 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
288 |
|
d550d98d3 ACPI: delete trac... |
289 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
290 |
} |
4be44fcd3 [ACPI] Lindent al... |
291 |
static int acpi_memory_disable_device(struct acpi_memory_device *mem_device) |
1da177e4c Linux-2.6.12-rc2 |
292 293 |
{ int result; |
9ac023989 [PATCH] acpi memo... |
294 |
struct acpi_memory_info *info, *n; |
1da177e4c Linux-2.6.12-rc2 |
295 |
|
1da177e4c Linux-2.6.12-rc2 |
296 297 298 299 300 |
/* * Ask the VM to offline this memory range. * Note: Assume that this function returns zero on success */ |
9ac023989 [PATCH] acpi memo... |
301 302 303 304 305 306 307 |
list_for_each_entry_safe(info, n, &mem_device->res_list, list) { if (info->enabled) { result = remove_memory(info->start_addr, info->length); if (result) return result; } kfree(info); |
1da177e4c Linux-2.6.12-rc2 |
308 309 310 311 312 |
} /* Power-off and eject the device */ result = acpi_memory_powerdown_device(mem_device); if (result) { |
1da177e4c Linux-2.6.12-rc2 |
313 314 315 316 317 318 319 320 |
/* Set the status of the device to invalid */ mem_device->state = MEMORY_INVALID_STATE; return result; } mem_device->state = MEMORY_POWER_OFF_STATE; return result; } |
4be44fcd3 [ACPI] Lindent al... |
321 |
static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) |
1da177e4c Linux-2.6.12-rc2 |
322 323 324 |
{ struct acpi_memory_device *mem_device; struct acpi_device *device; |
1da177e4c Linux-2.6.12-rc2 |
325 326 327 328 |
switch (event) { case ACPI_NOTIFY_BUS_CHECK: ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
4be44fcd3 [ACPI] Lindent al... |
329 330 331 |
" Received BUS CHECK notification for device ")); |
1da177e4c Linux-2.6.12-rc2 |
332 333 334 335 |
/* Fall Through */ case ACPI_NOTIFY_DEVICE_CHECK: if (event == ACPI_NOTIFY_DEVICE_CHECK) ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
4be44fcd3 [ACPI] Lindent al... |
336 337 338 |
" Received DEVICE CHECK notification for device ")); |
1da177e4c Linux-2.6.12-rc2 |
339 |
if (acpi_memory_get_device(handle, &mem_device)) { |
6468463ab ACPI: un-export A... |
340 341 |
printk(KERN_ERR PREFIX "Cannot find driver data "); |
d550d98d3 ACPI: delete trac... |
342 |
return; |
1da177e4c Linux-2.6.12-rc2 |
343 344 345 346 |
} if (!acpi_memory_check_device(mem_device)) { if (acpi_memory_enable_device(mem_device)) |
6468463ab ACPI: un-export A... |
347 348 349 |
printk(KERN_ERR PREFIX "Cannot enable memory device "); |
1da177e4c Linux-2.6.12-rc2 |
350 351 352 353 |
} break; case ACPI_NOTIFY_EJECT_REQUEST: ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
4be44fcd3 [ACPI] Lindent al... |
354 355 356 |
" Received EJECT REQUEST notification for device ")); |
1da177e4c Linux-2.6.12-rc2 |
357 358 |
if (acpi_bus_get_device(handle, &device)) { |
6468463ab ACPI: un-export A... |
359 360 |
printk(KERN_ERR PREFIX "Device doesn't exist "); |
1da177e4c Linux-2.6.12-rc2 |
361 362 363 364 |
break; } mem_device = acpi_driver_data(device); if (!mem_device) { |
6468463ab ACPI: un-export A... |
365 366 |
printk(KERN_ERR PREFIX "Driver Data is NULL "); |
1da177e4c Linux-2.6.12-rc2 |
367 368 369 370 371 372 373 |
break; } /* * Currently disabling memory device from kernel mode * TBD: Can also be disabled from user mode scripts * TBD: Can also be disabled by Callback registration |
4be44fcd3 [ACPI] Lindent al... |
374 |
* with generic sysfs driver |
1da177e4c Linux-2.6.12-rc2 |
375 376 |
*/ if (acpi_memory_disable_device(mem_device)) |
6468463ab ACPI: un-export A... |
377 378 379 |
printk(KERN_ERR PREFIX "Disable memory device "); |
1da177e4c Linux-2.6.12-rc2 |
380 381 382 383 384 385 |
/* * TBD: Invoke acpi_bus_remove to cleanup data structures */ break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
4be44fcd3 [ACPI] Lindent al... |
386 387 |
"Unsupported event [0x%x] ", event)); |
1da177e4c Linux-2.6.12-rc2 |
388 389 |
break; } |
d550d98d3 ACPI: delete trac... |
390 |
return; |
1da177e4c Linux-2.6.12-rc2 |
391 |
} |
4be44fcd3 [ACPI] Lindent al... |
392 |
static int acpi_memory_device_add(struct acpi_device *device) |
1da177e4c Linux-2.6.12-rc2 |
393 394 395 |
{ int result; struct acpi_memory_device *mem_device = NULL; |
1da177e4c Linux-2.6.12-rc2 |
396 397 |
if (!device) |
d550d98d3 ACPI: delete trac... |
398 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
399 |
|
36bcbec7c ACPI: replace kma... |
400 |
mem_device = kzalloc(sizeof(struct acpi_memory_device), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
401 |
if (!mem_device) |
d550d98d3 ACPI: delete trac... |
402 |
return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
403 |
|
9ac023989 [PATCH] acpi memo... |
404 |
INIT_LIST_HEAD(&mem_device->res_list); |
3b74863df ACPI: acpi_memhot... |
405 |
mem_device->device = device; |
1da177e4c Linux-2.6.12-rc2 |
406 407 |
sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME); sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS); |
db89b4f0d ACPI: catch calls... |
408 |
device->driver_data = mem_device; |
1da177e4c Linux-2.6.12-rc2 |
409 410 411 412 413 |
/* Get the range from the _CRS */ result = acpi_memory_get_device_resources(mem_device); if (result) { kfree(mem_device); |
d550d98d3 ACPI: delete trac... |
414 |
return result; |
1da177e4c Linux-2.6.12-rc2 |
415 416 417 418 |
} /* Set the device state */ mem_device->state = MEMORY_POWER_ON_STATE; |
6cbe44cd8 [PATCH] Change lo... |
419 420 |
printk(KERN_DEBUG "%s ", acpi_device_name(device)); |
1da177e4c Linux-2.6.12-rc2 |
421 |
|
887b95931 [PATCH] acpi memo... |
422 423 424 425 426 427 428 429 |
/* * Early boot code has recognized memory area by EFI/E820. * If DSDT shows these memory devices on boot, hotplug is not necessary * for them. So, it just returns until completion of this driver's * start up. */ if (!acpi_hotmem_initialized) return 0; |
1f425994f [PATCH] Catch not... |
430 431 432 433 |
if (!acpi_memory_check_device(mem_device)) { /* call add_memory func */ result = acpi_memory_enable_device(mem_device); if (result) |
55ac9a018 ACPI: replace ACP... |
434 435 436 |
printk(KERN_ERR PREFIX "Error in acpi_memory_enable_device "); |
1f425994f [PATCH] Catch not... |
437 |
} |
d120cfb54 merge linus into ... |
438 |
return result; |
1f425994f [PATCH] Catch not... |
439 |
} |
80f20fef6 ACPI: memory hotp... |
440 441 442 443 444 445 446 447 448 449 450 451 452 |
static int acpi_memory_device_remove(struct acpi_device *device, int type) { struct acpi_memory_device *mem_device = NULL; if (!device || !acpi_driver_data(device)) return -EINVAL; mem_device = acpi_driver_data(device); kfree(mem_device); return 0; } |
1da177e4c Linux-2.6.12-rc2 |
453 454 455 |
/* * Helper function to check for memory device */ |
4be44fcd3 [ACPI] Lindent al... |
456 |
static acpi_status is_memory_device(acpi_handle handle) |
1da177e4c Linux-2.6.12-rc2 |
457 458 459 |
{ char *hardware_id; acpi_status status; |
1da177e4c Linux-2.6.12-rc2 |
460 |
struct acpi_device_info *info; |
15b8dd53f ACPICA: Major upd... |
461 |
status = acpi_get_object_info(handle, &info); |
1da177e4c Linux-2.6.12-rc2 |
462 |
if (ACPI_FAILURE(status)) |
d550d98d3 ACPI: delete trac... |
463 |
return status; |
1da177e4c Linux-2.6.12-rc2 |
464 |
|
1da177e4c Linux-2.6.12-rc2 |
465 |
if (!(info->valid & ACPI_VALID_HID)) { |
15b8dd53f ACPICA: Major upd... |
466 |
kfree(info); |
d550d98d3 ACPI: delete trac... |
467 |
return AE_ERROR; |
1da177e4c Linux-2.6.12-rc2 |
468 |
} |
15b8dd53f ACPICA: Major upd... |
469 |
hardware_id = info->hardware_id.string; |
1da177e4c Linux-2.6.12-rc2 |
470 |
if ((hardware_id == NULL) || |
4be44fcd3 [ACPI] Lindent al... |
471 |
(strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID))) |
1da177e4c Linux-2.6.12-rc2 |
472 |
status = AE_ERROR; |
15b8dd53f ACPICA: Major upd... |
473 |
kfree(info); |
d550d98d3 ACPI: delete trac... |
474 |
return status; |
1da177e4c Linux-2.6.12-rc2 |
475 476 477 |
} static acpi_status |
4be44fcd3 [ACPI] Lindent al... |
478 479 |
acpi_memory_register_notify_handler(acpi_handle handle, u32 level, void *ctxt, void **retv) |
1da177e4c Linux-2.6.12-rc2 |
480 481 |
{ acpi_status status; |
1da177e4c Linux-2.6.12-rc2 |
482 483 |
status = is_memory_device(handle); |
07dd4855e ACPI: memory hotp... |
484 |
if (ACPI_FAILURE(status)) |
d550d98d3 ACPI: delete trac... |
485 |
return AE_OK; /* continue */ |
1da177e4c Linux-2.6.12-rc2 |
486 487 |
status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
4be44fcd3 [ACPI] Lindent al... |
488 |
acpi_memory_device_notify, NULL); |
a6fc67202 ACPI: Enable ACPI... |
489 |
/* continue */ |
d550d98d3 ACPI: delete trac... |
490 |
return AE_OK; |
1da177e4c Linux-2.6.12-rc2 |
491 492 493 |
} static acpi_status |
4be44fcd3 [ACPI] Lindent al... |
494 495 |
acpi_memory_deregister_notify_handler(acpi_handle handle, u32 level, void *ctxt, void **retv) |
1da177e4c Linux-2.6.12-rc2 |
496 497 |
{ acpi_status status; |
1da177e4c Linux-2.6.12-rc2 |
498 499 |
status = is_memory_device(handle); |
07dd4855e ACPI: memory hotp... |
500 |
if (ACPI_FAILURE(status)) |
d550d98d3 ACPI: delete trac... |
501 |
return AE_OK; /* continue */ |
1da177e4c Linux-2.6.12-rc2 |
502 503 |
status = acpi_remove_notify_handler(handle, |
4be44fcd3 [ACPI] Lindent al... |
504 505 |
ACPI_SYSTEM_NOTIFY, acpi_memory_device_notify); |
1da177e4c Linux-2.6.12-rc2 |
506 |
|
d550d98d3 ACPI: delete trac... |
507 |
return AE_OK; /* continue */ |
1da177e4c Linux-2.6.12-rc2 |
508 |
} |
4be44fcd3 [ACPI] Lindent al... |
509 |
static int __init acpi_memory_device_init(void) |
1da177e4c Linux-2.6.12-rc2 |
510 511 512 |
{ int result; acpi_status status; |
1da177e4c Linux-2.6.12-rc2 |
513 514 515 516 |
result = acpi_bus_register_driver(&acpi_memory_device_driver); if (result < 0) |
d550d98d3 ACPI: delete trac... |
517 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
518 519 |
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
4be44fcd3 [ACPI] Lindent al... |
520 |
ACPI_UINT32_MAX, |
2263576cf ACPICA: Add post-... |
521 |
acpi_memory_register_notify_handler, NULL, |
4be44fcd3 [ACPI] Lindent al... |
522 |
NULL, NULL); |
1da177e4c Linux-2.6.12-rc2 |
523 |
|
4be44fcd3 [ACPI] Lindent al... |
524 |
if (ACPI_FAILURE(status)) { |
a6fc67202 ACPI: Enable ACPI... |
525 |
ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed")); |
1da177e4c Linux-2.6.12-rc2 |
526 |
acpi_bus_unregister_driver(&acpi_memory_device_driver); |
d550d98d3 ACPI: delete trac... |
527 |
return -ENODEV; |
4be44fcd3 [ACPI] Lindent al... |
528 |
} |
1da177e4c Linux-2.6.12-rc2 |
529 |
|
887b95931 [PATCH] acpi memo... |
530 |
acpi_hotmem_initialized = 1; |
d550d98d3 ACPI: delete trac... |
531 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
532 |
} |
4be44fcd3 [ACPI] Lindent al... |
533 |
static void __exit acpi_memory_device_exit(void) |
1da177e4c Linux-2.6.12-rc2 |
534 535 |
{ acpi_status status; |
1da177e4c Linux-2.6.12-rc2 |
536 537 538 539 540 541 |
/* * Adding this to un-install notification handlers for all the device * handles. */ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
4be44fcd3 [ACPI] Lindent al... |
542 |
ACPI_UINT32_MAX, |
2263576cf ACPICA: Add post-... |
543 |
acpi_memory_deregister_notify_handler, NULL, |
4be44fcd3 [ACPI] Lindent al... |
544 |
NULL, NULL); |
1da177e4c Linux-2.6.12-rc2 |
545 |
|
4be44fcd3 [ACPI] Lindent al... |
546 |
if (ACPI_FAILURE(status)) |
a6fc67202 ACPI: Enable ACPI... |
547 |
ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed")); |
1da177e4c Linux-2.6.12-rc2 |
548 549 |
acpi_bus_unregister_driver(&acpi_memory_device_driver); |
d550d98d3 ACPI: delete trac... |
550 |
return; |
1da177e4c Linux-2.6.12-rc2 |
551 552 553 554 |
} module_init(acpi_memory_device_init); module_exit(acpi_memory_device_exit); |