ia64/linux-2.6.18-xen.hg

view drivers/serial/clps711x.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 * linux/drivers/char/clps711x.c
3 *
4 * Driver for CLPS711x serial ports
5 *
6 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
7 *
8 * Copyright 1999 ARM Limited
9 * Copyright (C) 2000 Deep Blue Solutions Ltd.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * $Id: clps711x.c,v 1.42 2002/07/28 10:03:28 rmk Exp $
26 *
27 */
29 #if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
30 #define SUPPORT_SYSRQ
31 #endif
33 #include <linux/module.h>
34 #include <linux/ioport.h>
35 #include <linux/init.h>
36 #include <linux/console.h>
37 #include <linux/sysrq.h>
38 #include <linux/spinlock.h>
39 #include <linux/device.h>
40 #include <linux/tty.h>
41 #include <linux/tty_flip.h>
42 #include <linux/serial_core.h>
43 #include <linux/serial.h>
45 #include <asm/hardware.h>
46 #include <asm/io.h>
47 #include <asm/irq.h>
48 #include <asm/hardware/clps7111.h>
50 #define UART_NR 2
52 #define SERIAL_CLPS711X_MAJOR 204
53 #define SERIAL_CLPS711X_MINOR 40
54 #define SERIAL_CLPS711X_NR UART_NR
56 /*
57 * We use the relevant SYSCON register as a base address for these ports.
58 */
59 #define UBRLCR(port) ((port)->iobase + UBRLCR1 - SYSCON1)
60 #define UARTDR(port) ((port)->iobase + UARTDR1 - SYSCON1)
61 #define SYSFLG(port) ((port)->iobase + SYSFLG1 - SYSCON1)
62 #define SYSCON(port) ((port)->iobase + SYSCON1 - SYSCON1)
64 #define TX_IRQ(port) ((port)->irq)
65 #define RX_IRQ(port) ((port)->irq + 1)
67 #define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
69 #define tx_enabled(port) ((port)->unused[0])
71 static void clps711xuart_stop_tx(struct uart_port *port)
72 {
73 if (tx_enabled(port)) {
74 disable_irq(TX_IRQ(port));
75 tx_enabled(port) = 0;
76 }
77 }
79 static void clps711xuart_start_tx(struct uart_port *port)
80 {
81 if (!tx_enabled(port)) {
82 enable_irq(TX_IRQ(port));
83 tx_enabled(port) = 1;
84 }
85 }
87 static void clps711xuart_stop_rx(struct uart_port *port)
88 {
89 disable_irq(RX_IRQ(port));
90 }
92 static void clps711xuart_enable_ms(struct uart_port *port)
93 {
94 }
96 static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
97 {
98 struct uart_port *port = dev_id;
99 struct tty_struct *tty = port->info->tty;
100 unsigned int status, ch, flg;
102 status = clps_readl(SYSFLG(port));
103 while (!(status & SYSFLG_URXFE)) {
104 ch = clps_readl(UARTDR(port));
106 port->icount.rx++;
108 flg = TTY_NORMAL;
110 /*
111 * Note that the error handling code is
112 * out of the main execution path
113 */
114 if (unlikely(ch & UART_ANY_ERR)) {
115 if (ch & UARTDR_PARERR)
116 port->icount.parity++;
117 else if (ch & UARTDR_FRMERR)
118 port->icount.frame++;
119 if (ch & UARTDR_OVERR)
120 port->icount.overrun++;
122 ch &= port->read_status_mask;
124 if (ch & UARTDR_PARERR)
125 flg = TTY_PARITY;
126 else if (ch & UARTDR_FRMERR)
127 flg = TTY_FRAME;
129 #ifdef SUPPORT_SYSRQ
130 port->sysrq = 0;
131 #endif
132 }
134 if (uart_handle_sysrq_char(port, ch, regs))
135 goto ignore_char;
137 /*
138 * CHECK: does overrun affect the current character?
139 * ASSUMPTION: it does not.
140 */
141 uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
143 ignore_char:
144 status = clps_readl(SYSFLG(port));
145 }
146 tty_flip_buffer_push(tty);
147 return IRQ_HANDLED;
148 }
150 static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
151 {
152 struct uart_port *port = dev_id;
153 struct circ_buf *xmit = &port->info->xmit;
154 int count;
156 if (port->x_char) {
157 clps_writel(port->x_char, UARTDR(port));
158 port->icount.tx++;
159 port->x_char = 0;
160 return IRQ_HANDLED;
161 }
162 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
163 clps711xuart_stop_tx(port);
164 return IRQ_HANDLED;
165 }
167 count = port->fifosize >> 1;
168 do {
169 clps_writel(xmit->buf[xmit->tail], UARTDR(port));
170 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
171 port->icount.tx++;
172 if (uart_circ_empty(xmit))
173 break;
174 } while (--count > 0);
176 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
177 uart_write_wakeup(port);
179 if (uart_circ_empty(xmit))
180 clps711xuart_stop_tx(port);
182 return IRQ_HANDLED;
183 }
185 static unsigned int clps711xuart_tx_empty(struct uart_port *port)
186 {
187 unsigned int status = clps_readl(SYSFLG(port));
188 return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
189 }
191 static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
192 {
193 unsigned int port_addr;
194 unsigned int result = 0;
195 unsigned int status;
197 port_addr = SYSFLG(port);
198 if (port_addr == SYSFLG1) {
199 status = clps_readl(SYSFLG1);
200 if (status & SYSFLG1_DCD)
201 result |= TIOCM_CAR;
202 if (status & SYSFLG1_DSR)
203 result |= TIOCM_DSR;
204 if (status & SYSFLG1_CTS)
205 result |= TIOCM_CTS;
206 }
208 return result;
209 }
211 static void
212 clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
213 {
214 }
216 static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
217 {
218 unsigned long flags;
219 unsigned int ubrlcr;
221 spin_lock_irqsave(&port->lock, flags);
222 ubrlcr = clps_readl(UBRLCR(port));
223 if (break_state == -1)
224 ubrlcr |= UBRLCR_BREAK;
225 else
226 ubrlcr &= ~UBRLCR_BREAK;
227 clps_writel(ubrlcr, UBRLCR(port));
228 spin_unlock_irqrestore(&port->lock, flags);
229 }
231 static int clps711xuart_startup(struct uart_port *port)
232 {
233 unsigned int syscon;
234 int retval;
236 tx_enabled(port) = 1;
238 /*
239 * Allocate the IRQs
240 */
241 retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
242 "clps711xuart_tx", port);
243 if (retval)
244 return retval;
246 retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
247 "clps711xuart_rx", port);
248 if (retval) {
249 free_irq(TX_IRQ(port), port);
250 return retval;
251 }
253 /*
254 * enable the port
255 */
256 syscon = clps_readl(SYSCON(port));
257 syscon |= SYSCON_UARTEN;
258 clps_writel(syscon, SYSCON(port));
260 return 0;
261 }
263 static void clps711xuart_shutdown(struct uart_port *port)
264 {
265 unsigned int ubrlcr, syscon;
267 /*
268 * Free the interrupt
269 */
270 free_irq(TX_IRQ(port), port); /* TX interrupt */
271 free_irq(RX_IRQ(port), port); /* RX interrupt */
273 /*
274 * disable the port
275 */
276 syscon = clps_readl(SYSCON(port));
277 syscon &= ~SYSCON_UARTEN;
278 clps_writel(syscon, SYSCON(port));
280 /*
281 * disable break condition and fifos
282 */
283 ubrlcr = clps_readl(UBRLCR(port));
284 ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
285 clps_writel(ubrlcr, UBRLCR(port));
286 }
288 static void
289 clps711xuart_set_termios(struct uart_port *port, struct termios *termios,
290 struct termios *old)
291 {
292 unsigned int ubrlcr, baud, quot;
293 unsigned long flags;
295 /*
296 * We don't implement CREAD.
297 */
298 termios->c_cflag |= CREAD;
300 /*
301 * Ask the core to calculate the divisor for us.
302 */
303 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
304 quot = uart_get_divisor(port, baud);
306 switch (termios->c_cflag & CSIZE) {
307 case CS5:
308 ubrlcr = UBRLCR_WRDLEN5;
309 break;
310 case CS6:
311 ubrlcr = UBRLCR_WRDLEN6;
312 break;
313 case CS7:
314 ubrlcr = UBRLCR_WRDLEN7;
315 break;
316 default: // CS8
317 ubrlcr = UBRLCR_WRDLEN8;
318 break;
319 }
320 if (termios->c_cflag & CSTOPB)
321 ubrlcr |= UBRLCR_XSTOP;
322 if (termios->c_cflag & PARENB) {
323 ubrlcr |= UBRLCR_PRTEN;
324 if (!(termios->c_cflag & PARODD))
325 ubrlcr |= UBRLCR_EVENPRT;
326 }
327 if (port->fifosize > 1)
328 ubrlcr |= UBRLCR_FIFOEN;
330 spin_lock_irqsave(&port->lock, flags);
332 /*
333 * Update the per-port timeout.
334 */
335 uart_update_timeout(port, termios->c_cflag, baud);
337 port->read_status_mask = UARTDR_OVERR;
338 if (termios->c_iflag & INPCK)
339 port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
341 /*
342 * Characters to ignore
343 */
344 port->ignore_status_mask = 0;
345 if (termios->c_iflag & IGNPAR)
346 port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
347 if (termios->c_iflag & IGNBRK) {
348 /*
349 * If we're ignoring parity and break indicators,
350 * ignore overruns to (for real raw support).
351 */
352 if (termios->c_iflag & IGNPAR)
353 port->ignore_status_mask |= UARTDR_OVERR;
354 }
356 quot -= 1;
358 clps_writel(ubrlcr | quot, UBRLCR(port));
360 spin_unlock_irqrestore(&port->lock, flags);
361 }
363 static const char *clps711xuart_type(struct uart_port *port)
364 {
365 return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
366 }
368 /*
369 * Configure/autoconfigure the port.
370 */
371 static void clps711xuart_config_port(struct uart_port *port, int flags)
372 {
373 if (flags & UART_CONFIG_TYPE)
374 port->type = PORT_CLPS711X;
375 }
377 static void clps711xuart_release_port(struct uart_port *port)
378 {
379 }
381 static int clps711xuart_request_port(struct uart_port *port)
382 {
383 return 0;
384 }
386 static struct uart_ops clps711x_pops = {
387 .tx_empty = clps711xuart_tx_empty,
388 .set_mctrl = clps711xuart_set_mctrl_null,
389 .get_mctrl = clps711xuart_get_mctrl,
390 .stop_tx = clps711xuart_stop_tx,
391 .start_tx = clps711xuart_start_tx,
392 .stop_rx = clps711xuart_stop_rx,
393 .enable_ms = clps711xuart_enable_ms,
394 .break_ctl = clps711xuart_break_ctl,
395 .startup = clps711xuart_startup,
396 .shutdown = clps711xuart_shutdown,
397 .set_termios = clps711xuart_set_termios,
398 .type = clps711xuart_type,
399 .config_port = clps711xuart_config_port,
400 .release_port = clps711xuart_release_port,
401 .request_port = clps711xuart_request_port,
402 };
404 static struct uart_port clps711x_ports[UART_NR] = {
405 {
406 .iobase = SYSCON1,
407 .irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
408 .uartclk = 3686400,
409 .fifosize = 16,
410 .ops = &clps711x_pops,
411 .line = 0,
412 .flags = UPF_BOOT_AUTOCONF,
413 },
414 {
415 .iobase = SYSCON2,
416 .irq = IRQ_UTXINT2, /* IRQ_URXINT2 */
417 .uartclk = 3686400,
418 .fifosize = 16,
419 .ops = &clps711x_pops,
420 .line = 1,
421 .flags = UPF_BOOT_AUTOCONF,
422 }
423 };
425 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
426 static void clps711xuart_console_putchar(struct uart_port *port, int ch)
427 {
428 while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF)
429 barrier();
430 clps_writel(ch, UARTDR(port));
431 }
433 /*
434 * Print a string to the serial port trying not to disturb
435 * any possible real use of the port...
436 *
437 * The console_lock must be held when we get here.
438 *
439 * Note that this is called with interrupts already disabled
440 */
441 static void
442 clps711xuart_console_write(struct console *co, const char *s,
443 unsigned int count)
444 {
445 struct uart_port *port = clps711x_ports + co->index;
446 unsigned int status, syscon;
448 /*
449 * Ensure that the port is enabled.
450 */
451 syscon = clps_readl(SYSCON(port));
452 clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
454 uart_console_write(port, s, count, clps711xuart_console_putchar);
456 /*
457 * Finally, wait for transmitter to become empty
458 * and restore the uart state.
459 */
460 do {
461 status = clps_readl(SYSFLG(port));
462 } while (status & SYSFLG_UBUSY);
464 clps_writel(syscon, SYSCON(port));
465 }
467 static void __init
468 clps711xuart_console_get_options(struct uart_port *port, int *baud,
469 int *parity, int *bits)
470 {
471 if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
472 unsigned int ubrlcr, quot;
474 ubrlcr = clps_readl(UBRLCR(port));
476 *parity = 'n';
477 if (ubrlcr & UBRLCR_PRTEN) {
478 if (ubrlcr & UBRLCR_EVENPRT)
479 *parity = 'e';
480 else
481 *parity = 'o';
482 }
484 if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7)
485 *bits = 7;
486 else
487 *bits = 8;
489 quot = ubrlcr & UBRLCR_BAUD_MASK;
490 *baud = port->uartclk / (16 * (quot + 1));
491 }
492 }
494 static int __init clps711xuart_console_setup(struct console *co, char *options)
495 {
496 struct uart_port *port;
497 int baud = 38400;
498 int bits = 8;
499 int parity = 'n';
500 int flow = 'n';
502 /*
503 * Check whether an invalid uart number has been specified, and
504 * if so, search for the first available port that does have
505 * console support.
506 */
507 port = uart_get_console(clps711x_ports, UART_NR, co);
509 if (options)
510 uart_parse_options(options, &baud, &parity, &bits, &flow);
511 else
512 clps711xuart_console_get_options(port, &baud, &parity, &bits);
514 return uart_set_options(port, co, baud, parity, bits, flow);
515 }
517 static struct uart_driver clps711x_reg;
518 static struct console clps711x_console = {
519 .name = "ttyCL",
520 .write = clps711xuart_console_write,
521 .device = uart_console_device,
522 .setup = clps711xuart_console_setup,
523 .flags = CON_PRINTBUFFER,
524 .index = -1,
525 .data = &clps711x_reg,
526 };
528 static int __init clps711xuart_console_init(void)
529 {
530 register_console(&clps711x_console);
531 return 0;
532 }
533 console_initcall(clps711xuart_console_init);
535 #define CLPS711X_CONSOLE &clps711x_console
536 #else
537 #define CLPS711X_CONSOLE NULL
538 #endif
540 static struct uart_driver clps711x_reg = {
541 .driver_name = "ttyCL",
542 .dev_name = "ttyCL",
543 .major = SERIAL_CLPS711X_MAJOR,
544 .minor = SERIAL_CLPS711X_MINOR,
545 .nr = UART_NR,
547 .cons = CLPS711X_CONSOLE,
548 };
550 static int __init clps711xuart_init(void)
551 {
552 int ret, i;
554 printk(KERN_INFO "Serial: CLPS711x driver $Revision: 1.42 $\n");
556 ret = uart_register_driver(&clps711x_reg);
557 if (ret)
558 return ret;
560 for (i = 0; i < UART_NR; i++)
561 uart_add_one_port(&clps711x_reg, &clps711x_ports[i]);
563 return 0;
564 }
566 static void __exit clps711xuart_exit(void)
567 {
568 int i;
570 for (i = 0; i < UART_NR; i++)
571 uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
573 uart_unregister_driver(&clps711x_reg);
574 }
576 module_init(clps711xuart_init);
577 module_exit(clps711xuart_exit);
579 MODULE_AUTHOR("Deep Blue Solutions Ltd");
580 MODULE_DESCRIPTION("CLPS-711x generic serial driver $Revision: 1.42 $");
581 MODULE_LICENSE("GPL");
582 MODULE_ALIAS_CHARDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR);