ia64/linux-2.6.18-xen.hg

view arch/mips/pci/pci-ocelot-c.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 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2004, 06 by Ralf Baechle (ralf@linux-mips.org)
7 */
9 #include <linux/types.h>
10 #include <linux/pci.h>
11 #include <linux/mv643xx.h>
13 #include <linux/init.h>
15 #include <asm/marvell.h>
17 /*
18 * We assume the address ranges have already been setup appropriately by
19 * the firmware. PMON in case of the Ocelot C does that.
20 */
21 static struct resource mv_pci_io_mem0_resource = {
22 .name = "MV64340 PCI0 IO MEM",
23 .flags = IORESOURCE_IO
24 };
26 static struct resource mv_pci_mem0_resource = {
27 .name = "MV64340 PCI0 MEM",
28 .flags = IORESOURCE_MEM
29 };
31 static struct mv_pci_controller mv_bus0_controller = {
32 .pcic = {
33 .pci_ops = &mv_pci_ops,
34 .mem_resource = &mv_pci_mem0_resource,
35 .io_resource = &mv_pci_io_mem0_resource,
36 },
37 .config_addr = MV64340_PCI_0_CONFIG_ADDR,
38 .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
39 };
41 static uint32_t mv_io_base, mv_io_size;
43 static void mv64340_pci0_init(void)
44 {
45 uint32_t mem0_base, mem0_size;
46 uint32_t io_base, io_size;
48 io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16;
49 io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16;
50 mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16;
51 mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16;
53 mv_pci_io_mem0_resource.start = 0;
54 mv_pci_io_mem0_resource.end = io_size - 1;
55 mv_pci_mem0_resource.start = mem0_base;
56 mv_pci_mem0_resource.end = mem0_base + mem0_size - 1;
57 mv_bus0_controller.pcic.mem_offset = mem0_base;
58 mv_bus0_controller.pcic.io_offset = 0;
60 ioport_resource.end = io_size - 1;
62 register_pci_controller(&mv_bus0_controller.pcic);
64 mv_io_base = io_base;
65 mv_io_size = io_size;
66 }
68 static struct resource mv_pci_io_mem1_resource = {
69 .name = "MV64340 PCI1 IO MEM",
70 .flags = IORESOURCE_IO
71 };
73 static struct resource mv_pci_mem1_resource = {
74 .name = "MV64340 PCI1 MEM",
75 .flags = IORESOURCE_MEM
76 };
78 static struct mv_pci_controller mv_bus1_controller = {
79 .pcic = {
80 .pci_ops = &mv_pci_ops,
81 .mem_resource = &mv_pci_mem1_resource,
82 .io_resource = &mv_pci_io_mem1_resource,
83 },
84 .config_addr = MV64340_PCI_1_CONFIG_ADDR,
85 .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
86 };
88 static __init void mv64340_pci1_init(void)
89 {
90 uint32_t mem0_base, mem0_size;
91 uint32_t io_base, io_size;
93 io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16;
94 io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16;
95 mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16;
96 mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16;
98 /*
99 * Here we assume the I/O window of second bus to be contiguous with
100 * the first. A gap is no problem but would waste address space for
101 * remapping the port space.
102 */
103 mv_pci_io_mem1_resource.start = mv_io_size;
104 mv_pci_io_mem1_resource.end = mv_io_size + io_size - 1;
105 mv_pci_mem1_resource.start = mem0_base;
106 mv_pci_mem1_resource.end = mem0_base + mem0_size - 1;
107 mv_bus1_controller.pcic.mem_offset = mem0_base;
108 mv_bus1_controller.pcic.io_offset = 0;
110 ioport_resource.end = io_base + io_size -mv_io_base - 1;
112 register_pci_controller(&mv_bus1_controller.pcic);
114 mv_io_size = io_base + io_size - mv_io_base;
115 }
117 static __init int __init ocelot_c_pci_init(void)
118 {
119 unsigned long io_v_base;
120 uint32_t enable;
122 enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
124 /*
125 * We require at least one enabled I/O or PCI memory window or we
126 * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3.
127 */
128 if (enable & (0x01 << 9) || enable & (0x01 << 10))
129 mv64340_pci0_init();
131 if (enable & (0x01 << 14) || enable & (0x01 << 15))
132 mv64340_pci1_init();
134 if (mv_io_size) {
135 io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size);
136 if (!io_v_base)
137 panic("Could not ioremap I/O port range");
139 set_io_port_base(io_v_base);
140 }
142 return 0;
143 }
145 arch_initcall(ocelot_c_pci_init);