ia64/linux-2.6.18-xen.hg

annotate arch/sparc64/kernel/isa.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 #include <linux/kernel.h>
ian@0 2 #include <linux/init.h>
ian@0 3 #include <linux/pci.h>
ian@0 4 #include <linux/slab.h>
ian@0 5 #include <asm/oplib.h>
ian@0 6 #include <asm/prom.h>
ian@0 7 #include <asm/of_device.h>
ian@0 8 #include <asm/isa.h>
ian@0 9
ian@0 10 struct sparc_isa_bridge *isa_chain;
ian@0 11
ian@0 12 static void __init fatal_err(const char *reason)
ian@0 13 {
ian@0 14 prom_printf("ISA: fatal error, %s.\n", reason);
ian@0 15 }
ian@0 16
ian@0 17 static void __init report_dev(struct sparc_isa_device *isa_dev, int child)
ian@0 18 {
ian@0 19 if (child)
ian@0 20 printk(" (%s)", isa_dev->prom_node->name);
ian@0 21 else
ian@0 22 printk(" [%s", isa_dev->prom_node->name);
ian@0 23 }
ian@0 24
ian@0 25 static struct linux_prom_registers * __init
ian@0 26 isa_dev_get_resource(struct sparc_isa_device *isa_dev)
ian@0 27 {
ian@0 28 struct linux_prom_registers *pregs;
ian@0 29 unsigned long base, len;
ian@0 30 int prop_len;
ian@0 31
ian@0 32 pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len);
ian@0 33
ian@0 34 /* Only the first one is interesting. */
ian@0 35 len = pregs[0].reg_size;
ian@0 36 base = (((unsigned long)pregs[0].which_io << 32) |
ian@0 37 (unsigned long)pregs[0].phys_addr);
ian@0 38 base += isa_dev->bus->parent->io_space.start;
ian@0 39
ian@0 40 isa_dev->resource.start = base;
ian@0 41 isa_dev->resource.end = (base + len - 1UL);
ian@0 42 isa_dev->resource.flags = IORESOURCE_IO;
ian@0 43 isa_dev->resource.name = isa_dev->prom_node->name;
ian@0 44
ian@0 45 request_resource(&isa_dev->bus->parent->io_space,
ian@0 46 &isa_dev->resource);
ian@0 47
ian@0 48 return pregs;
ian@0 49 }
ian@0 50
ian@0 51 static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev,
ian@0 52 struct linux_prom_registers *pregs)
ian@0 53 {
ian@0 54 struct of_device *op = of_find_device_by_node(isa_dev->prom_node);
ian@0 55
ian@0 56 if (!op || !op->num_irqs) {
ian@0 57 isa_dev->irq = PCI_IRQ_NONE;
ian@0 58 } else {
ian@0 59 isa_dev->irq = op->irqs[0];
ian@0 60 }
ian@0 61 }
ian@0 62
ian@0 63 static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
ian@0 64 {
ian@0 65 struct device_node *dp = parent_isa_dev->prom_node->child;
ian@0 66
ian@0 67 if (!dp)
ian@0 68 return;
ian@0 69
ian@0 70 printk(" ->");
ian@0 71 while (dp) {
ian@0 72 struct linux_prom_registers *regs;
ian@0 73 struct sparc_isa_device *isa_dev;
ian@0 74
ian@0 75 isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
ian@0 76 if (!isa_dev) {
ian@0 77 fatal_err("cannot allocate child isa_dev");
ian@0 78 prom_halt();
ian@0 79 }
ian@0 80
ian@0 81 memset(isa_dev, 0, sizeof(*isa_dev));
ian@0 82
ian@0 83 /* Link it in to parent. */
ian@0 84 isa_dev->next = parent_isa_dev->child;
ian@0 85 parent_isa_dev->child = isa_dev;
ian@0 86
ian@0 87 isa_dev->bus = parent_isa_dev->bus;
ian@0 88 isa_dev->prom_node = dp;
ian@0 89
ian@0 90 regs = isa_dev_get_resource(isa_dev);
ian@0 91 isa_dev_get_irq(isa_dev, regs);
ian@0 92
ian@0 93 report_dev(isa_dev, 1);
ian@0 94
ian@0 95 dp = dp->sibling;
ian@0 96 }
ian@0 97 }
ian@0 98
ian@0 99 static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
ian@0 100 {
ian@0 101 struct device_node *dp = isa_br->prom_node->child;
ian@0 102
ian@0 103 while (dp) {
ian@0 104 struct linux_prom_registers *regs;
ian@0 105 struct sparc_isa_device *isa_dev;
ian@0 106
ian@0 107 isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
ian@0 108 if (!isa_dev) {
ian@0 109 printk(KERN_DEBUG "ISA: cannot allocate isa_dev");
ian@0 110 return;
ian@0 111 }
ian@0 112
ian@0 113 memset(isa_dev, 0, sizeof(*isa_dev));
ian@0 114
ian@0 115 isa_dev->ofdev.node = dp;
ian@0 116 isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
ian@0 117 isa_dev->ofdev.dev.bus = &isa_bus_type;
ian@0 118 strcpy(isa_dev->ofdev.dev.bus_id, dp->path_component_name);
ian@0 119
ian@0 120 /* Register with core */
ian@0 121 if (of_device_register(&isa_dev->ofdev) != 0) {
ian@0 122 printk(KERN_DEBUG "isa: device registration error for %s!\n",
ian@0 123 isa_dev->ofdev.dev.bus_id);
ian@0 124 kfree(isa_dev);
ian@0 125 goto next_sibling;
ian@0 126 }
ian@0 127
ian@0 128 /* Link it in. */
ian@0 129 isa_dev->next = NULL;
ian@0 130 if (isa_br->devices == NULL) {
ian@0 131 isa_br->devices = isa_dev;
ian@0 132 } else {
ian@0 133 struct sparc_isa_device *tmp = isa_br->devices;
ian@0 134
ian@0 135 while (tmp->next)
ian@0 136 tmp = tmp->next;
ian@0 137
ian@0 138 tmp->next = isa_dev;
ian@0 139 }
ian@0 140
ian@0 141 isa_dev->bus = isa_br;
ian@0 142 isa_dev->prom_node = dp;
ian@0 143
ian@0 144 regs = isa_dev_get_resource(isa_dev);
ian@0 145 isa_dev_get_irq(isa_dev, regs);
ian@0 146
ian@0 147 report_dev(isa_dev, 0);
ian@0 148
ian@0 149 isa_fill_children(isa_dev);
ian@0 150
ian@0 151 printk("]");
ian@0 152
ian@0 153 next_sibling:
ian@0 154 dp = dp->sibling;
ian@0 155 }
ian@0 156 }
ian@0 157
ian@0 158 void __init isa_init(void)
ian@0 159 {
ian@0 160 struct pci_dev *pdev;
ian@0 161 unsigned short vendor, device;
ian@0 162 int index = 0;
ian@0 163
ian@0 164 vendor = PCI_VENDOR_ID_AL;
ian@0 165 device = PCI_DEVICE_ID_AL_M1533;
ian@0 166
ian@0 167 pdev = NULL;
ian@0 168 while ((pdev = pci_get_device(vendor, device, pdev)) != NULL) {
ian@0 169 struct pcidev_cookie *pdev_cookie;
ian@0 170 struct pci_pbm_info *pbm;
ian@0 171 struct sparc_isa_bridge *isa_br;
ian@0 172 struct device_node *dp;
ian@0 173
ian@0 174 pdev_cookie = pdev->sysdata;
ian@0 175 if (!pdev_cookie) {
ian@0 176 printk("ISA: Warning, ISA bridge ignored due to "
ian@0 177 "lack of OBP data.\n");
ian@0 178 continue;
ian@0 179 }
ian@0 180 pbm = pdev_cookie->pbm;
ian@0 181 dp = pdev_cookie->prom_node;
ian@0 182
ian@0 183 isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
ian@0 184 if (!isa_br) {
ian@0 185 printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge");
ian@0 186 return;
ian@0 187 }
ian@0 188
ian@0 189 memset(isa_br, 0, sizeof(*isa_br));
ian@0 190
ian@0 191 isa_br->ofdev.node = dp;
ian@0 192 isa_br->ofdev.dev.parent = &pdev->dev;
ian@0 193 isa_br->ofdev.dev.bus = &isa_bus_type;
ian@0 194 strcpy(isa_br->ofdev.dev.bus_id, dp->path_component_name);
ian@0 195
ian@0 196 /* Register with core */
ian@0 197 if (of_device_register(&isa_br->ofdev) != 0) {
ian@0 198 printk(KERN_DEBUG "isa: device registration error for %s!\n",
ian@0 199 isa_br->ofdev.dev.bus_id);
ian@0 200 kfree(isa_br);
ian@0 201 return;
ian@0 202 }
ian@0 203
ian@0 204 /* Link it in. */
ian@0 205 isa_br->next = isa_chain;
ian@0 206 isa_chain = isa_br;
ian@0 207
ian@0 208 isa_br->parent = pbm;
ian@0 209 isa_br->self = pdev;
ian@0 210 isa_br->index = index++;
ian@0 211 isa_br->prom_node = pdev_cookie->prom_node;
ian@0 212
ian@0 213 printk("isa%d:", isa_br->index);
ian@0 214
ian@0 215 isa_fill_devices(isa_br);
ian@0 216
ian@0 217 printk("\n");
ian@0 218 }
ian@0 219 }