aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/sunzilog.c
diff options
context:
space:
mode:
authorMartin Habets <errandir_news@mph.eclipse.co.uk>2007-12-11 06:37:04 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-12-12 10:36:34 -0500
commit58d784a5c754cd66ecd4791222162504d3c16c74 (patch)
treea25670e8dd1569cf5084af790873b246f45134c3 /drivers/serial/sunzilog.c
parent4af75653031c6d454b4ace47c1536f0d2e727e3e (diff)
[SERIAL] sparc: Infrastructure to fix section mismatch bugs.
This patch against 2.6.23 sparc-2.6.git contains a number of minor cleanups of the sparc serial drivers. Initially I fixed this build warning: WARNING: vmlinux.o(.text+0x107a2c): Section mismatch: reference to .init.text:add_preferred_console (between 'sunserial_console_match' and 'sunserial_console_termios') which is done by declaring sunserial_console_match() as __init. This resulted in build warnings on sunserial_current_minor. To resolve these the variable was changed so it is no longer global, and to hide operations on it inside 2 new functions. These functions handle the UART minor handling code that is common to all sparc serial drivers. These changes allowed to clean up the uart counters in all the sparc serial drivers, and the administration of minor device numbers. Lastly, sunserial_console_termios() does not need to be exported since it is only called from non-modular code. Sadly, the following build warning still exists: WARNING: vmlinux.o(__ksymtab+0x2910): Section mismatch: reference to .init.text:sunserial_console_match (between '__ksymtab_sunserial_console_match' and '__ksymtab_sunserial_unregister_minors') This could be resolved by not exporting sunserial_console_match(), but this is not possible at the moment because it is being called from modular code. On the other hand, this is a bogus warning since it comes from a ksymtab section. Signed-off-by: Martin Habets <errandir_news@mph.eclipse.co.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/serial/sunzilog.c')
-rw-r--r--drivers/serial/sunzilog.c41
1 files changed, 16 insertions, 25 deletions
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 283bef0d24cb..cb2e40506379 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -63,10 +63,6 @@
63 readb(&((__channel)->control)) 63 readb(&((__channel)->control))
64#endif 64#endif
65 65
66static int num_sunzilog;
67#define NUM_SUNZILOG num_sunzilog
68#define NUM_CHANNELS (NUM_SUNZILOG * 2)
69
70#define ZS_CLOCK 4915200 /* Zilog input clock rate. */ 66#define ZS_CLOCK 4915200 /* Zilog input clock rate. */
71#define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */ 67#define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */
72 68
@@ -1031,18 +1027,19 @@ static struct uart_driver sunzilog_reg = {
1031 .major = TTY_MAJOR, 1027 .major = TTY_MAJOR,
1032}; 1028};
1033 1029
1034static int __init sunzilog_alloc_tables(void) 1030static int __init sunzilog_alloc_tables(int num_sunzilog)
1035{ 1031{
1036 struct uart_sunzilog_port *up; 1032 struct uart_sunzilog_port *up;
1037 unsigned long size; 1033 unsigned long size;
1034 int num_channels = num_sunzilog * 2;
1038 int i; 1035 int i;
1039 1036
1040 size = NUM_CHANNELS * sizeof(struct uart_sunzilog_port); 1037 size = num_channels * sizeof(struct uart_sunzilog_port);
1041 sunzilog_port_table = kzalloc(size, GFP_KERNEL); 1038 sunzilog_port_table = kzalloc(size, GFP_KERNEL);
1042 if (!sunzilog_port_table) 1039 if (!sunzilog_port_table)
1043 return -ENOMEM; 1040 return -ENOMEM;
1044 1041
1045 for (i = 0; i < NUM_CHANNELS; i++) { 1042 for (i = 0; i < num_channels; i++) {
1046 up = &sunzilog_port_table[i]; 1043 up = &sunzilog_port_table[i];
1047 1044
1048 spin_lock_init(&up->port.lock); 1045 spin_lock_init(&up->port.lock);
@@ -1050,13 +1047,13 @@ static int __init sunzilog_alloc_tables(void)
1050 if (i == 0) 1047 if (i == 0)
1051 sunzilog_irq_chain = up; 1048 sunzilog_irq_chain = up;
1052 1049
1053 if (i < NUM_CHANNELS - 1) 1050 if (i < num_channels - 1)
1054 up->next = up + 1; 1051 up->next = up + 1;
1055 else 1052 else
1056 up->next = NULL; 1053 up->next = NULL;
1057 } 1054 }
1058 1055
1059 size = NUM_SUNZILOG * sizeof(struct zilog_layout __iomem *); 1056 size = num_sunzilog * sizeof(struct zilog_layout __iomem *);
1060 sunzilog_chip_regs = kzalloc(size, GFP_KERNEL); 1057 sunzilog_chip_regs = kzalloc(size, GFP_KERNEL);
1061 if (!sunzilog_chip_regs) { 1058 if (!sunzilog_chip_regs) {
1062 kfree(sunzilog_port_table); 1059 kfree(sunzilog_port_table);
@@ -1496,34 +1493,28 @@ static int __init sunzilog_init(void)
1496 struct device_node *dp; 1493 struct device_node *dp;
1497 int err, uart_count; 1494 int err, uart_count;
1498 int num_keybms; 1495 int num_keybms;
1496 int num_sunzilog = 0;
1499 1497
1500 NUM_SUNZILOG = 0;
1501 num_keybms = 0; 1498 num_keybms = 0;
1502 for_each_node_by_name(dp, "zs") { 1499 for_each_node_by_name(dp, "zs") {
1503 NUM_SUNZILOG++; 1500 num_sunzilog++;
1504 if (of_find_property(dp, "keyboard", NULL)) 1501 if (of_find_property(dp, "keyboard", NULL))
1505 num_keybms++; 1502 num_keybms++;
1506 } 1503 }
1507 1504
1508 uart_count = 0; 1505 uart_count = 0;
1509 if (NUM_SUNZILOG) { 1506 if (num_sunzilog) {
1510 int uart_count; 1507 int uart_count;
1511 1508
1512 err = sunzilog_alloc_tables(); 1509 err = sunzilog_alloc_tables(num_sunzilog);
1513 if (err) 1510 if (err)
1514 goto out; 1511 goto out;
1515 1512
1516 uart_count = (NUM_SUNZILOG * 2) - (2 * num_keybms); 1513 uart_count = (num_sunzilog * 2) - (2 * num_keybms);
1517 1514
1518 sunzilog_reg.nr = uart_count; 1515 err = sunserial_register_minors(&sunzilog_reg, uart_count);
1519 sunzilog_reg.minor = sunserial_current_minor;
1520 err = uart_register_driver(&sunzilog_reg);
1521 if (err) 1516 if (err)
1522 goto out_free_tables; 1517 goto out_free_tables;
1523
1524 sunzilog_reg.tty_driver->name_base = sunzilog_reg.minor - 64;
1525
1526 sunserial_current_minor += uart_count;
1527 } 1518 }
1528 1519
1529 err = of_register_driver(&zs_driver, &of_bus_type); 1520 err = of_register_driver(&zs_driver, &of_bus_type);
@@ -1557,8 +1548,8 @@ out_unregister_driver:
1557 of_unregister_driver(&zs_driver); 1548 of_unregister_driver(&zs_driver);
1558 1549
1559out_unregister_uart: 1550out_unregister_uart:
1560 if (NUM_SUNZILOG) { 1551 if (num_sunzilog) {
1561 uart_unregister_driver(&sunzilog_reg); 1552 sunserial_unregister_minors(&sunzilog_reg, num_sunzilog);
1562 sunzilog_reg.cons = NULL; 1553 sunzilog_reg.cons = NULL;
1563 } 1554 }
1564 1555
@@ -1590,8 +1581,8 @@ static void __exit sunzilog_exit(void)
1590 zilog_irq = -1; 1581 zilog_irq = -1;
1591 } 1582 }
1592 1583
1593 if (NUM_SUNZILOG) { 1584 if (sunzilog_reg.nr) {
1594 uart_unregister_driver(&sunzilog_reg); 1585 sunserial_unregister_minors(&sunzilog_reg, sunzilog_reg.nr);
1595 sunzilog_free_tables(); 1586 sunzilog_free_tables();
1596 } 1587 }
1597} 1588}