ia64/linux-2.6.18-xen.hg

annotate drivers/mtd/maps/pci.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
rev   line source
ian@0 1 /*
ian@0 2 * linux/drivers/mtd/maps/pci.c
ian@0 3 *
ian@0 4 * Copyright (C) 2001 Russell King, All rights reserved.
ian@0 5 *
ian@0 6 * This program is free software; you can redistribute it and/or modify
ian@0 7 * it under the terms of the GNU General Public License version 2 as
ian@0 8 * published by the Free Software Foundation.
ian@0 9 *
ian@0 10 * $Id: pci.c,v 1.14 2005/11/17 08:20:27 dwmw2 Exp $
ian@0 11 *
ian@0 12 * Generic PCI memory map driver. We support the following boards:
ian@0 13 * - Intel IQ80310 ATU.
ian@0 14 * - Intel EBSA285 (blank rom programming mode). Tested working 27/09/2001
ian@0 15 */
ian@0 16 #include <linux/module.h>
ian@0 17 #include <linux/kernel.h>
ian@0 18 #include <linux/pci.h>
ian@0 19 #include <linux/init.h>
ian@0 20 #include <linux/slab.h>
ian@0 21
ian@0 22 #include <linux/mtd/mtd.h>
ian@0 23 #include <linux/mtd/map.h>
ian@0 24 #include <linux/mtd/partitions.h>
ian@0 25
ian@0 26 struct map_pci_info;
ian@0 27
ian@0 28 struct mtd_pci_info {
ian@0 29 int (*init)(struct pci_dev *dev, struct map_pci_info *map);
ian@0 30 void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
ian@0 31 unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
ian@0 32 const char *map_name;
ian@0 33 };
ian@0 34
ian@0 35 struct map_pci_info {
ian@0 36 struct map_info map;
ian@0 37 void __iomem *base;
ian@0 38 void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
ian@0 39 unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
ian@0 40 struct pci_dev *dev;
ian@0 41 };
ian@0 42
ian@0 43 static map_word mtd_pci_read8(struct map_info *_map, unsigned long ofs)
ian@0 44 {
ian@0 45 struct map_pci_info *map = (struct map_pci_info *)_map;
ian@0 46 map_word val;
ian@0 47 val.x[0]= readb(map->base + map->translate(map, ofs));
ian@0 48 // printk("read8 : %08lx => %02x\n", ofs, val.x[0]);
ian@0 49 return val;
ian@0 50 }
ian@0 51
ian@0 52 #if 0
ian@0 53 static map_word mtd_pci_read16(struct map_info *_map, unsigned long ofs)
ian@0 54 {
ian@0 55 struct map_pci_info *map = (struct map_pci_info *)_map;
ian@0 56 map_word val;
ian@0 57 val.x[0] = readw(map->base + map->translate(map, ofs));
ian@0 58 // printk("read16: %08lx => %04x\n", ofs, val.x[0]);
ian@0 59 return val;
ian@0 60 }
ian@0 61 #endif
ian@0 62 static map_word mtd_pci_read32(struct map_info *_map, unsigned long ofs)
ian@0 63 {
ian@0 64 struct map_pci_info *map = (struct map_pci_info *)_map;
ian@0 65 map_word val;
ian@0 66 val.x[0] = readl(map->base + map->translate(map, ofs));
ian@0 67 // printk("read32: %08lx => %08x\n", ofs, val.x[0]);
ian@0 68 return val;
ian@0 69 }
ian@0 70
ian@0 71 static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len)
ian@0 72 {
ian@0 73 struct map_pci_info *map = (struct map_pci_info *)_map;
ian@0 74 memcpy_fromio(to, map->base + map->translate(map, from), len);
ian@0 75 }
ian@0 76
ian@0 77 static void mtd_pci_write8(struct map_info *_map, map_word val, unsigned long ofs)
ian@0 78 {
ian@0 79 struct map_pci_info *map = (struct map_pci_info *)_map;
ian@0 80 // printk("write8 : %08lx <= %02x\n", ofs, val.x[0]);
ian@0 81 writeb(val.x[0], map->base + map->translate(map, ofs));
ian@0 82 }
ian@0 83
ian@0 84 #if 0
ian@0 85 static void mtd_pci_write16(struct map_info *_map, map_word val, unsigned long ofs)
ian@0 86 {
ian@0 87 struct map_pci_info *map = (struct map_pci_info *)_map;
ian@0 88 // printk("write16: %08lx <= %04x\n", ofs, val.x[0]);
ian@0 89 writew(val.x[0], map->base + map->translate(map, ofs));
ian@0 90 }
ian@0 91 #endif
ian@0 92 static void mtd_pci_write32(struct map_info *_map, map_word val, unsigned long ofs)
ian@0 93 {
ian@0 94 struct map_pci_info *map = (struct map_pci_info *)_map;
ian@0 95 // printk("write32: %08lx <= %08x\n", ofs, val.x[0]);
ian@0 96 writel(val.x[0], map->base + map->translate(map, ofs));
ian@0 97 }
ian@0 98
ian@0 99 static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len)
ian@0 100 {
ian@0 101 struct map_pci_info *map = (struct map_pci_info *)_map;
ian@0 102 memcpy_toio(map->base + map->translate(map, to), from, len);
ian@0 103 }
ian@0 104
ian@0 105 static const struct map_info mtd_pci_map = {
ian@0 106 .phys = NO_XIP,
ian@0 107 .copy_from = mtd_pci_copyfrom,
ian@0 108 .copy_to = mtd_pci_copyto,
ian@0 109 };
ian@0 110
ian@0 111 /*
ian@0 112 * Intel IOP80310 Flash driver
ian@0 113 */
ian@0 114
ian@0 115 static int
ian@0 116 intel_iq80310_init(struct pci_dev *dev, struct map_pci_info *map)
ian@0 117 {
ian@0 118 u32 win_base;
ian@0 119
ian@0 120 map->map.bankwidth = 1;
ian@0 121 map->map.read = mtd_pci_read8,
ian@0 122 map->map.write = mtd_pci_write8,
ian@0 123
ian@0 124 map->map.size = 0x00800000;
ian@0 125 map->base = ioremap_nocache(pci_resource_start(dev, 0),
ian@0 126 pci_resource_len(dev, 0));
ian@0 127
ian@0 128 if (!map->base)
ian@0 129 return -ENOMEM;
ian@0 130
ian@0 131 /*
ian@0 132 * We want to base the memory window at Xscale
ian@0 133 * bus address 0, not 0x1000.
ian@0 134 */
ian@0 135 pci_read_config_dword(dev, 0x44, &win_base);
ian@0 136 pci_write_config_dword(dev, 0x44, 0);
ian@0 137
ian@0 138 map->map.map_priv_2 = win_base;
ian@0 139
ian@0 140 return 0;
ian@0 141 }
ian@0 142
ian@0 143 static void
ian@0 144 intel_iq80310_exit(struct pci_dev *dev, struct map_pci_info *map)
ian@0 145 {
ian@0 146 if (map->base)
ian@0 147 iounmap(map->base);
ian@0 148 pci_write_config_dword(dev, 0x44, map->map.map_priv_2);
ian@0 149 }
ian@0 150
ian@0 151 static unsigned long
ian@0 152 intel_iq80310_translate(struct map_pci_info *map, unsigned long ofs)
ian@0 153 {
ian@0 154 unsigned long page_addr = ofs & 0x00400000;
ian@0 155
ian@0 156 /*
ian@0 157 * This mundges the flash location so we avoid
ian@0 158 * the first 80 bytes (they appear to read nonsense).
ian@0 159 */
ian@0 160 if (page_addr) {
ian@0 161 writel(0x00000008, map->base + 0x1558);
ian@0 162 writel(0x00000000, map->base + 0x1550);
ian@0 163 } else {
ian@0 164 writel(0x00000007, map->base + 0x1558);
ian@0 165 writel(0x00800000, map->base + 0x1550);
ian@0 166 ofs += 0x00800000;
ian@0 167 }
ian@0 168
ian@0 169 return ofs;
ian@0 170 }
ian@0 171
ian@0 172 static struct mtd_pci_info intel_iq80310_info = {
ian@0 173 .init = intel_iq80310_init,
ian@0 174 .exit = intel_iq80310_exit,
ian@0 175 .translate = intel_iq80310_translate,
ian@0 176 .map_name = "cfi_probe",
ian@0 177 };
ian@0 178
ian@0 179 /*
ian@0 180 * Intel DC21285 driver
ian@0 181 */
ian@0 182
ian@0 183 static int
ian@0 184 intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map)
ian@0 185 {
ian@0 186 unsigned long base, len;
ian@0 187
ian@0 188 base = pci_resource_start(dev, PCI_ROM_RESOURCE);
ian@0 189 len = pci_resource_len(dev, PCI_ROM_RESOURCE);
ian@0 190
ian@0 191 if (!len || !base) {
ian@0 192 /*
ian@0 193 * No ROM resource
ian@0 194 */
ian@0 195 base = pci_resource_start(dev, 2);
ian@0 196 len = pci_resource_len(dev, 2);
ian@0 197
ian@0 198 /*
ian@0 199 * We need to re-allocate PCI BAR2 address range to the
ian@0 200 * PCI ROM BAR, and disable PCI BAR2.
ian@0 201 */
ian@0 202 } else {
ian@0 203 /*
ian@0 204 * Hmm, if an address was allocated to the ROM resource, but
ian@0 205 * not enabled, should we be allocating a new resource for it
ian@0 206 * or simply enabling it?
ian@0 207 */
ian@0 208 if (!(pci_resource_flags(dev, PCI_ROM_RESOURCE) &
ian@0 209 IORESOURCE_ROM_ENABLE)) {
ian@0 210 u32 val;
ian@0 211 pci_resource_flags(dev, PCI_ROM_RESOURCE) |= IORESOURCE_ROM_ENABLE;
ian@0 212 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
ian@0 213 val |= PCI_ROM_ADDRESS_ENABLE;
ian@0 214 pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
ian@0 215 printk("%s: enabling expansion ROM\n", pci_name(dev));
ian@0 216 }
ian@0 217 }
ian@0 218
ian@0 219 if (!len || !base)
ian@0 220 return -ENXIO;
ian@0 221
ian@0 222 map->map.bankwidth = 4;
ian@0 223 map->map.read = mtd_pci_read32,
ian@0 224 map->map.write = mtd_pci_write32,
ian@0 225 map->map.size = len;
ian@0 226 map->base = ioremap_nocache(base, len);
ian@0 227
ian@0 228 if (!map->base)
ian@0 229 return -ENOMEM;
ian@0 230
ian@0 231 return 0;
ian@0 232 }
ian@0 233
ian@0 234 static void
ian@0 235 intel_dc21285_exit(struct pci_dev *dev, struct map_pci_info *map)
ian@0 236 {
ian@0 237 u32 val;
ian@0 238
ian@0 239 if (map->base)
ian@0 240 iounmap(map->base);
ian@0 241
ian@0 242 /*
ian@0 243 * We need to undo the PCI BAR2/PCI ROM BAR address alteration.
ian@0 244 */
ian@0 245 pci_resource_flags(dev, PCI_ROM_RESOURCE) &= ~IORESOURCE_ROM_ENABLE;
ian@0 246 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
ian@0 247 val &= ~PCI_ROM_ADDRESS_ENABLE;
ian@0 248 pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
ian@0 249 }
ian@0 250
ian@0 251 static unsigned long
ian@0 252 intel_dc21285_translate(struct map_pci_info *map, unsigned long ofs)
ian@0 253 {
ian@0 254 return ofs & 0x00ffffc0 ? ofs : (ofs ^ (1 << 5));
ian@0 255 }
ian@0 256
ian@0 257 static struct mtd_pci_info intel_dc21285_info = {
ian@0 258 .init = intel_dc21285_init,
ian@0 259 .exit = intel_dc21285_exit,
ian@0 260 .translate = intel_dc21285_translate,
ian@0 261 .map_name = "jedec_probe",
ian@0 262 };
ian@0 263
ian@0 264 /*
ian@0 265 * PCI device ID table
ian@0 266 */
ian@0 267
ian@0 268 static struct pci_device_id mtd_pci_ids[] = {
ian@0 269 {
ian@0 270 .vendor = PCI_VENDOR_ID_INTEL,
ian@0 271 .device = 0x530d,
ian@0 272 .subvendor = PCI_ANY_ID,
ian@0 273 .subdevice = PCI_ANY_ID,
ian@0 274 .class = PCI_CLASS_MEMORY_OTHER << 8,
ian@0 275 .class_mask = 0xffff00,
ian@0 276 .driver_data = (unsigned long)&intel_iq80310_info,
ian@0 277 },
ian@0 278 {
ian@0 279 .vendor = PCI_VENDOR_ID_DEC,
ian@0 280 .device = PCI_DEVICE_ID_DEC_21285,
ian@0 281 .subvendor = 0, /* DC21285 defaults to 0 on reset */
ian@0 282 .subdevice = 0, /* DC21285 defaults to 0 on reset */
ian@0 283 .driver_data = (unsigned long)&intel_dc21285_info,
ian@0 284 },
ian@0 285 { 0, }
ian@0 286 };
ian@0 287
ian@0 288 /*
ian@0 289 * Generic code follows.
ian@0 290 */
ian@0 291
ian@0 292 static int __devinit
ian@0 293 mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
ian@0 294 {
ian@0 295 struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data;
ian@0 296 struct map_pci_info *map = NULL;
ian@0 297 struct mtd_info *mtd = NULL;
ian@0 298 int err;
ian@0 299
ian@0 300 err = pci_enable_device(dev);
ian@0 301 if (err)
ian@0 302 goto out;
ian@0 303
ian@0 304 err = pci_request_regions(dev, "pci mtd");
ian@0 305 if (err)
ian@0 306 goto out;
ian@0 307
ian@0 308 map = kmalloc(sizeof(*map), GFP_KERNEL);
ian@0 309 err = -ENOMEM;
ian@0 310 if (!map)
ian@0 311 goto release;
ian@0 312
ian@0 313 map->map = mtd_pci_map;
ian@0 314 map->map.name = pci_name(dev);
ian@0 315 map->dev = dev;
ian@0 316 map->exit = info->exit;
ian@0 317 map->translate = info->translate;
ian@0 318
ian@0 319 err = info->init(dev, map);
ian@0 320 if (err)
ian@0 321 goto release;
ian@0 322
ian@0 323 /* tsk - do_map_probe should take const char * */
ian@0 324 mtd = do_map_probe((char *)info->map_name, &map->map);
ian@0 325 err = -ENODEV;
ian@0 326 if (!mtd)
ian@0 327 goto release;
ian@0 328
ian@0 329 mtd->owner = THIS_MODULE;
ian@0 330 add_mtd_device(mtd);
ian@0 331
ian@0 332 pci_set_drvdata(dev, mtd);
ian@0 333
ian@0 334 return 0;
ian@0 335
ian@0 336 release:
ian@0 337 if (map) {
ian@0 338 map->exit(dev, map);
ian@0 339 kfree(map);
ian@0 340 }
ian@0 341
ian@0 342 pci_release_regions(dev);
ian@0 343 out:
ian@0 344 return err;
ian@0 345 }
ian@0 346
ian@0 347 static void __devexit
ian@0 348 mtd_pci_remove(struct pci_dev *dev)
ian@0 349 {
ian@0 350 struct mtd_info *mtd = pci_get_drvdata(dev);
ian@0 351 struct map_pci_info *map = mtd->priv;
ian@0 352
ian@0 353 del_mtd_device(mtd);
ian@0 354 map_destroy(mtd);
ian@0 355 map->exit(dev, map);
ian@0 356 kfree(map);
ian@0 357
ian@0 358 pci_set_drvdata(dev, NULL);
ian@0 359 pci_release_regions(dev);
ian@0 360 }
ian@0 361
ian@0 362 static struct pci_driver mtd_pci_driver = {
ian@0 363 .name = "MTD PCI",
ian@0 364 .probe = mtd_pci_probe,
ian@0 365 .remove = __devexit_p(mtd_pci_remove),
ian@0 366 .id_table = mtd_pci_ids,
ian@0 367 };
ian@0 368
ian@0 369 static int __init mtd_pci_maps_init(void)
ian@0 370 {
ian@0 371 return pci_register_driver(&mtd_pci_driver);
ian@0 372 }
ian@0 373
ian@0 374 static void __exit mtd_pci_maps_exit(void)
ian@0 375 {
ian@0 376 pci_unregister_driver(&mtd_pci_driver);
ian@0 377 }
ian@0 378
ian@0 379 module_init(mtd_pci_maps_init);
ian@0 380 module_exit(mtd_pci_maps_exit);
ian@0 381
ian@0 382 MODULE_LICENSE("GPL");
ian@0 383 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
ian@0 384 MODULE_DESCRIPTION("Generic PCI map driver");
ian@0 385 MODULE_DEVICE_TABLE(pci, mtd_pci_ids);
ian@0 386