ia64/linux-2.6.18-xen.hg

view drivers/rapidio/rio.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 * RapidIO interconnect services
3 * (RapidIO Interconnect Specification, http://www.rapidio.org)
4 *
5 * Copyright 2005 MontaVista Software, Inc.
6 * Matt Porter <mporter@kernel.crashing.org>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
14 #include <linux/types.h>
15 #include <linux/kernel.h>
17 #include <linux/delay.h>
18 #include <linux/init.h>
19 #include <linux/rio.h>
20 #include <linux/rio_drv.h>
21 #include <linux/rio_ids.h>
22 #include <linux/rio_regs.h>
23 #include <linux/module.h>
24 #include <linux/spinlock.h>
25 #include <linux/slab.h>
27 #include "rio.h"
29 static LIST_HEAD(rio_mports);
31 /**
32 * rio_local_get_device_id - Get the base/extended device id for a port
33 * @port: RIO master port from which to get the deviceid
34 *
35 * Reads the base/extended device id from the local device
36 * implementing the master port. Returns the 8/16-bit device
37 * id.
38 */
39 u16 rio_local_get_device_id(struct rio_mport *port)
40 {
41 u32 result;
43 rio_local_read_config_32(port, RIO_DID_CSR, &result);
45 return (RIO_GET_DID(result));
46 }
48 /**
49 * rio_request_inb_mbox - request inbound mailbox service
50 * @mport: RIO master port from which to allocate the mailbox resource
51 * @dev_id: Device specific pointer to pass on event
52 * @mbox: Mailbox number to claim
53 * @entries: Number of entries in inbound mailbox queue
54 * @minb: Callback to execute when inbound message is received
55 *
56 * Requests ownership of an inbound mailbox resource and binds
57 * a callback function to the resource. Returns %0 on success.
58 */
59 int rio_request_inb_mbox(struct rio_mport *mport,
60 void *dev_id,
61 int mbox,
62 int entries,
63 void (*minb) (struct rio_mport * mport, void *dev_id, int mbox,
64 int slot))
65 {
66 int rc = 0;
68 struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL);
70 if (res) {
71 rio_init_mbox_res(res, mbox, mbox);
73 /* Make sure this mailbox isn't in use */
74 if ((rc =
75 request_resource(&mport->riores[RIO_INB_MBOX_RESOURCE],
76 res)) < 0) {
77 kfree(res);
78 goto out;
79 }
81 mport->inb_msg[mbox].res = res;
83 /* Hook the inbound message callback */
84 mport->inb_msg[mbox].mcback = minb;
86 rc = rio_open_inb_mbox(mport, dev_id, mbox, entries);
87 } else
88 rc = -ENOMEM;
90 out:
91 return rc;
92 }
94 /**
95 * rio_release_inb_mbox - release inbound mailbox message service
96 * @mport: RIO master port from which to release the mailbox resource
97 * @mbox: Mailbox number to release
98 *
99 * Releases ownership of an inbound mailbox resource. Returns 0
100 * if the request has been satisfied.
101 */
102 int rio_release_inb_mbox(struct rio_mport *mport, int mbox)
103 {
104 rio_close_inb_mbox(mport, mbox);
106 /* Release the mailbox resource */
107 return release_resource(mport->inb_msg[mbox].res);
108 }
110 /**
111 * rio_request_outb_mbox - request outbound mailbox service
112 * @mport: RIO master port from which to allocate the mailbox resource
113 * @dev_id: Device specific pointer to pass on event
114 * @mbox: Mailbox number to claim
115 * @entries: Number of entries in outbound mailbox queue
116 * @moutb: Callback to execute when outbound message is sent
117 *
118 * Requests ownership of an outbound mailbox resource and binds
119 * a callback function to the resource. Returns 0 on success.
120 */
121 int rio_request_outb_mbox(struct rio_mport *mport,
122 void *dev_id,
123 int mbox,
124 int entries,
125 void (*moutb) (struct rio_mport * mport, void *dev_id, int mbox, int slot))
126 {
127 int rc = 0;
129 struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL);
131 if (res) {
132 rio_init_mbox_res(res, mbox, mbox);
134 /* Make sure this outbound mailbox isn't in use */
135 if ((rc =
136 request_resource(&mport->riores[RIO_OUTB_MBOX_RESOURCE],
137 res)) < 0) {
138 kfree(res);
139 goto out;
140 }
142 mport->outb_msg[mbox].res = res;
144 /* Hook the inbound message callback */
145 mport->outb_msg[mbox].mcback = moutb;
147 rc = rio_open_outb_mbox(mport, dev_id, mbox, entries);
148 } else
149 rc = -ENOMEM;
151 out:
152 return rc;
153 }
155 /**
156 * rio_release_outb_mbox - release outbound mailbox message service
157 * @mport: RIO master port from which to release the mailbox resource
158 * @mbox: Mailbox number to release
159 *
160 * Releases ownership of an inbound mailbox resource. Returns 0
161 * if the request has been satisfied.
162 */
163 int rio_release_outb_mbox(struct rio_mport *mport, int mbox)
164 {
165 rio_close_outb_mbox(mport, mbox);
167 /* Release the mailbox resource */
168 return release_resource(mport->outb_msg[mbox].res);
169 }
171 /**
172 * rio_setup_inb_dbell - bind inbound doorbell callback
173 * @mport: RIO master port to bind the doorbell callback
174 * @dev_id: Device specific pointer to pass on event
175 * @res: Doorbell message resource
176 * @dinb: Callback to execute when doorbell is received
177 *
178 * Adds a doorbell resource/callback pair into a port's
179 * doorbell event list. Returns 0 if the request has been
180 * satisfied.
181 */
182 static int
183 rio_setup_inb_dbell(struct rio_mport *mport, void *dev_id, struct resource *res,
184 void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst,
185 u16 info))
186 {
187 int rc = 0;
188 struct rio_dbell *dbell;
190 if (!(dbell = kmalloc(sizeof(struct rio_dbell), GFP_KERNEL))) {
191 rc = -ENOMEM;
192 goto out;
193 }
195 dbell->res = res;
196 dbell->dinb = dinb;
197 dbell->dev_id = dev_id;
199 list_add_tail(&dbell->node, &mport->dbells);
201 out:
202 return rc;
203 }
205 /**
206 * rio_request_inb_dbell - request inbound doorbell message service
207 * @mport: RIO master port from which to allocate the doorbell resource
208 * @dev_id: Device specific pointer to pass on event
209 * @start: Doorbell info range start
210 * @end: Doorbell info range end
211 * @dinb: Callback to execute when doorbell is received
212 *
213 * Requests ownership of an inbound doorbell resource and binds
214 * a callback function to the resource. Returns 0 if the request
215 * has been satisfied.
216 */
217 int rio_request_inb_dbell(struct rio_mport *mport,
218 void *dev_id,
219 u16 start,
220 u16 end,
221 void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src,
222 u16 dst, u16 info))
223 {
224 int rc = 0;
226 struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL);
228 if (res) {
229 rio_init_dbell_res(res, start, end);
231 /* Make sure these doorbells aren't in use */
232 if ((rc =
233 request_resource(&mport->riores[RIO_DOORBELL_RESOURCE],
234 res)) < 0) {
235 kfree(res);
236 goto out;
237 }
239 /* Hook the doorbell callback */
240 rc = rio_setup_inb_dbell(mport, dev_id, res, dinb);
241 } else
242 rc = -ENOMEM;
244 out:
245 return rc;
246 }
248 /**
249 * rio_release_inb_dbell - release inbound doorbell message service
250 * @mport: RIO master port from which to release the doorbell resource
251 * @start: Doorbell info range start
252 * @end: Doorbell info range end
253 *
254 * Releases ownership of an inbound doorbell resource and removes
255 * callback from the doorbell event list. Returns 0 if the request
256 * has been satisfied.
257 */
258 int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end)
259 {
260 int rc = 0, found = 0;
261 struct rio_dbell *dbell;
263 list_for_each_entry(dbell, &mport->dbells, node) {
264 if ((dbell->res->start == start) && (dbell->res->end == end)) {
265 found = 1;
266 break;
267 }
268 }
270 /* If we can't find an exact match, fail */
271 if (!found) {
272 rc = -EINVAL;
273 goto out;
274 }
276 /* Delete from list */
277 list_del(&dbell->node);
279 /* Release the doorbell resource */
280 rc = release_resource(dbell->res);
282 /* Free the doorbell event */
283 kfree(dbell);
285 out:
286 return rc;
287 }
289 /**
290 * rio_request_outb_dbell - request outbound doorbell message range
291 * @rdev: RIO device from which to allocate the doorbell resource
292 * @start: Doorbell message range start
293 * @end: Doorbell message range end
294 *
295 * Requests ownership of a doorbell message range. Returns a resource
296 * if the request has been satisfied or %NULL on failure.
297 */
298 struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start,
299 u16 end)
300 {
301 struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL);
303 if (res) {
304 rio_init_dbell_res(res, start, end);
306 /* Make sure these doorbells aren't in use */
307 if (request_resource(&rdev->riores[RIO_DOORBELL_RESOURCE], res)
308 < 0) {
309 kfree(res);
310 res = NULL;
311 }
312 }
314 return res;
315 }
317 /**
318 * rio_release_outb_dbell - release outbound doorbell message range
319 * @rdev: RIO device from which to release the doorbell resource
320 * @res: Doorbell resource to be freed
321 *
322 * Releases ownership of a doorbell message range. Returns 0 if the
323 * request has been satisfied.
324 */
325 int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res)
326 {
327 int rc = release_resource(res);
329 kfree(res);
331 return rc;
332 }
334 /**
335 * rio_mport_get_feature - query for devices' extended features
336 * @port: Master port to issue transaction
337 * @local: Indicate a local master port or remote device access
338 * @destid: Destination ID of the device
339 * @hopcount: Number of switch hops to the device
340 * @ftr: Extended feature code
341 *
342 * Tell if a device supports a given RapidIO capability.
343 * Returns the offset of the requested extended feature
344 * block within the device's RIO configuration space or
345 * 0 in case the device does not support it. Possible
346 * values for @ftr:
347 *
348 * %RIO_EFB_PAR_EP_ID LP/LVDS EP Devices
349 *
350 * %RIO_EFB_PAR_EP_REC_ID LP/LVDS EP Recovery Devices
351 *
352 * %RIO_EFB_PAR_EP_FREE_ID LP/LVDS EP Free Devices
353 *
354 * %RIO_EFB_SER_EP_ID LP/Serial EP Devices
355 *
356 * %RIO_EFB_SER_EP_REC_ID LP/Serial EP Recovery Devices
357 *
358 * %RIO_EFB_SER_EP_FREE_ID LP/Serial EP Free Devices
359 */
360 u32
361 rio_mport_get_feature(struct rio_mport * port, int local, u16 destid,
362 u8 hopcount, int ftr)
363 {
364 u32 asm_info, ext_ftr_ptr, ftr_header;
366 if (local)
367 rio_local_read_config_32(port, RIO_ASM_INFO_CAR, &asm_info);
368 else
369 rio_mport_read_config_32(port, destid, hopcount,
370 RIO_ASM_INFO_CAR, &asm_info);
372 ext_ftr_ptr = asm_info & RIO_EXT_FTR_PTR_MASK;
374 while (ext_ftr_ptr) {
375 if (local)
376 rio_local_read_config_32(port, ext_ftr_ptr,
377 &ftr_header);
378 else
379 rio_mport_read_config_32(port, destid, hopcount,
380 ext_ftr_ptr, &ftr_header);
381 if (RIO_GET_BLOCK_ID(ftr_header) == ftr)
382 return ext_ftr_ptr;
383 if (!(ext_ftr_ptr = RIO_GET_BLOCK_PTR(ftr_header)))
384 break;
385 }
387 return 0;
388 }
390 /**
391 * rio_get_asm - Begin or continue searching for a RIO device by vid/did/asm_vid/asm_did
392 * @vid: RIO vid to match or %RIO_ANY_ID to match all vids
393 * @did: RIO did to match or %RIO_ANY_ID to match all dids
394 * @asm_vid: RIO asm_vid to match or %RIO_ANY_ID to match all asm_vids
395 * @asm_did: RIO asm_did to match or %RIO_ANY_ID to match all asm_dids
396 * @from: Previous RIO device found in search, or %NULL for new search
397 *
398 * Iterates through the list of known RIO devices. If a RIO device is
399 * found with a matching @vid, @did, @asm_vid, @asm_did, the reference
400 * count to the device is incrememted and a pointer to its device
401 * structure is returned. Otherwise, %NULL is returned. A new search
402 * is initiated by passing %NULL to the @from argument. Otherwise, if
403 * @from is not %NULL, searches continue from next device on the global
404 * list. The reference count for @from is always decremented if it is
405 * not %NULL.
406 */
407 struct rio_dev *rio_get_asm(u16 vid, u16 did,
408 u16 asm_vid, u16 asm_did, struct rio_dev *from)
409 {
410 struct list_head *n;
411 struct rio_dev *rdev;
413 WARN_ON(in_interrupt());
414 spin_lock(&rio_global_list_lock);
415 n = from ? from->global_list.next : rio_devices.next;
417 while (n && (n != &rio_devices)) {
418 rdev = rio_dev_g(n);
419 if ((vid == RIO_ANY_ID || rdev->vid == vid) &&
420 (did == RIO_ANY_ID || rdev->did == did) &&
421 (asm_vid == RIO_ANY_ID || rdev->asm_vid == asm_vid) &&
422 (asm_did == RIO_ANY_ID || rdev->asm_did == asm_did))
423 goto exit;
424 n = n->next;
425 }
426 rdev = NULL;
427 exit:
428 rio_dev_put(from);
429 rdev = rio_dev_get(rdev);
430 spin_unlock(&rio_global_list_lock);
431 return rdev;
432 }
434 /**
435 * rio_get_device - Begin or continue searching for a RIO device by vid/did
436 * @vid: RIO vid to match or %RIO_ANY_ID to match all vids
437 * @did: RIO did to match or %RIO_ANY_ID to match all dids
438 * @from: Previous RIO device found in search, or %NULL for new search
439 *
440 * Iterates through the list of known RIO devices. If a RIO device is
441 * found with a matching @vid and @did, the reference count to the
442 * device is incrememted and a pointer to its device structure is returned.
443 * Otherwise, %NULL is returned. A new search is initiated by passing %NULL
444 * to the @from argument. Otherwise, if @from is not %NULL, searches
445 * continue from next device on the global list. The reference count for
446 * @from is always decremented if it is not %NULL.
447 */
448 struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from)
449 {
450 return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from);
451 }
453 static void rio_fixup_device(struct rio_dev *dev)
454 {
455 }
457 static int __devinit rio_init(void)
458 {
459 struct rio_dev *dev = NULL;
461 while ((dev = rio_get_device(RIO_ANY_ID, RIO_ANY_ID, dev)) != NULL) {
462 rio_fixup_device(dev);
463 }
464 return 0;
465 }
467 device_initcall(rio_init);
469 int rio_init_mports(void)
470 {
471 int rc = 0;
472 struct rio_mport *port;
474 list_for_each_entry(port, &rio_mports, node) {
475 if (!request_mem_region(port->iores.start,
476 port->iores.end - port->iores.start,
477 port->name)) {
478 printk(KERN_ERR
479 "RIO: Error requesting master port region %8.8lx-%8.8lx\n",
480 port->iores.start, port->iores.end - 1);
481 rc = -ENOMEM;
482 goto out;
483 }
485 if (port->host_deviceid >= 0)
486 rio_enum_mport(port);
487 else
488 rio_disc_mport(port);
489 }
491 out:
492 return rc;
493 }
495 void rio_register_mport(struct rio_mport *port)
496 {
497 list_add_tail(&port->node, &rio_mports);
498 }
500 EXPORT_SYMBOL_GPL(rio_local_get_device_id);
501 EXPORT_SYMBOL_GPL(rio_get_device);
502 EXPORT_SYMBOL_GPL(rio_get_asm);
503 EXPORT_SYMBOL_GPL(rio_request_inb_dbell);
504 EXPORT_SYMBOL_GPL(rio_release_inb_dbell);
505 EXPORT_SYMBOL_GPL(rio_request_outb_dbell);
506 EXPORT_SYMBOL_GPL(rio_release_outb_dbell);
507 EXPORT_SYMBOL_GPL(rio_request_inb_mbox);
508 EXPORT_SYMBOL_GPL(rio_release_inb_mbox);
509 EXPORT_SYMBOL_GPL(rio_request_outb_mbox);
510 EXPORT_SYMBOL_GPL(rio_release_outb_mbox);