ia64/linux-2.6.18-xen.hg

view drivers/mtd/maps/amd76xrom.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 * amd76xrom.c
3 *
4 * Normal mappings of chips in physical memory
5 * $Id: amd76xrom.c,v 1.21 2005/11/07 11:14:26 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>
22 #define xstr(s) str(s)
23 #define str(s) #s
24 #define MOD_NAME xstr(KBUILD_BASENAME)
26 #define ADDRESS_NAME_LEN 18
28 #define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
30 struct amd76xrom_window {
31 void __iomem *virt;
32 unsigned long phys;
33 unsigned long size;
34 struct list_head maps;
35 struct resource rsrc;
36 struct pci_dev *pdev;
37 };
39 struct amd76xrom_map_info {
40 struct list_head list;
41 struct map_info map;
42 struct mtd_info *mtd;
43 struct resource rsrc;
44 char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
45 };
47 static struct amd76xrom_window amd76xrom_window = {
48 .maps = LIST_HEAD_INIT(amd76xrom_window.maps),
49 };
51 static void amd76xrom_cleanup(struct amd76xrom_window *window)
52 {
53 struct amd76xrom_map_info *map, *scratch;
54 u8 byte;
56 if (window->pdev) {
57 /* Disable writes through the rom window */
58 pci_read_config_byte(window->pdev, 0x40, &byte);
59 pci_write_config_byte(window->pdev, 0x40, byte & ~1);
60 }
62 /* Free all of the mtd devices */
63 list_for_each_entry_safe(map, scratch, &window->maps, list) {
64 if (map->rsrc.parent) {
65 release_resource(&map->rsrc);
66 }
67 del_mtd_device(map->mtd);
68 map_destroy(map->mtd);
69 list_del(&map->list);
70 kfree(map);
71 }
72 if (window->rsrc.parent)
73 release_resource(&window->rsrc);
75 if (window->virt) {
76 iounmap(window->virt);
77 window->virt = NULL;
78 window->phys = 0;
79 window->size = 0;
80 window->pdev = NULL;
81 }
82 }
85 static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
86 const struct pci_device_id *ent)
87 {
88 static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
89 u8 byte;
90 struct amd76xrom_window *window = &amd76xrom_window;
91 struct amd76xrom_map_info *map = NULL;
92 unsigned long map_top;
94 /* Remember the pci dev I find the window in */
95 window->pdev = pdev;
97 /* Assume the rom window is properly setup, and find it's size */
98 pci_read_config_byte(pdev, 0x43, &byte);
99 if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) {
100 window->phys = 0xffb00000; /* 5MiB */
101 }
102 else if ((byte & (1<<7)) == (1<<7)) {
103 window->phys = 0xffc00000; /* 4MiB */
104 }
105 else {
106 window->phys = 0xffff0000; /* 64KiB */
107 }
108 window->size = 0xffffffffUL - window->phys + 1UL;
110 /*
111 * Try to reserve the window mem region. If this fails then
112 * it is likely due to a fragment of the window being
113 * "reseved" by the BIOS. In the case that the
114 * request_mem_region() fails then once the rom size is
115 * discovered we will try to reserve the unreserved fragment.
116 */
117 window->rsrc.name = MOD_NAME;
118 window->rsrc.start = window->phys;
119 window->rsrc.end = window->phys + window->size - 1;
120 window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
121 if (request_resource(&iomem_resource, &window->rsrc)) {
122 window->rsrc.parent = NULL;
123 printk(KERN_ERR MOD_NAME
124 " %s(): Unable to register resource"
125 " 0x%.16llx-0x%.16llx - kernel bug?\n",
126 __func__,
127 (unsigned long long)window->rsrc.start,
128 (unsigned long long)window->rsrc.end);
129 }
131 #if 0
133 /* Enable the selected rom window */
134 pci_read_config_byte(pdev, 0x43, &byte);
135 pci_write_config_byte(pdev, 0x43, byte | rwindow->segen_bits);
136 #endif
138 /* Enable writes through the rom window */
139 pci_read_config_byte(pdev, 0x40, &byte);
140 pci_write_config_byte(pdev, 0x40, byte | 1);
142 /* FIXME handle registers 0x80 - 0x8C the bios region locks */
144 /* For write accesses caches are useless */
145 window->virt = ioremap_nocache(window->phys, window->size);
146 if (!window->virt) {
147 printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
148 window->phys, window->size);
149 goto out;
150 }
152 /* Get the first address to look for an rom chip at */
153 map_top = window->phys;
154 #if 1
155 /* The probe sequence run over the firmware hub lock
156 * registers sets them to 0x7 (no access).
157 * Probe at most the last 4M of the address space.
158 */
159 if (map_top < 0xffc00000) {
160 map_top = 0xffc00000;
161 }
162 #endif
163 /* Loop through and look for rom chips */
164 while((map_top - 1) < 0xffffffffUL) {
165 struct cfi_private *cfi;
166 unsigned long offset;
167 int i;
169 if (!map) {
170 map = kmalloc(sizeof(*map), GFP_KERNEL);
171 }
172 if (!map) {
173 printk(KERN_ERR MOD_NAME ": kmalloc failed");
174 goto out;
175 }
176 memset(map, 0, sizeof(*map));
177 INIT_LIST_HEAD(&map->list);
178 map->map.name = map->map_name;
179 map->map.phys = map_top;
180 offset = map_top - window->phys;
181 map->map.virt = (void __iomem *)
182 (((unsigned long)(window->virt)) + offset);
183 map->map.size = 0xffffffffUL - map_top + 1UL;
184 /* Set the name of the map to the address I am trying */
185 sprintf(map->map_name, "%s @%08lx",
186 MOD_NAME, map->map.phys);
188 /* There is no generic VPP support */
189 for(map->map.bankwidth = 32; map->map.bankwidth;
190 map->map.bankwidth >>= 1)
191 {
192 char **probe_type;
193 /* Skip bankwidths that are not supported */
194 if (!map_bankwidth_supported(map->map.bankwidth))
195 continue;
197 /* Setup the map methods */
198 simple_map_init(&map->map);
200 /* Try all of the probe methods */
201 probe_type = rom_probe_types;
202 for(; *probe_type; probe_type++) {
203 map->mtd = do_map_probe(*probe_type, &map->map);
204 if (map->mtd)
205 goto found;
206 }
207 }
208 map_top += ROM_PROBE_STEP_SIZE;
209 continue;
210 found:
211 /* Trim the size if we are larger than the map */
212 if (map->mtd->size > map->map.size) {
213 printk(KERN_WARNING MOD_NAME
214 " rom(%u) larger than window(%lu). fixing...\n",
215 map->mtd->size, map->map.size);
216 map->mtd->size = map->map.size;
217 }
218 if (window->rsrc.parent) {
219 /*
220 * Registering the MTD device in iomem may not be possible
221 * if there is a BIOS "reserved" and BUSY range. If this
222 * fails then continue anyway.
223 */
224 map->rsrc.name = map->map_name;
225 map->rsrc.start = map->map.phys;
226 map->rsrc.end = map->map.phys + map->mtd->size - 1;
227 map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
228 if (request_resource(&window->rsrc, &map->rsrc)) {
229 printk(KERN_ERR MOD_NAME
230 ": cannot reserve MTD resource\n");
231 map->rsrc.parent = NULL;
232 }
233 }
235 /* Make the whole region visible in the map */
236 map->map.virt = window->virt;
237 map->map.phys = window->phys;
238 cfi = map->map.fldrv_priv;
239 for(i = 0; i < cfi->numchips; i++) {
240 cfi->chips[i].start += offset;
241 }
243 /* Now that the mtd devices is complete claim and export it */
244 map->mtd->owner = THIS_MODULE;
245 if (add_mtd_device(map->mtd)) {
246 map_destroy(map->mtd);
247 map->mtd = NULL;
248 goto out;
249 }
252 /* Calculate the new value of map_top */
253 map_top += map->mtd->size;
255 /* File away the map structure */
256 list_add(&map->list, &window->maps);
257 map = NULL;
258 }
260 out:
261 /* Free any left over map structures */
262 kfree(map);
263 /* See if I have any map structures */
264 if (list_empty(&window->maps)) {
265 amd76xrom_cleanup(window);
266 return -ENODEV;
267 }
268 return 0;
269 }
272 static void __devexit amd76xrom_remove_one (struct pci_dev *pdev)
273 {
274 struct amd76xrom_window *window = &amd76xrom_window;
276 amd76xrom_cleanup(window);
277 }
279 static struct pci_device_id amd76xrom_pci_tbl[] = {
280 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410,
281 PCI_ANY_ID, PCI_ANY_ID, },
282 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7440,
283 PCI_ANY_ID, PCI_ANY_ID, },
284 { PCI_VENDOR_ID_AMD, 0x7468 }, /* amd8111 support */
285 { 0, }
286 };
288 MODULE_DEVICE_TABLE(pci, amd76xrom_pci_tbl);
290 #if 0
291 static struct pci_driver amd76xrom_driver = {
292 .name = MOD_NAME,
293 .id_table = amd76xrom_pci_tbl,
294 .probe = amd76xrom_init_one,
295 .remove = amd76xrom_remove_one,
296 };
297 #endif
299 static int __init init_amd76xrom(void)
300 {
301 struct pci_dev *pdev;
302 struct pci_device_id *id;
303 pdev = NULL;
304 for(id = amd76xrom_pci_tbl; id->vendor; id++) {
305 pdev = pci_find_device(id->vendor, id->device, NULL);
306 if (pdev) {
307 break;
308 }
309 }
310 if (pdev) {
311 return amd76xrom_init_one(pdev, &amd76xrom_pci_tbl[0]);
312 }
313 return -ENXIO;
314 #if 0
315 return pci_register_driver(&amd76xrom_driver);
316 #endif
317 }
319 static void __exit cleanup_amd76xrom(void)
320 {
321 amd76xrom_remove_one(amd76xrom_window.pdev);
322 }
324 module_init(init_amd76xrom);
325 module_exit(cleanup_amd76xrom);
327 MODULE_LICENSE("GPL");
328 MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
329 MODULE_DESCRIPTION("MTD map driver for BIOS chips on the AMD76X southbridge");