ia64/linux-2.6.18-xen.hg

view drivers/mtd/maps/ixp2000.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: ixp2000.c,v 1.9 2005/11/07 11:14:27 gleixner Exp $
3 *
4 * drivers/mtd/maps/ixp2000.c
5 *
6 * Mapping for the Intel XScale IXP2000 based systems
7 *
8 * Copyright (C) 2002 Intel Corp.
9 * Copyright (C) 2003-2004 MontaVista Software, Inc.
10 *
11 * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
12 * Maintainer: Deepak Saxena <dsaxena@plexity.net>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 *
18 */
20 #include <linux/module.h>
21 #include <linux/types.h>
22 #include <linux/init.h>
23 #include <linux/kernel.h>
24 #include <linux/string.h>
25 #include <linux/slab.h>
26 #include <linux/ioport.h>
27 #include <linux/device.h>
28 #include <linux/platform_device.h>
30 #include <linux/mtd/mtd.h>
31 #include <linux/mtd/map.h>
32 #include <linux/mtd/partitions.h>
34 #include <asm/io.h>
35 #include <asm/hardware.h>
36 #include <asm/mach/flash.h>
38 #include <linux/reboot.h>
40 struct ixp2000_flash_info {
41 struct mtd_info *mtd;
42 struct map_info map;
43 struct mtd_partition *partitions;
44 struct resource *res;
45 };
47 static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs)
48 {
49 unsigned long (*set_bank)(unsigned long) =
50 (unsigned long(*)(unsigned long))map->map_priv_2;
52 return (set_bank ? set_bank(ofs) : ofs);
53 }
55 #ifdef __ARMEB__
56 /*
57 * Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which
58 * causes the lower address bits to be XORed with 0x11 on 8 bit accesses
59 * and XORed with 0x10 on 16 bit accesses. See the spec update, erratum 44.
60 */
61 static int erratum44_workaround = 0;
63 static inline unsigned long address_fix8_write(unsigned long addr)
64 {
65 if (erratum44_workaround) {
66 return (addr ^ 3);
67 }
68 return addr;
69 }
70 #else
72 #define address_fix8_write(x) (x)
73 #endif
75 static map_word ixp2000_flash_read8(struct map_info *map, unsigned long ofs)
76 {
77 map_word val;
79 val.x[0] = *((u8 *)(map->map_priv_1 + flash_bank_setup(map, ofs)));
80 return val;
81 }
83 /*
84 * We can't use the standard memcpy due to the broken SlowPort
85 * address translation on rev A0 and A1 silicon and the fact that
86 * we have banked flash.
87 */
88 static void ixp2000_flash_copy_from(struct map_info *map, void *to,
89 unsigned long from, ssize_t len)
90 {
91 from = flash_bank_setup(map, from);
92 while(len--)
93 *(__u8 *) to++ = *(__u8 *)(map->map_priv_1 + from++);
94 }
96 static void ixp2000_flash_write8(struct map_info *map, map_word d, unsigned long ofs)
97 {
98 *(__u8 *) (address_fix8_write(map->map_priv_1 +
99 flash_bank_setup(map, ofs))) = d.x[0];
100 }
102 static void ixp2000_flash_copy_to(struct map_info *map, unsigned long to,
103 const void *from, ssize_t len)
104 {
105 to = flash_bank_setup(map, to);
106 while(len--) {
107 unsigned long tmp = address_fix8_write(map->map_priv_1 + to++);
108 *(__u8 *)(tmp) = *(__u8 *)(from++);
109 }
110 }
113 static int ixp2000_flash_remove(struct platform_device *dev)
114 {
115 struct flash_platform_data *plat = dev->dev.platform_data;
116 struct ixp2000_flash_info *info = platform_get_drvdata(dev);
118 platform_set_drvdata(dev, NULL);
120 if(!info)
121 return 0;
123 if (info->mtd) {
124 del_mtd_partitions(info->mtd);
125 map_destroy(info->mtd);
126 }
127 if (info->map.map_priv_1)
128 iounmap((void *) info->map.map_priv_1);
130 kfree(info->partitions);
132 if (info->res) {
133 release_resource(info->res);
134 kfree(info->res);
135 }
137 if (plat->exit)
138 plat->exit();
140 return 0;
141 }
144 static int ixp2000_flash_probe(struct platform_device *dev)
145 {
146 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
147 struct ixp2000_flash_data *ixp_data = dev->dev.platform_data;
148 struct flash_platform_data *plat;
149 struct ixp2000_flash_info *info;
150 unsigned long window_size;
151 int err = -1;
153 if (!ixp_data)
154 return -ENODEV;
156 plat = ixp_data->platform_data;
157 if (!plat)
158 return -ENODEV;
160 window_size = dev->resource->end - dev->resource->start + 1;
161 dev_info(&dev->dev, "Probe of IXP2000 flash(%d banks x %dMiB)\n",
162 ixp_data->nr_banks, ((u32)window_size >> 20));
164 if (plat->width != 1) {
165 dev_err(&dev->dev, "IXP2000 MTD map only supports 8-bit mode, asking for %d\n",
166 plat->width * 8);
167 return -EIO;
168 }
170 info = kmalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL);
171 if(!info) {
172 err = -ENOMEM;
173 goto Error;
174 }
175 memzero(info, sizeof(struct ixp2000_flash_info));
177 platform_set_drvdata(dev, info);
179 /*
180 * Tell the MTD layer we're not 1:1 mapped so that it does
181 * not attempt to do a direct access on us.
182 */
183 info->map.phys = NO_XIP;
185 info->map.size = ixp_data->nr_banks * window_size;
186 info->map.bankwidth = 1;
188 /*
189 * map_priv_2 is used to store a ptr to to the bank_setup routine
190 */
191 info->map.map_priv_2 = (unsigned long) ixp_data->bank_setup;
193 info->map.name = dev->dev.bus_id;
194 info->map.read = ixp2000_flash_read8;
195 info->map.write = ixp2000_flash_write8;
196 info->map.copy_from = ixp2000_flash_copy_from;
197 info->map.copy_to = ixp2000_flash_copy_to;
199 info->res = request_mem_region(dev->resource->start,
200 dev->resource->end - dev->resource->start + 1,
201 dev->dev.bus_id);
202 if (!info->res) {
203 dev_err(&dev->dev, "Could not reserve memory region\n");
204 err = -ENOMEM;
205 goto Error;
206 }
208 info->map.map_priv_1 = (unsigned long) ioremap(dev->resource->start,
209 dev->resource->end - dev->resource->start + 1);
210 if (!info->map.map_priv_1) {
211 dev_err(&dev->dev, "Failed to ioremap flash region\n");
212 err = -EIO;
213 goto Error;
214 }
216 #if defined(__ARMEB__)
217 /*
218 * Enable erratum 44 workaround for NPUs with broken slowport
219 */
221 erratum44_workaround = ixp2000_has_broken_slowport();
222 dev_info(&dev->dev, "Erratum 44 workaround %s\n",
223 erratum44_workaround ? "enabled" : "disabled");
224 #endif
226 info->mtd = do_map_probe(plat->map_name, &info->map);
227 if (!info->mtd) {
228 dev_err(&dev->dev, "map_probe failed\n");
229 err = -ENXIO;
230 goto Error;
231 }
232 info->mtd->owner = THIS_MODULE;
234 err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
235 if (err > 0) {
236 err = add_mtd_partitions(info->mtd, info->partitions, err);
237 if(err)
238 dev_err(&dev->dev, "Could not parse partitions\n");
239 }
241 if (err)
242 goto Error;
244 return 0;
246 Error:
247 ixp2000_flash_remove(dev);
248 return err;
249 }
251 static struct platform_driver ixp2000_flash_driver = {
252 .probe = ixp2000_flash_probe,
253 .remove = ixp2000_flash_remove,
254 .driver = {
255 .name = "IXP2000-Flash",
256 },
257 };
259 static int __init ixp2000_flash_init(void)
260 {
261 return platform_driver_register(&ixp2000_flash_driver);
262 }
264 static void __exit ixp2000_flash_exit(void)
265 {
266 platform_driver_unregister(&ixp2000_flash_driver);
267 }
269 module_init(ixp2000_flash_init);
270 module_exit(ixp2000_flash_exit);
271 MODULE_LICENSE("GPL");
272 MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");