ia64/linux-2.6.18-xen.hg

view drivers/serial/sunhv.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 /* sunhv.c: Serial driver for SUN4V hypervisor console.
2 *
3 * Copyright (C) 2006 David S. Miller (davem@davemloft.net)
4 */
6 #include <linux/module.h>
7 #include <linux/kernel.h>
8 #include <linux/errno.h>
9 #include <linux/tty.h>
10 #include <linux/tty_flip.h>
11 #include <linux/major.h>
12 #include <linux/circ_buf.h>
13 #include <linux/serial.h>
14 #include <linux/sysrq.h>
15 #include <linux/console.h>
16 #include <linux/spinlock.h>
17 #include <linux/slab.h>
18 #include <linux/delay.h>
19 #include <linux/init.h>
21 #include <asm/hypervisor.h>
22 #include <asm/spitfire.h>
23 #include <asm/prom.h>
24 #include <asm/of_device.h>
25 #include <asm/irq.h>
27 #if defined(CONFIG_MAGIC_SYSRQ)
28 #define SUPPORT_SYSRQ
29 #endif
31 #include <linux/serial_core.h>
33 #include "suncore.h"
35 #define CON_BREAK ((long)-1)
36 #define CON_HUP ((long)-2)
38 static inline long hypervisor_con_getchar(long *status)
39 {
40 register unsigned long func asm("%o5");
41 register unsigned long arg0 asm("%o0");
42 register unsigned long arg1 asm("%o1");
44 func = HV_FAST_CONS_GETCHAR;
45 arg0 = 0;
46 arg1 = 0;
47 __asm__ __volatile__("ta %6"
48 : "=&r" (func), "=&r" (arg0), "=&r" (arg1)
49 : "0" (func), "1" (arg0), "2" (arg1),
50 "i" (HV_FAST_TRAP));
52 *status = arg0;
54 return (long) arg1;
55 }
57 static inline long hypervisor_con_putchar(long ch)
58 {
59 register unsigned long func asm("%o5");
60 register unsigned long arg0 asm("%o0");
62 func = HV_FAST_CONS_PUTCHAR;
63 arg0 = ch;
64 __asm__ __volatile__("ta %4"
65 : "=&r" (func), "=&r" (arg0)
66 : "0" (func), "1" (arg0), "i" (HV_FAST_TRAP));
68 return (long) arg0;
69 }
71 #define IGNORE_BREAK 0x1
72 #define IGNORE_ALL 0x2
74 static int hung_up = 0;
76 static struct tty_struct *receive_chars(struct uart_port *port, struct pt_regs *regs)
77 {
78 struct tty_struct *tty = NULL;
79 int saw_console_brk = 0;
80 int limit = 10000;
82 if (port->info != NULL) /* Unopened serial console */
83 tty = port->info->tty;
85 while (limit-- > 0) {
86 long status;
87 long c = hypervisor_con_getchar(&status);
88 unsigned char flag;
90 if (status == HV_EWOULDBLOCK)
91 break;
93 if (c == CON_BREAK) {
94 if (uart_handle_break(port))
95 continue;
96 saw_console_brk = 1;
97 c = 0;
98 }
100 if (c == CON_HUP) {
101 hung_up = 1;
102 uart_handle_dcd_change(port, 0);
103 } else if (hung_up) {
104 hung_up = 0;
105 uart_handle_dcd_change(port, 1);
106 }
108 if (tty == NULL) {
109 uart_handle_sysrq_char(port, c, regs);
110 continue;
111 }
113 flag = TTY_NORMAL;
114 port->icount.rx++;
115 if (c == CON_BREAK) {
116 port->icount.brk++;
117 if (uart_handle_break(port))
118 continue;
119 flag = TTY_BREAK;
120 }
122 if (uart_handle_sysrq_char(port, c, regs))
123 continue;
125 if ((port->ignore_status_mask & IGNORE_ALL) ||
126 ((port->ignore_status_mask & IGNORE_BREAK) &&
127 (c == CON_BREAK)))
128 continue;
130 tty_insert_flip_char(tty, c, flag);
131 }
133 if (saw_console_brk)
134 sun_do_break();
136 return tty;
137 }
139 static void transmit_chars(struct uart_port *port)
140 {
141 struct circ_buf *xmit;
143 if (!port->info)
144 return;
146 xmit = &port->info->xmit;
147 if (uart_circ_empty(xmit) || uart_tx_stopped(port))
148 return;
150 while (!uart_circ_empty(xmit)) {
151 long status = hypervisor_con_putchar(xmit->buf[xmit->tail]);
153 if (status != HV_EOK)
154 break;
156 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
157 port->icount.tx++;
158 }
160 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
161 uart_write_wakeup(port);
162 }
164 static irqreturn_t sunhv_interrupt(int irq, void *dev_id, struct pt_regs *regs)
165 {
166 struct uart_port *port = dev_id;
167 struct tty_struct *tty;
168 unsigned long flags;
170 spin_lock_irqsave(&port->lock, flags);
171 tty = receive_chars(port, regs);
172 transmit_chars(port);
173 spin_unlock_irqrestore(&port->lock, flags);
175 if (tty)
176 tty_flip_buffer_push(tty);
178 return IRQ_HANDLED;
179 }
181 /* port->lock is not held. */
182 static unsigned int sunhv_tx_empty(struct uart_port *port)
183 {
184 /* Transmitter is always empty for us. If the circ buffer
185 * is non-empty or there is an x_char pending, our caller
186 * will do the right thing and ignore what we return here.
187 */
188 return TIOCSER_TEMT;
189 }
191 /* port->lock held by caller. */
192 static void sunhv_set_mctrl(struct uart_port *port, unsigned int mctrl)
193 {
194 return;
195 }
197 /* port->lock is held by caller and interrupts are disabled. */
198 static unsigned int sunhv_get_mctrl(struct uart_port *port)
199 {
200 return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS;
201 }
203 /* port->lock held by caller. */
204 static void sunhv_stop_tx(struct uart_port *port)
205 {
206 return;
207 }
209 /* port->lock held by caller. */
210 static void sunhv_start_tx(struct uart_port *port)
211 {
212 struct circ_buf *xmit = &port->info->xmit;
214 while (!uart_circ_empty(xmit)) {
215 long status = hypervisor_con_putchar(xmit->buf[xmit->tail]);
217 if (status != HV_EOK)
218 break;
220 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
221 port->icount.tx++;
222 }
223 }
225 /* port->lock is not held. */
226 static void sunhv_send_xchar(struct uart_port *port, char ch)
227 {
228 unsigned long flags;
229 int limit = 10000;
231 spin_lock_irqsave(&port->lock, flags);
233 while (limit-- > 0) {
234 long status = hypervisor_con_putchar(ch);
235 if (status == HV_EOK)
236 break;
237 }
239 spin_unlock_irqrestore(&port->lock, flags);
240 }
242 /* port->lock held by caller. */
243 static void sunhv_stop_rx(struct uart_port *port)
244 {
245 }
247 /* port->lock held by caller. */
248 static void sunhv_enable_ms(struct uart_port *port)
249 {
250 }
252 /* port->lock is not held. */
253 static void sunhv_break_ctl(struct uart_port *port, int break_state)
254 {
255 if (break_state) {
256 unsigned long flags;
257 int limit = 1000000;
259 spin_lock_irqsave(&port->lock, flags);
261 while (limit-- > 0) {
262 long status = hypervisor_con_putchar(CON_BREAK);
263 if (status == HV_EOK)
264 break;
265 udelay(2);
266 }
268 spin_unlock_irqrestore(&port->lock, flags);
269 }
270 }
272 /* port->lock is not held. */
273 static int sunhv_startup(struct uart_port *port)
274 {
275 return 0;
276 }
278 /* port->lock is not held. */
279 static void sunhv_shutdown(struct uart_port *port)
280 {
281 }
283 /* port->lock is not held. */
284 static void sunhv_set_termios(struct uart_port *port, struct termios *termios,
285 struct termios *old)
286 {
287 unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
288 unsigned int quot = uart_get_divisor(port, baud);
289 unsigned int iflag, cflag;
290 unsigned long flags;
292 spin_lock_irqsave(&port->lock, flags);
294 iflag = termios->c_iflag;
295 cflag = termios->c_cflag;
297 port->ignore_status_mask = 0;
298 if (iflag & IGNBRK)
299 port->ignore_status_mask |= IGNORE_BREAK;
300 if ((cflag & CREAD) == 0)
301 port->ignore_status_mask |= IGNORE_ALL;
303 /* XXX */
304 uart_update_timeout(port, cflag,
305 (port->uartclk / (16 * quot)));
307 spin_unlock_irqrestore(&port->lock, flags);
308 }
310 static const char *sunhv_type(struct uart_port *port)
311 {
312 return "SUN4V HCONS";
313 }
315 static void sunhv_release_port(struct uart_port *port)
316 {
317 }
319 static int sunhv_request_port(struct uart_port *port)
320 {
321 return 0;
322 }
324 static void sunhv_config_port(struct uart_port *port, int flags)
325 {
326 }
328 static int sunhv_verify_port(struct uart_port *port, struct serial_struct *ser)
329 {
330 return -EINVAL;
331 }
333 static struct uart_ops sunhv_pops = {
334 .tx_empty = sunhv_tx_empty,
335 .set_mctrl = sunhv_set_mctrl,
336 .get_mctrl = sunhv_get_mctrl,
337 .stop_tx = sunhv_stop_tx,
338 .start_tx = sunhv_start_tx,
339 .send_xchar = sunhv_send_xchar,
340 .stop_rx = sunhv_stop_rx,
341 .enable_ms = sunhv_enable_ms,
342 .break_ctl = sunhv_break_ctl,
343 .startup = sunhv_startup,
344 .shutdown = sunhv_shutdown,
345 .set_termios = sunhv_set_termios,
346 .type = sunhv_type,
347 .release_port = sunhv_release_port,
348 .request_port = sunhv_request_port,
349 .config_port = sunhv_config_port,
350 .verify_port = sunhv_verify_port,
351 };
353 static struct uart_driver sunhv_reg = {
354 .owner = THIS_MODULE,
355 .driver_name = "serial",
356 .dev_name = "ttyS",
357 .major = TTY_MAJOR,
358 };
360 static struct uart_port *sunhv_port;
362 static inline void sunhv_console_putchar(struct uart_port *port, char c)
363 {
364 unsigned long flags;
365 int limit = 1000000;
367 spin_lock_irqsave(&port->lock, flags);
369 while (limit-- > 0) {
370 long status = hypervisor_con_putchar(c);
371 if (status == HV_EOK)
372 break;
373 udelay(2);
374 }
376 spin_unlock_irqrestore(&port->lock, flags);
377 }
379 static void sunhv_console_write(struct console *con, const char *s, unsigned n)
380 {
381 struct uart_port *port = sunhv_port;
382 int i;
384 for (i = 0; i < n; i++) {
385 if (*s == '\n')
386 sunhv_console_putchar(port, '\r');
387 sunhv_console_putchar(port, *s++);
388 }
389 }
391 static struct console sunhv_console = {
392 .name = "ttyHV",
393 .write = sunhv_console_write,
394 .device = uart_console_device,
395 .flags = CON_PRINTBUFFER,
396 .index = -1,
397 .data = &sunhv_reg,
398 };
400 static inline struct console *SUNHV_CONSOLE(void)
401 {
402 if (con_is_present())
403 return NULL;
405 sunhv_console.index = 0;
407 return &sunhv_console;
408 }
410 static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match)
411 {
412 struct uart_port *port;
413 int err;
415 if (op->irqs[0] == 0xffffffff)
416 return -ENODEV;
418 port = kzalloc(sizeof(struct uart_port), GFP_KERNEL);
419 if (unlikely(!port))
420 return -ENOMEM;
422 sunhv_port = port;
424 port->line = 0;
425 port->ops = &sunhv_pops;
426 port->type = PORT_SUNHV;
427 port->uartclk = ( 29491200 / 16 ); /* arbitrary */
429 port->membase = (unsigned char __iomem *) __pa(port);
431 port->irq = op->irqs[0];
433 port->dev = &op->dev;
435 sunhv_reg.minor = sunserial_current_minor;
436 sunhv_reg.nr = 1;
438 err = uart_register_driver(&sunhv_reg);
439 if (err)
440 goto out_free_port;
442 sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64;
443 sunserial_current_minor += 1;
445 sunhv_reg.cons = SUNHV_CONSOLE();
447 err = uart_add_one_port(&sunhv_reg, port);
448 if (err)
449 goto out_unregister_driver;
451 err = request_irq(port->irq, sunhv_interrupt, 0, "hvcons", port);
452 if (err)
453 goto out_remove_port;
455 dev_set_drvdata(&op->dev, port);
457 return 0;
459 out_remove_port:
460 uart_remove_one_port(&sunhv_reg, port);
462 out_unregister_driver:
463 sunserial_current_minor -= 1;
464 uart_unregister_driver(&sunhv_reg);
466 out_free_port:
467 kfree(port);
468 sunhv_port = NULL;
469 return err;
470 }
472 static int __devexit hv_remove(struct of_device *dev)
473 {
474 struct uart_port *port = dev_get_drvdata(&dev->dev);
476 free_irq(port->irq, port);
478 uart_remove_one_port(&sunhv_reg, port);
480 sunserial_current_minor -= 1;
481 uart_unregister_driver(&sunhv_reg);
483 kfree(port);
484 sunhv_port = NULL;
486 dev_set_drvdata(&dev->dev, NULL);
488 return 0;
489 }
491 static struct of_device_id hv_match[] = {
492 {
493 .name = "console",
494 .compatible = "qcn",
495 },
496 {},
497 };
498 MODULE_DEVICE_TABLE(of, hv_match);
500 static struct of_platform_driver hv_driver = {
501 .name = "hv",
502 .match_table = hv_match,
503 .probe = hv_probe,
504 .remove = __devexit_p(hv_remove),
505 };
507 static int __init sunhv_init(void)
508 {
509 if (tlb_type != hypervisor)
510 return -ENODEV;
512 return of_register_driver(&hv_driver, &of_bus_type);
513 }
515 static void __exit sunhv_exit(void)
516 {
517 of_unregister_driver(&hv_driver);
518 }
520 module_init(sunhv_init);
521 module_exit(sunhv_exit);
523 MODULE_AUTHOR("David S. Miller");
524 MODULE_DESCRIPTION("SUN4V Hypervisor console driver");
525 MODULE_VERSION("2.0");
526 MODULE_LICENSE("GPL");