ia64/linux-2.6.18-xen.hg

view arch/mips/sgi-ip27/ip27-hubio.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 * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.
3 * Copyright (C) 2004 Christoph Hellwig.
4 * Released under GPL v2.
5 *
6 * Support functions for the HUB ASIC - mostly PIO mapping related.
7 */
9 #include <linux/bitops.h>
10 #include <linux/string.h>
11 #include <linux/mmzone.h>
12 #include <asm/sn/addrs.h>
13 #include <asm/sn/arch.h>
14 #include <asm/sn/hub.h>
17 static int force_fire_and_forget = 1;
19 /**
20 * hub_pio_map - establish a HUB PIO mapping
21 *
22 * @hub: hub to perform PIO mapping on
23 * @widget: widget ID to perform PIO mapping for
24 * @xtalk_addr: xtalk_address that needs to be mapped
25 * @size: size of the PIO mapping
26 *
27 **/
28 unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget,
29 unsigned long xtalk_addr, size_t size)
30 {
31 nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
32 volatile hubreg_t junk;
33 unsigned i;
35 /* use small-window mapping if possible */
36 if ((xtalk_addr % SWIN_SIZE) + size <= SWIN_SIZE)
37 return NODE_SWIN_BASE(nasid, widget) + (xtalk_addr % SWIN_SIZE);
39 if ((xtalk_addr % BWIN_SIZE) + size > BWIN_SIZE) {
40 printk(KERN_WARNING "PIO mapping at hub %d widget %d addr 0x%lx"
41 " too big (%ld)\n",
42 nasid, widget, xtalk_addr, size);
43 return 0;
44 }
46 xtalk_addr &= ~(BWIN_SIZE-1);
47 for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) {
48 if (test_and_set_bit(i, hub_data(cnode)->h_bigwin_used))
49 continue;
51 /*
52 * The code below does a PIO write to setup an ITTE entry.
53 *
54 * We need to prevent other CPUs from seeing our updated
55 * memory shadow of the ITTE (in the piomap) until the ITTE
56 * entry is actually set up; otherwise, another CPU might
57 * attempt a PIO prematurely.
58 *
59 * Also, the only way we can know that an entry has been
60 * received by the hub and can be used by future PIO reads/
61 * writes is by reading back the ITTE entry after writing it.
62 *
63 * For these two reasons, we PIO read back the ITTE entry
64 * after we write it.
65 */
66 IIO_ITTE_PUT(nasid, i, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr);
67 junk = HUB_L(IIO_ITTE_GET(nasid, i));
69 return NODE_BWIN_BASE(nasid, widget) + (xtalk_addr % BWIN_SIZE);
70 }
72 printk(KERN_WARNING "unable to establish PIO mapping for at"
73 " hub %d widget %d addr 0x%lx\n",
74 nasid, widget, xtalk_addr);
75 return 0;
76 }
79 /*
80 * hub_setup_prb(nasid, prbnum, credits, conveyor)
81 *
82 * Put a PRB into fire-and-forget mode if conveyor isn't set. Otherwise,
83 * put it into conveyor belt mode with the specified number of credits.
84 */
85 static void hub_setup_prb(nasid_t nasid, int prbnum, int credits)
86 {
87 iprb_t prb;
88 int prb_offset;
90 /*
91 * Get the current register value.
92 */
93 prb_offset = IIO_IOPRB(prbnum);
94 prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset);
96 /*
97 * Clear out some fields.
98 */
99 prb.iprb_ovflow = 1;
100 prb.iprb_bnakctr = 0;
101 prb.iprb_anakctr = 0;
103 /*
104 * Enable or disable fire-and-forget mode.
105 */
106 prb.iprb_ff = force_fire_and_forget ? 1 : 0;
108 /*
109 * Set the appropriate number of PIO cresits for the widget.
110 */
111 prb.iprb_xtalkctr = credits;
113 /*
114 * Store the new value to the register.
115 */
116 REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval);
117 }
119 /**
120 * hub_set_piomode - set pio mode for a given hub
121 *
122 * @nasid: physical node ID for the hub in question
123 *
124 * Put the hub into either "PIO conveyor belt" mode or "fire-and-forget" mode.
125 * To do this, we have to make absolutely sure that no PIOs are in progress
126 * so we turn off access to all widgets for the duration of the function.
127 *
128 * XXX - This code should really check what kind of widget we're talking
129 * to. Bridges can only handle three requests, but XG will do more.
130 * How many can crossbow handle to widget 0? We're assuming 1.
131 *
132 * XXX - There is a bug in the crossbow that link reset PIOs do not
133 * return write responses. The easiest solution to this problem is to
134 * leave widget 0 (xbow) in fire-and-forget mode at all times. This
135 * only affects pio's to xbow registers, which should be rare.
136 **/
137 static void hub_set_piomode(nasid_t nasid)
138 {
139 hubreg_t ii_iowa;
140 hubii_wcr_t ii_wcr;
141 unsigned i;
143 ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS);
144 REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0);
146 ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR);
148 if (ii_wcr.iwcr_dir_con) {
149 /*
150 * Assume a bridge here.
151 */
152 hub_setup_prb(nasid, 0, 3);
153 } else {
154 /*
155 * Assume a crossbow here.
156 */
157 hub_setup_prb(nasid, 0, 1);
158 }
160 /*
161 * XXX - Here's where we should take the widget type into
162 * when account assigning credits.
163 */
164 for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++)
165 hub_setup_prb(nasid, i, 3);
167 REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);
168 }
170 /*
171 * hub_pio_init - PIO-related hub initalization
172 *
173 * @hub: hubinfo structure for our hub
174 */
175 void hub_pio_init(cnodeid_t cnode)
176 {
177 nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
178 unsigned i;
180 /* initialize big window piomaps for this hub */
181 bitmap_zero(hub_data(cnode)->h_bigwin_used, HUB_NUM_BIG_WINDOW);
182 for (i = 0; i < HUB_NUM_BIG_WINDOW; i++)
183 IIO_ITTE_DISABLE(nasid, i);
185 hub_set_piomode(nasid);
186 }