ia64/linux-2.6.18-xen.hg

view drivers/mtd/maps/physmap.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 * $Id: physmap.c,v 1.39 2005/11/29 14:49:36 gleixner Exp $
3 *
4 * Normal mappings of chips in physical memory
5 *
6 * Copyright (C) 2003 MontaVista Software Inc.
7 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
8 *
9 * 031022 - [jsun] add run-time configure and partition setup
10 */
12 #include <linux/module.h>
13 #include <linux/types.h>
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/slab.h>
17 #include <linux/device.h>
18 #include <linux/platform_device.h>
19 #include <linux/mtd/mtd.h>
20 #include <linux/mtd/map.h>
21 #include <linux/mtd/partitions.h>
22 #include <linux/mtd/physmap.h>
23 #include <asm/io.h>
25 struct physmap_flash_info {
26 struct mtd_info *mtd;
27 struct map_info map;
28 struct resource *res;
29 #ifdef CONFIG_MTD_PARTITIONS
30 int nr_parts;
31 struct mtd_partition *parts;
32 #endif
33 };
36 static int physmap_flash_remove(struct platform_device *dev)
37 {
38 struct physmap_flash_info *info;
39 struct physmap_flash_data *physmap_data;
41 info = platform_get_drvdata(dev);
42 if (info == NULL)
43 return 0;
44 platform_set_drvdata(dev, NULL);
46 physmap_data = dev->dev.platform_data;
48 if (info->mtd != NULL) {
49 #ifdef CONFIG_MTD_PARTITIONS
50 if (info->nr_parts) {
51 del_mtd_partitions(info->mtd);
52 kfree(info->parts);
53 } else if (physmap_data->nr_parts) {
54 del_mtd_partitions(info->mtd);
55 } else {
56 del_mtd_device(info->mtd);
57 }
58 #else
59 del_mtd_device(info->mtd);
60 #endif
61 map_destroy(info->mtd);
62 }
64 if (info->map.virt != NULL)
65 iounmap((void *)info->map.virt);
67 if (info->res != NULL) {
68 release_resource(info->res);
69 kfree(info->res);
70 }
72 return 0;
73 }
75 static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
76 #ifdef CONFIG_MTD_PARTITIONS
77 static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
78 #endif
80 static int physmap_flash_probe(struct platform_device *dev)
81 {
82 struct physmap_flash_data *physmap_data;
83 struct physmap_flash_info *info;
84 const char **probe_type;
85 int err;
87 physmap_data = dev->dev.platform_data;
88 if (physmap_data == NULL)
89 return -ENODEV;
91 printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
92 (unsigned long long)dev->resource->end - dev->resource->start + 1,
93 (unsigned long long)dev->resource->start);
95 info = kmalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
96 if (info == NULL) {
97 err = -ENOMEM;
98 goto err_out;
99 }
100 memset(info, 0, sizeof(*info));
102 platform_set_drvdata(dev, info);
104 info->res = request_mem_region(dev->resource->start,
105 dev->resource->end - dev->resource->start + 1,
106 dev->dev.bus_id);
107 if (info->res == NULL) {
108 dev_err(&dev->dev, "Could not reserve memory region\n");
109 err = -ENOMEM;
110 goto err_out;
111 }
113 info->map.name = dev->dev.bus_id;
114 info->map.phys = dev->resource->start;
115 info->map.size = dev->resource->end - dev->resource->start + 1;
116 info->map.bankwidth = physmap_data->width;
117 info->map.set_vpp = physmap_data->set_vpp;
119 info->map.virt = ioremap(info->map.phys, info->map.size);
120 if (info->map.virt == NULL) {
121 dev_err(&dev->dev, "Failed to ioremap flash region\n");
122 err = EIO;
123 goto err_out;
124 }
126 simple_map_init(&info->map);
128 probe_type = rom_probe_types;
129 for (; info->mtd == NULL && *probe_type != NULL; probe_type++)
130 info->mtd = do_map_probe(*probe_type, &info->map);
131 if (info->mtd == NULL) {
132 dev_err(&dev->dev, "map_probe failed\n");
133 err = -ENXIO;
134 goto err_out;
135 }
136 info->mtd->owner = THIS_MODULE;
138 #ifdef CONFIG_MTD_PARTITIONS
139 err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0);
140 if (err > 0) {
141 add_mtd_partitions(info->mtd, info->parts, err);
142 return 0;
143 }
145 if (physmap_data->nr_parts) {
146 printk(KERN_NOTICE "Using physmap partition information\n");
147 add_mtd_partitions(info->mtd, physmap_data->parts,
148 physmap_data->nr_parts);
149 return 0;
150 }
151 #endif
153 add_mtd_device(info->mtd);
154 return 0;
156 err_out:
157 physmap_flash_remove(dev);
158 return err;
159 }
161 static struct platform_driver physmap_flash_driver = {
162 .probe = physmap_flash_probe,
163 .remove = physmap_flash_remove,
164 .driver = {
165 .name = "physmap-flash",
166 },
167 };
170 #ifdef CONFIG_MTD_PHYSMAP_LEN
171 #if CONFIG_MTD_PHYSMAP_LEN != 0
172 #warning using PHYSMAP compat code
173 #define PHYSMAP_COMPAT
174 #endif
175 #endif
177 #ifdef PHYSMAP_COMPAT
178 static struct physmap_flash_data physmap_flash_data = {
179 .width = CONFIG_MTD_PHYSMAP_BANKWIDTH,
180 };
182 static struct resource physmap_flash_resource = {
183 .start = CONFIG_MTD_PHYSMAP_START,
184 .end = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN - 1,
185 .flags = IORESOURCE_MEM,
186 };
188 static struct platform_device physmap_flash = {
189 .name = "physmap-flash",
190 .id = 0,
191 .dev = {
192 .platform_data = &physmap_flash_data,
193 },
194 .num_resources = 1,
195 .resource = &physmap_flash_resource,
196 };
198 void physmap_configure(unsigned long addr, unsigned long size,
199 int bankwidth, void (*set_vpp)(struct map_info *, int))
200 {
201 physmap_flash_resource.start = addr;
202 physmap_flash_resource.end = addr + size - 1;
203 physmap_flash_data.width = bankwidth;
204 physmap_flash_data.set_vpp = set_vpp;
205 }
207 #ifdef CONFIG_MTD_PARTITIONS
208 void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
209 {
210 physmap_flash_data.nr_parts = num_parts;
211 physmap_flash_data.parts = parts;
212 }
213 #endif
214 #endif
216 static int __init physmap_init(void)
217 {
218 int err;
220 err = platform_driver_register(&physmap_flash_driver);
221 #ifdef PHYSMAP_COMPAT
222 if (err == 0)
223 platform_device_register(&physmap_flash);
224 #endif
226 return err;
227 }
229 static void __exit physmap_exit(void)
230 {
231 #ifdef PHYSMAP_COMPAT
232 platform_device_unregister(&physmap_flash);
233 #endif
234 platform_driver_unregister(&physmap_flash_driver);
235 }
237 module_init(physmap_init);
238 module_exit(physmap_exit);
240 MODULE_LICENSE("GPL");
241 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
242 MODULE_DESCRIPTION("Generic configurable MTD map driver");