ia64/linux-2.6.18-xen.hg

view arch/mips/sni/irq.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) 1992 Linus Torvalds
7 * Copyright (C) 1994 - 2000 Ralf Baechle
8 */
9 #include <linux/delay.h>
10 #include <linux/init.h>
11 #include <linux/interrupt.h>
12 #include <linux/irq.h>
13 #include <linux/kernel.h>
14 #include <linux/spinlock.h>
16 #include <asm/i8259.h>
17 #include <asm/io.h>
18 #include <asm/sni.h>
20 DEFINE_SPINLOCK(pciasic_lock);
22 static void enable_pciasic_irq(unsigned int irq)
23 {
24 unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
25 unsigned long flags;
27 spin_lock_irqsave(&pciasic_lock, flags);
28 *(volatile u8 *) PCIMT_IRQSEL |= mask;
29 spin_unlock_irqrestore(&pciasic_lock, flags);
30 }
32 static unsigned int startup_pciasic_irq(unsigned int irq)
33 {
34 enable_pciasic_irq(irq);
35 return 0; /* never anything pending */
36 }
38 #define shutdown_pciasic_irq disable_pciasic_irq
40 void disable_pciasic_irq(unsigned int irq)
41 {
42 unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2));
43 unsigned long flags;
45 spin_lock_irqsave(&pciasic_lock, flags);
46 *(volatile u8 *) PCIMT_IRQSEL &= mask;
47 spin_unlock_irqrestore(&pciasic_lock, flags);
48 }
50 #define mask_and_ack_pciasic_irq disable_pciasic_irq
52 static void end_pciasic_irq(unsigned int irq)
53 {
54 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
55 enable_pciasic_irq(irq);
56 }
58 static struct irq_chip pciasic_irq_type = {
59 .typename = "ASIC-PCI",
60 .startup = startup_pciasic_irq,
61 .shutdown = shutdown_pciasic_irq,
62 .enable = enable_pciasic_irq,
63 .disable = disable_pciasic_irq,
64 .ack = mask_and_ack_pciasic_irq,
65 .end = end_pciasic_irq,
66 };
68 /*
69 * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
70 * button interrupts. Later ...
71 */
72 static void pciasic_hwint0(struct pt_regs *regs)
73 {
74 panic("Received int0 but no handler yet ...");
75 }
77 /* This interrupt was used for the com1 console on the first prototypes. */
78 static void pciasic_hwint2(struct pt_regs *regs)
79 {
80 /* I think this shouldn't happen on production machines. */
81 panic("hwint2 and no handler yet");
82 }
84 /* hwint5 is the r4k count / compare interrupt */
85 static void pciasic_hwint5(struct pt_regs *regs)
86 {
87 panic("hwint5 and no handler yet");
88 }
90 static unsigned int ls1bit8(unsigned int x)
91 {
92 int b = 7, s;
94 s = 4; if ((x & 0x0f) == 0) s = 0; b -= s; x <<= s;
95 s = 2; if ((x & 0x30) == 0) s = 0; b -= s; x <<= s;
96 s = 1; if ((x & 0x40) == 0) s = 0; b -= s;
98 return b;
99 }
101 /*
102 * hwint 1 deals with EISA and SCSI interrupts,
103 *
104 * The EISA_INT bit in CSITPEND is high active, all others are low active.
105 */
106 static void pciasic_hwint1(struct pt_regs *regs)
107 {
108 u8 pend = *(volatile char *)PCIMT_CSITPEND;
109 unsigned long flags;
111 if (pend & IT_EISA) {
112 int irq;
113 /*
114 * Note: ASIC PCI's builtin interrupt achknowledge feature is
115 * broken. Using it may result in loss of some or all i8259
116 * interupts, so don't use PCIMT_INT_ACKNOWLEDGE ...
117 */
118 irq = i8259_irq();
119 if (unlikely(irq < 0))
120 return;
122 do_IRQ(irq, regs);
123 }
125 if (!(pend & IT_SCSI)) {
126 flags = read_c0_status();
127 clear_c0_status(ST0_IM);
128 do_IRQ(PCIMT_IRQ_SCSI, regs);
129 write_c0_status(flags);
130 }
131 }
133 /*
134 * hwint 3 should deal with the PCI A - D interrupts,
135 */
136 static void pciasic_hwint3(struct pt_regs *regs)
137 {
138 u8 pend = *(volatile char *)PCIMT_CSITPEND;
139 int irq;
141 pend &= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
142 clear_c0_status(IE_IRQ3);
143 irq = PCIMT_IRQ_INT2 + ls1bit8(pend);
144 do_IRQ(irq, regs);
145 set_c0_status(IE_IRQ3);
146 }
148 /*
149 * hwint 4 is used for only the onboard PCnet 32.
150 */
151 static void pciasic_hwint4(struct pt_regs *regs)
152 {
153 clear_c0_status(IE_IRQ4);
154 do_IRQ(PCIMT_IRQ_ETHERNET, regs);
155 set_c0_status(IE_IRQ4);
156 }
158 asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
159 {
160 unsigned int pending = read_c0_status() & read_c0_cause();
161 static unsigned char led_cache;
163 *(volatile unsigned char *) PCIMT_CSLED = ++led_cache;
165 if (pending & 0x0800)
166 pciasic_hwint1(regs);
167 else if (pending & 0x4000)
168 pciasic_hwint4(regs);
169 else if (pending & 0x2000)
170 pciasic_hwint3(regs);
171 else if (pending & 0x1000)
172 pciasic_hwint2(regs);
173 else if (pending & 0x8000)
174 pciasic_hwint5(regs);
175 else if (pending & 0x0400)
176 pciasic_hwint0(regs);
177 }
179 void __init init_pciasic(void)
180 {
181 unsigned long flags;
183 spin_lock_irqsave(&pciasic_lock, flags);
184 * (volatile u8 *) PCIMT_IRQSEL =
185 IT_EISA | IT_INTA | IT_INTB | IT_INTC | IT_INTD;
186 spin_unlock_irqrestore(&pciasic_lock, flags);
187 }
189 /*
190 * On systems with i8259-style interrupt controllers we assume for
191 * driver compatibility reasons interrupts 0 - 15 to be the i8295
192 * interrupts even if the hardware uses a different interrupt numbering.
193 */
194 void __init arch_init_irq(void)
195 {
196 int i;
198 init_i8259_irqs(); /* Integrated i8259 */
199 init_pciasic();
201 /* Actually we've got more interrupts to handle ... */
202 for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++) {
203 irq_desc[i].status = IRQ_DISABLED;
204 irq_desc[i].action = 0;
205 irq_desc[i].depth = 1;
206 irq_desc[i].chip = &pciasic_irq_type;
207 }
209 change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ2|IE_IRQ3|IE_IRQ4);
210 }