ia64/linux-2.6.18-xen.hg

view drivers/net/fec_8xx/fec_mii.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 * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
3 *
4 * Copyright (c) 2003 Intracom S.A.
5 * by Pantelis Antoniou <panto@intracom.gr>
6 *
7 * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
8 * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
9 *
10 * Released under the GPL
11 */
13 #include <linux/module.h>
14 #include <linux/types.h>
15 #include <linux/kernel.h>
16 #include <linux/sched.h>
17 #include <linux/string.h>
18 #include <linux/ptrace.h>
19 #include <linux/errno.h>
20 #include <linux/ioport.h>
21 #include <linux/slab.h>
22 #include <linux/interrupt.h>
23 #include <linux/pci.h>
24 #include <linux/init.h>
25 #include <linux/delay.h>
26 #include <linux/netdevice.h>
27 #include <linux/etherdevice.h>
28 #include <linux/skbuff.h>
29 #include <linux/spinlock.h>
30 #include <linux/mii.h>
31 #include <linux/ethtool.h>
32 #include <linux/bitops.h>
34 #include <asm/8xx_immap.h>
35 #include <asm/pgtable.h>
36 #include <asm/mpc8xx.h>
37 #include <asm/irq.h>
38 #include <asm/uaccess.h>
39 #include <asm/commproc.h>
41 /*************************************************/
43 #include "fec_8xx.h"
45 /*************************************************/
47 /* Make MII read/write commands for the FEC.
48 */
49 #define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
50 #define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
51 #define mk_mii_end 0
53 /*************************************************/
55 /* XXX both FECs use the MII interface of FEC1 */
56 static DEFINE_SPINLOCK(fec_mii_lock);
58 #define FEC_MII_LOOPS 10000
60 int fec_mii_read(struct net_device *dev, int phy_id, int location)
61 {
62 struct fec_enet_private *fep = netdev_priv(dev);
63 fec_t *fecp;
64 int i, ret = -1;
65 unsigned long flags;
67 /* XXX MII interface is only connected to FEC1 */
68 fecp = &((immap_t *) IMAP_ADDR)->im_cpm.cp_fec;
70 spin_lock_irqsave(&fec_mii_lock, flags);
72 if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) {
73 FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
74 FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
75 FW(fecp, ievent, FEC_ENET_MII);
76 }
78 /* Add PHY address to register command. */
79 FW(fecp, mii_speed, fep->fec_phy_speed);
80 FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location));
82 for (i = 0; i < FEC_MII_LOOPS; i++)
83 if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
84 break;
86 if (i < FEC_MII_LOOPS) {
87 FW(fecp, ievent, FEC_ENET_MII);
88 ret = FR(fecp, mii_data) & 0xffff;
89 }
91 spin_unlock_irqrestore(&fec_mii_lock, flags);
93 return ret;
94 }
96 void fec_mii_write(struct net_device *dev, int phy_id, int location, int value)
97 {
98 struct fec_enet_private *fep = netdev_priv(dev);
99 fec_t *fecp;
100 unsigned long flags;
101 int i;
103 /* XXX MII interface is only connected to FEC1 */
104 fecp = &((immap_t *) IMAP_ADDR)->im_cpm.cp_fec;
106 spin_lock_irqsave(&fec_mii_lock, flags);
108 if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) {
109 FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
110 FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
111 FW(fecp, ievent, FEC_ENET_MII);
112 }
114 /* Add PHY address to register command. */
115 FW(fecp, mii_speed, fep->fec_phy_speed); /* always adapt mii speed */
116 FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value));
118 for (i = 0; i < FEC_MII_LOOPS; i++)
119 if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
120 break;
122 if (i < FEC_MII_LOOPS)
123 FW(fecp, ievent, FEC_ENET_MII);
125 spin_unlock_irqrestore(&fec_mii_lock, flags);
126 }
128 /*************************************************/
130 #ifdef CONFIG_FEC_8XX_GENERIC_PHY
132 /*
133 * Generic PHY support.
134 * Should work for all PHYs, but link change is detected by polling
135 */
137 static void generic_timer_callback(unsigned long data)
138 {
139 struct net_device *dev = (struct net_device *)data;
140 struct fec_enet_private *fep = netdev_priv(dev);
142 fep->phy_timer_list.expires = jiffies + HZ / 2;
144 add_timer(&fep->phy_timer_list);
146 fec_mii_link_status_change_check(dev, 0);
147 }
149 static void generic_startup(struct net_device *dev)
150 {
151 struct fec_enet_private *fep = netdev_priv(dev);
153 fep->phy_timer_list.expires = jiffies + HZ / 2; /* every 500ms */
154 fep->phy_timer_list.data = (unsigned long)dev;
155 fep->phy_timer_list.function = generic_timer_callback;
156 add_timer(&fep->phy_timer_list);
157 }
159 static void generic_shutdown(struct net_device *dev)
160 {
161 struct fec_enet_private *fep = netdev_priv(dev);
163 del_timer_sync(&fep->phy_timer_list);
164 }
166 #endif
168 #ifdef CONFIG_FEC_8XX_DM9161_PHY
170 /* ------------------------------------------------------------------------- */
171 /* The Davicom DM9161 is used on the NETTA board */
173 /* register definitions */
175 #define MII_DM9161_ACR 16 /* Aux. Config Register */
176 #define MII_DM9161_ACSR 17 /* Aux. Config/Status Register */
177 #define MII_DM9161_10TCSR 18 /* 10BaseT Config/Status Reg. */
178 #define MII_DM9161_INTR 21 /* Interrupt Register */
179 #define MII_DM9161_RECR 22 /* Receive Error Counter Reg. */
180 #define MII_DM9161_DISCR 23 /* Disconnect Counter Register */
182 static void dm9161_startup(struct net_device *dev)
183 {
184 struct fec_enet_private *fep = netdev_priv(dev);
186 fec_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
187 }
189 static void dm9161_ack_int(struct net_device *dev)
190 {
191 struct fec_enet_private *fep = netdev_priv(dev);
193 fec_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
194 }
196 static void dm9161_shutdown(struct net_device *dev)
197 {
198 struct fec_enet_private *fep = netdev_priv(dev);
200 fec_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
201 }
203 #endif
205 #ifdef CONFIG_FEC_8XX_LXT971_PHY
207 /* Support for LXT971/972 PHY */
209 #define MII_LXT971_PCR 16 /* Port Control Register */
210 #define MII_LXT971_SR2 17 /* Status Register 2 */
211 #define MII_LXT971_IER 18 /* Interrupt Enable Register */
212 #define MII_LXT971_ISR 19 /* Interrupt Status Register */
213 #define MII_LXT971_LCR 20 /* LED Control Register */
214 #define MII_LXT971_TCR 30 /* Transmit Control Register */
216 static void lxt971_startup(struct net_device *dev)
217 {
218 struct fec_enet_private *fep = netdev_priv(dev);
220 fec_mii_write(dev, fep->mii_if.phy_id, MII_LXT971_IER, 0x00F2);
221 }
223 static void lxt971_ack_int(struct net_device *dev)
224 {
225 struct fec_enet_private *fep = netdev_priv(dev);
227 fec_mii_read(dev, fep->mii_if.phy_id, MII_LXT971_ISR);
228 }
230 static void lxt971_shutdown(struct net_device *dev)
231 {
232 struct fec_enet_private *fep = netdev_priv(dev);
234 fec_mii_write(dev, fep->mii_if.phy_id, MII_LXT971_IER, 0x0000);
235 }
236 #endif
238 /**********************************************************************************/
240 static const struct phy_info phy_info[] = {
241 #ifdef CONFIG_FEC_8XX_DM9161_PHY
242 {
243 .id = 0x00181b88,
244 .name = "DM9161",
245 .startup = dm9161_startup,
246 .ack_int = dm9161_ack_int,
247 .shutdown = dm9161_shutdown,
248 },
249 #endif
250 #ifdef CONFIG_FEC_8XX_LXT971_PHY
251 {
252 .id = 0x0001378e,
253 .name = "LXT971/972",
254 .startup = lxt971_startup,
255 .ack_int = lxt971_ack_int,
256 .shutdown = lxt971_shutdown,
257 },
258 #endif
259 #ifdef CONFIG_FEC_8XX_GENERIC_PHY
260 {
261 .id = 0,
262 .name = "GENERIC",
263 .startup = generic_startup,
264 .shutdown = generic_shutdown,
265 },
266 #endif
267 };
269 /**********************************************************************************/
271 int fec_mii_phy_id_detect(struct net_device *dev)
272 {
273 struct fec_enet_private *fep = netdev_priv(dev);
274 const struct fec_platform_info *fpi = fep->fpi;
275 int i, r, start, end, phytype, physubtype;
276 const struct phy_info *phy;
277 int phy_hwid, phy_id;
279 /* if no MDIO */
280 if (fpi->use_mdio == 0)
281 return -1;
283 phy_hwid = -1;
284 fep->phy = NULL;
286 /* auto-detect? */
287 if (fpi->phy_addr == -1) {
288 start = 0;
289 end = 32;
290 } else { /* direct */
291 start = fpi->phy_addr;
292 end = start + 1;
293 }
295 for (phy_id = start; phy_id < end; phy_id++) {
296 r = fec_mii_read(dev, phy_id, MII_PHYSID1);
297 if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
298 continue;
299 r = fec_mii_read(dev, phy_id, MII_PHYSID2);
300 if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff)
301 continue;
302 phy_hwid = (phytype << 16) | physubtype;
303 if (phy_hwid != -1)
304 break;
305 }
307 if (phy_hwid == -1) {
308 printk(KERN_ERR DRV_MODULE_NAME
309 ": %s No PHY detected!\n", dev->name);
310 return -1;
311 }
313 for (i = 0, phy = phy_info; i < sizeof(phy_info) / sizeof(phy_info[0]);
314 i++, phy++)
315 if (phy->id == (phy_hwid >> 4) || phy->id == 0)
316 break;
318 if (i >= sizeof(phy_info) / sizeof(phy_info[0])) {
319 printk(KERN_ERR DRV_MODULE_NAME
320 ": %s PHY id 0x%08x is not supported!\n",
321 dev->name, phy_hwid);
322 return -1;
323 }
325 fep->phy = phy;
327 printk(KERN_INFO DRV_MODULE_NAME
328 ": %s Phy @ 0x%x, type %s (0x%08x)\n",
329 dev->name, phy_id, fep->phy->name, phy_hwid);
331 return phy_id;
332 }
334 void fec_mii_startup(struct net_device *dev)
335 {
336 struct fec_enet_private *fep = netdev_priv(dev);
337 const struct fec_platform_info *fpi = fep->fpi;
339 if (!fpi->use_mdio || fep->phy == NULL)
340 return;
342 if (fep->phy->startup == NULL)
343 return;
345 (*fep->phy->startup) (dev);
346 }
348 void fec_mii_shutdown(struct net_device *dev)
349 {
350 struct fec_enet_private *fep = netdev_priv(dev);
351 const struct fec_platform_info *fpi = fep->fpi;
353 if (!fpi->use_mdio || fep->phy == NULL)
354 return;
356 if (fep->phy->shutdown == NULL)
357 return;
359 (*fep->phy->shutdown) (dev);
360 }
362 void fec_mii_ack_int(struct net_device *dev)
363 {
364 struct fec_enet_private *fep = netdev_priv(dev);
365 const struct fec_platform_info *fpi = fep->fpi;
367 if (!fpi->use_mdio || fep->phy == NULL)
368 return;
370 if (fep->phy->ack_int == NULL)
371 return;
373 (*fep->phy->ack_int) (dev);
374 }
376 /* helper function */
377 static int mii_negotiated(struct mii_if_info *mii)
378 {
379 int advert, lpa, val;
381 if (!mii_link_ok(mii))
382 return 0;
384 val = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_BMSR);
385 if ((val & BMSR_ANEGCOMPLETE) == 0)
386 return 0;
388 advert = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_ADVERTISE);
389 lpa = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_LPA);
391 return mii_nway_result(advert & lpa);
392 }
394 void fec_mii_link_status_change_check(struct net_device *dev, int init_media)
395 {
396 struct fec_enet_private *fep = netdev_priv(dev);
397 unsigned int media;
398 unsigned long flags;
400 if (mii_check_media(&fep->mii_if, netif_msg_link(fep), init_media) == 0)
401 return;
403 media = mii_negotiated(&fep->mii_if);
405 if (netif_carrier_ok(dev)) {
406 spin_lock_irqsave(&fep->lock, flags);
407 fec_restart(dev, !!(media & ADVERTISE_FULL),
408 (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)) ?
409 100 : 10);
410 spin_unlock_irqrestore(&fep->lock, flags);
412 netif_start_queue(dev);
413 } else {
414 netif_stop_queue(dev);
416 spin_lock_irqsave(&fep->lock, flags);
417 fec_stop(dev);
418 spin_unlock_irqrestore(&fep->lock, flags);
420 }
421 }