ia64/linux-2.6.18-xen.hg

annotate arch/mips/pci/ops-pnx8550.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 *
ian@0 3 * BRIEF MODULE DESCRIPTION
ian@0 4 *
ian@0 5 * 2.6 port, Embedded Alley Solutions, Inc
ian@0 6 *
ian@0 7 * Based on:
ian@0 8 * Author: source@mvista.com
ian@0 9 *
ian@0 10 * This program is free software; you can distribute it and/or modify it
ian@0 11 * under the terms of the GNU General Public License (Version 2) as
ian@0 12 * published by the Free Software Foundation.
ian@0 13 *
ian@0 14 * This program is distributed in the hope it will be useful, but WITHOUT
ian@0 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ian@0 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ian@0 17 * for more details.
ian@0 18 *
ian@0 19 * You should have received a copy of the GNU General Public License along
ian@0 20 * with this program; if not, write to the Free Software Foundation, Inc.,
ian@0 21 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
ian@0 22 */
ian@0 23 #include <linux/types.h>
ian@0 24 #include <linux/pci.h>
ian@0 25 #include <linux/kernel.h>
ian@0 26 #include <linux/init.h>
ian@0 27 #include <linux/vmalloc.h>
ian@0 28 #include <linux/delay.h>
ian@0 29
ian@0 30 #include <asm/mach-pnx8550/pci.h>
ian@0 31 #include <asm/mach-pnx8550/glb.h>
ian@0 32 #include <asm/debug.h>
ian@0 33
ian@0 34
ian@0 35 static inline void clear_status(void)
ian@0 36 {
ian@0 37 unsigned long pci_stat;
ian@0 38
ian@0 39 pci_stat = inl(PCI_BASE | PCI_GPPM_STATUS);
ian@0 40 outl(pci_stat, PCI_BASE | PCI_GPPM_ICLR);
ian@0 41 }
ian@0 42
ian@0 43 static inline unsigned int
ian@0 44 calc_cfg_addr(struct pci_bus *bus, unsigned int devfn, int where)
ian@0 45 {
ian@0 46 unsigned int addr;
ian@0 47
ian@0 48 addr = ((bus->number > 0) ? (((bus->number & 0xff) << PCI_CFG_BUS_SHIFT) | 1) : 0);
ian@0 49 addr |= ((devfn & 0xff) << PCI_CFG_FUNC_SHIFT) | (where & 0xfc);
ian@0 50
ian@0 51 return addr;
ian@0 52 }
ian@0 53
ian@0 54 static int
ian@0 55 config_access(unsigned int pci_cmd, struct pci_bus *bus, unsigned int devfn, int where, unsigned int pci_mode, unsigned int *val)
ian@0 56 {
ian@0 57 unsigned int flags;
ian@0 58 unsigned long loops = 0;
ian@0 59 unsigned long ioaddr = calc_cfg_addr(bus, devfn, where);
ian@0 60
ian@0 61 local_irq_save(flags);
ian@0 62 /*Clear pending interrupt status */
ian@0 63 if (inl(PCI_BASE | PCI_GPPM_STATUS)) {
ian@0 64 clear_status();
ian@0 65 while (!(inl(PCI_BASE | PCI_GPPM_STATUS) == 0)) ;
ian@0 66 }
ian@0 67
ian@0 68 outl(ioaddr, PCI_BASE | PCI_GPPM_ADDR);
ian@0 69
ian@0 70 if ((pci_cmd == PCI_CMD_IOW) || (pci_cmd == PCI_CMD_CONFIG_WRITE))
ian@0 71 outl(*val, PCI_BASE | PCI_GPPM_WDAT);
ian@0 72
ian@0 73 outl(INIT_PCI_CYCLE | pci_cmd | (pci_mode & PCI_BYTE_ENABLE_MASK),
ian@0 74 PCI_BASE | PCI_GPPM_CTRL);
ian@0 75
ian@0 76 loops =
ian@0 77 ((loops_per_jiffy *
ian@0 78 PCI_IO_JIFFIES_TIMEOUT) >> (PCI_IO_JIFFIES_SHIFT));
ian@0 79 while (1) {
ian@0 80 if (inl(PCI_BASE | PCI_GPPM_STATUS) & GPPM_DONE) {
ian@0 81 if ((pci_cmd == PCI_CMD_IOR) ||
ian@0 82 (pci_cmd == PCI_CMD_CONFIG_READ))
ian@0 83 *val = inl(PCI_BASE | PCI_GPPM_RDAT);
ian@0 84 clear_status();
ian@0 85 local_irq_restore(flags);
ian@0 86 return PCIBIOS_SUCCESSFUL;
ian@0 87 } else if (inl(PCI_BASE | PCI_GPPM_STATUS) & GPPM_R_MABORT) {
ian@0 88 break;
ian@0 89 }
ian@0 90
ian@0 91 loops--;
ian@0 92 if (loops == 0) {
ian@0 93 printk("%s : Arbiter Locked.\n", __FUNCTION__);
ian@0 94 }
ian@0 95 }
ian@0 96
ian@0 97 clear_status();
ian@0 98 if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_IOW)) {
ian@0 99 printk("%s timeout (GPPM_CTRL=%X) ioaddr %lX pci_cmd %X\n",
ian@0 100 __FUNCTION__, inl(PCI_BASE | PCI_GPPM_CTRL), ioaddr,
ian@0 101 pci_cmd);
ian@0 102 }
ian@0 103
ian@0 104 if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_CONFIG_READ))
ian@0 105 *val = 0xffffffff;
ian@0 106 local_irq_restore(flags);
ian@0 107 return PCIBIOS_DEVICE_NOT_FOUND;
ian@0 108 }
ian@0 109
ian@0 110 /*
ian@0 111 * We can't address 8 and 16 bit words directly. Instead we have to
ian@0 112 * read/write a 32bit word and mask/modify the data we actually want.
ian@0 113 */
ian@0 114 static int
ian@0 115 read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 * val)
ian@0 116 {
ian@0 117 unsigned int data = 0;
ian@0 118 int err;
ian@0 119
ian@0 120 if (bus == 0)
ian@0 121 return -1;
ian@0 122
ian@0 123 err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(1 << (where & 3)), &data);
ian@0 124 switch (where & 0x03) {
ian@0 125 case 0:
ian@0 126 *val = (unsigned char)(data & 0x000000ff);
ian@0 127 break;
ian@0 128 case 1:
ian@0 129 *val = (unsigned char)((data & 0x0000ff00) >> 8);
ian@0 130 break;
ian@0 131 case 2:
ian@0 132 *val = (unsigned char)((data & 0x00ff0000) >> 16);
ian@0 133 break;
ian@0 134 case 3:
ian@0 135 *val = (unsigned char)((data & 0xff000000) >> 24);
ian@0 136 break;
ian@0 137 }
ian@0 138
ian@0 139 return err;
ian@0 140 }
ian@0 141
ian@0 142 static int
ian@0 143 read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 * val)
ian@0 144 {
ian@0 145 unsigned int data = 0;
ian@0 146 int err;
ian@0 147
ian@0 148 if (bus == 0)
ian@0 149 return -1;
ian@0 150
ian@0 151 if (where & 0x01)
ian@0 152 return PCIBIOS_BAD_REGISTER_NUMBER;
ian@0 153
ian@0 154 err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(3 << (where & 3)), &data);
ian@0 155 switch (where & 0x02) {
ian@0 156 case 0:
ian@0 157 *val = (unsigned short)(data & 0x0000ffff);
ian@0 158 break;
ian@0 159 case 2:
ian@0 160 *val = (unsigned short)((data & 0xffff0000) >> 16);
ian@0 161 break;
ian@0 162 }
ian@0 163
ian@0 164 return err;
ian@0 165 }
ian@0 166
ian@0 167 static int
ian@0 168 read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 * val)
ian@0 169 {
ian@0 170 int err;
ian@0 171 if (bus == 0)
ian@0 172 return -1;
ian@0 173
ian@0 174 if (where & 0x03)
ian@0 175 return PCIBIOS_BAD_REGISTER_NUMBER;
ian@0 176
ian@0 177 err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, 0, val);
ian@0 178
ian@0 179 return err;
ian@0 180 }
ian@0 181
ian@0 182 static int
ian@0 183 write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val)
ian@0 184 {
ian@0 185 unsigned int data = (unsigned int)val;
ian@0 186 int err;
ian@0 187
ian@0 188 if (bus == 0)
ian@0 189 return -1;
ian@0 190
ian@0 191 switch (where & 0x03) {
ian@0 192 case 1:
ian@0 193 data = (data << 8);
ian@0 194 break;
ian@0 195 case 2:
ian@0 196 data = (data << 16);
ian@0 197 break;
ian@0 198 case 3:
ian@0 199 data = (data << 24);
ian@0 200 break;
ian@0 201 default:
ian@0 202 break;
ian@0 203 }
ian@0 204
ian@0 205 err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(1 << (where & 3)), &data);
ian@0 206
ian@0 207 return err;
ian@0 208 }
ian@0 209
ian@0 210 static int
ian@0 211 write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val)
ian@0 212 {
ian@0 213 unsigned int data = (unsigned int)val;
ian@0 214 int err;
ian@0 215
ian@0 216 if (bus == 0)
ian@0 217 return -1;
ian@0 218
ian@0 219 if (where & 0x01)
ian@0 220 return PCIBIOS_BAD_REGISTER_NUMBER;
ian@0 221
ian@0 222 switch (where & 0x02) {
ian@0 223 case 2:
ian@0 224 data = (data << 16);
ian@0 225 break;
ian@0 226 default:
ian@0 227 break;
ian@0 228 }
ian@0 229 err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, ~(3 << (where & 3)), &data);
ian@0 230
ian@0 231 return err;
ian@0 232 }
ian@0 233
ian@0 234 static int
ian@0 235 write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val)
ian@0 236 {
ian@0 237 int err;
ian@0 238 if (bus == 0)
ian@0 239 return -1;
ian@0 240
ian@0 241 if (where & 0x03)
ian@0 242 return PCIBIOS_BAD_REGISTER_NUMBER;
ian@0 243
ian@0 244 err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, 0, &val);
ian@0 245
ian@0 246 return err;
ian@0 247 }
ian@0 248
ian@0 249 static int config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
ian@0 250 {
ian@0 251 switch (size) {
ian@0 252 case 1: {
ian@0 253 u8 _val;
ian@0 254 int rc = read_config_byte(bus, devfn, where, &_val);
ian@0 255 *val = _val;
ian@0 256 return rc;
ian@0 257 }
ian@0 258 case 2: {
ian@0 259 u16 _val;
ian@0 260 int rc = read_config_word(bus, devfn, where, &_val);
ian@0 261 *val = _val;
ian@0 262 return rc;
ian@0 263 }
ian@0 264 default:
ian@0 265 return read_config_dword(bus, devfn, where, val);
ian@0 266 }
ian@0 267 }
ian@0 268
ian@0 269 static int config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
ian@0 270 {
ian@0 271 switch (size) {
ian@0 272 case 1:
ian@0 273 return write_config_byte(bus, devfn, where, (u8) val);
ian@0 274 case 2:
ian@0 275 return write_config_word(bus, devfn, where, (u16) val);
ian@0 276 default:
ian@0 277 return write_config_dword(bus, devfn, where, val);
ian@0 278 }
ian@0 279 }
ian@0 280
ian@0 281 struct pci_ops pnx8550_pci_ops = {
ian@0 282 config_read,
ian@0 283 config_write
ian@0 284 };