ia64/linux-2.6.18-xen.hg

view drivers/pci/msi-altix.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 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
7 */
9 #include <linux/types.h>
10 #include <linux/pci.h>
11 #include <linux/cpumask.h>
13 #include <asm/sn/addrs.h>
14 #include <asm/sn/intr.h>
15 #include <asm/sn/pcibus_provider_defs.h>
16 #include <asm/sn/pcidev.h>
17 #include <asm/sn/nodepda.h>
19 #include "msi.h"
21 struct sn_msi_info {
22 u64 pci_addr;
23 struct sn_irq_info *sn_irq_info;
24 };
26 static struct sn_msi_info *sn_msi_info;
28 static void
29 sn_msi_teardown(unsigned int vector)
30 {
31 nasid_t nasid;
32 int widget;
33 struct pci_dev *pdev;
34 struct pcidev_info *sn_pdev;
35 struct sn_irq_info *sn_irq_info;
36 struct pcibus_bussoft *bussoft;
37 struct sn_pcibus_provider *provider;
39 sn_irq_info = sn_msi_info[vector].sn_irq_info;
40 if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
41 return;
43 sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
44 pdev = sn_pdev->pdi_linux_pcidev;
45 provider = SN_PCIDEV_BUSPROVIDER(pdev);
47 (*provider->dma_unmap)(pdev,
48 sn_msi_info[vector].pci_addr,
49 PCI_DMA_FROMDEVICE);
50 sn_msi_info[vector].pci_addr = 0;
52 bussoft = SN_PCIDEV_BUSSOFT(pdev);
53 nasid = NASID_GET(bussoft->bs_base);
54 widget = (nasid & 1) ?
55 TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
56 SWIN_WIDGETNUM(bussoft->bs_base);
58 sn_intr_free(nasid, widget, sn_irq_info);
59 sn_msi_info[vector].sn_irq_info = NULL;
61 return;
62 }
64 int
65 sn_msi_setup(struct pci_dev *pdev, unsigned int vector,
66 u32 *addr_hi, u32 *addr_lo, u32 *data)
67 {
68 int widget;
69 int status;
70 nasid_t nasid;
71 u64 bus_addr;
72 struct sn_irq_info *sn_irq_info;
73 struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
74 struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
76 if (bussoft == NULL)
77 return -EINVAL;
79 if (provider == NULL || provider->dma_map_consistent == NULL)
80 return -EINVAL;
82 /*
83 * Set up the vector plumbing. Let the prom (via sn_intr_alloc)
84 * decide which cpu to direct this msi at by default.
85 */
87 nasid = NASID_GET(bussoft->bs_base);
88 widget = (nasid & 1) ?
89 TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
90 SWIN_WIDGETNUM(bussoft->bs_base);
92 sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
93 if (! sn_irq_info)
94 return -ENOMEM;
96 status = sn_intr_alloc(nasid, widget, sn_irq_info, vector, -1, -1);
97 if (status) {
98 kfree(sn_irq_info);
99 return -ENOMEM;
100 }
102 sn_irq_info->irq_int_bit = -1; /* mark this as an MSI irq */
103 sn_irq_fixup(pdev, sn_irq_info);
105 /* Prom probably should fill these in, but doesn't ... */
106 sn_irq_info->irq_bridge_type = bussoft->bs_asic_type;
107 sn_irq_info->irq_bridge = (void *)bussoft->bs_base;
109 /*
110 * Map the xio address into bus space
111 */
112 bus_addr = (*provider->dma_map_consistent)(pdev,
113 sn_irq_info->irq_xtalkaddr,
114 sizeof(sn_irq_info->irq_xtalkaddr),
115 SN_DMA_MSI|SN_DMA_ADDR_XIO);
116 if (! bus_addr) {
117 sn_intr_free(nasid, widget, sn_irq_info);
118 kfree(sn_irq_info);
119 return -ENOMEM;
120 }
122 sn_msi_info[vector].sn_irq_info = sn_irq_info;
123 sn_msi_info[vector].pci_addr = bus_addr;
125 *addr_hi = (u32)(bus_addr >> 32);
126 *addr_lo = (u32)(bus_addr & 0x00000000ffffffff);
128 /*
129 * In the SN platform, bit 16 is a "send vector" bit which
130 * must be present in order to move the vector through the system.
131 */
132 *data = 0x100 + (unsigned int)vector;
134 #ifdef CONFIG_SMP
135 set_irq_affinity_info((vector & 0xff), sn_irq_info->irq_cpuid, 0);
136 #endif
138 return 0;
139 }
141 static void
142 sn_msi_target(unsigned int vector, unsigned int cpu,
143 u32 *addr_hi, u32 *addr_lo)
144 {
145 int slice;
146 nasid_t nasid;
147 u64 bus_addr;
148 struct pci_dev *pdev;
149 struct pcidev_info *sn_pdev;
150 struct sn_irq_info *sn_irq_info;
151 struct sn_irq_info *new_irq_info;
152 struct sn_pcibus_provider *provider;
154 sn_irq_info = sn_msi_info[vector].sn_irq_info;
155 if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
156 return;
158 /*
159 * Release XIO resources for the old MSI PCI address
160 */
162 sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
163 pdev = sn_pdev->pdi_linux_pcidev;
164 provider = SN_PCIDEV_BUSPROVIDER(pdev);
166 bus_addr = (u64)(*addr_hi) << 32 | (u64)(*addr_lo);
167 (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE);
168 sn_msi_info[vector].pci_addr = 0;
170 nasid = cpuid_to_nasid(cpu);
171 slice = cpuid_to_slice(cpu);
173 new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
174 sn_msi_info[vector].sn_irq_info = new_irq_info;
175 if (new_irq_info == NULL)
176 return;
178 /*
179 * Map the xio address into bus space
180 */
182 bus_addr = (*provider->dma_map_consistent)(pdev,
183 new_irq_info->irq_xtalkaddr,
184 sizeof(new_irq_info->irq_xtalkaddr),
185 SN_DMA_MSI|SN_DMA_ADDR_XIO);
187 sn_msi_info[vector].pci_addr = bus_addr;
188 *addr_hi = (u32)(bus_addr >> 32);
189 *addr_lo = (u32)(bus_addr & 0x00000000ffffffff);
190 }
192 struct msi_ops sn_msi_ops = {
193 .setup = sn_msi_setup,
194 .teardown = sn_msi_teardown,
195 #ifdef CONFIG_SMP
196 .target = sn_msi_target,
197 #endif
198 };
200 int
201 sn_msi_init(void)
202 {
203 sn_msi_info =
204 kzalloc(sizeof(struct sn_msi_info) * NR_VECTORS, GFP_KERNEL);
205 if (! sn_msi_info)
206 return -ENOMEM;
208 msi_register(&sn_msi_ops);
209 return 0;
210 }