ia64/linux-2.6.18-xen.hg

annotate drivers/pci/search.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 5888ffa4b252
children
rev   line source
ian@0 1 /*
ian@0 2 * PCI searching functions.
ian@0 3 *
ian@0 4 * Copyright (C) 1993 -- 1997 Drew Eckhardt, Frederic Potter,
ian@0 5 * David Mosberger-Tang
ian@0 6 * Copyright (C) 1997 -- 2000 Martin Mares <mj@ucw.cz>
ian@0 7 * Copyright (C) 2003 -- 2004 Greg Kroah-Hartman <greg@kroah.com>
ian@0 8 */
ian@0 9
ian@0 10 #include <linux/init.h>
ian@0 11 #include <linux/pci.h>
ian@0 12 #include <linux/module.h>
ian@0 13 #include <linux/interrupt.h>
ian@0 14 #include "pci.h"
ian@0 15
ian@0 16 DECLARE_RWSEM(pci_bus_sem);
ian@0 17
ian@0 18 static struct pci_bus * __devinit
ian@0 19 pci_do_find_bus(struct pci_bus* bus, unsigned char busnr)
ian@0 20 {
ian@0 21 struct pci_bus* child;
ian@0 22 struct list_head *tmp;
ian@0 23
ian@0 24 if(bus->number == busnr)
ian@0 25 return bus;
ian@0 26
ian@0 27 list_for_each(tmp, &bus->children) {
ian@0 28 child = pci_do_find_bus(pci_bus_b(tmp), busnr);
ian@0 29 if(child)
ian@0 30 return child;
ian@0 31 }
ian@0 32 return NULL;
ian@0 33 }
ian@0 34
ian@0 35 /**
ian@0 36 * pci_find_bus - locate PCI bus from a given domain and bus number
ian@0 37 * @domain: number of PCI domain to search
ian@0 38 * @busnr: number of desired PCI bus
ian@0 39 *
ian@0 40 * Given a PCI bus number and domain number, the desired PCI bus is located
ian@0 41 * in the global list of PCI buses. If the bus is found, a pointer to its
ian@0 42 * data structure is returned. If no bus is found, %NULL is returned.
ian@0 43 */
ian@0 44 struct pci_bus * pci_find_bus(int domain, int busnr)
ian@0 45 {
ian@0 46 struct pci_bus *bus = NULL;
ian@0 47 struct pci_bus *tmp_bus;
ian@0 48
ian@0 49 while ((bus = pci_find_next_bus(bus)) != NULL) {
ian@0 50 if (pci_domain_nr(bus) != domain)
ian@0 51 continue;
ian@0 52 tmp_bus = pci_do_find_bus(bus, busnr);
ian@0 53 if (tmp_bus)
ian@0 54 return tmp_bus;
ian@0 55 }
ian@0 56 return NULL;
ian@0 57 }
ian@0 58
ian@0 59 /**
ian@0 60 * pci_find_next_bus - begin or continue searching for a PCI bus
ian@0 61 * @from: Previous PCI bus found, or %NULL for new search.
ian@0 62 *
ian@0 63 * Iterates through the list of known PCI busses. A new search is
ian@0 64 * initiated by passing %NULL as the @from argument. Otherwise if
ian@0 65 * @from is not %NULL, searches continue from next device on the
ian@0 66 * global list.
ian@0 67 */
ian@0 68 struct pci_bus *
ian@0 69 pci_find_next_bus(const struct pci_bus *from)
ian@0 70 {
ian@0 71 struct list_head *n;
ian@0 72 struct pci_bus *b = NULL;
ian@0 73
ian@0 74 WARN_ON(in_interrupt());
ian@0 75 down_read(&pci_bus_sem);
ian@0 76 n = from ? from->node.next : pci_root_buses.next;
ian@0 77 if (n != &pci_root_buses)
ian@0 78 b = pci_bus_b(n);
ian@0 79 up_read(&pci_bus_sem);
ian@0 80 return b;
ian@0 81 }
ian@0 82
ian@0 83 /**
ian@0 84 * pci_find_slot - locate PCI device from a given PCI slot
ian@0 85 * @bus: number of PCI bus on which desired PCI device resides
ian@0 86 * @devfn: encodes number of PCI slot in which the desired PCI
ian@0 87 * device resides and the logical device number within that slot
ian@0 88 * in case of multi-function devices.
ian@0 89 *
ian@0 90 * Given a PCI bus and slot/function number, the desired PCI device
ian@0 91 * is located in system global list of PCI devices. If the device
ian@0 92 * is found, a pointer to its data structure is returned. If no
ian@0 93 * device is found, %NULL is returned.
ian@0 94 */
ian@0 95 struct pci_dev *
ian@0 96 pci_find_slot(unsigned int bus, unsigned int devfn)
ian@0 97 {
ian@0 98 struct pci_dev *dev = NULL;
ian@0 99
ian@0 100 while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
ian@0 101 if (dev->bus->number == bus && dev->devfn == devfn)
ian@0 102 return dev;
ian@0 103 }
ian@0 104 return NULL;
ian@0 105 }
ian@0 106
ian@0 107 /**
ian@0 108 * pci_get_slot - locate PCI device for a given PCI slot
ian@0 109 * @bus: PCI bus on which desired PCI device resides
ian@0 110 * @devfn: encodes number of PCI slot in which the desired PCI
ian@0 111 * device resides and the logical device number within that slot
ian@0 112 * in case of multi-function devices.
ian@0 113 *
ian@0 114 * Given a PCI bus and slot/function number, the desired PCI device
ian@0 115 * is located in the list of PCI devices.
ian@0 116 * If the device is found, its reference count is increased and this
ian@0 117 * function returns a pointer to its data structure. The caller must
ian@0 118 * decrement the reference count by calling pci_dev_put().
ian@0 119 * If no device is found, %NULL is returned.
ian@0 120 */
ian@0 121 struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn)
ian@0 122 {
ian@0 123 struct list_head *tmp;
ian@0 124 struct pci_dev *dev;
ian@0 125
ian@0 126 WARN_ON(in_interrupt());
ian@0 127 down_read(&pci_bus_sem);
ian@0 128
ian@0 129 list_for_each(tmp, &bus->devices) {
ian@0 130 dev = pci_dev_b(tmp);
ian@0 131 if (dev->devfn == devfn)
ian@0 132 goto out;
ian@0 133 }
ian@0 134
ian@0 135 dev = NULL;
ian@0 136 out:
ian@0 137 pci_dev_get(dev);
ian@0 138 up_read(&pci_bus_sem);
ian@0 139 return dev;
ian@0 140 }
ian@0 141
ian@0 142 /**
ian@0 143 * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
ian@0 144 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
ian@0 145 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
ian@0 146 * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
ian@0 147 * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
ian@0 148 * @from: Previous PCI device found in search, or %NULL for new search.
ian@0 149 *
ian@0 150 * Iterates through the list of known PCI devices. If a PCI device is
ian@0 151 * found with a matching @vendor, @device, @ss_vendor and @ss_device, a
ian@0 152 * pointer to its device structure is returned. Otherwise, %NULL is returned.
ian@0 153 * A new search is initiated by passing %NULL as the @from argument.
ian@0 154 * Otherwise if @from is not %NULL, searches continue from next device
ian@0 155 * on the global list.
ian@0 156 *
ian@0 157 * NOTE: Do not use this function any more; use pci_get_subsys() instead, as
ian@0 158 * the PCI device returned by this function can disappear at any moment in
ian@0 159 * time.
ian@0 160 */
ian@0 161 static struct pci_dev * pci_find_subsys(unsigned int vendor,
ian@0 162 unsigned int device,
ian@0 163 unsigned int ss_vendor,
ian@0 164 unsigned int ss_device,
ian@0 165 const struct pci_dev *from)
ian@0 166 {
ian@0 167 struct list_head *n;
ian@0 168 struct pci_dev *dev;
ian@0 169
ian@0 170 WARN_ON(in_interrupt());
ian@0 171 down_read(&pci_bus_sem);
ian@0 172 n = from ? from->global_list.next : pci_devices.next;
ian@0 173
ian@0 174 while (n && (n != &pci_devices)) {
ian@0 175 dev = pci_dev_g(n);
ian@0 176 if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
ian@0 177 (device == PCI_ANY_ID || dev->device == device) &&
ian@0 178 (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
ian@0 179 (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
ian@0 180 goto exit;
ian@0 181 n = n->next;
ian@0 182 }
ian@0 183 dev = NULL;
ian@0 184 exit:
ian@0 185 up_read(&pci_bus_sem);
ian@0 186 return dev;
ian@0 187 }
ian@0 188
ian@0 189 /**
ian@0 190 * pci_find_device - begin or continue searching for a PCI device by vendor/device id
ian@0 191 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
ian@0 192 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
ian@0 193 * @from: Previous PCI device found in search, or %NULL for new search.
ian@0 194 *
ian@0 195 * Iterates through the list of known PCI devices. If a PCI device is found
ian@0 196 * with a matching @vendor and @device, a pointer to its device structure is
ian@0 197 * returned. Otherwise, %NULL is returned.
ian@0 198 * A new search is initiated by passing %NULL as the @from argument.
ian@0 199 * Otherwise if @from is not %NULL, searches continue from next device
ian@0 200 * on the global list.
ian@0 201 *
ian@0 202 * NOTE: Do not use this function any more; use pci_get_device() instead, as
ian@0 203 * the PCI device returned by this function can disappear at any moment in
ian@0 204 * time.
ian@0 205 */
ian@0 206 struct pci_dev *
ian@0 207 pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from)
ian@0 208 {
ian@0 209 return pci_find_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
ian@0 210 }
ian@0 211
ian@0 212 /**
ian@0 213 * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
ian@0 214 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
ian@0 215 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
ian@0 216 * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
ian@0 217 * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
ian@0 218 * @from: Previous PCI device found in search, or %NULL for new search.
ian@0 219 *
ian@0 220 * Iterates through the list of known PCI devices. If a PCI device is found
ian@0 221 * with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its
ian@0 222 * device structure is returned, and the reference count to the device is
ian@0 223 * incremented. Otherwise, %NULL is returned. A new search is initiated by
ian@0 224 * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
ian@0 225 * searches continue from next device on the global list.
ian@0 226 * The reference count for @from is always decremented if it is not %NULL.
ian@0 227 */
ian@0 228 struct pci_dev *
ian@0 229 pci_get_subsys(unsigned int vendor, unsigned int device,
ian@0 230 unsigned int ss_vendor, unsigned int ss_device,
ian@0 231 struct pci_dev *from)
ian@0 232 {
ian@0 233 struct list_head *n;
ian@0 234 struct pci_dev *dev;
ian@0 235
ian@0 236 WARN_ON(in_interrupt());
ian@0 237 down_read(&pci_bus_sem);
ian@0 238 n = from ? from->global_list.next : pci_devices.next;
ian@0 239
ian@0 240 while (n && (n != &pci_devices)) {
ian@0 241 dev = pci_dev_g(n);
ian@0 242 if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
ian@0 243 (device == PCI_ANY_ID || dev->device == device) &&
ian@0 244 (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
ian@0 245 (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
ian@0 246 goto exit;
ian@0 247 n = n->next;
ian@0 248 }
ian@0 249 dev = NULL;
ian@0 250 exit:
ian@0 251 dev = pci_dev_get(dev);
ian@0 252 up_read(&pci_bus_sem);
ian@0 253 pci_dev_put(from);
ian@0 254 return dev;
ian@0 255 }
ian@0 256
ian@0 257 /**
ian@0 258 * pci_get_device - begin or continue searching for a PCI device by vendor/device id
ian@0 259 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
ian@0 260 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
ian@0 261 * @from: Previous PCI device found in search, or %NULL for new search.
ian@0 262 *
ian@0 263 * Iterates through the list of known PCI devices. If a PCI device is
ian@0 264 * found with a matching @vendor and @device, the reference count to the
ian@0 265 * device is incremented and a pointer to its device structure is returned.
ian@0 266 * Otherwise, %NULL is returned. A new search is initiated by passing %NULL
ian@0 267 * as the @from argument. Otherwise if @from is not %NULL, searches continue
ian@0 268 * from next device on the global list. The reference count for @from is
ian@0 269 * always decremented if it is not %NULL.
ian@0 270 */
ian@0 271 struct pci_dev *
ian@0 272 pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
ian@0 273 {
ian@0 274 return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
ian@0 275 }
ian@0 276
ian@0 277
ian@0 278 /**
ian@0 279 * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id
ian@0 280 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
ian@0 281 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
ian@0 282 * @from: Previous PCI device found in search, or %NULL for new search.
ian@0 283 *
ian@0 284 * Iterates through the list of known PCI devices in the reverse order of
ian@0 285 * pci_find_device().
ian@0 286 * If a PCI device is found with a matching @vendor and @device, a pointer to
ian@0 287 * its device structure is returned. Otherwise, %NULL is returned.
ian@0 288 * A new search is initiated by passing %NULL as the @from argument.
ian@0 289 * Otherwise if @from is not %NULL, searches continue from previous device
ian@0 290 * on the global list.
ian@0 291 */
ian@0 292 struct pci_dev *
ian@0 293 pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct pci_dev *from)
ian@0 294 {
ian@0 295 struct list_head *n;
ian@0 296 struct pci_dev *dev;
ian@0 297
ian@0 298 WARN_ON(in_interrupt());
ian@0 299 down_read(&pci_bus_sem);
ian@0 300 n = from ? from->global_list.prev : pci_devices.prev;
ian@0 301
ian@0 302 while (n && (n != &pci_devices)) {
ian@0 303 dev = pci_dev_g(n);
ian@0 304 if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
ian@0 305 (device == PCI_ANY_ID || dev->device == device))
ian@0 306 goto exit;
ian@0 307 n = n->prev;
ian@0 308 }
ian@0 309 dev = NULL;
ian@0 310 exit:
ian@0 311 up_read(&pci_bus_sem);
ian@0 312 return dev;
ian@0 313 }
ian@0 314
ian@0 315 /**
ian@0 316 * pci_get_class - begin or continue searching for a PCI device by class
ian@0 317 * @class: search for a PCI device with this class designation
ian@0 318 * @from: Previous PCI device found in search, or %NULL for new search.
ian@0 319 *
ian@0 320 * Iterates through the list of known PCI devices. If a PCI device is
ian@0 321 * found with a matching @class, the reference count to the device is
ian@0 322 * incremented and a pointer to its device structure is returned.
ian@0 323 * Otherwise, %NULL is returned.
ian@0 324 * A new search is initiated by passing %NULL as the @from argument.
ian@0 325 * Otherwise if @from is not %NULL, searches continue from next device
ian@0 326 * on the global list. The reference count for @from is always decremented
ian@0 327 * if it is not %NULL.
ian@0 328 */
ian@0 329 struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
ian@0 330 {
ian@0 331 struct list_head *n;
ian@0 332 struct pci_dev *dev;
ian@0 333
ian@0 334 WARN_ON(in_interrupt());
ian@0 335 down_read(&pci_bus_sem);
ian@0 336 n = from ? from->global_list.next : pci_devices.next;
ian@0 337
ian@0 338 while (n && (n != &pci_devices)) {
ian@0 339 dev = pci_dev_g(n);
ian@0 340 if (dev->class == class)
ian@0 341 goto exit;
ian@0 342 n = n->next;
ian@0 343 }
ian@0 344 dev = NULL;
ian@0 345 exit:
ian@0 346 dev = pci_dev_get(dev);
ian@0 347 up_read(&pci_bus_sem);
ian@0 348 pci_dev_put(from);
ian@0 349 return dev;
ian@0 350 }
ian@0 351
ian@0 352 /**
ian@0 353 * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not.
ian@0 354 * @ids: A pointer to a null terminated list of struct pci_device_id structures
ian@0 355 * that describe the type of PCI device the caller is trying to find.
ian@0 356 *
ian@0 357 * Obvious fact: You do not have a reference to any device that might be found
ian@0 358 * by this function, so if that device is removed from the system right after
ian@0 359 * this function is finished, the value will be stale. Use this function to
ian@0 360 * find devices that are usually built into a system, or for a general hint as
ian@0 361 * to if another device happens to be present at this specific moment in time.
ian@0 362 */
ian@0 363 int pci_dev_present(const struct pci_device_id *ids)
ian@0 364 {
ian@0 365 struct pci_dev *dev;
ian@0 366 int found = 0;
ian@0 367
ian@0 368 WARN_ON(in_interrupt());
ian@0 369 down_read(&pci_bus_sem);
ian@0 370 while (ids->vendor || ids->subvendor || ids->class_mask) {
ian@0 371 list_for_each_entry(dev, &pci_devices, global_list) {
ian@0 372 if (pci_match_one_device(ids, dev)) {
ian@0 373 found = 1;
ian@0 374 goto exit;
ian@0 375 }
ian@0 376 }
ian@0 377 ids++;
ian@0 378 }
ian@0 379 exit:
ian@0 380 up_read(&pci_bus_sem);
ian@0 381 return found;
ian@0 382 }
keir@735 383
keir@735 384 /**
keir@735 385 * pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot
keir@735 386 * @bus: number of PCI bus on which desired PCI device resides
keir@735 387 * @devfn: encodes number of PCI slot in which the desired PCI
keir@735 388 * device resides and the logical device number within that slot
keir@735 389 * in case of multi-function devices.
keir@735 390 *
keir@735 391 * Note: the bus/slot search is limited to PCI domain (segment) 0.
keir@735 392 *
keir@735 393 * Given a PCI bus and slot/function number, the desired PCI device
keir@735 394 * is located in system global list of PCI devices. If the device
keir@735 395 * is found, a pointer to its data structure is returned. If no
keir@735 396 * device is found, %NULL is returned. The returned device has its
keir@735 397 * reference count bumped by one.
keir@735 398 */
keir@735 399
keir@735 400 struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
keir@735 401 {
keir@735 402 struct pci_dev *dev = NULL;
keir@735 403
keir@735 404 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
keir@735 405 if (pci_domain_nr(dev->bus) == 0 &&
keir@735 406 (dev->bus->number == bus && dev->devfn == devfn))
keir@735 407 return dev;
keir@735 408 }
keir@735 409 return NULL;
keir@735 410 }
keir@735 411
keir@735 412
ian@0 413 EXPORT_SYMBOL(pci_dev_present);
ian@0 414
ian@0 415 EXPORT_SYMBOL(pci_find_bus);
ian@0 416 EXPORT_SYMBOL(pci_find_next_bus);
ian@0 417 EXPORT_SYMBOL(pci_find_device);
ian@0 418 EXPORT_SYMBOL(pci_find_device_reverse);
ian@0 419 EXPORT_SYMBOL(pci_find_slot);
ian@0 420 EXPORT_SYMBOL(pci_get_device);
ian@0 421 EXPORT_SYMBOL(pci_get_subsys);
ian@0 422 EXPORT_SYMBOL(pci_get_slot);
keir@735 423 EXPORT_SYMBOL(pci_get_bus_and_slot);
ian@0 424 EXPORT_SYMBOL(pci_get_class);