ia64/linux-2.6.18-xen.hg

view drivers/mtd/maps/ichxrom.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 * ichxrom.c
3 *
4 * Normal mappings of chips in physical memory
5 * $Id: ichxrom.c,v 1.19 2005/11/07 11:14:27 gleixner Exp $
6 */
8 #include <linux/module.h>
9 #include <linux/types.h>
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <asm/io.h>
13 #include <linux/mtd/mtd.h>
14 #include <linux/mtd/map.h>
15 #include <linux/mtd/cfi.h>
16 #include <linux/mtd/flashchip.h>
17 #include <linux/pci.h>
18 #include <linux/pci_ids.h>
19 #include <linux/list.h>
21 #define xstr(s) str(s)
22 #define str(s) #s
23 #define MOD_NAME xstr(KBUILD_BASENAME)
25 #define ADDRESS_NAME_LEN 18
27 #define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
29 #define BIOS_CNTL 0x4e
30 #define FWH_DEC_EN1 0xE3
31 #define FWH_DEC_EN2 0xF0
32 #define FWH_SEL1 0xE8
33 #define FWH_SEL2 0xEE
35 struct ichxrom_window {
36 void __iomem* virt;
37 unsigned long phys;
38 unsigned long size;
39 struct list_head maps;
40 struct resource rsrc;
41 struct pci_dev *pdev;
42 };
44 struct ichxrom_map_info {
45 struct list_head list;
46 struct map_info map;
47 struct mtd_info *mtd;
48 struct resource rsrc;
49 char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
50 };
52 static struct ichxrom_window ichxrom_window = {
53 .maps = LIST_HEAD_INIT(ichxrom_window.maps),
54 };
56 static void ichxrom_cleanup(struct ichxrom_window *window)
57 {
58 struct ichxrom_map_info *map, *scratch;
59 u16 word;
61 /* Disable writes through the rom window */
62 pci_read_config_word(window->pdev, BIOS_CNTL, &word);
63 pci_write_config_word(window->pdev, BIOS_CNTL, word & ~1);
65 /* Free all of the mtd devices */
66 list_for_each_entry_safe(map, scratch, &window->maps, list) {
67 if (map->rsrc.parent)
68 release_resource(&map->rsrc);
69 del_mtd_device(map->mtd);
70 map_destroy(map->mtd);
71 list_del(&map->list);
72 kfree(map);
73 }
74 if (window->rsrc.parent)
75 release_resource(&window->rsrc);
76 if (window->virt) {
77 iounmap(window->virt);
78 window->virt = NULL;
79 window->phys = 0;
80 window->size = 0;
81 window->pdev = NULL;
82 }
83 }
86 static int __devinit ichxrom_init_one (struct pci_dev *pdev,
87 const struct pci_device_id *ent)
88 {
89 static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
90 struct ichxrom_window *window = &ichxrom_window;
91 struct ichxrom_map_info *map = NULL;
92 unsigned long map_top;
93 u8 byte;
94 u16 word;
96 /* For now I just handle the ichx and I assume there
97 * are not a lot of resources up at the top of the address
98 * space. It is possible to handle other devices in the
99 * top 16MB but it is very painful. Also since
100 * you can only really attach a FWH to an ICHX there
101 * a number of simplifications you can make.
102 *
103 * Also you can page firmware hubs if an 8MB window isn't enough
104 * but don't currently handle that case either.
105 */
106 window->pdev = pdev;
108 /* Find a region continuous to the end of the ROM window */
109 window->phys = 0;
110 pci_read_config_byte(pdev, FWH_DEC_EN1, &byte);
111 if (byte == 0xff) {
112 window->phys = 0xffc00000;
113 pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
114 if ((byte & 0x0f) == 0x0f) {
115 window->phys = 0xff400000;
116 }
117 else if ((byte & 0x0e) == 0x0e) {
118 window->phys = 0xff500000;
119 }
120 else if ((byte & 0x0c) == 0x0c) {
121 window->phys = 0xff600000;
122 }
123 else if ((byte & 0x08) == 0x08) {
124 window->phys = 0xff700000;
125 }
126 }
127 else if ((byte & 0xfe) == 0xfe) {
128 window->phys = 0xffc80000;
129 }
130 else if ((byte & 0xfc) == 0xfc) {
131 window->phys = 0xffd00000;
132 }
133 else if ((byte & 0xf8) == 0xf8) {
134 window->phys = 0xffd80000;
135 }
136 else if ((byte & 0xf0) == 0xf0) {
137 window->phys = 0xffe00000;
138 }
139 else if ((byte & 0xe0) == 0xe0) {
140 window->phys = 0xffe80000;
141 }
142 else if ((byte & 0xc0) == 0xc0) {
143 window->phys = 0xfff00000;
144 }
145 else if ((byte & 0x80) == 0x80) {
146 window->phys = 0xfff80000;
147 }
149 if (window->phys == 0) {
150 printk(KERN_ERR MOD_NAME ": Rom window is closed\n");
151 goto out;
152 }
153 window->phys -= 0x400000UL;
154 window->size = (0xffffffffUL - window->phys) + 1UL;
156 /* Enable writes through the rom window */
157 pci_read_config_word(pdev, BIOS_CNTL, &word);
158 if (!(word & 1) && (word & (1<<1))) {
159 /* The BIOS will generate an error if I enable
160 * this device, so don't even try.
161 */
162 printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n");
163 goto out;
164 }
165 pci_write_config_word(pdev, BIOS_CNTL, word | 1);
167 /*
168 * Try to reserve the window mem region. If this fails then
169 * it is likely due to the window being "reseved" by the BIOS.
170 */
171 window->rsrc.name = MOD_NAME;
172 window->rsrc.start = window->phys;
173 window->rsrc.end = window->phys + window->size - 1;
174 window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
175 if (request_resource(&iomem_resource, &window->rsrc)) {
176 window->rsrc.parent = NULL;
177 printk(KERN_DEBUG MOD_NAME
178 ": %s(): Unable to register resource"
179 " 0x%.16llx-0x%.16llx - kernel bug?\n",
180 __func__,
181 (unsigned long long)window->rsrc.start,
182 (unsigned long long)window->rsrc.end);
183 }
185 /* Map the firmware hub into my address space. */
186 window->virt = ioremap_nocache(window->phys, window->size);
187 if (!window->virt) {
188 printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
189 window->phys, window->size);
190 goto out;
191 }
193 /* Get the first address to look for an rom chip at */
194 map_top = window->phys;
195 if ((window->phys & 0x3fffff) != 0) {
196 map_top = window->phys + 0x400000;
197 }
198 #if 1
199 /* The probe sequence run over the firmware hub lock
200 * registers sets them to 0x7 (no access).
201 * Probe at most the last 4M of the address space.
202 */
203 if (map_top < 0xffc00000) {
204 map_top = 0xffc00000;
205 }
206 #endif
207 /* Loop through and look for rom chips */
208 while((map_top - 1) < 0xffffffffUL) {
209 struct cfi_private *cfi;
210 unsigned long offset;
211 int i;
213 if (!map) {
214 map = kmalloc(sizeof(*map), GFP_KERNEL);
215 }
216 if (!map) {
217 printk(KERN_ERR MOD_NAME ": kmalloc failed");
218 goto out;
219 }
220 memset(map, 0, sizeof(*map));
221 INIT_LIST_HEAD(&map->list);
222 map->map.name = map->map_name;
223 map->map.phys = map_top;
224 offset = map_top - window->phys;
225 map->map.virt = (void __iomem *)
226 (((unsigned long)(window->virt)) + offset);
227 map->map.size = 0xffffffffUL - map_top + 1UL;
228 /* Set the name of the map to the address I am trying */
229 sprintf(map->map_name, "%s @%08lx",
230 MOD_NAME, map->map.phys);
232 /* Firmware hubs only use vpp when being programmed
233 * in a factory setting. So in-place programming
234 * needs to use a different method.
235 */
236 for(map->map.bankwidth = 32; map->map.bankwidth;
237 map->map.bankwidth >>= 1)
238 {
239 char **probe_type;
240 /* Skip bankwidths that are not supported */
241 if (!map_bankwidth_supported(map->map.bankwidth))
242 continue;
244 /* Setup the map methods */
245 simple_map_init(&map->map);
247 /* Try all of the probe methods */
248 probe_type = rom_probe_types;
249 for(; *probe_type; probe_type++) {
250 map->mtd = do_map_probe(*probe_type, &map->map);
251 if (map->mtd)
252 goto found;
253 }
254 }
255 map_top += ROM_PROBE_STEP_SIZE;
256 continue;
257 found:
258 /* Trim the size if we are larger than the map */
259 if (map->mtd->size > map->map.size) {
260 printk(KERN_WARNING MOD_NAME
261 " rom(%u) larger than window(%lu). fixing...\n",
262 map->mtd->size, map->map.size);
263 map->mtd->size = map->map.size;
264 }
265 if (window->rsrc.parent) {
266 /*
267 * Registering the MTD device in iomem may not be possible
268 * if there is a BIOS "reserved" and BUSY range. If this
269 * fails then continue anyway.
270 */
271 map->rsrc.name = map->map_name;
272 map->rsrc.start = map->map.phys;
273 map->rsrc.end = map->map.phys + map->mtd->size - 1;
274 map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
275 if (request_resource(&window->rsrc, &map->rsrc)) {
276 printk(KERN_ERR MOD_NAME
277 ": cannot reserve MTD resource\n");
278 map->rsrc.parent = NULL;
279 }
280 }
282 /* Make the whole region visible in the map */
283 map->map.virt = window->virt;
284 map->map.phys = window->phys;
285 cfi = map->map.fldrv_priv;
286 for(i = 0; i < cfi->numchips; i++) {
287 cfi->chips[i].start += offset;
288 }
290 /* Now that the mtd devices is complete claim and export it */
291 map->mtd->owner = THIS_MODULE;
292 if (add_mtd_device(map->mtd)) {
293 map_destroy(map->mtd);
294 map->mtd = NULL;
295 goto out;
296 }
299 /* Calculate the new value of map_top */
300 map_top += map->mtd->size;
302 /* File away the map structure */
303 list_add(&map->list, &window->maps);
304 map = NULL;
305 }
307 out:
308 /* Free any left over map structures */
309 kfree(map);
311 /* See if I have any map structures */
312 if (list_empty(&window->maps)) {
313 ichxrom_cleanup(window);
314 return -ENODEV;
315 }
316 return 0;
317 }
320 static void __devexit ichxrom_remove_one (struct pci_dev *pdev)
321 {
322 struct ichxrom_window *window = &ichxrom_window;
323 ichxrom_cleanup(window);
324 }
326 static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = {
327 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
328 PCI_ANY_ID, PCI_ANY_ID, },
329 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
330 PCI_ANY_ID, PCI_ANY_ID, },
331 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
332 PCI_ANY_ID, PCI_ANY_ID, },
333 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
334 PCI_ANY_ID, PCI_ANY_ID, },
335 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
336 PCI_ANY_ID, PCI_ANY_ID, },
337 { 0, },
338 };
340 #if 0
341 MODULE_DEVICE_TABLE(pci, ichxrom_pci_tbl);
343 static struct pci_driver ichxrom_driver = {
344 .name = MOD_NAME,
345 .id_table = ichxrom_pci_tbl,
346 .probe = ichxrom_init_one,
347 .remove = ichxrom_remove_one,
348 };
349 #endif
351 static int __init init_ichxrom(void)
352 {
353 struct pci_dev *pdev;
354 struct pci_device_id *id;
356 pdev = NULL;
357 for (id = ichxrom_pci_tbl; id->vendor; id++) {
358 pdev = pci_find_device(id->vendor, id->device, NULL);
359 if (pdev) {
360 break;
361 }
362 }
363 if (pdev) {
364 return ichxrom_init_one(pdev, &ichxrom_pci_tbl[0]);
365 }
366 return -ENXIO;
367 #if 0
368 return pci_register_driver(&ichxrom_driver);
369 #endif
370 }
372 static void __exit cleanup_ichxrom(void)
373 {
374 ichxrom_remove_one(ichxrom_window.pdev);
375 }
377 module_init(init_ichxrom);
378 module_exit(cleanup_ichxrom);
380 MODULE_LICENSE("GPL");
381 MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
382 MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ICHX southbridge");