ia64/linux-2.6.18-xen.hg

view drivers/net/mvme147.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 /* mvme147.c : the Linux/mvme147/lance ethernet driver
2 *
3 * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
4 * Based on the Sun Lance driver and the NetBSD HP Lance driver
5 * Uses the generic 7990.c LANCE code.
6 */
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/types.h>
11 #include <linux/interrupt.h>
12 #include <linux/ioport.h>
13 #include <linux/slab.h>
14 #include <linux/string.h>
15 #include <linux/delay.h>
16 #include <linux/init.h>
17 #include <linux/errno.h>
18 /* Used for the temporal inet entries and routing */
19 #include <linux/socket.h>
20 #include <linux/route.h>
21 #include <linux/netdevice.h>
22 #include <linux/etherdevice.h>
23 #include <linux/skbuff.h>
25 #include <asm/system.h>
26 #include <asm/io.h>
27 #include <asm/pgtable.h>
28 #include <asm/mvme147hw.h>
30 /* We have 16834 bytes of RAM for the init block and buffers. This places
31 * an upper limit on the number of buffers we can use. NetBSD uses 8 Rx
32 * buffers and 2 Tx buffers.
33 */
34 #define LANCE_LOG_TX_BUFFERS 1
35 #define LANCE_LOG_RX_BUFFERS 3
37 #include "7990.h" /* use generic LANCE code */
39 /* Our private data structure */
40 struct m147lance_private {
41 struct lance_private lance;
42 unsigned long ram;
43 };
45 /* function prototypes... This is easy because all the grot is in the
46 * generic LANCE support. All we have to support is probing for boards,
47 * plus board-specific init, open and close actions.
48 * Oh, and we need to tell the generic code how to read and write LANCE registers...
49 */
50 static int m147lance_open(struct net_device *dev);
51 static int m147lance_close(struct net_device *dev);
52 static void m147lance_writerap(struct lance_private *lp, unsigned short value);
53 static void m147lance_writerdp(struct lance_private *lp, unsigned short value);
54 static unsigned short m147lance_readrdp(struct lance_private *lp);
56 typedef void (*writerap_t)(void *, unsigned short);
57 typedef void (*writerdp_t)(void *, unsigned short);
58 typedef unsigned short (*readrdp_t)(void *);
60 /* Initialise the one and only on-board 7990 */
61 struct net_device * __init mvme147lance_probe(int unit)
62 {
63 struct net_device *dev;
64 static int called;
65 static const char name[] = "MVME147 LANCE";
66 struct m147lance_private *lp;
67 u_long *addr;
68 u_long address;
69 int err;
71 if (!MACH_IS_MVME147 || called)
72 return ERR_PTR(-ENODEV);
73 called++;
75 dev = alloc_etherdev(sizeof(struct m147lance_private));
76 if (!dev)
77 return ERR_PTR(-ENOMEM);
79 if (unit >= 0)
80 sprintf(dev->name, "eth%d", unit);
82 SET_MODULE_OWNER(dev);
84 /* Fill the dev fields */
85 dev->base_addr = (unsigned long)MVME147_LANCE_BASE;
86 dev->open = &m147lance_open;
87 dev->stop = &m147lance_close;
88 dev->hard_start_xmit = &lance_start_xmit;
89 dev->get_stats = &lance_get_stats;
90 dev->set_multicast_list = &lance_set_multicast;
91 dev->tx_timeout = &lance_tx_timeout;
92 dev->dma = 0;
94 addr=(u_long *)ETHERNET_ADDRESS;
95 address = *addr;
96 dev->dev_addr[0]=0x08;
97 dev->dev_addr[1]=0x00;
98 dev->dev_addr[2]=0x3e;
99 address=address>>8;
100 dev->dev_addr[5]=address&0xff;
101 address=address>>8;
102 dev->dev_addr[4]=address&0xff;
103 address=address>>8;
104 dev->dev_addr[3]=address&0xff;
106 printk("%s: MVME147 at 0x%08lx, irq %d, Hardware Address %02x:%02x:%02x:%02x:%02x:%02x\n",
107 dev->name, dev->base_addr, MVME147_LANCE_IRQ,
108 dev->dev_addr[0],
109 dev->dev_addr[1], dev->dev_addr[2],
110 dev->dev_addr[3], dev->dev_addr[4],
111 dev->dev_addr[5]);
113 lp = (struct m147lance_private *)dev->priv;
114 lp->ram = __get_dma_pages(GFP_ATOMIC, 3); /* 16K */
115 if (!lp->ram)
116 {
117 printk("%s: No memory for LANCE buffers\n", dev->name);
118 free_netdev(dev);
119 return ERR_PTR(-ENOMEM);
120 }
122 lp->lance.name = (char*)name; /* discards const, shut up gcc */
123 lp->lance.base = dev->base_addr;
124 lp->lance.init_block = (struct lance_init_block *)(lp->ram); /* CPU addr */
125 lp->lance.lance_init_block = (struct lance_init_block *)(lp->ram); /* LANCE addr of same RAM */
126 lp->lance.busmaster_regval = LE_C3_BSWP; /* we're bigendian */
127 lp->lance.irq = MVME147_LANCE_IRQ;
128 lp->lance.writerap = (writerap_t)m147lance_writerap;
129 lp->lance.writerdp = (writerdp_t)m147lance_writerdp;
130 lp->lance.readrdp = (readrdp_t)m147lance_readrdp;
131 lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
132 lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
133 lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
134 lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
136 err = register_netdev(dev);
137 if (err) {
138 free_pages(lp->ram, 3);
139 free_netdev(dev);
140 return ERR_PTR(err);
141 }
143 return dev;
144 }
146 static void m147lance_writerap(struct lance_private *lp, unsigned short value)
147 {
148 out_be16(lp->base + LANCE_RAP, value);
149 }
151 static void m147lance_writerdp(struct lance_private *lp, unsigned short value)
152 {
153 out_be16(lp->base + LANCE_RDP, value);
154 }
156 static unsigned short m147lance_readrdp(struct lance_private *lp)
157 {
158 return in_be16(lp->base + LANCE_RDP);
159 }
161 static int m147lance_open(struct net_device *dev)
162 {
163 int status;
165 status = lance_open(dev); /* call generic lance open code */
166 if (status)
167 return status;
168 /* enable interrupts at board level. */
169 m147_pcc->lan_cntrl=0; /* clear the interrupts (if any) */
170 m147_pcc->lan_cntrl=0x08 | 0x04; /* Enable irq 4 */
172 return 0;
173 }
175 static int m147lance_close(struct net_device *dev)
176 {
177 /* disable interrupts at boardlevel */
178 m147_pcc->lan_cntrl=0x0; /* disable interrupts */
179 lance_close(dev);
180 return 0;
181 }
183 #ifdef MODULE
184 MODULE_LICENSE("GPL");
186 static struct net_device *dev_mvme147_lance;
187 int init_module(void)
188 {
189 dev_mvme147_lance = mvme147lance_probe(-1);
190 if (IS_ERR(dev_mvme147_lance))
191 return PTR_ERR(dev_mvme147_lance);
192 return 0;
193 }
195 void cleanup_module(void)
196 {
197 struct m147lance_private *lp = dev_mvme147_lance->priv;
198 unregister_netdev(dev_mvme147_lance);
199 free_pages(lp->ram, 3);
200 free_netdev(dev_mvme147_lance);
201 }
203 #endif /* MODULE */