ia64/linux-2.6.18-xen.hg

view drivers/acpi/ac.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /*
2 * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 27 $)
3 *
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 *
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22 *
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 */
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/types.h>
30 #include <linux/proc_fs.h>
31 #include <linux/seq_file.h>
32 #include <acpi/acpi_bus.h>
33 #include <acpi/acpi_drivers.h>
35 #define ACPI_AC_COMPONENT 0x00020000
36 #define ACPI_AC_CLASS "ac_adapter"
37 #define ACPI_AC_HID "ACPI0003"
38 #define ACPI_AC_DRIVER_NAME "ACPI AC Adapter Driver"
39 #define ACPI_AC_DEVICE_NAME "AC Adapter"
40 #define ACPI_AC_FILE_STATE "state"
41 #define ACPI_AC_NOTIFY_STATUS 0x80
42 #define ACPI_AC_STATUS_OFFLINE 0x00
43 #define ACPI_AC_STATUS_ONLINE 0x01
44 #define ACPI_AC_STATUS_UNKNOWN 0xFF
46 #define _COMPONENT ACPI_AC_COMPONENT
47 ACPI_MODULE_NAME("acpi_ac")
49 MODULE_AUTHOR("Paul Diefenbaugh");
50 MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
51 MODULE_LICENSE("GPL");
53 extern struct proc_dir_entry *acpi_lock_ac_dir(void);
54 extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
56 static int acpi_ac_add(struct acpi_device *device);
57 static int acpi_ac_remove(struct acpi_device *device, int type);
58 static int acpi_ac_open_fs(struct inode *inode, struct file *file);
60 static struct acpi_driver acpi_ac_driver = {
61 .name = ACPI_AC_DRIVER_NAME,
62 .class = ACPI_AC_CLASS,
63 .ids = ACPI_AC_HID,
64 .ops = {
65 .add = acpi_ac_add,
66 .remove = acpi_ac_remove,
67 },
68 };
70 struct acpi_ac {
71 struct acpi_device * device;
72 unsigned long state;
73 };
75 static const struct file_operations acpi_ac_fops = {
76 .open = acpi_ac_open_fs,
77 .read = seq_read,
78 .llseek = seq_lseek,
79 .release = single_release,
80 };
82 /* --------------------------------------------------------------------------
83 AC Adapter Management
84 -------------------------------------------------------------------------- */
86 static int acpi_ac_get_state(struct acpi_ac *ac)
87 {
88 acpi_status status = AE_OK;
91 if (!ac)
92 return -EINVAL;
94 status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state);
95 if (ACPI_FAILURE(status)) {
96 ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state"));
97 ac->state = ACPI_AC_STATUS_UNKNOWN;
98 return -ENODEV;
99 }
101 return 0;
102 }
104 /* --------------------------------------------------------------------------
105 FS Interface (/proc)
106 -------------------------------------------------------------------------- */
108 static struct proc_dir_entry *acpi_ac_dir;
110 static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
111 {
112 struct acpi_ac *ac = (struct acpi_ac *)seq->private;
115 if (!ac)
116 return 0;
118 if (acpi_ac_get_state(ac)) {
119 seq_puts(seq, "ERROR: Unable to read AC Adapter state\n");
120 return 0;
121 }
123 seq_puts(seq, "state: ");
124 switch (ac->state) {
125 case ACPI_AC_STATUS_OFFLINE:
126 seq_puts(seq, "off-line\n");
127 break;
128 case ACPI_AC_STATUS_ONLINE:
129 seq_puts(seq, "on-line\n");
130 break;
131 default:
132 seq_puts(seq, "unknown\n");
133 break;
134 }
136 return 0;
137 }
139 static int acpi_ac_open_fs(struct inode *inode, struct file *file)
140 {
141 return single_open(file, acpi_ac_seq_show, PDE(inode)->data);
142 }
144 static int acpi_ac_add_fs(struct acpi_device *device)
145 {
146 struct proc_dir_entry *entry = NULL;
149 if (!acpi_device_dir(device)) {
150 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
151 acpi_ac_dir);
152 if (!acpi_device_dir(device))
153 return -ENODEV;
154 acpi_device_dir(device)->owner = THIS_MODULE;
155 }
157 /* 'state' [R] */
158 entry = create_proc_entry(ACPI_AC_FILE_STATE,
159 S_IRUGO, acpi_device_dir(device));
160 if (!entry)
161 return -ENODEV;
162 else {
163 entry->proc_fops = &acpi_ac_fops;
164 entry->data = acpi_driver_data(device);
165 entry->owner = THIS_MODULE;
166 }
168 return 0;
169 }
171 static int acpi_ac_remove_fs(struct acpi_device *device)
172 {
174 if (acpi_device_dir(device)) {
175 remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device));
177 remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
178 acpi_device_dir(device) = NULL;
179 }
181 return 0;
182 }
184 /* --------------------------------------------------------------------------
185 Driver Model
186 -------------------------------------------------------------------------- */
188 static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
189 {
190 struct acpi_ac *ac = (struct acpi_ac *)data;
191 struct acpi_device *device = NULL;
194 if (!ac)
195 return;
197 device = ac->device;
198 switch (event) {
199 case ACPI_AC_NOTIFY_STATUS:
200 case ACPI_NOTIFY_BUS_CHECK:
201 case ACPI_NOTIFY_DEVICE_CHECK:
202 acpi_ac_get_state(ac);
203 acpi_bus_generate_event(device, event, (u32) ac->state);
204 break;
205 default:
206 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
207 "Unsupported event [0x%x]\n", event));
208 break;
209 }
211 return;
212 }
214 static int acpi_ac_add(struct acpi_device *device)
215 {
216 int result = 0;
217 acpi_status status = AE_OK;
218 struct acpi_ac *ac = NULL;
221 if (!device)
222 return -EINVAL;
224 ac = kmalloc(sizeof(struct acpi_ac), GFP_KERNEL);
225 if (!ac)
226 return -ENOMEM;
227 memset(ac, 0, sizeof(struct acpi_ac));
229 ac->device = device;
230 strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
231 strcpy(acpi_device_class(device), ACPI_AC_CLASS);
232 acpi_driver_data(device) = ac;
234 result = acpi_ac_get_state(ac);
235 if (result)
236 goto end;
238 result = acpi_ac_add_fs(device);
239 if (result)
240 goto end;
242 status = acpi_install_notify_handler(device->handle,
243 ACPI_ALL_NOTIFY, acpi_ac_notify,
244 ac);
245 if (ACPI_FAILURE(status)) {
246 result = -ENODEV;
247 goto end;
248 }
250 printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
251 acpi_device_name(device), acpi_device_bid(device),
252 ac->state ? "on-line" : "off-line");
254 end:
255 if (result) {
256 acpi_ac_remove_fs(device);
257 kfree(ac);
258 }
260 return result;
261 }
263 static int acpi_ac_remove(struct acpi_device *device, int type)
264 {
265 acpi_status status = AE_OK;
266 struct acpi_ac *ac = NULL;
269 if (!device || !acpi_driver_data(device))
270 return -EINVAL;
272 ac = (struct acpi_ac *)acpi_driver_data(device);
274 status = acpi_remove_notify_handler(device->handle,
275 ACPI_ALL_NOTIFY, acpi_ac_notify);
277 acpi_ac_remove_fs(device);
279 kfree(ac);
281 return 0;
282 }
284 static int __init acpi_ac_init(void)
285 {
286 int result;
288 if (acpi_disabled)
289 return -ENODEV;
291 acpi_ac_dir = acpi_lock_ac_dir();
292 if (!acpi_ac_dir)
293 return -ENODEV;
295 result = acpi_bus_register_driver(&acpi_ac_driver);
296 if (result < 0) {
297 acpi_unlock_ac_dir(acpi_ac_dir);
298 return -ENODEV;
299 }
301 return 0;
302 }
304 static void __exit acpi_ac_exit(void)
305 {
307 acpi_bus_unregister_driver(&acpi_ac_driver);
309 acpi_unlock_ac_dir(acpi_ac_dir);
311 return;
312 }
314 module_init(acpi_ac_init);
315 module_exit(acpi_ac_exit);