ia64/linux-2.6.18-xen.hg

view drivers/net/mipsnet.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 */
7 #define DEBUG
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/netdevice.h>
13 #include <linux/sched.h>
14 #include <linux/etherdevice.h>
15 #include <linux/netdevice.h>
16 #include <linux/platform_device.h>
17 #include <asm/io.h>
18 #include <asm/mips-boards/simint.h>
20 #include "mipsnet.h" /* actual device IO mapping */
22 #define MIPSNET_VERSION "2005-06-20"
24 #define mipsnet_reg_address(dev, field) (dev->base_addr + field_offset(field))
26 struct mipsnet_priv {
27 struct net_device_stats stats;
28 };
30 static struct platform_device *mips_plat_dev;
32 static char mipsnet_string[] = "mipsnet";
34 /*
35 * Copy data from the MIPSNET rx data port
36 */
37 static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
38 int len)
39 {
40 uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount));
41 if (available_len < len)
42 return -EFAULT;
44 for (; len > 0; len--, kdata++) {
45 *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer));
46 }
48 return inl(mipsnet_reg_address(dev, rxDataCount));
49 }
51 static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
52 struct sk_buff *skb)
53 {
54 int count_to_go = skb->len;
55 char *buf_ptr = skb->data;
56 struct mipsnet_priv *mp = netdev_priv(dev);
58 pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
59 dev->name, __FUNCTION__, skb->len);
61 outl(skb->len, mipsnet_reg_address(dev, txDataCount));
63 pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
64 dev->name, __FUNCTION__, skb->len);
66 for (; count_to_go; buf_ptr++, count_to_go--) {
67 outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
68 }
70 mp->stats.tx_packets++;
71 mp->stats.tx_bytes += skb->len;
73 return skb->len;
74 }
76 static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
77 {
78 pr_debug("%s:%s(): transmitting %d bytes\n",
79 dev->name, __FUNCTION__, skb->len);
81 /* Only one packet at a time. Once TXDONE interrupt is serviced, the
82 * queue will be restarted.
83 */
84 netif_stop_queue(dev);
85 mipsnet_put_todevice(dev, skb);
87 return 0;
88 }
90 static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
91 {
92 struct sk_buff *skb;
93 size_t len = count;
94 struct mipsnet_priv *mp = netdev_priv(dev);
96 if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
97 mp->stats.rx_dropped++;
98 return -ENOMEM;
99 }
101 skb_reserve(skb, 2);
102 if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len))
103 return -EFAULT;
105 skb->dev = dev;
106 skb->protocol = eth_type_trans(skb, dev);
107 skb->ip_summed = CHECKSUM_UNNECESSARY;
109 pr_debug("%s:%s(): pushing RXed data to kernel\n",
110 dev->name, __FUNCTION__);
111 netif_rx(skb);
113 mp->stats.rx_packets++;
114 mp->stats.rx_bytes += len;
116 return count;
117 }
119 static irqreturn_t
120 mipsnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
121 {
122 struct net_device *dev = dev_id;
124 irqreturn_t retval = IRQ_NONE;
125 uint64_t interruptFlags;
127 if (irq == dev->irq) {
128 pr_debug("%s:%s(): irq %d for device\n",
129 dev->name, __FUNCTION__, irq);
131 retval = IRQ_HANDLED;
133 interruptFlags =
134 inl(mipsnet_reg_address(dev, interruptControl));
135 pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
136 __FUNCTION__, interruptFlags);
138 if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
139 pr_debug("%s:%s(): got TXDone\n",
140 dev->name, __FUNCTION__);
141 outl(MIPSNET_INTCTL_TXDONE,
142 mipsnet_reg_address(dev, interruptControl));
143 // only one packet at a time, we are done.
144 netif_wake_queue(dev);
145 } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
146 pr_debug("%s:%s(): got RX data\n",
147 dev->name, __FUNCTION__);
148 mipsnet_get_fromdev(dev,
149 inl(mipsnet_reg_address(dev, rxDataCount)));
150 pr_debug("%s:%s(): clearing RX int\n",
151 dev->name, __FUNCTION__);
152 outl(MIPSNET_INTCTL_RXDONE,
153 mipsnet_reg_address(dev, interruptControl));
155 } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
156 pr_debug("%s:%s(): got test interrupt\n",
157 dev->name, __FUNCTION__);
158 // TESTBIT is cleared on read.
159 // And takes effect after a write with 0
160 outl(0, mipsnet_reg_address(dev, interruptControl));
161 } else {
162 pr_debug("%s:%s(): no valid fags 0x%016llx\n",
163 dev->name, __FUNCTION__, interruptFlags);
164 // Maybe shared IRQ, just ignore, no clearing.
165 retval = IRQ_NONE;
166 }
168 } else {
169 printk(KERN_INFO "%s: %s(): irq %d for unknown device\n",
170 dev->name, __FUNCTION__, irq);
171 retval = IRQ_NONE;
172 }
173 return retval;
174 } //mipsnet_interrupt()
176 static int mipsnet_open(struct net_device *dev)
177 {
178 int err;
179 pr_debug("%s: mipsnet_open\n", dev->name);
181 err = request_irq(dev->irq, &mipsnet_interrupt,
182 IRQF_SHARED, dev->name, (void *) dev);
184 if (err) {
185 pr_debug("%s: %s(): can't get irq %d\n",
186 dev->name, __FUNCTION__, dev->irq);
187 release_region(dev->base_addr, MIPSNET_IO_EXTENT);
188 return err;
189 }
191 pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
192 dev->name, __FUNCTION__, dev->base_addr, dev->irq);
195 netif_start_queue(dev);
197 // test interrupt handler
198 outl(MIPSNET_INTCTL_TESTBIT,
199 mipsnet_reg_address(dev, interruptControl));
202 return 0;
203 }
205 static int mipsnet_close(struct net_device *dev)
206 {
207 pr_debug("%s: %s()\n", dev->name, __FUNCTION__);
208 netif_stop_queue(dev);
209 return 0;
210 }
212 static struct net_device_stats *mipsnet_get_stats(struct net_device *dev)
213 {
214 struct mipsnet_priv *mp = netdev_priv(dev);
216 return &mp->stats;
217 }
219 static void mipsnet_set_mclist(struct net_device *dev)
220 {
221 // we don't do anything
222 return;
223 }
225 static int __init mipsnet_probe(struct device *dev)
226 {
227 struct net_device *netdev;
228 int err;
230 netdev = alloc_etherdev(sizeof(struct mipsnet_priv));
231 if (!netdev) {
232 err = -ENOMEM;
233 goto out;
234 }
236 dev_set_drvdata(dev, netdev);
238 netdev->open = mipsnet_open;
239 netdev->stop = mipsnet_close;
240 netdev->hard_start_xmit = mipsnet_xmit;
241 netdev->get_stats = mipsnet_get_stats;
242 netdev->set_multicast_list = mipsnet_set_mclist;
244 /*
245 * TODO: probe for these or load them from PARAM
246 */
247 netdev->base_addr = 0x4200;
248 netdev->irq = MIPSCPU_INT_BASE + MIPSCPU_INT_MB0 +
249 inl(mipsnet_reg_address(netdev, interruptInfo));
251 // Get the io region now, get irq on open()
252 if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
253 pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
254 "for dev is not availble.\n", netdev->name,
255 __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
256 err = -EBUSY;
257 goto out_free_netdev;
258 }
260 /*
261 * Lacking any better mechanism to allocate a MAC address we use a
262 * random one ...
263 */
264 random_ether_addr(netdev->dev_addr);
266 err = register_netdev(netdev);
267 if (err) {
268 printk(KERN_ERR "MIPSNet: failed to register netdev.\n");
269 goto out_free_region;
270 }
272 return 0;
274 out_free_region:
275 release_region(netdev->base_addr, MIPSNET_IO_EXTENT);
277 out_free_netdev:
278 free_netdev(netdev);
280 out:
281 return err;
282 }
284 static int __devexit mipsnet_device_remove(struct device *device)
285 {
286 struct net_device *dev = dev_get_drvdata(device);
288 unregister_netdev(dev);
289 release_region(dev->base_addr, MIPSNET_IO_EXTENT);
290 free_netdev(dev);
291 dev_set_drvdata(device, NULL);
293 return 0;
294 }
296 static struct device_driver mipsnet_driver = {
297 .name = mipsnet_string,
298 .bus = &platform_bus_type,
299 .probe = mipsnet_probe,
300 .remove = __devexit_p(mipsnet_device_remove),
301 };
303 static void mipsnet_platform_release(struct device *device)
304 {
305 struct platform_device *pldev;
307 /* free device */
308 pldev = to_platform_device(device);
309 kfree(pldev);
310 }
312 static int __init mipsnet_init_module(void)
313 {
314 struct platform_device *pldev;
315 int err;
317 printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. "
318 "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION);
320 if (driver_register(&mipsnet_driver)) {
321 printk(KERN_ERR "Driver registration failed\n");
322 err = -ENODEV;
323 goto out;
324 }
326 if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
327 err = -ENOMEM;
328 goto out_unregister_driver;
329 }
331 memset (pldev, 0, sizeof (*pldev));
332 pldev->name = mipsnet_string;
333 pldev->id = 0;
334 pldev->dev.release = mipsnet_platform_release;
336 if (platform_device_register(pldev)) {
337 err = -ENODEV;
338 goto out_free_pldev;
339 }
341 if (!pldev->dev.driver) {
342 /*
343 * The driver was not bound to this device, there was
344 * no hardware at this address. Unregister it, as the
345 * release fuction will take care of freeing the
346 * allocated structure
347 */
348 platform_device_unregister (pldev);
349 }
351 mips_plat_dev = pldev;
353 return 0;
355 out_free_pldev:
356 kfree(pldev);
358 out_unregister_driver:
359 driver_unregister(&mipsnet_driver);
360 out:
361 return err;
362 }
364 static void __exit mipsnet_exit_module(void)
365 {
366 pr_debug("MIPSNet Ethernet driver exiting\n");
368 driver_unregister(&mipsnet_driver);
369 }
371 module_init(mipsnet_init_module);
372 module_exit(mipsnet_exit_module);