ia64/linux-2.6.18-xen.hg

view drivers/net/jazzsonic.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 * jazzsonic.c
3 *
4 * (C) 2005 Finn Thain
5 *
6 * Converted to DMA API, and (from the mac68k project) introduced
7 * dhd's support for 16-bit cards.
8 *
9 * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
10 *
11 * This driver is based on work from Andreas Busse, but most of
12 * the code is rewritten.
13 *
14 * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
15 *
16 * A driver for the onboard Sonic ethernet controller on Mips Jazz
17 * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and
18 * perhaps others, too)
19 */
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/types.h>
24 #include <linux/fcntl.h>
25 #include <linux/interrupt.h>
26 #include <linux/init.h>
27 #include <linux/ioport.h>
28 #include <linux/in.h>
29 #include <linux/slab.h>
30 #include <linux/string.h>
31 #include <linux/delay.h>
32 #include <linux/errno.h>
33 #include <linux/netdevice.h>
34 #include <linux/etherdevice.h>
35 #include <linux/skbuff.h>
36 #include <linux/platform_device.h>
37 #include <linux/dma-mapping.h>
39 #include <asm/bootinfo.h>
40 #include <asm/system.h>
41 #include <asm/pgtable.h>
42 #include <asm/io.h>
43 #include <asm/dma.h>
44 #include <asm/jazz.h>
45 #include <asm/jazzdma.h>
47 static char jazz_sonic_string[] = "jazzsonic";
48 static struct platform_device *jazz_sonic_device;
50 #define SONIC_MEM_SIZE 0x100
52 #include "sonic.h"
54 /*
55 * Macros to access SONIC registers
56 */
57 #define SONIC_READ(reg) (*((volatile unsigned int *)dev->base_addr+reg))
59 #define SONIC_WRITE(reg,val) \
60 do { \
61 *((volatile unsigned int *)dev->base_addr+(reg)) = (val); \
62 } while (0)
65 /* use 0 for production, 1 for verification, >1 for debug */
66 #ifdef SONIC_DEBUG
67 static unsigned int sonic_debug = SONIC_DEBUG;
68 #else
69 static unsigned int sonic_debug = 1;
70 #endif
72 /*
73 * Base address and interrupt of the SONIC controller on JAZZ boards
74 */
75 static struct {
76 unsigned int port;
77 unsigned int irq;
78 } sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}};
80 /*
81 * We cannot use station (ethernet) address prefixes to detect the
82 * sonic controller since these are board manufacturer depended.
83 * So we check for known Silicon Revision IDs instead.
84 */
85 static unsigned short known_revisions[] =
86 {
87 0x04, /* Mips Magnum 4000 */
88 0xffff /* end of list */
89 };
91 static int __init sonic_probe1(struct net_device *dev)
92 {
93 static unsigned version_printed;
94 unsigned int silicon_revision;
95 unsigned int val;
96 struct sonic_local *lp = netdev_priv(dev);
97 int err = -ENODEV;
98 int i;
100 if (!request_mem_region(dev->base_addr, SONIC_MEM_SIZE, jazz_sonic_string))
101 return -EBUSY;
103 /*
104 * get the Silicon Revision ID. If this is one of the known
105 * one assume that we found a SONIC ethernet controller at
106 * the expected location.
107 */
108 silicon_revision = SONIC_READ(SONIC_SR);
109 if (sonic_debug > 1)
110 printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision);
112 i = 0;
113 while (known_revisions[i] != 0xffff
114 && known_revisions[i] != silicon_revision)
115 i++;
117 if (known_revisions[i] == 0xffff) {
118 printk("SONIC ethernet controller not found (0x%4x)\n",
119 silicon_revision);
120 goto out;
121 }
123 if (sonic_debug && version_printed++ == 0)
124 printk(version);
126 printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", lp->device->bus_id, dev->base_addr);
128 /*
129 * Put the sonic into software reset, then
130 * retrieve and print the ethernet address.
131 */
132 SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
133 SONIC_WRITE(SONIC_CEP,0);
134 for (i=0; i<3; i++) {
135 val = SONIC_READ(SONIC_CAP0-i);
136 dev->dev_addr[i*2] = val;
137 dev->dev_addr[i*2+1] = val >> 8;
138 }
140 err = -ENOMEM;
142 /* Initialize the device structure. */
144 lp->dma_bitmode = SONIC_BITMODE32;
146 /* Allocate the entire chunk of memory for the descriptors.
147 Note that this cannot cross a 64K boundary. */
148 if ((lp->descriptors = dma_alloc_coherent(lp->device,
149 SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
150 &lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
151 printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id);
152 goto out;
153 }
155 /* Now set up the pointers to point to the appropriate places */
156 lp->cda = lp->descriptors;
157 lp->tda = lp->cda + (SIZEOF_SONIC_CDA
158 * SONIC_BUS_SCALE(lp->dma_bitmode));
159 lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
160 * SONIC_BUS_SCALE(lp->dma_bitmode));
161 lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
162 * SONIC_BUS_SCALE(lp->dma_bitmode));
164 lp->cda_laddr = lp->descriptors_laddr;
165 lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
166 * SONIC_BUS_SCALE(lp->dma_bitmode));
167 lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
168 * SONIC_BUS_SCALE(lp->dma_bitmode));
169 lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
170 * SONIC_BUS_SCALE(lp->dma_bitmode));
172 dev->open = sonic_open;
173 dev->stop = sonic_close;
174 dev->hard_start_xmit = sonic_send_packet;
175 dev->get_stats = sonic_get_stats;
176 dev->set_multicast_list = &sonic_multicast_list;
177 dev->tx_timeout = sonic_tx_timeout;
178 dev->watchdog_timeo = TX_TIMEOUT;
180 /*
181 * clear tally counter
182 */
183 SONIC_WRITE(SONIC_CRCT,0xffff);
184 SONIC_WRITE(SONIC_FAET,0xffff);
185 SONIC_WRITE(SONIC_MPT,0xffff);
187 return 0;
188 out:
189 release_region(dev->base_addr, SONIC_MEM_SIZE);
190 return err;
191 }
193 /*
194 * Probe for a SONIC ethernet controller on a Mips Jazz board.
195 * Actually probing is superfluous but we're paranoid.
196 */
197 static int __init jazz_sonic_probe(struct platform_device *pdev)
198 {
199 struct net_device *dev;
200 struct sonic_local *lp;
201 int err = 0;
202 int i;
204 /*
205 * Don't probe if we're not running on a Jazz board.
206 */
207 if (mips_machgroup != MACH_GROUP_JAZZ)
208 return -ENODEV;
210 dev = alloc_etherdev(sizeof(struct sonic_local));
211 if (!dev)
212 return -ENOMEM;
214 lp = netdev_priv(dev);
215 lp->device = &pdev->dev;
216 SET_NETDEV_DEV(dev, &pdev->dev);
217 SET_MODULE_OWNER(dev);
219 netdev_boot_setup_check(dev);
221 if (dev->base_addr >= KSEG0) { /* Check a single specified location. */
222 err = sonic_probe1(dev);
223 } else if (dev->base_addr != 0) { /* Don't probe at all. */
224 err = -ENXIO;
225 } else {
226 for (i = 0; sonic_portlist[i].port; i++) {
227 dev->base_addr = sonic_portlist[i].port;
228 dev->irq = sonic_portlist[i].irq;
229 if (sonic_probe1(dev) == 0)
230 break;
231 }
232 if (!sonic_portlist[i].port)
233 err = -ENODEV;
234 }
235 if (err)
236 goto out;
237 err = register_netdev(dev);
238 if (err)
239 goto out1;
241 printk("%s: MAC ", dev->name);
242 for (i = 0; i < 6; i++) {
243 printk("%2.2x", dev->dev_addr[i]);
244 if (i < 5)
245 printk(":");
246 }
247 printk(" IRQ %d\n", dev->irq);
249 return 0;
251 out1:
252 release_region(dev->base_addr, SONIC_MEM_SIZE);
253 out:
254 free_netdev(dev);
256 return err;
257 }
259 MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
260 module_param(sonic_debug, int, 0);
261 MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
263 #define SONIC_IRQ_FLAG IRQF_DISABLED
265 #include "sonic.c"
267 static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
268 {
269 struct net_device *dev = platform_get_drvdata(pdev);
270 struct sonic_local* lp = netdev_priv(dev);
272 unregister_netdev (dev);
273 dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
274 lp->descriptors, lp->descriptors_laddr);
275 release_region (dev->base_addr, SONIC_MEM_SIZE);
276 free_netdev (dev);
278 return 0;
279 }
281 static struct platform_driver jazz_sonic_driver = {
282 .probe = jazz_sonic_probe,
283 .remove = __devexit_p(jazz_sonic_device_remove),
284 .driver = {
285 .name = jazz_sonic_string,
286 },
287 };
289 static int __init jazz_sonic_init_module(void)
290 {
291 int err;
293 if ((err = platform_driver_register(&jazz_sonic_driver))) {
294 printk(KERN_ERR "Driver registration failed\n");
295 return err;
296 }
298 jazz_sonic_device = platform_device_alloc(jazz_sonic_string, 0);
299 if (!jazz_sonic_device)
300 goto out_unregister;
302 if (platform_device_add(jazz_sonic_device)) {
303 platform_device_put(jazz_sonic_device);
304 jazz_sonic_device = NULL;
305 }
307 return 0;
309 out_unregister:
310 platform_driver_unregister(&jazz_sonic_driver);
312 return -ENOMEM;
313 }
315 static void __exit jazz_sonic_cleanup_module(void)
316 {
317 platform_driver_unregister(&jazz_sonic_driver);
319 if (jazz_sonic_device) {
320 platform_device_unregister(jazz_sonic_device);
321 jazz_sonic_device = NULL;
322 }
323 }
325 module_init(jazz_sonic_init_module);
326 module_exit(jazz_sonic_cleanup_module);