ia64/linux-2.6.18-xen.hg

annotate drivers/mtd/maps/ixp4xx.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 * $Id: ixp4xx.c,v 1.13 2005/11/16 16:23:21 dvrabel Exp $
ian@0 3 *
ian@0 4 * drivers/mtd/maps/ixp4xx.c
ian@0 5 *
ian@0 6 * MTD Map file for IXP4XX based systems. Please do not make per-board
ian@0 7 * changes in here. If your board needs special setup, do it in your
ian@0 8 * platform level code in arch/arm/mach-ixp4xx/board-setup.c
ian@0 9 *
ian@0 10 * Original Author: Intel Corporation
ian@0 11 * Maintainer: Deepak Saxena <dsaxena@mvista.com>
ian@0 12 *
ian@0 13 * Copyright (C) 2002 Intel Corporation
ian@0 14 * Copyright (C) 2003-2004 MontaVista Software, Inc.
ian@0 15 *
ian@0 16 */
ian@0 17
ian@0 18 #include <linux/module.h>
ian@0 19 #include <linux/types.h>
ian@0 20 #include <linux/init.h>
ian@0 21 #include <linux/kernel.h>
ian@0 22 #include <linux/string.h>
ian@0 23 #include <linux/slab.h>
ian@0 24 #include <linux/ioport.h>
ian@0 25 #include <linux/device.h>
ian@0 26 #include <linux/platform_device.h>
ian@0 27
ian@0 28 #include <linux/mtd/mtd.h>
ian@0 29 #include <linux/mtd/map.h>
ian@0 30 #include <linux/mtd/partitions.h>
ian@0 31
ian@0 32 #include <asm/io.h>
ian@0 33 #include <asm/mach/flash.h>
ian@0 34
ian@0 35 #include <linux/reboot.h>
ian@0 36
ian@0 37 /*
ian@0 38 * Read/write a 16 bit word from flash address 'addr'.
ian@0 39 *
ian@0 40 * When the cpu is in little-endian mode it swizzles the address lines
ian@0 41 * ('address coherency') so we need to undo the swizzling to ensure commands
ian@0 42 * and the like end up on the correct flash address.
ian@0 43 *
ian@0 44 * To further complicate matters, due to the way the expansion bus controller
ian@0 45 * handles 32 bit reads, the byte stream ABCD is stored on the flash as:
ian@0 46 * D15 D0
ian@0 47 * +---+---+
ian@0 48 * | A | B | 0
ian@0 49 * +---+---+
ian@0 50 * | C | D | 2
ian@0 51 * +---+---+
ian@0 52 * This means that on LE systems each 16 bit word must be swapped. Note that
ian@0 53 * this requires CONFIG_MTD_CFI_BE_BYTE_SWAP to be enabled to 'unswap' the CFI
ian@0 54 * data and other flash commands which are always in D7-D0.
ian@0 55 */
ian@0 56 #ifndef __ARMEB__
ian@0 57 #ifndef CONFIG_MTD_CFI_BE_BYTE_SWAP
ian@0 58 # error CONFIG_MTD_CFI_BE_BYTE_SWAP required
ian@0 59 #endif
ian@0 60
ian@0 61 static inline u16 flash_read16(void __iomem *addr)
ian@0 62 {
ian@0 63 return be16_to_cpu(__raw_readw((void __iomem *)((unsigned long)addr ^ 0x2)));
ian@0 64 }
ian@0 65
ian@0 66 static inline void flash_write16(u16 d, void __iomem *addr)
ian@0 67 {
ian@0 68 __raw_writew(cpu_to_be16(d), (void __iomem *)((unsigned long)addr ^ 0x2));
ian@0 69 }
ian@0 70
ian@0 71 #define BYTE0(h) ((h) & 0xFF)
ian@0 72 #define BYTE1(h) (((h) >> 8) & 0xFF)
ian@0 73
ian@0 74 #else
ian@0 75
ian@0 76 static inline u16 flash_read16(const void __iomem *addr)
ian@0 77 {
ian@0 78 return __raw_readw(addr);
ian@0 79 }
ian@0 80
ian@0 81 static inline void flash_write16(u16 d, void __iomem *addr)
ian@0 82 {
ian@0 83 __raw_writew(d, addr);
ian@0 84 }
ian@0 85
ian@0 86 #define BYTE0(h) (((h) >> 8) & 0xFF)
ian@0 87 #define BYTE1(h) ((h) & 0xFF)
ian@0 88 #endif
ian@0 89
ian@0 90 static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
ian@0 91 {
ian@0 92 map_word val;
ian@0 93 val.x[0] = flash_read16(map->virt + ofs);
ian@0 94 return val;
ian@0 95 }
ian@0 96
ian@0 97 /*
ian@0 98 * The IXP4xx expansion bus only allows 16-bit wide acceses
ian@0 99 * when attached to a 16-bit wide device (such as the 28F128J3A),
ian@0 100 * so we can't just memcpy_fromio().
ian@0 101 */
ian@0 102 static void ixp4xx_copy_from(struct map_info *map, void *to,
ian@0 103 unsigned long from, ssize_t len)
ian@0 104 {
ian@0 105 u8 *dest = (u8 *) to;
ian@0 106 void __iomem *src = map->virt + from;
ian@0 107
ian@0 108 if (len <= 0)
ian@0 109 return;
ian@0 110
ian@0 111 if (from & 1) {
ian@0 112 *dest++ = BYTE1(flash_read16(src));
ian@0 113 src++;
ian@0 114 --len;
ian@0 115 }
ian@0 116
ian@0 117 while (len >= 2) {
ian@0 118 u16 data = flash_read16(src);
ian@0 119 *dest++ = BYTE0(data);
ian@0 120 *dest++ = BYTE1(data);
ian@0 121 src += 2;
ian@0 122 len -= 2;
ian@0 123 }
ian@0 124
ian@0 125 if (len > 0)
ian@0 126 *dest++ = BYTE0(flash_read16(src));
ian@0 127 }
ian@0 128
ian@0 129 /*
ian@0 130 * Unaligned writes are ignored, causing the 8-bit
ian@0 131 * probe to fail and proceed to the 16-bit probe (which succeeds).
ian@0 132 */
ian@0 133 static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
ian@0 134 {
ian@0 135 if (!(adr & 1))
ian@0 136 flash_write16(d.x[0], map->virt + adr);
ian@0 137 }
ian@0 138
ian@0 139 /*
ian@0 140 * Fast write16 function without the probing check above
ian@0 141 */
ian@0 142 static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
ian@0 143 {
ian@0 144 flash_write16(d.x[0], map->virt + adr);
ian@0 145 }
ian@0 146
ian@0 147 struct ixp4xx_flash_info {
ian@0 148 struct mtd_info *mtd;
ian@0 149 struct map_info map;
ian@0 150 struct mtd_partition *partitions;
ian@0 151 struct resource *res;
ian@0 152 };
ian@0 153
ian@0 154 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
ian@0 155
ian@0 156 static int ixp4xx_flash_remove(struct platform_device *dev)
ian@0 157 {
ian@0 158 struct flash_platform_data *plat = dev->dev.platform_data;
ian@0 159 struct ixp4xx_flash_info *info = platform_get_drvdata(dev);
ian@0 160
ian@0 161 platform_set_drvdata(dev, NULL);
ian@0 162
ian@0 163 if(!info)
ian@0 164 return 0;
ian@0 165
ian@0 166 if (info->mtd) {
ian@0 167 del_mtd_partitions(info->mtd);
ian@0 168 map_destroy(info->mtd);
ian@0 169 }
ian@0 170 if (info->map.virt)
ian@0 171 iounmap(info->map.virt);
ian@0 172
ian@0 173 kfree(info->partitions);
ian@0 174
ian@0 175 if (info->res) {
ian@0 176 release_resource(info->res);
ian@0 177 kfree(info->res);
ian@0 178 }
ian@0 179
ian@0 180 if (plat->exit)
ian@0 181 plat->exit();
ian@0 182
ian@0 183 return 0;
ian@0 184 }
ian@0 185
ian@0 186 static int ixp4xx_flash_probe(struct platform_device *dev)
ian@0 187 {
ian@0 188 struct flash_platform_data *plat = dev->dev.platform_data;
ian@0 189 struct ixp4xx_flash_info *info;
ian@0 190 int err = -1;
ian@0 191
ian@0 192 if (!plat)
ian@0 193 return -ENODEV;
ian@0 194
ian@0 195 if (plat->init) {
ian@0 196 err = plat->init();
ian@0 197 if (err)
ian@0 198 return err;
ian@0 199 }
ian@0 200
ian@0 201 info = kmalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL);
ian@0 202 if(!info) {
ian@0 203 err = -ENOMEM;
ian@0 204 goto Error;
ian@0 205 }
ian@0 206 memzero(info, sizeof(struct ixp4xx_flash_info));
ian@0 207
ian@0 208 platform_set_drvdata(dev, info);
ian@0 209
ian@0 210 /*
ian@0 211 * Tell the MTD layer we're not 1:1 mapped so that it does
ian@0 212 * not attempt to do a direct access on us.
ian@0 213 */
ian@0 214 info->map.phys = NO_XIP;
ian@0 215 info->map.size = dev->resource->end - dev->resource->start + 1;
ian@0 216
ian@0 217 /*
ian@0 218 * We only support 16-bit accesses for now. If and when
ian@0 219 * any board use 8-bit access, we'll fixup the driver to
ian@0 220 * handle that.
ian@0 221 */
ian@0 222 info->map.bankwidth = 2;
ian@0 223 info->map.name = dev->dev.bus_id;
ian@0 224 info->map.read = ixp4xx_read16,
ian@0 225 info->map.write = ixp4xx_probe_write16,
ian@0 226 info->map.copy_from = ixp4xx_copy_from,
ian@0 227
ian@0 228 info->res = request_mem_region(dev->resource->start,
ian@0 229 dev->resource->end - dev->resource->start + 1,
ian@0 230 "IXP4XXFlash");
ian@0 231 if (!info->res) {
ian@0 232 printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n");
ian@0 233 err = -ENOMEM;
ian@0 234 goto Error;
ian@0 235 }
ian@0 236
ian@0 237 info->map.virt = ioremap(dev->resource->start,
ian@0 238 dev->resource->end - dev->resource->start + 1);
ian@0 239 if (!info->map.virt) {
ian@0 240 printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n");
ian@0 241 err = -EIO;
ian@0 242 goto Error;
ian@0 243 }
ian@0 244
ian@0 245 info->mtd = do_map_probe(plat->map_name, &info->map);
ian@0 246 if (!info->mtd) {
ian@0 247 printk(KERN_ERR "IXP4XXFlash: map_probe failed\n");
ian@0 248 err = -ENXIO;
ian@0 249 goto Error;
ian@0 250 }
ian@0 251 info->mtd->owner = THIS_MODULE;
ian@0 252
ian@0 253 /* Use the fast version */
ian@0 254 info->map.write = ixp4xx_write16,
ian@0 255
ian@0 256 err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
ian@0 257 if (err > 0) {
ian@0 258 err = add_mtd_partitions(info->mtd, info->partitions, err);
ian@0 259 if(err)
ian@0 260 printk(KERN_ERR "Could not parse partitions\n");
ian@0 261 }
ian@0 262
ian@0 263 if (err)
ian@0 264 goto Error;
ian@0 265
ian@0 266 return 0;
ian@0 267
ian@0 268 Error:
ian@0 269 ixp4xx_flash_remove(dev);
ian@0 270 return err;
ian@0 271 }
ian@0 272
ian@0 273 static struct platform_driver ixp4xx_flash_driver = {
ian@0 274 .probe = ixp4xx_flash_probe,
ian@0 275 .remove = ixp4xx_flash_remove,
ian@0 276 .driver = {
ian@0 277 .name = "IXP4XX-Flash",
ian@0 278 },
ian@0 279 };
ian@0 280
ian@0 281 static int __init ixp4xx_flash_init(void)
ian@0 282 {
ian@0 283 return platform_driver_register(&ixp4xx_flash_driver);
ian@0 284 }
ian@0 285
ian@0 286 static void __exit ixp4xx_flash_exit(void)
ian@0 287 {
ian@0 288 platform_driver_unregister(&ixp4xx_flash_driver);
ian@0 289 }
ian@0 290
ian@0 291
ian@0 292 module_init(ixp4xx_flash_init);
ian@0 293 module_exit(ixp4xx_flash_exit);
ian@0 294
ian@0 295 MODULE_LICENSE("GPL");
ian@0 296 MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems");
ian@0 297 MODULE_AUTHOR("Deepak Saxena");