ia64/linux-2.6.18-xen.hg

view drivers/serial/netx-serial.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 * drivers/serial/netx-serial.c
3 *
4 * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
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 version 2
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
20 #include <linux/config.h>
22 #if defined(CONFIG_SERIAL_NETX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
23 #define SUPPORT_SYSRQ
24 #endif
26 #include <linux/device.h>
27 #include <linux/module.h>
28 #include <linux/ioport.h>
29 #include <linux/init.h>
30 #include <linux/console.h>
31 #include <linux/sysrq.h>
32 #include <linux/platform_device.h>
33 #include <linux/tty.h>
34 #include <linux/tty_flip.h>
35 #include <linux/serial_core.h>
36 #include <linux/serial.h>
38 #include <asm/io.h>
39 #include <asm/irq.h>
40 #include <asm/hardware.h>
41 #include <asm/arch/netx-regs.h>
43 /* We've been assigned a range on the "Low-density serial ports" major */
44 #define SERIAL_NX_MAJOR 204
45 #define MINOR_START 170
47 #ifdef CONFIG_SERIAL_NETX_CONSOLE
49 enum uart_regs {
50 UART_DR = 0x00,
51 UART_SR = 0x04,
52 UART_LINE_CR = 0x08,
53 UART_BAUDDIV_MSB = 0x0c,
54 UART_BAUDDIV_LSB = 0x10,
55 UART_CR = 0x14,
56 UART_FR = 0x18,
57 UART_IIR = 0x1c,
58 UART_ILPR = 0x20,
59 UART_RTS_CR = 0x24,
60 UART_RTS_LEAD = 0x28,
61 UART_RTS_TRAIL = 0x2c,
62 UART_DRV_ENABLE = 0x30,
63 UART_BRM_CR = 0x34,
64 UART_RXFIFO_IRQLEVEL = 0x38,
65 UART_TXFIFO_IRQLEVEL = 0x3c,
66 };
68 #define SR_FE (1<<0)
69 #define SR_PE (1<<1)
70 #define SR_BE (1<<2)
71 #define SR_OE (1<<3)
73 #define LINE_CR_BRK (1<<0)
74 #define LINE_CR_PEN (1<<1)
75 #define LINE_CR_EPS (1<<2)
76 #define LINE_CR_STP2 (1<<3)
77 #define LINE_CR_FEN (1<<4)
78 #define LINE_CR_5BIT (0<<5)
79 #define LINE_CR_6BIT (1<<5)
80 #define LINE_CR_7BIT (2<<5)
81 #define LINE_CR_8BIT (3<<5)
82 #define LINE_CR_BITS_MASK (3<<5)
84 #define CR_UART_EN (1<<0)
85 #define CR_SIREN (1<<1)
86 #define CR_SIRLP (1<<2)
87 #define CR_MSIE (1<<3)
88 #define CR_RIE (1<<4)
89 #define CR_TIE (1<<5)
90 #define CR_RTIE (1<<6)
91 #define CR_LBE (1<<7)
93 #define FR_CTS (1<<0)
94 #define FR_DSR (1<<1)
95 #define FR_DCD (1<<2)
96 #define FR_BUSY (1<<3)
97 #define FR_RXFE (1<<4)
98 #define FR_TXFF (1<<5)
99 #define FR_RXFF (1<<6)
100 #define FR_TXFE (1<<7)
102 #define IIR_MIS (1<<0)
103 #define IIR_RIS (1<<1)
104 #define IIR_TIS (1<<2)
105 #define IIR_RTIS (1<<3)
106 #define IIR_MASK 0xf
108 #define RTS_CR_AUTO (1<<0)
109 #define RTS_CR_RTS (1<<1)
110 #define RTS_CR_COUNT (1<<2)
111 #define RTS_CR_MOD2 (1<<3)
112 #define RTS_CR_RTS_POL (1<<4)
113 #define RTS_CR_CTS_CTR (1<<5)
114 #define RTS_CR_CTS_POL (1<<6)
115 #define RTS_CR_STICK (1<<7)
117 #define UART_PORT_SIZE 0x40
118 #define DRIVER_NAME "netx-uart"
120 struct netx_port {
121 struct uart_port port;
122 };
124 static void netx_stop_tx(struct uart_port *port)
125 {
126 unsigned int val;
127 val = readl(port->membase + UART_CR);
128 writel(val & ~CR_TIE, port->membase + UART_CR);
129 }
131 static void netx_stop_rx(struct uart_port *port)
132 {
133 unsigned int val;
134 val = readl(port->membase + UART_CR);
135 writel(val & ~CR_RIE, port->membase + UART_CR);
136 }
138 static void netx_enable_ms(struct uart_port *port)
139 {
140 unsigned int val;
141 val = readl(port->membase + UART_CR);
142 writel(val | CR_MSIE, port->membase + UART_CR);
143 }
145 static inline void netx_transmit_buffer(struct uart_port *port)
146 {
147 struct circ_buf *xmit = &port->info->xmit;
149 if (port->x_char) {
150 writel(port->x_char, port->membase + UART_DR);
151 port->icount.tx++;
152 port->x_char = 0;
153 return;
154 }
156 if (uart_tx_stopped(port) || uart_circ_empty(xmit)) {
157 netx_stop_tx(port);
158 return;
159 }
161 do {
162 /* send xmit->buf[xmit->tail]
163 * out the port here */
164 writel(xmit->buf[xmit->tail], port->membase + UART_DR);
165 xmit->tail = (xmit->tail + 1) &
166 (UART_XMIT_SIZE - 1);
167 port->icount.tx++;
168 if (uart_circ_empty(xmit))
169 break;
170 } while (!(readl(port->membase + UART_FR) & FR_TXFF));
172 if (uart_circ_empty(xmit))
173 netx_stop_tx(port);
174 }
176 static void netx_start_tx(struct uart_port *port)
177 {
178 writel(
179 readl(port->membase + UART_CR) | CR_TIE, port->membase + UART_CR);
181 if (!(readl(port->membase + UART_FR) & FR_TXFF))
182 netx_transmit_buffer(port);
183 }
185 static unsigned int netx_tx_empty(struct uart_port *port)
186 {
187 return readl(port->membase + UART_FR) & FR_BUSY ? 0 : TIOCSER_TEMT;
188 }
190 static void netx_txint(struct uart_port *port)
191 {
192 struct circ_buf *xmit = &port->info->xmit;
194 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
195 netx_stop_tx(port);
196 return;
197 }
199 netx_transmit_buffer(port);
201 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
202 uart_write_wakeup(port);
203 }
205 static void netx_rxint(struct uart_port *port, struct pt_regs *regs)
206 {
207 unsigned char rx, flg, status;
208 struct tty_struct *tty = port->info->tty;
210 while (!(readl(port->membase + UART_FR) & FR_RXFE)) {
211 rx = readl(port->membase + UART_DR);
212 flg = TTY_NORMAL;
213 port->icount.rx++;
214 status = readl(port->membase + UART_SR);
215 if (status & SR_BE) {
216 writel(0, port->membase + UART_SR);
217 if (uart_handle_break(port))
218 continue;
219 }
221 if (unlikely(status & (SR_FE | SR_PE | SR_OE))) {
223 if (status & SR_PE)
224 port->icount.parity++;
225 else if (status & SR_FE)
226 port->icount.frame++;
227 if (status & SR_OE)
228 port->icount.overrun++;
230 status &= port->read_status_mask;
232 if (status & SR_BE)
233 flg = TTY_BREAK;
234 else if (status & SR_PE)
235 flg = TTY_PARITY;
236 else if (status & SR_FE)
237 flg = TTY_FRAME;
238 }
240 if (uart_handle_sysrq_char(port, rx, regs))
241 continue;
243 uart_insert_char(port, status, SR_OE, rx, flg);
244 }
246 tty_flip_buffer_push(tty);
247 return;
248 }
250 static irqreturn_t netx_int(int irq, void *dev_id, struct pt_regs *regs)
251 {
252 struct uart_port *port = (struct uart_port *)dev_id;
253 unsigned long flags;
254 unsigned char status;
256 spin_lock_irqsave(&port->lock,flags);
258 status = readl(port->membase + UART_IIR) & IIR_MASK;
259 while (status) {
260 if (status & IIR_RIS)
261 netx_rxint(port, regs);
262 if (status & IIR_TIS)
263 netx_txint(port);
264 if (status & IIR_MIS) {
265 if (readl(port->membase + UART_FR) & FR_CTS)
266 uart_handle_cts_change(port, 1);
267 else
268 uart_handle_cts_change(port, 0);
269 }
270 writel(0, port->membase + UART_IIR);
271 status = readl(port->membase + UART_IIR) & IIR_MASK;
272 }
274 spin_unlock_irqrestore(&port->lock,flags);
275 return IRQ_HANDLED;
276 }
278 static unsigned int netx_get_mctrl(struct uart_port *port)
279 {
280 unsigned int ret = TIOCM_DSR | TIOCM_CAR;
282 if (readl(port->membase + UART_FR) & FR_CTS)
283 ret |= TIOCM_CTS;
285 return ret;
286 }
288 static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl)
289 {
290 unsigned int val;
292 if (mctrl & TIOCM_RTS) {
293 val = readl(port->membase + UART_RTS_CR);
294 writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR);
295 }
296 }
298 static void netx_break_ctl(struct uart_port *port, int break_state)
299 {
300 unsigned int line_cr;
301 spin_lock_irq(&port->lock);
303 line_cr = readl(port->membase + UART_LINE_CR);
304 if (break_state != 0)
305 line_cr |= LINE_CR_BRK;
306 else
307 line_cr &= ~LINE_CR_BRK;
308 writel(line_cr, port->membase + UART_LINE_CR);
310 spin_unlock_irq(&port->lock);
311 }
313 static int netx_startup(struct uart_port *port)
314 {
315 int ret;
317 ret = request_irq(port->irq, netx_int, 0,
318 DRIVER_NAME, port);
319 if (ret) {
320 dev_err(port->dev, "unable to grab irq%d\n",port->irq);
321 goto exit;
322 }
324 writel(readl(port->membase + UART_LINE_CR) | LINE_CR_FEN,
325 port->membase + UART_LINE_CR);
327 writel(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE | CR_UART_EN,
328 port->membase + UART_CR);
330 exit:
331 return ret;
332 }
334 static void netx_shutdown(struct uart_port *port)
335 {
336 writel(0, port->membase + UART_CR) ;
338 free_irq(port->irq, port);
339 }
341 static void
342 netx_set_termios(struct uart_port *port, struct termios *termios,
343 struct termios *old)
344 {
345 unsigned int baud, quot;
346 unsigned char old_cr;
347 unsigned char line_cr = LINE_CR_FEN;
348 unsigned char rts_cr = 0;
350 switch (termios->c_cflag & CSIZE) {
351 case CS5:
352 line_cr |= LINE_CR_5BIT;
353 break;
354 case CS6:
355 line_cr |= LINE_CR_6BIT;
356 break;
357 case CS7:
358 line_cr |= LINE_CR_7BIT;
359 break;
360 case CS8:
361 line_cr |= LINE_CR_8BIT;
362 break;
363 }
365 if (termios->c_cflag & CSTOPB)
366 line_cr |= LINE_CR_STP2;
368 if (termios->c_cflag & PARENB) {
369 line_cr |= LINE_CR_PEN;
370 if (!(termios->c_cflag & PARODD))
371 line_cr |= LINE_CR_EPS;
372 }
374 if (termios->c_cflag & CRTSCTS)
375 rts_cr = RTS_CR_AUTO | RTS_CR_CTS_CTR | RTS_CR_RTS_POL;
377 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
378 quot = baud * 4096;
379 quot /= 1000;
380 quot *= 256;
381 quot /= 100000;
383 spin_lock_irq(&port->lock);
385 uart_update_timeout(port, termios->c_cflag, baud);
387 old_cr = readl(port->membase + UART_CR);
389 /* disable interrupts */
390 writel(old_cr & ~(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE),
391 port->membase + UART_CR);
393 /* drain transmitter */
394 while (readl(port->membase + UART_FR) & FR_BUSY);
396 /* disable UART */
397 writel(old_cr & ~CR_UART_EN, port->membase + UART_CR);
399 /* modem status interrupts */
400 old_cr &= ~CR_MSIE;
401 if (UART_ENABLE_MS(port, termios->c_cflag))
402 old_cr |= CR_MSIE;
404 writel((quot>>8) & 0xff, port->membase + UART_BAUDDIV_MSB);
405 writel(quot & 0xff, port->membase + UART_BAUDDIV_LSB);
406 writel(line_cr, port->membase + UART_LINE_CR);
408 writel(rts_cr, port->membase + UART_RTS_CR);
410 /*
411 * Characters to ignore
412 */
413 port->ignore_status_mask = 0;
414 if (termios->c_iflag & IGNPAR)
415 port->ignore_status_mask |= SR_PE;
416 if (termios->c_iflag & IGNBRK) {
417 port->ignore_status_mask |= SR_BE;
418 /*
419 * If we're ignoring parity and break indicators,
420 * ignore overruns too (for real raw support).
421 */
422 if (termios->c_iflag & IGNPAR)
423 port->ignore_status_mask |= SR_PE;
424 }
426 port->read_status_mask = 0;
427 if (termios->c_iflag & (BRKINT | PARMRK))
428 port->read_status_mask |= SR_BE;
429 if (termios->c_iflag & INPCK)
430 port->read_status_mask |= SR_PE | SR_FE;
432 writel(old_cr, port->membase + UART_CR);
434 spin_unlock_irq(&port->lock);
435 }
437 static const char *netx_type(struct uart_port *port)
438 {
439 return port->type == PORT_NETX ? "NETX" : NULL;
440 }
442 static void netx_release_port(struct uart_port *port)
443 {
444 release_mem_region(port->mapbase, UART_PORT_SIZE);
445 }
447 static int netx_request_port(struct uart_port *port)
448 {
449 return request_mem_region(port->mapbase, UART_PORT_SIZE,
450 DRIVER_NAME) != NULL ? 0 : -EBUSY;
451 }
453 static void netx_config_port(struct uart_port *port, int flags)
454 {
455 if (flags & UART_CONFIG_TYPE && netx_request_port(port) == 0)
456 port->type = PORT_NETX;
457 }
459 static int
460 netx_verify_port(struct uart_port *port, struct serial_struct *ser)
461 {
462 int ret = 0;
464 if (ser->type != PORT_UNKNOWN && ser->type != PORT_NETX)
465 ret = -EINVAL;
467 return ret;
468 }
470 static struct uart_ops netx_pops = {
471 .tx_empty = netx_tx_empty,
472 .set_mctrl = netx_set_mctrl,
473 .get_mctrl = netx_get_mctrl,
474 .stop_tx = netx_stop_tx,
475 .start_tx = netx_start_tx,
476 .stop_rx = netx_stop_rx,
477 .enable_ms = netx_enable_ms,
478 .break_ctl = netx_break_ctl,
479 .startup = netx_startup,
480 .shutdown = netx_shutdown,
481 .set_termios = netx_set_termios,
482 .type = netx_type,
483 .release_port = netx_release_port,
484 .request_port = netx_request_port,
485 .config_port = netx_config_port,
486 .verify_port = netx_verify_port,
487 };
489 static struct netx_port netx_ports[] = {
490 {
491 .port = {
492 .type = PORT_NETX,
493 .iotype = UPIO_MEM,
494 .membase = (char __iomem *)io_p2v(NETX_PA_UART0),
495 .mapbase = NETX_PA_UART0,
496 .irq = NETX_IRQ_UART0,
497 .uartclk = 100000000,
498 .fifosize = 16,
499 .flags = UPF_BOOT_AUTOCONF,
500 .ops = &netx_pops,
501 .line = 0,
502 },
503 }, {
504 .port = {
505 .type = PORT_NETX,
506 .iotype = UPIO_MEM,
507 .membase = (char __iomem *)io_p2v(NETX_PA_UART1),
508 .mapbase = NETX_PA_UART1,
509 .irq = NETX_IRQ_UART1,
510 .uartclk = 100000000,
511 .fifosize = 16,
512 .flags = UPF_BOOT_AUTOCONF,
513 .ops = &netx_pops,
514 .line = 1,
515 },
516 }, {
517 .port = {
518 .type = PORT_NETX,
519 .iotype = UPIO_MEM,
520 .membase = (char __iomem *)io_p2v(NETX_PA_UART2),
521 .mapbase = NETX_PA_UART2,
522 .irq = NETX_IRQ_UART2,
523 .uartclk = 100000000,
524 .fifosize = 16,
525 .flags = UPF_BOOT_AUTOCONF,
526 .ops = &netx_pops,
527 .line = 2,
528 },
529 }
530 };
532 static void netx_console_putchar(struct uart_port *port, int ch)
533 {
534 while (readl(port->membase + UART_FR) & FR_BUSY);
535 writel(ch, port->membase + UART_DR);
536 }
538 static void
539 netx_console_write(struct console *co, const char *s, unsigned int count)
540 {
541 struct uart_port *port = &netx_ports[co->index].port;
542 unsigned char cr_save;
544 cr_save = readl(port->membase + UART_CR);
545 writel(cr_save | CR_UART_EN, port->membase + UART_CR);
547 uart_console_write(port, s, count, netx_console_putchar);
549 while (readl(port->membase + UART_FR) & FR_BUSY);
550 writel(cr_save, port->membase + UART_CR);
551 }
553 static void __init
554 netx_console_get_options(struct uart_port *port, int *baud,
555 int *parity, int *bits, int *flow)
556 {
557 unsigned char line_cr;
559 *baud = (readl(port->membase + UART_BAUDDIV_MSB) << 8) |
560 readl(port->membase + UART_BAUDDIV_LSB);
561 *baud *= 1000;
562 *baud /= 4096;
563 *baud *= 1000;
564 *baud /= 256;
565 *baud *= 100;
567 line_cr = readl(port->membase + UART_LINE_CR);
568 *parity = 'n';
569 if (line_cr & LINE_CR_PEN) {
570 if (line_cr & LINE_CR_EPS)
571 *parity = 'e';
572 else
573 *parity = 'o';
574 }
576 switch (line_cr & LINE_CR_BITS_MASK) {
577 case LINE_CR_8BIT:
578 *bits = 8;
579 break;
580 case LINE_CR_7BIT:
581 *bits = 7;
582 break;
583 case LINE_CR_6BIT:
584 *bits = 6;
585 break;
586 case LINE_CR_5BIT:
587 *bits = 5;
588 break;
589 }
591 if (readl(port->membase + UART_RTS_CR) & RTS_CR_AUTO)
592 *flow = 'r';
593 }
595 static int __init
596 netx_console_setup(struct console *co, char *options)
597 {
598 struct netx_port *sport;
599 int baud = 9600;
600 int bits = 8;
601 int parity = 'n';
602 int flow = 'n';
604 /*
605 * Check whether an invalid uart number has been specified, and
606 * if so, search for the first available port that does have
607 * console support.
608 */
609 if (co->index == -1 || co->index >= ARRAY_SIZE(netx_ports))
610 co->index = 0;
611 sport = &netx_ports[co->index];
613 if (options) {
614 uart_parse_options(options, &baud, &parity, &bits, &flow);
615 } else {
616 /* if the UART is enabled, assume it has been correctly setup
617 * by the bootloader and get the options
618 */
619 if (readl(sport->port.membase + UART_CR) & CR_UART_EN) {
620 netx_console_get_options(&sport->port, &baud,
621 &parity, &bits, &flow);
622 }
624 }
626 return uart_set_options(&sport->port, co, baud, parity, bits, flow);
627 }
629 static struct uart_driver netx_reg;
630 static struct console netx_console = {
631 .name = "ttyNX",
632 .write = netx_console_write,
633 .device = uart_console_device,
634 .setup = netx_console_setup,
635 .flags = CON_PRINTBUFFER,
636 .index = -1,
637 .data = &netx_reg,
638 };
640 static int __init netx_console_init(void)
641 {
642 register_console(&netx_console);
643 return 0;
644 }
645 console_initcall(netx_console_init);
647 #define NETX_CONSOLE &netx_console
648 #else
649 #define NETX_CONSOLE NULL
650 #endif
652 static struct uart_driver netx_reg = {
653 .owner = THIS_MODULE,
654 .driver_name = DRIVER_NAME,
655 .dev_name = "ttyNX",
656 .major = SERIAL_NX_MAJOR,
657 .minor = MINOR_START,
658 .nr = ARRAY_SIZE(netx_ports),
659 .cons = NETX_CONSOLE,
660 };
662 static int serial_netx_suspend(struct platform_device *pdev, pm_message_t state)
663 {
664 struct netx_port *sport = platform_get_drvdata(pdev);
666 if (sport)
667 uart_suspend_port(&netx_reg, &sport->port);
669 return 0;
670 }
672 static int serial_netx_resume(struct platform_device *pdev)
673 {
674 struct netx_port *sport = platform_get_drvdata(pdev);
676 if (sport)
677 uart_resume_port(&netx_reg, &sport->port);
679 return 0;
680 }
682 static int serial_netx_probe(struct platform_device *pdev)
683 {
684 struct uart_port *port = &netx_ports[pdev->id].port;
686 dev_info(&pdev->dev, "initialising\n");
688 port->dev = &pdev->dev;
690 writel(1, port->membase + UART_RXFIFO_IRQLEVEL);
691 uart_add_one_port(&netx_reg, &netx_ports[pdev->id].port);
692 platform_set_drvdata(pdev, &netx_ports[pdev->id]);
694 return 0;
695 }
697 static int serial_netx_remove(struct platform_device *pdev)
698 {
699 struct netx_port *sport = platform_get_drvdata(pdev);
701 platform_set_drvdata(pdev, NULL);
703 if (sport)
704 uart_remove_one_port(&netx_reg, &sport->port);
706 return 0;
707 }
709 static struct platform_driver serial_netx_driver = {
710 .probe = serial_netx_probe,
711 .remove = serial_netx_remove,
713 .suspend = serial_netx_suspend,
714 .resume = serial_netx_resume,
716 .driver = {
717 .name = DRIVER_NAME,
718 },
719 };
721 static int __init netx_serial_init(void)
722 {
723 int ret;
725 printk(KERN_INFO "Serial: NetX driver\n");
727 ret = uart_register_driver(&netx_reg);
728 if (ret)
729 return ret;
731 ret = platform_driver_register(&serial_netx_driver);
732 if (ret != 0)
733 uart_unregister_driver(&netx_reg);
735 return 0;
736 }
738 static void __exit netx_serial_exit(void)
739 {
740 platform_driver_unregister(&serial_netx_driver);
741 uart_unregister_driver(&netx_reg);
742 }
744 module_init(netx_serial_init);
745 module_exit(netx_serial_exit);
747 MODULE_AUTHOR("Sascha Hauer");
748 MODULE_DESCRIPTION("NetX serial port driver");
749 MODULE_LICENSE("GPL");