diff options
author | Martin Habets <errandir_news@mph.eclipse.co.uk> | 2007-12-11 06:37:04 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-12-12 10:36:34 -0500 |
commit | 58d784a5c754cd66ecd4791222162504d3c16c74 (patch) | |
tree | a25670e8dd1569cf5084af790873b246f45134c3 /drivers/serial/sunzilog.c | |
parent | 4af75653031c6d454b4ace47c1536f0d2e727e3e (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.c | 41 |
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 | ||
66 | static 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 | ||
1034 | static int __init sunzilog_alloc_tables(void) | 1030 | static 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 | ||
1559 | out_unregister_uart: | 1550 | out_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 | } |