ia64/linux-2.6.18-xen.hg

view drivers/acpi/motherboard.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 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or (at
6 * your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16 *
17 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18 */
20 /* Purpose: Prevent PCMCIA cards from using motherboard resources. */
22 #include <linux/kernel.h>
23 #include <linux/init.h>
24 #include <linux/types.h>
25 #include <linux/pci.h>
26 #include <linux/ioport.h>
27 #include <asm/io.h>
29 #include <acpi/acpi_bus.h>
30 #include <acpi/acpi_drivers.h>
32 #define _COMPONENT ACPI_SYSTEM_COMPONENT
33 ACPI_MODULE_NAME("acpi_motherboard")
35 /* Dell use PNP0C01 instead of PNP0C02 */
36 #define ACPI_MB_HID1 "PNP0C01"
37 #define ACPI_MB_HID2 "PNP0C02"
38 /**
39 * Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved
40 * Doesn't care about the failure of 'request_region', since other may reserve
41 * the io ports as well
42 */
43 #define IS_RESERVED_ADDR(base, len) \
44 (((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \
45 && ((base) + (len) > PCIBIOS_MIN_IO))
46 /*
47 * Clearing the flag (IORESOURCE_BUSY) allows drivers to use
48 * the io ports if they really know they can use it, while
49 * still preventing hotplug PCI devices from using it.
50 */
51 static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data)
52 {
53 struct resource *requested_res = NULL;
56 if (res->type == ACPI_RESOURCE_TYPE_IO) {
57 struct acpi_resource_io *io_res = &res->data.io;
59 if (io_res->minimum != io_res->maximum)
60 return AE_OK;
61 if (IS_RESERVED_ADDR
62 (io_res->minimum, io_res->address_length)) {
63 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
64 "Motherboard resources 0x%08x - 0x%08x\n",
65 io_res->minimum,
66 io_res->minimum +
67 io_res->address_length));
68 requested_res =
69 request_region(io_res->minimum,
70 io_res->address_length, "motherboard");
71 }
72 } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_IO) {
73 struct acpi_resource_fixed_io *fixed_io_res =
74 &res->data.fixed_io;
76 if (IS_RESERVED_ADDR
77 (fixed_io_res->address, fixed_io_res->address_length)) {
78 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
79 "Motherboard resources 0x%08x - 0x%08x\n",
80 fixed_io_res->address,
81 fixed_io_res->address +
82 fixed_io_res->address_length));
83 requested_res =
84 request_region(fixed_io_res->address,
85 fixed_io_res->address_length,
86 "motherboard");
87 }
88 } else {
89 /* Memory mapped IO? */
90 }
92 if (requested_res)
93 requested_res->flags &= ~IORESOURCE_BUSY;
94 return AE_OK;
95 }
97 static int acpi_motherboard_add(struct acpi_device *device)
98 {
99 if (!device)
100 return -EINVAL;
101 acpi_walk_resources(device->handle, METHOD_NAME__CRS,
102 acpi_reserve_io_ranges, NULL);
104 return 0;
105 }
107 static struct acpi_driver acpi_motherboard_driver1 = {
108 .name = "motherboard",
109 .class = "",
110 .ids = ACPI_MB_HID1,
111 .ops = {
112 .add = acpi_motherboard_add,
113 },
114 };
116 static struct acpi_driver acpi_motherboard_driver2 = {
117 .name = "motherboard",
118 .class = "",
119 .ids = ACPI_MB_HID2,
120 .ops = {
121 .add = acpi_motherboard_add,
122 },
123 };
125 static void __init acpi_request_region (struct acpi_generic_address *addr,
126 unsigned int length, char *desc)
127 {
128 if (!addr->address || !length)
129 return;
131 if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_IO)
132 request_region(addr->address, length, desc);
133 else if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
134 request_mem_region(addr->address, length, desc);
135 }
137 static void __init acpi_reserve_resources(void)
138 {
139 acpi_request_region(&acpi_gbl_FADT->xpm1a_evt_blk,
140 acpi_gbl_FADT->pm1_evt_len, "ACPI PM1a_EVT_BLK");
142 acpi_request_region(&acpi_gbl_FADT->xpm1b_evt_blk,
143 acpi_gbl_FADT->pm1_evt_len, "ACPI PM1b_EVT_BLK");
145 acpi_request_region(&acpi_gbl_FADT->xpm1a_cnt_blk,
146 acpi_gbl_FADT->pm1_cnt_len, "ACPI PM1a_CNT_BLK");
148 acpi_request_region(&acpi_gbl_FADT->xpm1b_cnt_blk,
149 acpi_gbl_FADT->pm1_cnt_len, "ACPI PM1b_CNT_BLK");
151 if (acpi_gbl_FADT->pm_tm_len == 4)
152 acpi_request_region(&acpi_gbl_FADT->xpm_tmr_blk, 4, "ACPI PM_TMR");
154 acpi_request_region(&acpi_gbl_FADT->xpm2_cnt_blk,
155 acpi_gbl_FADT->pm2_cnt_len, "ACPI PM2_CNT_BLK");
157 /* Length of GPE blocks must be a non-negative multiple of 2 */
159 if (!(acpi_gbl_FADT->gpe0_blk_len & 0x1))
160 acpi_request_region(&acpi_gbl_FADT->xgpe0_blk,
161 acpi_gbl_FADT->gpe0_blk_len, "ACPI GPE0_BLK");
163 if (!(acpi_gbl_FADT->gpe1_blk_len & 0x1))
164 acpi_request_region(&acpi_gbl_FADT->xgpe1_blk,
165 acpi_gbl_FADT->gpe1_blk_len, "ACPI GPE1_BLK");
166 }
168 static int __init acpi_motherboard_init(void)
169 {
170 acpi_bus_register_driver(&acpi_motherboard_driver1);
171 acpi_bus_register_driver(&acpi_motherboard_driver2);
172 /*
173 * Guarantee motherboard IO reservation first
174 * This module must run after scan.c
175 */
176 if (!acpi_disabled)
177 acpi_reserve_resources();
178 return 0;
179 }
181 /**
182 * Reserve motherboard resources after PCI claim BARs,
183 * but before PCI assign resources for uninitialized PCI devices
184 */
185 fs_initcall(acpi_motherboard_init);