ia64/linux-2.6.18-xen.hg

view arch/sparc64/kernel/central.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 3e8752eb6d9c
children
line source
1 /* $Id: central.c,v 1.15 2001/12/19 00:29:51 davem Exp $
2 * central.c: Central FHC driver for Sunfire/Starfire/Wildfire.
3 *
4 * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com)
5 */
7 #include <linux/kernel.h>
8 #include <linux/types.h>
9 #include <linux/string.h>
10 #include <linux/timer.h>
11 #include <linux/sched.h>
12 #include <linux/delay.h>
13 #include <linux/init.h>
14 #include <linux/bootmem.h>
16 #include <asm/page.h>
17 #include <asm/fhc.h>
18 #include <asm/starfire.h>
20 struct linux_central *central_bus = NULL;
21 struct linux_fhc *fhc_list = NULL;
23 #define IS_CENTRAL_FHC(__fhc) ((__fhc) == central_bus->child)
25 static void central_probe_failure(int line)
26 {
27 prom_printf("CENTRAL: Critical device probe failure at central.c:%d\n",
28 line);
29 prom_halt();
30 }
32 static void central_ranges_init(struct linux_central *central)
33 {
34 struct device_node *dp = central->prom_node;
35 void *pval;
36 int len;
38 central->num_central_ranges = 0;
39 pval = of_get_property(dp, "ranges", &len);
40 if (pval) {
41 memcpy(central->central_ranges, pval, len);
42 central->num_central_ranges =
43 (len / sizeof(struct linux_prom_ranges));
44 }
45 }
47 static void fhc_ranges_init(struct linux_fhc *fhc)
48 {
49 struct device_node *dp = fhc->prom_node;
50 void *pval;
51 int len;
53 fhc->num_fhc_ranges = 0;
54 pval = of_get_property(dp, "ranges", &len);
55 if (pval) {
56 memcpy(fhc->fhc_ranges, pval, len);
57 fhc->num_fhc_ranges =
58 (len / sizeof(struct linux_prom_ranges));
59 }
60 }
62 /* Range application routines are exported to various drivers,
63 * so do not __init this.
64 */
65 static void adjust_regs(struct linux_prom_registers *regp, int nregs,
66 struct linux_prom_ranges *rangep, int nranges)
67 {
68 int regc, rngc;
70 for (regc = 0; regc < nregs; regc++) {
71 for (rngc = 0; rngc < nranges; rngc++)
72 if (regp[regc].which_io == rangep[rngc].ot_child_space)
73 break; /* Fount it */
74 if (rngc == nranges) /* oops */
75 central_probe_failure(__LINE__);
76 regp[regc].which_io = rangep[rngc].ot_parent_space;
77 regp[regc].phys_addr -= rangep[rngc].ot_child_base;
78 regp[regc].phys_addr += rangep[rngc].ot_parent_base;
79 }
80 }
82 /* Apply probed fhc ranges to registers passed, if no ranges return. */
83 void apply_fhc_ranges(struct linux_fhc *fhc,
84 struct linux_prom_registers *regs,
85 int nregs)
86 {
87 if (fhc->num_fhc_ranges)
88 adjust_regs(regs, nregs, fhc->fhc_ranges,
89 fhc->num_fhc_ranges);
90 }
92 /* Apply probed central ranges to registers passed, if no ranges return. */
93 void apply_central_ranges(struct linux_central *central,
94 struct linux_prom_registers *regs, int nregs)
95 {
96 if (central->num_central_ranges)
97 adjust_regs(regs, nregs, central->central_ranges,
98 central->num_central_ranges);
99 }
101 void * __init central_alloc_bootmem(unsigned long size)
102 {
103 void *ret;
105 ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
106 if (ret != NULL)
107 memset(ret, 0, size);
109 return ret;
110 }
112 static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r)
113 {
114 unsigned long ret = ((unsigned long) r->which_io) << 32;
116 return ret | (unsigned long) r->phys_addr;
117 }
119 static void probe_other_fhcs(void)
120 {
121 struct device_node *dp;
122 struct linux_prom64_registers *fpregs;
124 for_each_node_by_name(dp, "fhc") {
125 struct linux_fhc *fhc;
126 int board;
127 u32 tmp;
129 if (dp->parent &&
130 dp->parent->parent != NULL)
131 continue;
133 fhc = (struct linux_fhc *)
134 central_alloc_bootmem(sizeof(struct linux_fhc));
135 if (fhc == NULL)
136 central_probe_failure(__LINE__);
138 /* Link it into the FHC chain. */
139 fhc->next = fhc_list;
140 fhc_list = fhc;
142 /* Toplevel FHCs have no parent. */
143 fhc->parent = NULL;
145 fhc->prom_node = dp;
146 fhc_ranges_init(fhc);
148 /* Non-central FHC's have 64-bit OBP format registers. */
149 fpregs = of_get_property(dp, "reg", NULL);
150 if (!fpregs)
151 central_probe_failure(__LINE__);
153 /* Only central FHC needs special ranges applied. */
154 fhc->fhc_regs.pregs = fpregs[0].phys_addr;
155 fhc->fhc_regs.ireg = fpregs[1].phys_addr;
156 fhc->fhc_regs.ffregs = fpregs[2].phys_addr;
157 fhc->fhc_regs.sregs = fpregs[3].phys_addr;
158 fhc->fhc_regs.uregs = fpregs[4].phys_addr;
159 fhc->fhc_regs.tregs = fpregs[5].phys_addr;
161 board = of_getintprop_default(dp, "board#", -1);
162 fhc->board = board;
164 tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL);
165 if ((tmp & FHC_JTAG_CTRL_MENAB) != 0)
166 fhc->jtag_master = 1;
167 else
168 fhc->jtag_master = 0;
170 tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID);
171 printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] %s\n",
172 board,
173 (tmp & FHC_ID_VERS) >> 28,
174 (tmp & FHC_ID_PARTID) >> 12,
175 (tmp & FHC_ID_MANUF) >> 1,
176 (fhc->jtag_master ? "(JTAG Master)" : ""));
178 /* This bit must be set in all non-central FHC's in
179 * the system. When it is clear, this identifies
180 * the central board.
181 */
182 tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
183 tmp |= FHC_CONTROL_IXIST;
184 upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
185 }
186 }
188 static void probe_clock_board(struct linux_central *central,
189 struct linux_fhc *fhc,
190 struct device_node *fp)
191 {
192 struct device_node *dp;
193 struct linux_prom_registers cregs[3], *pr;
194 int nslots, tmp, nregs;
196 dp = fp->child;
197 while (dp) {
198 if (!strcmp(dp->name, "clock-board"))
199 break;
200 dp = dp->sibling;
201 }
202 if (!dp)
203 central_probe_failure(__LINE__);
205 pr = of_get_property(dp, "reg", &nregs);
206 if (!pr)
207 central_probe_failure(__LINE__);
209 memcpy(cregs, pr, nregs);
210 nregs /= sizeof(struct linux_prom_registers);
212 apply_fhc_ranges(fhc, &cregs[0], nregs);
213 apply_central_ranges(central, &cregs[0], nregs);
214 central->cfreg = prom_reg_to_paddr(&cregs[0]);
215 central->clkregs = prom_reg_to_paddr(&cregs[1]);
217 if (nregs == 2)
218 central->clkver = 0UL;
219 else
220 central->clkver = prom_reg_to_paddr(&cregs[2]);
222 tmp = upa_readb(central->clkregs + CLOCK_STAT1);
223 tmp &= 0xc0;
224 switch(tmp) {
225 case 0x40:
226 nslots = 16;
227 break;
228 case 0xc0:
229 nslots = 8;
230 break;
231 case 0x80:
232 if (central->clkver != 0UL &&
233 upa_readb(central->clkver) != 0) {
234 if ((upa_readb(central->clkver) & 0x80) != 0)
235 nslots = 4;
236 else
237 nslots = 5;
238 break;
239 }
240 default:
241 nslots = 4;
242 break;
243 };
244 central->slots = nslots;
245 printk("CENTRAL: Detected %d slot Enterprise system. cfreg[%02x] cver[%02x]\n",
246 central->slots, upa_readb(central->cfreg),
247 (central->clkver ? upa_readb(central->clkver) : 0x00));
248 }
250 static void ZAP(unsigned long iclr, unsigned long imap)
251 {
252 u32 imap_tmp;
254 upa_writel(0, iclr);
255 upa_readl(iclr);
256 imap_tmp = upa_readl(imap);
257 imap_tmp &= ~(0x80000000);
258 upa_writel(imap_tmp, imap);
259 upa_readl(imap);
260 }
262 static void init_all_fhc_hw(void)
263 {
264 struct linux_fhc *fhc;
266 for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) {
267 u32 tmp;
269 /* Clear all of the interrupt mapping registers
270 * just in case OBP left them in a foul state.
271 */
272 ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR,
273 fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP);
274 ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR,
275 fhc->fhc_regs.sregs + FHC_SREGS_IMAP);
276 ZAP(fhc->fhc_regs.uregs + FHC_UREGS_ICLR,
277 fhc->fhc_regs.uregs + FHC_UREGS_IMAP);
278 ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR,
279 fhc->fhc_regs.tregs + FHC_TREGS_IMAP);
281 /* Setup FHC control register. */
282 tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
284 /* All non-central boards have this bit set. */
285 if (! IS_CENTRAL_FHC(fhc))
286 tmp |= FHC_CONTROL_IXIST;
288 /* For all FHCs, clear the firmware synchronization
289 * line and both low power mode enables.
290 */
291 tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF |
292 FHC_CONTROL_SLINE);
294 upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
295 upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
296 }
298 }
300 void central_probe(void)
301 {
302 struct linux_prom_registers fpregs[6], *pr;
303 struct linux_fhc *fhc;
304 struct device_node *dp, *fp;
305 int err;
307 dp = of_find_node_by_name(NULL, "central");
308 if (!dp) {
309 if (this_is_starfire)
310 starfire_cpu_setup();
311 return;
312 }
314 /* Ok we got one, grab some memory for software state. */
315 central_bus = (struct linux_central *)
316 central_alloc_bootmem(sizeof(struct linux_central));
317 if (central_bus == NULL)
318 central_probe_failure(__LINE__);
320 fhc = (struct linux_fhc *)
321 central_alloc_bootmem(sizeof(struct linux_fhc));
322 if (fhc == NULL)
323 central_probe_failure(__LINE__);
325 /* First init central. */
326 central_bus->child = fhc;
327 central_bus->prom_node = dp;
328 central_ranges_init(central_bus);
330 /* And then central's FHC. */
331 fhc->next = fhc_list;
332 fhc_list = fhc;
334 fhc->parent = central_bus;
335 fp = dp->child;
336 while (fp) {
337 if (!strcmp(fp->name, "fhc"))
338 break;
339 fp = fp->sibling;
340 }
341 if (!fp)
342 central_probe_failure(__LINE__);
344 fhc->prom_node = fp;
345 fhc_ranges_init(fhc);
347 /* Now, map in FHC register set. */
348 pr = of_get_property(fp, "reg", NULL);
349 if (!pr)
350 central_probe_failure(__LINE__);
351 memcpy(fpregs, pr, sizeof(fpregs));
353 apply_central_ranges(central_bus, &fpregs[0], 6);
355 fhc->fhc_regs.pregs = prom_reg_to_paddr(&fpregs[0]);
356 fhc->fhc_regs.ireg = prom_reg_to_paddr(&fpregs[1]);
357 fhc->fhc_regs.ffregs = prom_reg_to_paddr(&fpregs[2]);
358 fhc->fhc_regs.sregs = prom_reg_to_paddr(&fpregs[3]);
359 fhc->fhc_regs.uregs = prom_reg_to_paddr(&fpregs[4]);
360 fhc->fhc_regs.tregs = prom_reg_to_paddr(&fpregs[5]);
362 /* Obtain board number from board status register, Central's
363 * FHC lacks "board#" property.
364 */
365 err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_BSR);
366 fhc->board = (((err >> 16) & 0x01) |
367 ((err >> 12) & 0x0e));
369 fhc->jtag_master = 0;
371 /* Attach the clock board registers for CENTRAL. */
372 probe_clock_board(central_bus, fhc, fp);
374 err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID);
375 printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n",
376 fhc->board,
377 ((err & FHC_ID_VERS) >> 28),
378 ((err & FHC_ID_PARTID) >> 12),
379 ((err & FHC_ID_MANUF) >> 1));
381 probe_other_fhcs();
383 init_all_fhc_hw();
384 }
386 static __inline__ void fhc_ledblink(struct linux_fhc *fhc, int on)
387 {
388 u32 tmp;
390 tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
392 /* NOTE: reverse logic on this bit */
393 if (on)
394 tmp &= ~(FHC_CONTROL_RLED);
395 else
396 tmp |= FHC_CONTROL_RLED;
397 tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE);
399 upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
400 upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
401 }
403 static __inline__ void central_ledblink(struct linux_central *central, int on)
404 {
405 u8 tmp;
407 tmp = upa_readb(central->clkregs + CLOCK_CTRL);
409 /* NOTE: reverse logic on this bit */
410 if (on)
411 tmp &= ~(CLOCK_CTRL_RLED);
412 else
413 tmp |= CLOCK_CTRL_RLED;
415 upa_writeb(tmp, central->clkregs + CLOCK_CTRL);
416 upa_readb(central->clkregs + CLOCK_CTRL);
417 }
419 static struct timer_list sftimer;
420 static int led_state;
422 static void sunfire_timer(unsigned long __ignored)
423 {
424 struct linux_fhc *fhc;
426 central_ledblink(central_bus, led_state);
427 for (fhc = fhc_list; fhc != NULL; fhc = fhc->next)
428 if (! IS_CENTRAL_FHC(fhc))
429 fhc_ledblink(fhc, led_state);
430 led_state = ! led_state;
431 sftimer.expires = jiffies + (HZ >> 1);
432 add_timer(&sftimer);
433 }
435 /* After PCI/SBUS busses have been probed, this is called to perform
436 * final initialization of all FireHose Controllers in the system.
437 */
438 void firetruck_init(void)
439 {
440 struct linux_central *central = central_bus;
441 u8 ctrl;
443 /* No central bus, nothing to do. */
444 if (central == NULL)
445 return;
447 /* OBP leaves it on, turn it off so clock board timer LED
448 * is in sync with FHC ones.
449 */
450 ctrl = upa_readb(central->clkregs + CLOCK_CTRL);
451 ctrl &= ~(CLOCK_CTRL_RLED);
452 upa_writeb(ctrl, central->clkregs + CLOCK_CTRL);
454 led_state = 0;
455 init_timer(&sftimer);
456 sftimer.data = 0;
457 sftimer.function = &sunfire_timer;
458 sftimer.expires = jiffies + (HZ >> 1);
459 add_timer(&sftimer);
460 }