ia64/linux-2.6.18-xen.hg

view drivers/net/ixp2000/enp2611.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 * IXP2400 MSF network device driver for the Radisys ENP2611
3 * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
4 * Dedicated to Marija Kulikova.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/netdevice.h>
15 #include <linux/etherdevice.h>
16 #include <linux/init.h>
17 #include <linux/moduleparam.h>
18 #include <asm/hardware/uengine.h>
19 #include <asm/mach-types.h>
20 #include <asm/io.h>
21 #include "ixpdev.h"
22 #include "caleb.h"
23 #include "ixp2400-msf.h"
24 #include "pm3386.h"
26 /***********************************************************************
27 * The Radisys ENP2611 is a PCI form factor board with three SFP GBIC
28 * slots, connected via two PMC/Sierra 3386s and an SPI-3 bridge FPGA
29 * to the IXP2400.
30 *
31 * +-------------+
32 * SFP GBIC #0 ---+ | +---------+
33 * | PM3386 #0 +-------+ |
34 * SFP GBIC #1 ---+ | | "Caleb" | +---------+
35 * +-------------+ | | | |
36 * | SPI-3 +---------+ IXP2400 |
37 * +-------------+ | bridge | | |
38 * SFP GBIC #2 ---+ | | FPGA | +---------+
39 * | PM3386 #1 +-------+ |
40 * | | +---------+
41 * +-------------+
42 * ^ ^ ^
43 * | 1.25Gbaud | 104MHz | 104MHz
44 * | SERDES ea. | SPI-3 ea. | SPI-3
45 *
46 ***********************************************************************/
47 static struct ixp2400_msf_parameters enp2611_msf_parameters =
48 {
49 .rx_mode = IXP2400_RX_MODE_UTOPIA_POS |
50 IXP2400_RX_MODE_1x32 |
51 IXP2400_RX_MODE_MPHY |
52 IXP2400_RX_MODE_MPHY_32 |
53 IXP2400_RX_MODE_MPHY_POLLED_STATUS |
54 IXP2400_RX_MODE_MPHY_LEVEL3 |
55 IXP2400_RX_MODE_RBUF_SIZE_64,
57 .rxclk01_multiplier = IXP2400_PLL_MULTIPLIER_16,
59 .rx_poll_ports = 3,
61 .rx_channel_mode = {
62 IXP2400_PORT_RX_MODE_MASTER |
63 IXP2400_PORT_RX_MODE_POS_PHY |
64 IXP2400_PORT_RX_MODE_POS_PHY_L3 |
65 IXP2400_PORT_RX_MODE_ODD_PARITY |
66 IXP2400_PORT_RX_MODE_2_CYCLE_DECODE,
68 IXP2400_PORT_RX_MODE_MASTER |
69 IXP2400_PORT_RX_MODE_POS_PHY |
70 IXP2400_PORT_RX_MODE_POS_PHY_L3 |
71 IXP2400_PORT_RX_MODE_ODD_PARITY |
72 IXP2400_PORT_RX_MODE_2_CYCLE_DECODE,
74 IXP2400_PORT_RX_MODE_MASTER |
75 IXP2400_PORT_RX_MODE_POS_PHY |
76 IXP2400_PORT_RX_MODE_POS_PHY_L3 |
77 IXP2400_PORT_RX_MODE_ODD_PARITY |
78 IXP2400_PORT_RX_MODE_2_CYCLE_DECODE,
80 IXP2400_PORT_RX_MODE_MASTER |
81 IXP2400_PORT_RX_MODE_POS_PHY |
82 IXP2400_PORT_RX_MODE_POS_PHY_L3 |
83 IXP2400_PORT_RX_MODE_ODD_PARITY |
84 IXP2400_PORT_RX_MODE_2_CYCLE_DECODE
85 },
87 .tx_mode = IXP2400_TX_MODE_UTOPIA_POS |
88 IXP2400_TX_MODE_1x32 |
89 IXP2400_TX_MODE_MPHY |
90 IXP2400_TX_MODE_MPHY_32 |
91 IXP2400_TX_MODE_MPHY_POLLED_STATUS |
92 IXP2400_TX_MODE_MPHY_LEVEL3 |
93 IXP2400_TX_MODE_TBUF_SIZE_64,
95 .txclk01_multiplier = IXP2400_PLL_MULTIPLIER_16,
97 .tx_poll_ports = 3,
99 .tx_channel_mode = {
100 IXP2400_PORT_TX_MODE_MASTER |
101 IXP2400_PORT_TX_MODE_POS_PHY |
102 IXP2400_PORT_TX_MODE_ODD_PARITY |
103 IXP2400_PORT_TX_MODE_2_CYCLE_DECODE,
105 IXP2400_PORT_TX_MODE_MASTER |
106 IXP2400_PORT_TX_MODE_POS_PHY |
107 IXP2400_PORT_TX_MODE_ODD_PARITY |
108 IXP2400_PORT_TX_MODE_2_CYCLE_DECODE,
110 IXP2400_PORT_TX_MODE_MASTER |
111 IXP2400_PORT_TX_MODE_POS_PHY |
112 IXP2400_PORT_TX_MODE_ODD_PARITY |
113 IXP2400_PORT_TX_MODE_2_CYCLE_DECODE,
115 IXP2400_PORT_TX_MODE_MASTER |
116 IXP2400_PORT_TX_MODE_POS_PHY |
117 IXP2400_PORT_TX_MODE_ODD_PARITY |
118 IXP2400_PORT_TX_MODE_2_CYCLE_DECODE
119 }
120 };
122 struct enp2611_ixpdev_priv
123 {
124 struct ixpdev_priv ixpdev_priv;
125 struct net_device_stats stats;
126 };
128 static struct net_device *nds[3];
129 static struct timer_list link_check_timer;
131 static struct net_device_stats *enp2611_get_stats(struct net_device *dev)
132 {
133 struct enp2611_ixpdev_priv *ip = netdev_priv(dev);
135 pm3386_get_stats(ip->ixpdev_priv.channel, &(ip->stats));
137 return &(ip->stats);
138 }
140 /* @@@ Poll the SFP moddef0 line too. */
141 /* @@@ Try to use the pm3386 DOOL interrupt as well. */
142 static void enp2611_check_link_status(unsigned long __dummy)
143 {
144 int i;
146 for (i = 0; i < 3; i++) {
147 struct net_device *dev;
148 int status;
150 dev = nds[i];
151 if (dev == NULL)
152 continue;
154 status = pm3386_is_link_up(i);
155 if (status && !netif_carrier_ok(dev)) {
156 /* @@@ Should report autonegotiation status. */
157 printk(KERN_INFO "%s: NIC Link is Up\n", dev->name);
159 pm3386_enable_tx(i);
160 caleb_enable_tx(i);
161 netif_carrier_on(dev);
162 } else if (!status && netif_carrier_ok(dev)) {
163 printk(KERN_INFO "%s: NIC Link is Down\n", dev->name);
165 netif_carrier_off(dev);
166 caleb_disable_tx(i);
167 pm3386_disable_tx(i);
168 }
169 }
171 link_check_timer.expires = jiffies + HZ / 10;
172 add_timer(&link_check_timer);
173 }
175 static void enp2611_set_port_admin_status(int port, int up)
176 {
177 if (up) {
178 caleb_enable_rx(port);
180 pm3386_set_carrier(port, 1);
181 pm3386_enable_rx(port);
182 } else {
183 caleb_disable_tx(port);
184 pm3386_disable_tx(port);
185 /* @@@ Flush out pending packets. */
186 pm3386_set_carrier(port, 0);
188 pm3386_disable_rx(port);
189 caleb_disable_rx(port);
190 }
191 }
193 static int __init enp2611_init_module(void)
194 {
195 int ports;
196 int i;
198 if (!machine_is_enp2611())
199 return -ENODEV;
201 caleb_reset();
202 pm3386_reset();
204 ports = pm3386_port_count();
205 for (i = 0; i < ports; i++) {
206 nds[i] = ixpdev_alloc(i, sizeof(struct enp2611_ixpdev_priv));
207 if (nds[i] == NULL) {
208 while (--i >= 0)
209 free_netdev(nds[i]);
210 return -ENOMEM;
211 }
213 SET_MODULE_OWNER(nds[i]);
214 nds[i]->get_stats = enp2611_get_stats;
215 pm3386_init_port(i);
216 pm3386_get_mac(i, nds[i]->dev_addr);
217 }
219 ixp2400_msf_init(&enp2611_msf_parameters);
221 if (ixpdev_init(ports, nds, enp2611_set_port_admin_status)) {
222 for (i = 0; i < ports; i++)
223 if (nds[i])
224 free_netdev(nds[i]);
225 return -EINVAL;
226 }
228 init_timer(&link_check_timer);
229 link_check_timer.function = enp2611_check_link_status;
230 link_check_timer.expires = jiffies;
231 add_timer(&link_check_timer);
233 return 0;
234 }
236 static void __exit enp2611_cleanup_module(void)
237 {
238 int i;
240 del_timer_sync(&link_check_timer);
242 ixpdev_deinit();
243 for (i = 0; i < 3; i++)
244 free_netdev(nds[i]);
245 }
247 module_init(enp2611_init_module);
248 module_exit(enp2611_cleanup_module);
249 MODULE_LICENSE("GPL");