ia64/linux-2.6.18-xen.hg

view arch/mips/pci/ops-tx4938.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 * Define the pci_ops for the Toshiba rbtx4938
3 * Copyright (C) 2000-2001 Toshiba Corporation
4 *
5 * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
6 * terms of the GNU General Public License version 2. This program is
7 * licensed "as is" without any warranty of any kind, whether express
8 * or implied.
9 *
10 * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
11 */
12 #include <linux/types.h>
13 #include <linux/pci.h>
14 #include <linux/kernel.h>
15 #include <linux/init.h>
17 #include <asm/addrspace.h>
18 #include <asm/tx4938/rbtx4938.h>
20 /* initialize in setup */
21 struct resource pci_io_resource = {
22 .name = "pci IO space",
23 .start = 0,
24 .end = 0,
25 .flags = IORESOURCE_IO
26 };
28 /* initialize in setup */
29 struct resource pci_mem_resource = {
30 .name = "pci memory space",
31 .start = 0,
32 .end = 0,
33 .flags = IORESOURCE_MEM
34 };
36 struct resource tx4938_pcic1_pci_io_resource = {
37 .name = "PCI1 IO",
38 .start = 0,
39 .end = 0,
40 .flags = IORESOURCE_IO
41 };
42 struct resource tx4938_pcic1_pci_mem_resource = {
43 .name = "PCI1 mem",
44 .start = 0,
45 .end = 0,
46 .flags = IORESOURCE_MEM
47 };
49 static int mkaddr(int bus, int dev_fn, int where, int *flagsp)
50 {
51 if (bus > 0) {
52 /* Type 1 configuration */
53 tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
54 ((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1;
55 } else {
56 if (dev_fn >= PCI_DEVFN(TX4938_PCIC_MAX_DEVNU, 0))
57 return -1;
59 /* Type 0 configuration */
60 tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
61 ((dev_fn & 0xff) << 0x08) | (where & 0xfc);
62 }
63 /* clear M_ABORT and Disable M_ABORT Int. */
64 tx4938_pcicptr->pcistatus =
65 (tx4938_pcicptr->pcistatus & 0x0000ffff) |
66 (PCI_STATUS_REC_MASTER_ABORT << 16);
67 tx4938_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
69 return 0;
70 }
72 static int check_abort(int flags)
73 {
74 int code = PCIBIOS_SUCCESSFUL;
75 /* wait write cycle completion before checking error status */
76 while (tx4938_pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB)
77 ;
78 if (tx4938_pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
79 tx4938_pcicptr->pcistatus =
80 (tx4938_pcicptr->
81 pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT
82 << 16);
83 tx4938_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
84 code = PCIBIOS_DEVICE_NOT_FOUND;
85 }
86 return code;
87 }
89 static int tx4938_pcibios_read_config(struct pci_bus *bus, unsigned int devfn,
90 int where, int size, u32 * val)
91 {
92 int flags, retval, dev, busno, func;
94 dev = PCI_SLOT(devfn);
95 func = PCI_FUNC(devfn);
97 /* check if the bus is top-level */
98 if (bus->parent != NULL)
99 busno = bus->number;
100 else {
101 busno = 0;
102 }
104 if (mkaddr(busno, devfn, where, &flags))
105 return -1;
107 switch (size) {
108 case 1:
109 *val = *(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
110 #ifdef __BIG_ENDIAN
111 ((where & 3) ^ 3));
112 #else
113 (where & 3));
114 #endif
115 break;
116 case 2:
117 *val = *(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
118 #ifdef __BIG_ENDIAN
119 ((where & 3) ^ 2));
120 #else
121 (where & 3));
122 #endif
123 break;
124 case 4:
125 *val = tx4938_pcicptr->g2pcfgdata;
126 break;
127 }
129 retval = check_abort(flags);
130 if (retval == PCIBIOS_DEVICE_NOT_FOUND)
131 *val = 0xffffffff;
133 return retval;
134 }
136 static int tx4938_pcibios_write_config(struct pci_bus *bus, unsigned int devfn, int where,
137 int size, u32 val)
138 {
139 int flags, dev, busno, func;
141 busno = bus->number;
142 dev = PCI_SLOT(devfn);
143 func = PCI_FUNC(devfn);
145 /* check if the bus is top-level */
146 if (bus->parent != NULL) {
147 busno = bus->number;
148 } else {
149 busno = 0;
150 }
152 if (mkaddr(busno, devfn, where, &flags))
153 return -1;
155 switch (size) {
156 case 1:
157 *(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
158 #ifdef __BIG_ENDIAN
159 ((where & 3) ^ 3)) = val;
160 #else
161 (where & 3)) = val;
162 #endif
163 break;
164 case 2:
165 *(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
166 #ifdef __BIG_ENDIAN
167 ((where & 0x3) ^ 0x2)) = val;
168 #else
169 (where & 3)) = val;
170 #endif
171 break;
172 case 4:
173 tx4938_pcicptr->g2pcfgdata = val;
174 break;
175 }
177 return check_abort(flags);
178 }
180 struct pci_ops tx4938_pci_ops = {
181 tx4938_pcibios_read_config,
182 tx4938_pcibios_write_config
183 };
185 struct pci_controller tx4938_pci_controller[] = {
186 /* h/w only supports devices 0x00 to 0x14 */
187 {
188 .pci_ops = &tx4938_pci_ops,
189 .io_resource = &pci_io_resource,
190 .mem_resource = &pci_mem_resource,
191 },
192 /* h/w only supports devices 0x00 to 0x14 */
193 {
194 .pci_ops = &tx4938_pci_ops,
195 .io_resource = &tx4938_pcic1_pci_io_resource,
196 .mem_resource = &tx4938_pcic1_pci_mem_resource,
197 }
198 };