ia64/linux-2.6.18-xen.hg

view drivers/mtd/maps/tqm8xxl.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 * Handle mapping of the flash memory access routines
3 * on TQM8xxL based devices.
4 *
5 * $Id: tqm8xxl.c,v 1.15 2005/11/07 11:14:28 gleixner Exp $
6 *
7 * based on rpxlite.c
8 *
9 * Copyright(C) 2001 Kirk Lee <kirk@hpc.ee.ntu.edu.tw>
10 *
11 * This code is GPLed
12 *
13 */
15 /*
16 * According to TQM8xxL hardware manual, TQM8xxL series have
17 * following flash memory organisations:
18 * | capacity | | chip type | | bank0 | | bank1 |
19 * 2MiB 512Kx16 2MiB 0
20 * 4MiB 1Mx16 4MiB 0
21 * 8MiB 1Mx16 4MiB 4MiB
22 * Thus, we choose CONFIG_MTD_CFI_I2 & CONFIG_MTD_CFI_B4 at
23 * kernel configuration.
24 */
25 #include <linux/module.h>
26 #include <linux/types.h>
27 #include <linux/kernel.h>
28 #include <linux/init.h>
29 #include <linux/slab.h>
31 #include <linux/mtd/mtd.h>
32 #include <linux/mtd/map.h>
33 #include <linux/mtd/partitions.h>
35 #include <asm/io.h>
37 #define FLASH_ADDR 0x40000000
38 #define FLASH_SIZE 0x00800000
39 #define FLASH_BANK_MAX 4
41 // trivial struct to describe partition information
42 struct mtd_part_def
43 {
44 int nums;
45 unsigned char *type;
46 struct mtd_partition* mtd_part;
47 };
49 //static struct mtd_info *mymtd;
50 static struct mtd_info* mtd_banks[FLASH_BANK_MAX];
51 static struct map_info* map_banks[FLASH_BANK_MAX];
52 static struct mtd_part_def part_banks[FLASH_BANK_MAX];
53 static unsigned long num_banks;
54 static void __iomem *start_scan_addr;
56 /*
57 * Here are partition information for all known TQM8xxL series devices.
58 * See include/linux/mtd/partitions.h for definition of the mtd_partition
59 * structure.
60 *
61 * The *_max_flash_size is the maximum possible mapped flash size which
62 * is not necessarily the actual flash size. It must correspond to the
63 * value specified in the mapping definition defined by the
64 * "struct map_desc *_io_desc" for the corresponding machine.
65 */
67 #ifdef CONFIG_MTD_PARTITIONS
68 /* Currently, TQM8xxL has upto 8MiB flash */
69 static unsigned long tqm8xxl_max_flash_size = 0x00800000;
71 /* partition definition for first flash bank
72 * (cf. "drivers/char/flash_config.c")
73 */
74 static struct mtd_partition tqm8xxl_partitions[] = {
75 {
76 .name = "ppcboot",
77 .offset = 0x00000000,
78 .size = 0x00020000, /* 128KB */
79 .mask_flags = MTD_WRITEABLE, /* force read-only */
80 },
81 {
82 .name = "kernel", /* default kernel image */
83 .offset = 0x00020000,
84 .size = 0x000e0000,
85 .mask_flags = MTD_WRITEABLE, /* force read-only */
86 },
87 {
88 .name = "user",
89 .offset = 0x00100000,
90 .size = 0x00100000,
91 },
92 {
93 .name = "initrd",
94 .offset = 0x00200000,
95 .size = 0x00200000,
96 }
97 };
98 /* partition definition for second flash bank */
99 static struct mtd_partition tqm8xxl_fs_partitions[] = {
100 {
101 .name = "cramfs",
102 .offset = 0x00000000,
103 .size = 0x00200000,
104 },
105 {
106 .name = "jffs",
107 .offset = 0x00200000,
108 .size = 0x00200000,
109 //.size = MTDPART_SIZ_FULL,
110 }
111 };
112 #endif
114 int __init init_tqm_mtd(void)
115 {
116 int idx = 0, ret = 0;
117 unsigned long flash_addr, flash_size, mtd_size = 0;
118 /* pointer to TQM8xxL board info data */
119 bd_t *bd = (bd_t *)__res;
121 flash_addr = bd->bi_flashstart;
122 flash_size = bd->bi_flashsize;
124 //request maximum flash size address space
125 start_scan_addr = ioremap(flash_addr, flash_size);
126 if (!start_scan_addr) {
127 printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr);
128 return -EIO;
129 }
131 for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
132 if(mtd_size >= flash_size)
133 break;
135 printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx);
137 map_banks[idx] = (struct map_info *)kmalloc(sizeof(struct map_info), GFP_KERNEL);
138 if(map_banks[idx] == NULL) {
139 ret = -ENOMEM;
140 /* FIXME: What if some MTD devices were probed already? */
141 goto error_mem;
142 }
144 memset((void *)map_banks[idx], 0, sizeof(struct map_info));
145 map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL);
147 if (!map_banks[idx]->name) {
148 ret = -ENOMEM;
149 /* FIXME: What if some MTD devices were probed already? */
150 goto error_mem;
151 }
152 sprintf(map_banks[idx]->name, "TQM8xxL%d", idx);
154 map_banks[idx]->size = flash_size;
155 map_banks[idx]->bankwidth = 4;
157 simple_map_init(map_banks[idx]);
159 map_banks[idx]->virt = start_scan_addr;
160 map_banks[idx]->phys = flash_addr;
161 /* FIXME: This looks utterly bogus, but I'm trying to
162 preserve the behaviour of the original (shown here)...
164 map_banks[idx]->map_priv_1 =
165 start_scan_addr + ((idx > 0) ?
166 (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0);
167 */
169 if (idx && mtd_banks[idx-1]) {
170 map_banks[idx]->virt += mtd_banks[idx-1]->size;
171 map_banks[idx]->phys += mtd_banks[idx-1]->size;
172 }
174 //start to probe flash chips
175 mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]);
177 if (mtd_banks[idx]) {
178 mtd_banks[idx]->owner = THIS_MODULE;
179 mtd_size += mtd_banks[idx]->size;
180 num_banks++;
182 printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks,
183 mtd_banks[idx]->name, mtd_banks[idx]->size);
184 }
185 }
187 /* no supported flash chips found */
188 if (!num_banks) {
189 printk(KERN_NOTICE "TQM8xxL: No support flash chips found!\n");
190 ret = -ENXIO;
191 goto error_mem;
192 }
194 #ifdef CONFIG_MTD_PARTITIONS
195 /*
196 * Select Static partition definitions
197 */
198 part_banks[0].mtd_part = tqm8xxl_partitions;
199 part_banks[0].type = "Static image";
200 part_banks[0].nums = ARRAY_SIZE(tqm8xxl_partitions);
202 part_banks[1].mtd_part = tqm8xxl_fs_partitions;
203 part_banks[1].type = "Static file system";
204 part_banks[1].nums = ARRAY_SIZE(tqm8xxl_fs_partitions);
206 for(idx = 0; idx < num_banks ; idx++) {
207 if (part_banks[idx].nums == 0) {
208 printk(KERN_NOTICE "TQM flash%d: no partition info available, registering whole flash at once\n", idx);
209 add_mtd_device(mtd_banks[idx]);
210 } else {
211 printk(KERN_NOTICE "TQM flash%d: Using %s partition definition\n",
212 idx, part_banks[idx].type);
213 add_mtd_partitions(mtd_banks[idx], part_banks[idx].mtd_part,
214 part_banks[idx].nums);
215 }
216 }
217 #else
218 printk(KERN_NOTICE "TQM flash: registering %d whole flash banks at once\n", num_banks);
219 for(idx = 0 ; idx < num_banks ; idx++)
220 add_mtd_device(mtd_banks[idx]);
221 #endif
222 return 0;
223 error_mem:
224 for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
225 if(map_banks[idx] != NULL) {
226 kfree(map_banks[idx]->name);
227 map_banks[idx]->name = NULL;
228 kfree(map_banks[idx]);
229 map_banks[idx] = NULL;
230 }
231 }
232 error:
233 iounmap(start_scan_addr);
234 return ret;
235 }
237 static void __exit cleanup_tqm_mtd(void)
238 {
239 unsigned int idx = 0;
240 for(idx = 0 ; idx < num_banks ; idx++) {
241 /* destroy mtd_info previously allocated */
242 if (mtd_banks[idx]) {
243 del_mtd_partitions(mtd_banks[idx]);
244 map_destroy(mtd_banks[idx]);
245 }
246 /* release map_info not used anymore */
247 kfree(map_banks[idx]->name);
248 kfree(map_banks[idx]);
249 }
251 if (start_scan_addr) {
252 iounmap(start_scan_addr);
253 start_scan_addr = 0;
254 }
255 }
257 module_init(init_tqm_mtd);
258 module_exit(cleanup_tqm_mtd);
260 MODULE_LICENSE("GPL");
261 MODULE_AUTHOR("Kirk Lee <kirk@hpc.ee.ntu.edu.tw>");
262 MODULE_DESCRIPTION("MTD map driver for TQM8xxL boards");