ia64/linux-2.6.18-xen.hg

view drivers/mca/mca-legacy.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 /* -*- mode: c; c-basic-offset: 8 -*- */
3 /*
4 * MCA bus support functions for legacy (2.4) API.
5 *
6 * Legacy API means the API that operates in terms of MCA slot number
7 *
8 * (C) 2002 James Bottomley <James.Bottomley@HansenPartnership.com>
9 *
10 **-----------------------------------------------------------------------------
11 **
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License as published by
14 ** the Free Software Foundation; either version 2 of the License, or
15 ** (at your option) any later version.
16 **
17 ** This program is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ** GNU General Public License for more details.
21 **
22 ** You should have received a copy of the GNU General Public License
23 ** along with this program; if not, write to the Free Software
24 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 **
26 **-----------------------------------------------------------------------------
27 */
29 #include <linux/module.h>
30 #include <linux/device.h>
31 #include <linux/mca-legacy.h>
32 #include <asm/io.h>
34 /* NOTE: This structure is stack allocated */
35 struct mca_find_adapter_info {
36 int id;
37 int slot;
38 struct mca_device *mca_dev;
39 };
41 /* The purpose of this iterator is to loop over all the devices and
42 * find the one with the smallest slot number that's just greater than
43 * or equal to the required slot with a matching id */
44 static int mca_find_adapter_callback(struct device *dev, void *data)
45 {
46 struct mca_find_adapter_info *info = data;
47 struct mca_device *mca_dev = to_mca_device(dev);
49 if(mca_dev->pos_id != info->id)
50 return 0;
52 if(mca_dev->slot < info->slot)
53 return 0;
55 if(!info->mca_dev || info->mca_dev->slot >= mca_dev->slot)
56 info->mca_dev = mca_dev;
58 return 0;
59 }
61 /**
62 * mca_find_adapter - scan for adapters
63 * @id: MCA identification to search for
64 * @start: starting slot
65 *
66 * Search the MCA configuration for adapters matching the 16bit
67 * ID given. The first time it should be called with start as zero
68 * and then further calls made passing the return value of the
69 * previous call until %MCA_NOTFOUND is returned.
70 *
71 * Disabled adapters are not reported.
72 */
74 int mca_find_adapter(int id, int start)
75 {
76 struct mca_find_adapter_info info;
78 if(id == 0xffff)
79 return MCA_NOTFOUND;
81 info.slot = start;
82 info.id = id;
83 info.mca_dev = NULL;
85 for(;;) {
86 bus_for_each_dev(&mca_bus_type, NULL, &info, mca_find_adapter_callback);
88 if(info.mca_dev == NULL)
89 return MCA_NOTFOUND;
91 if(info.mca_dev->status != MCA_ADAPTER_DISABLED)
92 break;
94 /* OK, found adapter but it was disabled. Go around
95 * again, excluding the slot we just found */
97 info.slot = info.mca_dev->slot + 1;
98 info.mca_dev = NULL;
99 }
101 return info.mca_dev->slot;
102 }
103 EXPORT_SYMBOL(mca_find_adapter);
105 /*--------------------------------------------------------------------*/
107 /**
108 * mca_find_unused_adapter - scan for unused adapters
109 * @id: MCA identification to search for
110 * @start: starting slot
111 *
112 * Search the MCA configuration for adapters matching the 16bit
113 * ID given. The first time it should be called with start as zero
114 * and then further calls made passing the return value of the
115 * previous call until %MCA_NOTFOUND is returned.
116 *
117 * Adapters that have been claimed by drivers and those that
118 * are disabled are not reported. This function thus allows a driver
119 * to scan for further cards when some may already be driven.
120 */
122 int mca_find_unused_adapter(int id, int start)
123 {
124 struct mca_find_adapter_info info = { 0 };
126 if (!MCA_bus || id == 0xffff)
127 return MCA_NOTFOUND;
129 info.slot = start;
130 info.id = id;
131 info.mca_dev = NULL;
133 for(;;) {
134 bus_for_each_dev(&mca_bus_type, NULL, &info, mca_find_adapter_callback);
136 if(info.mca_dev == NULL)
137 return MCA_NOTFOUND;
139 if(info.mca_dev->status != MCA_ADAPTER_DISABLED
140 && !info.mca_dev->driver_loaded)
141 break;
143 /* OK, found adapter but it was disabled or already in
144 * use. Go around again, excluding the slot we just
145 * found */
147 info.slot = info.mca_dev->slot + 1;
148 info.mca_dev = NULL;
149 }
151 return info.mca_dev->slot;
152 }
153 EXPORT_SYMBOL(mca_find_unused_adapter);
155 /* NOTE: stack allocated structure */
156 struct mca_find_device_by_slot_info {
157 int slot;
158 struct mca_device *mca_dev;
159 };
161 static int mca_find_device_by_slot_callback(struct device *dev, void *data)
162 {
163 struct mca_find_device_by_slot_info *info = data;
164 struct mca_device *mca_dev = to_mca_device(dev);
166 if(mca_dev->slot == info->slot)
167 info->mca_dev = mca_dev;
169 return 0;
170 }
172 struct mca_device *mca_find_device_by_slot(int slot)
173 {
174 struct mca_find_device_by_slot_info info;
176 info.slot = slot;
177 info.mca_dev = NULL;
179 bus_for_each_dev(&mca_bus_type, NULL, &info, mca_find_device_by_slot_callback);
181 return info.mca_dev;
182 }
184 /**
185 * mca_read_stored_pos - read POS register from boot data
186 * @slot: slot number to read from
187 * @reg: register to read from
188 *
189 * Fetch a POS value that was stored at boot time by the kernel
190 * when it scanned the MCA space. The register value is returned.
191 * Missing or invalid registers report 0.
192 */
193 unsigned char mca_read_stored_pos(int slot, int reg)
194 {
195 struct mca_device *mca_dev = mca_find_device_by_slot(slot);
197 if(!mca_dev)
198 return 0;
200 return mca_device_read_stored_pos(mca_dev, reg);
201 }
202 EXPORT_SYMBOL(mca_read_stored_pos);
205 /**
206 * mca_read_pos - read POS register from card
207 * @slot: slot number to read from
208 * @reg: register to read from
209 *
210 * Fetch a POS value directly from the hardware to obtain the
211 * current value. This is much slower than mca_read_stored_pos and
212 * may not be invoked from interrupt context. It handles the
213 * deep magic required for onboard devices transparently.
214 */
216 unsigned char mca_read_pos(int slot, int reg)
217 {
218 struct mca_device *mca_dev = mca_find_device_by_slot(slot);
220 if(!mca_dev)
221 return 0;
223 return mca_device_read_pos(mca_dev, reg);
224 }
225 EXPORT_SYMBOL(mca_read_pos);
228 /**
229 * mca_write_pos - read POS register from card
230 * @slot: slot number to read from
231 * @reg: register to read from
232 * @byte: byte to write to the POS registers
233 *
234 * Store a POS value directly from the hardware. You should not
235 * normally need to use this function and should have a very good
236 * knowledge of MCA bus before you do so. Doing this wrongly can
237 * damage the hardware.
238 *
239 * This function may not be used from interrupt context.
240 *
241 * Note that this a technically a Bad Thing, as IBM tech stuff says
242 * you should only set POS values through their utilities.
243 * However, some devices such as the 3c523 recommend that you write
244 * back some data to make sure the configuration is consistent.
245 * I'd say that IBM is right, but I like my drivers to work.
246 *
247 * This function can't do checks to see if multiple devices end up
248 * with the same resources, so you might see magic smoke if someone
249 * screws up.
250 */
252 void mca_write_pos(int slot, int reg, unsigned char byte)
253 {
254 struct mca_device *mca_dev = mca_find_device_by_slot(slot);
256 if(!mca_dev)
257 return;
259 mca_device_write_pos(mca_dev, reg, byte);
260 }
261 EXPORT_SYMBOL(mca_write_pos);
263 /**
264 * mca_set_adapter_name - Set the description of the card
265 * @slot: slot to name
266 * @name: text string for the namen
267 *
268 * This function sets the name reported via /proc for this
269 * adapter slot. This is for user information only. Setting a
270 * name deletes any previous name.
271 */
273 void mca_set_adapter_name(int slot, char* name)
274 {
275 struct mca_device *mca_dev = mca_find_device_by_slot(slot);
277 if(!mca_dev)
278 return;
280 mca_device_set_name(mca_dev, name);
281 }
282 EXPORT_SYMBOL(mca_set_adapter_name);
284 /**
285 * mca_is_adapter_used - check if claimed by driver
286 * @slot: slot to check
287 *
288 * Returns 1 if the slot has been claimed by a driver
289 */
291 int mca_is_adapter_used(int slot)
292 {
293 struct mca_device *mca_dev = mca_find_device_by_slot(slot);
295 if(!mca_dev)
296 return 0;
298 return mca_device_claimed(mca_dev);
299 }
300 EXPORT_SYMBOL(mca_is_adapter_used);
302 /**
303 * mca_mark_as_used - claim an MCA device
304 * @slot: slot to claim
305 * FIXME: should we make this threadsafe
306 *
307 * Claim an MCA slot for a device driver. If the
308 * slot is already taken the function returns 1,
309 * if it is not taken it is claimed and 0 is
310 * returned.
311 */
313 int mca_mark_as_used(int slot)
314 {
315 struct mca_device *mca_dev = mca_find_device_by_slot(slot);
317 if(!mca_dev)
318 /* FIXME: this is actually a severe error */
319 return 1;
321 if(mca_device_claimed(mca_dev))
322 return 1;
324 mca_device_set_claim(mca_dev, 1);
326 return 0;
327 }
328 EXPORT_SYMBOL(mca_mark_as_used);
330 /**
331 * mca_mark_as_unused - release an MCA device
332 * @slot: slot to claim
333 *
334 * Release the slot for other drives to use.
335 */
337 void mca_mark_as_unused(int slot)
338 {
339 struct mca_device *mca_dev = mca_find_device_by_slot(slot);
341 if(!mca_dev)
342 return;
344 mca_device_set_claim(mca_dev, 0);
345 }
346 EXPORT_SYMBOL(mca_mark_as_unused);