aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/serial/suncore.c33
-rw-r--r--drivers/serial/suncore.h3
-rw-r--r--drivers/serial/sunhv.c14
-rw-r--r--drivers/serial/sunsab.c16
-rw-r--r--drivers/serial/sunsu.c16
-rw-r--r--drivers/serial/sunzilog.c41
6 files changed, 58 insertions, 65 deletions
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
index 70a09a3d5af0..707c5b03bce9 100644
--- a/drivers/serial/suncore.c
+++ b/drivers/serial/suncore.c
@@ -23,11 +23,36 @@
23 23
24#include "suncore.h" 24#include "suncore.h"
25 25
26int sunserial_current_minor = 64; 26static int sunserial_current_minor = 64;
27 27
28EXPORT_SYMBOL(sunserial_current_minor); 28int sunserial_register_minors(struct uart_driver *drv, int count)
29{
30 int err = 0;
31
32 drv->minor = sunserial_current_minor;
33 drv->nr += count;
34 /* Register the driver on the first call */
35 if (drv->nr == count)
36 err = uart_register_driver(drv);
37 if (err == 0) {
38 sunserial_current_minor += count;
39 drv->tty_driver->name_base = drv->minor - 64;
40 }
41 return err;
42}
43EXPORT_SYMBOL(sunserial_register_minors);
44
45void sunserial_unregister_minors(struct uart_driver *drv, int count)
46{
47 drv->nr -= count;
48 sunserial_current_minor -= count;
49
50 if (drv->nr == 0)
51 uart_unregister_driver(drv);
52}
53EXPORT_SYMBOL(sunserial_unregister_minors);
29 54
30int sunserial_console_match(struct console *con, struct device_node *dp, 55int __init sunserial_console_match(struct console *con, struct device_node *dp,
31 struct uart_driver *drv, int line) 56 struct uart_driver *drv, int line)
32{ 57{
33 int off; 58 int off;
@@ -133,8 +158,6 @@ sunserial_console_termios(struct console *con)
133 con->cflag = cflag; 158 con->cflag = cflag;
134} 159}
135 160
136EXPORT_SYMBOL(sunserial_console_termios);
137
138/* Sun serial MOUSE auto baud rate detection. */ 161/* Sun serial MOUSE auto baud rate detection. */
139static struct mouse_baud_cflag { 162static struct mouse_baud_cflag {
140 int baud; 163 int baud;
diff --git a/drivers/serial/suncore.h b/drivers/serial/suncore.h
index 829d7d65d6db..042668aa602e 100644
--- a/drivers/serial/suncore.h
+++ b/drivers/serial/suncore.h
@@ -22,7 +22,8 @@
22extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *); 22extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *);
23extern int suncore_mouse_baud_detection(unsigned char, int); 23extern int suncore_mouse_baud_detection(unsigned char, int);
24 24
25extern int sunserial_current_minor; 25extern int sunserial_register_minors(struct uart_driver *, int);
26extern void sunserial_unregister_minors(struct uart_driver *, int);
26 27
27extern int sunserial_console_match(struct console *, struct device_node *, 28extern int sunserial_console_match(struct console *, struct device_node *,
28 struct uart_driver *, int); 29 struct uart_driver *, int);
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index 8ff900b09811..be0fe152891b 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -562,16 +562,10 @@ static int __devinit hv_probe(struct of_device *op, const struct of_device_id *m
562 562
563 port->dev = &op->dev; 563 port->dev = &op->dev;
564 564
565 sunhv_reg.minor = sunserial_current_minor; 565 err = sunserial_register_minors(&sunhv_reg, 1);
566 sunhv_reg.nr = 1;
567
568 err = uart_register_driver(&sunhv_reg);
569 if (err) 566 if (err)
570 goto out_free_con_read_page; 567 goto out_free_con_read_page;
571 568
572 sunhv_reg.tty_driver->name_base = sunhv_reg.minor - 64;
573 sunserial_current_minor += 1;
574
575 sunserial_console_match(&sunhv_console, op->node, 569 sunserial_console_match(&sunhv_console, op->node,
576 &sunhv_reg, port->line); 570 &sunhv_reg, port->line);
577 571
@@ -591,8 +585,7 @@ out_remove_port:
591 uart_remove_one_port(&sunhv_reg, port); 585 uart_remove_one_port(&sunhv_reg, port);
592 586
593out_unregister_driver: 587out_unregister_driver:
594 sunserial_current_minor -= 1; 588 sunserial_unregister_minors(&sunhv_reg, 1);
595 uart_unregister_driver(&sunhv_reg);
596 589
597out_free_con_read_page: 590out_free_con_read_page:
598 kfree(con_read_page); 591 kfree(con_read_page);
@@ -614,8 +607,7 @@ static int __devexit hv_remove(struct of_device *dev)
614 607
615 uart_remove_one_port(&sunhv_reg, port); 608 uart_remove_one_port(&sunhv_reg, port);
616 609
617 sunserial_current_minor -= 1; 610 sunserial_unregister_minors(&sunhv_reg, 1);
618 uart_unregister_driver(&sunhv_reg);
619 611
620 kfree(port); 612 kfree(port);
621 sunhv_port = NULL; 613 sunhv_port = NULL;
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index ff610c23314b..543f93741e6f 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -832,7 +832,6 @@ static struct uart_driver sunsab_reg = {
832}; 832};
833 833
834static struct uart_sunsab_port *sunsab_ports; 834static struct uart_sunsab_port *sunsab_ports;
835static int num_channels;
836 835
837#ifdef CONFIG_SERIAL_SUNSAB_CONSOLE 836#ifdef CONFIG_SERIAL_SUNSAB_CONSOLE
838 837
@@ -1102,8 +1101,8 @@ static int __init sunsab_init(void)
1102{ 1101{
1103 struct device_node *dp; 1102 struct device_node *dp;
1104 int err; 1103 int err;
1104 int num_channels = 0;
1105 1105
1106 num_channels = 0;
1107 for_each_node_by_name(dp, "se") 1106 for_each_node_by_name(dp, "se")
1108 num_channels += 2; 1107 num_channels += 2;
1109 for_each_node_by_name(dp, "serial") { 1108 for_each_node_by_name(dp, "serial") {
@@ -1117,20 +1116,14 @@ static int __init sunsab_init(void)
1117 if (!sunsab_ports) 1116 if (!sunsab_ports)
1118 return -ENOMEM; 1117 return -ENOMEM;
1119 1118
1120 sunsab_reg.minor = sunserial_current_minor;
1121 sunsab_reg.nr = num_channels;
1122 sunsab_reg.cons = SUNSAB_CONSOLE(); 1119 sunsab_reg.cons = SUNSAB_CONSOLE();
1123 1120 err = sunserial_register_minors(&sunsab_reg, num_channels);
1124 err = uart_register_driver(&sunsab_reg);
1125 if (err) { 1121 if (err) {
1126 kfree(sunsab_ports); 1122 kfree(sunsab_ports);
1127 sunsab_ports = NULL; 1123 sunsab_ports = NULL;
1128 1124
1129 return err; 1125 return err;
1130 } 1126 }
1131
1132 sunsab_reg.tty_driver->name_base = sunsab_reg.minor - 64;
1133 sunserial_current_minor += num_channels;
1134 } 1127 }
1135 1128
1136 return of_register_driver(&sab_driver, &of_bus_type); 1129 return of_register_driver(&sab_driver, &of_bus_type);
@@ -1139,9 +1132,8 @@ static int __init sunsab_init(void)
1139static void __exit sunsab_exit(void) 1132static void __exit sunsab_exit(void)
1140{ 1133{
1141 of_unregister_driver(&sab_driver); 1134 of_unregister_driver(&sab_driver);
1142 if (num_channels) { 1135 if (sunsab_reg.nr) {
1143 sunserial_current_minor -= num_channels; 1136 sunserial_unregister_minors(&sunsab_reg, sunsab_reg.nr);
1144 uart_unregister_driver(&sunsab_reg);
1145 } 1137 }
1146 1138
1147 kfree(sunsab_ports); 1139 kfree(sunsab_ports);
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index e074943feff5..4e2302d43ab1 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1528,14 +1528,12 @@ static struct of_platform_driver su_driver = {
1528 .remove = __devexit_p(su_remove), 1528 .remove = __devexit_p(su_remove),
1529}; 1529};
1530 1530
1531static int num_uart;
1532
1533static int __init sunsu_init(void) 1531static int __init sunsu_init(void)
1534{ 1532{
1535 struct device_node *dp; 1533 struct device_node *dp;
1536 int err; 1534 int err;
1535 int num_uart = 0;
1537 1536
1538 num_uart = 0;
1539 for_each_node_by_name(dp, "su") { 1537 for_each_node_by_name(dp, "su") {
1540 if (su_get_type(dp) == SU_PORT_PORT) 1538 if (su_get_type(dp) == SU_PORT_PORT)
1541 num_uart++; 1539 num_uart++;
@@ -1552,26 +1550,22 @@ static int __init sunsu_init(void)
1552 } 1550 }
1553 1551
1554 if (num_uart) { 1552 if (num_uart) {
1555 sunsu_reg.minor = sunserial_current_minor; 1553 err = sunserial_register_minors(&sunsu_reg, num_uart);
1556 sunsu_reg.nr = num_uart;
1557 err = uart_register_driver(&sunsu_reg);
1558 if (err) 1554 if (err)
1559 return err; 1555 return err;
1560 sunsu_reg.tty_driver->name_base = sunsu_reg.minor - 64;
1561 sunserial_current_minor += num_uart;
1562 } 1556 }
1563 1557
1564 err = of_register_driver(&su_driver, &of_bus_type); 1558 err = of_register_driver(&su_driver, &of_bus_type);
1565 if (err && num_uart) 1559 if (err && num_uart)
1566 uart_unregister_driver(&sunsu_reg); 1560 sunserial_unregister_minors(&sunsu_reg, num_uart);
1567 1561
1568 return err; 1562 return err;
1569} 1563}
1570 1564
1571static void __exit sunsu_exit(void) 1565static void __exit sunsu_exit(void)
1572{ 1566{
1573 if (num_uart) 1567 if (sunsu_reg.nr)
1574 uart_unregister_driver(&sunsu_reg); 1568 sunserial_unregister_minors(&sunsu_reg, sunsu_reg.nr);
1575} 1569}
1576 1570
1577module_init(sunsu_init); 1571module_init(sunsu_init);
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}