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