ia64/linux-2.6.18-xen.hg

view drivers/mtd/maps/octagon-5066.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 // $Id: octagon-5066.c,v 1.28 2005/11/07 11:14:27 gleixner Exp $
2 /* ######################################################################
4 Octagon 5066 MTD Driver.
6 The Octagon 5066 is a SBC based on AMD's 586-WB running at 133 MHZ. It
7 comes with a builtin AMD 29F016 flash chip and a socketed EEPROM that
8 is replacable by flash. Both units are mapped through a multiplexer
9 into a 32k memory window at 0xe8000. The control register for the
10 multiplexing unit is located at IO 0x208 with a bit map of
11 0-5 Page Selection in 32k increments
12 6-7 Device selection:
13 00 SSD off
14 01 SSD 0 (Socket)
15 10 SSD 1 (Flash chip)
16 11 undefined
18 On each SSD, the first 128k is reserved for use by the bios
19 (actually it IS the bios..) This only matters if you are booting off the
20 flash, you must not put a file system starting there.
22 The driver tries to do a detection algorithm to guess what sort of devices
23 are plugged into the sockets.
25 ##################################################################### */
27 #include <linux/module.h>
28 #include <linux/slab.h>
29 #include <linux/ioport.h>
30 #include <linux/init.h>
31 #include <asm/io.h>
33 #include <linux/mtd/map.h>
34 #include <linux/mtd/mtd.h>
36 #define WINDOW_START 0xe8000
37 #define WINDOW_LENGTH 0x8000
38 #define WINDOW_SHIFT 27
39 #define WINDOW_MASK 0x7FFF
40 #define PAGE_IO 0x208
42 static volatile char page_n_dev = 0;
43 static unsigned long iomapadr;
44 static DEFINE_SPINLOCK(oct5066_spin);
46 /*
47 * We use map_priv_1 to identify which device we are.
48 */
50 static void __oct5066_page(struct map_info *map, __u8 byte)
51 {
52 outb(byte,PAGE_IO);
53 page_n_dev = byte;
54 }
56 static inline void oct5066_page(struct map_info *map, unsigned long ofs)
57 {
58 __u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT);
60 if (page_n_dev != byte)
61 __oct5066_page(map, byte);
62 }
65 static map_word oct5066_read8(struct map_info *map, unsigned long ofs)
66 {
67 map_word ret;
68 spin_lock(&oct5066_spin);
69 oct5066_page(map, ofs);
70 ret.x[0] = readb(iomapadr + (ofs & WINDOW_MASK));
71 spin_unlock(&oct5066_spin);
72 return ret;
73 }
75 static void oct5066_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
76 {
77 while(len) {
78 unsigned long thislen = len;
79 if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
80 thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
82 spin_lock(&oct5066_spin);
83 oct5066_page(map, from);
84 memcpy_fromio(to, iomapadr + from, thislen);
85 spin_unlock(&oct5066_spin);
86 to += thislen;
87 from += thislen;
88 len -= thislen;
89 }
90 }
92 static void oct5066_write8(struct map_info *map, map_word d, unsigned long adr)
93 {
94 spin_lock(&oct5066_spin);
95 oct5066_page(map, adr);
96 writeb(d.x[0], iomapadr + (adr & WINDOW_MASK));
97 spin_unlock(&oct5066_spin);
98 }
100 static void oct5066_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
101 {
102 while(len) {
103 unsigned long thislen = len;
104 if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
105 thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
107 spin_lock(&oct5066_spin);
108 oct5066_page(map, to);
109 memcpy_toio(iomapadr + to, from, thislen);
110 spin_unlock(&oct5066_spin);
111 to += thislen;
112 from += thislen;
113 len -= thislen;
114 }
115 }
117 static struct map_info oct5066_map[2] = {
118 {
119 .name = "Octagon 5066 Socket",
120 .phys = NO_XIP,
121 .size = 512 * 1024,
122 .bankwidth = 1,
123 .read = oct5066_read8,
124 .copy_from = oct5066_copy_from,
125 .write = oct5066_write8,
126 .copy_to = oct5066_copy_to,
127 .map_priv_1 = 1<<6
128 },
129 {
130 .name = "Octagon 5066 Internal Flash",
131 .phys = NO_XIP,
132 .size = 2 * 1024 * 1024,
133 .bankwidth = 1,
134 .read = oct5066_read8,
135 .copy_from = oct5066_copy_from,
136 .write = oct5066_write8,
137 .copy_to = oct5066_copy_to,
138 .map_priv_1 = 2<<6
139 }
140 };
142 static struct mtd_info *oct5066_mtd[2] = {NULL, NULL};
144 // OctProbe - Sense if this is an octagon card
145 // ---------------------------------------------------------------------
146 /* Perform a simple validity test, we map the window select SSD0 and
147 change pages while monitoring the window. A change in the window,
148 controlled by the PAGE_IO port is a functioning 5066 board. This will
149 fail if the thing in the socket is set to a uniform value. */
150 static int __init OctProbe(void)
151 {
152 unsigned int Base = (1 << 6);
153 unsigned long I;
154 unsigned long Values[10];
155 for (I = 0; I != 20; I++)
156 {
157 outb(Base + (I%10),PAGE_IO);
158 if (I < 10)
159 {
160 // Record the value and check for uniqueness
161 Values[I%10] = readl(iomapadr);
162 if (I > 0 && Values[I%10] == Values[0])
163 return -EAGAIN;
164 }
165 else
166 {
167 // Make sure we get the same values on the second pass
168 if (Values[I%10] != readl(iomapadr))
169 return -EAGAIN;
170 }
171 }
172 return 0;
173 }
175 void cleanup_oct5066(void)
176 {
177 int i;
178 for (i=0; i<2; i++) {
179 if (oct5066_mtd[i]) {
180 del_mtd_device(oct5066_mtd[i]);
181 map_destroy(oct5066_mtd[i]);
182 }
183 }
184 iounmap((void *)iomapadr);
185 release_region(PAGE_IO, 1);
186 }
188 int __init init_oct5066(void)
189 {
190 int i;
191 int ret = 0;
193 // Do an autoprobe sequence
194 if (!request_region(PAGE_IO,1,"Octagon SSD")) {
195 printk(KERN_NOTICE "5066: Page Register in Use\n");
196 return -EAGAIN;
197 }
198 iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH);
199 if (!iomapadr) {
200 printk(KERN_NOTICE "Failed to ioremap memory region\n");
201 ret = -EIO;
202 goto out_rel;
203 }
204 if (OctProbe() != 0) {
205 printk(KERN_NOTICE "5066: Octagon Probe Failed, is this an Octagon 5066 SBC?\n");
206 iounmap((void *)iomapadr);
207 ret = -EAGAIN;
208 goto out_unmap;
209 }
211 // Print out our little header..
212 printk("Octagon 5066 SSD IO:0x%x MEM:0x%x-0x%x\n",PAGE_IO,WINDOW_START,
213 WINDOW_START+WINDOW_LENGTH);
215 for (i=0; i<2; i++) {
216 oct5066_mtd[i] = do_map_probe("cfi_probe", &oct5066_map[i]);
217 if (!oct5066_mtd[i])
218 oct5066_mtd[i] = do_map_probe("jedec", &oct5066_map[i]);
219 if (!oct5066_mtd[i])
220 oct5066_mtd[i] = do_map_probe("map_ram", &oct5066_map[i]);
221 if (!oct5066_mtd[i])
222 oct5066_mtd[i] = do_map_probe("map_rom", &oct5066_map[i]);
223 if (oct5066_mtd[i]) {
224 oct5066_mtd[i]->owner = THIS_MODULE;
225 add_mtd_device(oct5066_mtd[i]);
226 }
227 }
229 if (!oct5066_mtd[0] && !oct5066_mtd[1]) {
230 cleanup_oct5066();
231 return -ENXIO;
232 }
234 return 0;
236 out_unmap:
237 iounmap((void *)iomapadr);
238 out_rel:
239 release_region(PAGE_IO, 1);
240 return ret;
241 }
243 module_init(init_oct5066);
244 module_exit(cleanup_oct5066);
246 MODULE_LICENSE("GPL");
247 MODULE_AUTHOR("Jason Gunthorpe <jgg@deltatee.com>, David Woodhouse <dwmw2@infradead.org>");
248 MODULE_DESCRIPTION("MTD map driver for Octagon 5066 Single Board Computer");