ia64/linux-2.6.18-xen.hg

view drivers/serial/21285.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/21285.c
3 *
4 * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
5 *
6 * Based on drivers/char/serial.c
7 *
8 * $Id: 21285.c,v 1.37 2002/07/28 10:03:27 rmk Exp $
9 */
10 #include <linux/module.h>
11 #include <linux/tty.h>
12 #include <linux/ioport.h>
13 #include <linux/init.h>
14 #include <linux/console.h>
15 #include <linux/device.h>
16 #include <linux/tty_flip.h>
17 #include <linux/serial_core.h>
18 #include <linux/serial.h>
20 #include <asm/io.h>
21 #include <asm/irq.h>
22 #include <asm/mach-types.h>
23 #include <asm/hardware/dec21285.h>
24 #include <asm/hardware.h>
26 #define BAUD_BASE (mem_fclk_21285/64)
28 #define SERIAL_21285_NAME "ttyFB"
29 #define SERIAL_21285_MAJOR 204
30 #define SERIAL_21285_MINOR 4
32 #define RXSTAT_DUMMY_READ 0x80000000
33 #define RXSTAT_FRAME (1 << 0)
34 #define RXSTAT_PARITY (1 << 1)
35 #define RXSTAT_OVERRUN (1 << 2)
36 #define RXSTAT_ANYERR (RXSTAT_FRAME|RXSTAT_PARITY|RXSTAT_OVERRUN)
38 #define H_UBRLCR_BREAK (1 << 0)
39 #define H_UBRLCR_PARENB (1 << 1)
40 #define H_UBRLCR_PAREVN (1 << 2)
41 #define H_UBRLCR_STOPB (1 << 3)
42 #define H_UBRLCR_FIFO (1 << 4)
44 static const char serial21285_name[] = "Footbridge UART";
46 #define tx_enabled(port) ((port)->unused[0])
47 #define rx_enabled(port) ((port)->unused[1])
49 /*
50 * The documented expression for selecting the divisor is:
51 * BAUD_BASE / baud - 1
52 * However, typically BAUD_BASE is not divisible by baud, so
53 * we want to select the divisor that gives us the minimum
54 * error. Therefore, we want:
55 * int(BAUD_BASE / baud - 0.5) ->
56 * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
57 * int((BAUD_BASE - (baud >> 1)) / baud)
58 */
60 static void serial21285_stop_tx(struct uart_port *port)
61 {
62 if (tx_enabled(port)) {
63 disable_irq(IRQ_CONTX);
64 tx_enabled(port) = 0;
65 }
66 }
68 static void serial21285_start_tx(struct uart_port *port)
69 {
70 if (!tx_enabled(port)) {
71 enable_irq(IRQ_CONTX);
72 tx_enabled(port) = 1;
73 }
74 }
76 static void serial21285_stop_rx(struct uart_port *port)
77 {
78 if (rx_enabled(port)) {
79 disable_irq(IRQ_CONRX);
80 rx_enabled(port) = 0;
81 }
82 }
84 static void serial21285_enable_ms(struct uart_port *port)
85 {
86 }
88 static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
89 {
90 struct uart_port *port = dev_id;
91 struct tty_struct *tty = port->info->tty;
92 unsigned int status, ch, flag, rxs, max_count = 256;
94 status = *CSR_UARTFLG;
95 while (!(status & 0x10) && max_count--) {
96 ch = *CSR_UARTDR;
97 flag = TTY_NORMAL;
98 port->icount.rx++;
100 rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ;
101 if (unlikely(rxs & RXSTAT_ANYERR)) {
102 if (rxs & RXSTAT_PARITY)
103 port->icount.parity++;
104 else if (rxs & RXSTAT_FRAME)
105 port->icount.frame++;
106 if (rxs & RXSTAT_OVERRUN)
107 port->icount.overrun++;
109 rxs &= port->read_status_mask;
111 if (rxs & RXSTAT_PARITY)
112 flag = TTY_PARITY;
113 else if (rxs & RXSTAT_FRAME)
114 flag = TTY_FRAME;
115 }
117 uart_insert_char(port, rxs, RXSTAT_OVERRUN, ch, flag);
119 status = *CSR_UARTFLG;
120 }
121 tty_flip_buffer_push(tty);
123 return IRQ_HANDLED;
124 }
126 static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs)
127 {
128 struct uart_port *port = dev_id;
129 struct circ_buf *xmit = &port->info->xmit;
130 int count = 256;
132 if (port->x_char) {
133 *CSR_UARTDR = port->x_char;
134 port->icount.tx++;
135 port->x_char = 0;
136 goto out;
137 }
138 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
139 serial21285_stop_tx(port);
140 goto out;
141 }
143 do {
144 *CSR_UARTDR = xmit->buf[xmit->tail];
145 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
146 port->icount.tx++;
147 if (uart_circ_empty(xmit))
148 break;
149 } while (--count > 0 && !(*CSR_UARTFLG & 0x20));
151 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
152 uart_write_wakeup(port);
154 if (uart_circ_empty(xmit))
155 serial21285_stop_tx(port);
157 out:
158 return IRQ_HANDLED;
159 }
161 static unsigned int serial21285_tx_empty(struct uart_port *port)
162 {
163 return (*CSR_UARTFLG & 8) ? 0 : TIOCSER_TEMT;
164 }
166 /* no modem control lines */
167 static unsigned int serial21285_get_mctrl(struct uart_port *port)
168 {
169 return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
170 }
172 static void serial21285_set_mctrl(struct uart_port *port, unsigned int mctrl)
173 {
174 }
176 static void serial21285_break_ctl(struct uart_port *port, int break_state)
177 {
178 unsigned long flags;
179 unsigned int h_lcr;
181 spin_lock_irqsave(&port->lock, flags);
182 h_lcr = *CSR_H_UBRLCR;
183 if (break_state)
184 h_lcr |= H_UBRLCR_BREAK;
185 else
186 h_lcr &= ~H_UBRLCR_BREAK;
187 *CSR_H_UBRLCR = h_lcr;
188 spin_unlock_irqrestore(&port->lock, flags);
189 }
191 static int serial21285_startup(struct uart_port *port)
192 {
193 int ret;
195 tx_enabled(port) = 1;
196 rx_enabled(port) = 1;
198 ret = request_irq(IRQ_CONRX, serial21285_rx_chars, 0,
199 serial21285_name, port);
200 if (ret == 0) {
201 ret = request_irq(IRQ_CONTX, serial21285_tx_chars, 0,
202 serial21285_name, port);
203 if (ret)
204 free_irq(IRQ_CONRX, port);
205 }
207 return ret;
208 }
210 static void serial21285_shutdown(struct uart_port *port)
211 {
212 free_irq(IRQ_CONTX, port);
213 free_irq(IRQ_CONRX, port);
214 }
216 static void
217 serial21285_set_termios(struct uart_port *port, struct termios *termios,
218 struct termios *old)
219 {
220 unsigned long flags;
221 unsigned int baud, quot, h_lcr;
223 /*
224 * We don't support modem control lines.
225 */
226 termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
227 termios->c_cflag |= CLOCAL;
229 /*
230 * We don't support BREAK character recognition.
231 */
232 termios->c_iflag &= ~(IGNBRK | BRKINT);
234 /*
235 * Ask the core to calculate the divisor for us.
236 */
237 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
238 quot = uart_get_divisor(port, baud);
240 switch (termios->c_cflag & CSIZE) {
241 case CS5:
242 h_lcr = 0x00;
243 break;
244 case CS6:
245 h_lcr = 0x20;
246 break;
247 case CS7:
248 h_lcr = 0x40;
249 break;
250 default: /* CS8 */
251 h_lcr = 0x60;
252 break;
253 }
255 if (termios->c_cflag & CSTOPB)
256 h_lcr |= H_UBRLCR_STOPB;
257 if (termios->c_cflag & PARENB) {
258 h_lcr |= H_UBRLCR_PARENB;
259 if (!(termios->c_cflag & PARODD))
260 h_lcr |= H_UBRLCR_PAREVN;
261 }
263 if (port->fifosize)
264 h_lcr |= H_UBRLCR_FIFO;
266 spin_lock_irqsave(&port->lock, flags);
268 /*
269 * Update the per-port timeout.
270 */
271 uart_update_timeout(port, termios->c_cflag, baud);
273 /*
274 * Which character status flags are we interested in?
275 */
276 port->read_status_mask = RXSTAT_OVERRUN;
277 if (termios->c_iflag & INPCK)
278 port->read_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
280 /*
281 * Which character status flags should we ignore?
282 */
283 port->ignore_status_mask = 0;
284 if (termios->c_iflag & IGNPAR)
285 port->ignore_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
286 if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
287 port->ignore_status_mask |= RXSTAT_OVERRUN;
289 /*
290 * Ignore all characters if CREAD is not set.
291 */
292 if ((termios->c_cflag & CREAD) == 0)
293 port->ignore_status_mask |= RXSTAT_DUMMY_READ;
295 quot -= 1;
297 *CSR_UARTCON = 0;
298 *CSR_L_UBRLCR = quot & 0xff;
299 *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
300 *CSR_H_UBRLCR = h_lcr;
301 *CSR_UARTCON = 1;
303 spin_unlock_irqrestore(&port->lock, flags);
304 }
306 static const char *serial21285_type(struct uart_port *port)
307 {
308 return port->type == PORT_21285 ? "DC21285" : NULL;
309 }
311 static void serial21285_release_port(struct uart_port *port)
312 {
313 release_mem_region(port->mapbase, 32);
314 }
316 static int serial21285_request_port(struct uart_port *port)
317 {
318 return request_mem_region(port->mapbase, 32, serial21285_name)
319 != NULL ? 0 : -EBUSY;
320 }
322 static void serial21285_config_port(struct uart_port *port, int flags)
323 {
324 if (flags & UART_CONFIG_TYPE && serial21285_request_port(port) == 0)
325 port->type = PORT_21285;
326 }
328 /*
329 * verify the new serial_struct (for TIOCSSERIAL).
330 */
331 static int serial21285_verify_port(struct uart_port *port, struct serial_struct *ser)
332 {
333 int ret = 0;
334 if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285)
335 ret = -EINVAL;
336 if (ser->irq != NO_IRQ)
337 ret = -EINVAL;
338 if (ser->baud_base != port->uartclk / 16)
339 ret = -EINVAL;
340 return ret;
341 }
343 static struct uart_ops serial21285_ops = {
344 .tx_empty = serial21285_tx_empty,
345 .get_mctrl = serial21285_get_mctrl,
346 .set_mctrl = serial21285_set_mctrl,
347 .stop_tx = serial21285_stop_tx,
348 .start_tx = serial21285_start_tx,
349 .stop_rx = serial21285_stop_rx,
350 .enable_ms = serial21285_enable_ms,
351 .break_ctl = serial21285_break_ctl,
352 .startup = serial21285_startup,
353 .shutdown = serial21285_shutdown,
354 .set_termios = serial21285_set_termios,
355 .type = serial21285_type,
356 .release_port = serial21285_release_port,
357 .request_port = serial21285_request_port,
358 .config_port = serial21285_config_port,
359 .verify_port = serial21285_verify_port,
360 };
362 static struct uart_port serial21285_port = {
363 .mapbase = 0x42000160,
364 .iotype = UPIO_MEM,
365 .irq = NO_IRQ,
366 .fifosize = 16,
367 .ops = &serial21285_ops,
368 .flags = UPF_BOOT_AUTOCONF,
369 };
371 static void serial21285_setup_ports(void)
372 {
373 serial21285_port.uartclk = mem_fclk_21285 / 4;
374 }
376 #ifdef CONFIG_SERIAL_21285_CONSOLE
377 static void serial21285_console_putchar(struct uart_port *port, int ch)
378 {
379 while (*CSR_UARTFLG & 0x20)
380 barrier();
381 *CSR_UARTDR = ch;
382 }
384 static void
385 serial21285_console_write(struct console *co, const char *s,
386 unsigned int count)
387 {
388 uart_console_write(&serial21285_port, s, count, serial21285_console_putchar);
389 }
391 static void __init
392 serial21285_get_options(struct uart_port *port, int *baud,
393 int *parity, int *bits)
394 {
395 if (*CSR_UARTCON == 1) {
396 unsigned int tmp;
398 tmp = *CSR_H_UBRLCR;
399 switch (tmp & 0x60) {
400 case 0x00:
401 *bits = 5;
402 break;
403 case 0x20:
404 *bits = 6;
405 break;
406 case 0x40:
407 *bits = 7;
408 break;
409 default:
410 case 0x60:
411 *bits = 8;
412 break;
413 }
415 if (tmp & H_UBRLCR_PARENB) {
416 *parity = 'o';
417 if (tmp & H_UBRLCR_PAREVN)
418 *parity = 'e';
419 }
421 tmp = *CSR_L_UBRLCR | (*CSR_M_UBRLCR << 8);
423 *baud = port->uartclk / (16 * (tmp + 1));
424 }
425 }
427 static int __init serial21285_console_setup(struct console *co, char *options)
428 {
429 struct uart_port *port = &serial21285_port;
430 int baud = 9600;
431 int bits = 8;
432 int parity = 'n';
433 int flow = 'n';
435 if (machine_is_personal_server())
436 baud = 57600;
438 /*
439 * Check whether an invalid uart number has been specified, and
440 * if so, search for the first available port that does have
441 * console support.
442 */
443 if (options)
444 uart_parse_options(options, &baud, &parity, &bits, &flow);
445 else
446 serial21285_get_options(port, &baud, &parity, &bits);
448 return uart_set_options(port, co, baud, parity, bits, flow);
449 }
451 static struct uart_driver serial21285_reg;
453 static struct console serial21285_console =
454 {
455 .name = SERIAL_21285_NAME,
456 .write = serial21285_console_write,
457 .device = uart_console_device,
458 .setup = serial21285_console_setup,
459 .flags = CON_PRINTBUFFER,
460 .index = -1,
461 .data = &serial21285_reg,
462 };
464 static int __init rs285_console_init(void)
465 {
466 serial21285_setup_ports();
467 register_console(&serial21285_console);
468 return 0;
469 }
470 console_initcall(rs285_console_init);
472 #define SERIAL_21285_CONSOLE &serial21285_console
473 #else
474 #define SERIAL_21285_CONSOLE NULL
475 #endif
477 static struct uart_driver serial21285_reg = {
478 .owner = THIS_MODULE,
479 .driver_name = "ttyFB",
480 .dev_name = "ttyFB",
481 .major = SERIAL_21285_MAJOR,
482 .minor = SERIAL_21285_MINOR,
483 .nr = 1,
484 .cons = SERIAL_21285_CONSOLE,
485 };
487 static int __init serial21285_init(void)
488 {
489 int ret;
491 printk(KERN_INFO "Serial: 21285 driver $Revision: 1.37 $\n");
493 serial21285_setup_ports();
495 ret = uart_register_driver(&serial21285_reg);
496 if (ret == 0)
497 uart_add_one_port(&serial21285_reg, &serial21285_port);
499 return ret;
500 }
502 static void __exit serial21285_exit(void)
503 {
504 uart_remove_one_port(&serial21285_reg, &serial21285_port);
505 uart_unregister_driver(&serial21285_reg);
506 }
508 module_init(serial21285_init);
509 module_exit(serial21285_exit);
511 MODULE_LICENSE("GPL");
512 MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver $Revision: 1.37 $");
513 MODULE_ALIAS_CHARDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);