ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/sys_noritake.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 * linux/arch/alpha/kernel/sys_noritake.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Code supporting the NORITAKE (AlphaServer 1000A),
9 * CORELLE (AlphaServer 800), and ALCOR Primo (AlphaStation 600A).
10 */
12 #include <linux/kernel.h>
13 #include <linux/types.h>
14 #include <linux/mm.h>
15 #include <linux/sched.h>
16 #include <linux/pci.h>
17 #include <linux/init.h>
18 #include <linux/bitops.h>
20 #include <asm/ptrace.h>
21 #include <asm/system.h>
22 #include <asm/dma.h>
23 #include <asm/irq.h>
24 #include <asm/mmu_context.h>
25 #include <asm/io.h>
26 #include <asm/pgtable.h>
27 #include <asm/core_apecs.h>
28 #include <asm/core_cia.h>
29 #include <asm/tlbflush.h>
31 #include "proto.h"
32 #include "irq_impl.h"
33 #include "pci_impl.h"
34 #include "machvec_impl.h"
36 /* Note mask bit is true for ENABLED irqs. */
37 static int cached_irq_mask;
39 static inline void
40 noritake_update_irq_hw(int irq, int mask)
41 {
42 int port = 0x54a;
43 if (irq >= 32) {
44 mask >>= 16;
45 port = 0x54c;
46 }
47 outw(mask, port);
48 }
50 static void
51 noritake_enable_irq(unsigned int irq)
52 {
53 noritake_update_irq_hw(irq, cached_irq_mask |= 1 << (irq - 16));
54 }
56 static void
57 noritake_disable_irq(unsigned int irq)
58 {
59 noritake_update_irq_hw(irq, cached_irq_mask &= ~(1 << (irq - 16)));
60 }
62 static unsigned int
63 noritake_startup_irq(unsigned int irq)
64 {
65 noritake_enable_irq(irq);
66 return 0;
67 }
69 static struct hw_interrupt_type noritake_irq_type = {
70 .typename = "NORITAKE",
71 .startup = noritake_startup_irq,
72 .shutdown = noritake_disable_irq,
73 .enable = noritake_enable_irq,
74 .disable = noritake_disable_irq,
75 .ack = noritake_disable_irq,
76 .end = noritake_enable_irq,
77 };
79 static void
80 noritake_device_interrupt(unsigned long vector, struct pt_regs *regs)
81 {
82 unsigned long pld;
83 unsigned int i;
85 /* Read the interrupt summary registers of NORITAKE */
86 pld = (((unsigned long) inw(0x54c) << 32)
87 | ((unsigned long) inw(0x54a) << 16)
88 | ((unsigned long) inb(0xa0) << 8)
89 | inb(0x20));
91 /*
92 * Now for every possible bit set, work through them and call
93 * the appropriate interrupt handler.
94 */
95 while (pld) {
96 i = ffz(~pld);
97 pld &= pld - 1; /* clear least bit set */
98 if (i < 16) {
99 isa_device_interrupt(vector, regs);
100 } else {
101 handle_irq(i, regs);
102 }
103 }
104 }
106 static void
107 noritake_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
108 {
109 int irq;
111 irq = (vector - 0x800) >> 4;
113 /*
114 * I really hate to do this, too, but the NORITAKE SRM console also
115 * reports PCI vectors *lower* than I expected from the bit numbers
116 * in the documentation.
117 * But I really don't want to change the fixup code for allocation
118 * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
119 * look nice and clean now.
120 * So, here's this additional grotty hack... :-(
121 */
122 if (irq >= 16)
123 irq = irq + 1;
125 handle_irq(irq, regs);
126 }
128 static void __init
129 noritake_init_irq(void)
130 {
131 long i;
133 if (alpha_using_srm)
134 alpha_mv.device_interrupt = noritake_srm_device_interrupt;
136 outw(0, 0x54a);
137 outw(0, 0x54c);
139 for (i = 16; i < 48; ++i) {
140 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
141 irq_desc[i].chip = &noritake_irq_type;
142 }
144 init_i8259a_irqs();
145 common_init_isa_dma();
146 }
149 /*
150 * PCI Fixup configuration.
151 *
152 * Summary @ 0x542, summary register #1:
153 * Bit Meaning
154 * 0 All valid ints from summary regs 2 & 3
155 * 1 QLOGIC ISP1020A SCSI
156 * 2 Interrupt Line A from slot 0
157 * 3 Interrupt Line B from slot 0
158 * 4 Interrupt Line A from slot 1
159 * 5 Interrupt line B from slot 1
160 * 6 Interrupt Line A from slot 2
161 * 7 Interrupt Line B from slot 2
162 * 8 Interrupt Line A from slot 3
163 * 9 Interrupt Line B from slot 3
164 *10 Interrupt Line A from slot 4
165 *11 Interrupt Line B from slot 4
166 *12 Interrupt Line A from slot 5
167 *13 Interrupt Line B from slot 5
168 *14 Interrupt Line A from slot 6
169 *15 Interrupt Line B from slot 6
170 *
171 * Summary @ 0x544, summary register #2:
172 * Bit Meaning
173 * 0 OR of all unmasked ints in SR #2
174 * 1 OR of secondary bus ints
175 * 2 Interrupt Line C from slot 0
176 * 3 Interrupt Line D from slot 0
177 * 4 Interrupt Line C from slot 1
178 * 5 Interrupt line D from slot 1
179 * 6 Interrupt Line C from slot 2
180 * 7 Interrupt Line D from slot 2
181 * 8 Interrupt Line C from slot 3
182 * 9 Interrupt Line D from slot 3
183 *10 Interrupt Line C from slot 4
184 *11 Interrupt Line D from slot 4
185 *12 Interrupt Line C from slot 5
186 *13 Interrupt Line D from slot 5
187 *14 Interrupt Line C from slot 6
188 *15 Interrupt Line D from slot 6
189 *
190 * The device to slot mapping looks like:
191 *
192 * Slot Device
193 * 7 Intel PCI-EISA bridge chip
194 * 8 DEC PCI-PCI bridge chip
195 * 11 PCI on board slot 0
196 * 12 PCI on board slot 1
197 * 13 PCI on board slot 2
198 *
199 *
200 * This two layered interrupt approach means that we allocate IRQ 16 and
201 * above for PCI interrupts. The IRQ relates to which bit the interrupt
202 * comes in on. This makes interrupt processing much easier.
203 */
205 static int __init
206 noritake_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
207 {
208 static char irq_tab[15][5] __initdata = {
209 /*INT INTA INTB INTC INTD */
210 /* note: IDSELs 16, 17, and 25 are CORELLE only */
211 { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
212 { -1, -1, -1, -1, -1}, /* IdSel 17, S3 Trio64 */
213 { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
214 { -1, -1, -1, -1, -1}, /* IdSel 19, PPB */
215 { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
216 { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
217 { 16+2, 16+2, 16+3, 32+2, 32+3}, /* IdSel 22, slot 0 */
218 { 16+4, 16+4, 16+5, 32+4, 32+5}, /* IdSel 23, slot 1 */
219 { 16+6, 16+6, 16+7, 32+6, 32+7}, /* IdSel 24, slot 2 */
220 { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 25, slot 3 */
221 /* The following 5 are actually on PCI bus 1, which is
222 across the built-in bridge of the NORITAKE only. */
223 { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
224 { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 17, slot 3 */
225 {16+10, 16+10, 16+11, 32+10, 32+11}, /* IdSel 18, slot 4 */
226 {16+12, 16+12, 16+13, 32+12, 32+13}, /* IdSel 19, slot 5 */
227 {16+14, 16+14, 16+15, 32+14, 32+15}, /* IdSel 20, slot 6 */
228 };
229 const long min_idsel = 5, max_idsel = 19, irqs_per_slot = 5;
230 return COMMON_TABLE_LOOKUP;
231 }
233 static u8 __init
234 noritake_swizzle(struct pci_dev *dev, u8 *pinp)
235 {
236 int slot, pin = *pinp;
238 if (dev->bus->number == 0) {
239 slot = PCI_SLOT(dev->devfn);
240 }
241 /* Check for the built-in bridge */
242 else if (PCI_SLOT(dev->bus->self->devfn) == 8) {
243 slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */
244 }
245 else
246 {
247 /* Must be a card-based bridge. */
248 do {
249 if (PCI_SLOT(dev->bus->self->devfn) == 8) {
250 slot = PCI_SLOT(dev->devfn) + 15;
251 break;
252 }
253 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
255 /* Move up the chain of bridges. */
256 dev = dev->bus->self;
257 /* Slot of the next bridge. */
258 slot = PCI_SLOT(dev->devfn);
259 } while (dev->bus->self);
260 }
261 *pinp = pin;
262 return slot;
263 }
265 #if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
266 static void
267 noritake_apecs_machine_check(unsigned long vector, unsigned long la_ptr,
268 struct pt_regs * regs)
269 {
270 #define MCHK_NO_DEVSEL 0x205U
271 #define MCHK_NO_TABT 0x204U
273 struct el_common *mchk_header;
274 unsigned int code;
276 mchk_header = (struct el_common *)la_ptr;
278 /* Clear the error before any reporting. */
279 mb();
280 mb(); /* magic */
281 draina();
282 apecs_pci_clr_err();
283 wrmces(0x7);
284 mb();
286 code = mchk_header->code;
287 process_mcheck_info(vector, la_ptr, regs, "NORITAKE APECS",
288 (mcheck_expected(0)
289 && (code == MCHK_NO_DEVSEL
290 || code == MCHK_NO_TABT)));
291 }
292 #endif
295 /*
296 * The System Vectors
297 */
299 #if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
300 struct alpha_machine_vector noritake_mv __initmv = {
301 .vector_name = "Noritake",
302 DO_EV4_MMU,
303 DO_DEFAULT_RTC,
304 DO_APECS_IO,
305 .machine_check = noritake_apecs_machine_check,
306 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
307 .min_io_address = EISA_DEFAULT_IO_BASE,
308 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
310 .nr_irqs = 48,
311 .device_interrupt = noritake_device_interrupt,
313 .init_arch = apecs_init_arch,
314 .init_irq = noritake_init_irq,
315 .init_rtc = common_init_rtc,
316 .init_pci = common_init_pci,
317 .pci_map_irq = noritake_map_irq,
318 .pci_swizzle = noritake_swizzle,
319 };
320 ALIAS_MV(noritake)
321 #endif
323 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO)
324 struct alpha_machine_vector noritake_primo_mv __initmv = {
325 .vector_name = "Noritake-Primo",
326 DO_EV5_MMU,
327 DO_DEFAULT_RTC,
328 DO_CIA_IO,
329 .machine_check = cia_machine_check,
330 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
331 .min_io_address = EISA_DEFAULT_IO_BASE,
332 .min_mem_address = CIA_DEFAULT_MEM_BASE,
334 .nr_irqs = 48,
335 .device_interrupt = noritake_device_interrupt,
337 .init_arch = cia_init_arch,
338 .init_irq = noritake_init_irq,
339 .init_rtc = common_init_rtc,
340 .init_pci = cia_init_pci,
341 .kill_arch = cia_kill_arch,
342 .pci_map_irq = noritake_map_irq,
343 .pci_swizzle = noritake_swizzle,
344 };
345 ALIAS_MV(noritake_primo)
346 #endif