ia64/linux-2.6.18-xen.hg

annotate arch/mips/pci/pci-bcm1480ht.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
rev   line source
ian@0 1 /*
ian@0 2 * Copyright (C) 2001,2002,2005 Broadcom Corporation
ian@0 3 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
ian@0 4 *
ian@0 5 * This program is free software; you can redistribute it and/or
ian@0 6 * modify it under the terms of the GNU General Public License
ian@0 7 * as published by the Free Software Foundation; either version 2
ian@0 8 * of the License, or (at your option) any later version.
ian@0 9 *
ian@0 10 * This program is distributed in the hope that it will be useful,
ian@0 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ian@0 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ian@0 13 * GNU General Public License for more details.
ian@0 14 *
ian@0 15 * You should have received a copy of the GNU General Public License
ian@0 16 * along with this program; if not, write to the Free Software
ian@0 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
ian@0 18 */
ian@0 19
ian@0 20 /*
ian@0 21 * BCM1480/1455-specific HT support (looking like PCI)
ian@0 22 *
ian@0 23 * This module provides the glue between Linux's PCI subsystem
ian@0 24 * and the hardware. We basically provide glue for accessing
ian@0 25 * configuration space, and set up the translation for I/O
ian@0 26 * space accesses.
ian@0 27 *
ian@0 28 * To access configuration space, we use ioremap. In the 32-bit
ian@0 29 * kernel, this consumes either 4 or 8 page table pages, and 16MB of
ian@0 30 * kernel mapped memory. Hopefully neither of these should be a huge
ian@0 31 * problem.
ian@0 32 *
ian@0 33 */
ian@0 34 #include <linux/types.h>
ian@0 35 #include <linux/pci.h>
ian@0 36 #include <linux/kernel.h>
ian@0 37 #include <linux/init.h>
ian@0 38 #include <linux/mm.h>
ian@0 39 #include <linux/console.h>
ian@0 40 #include <linux/tty.h>
ian@0 41
ian@0 42 #include <asm/sibyte/bcm1480_regs.h>
ian@0 43 #include <asm/sibyte/bcm1480_scd.h>
ian@0 44 #include <asm/sibyte/board.h>
ian@0 45 #include <asm/io.h>
ian@0 46
ian@0 47 /*
ian@0 48 * Macros for calculating offsets into config space given a device
ian@0 49 * structure or dev/fun/reg
ian@0 50 */
ian@0 51 #define CFGOFFSET(bus,devfn,where) (((bus)<<16)+((devfn)<<8)+(where))
ian@0 52 #define CFGADDR(bus,devfn,where) CFGOFFSET((bus)->number,(devfn),where)
ian@0 53
ian@0 54 static void *ht_cfg_space;
ian@0 55
ian@0 56 #define PCI_BUS_ENABLED 1
ian@0 57 #define PCI_DEVICE_MODE 2
ian@0 58
ian@0 59 static int bcm1480ht_bus_status = 0;
ian@0 60
ian@0 61 #define PCI_BRIDGE_DEVICE 0
ian@0 62 #define HT_BRIDGE_DEVICE 1
ian@0 63
ian@0 64 /*
ian@0 65 * HT's level-sensitive interrupts require EOI, which is generated
ian@0 66 * through a 4MB memory-mapped region
ian@0 67 */
ian@0 68 unsigned long ht_eoi_space;
ian@0 69
ian@0 70 /*
ian@0 71 * Read/write 32-bit values in config space.
ian@0 72 */
ian@0 73 static inline u32 READCFG32(u32 addr)
ian@0 74 {
ian@0 75 return *(u32 *)(ht_cfg_space + (addr&~3));
ian@0 76 }
ian@0 77
ian@0 78 static inline void WRITECFG32(u32 addr, u32 data)
ian@0 79 {
ian@0 80 *(u32 *)(ht_cfg_space + (addr & ~3)) = data;
ian@0 81 }
ian@0 82
ian@0 83 /*
ian@0 84 * Some checks before doing config cycles:
ian@0 85 * In PCI Device Mode, hide everything on bus 0 except the LDT host
ian@0 86 * bridge. Otherwise, access is controlled by bridge MasterEn bits.
ian@0 87 */
ian@0 88 static int bcm1480ht_can_access(struct pci_bus *bus, int devfn)
ian@0 89 {
ian@0 90 u32 devno;
ian@0 91
ian@0 92 if (!(bcm1480ht_bus_status & (PCI_BUS_ENABLED | PCI_DEVICE_MODE)))
ian@0 93 return 0;
ian@0 94
ian@0 95 if (bus->number == 0) {
ian@0 96 devno = PCI_SLOT(devfn);
ian@0 97 if (bcm1480ht_bus_status & PCI_DEVICE_MODE)
ian@0 98 return 0;
ian@0 99 }
ian@0 100 return 1;
ian@0 101 }
ian@0 102
ian@0 103 /*
ian@0 104 * Read/write access functions for various sizes of values
ian@0 105 * in config space. Return all 1's for disallowed accesses
ian@0 106 * for a kludgy but adequate simulation of master aborts.
ian@0 107 */
ian@0 108
ian@0 109 static int bcm1480ht_pcibios_read(struct pci_bus *bus, unsigned int devfn,
ian@0 110 int where, int size, u32 * val)
ian@0 111 {
ian@0 112 u32 data = 0;
ian@0 113
ian@0 114 if ((size == 2) && (where & 1))
ian@0 115 return PCIBIOS_BAD_REGISTER_NUMBER;
ian@0 116 else if ((size == 4) && (where & 3))
ian@0 117 return PCIBIOS_BAD_REGISTER_NUMBER;
ian@0 118
ian@0 119 if (bcm1480ht_can_access(bus, devfn))
ian@0 120 data = READCFG32(CFGADDR(bus, devfn, where));
ian@0 121 else
ian@0 122 data = 0xFFFFFFFF;
ian@0 123
ian@0 124 if (size == 1)
ian@0 125 *val = (data >> ((where & 3) << 3)) & 0xff;
ian@0 126 else if (size == 2)
ian@0 127 *val = (data >> ((where & 3) << 3)) & 0xffff;
ian@0 128 else
ian@0 129 *val = data;
ian@0 130
ian@0 131 return PCIBIOS_SUCCESSFUL;
ian@0 132 }
ian@0 133
ian@0 134 static int bcm1480ht_pcibios_write(struct pci_bus *bus, unsigned int devfn,
ian@0 135 int where, int size, u32 val)
ian@0 136 {
ian@0 137 u32 cfgaddr = CFGADDR(bus, devfn, where);
ian@0 138 u32 data = 0;
ian@0 139
ian@0 140 if ((size == 2) && (where & 1))
ian@0 141 return PCIBIOS_BAD_REGISTER_NUMBER;
ian@0 142 else if ((size == 4) && (where & 3))
ian@0 143 return PCIBIOS_BAD_REGISTER_NUMBER;
ian@0 144
ian@0 145 if (!bcm1480ht_can_access(bus, devfn))
ian@0 146 return PCIBIOS_BAD_REGISTER_NUMBER;
ian@0 147
ian@0 148 data = READCFG32(cfgaddr);
ian@0 149
ian@0 150 if (size == 1)
ian@0 151 data = (data & ~(0xff << ((where & 3) << 3))) |
ian@0 152 (val << ((where & 3) << 3));
ian@0 153 else if (size == 2)
ian@0 154 data = (data & ~(0xffff << ((where & 3) << 3))) |
ian@0 155 (val << ((where & 3) << 3));
ian@0 156 else
ian@0 157 data = val;
ian@0 158
ian@0 159 WRITECFG32(cfgaddr, data);
ian@0 160
ian@0 161 return PCIBIOS_SUCCESSFUL;
ian@0 162 }
ian@0 163
ian@0 164 static int bcm1480ht_pcibios_get_busno(void)
ian@0 165 {
ian@0 166 return 0;
ian@0 167 }
ian@0 168
ian@0 169 struct pci_ops bcm1480ht_pci_ops = {
ian@0 170 .read = bcm1480ht_pcibios_read,
ian@0 171 .write = bcm1480ht_pcibios_write,
ian@0 172 };
ian@0 173
ian@0 174 static struct resource bcm1480ht_mem_resource = {
ian@0 175 .name = "BCM1480 HT MEM",
ian@0 176 .start = 0x40000000UL,
ian@0 177 .end = 0x5fffffffUL,
ian@0 178 .flags = IORESOURCE_MEM,
ian@0 179 };
ian@0 180
ian@0 181 static struct resource bcm1480ht_io_resource = {
ian@0 182 .name = "BCM1480 HT I/O",
ian@0 183 .start = 0x00000000UL,
ian@0 184 .end = 0x01ffffffUL,
ian@0 185 .flags = IORESOURCE_IO,
ian@0 186 };
ian@0 187
ian@0 188 struct pci_controller bcm1480ht_controller = {
ian@0 189 .pci_ops = &bcm1480ht_pci_ops,
ian@0 190 .mem_resource = &bcm1480ht_mem_resource,
ian@0 191 .io_resource = &bcm1480ht_io_resource,
ian@0 192 .index = 1,
ian@0 193 .get_busno = bcm1480ht_pcibios_get_busno,
ian@0 194 };
ian@0 195
ian@0 196 static int __init bcm1480ht_pcibios_init(void)
ian@0 197 {
ian@0 198 uint32_t cmdreg;
ian@0 199
ian@0 200 ht_cfg_space = ioremap(A_BCM1480_PHYS_HT_CFG_MATCH_BITS, 16*1024*1024);
ian@0 201
ian@0 202 /*
ian@0 203 * See if the PCI bus has been configured by the firmware.
ian@0 204 */
ian@0 205 cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0),
ian@0 206 PCI_COMMAND));
ian@0 207 if (!(cmdreg & PCI_COMMAND_MASTER)) {
ian@0 208 printk("HT: Skipping HT probe. Bus is not initialized.\n");
ian@0 209 iounmap(ht_cfg_space);
ian@0 210 return 1; /* XXX */
ian@0 211 }
ian@0 212 bcm1480ht_bus_status |= PCI_BUS_ENABLED;
ian@0 213
ian@0 214 ht_eoi_space = (unsigned long)
ian@0 215 ioremap(A_BCM1480_PHYS_HT_SPECIAL_MATCH_BYTES,
ian@0 216 4 * 1024 * 1024);
ian@0 217
ian@0 218 register_pci_controller(&bcm1480ht_controller);
ian@0 219
ian@0 220 return 0;
ian@0 221 }
ian@0 222
ian@0 223 arch_initcall(bcm1480ht_pcibios_init);