diff options
author | Alan Cox <alan@redhat.com> | 2008-08-19 23:49:40 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-16 10:52:02 -0400 |
commit | 25db8ad5c56700e7716fe23426b16c5e3b1674b4 (patch) | |
tree | a4f4864f7fb83b091289f4ef73279d8d8b9f34c6 /drivers/serial/8250.c | |
parent | 5fef06e8c8c52aa7170dbbb068aa996d83738d38 (diff) |
serial, 8250: remove NR_IRQ usage
Works on my test box with a quick test.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/serial/8250.c')
-rw-r--r-- | drivers/serial/8250.c | 67 |
1 files changed, 55 insertions, 12 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index d3ca7d32abe0..c66bb44c4747 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -156,11 +156,15 @@ struct uart_8250_port { | |||
156 | }; | 156 | }; |
157 | 157 | ||
158 | struct irq_info { | 158 | struct irq_info { |
159 | spinlock_t lock; | 159 | struct hlist_node node; |
160 | int irq; | ||
161 | spinlock_t lock; /* Protects list not the hash */ | ||
160 | struct list_head *head; | 162 | struct list_head *head; |
161 | }; | 163 | }; |
162 | 164 | ||
163 | static struct irq_info irq_lists[NR_IRQS]; | 165 | #define NR_IRQ_HASH 32 /* Can be adjusted later */ |
166 | static struct hlist_head irq_lists[NR_IRQ_HASH]; | ||
167 | static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */ | ||
164 | 168 | ||
165 | /* | 169 | /* |
166 | * Here we define the default xmit fifo size used for each type of UART. | 170 | * Here we define the default xmit fifo size used for each type of UART. |
@@ -1545,15 +1549,43 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up) | |||
1545 | BUG_ON(i->head != &up->list); | 1549 | BUG_ON(i->head != &up->list); |
1546 | i->head = NULL; | 1550 | i->head = NULL; |
1547 | } | 1551 | } |
1548 | |||
1549 | spin_unlock_irq(&i->lock); | 1552 | spin_unlock_irq(&i->lock); |
1553 | /* List empty so throw away the hash node */ | ||
1554 | if (i->head == NULL) { | ||
1555 | hlist_del(&i->node); | ||
1556 | kfree(i); | ||
1557 | } | ||
1550 | } | 1558 | } |
1551 | 1559 | ||
1552 | static int serial_link_irq_chain(struct uart_8250_port *up) | 1560 | static int serial_link_irq_chain(struct uart_8250_port *up) |
1553 | { | 1561 | { |
1554 | struct irq_info *i = irq_lists + up->port.irq; | 1562 | struct hlist_head *h; |
1563 | struct hlist_node *n; | ||
1564 | struct irq_info *i; | ||
1555 | int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0; | 1565 | int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0; |
1556 | 1566 | ||
1567 | mutex_lock(&hash_mutex); | ||
1568 | |||
1569 | h = &irq_lists[up->port.irq % NR_IRQ_HASH]; | ||
1570 | |||
1571 | hlist_for_each(n, h) { | ||
1572 | i = hlist_entry(n, struct irq_info, node); | ||
1573 | if (i->irq == up->port.irq) | ||
1574 | break; | ||
1575 | } | ||
1576 | |||
1577 | if (n == NULL) { | ||
1578 | i = kzalloc(sizeof(struct irq_info), GFP_KERNEL); | ||
1579 | if (i == NULL) { | ||
1580 | mutex_unlock(&hash_mutex); | ||
1581 | return -ENOMEM; | ||
1582 | } | ||
1583 | spin_lock_init(&i->lock); | ||
1584 | i->irq = up->port.irq; | ||
1585 | hlist_add_head(&i->node, h); | ||
1586 | } | ||
1587 | mutex_unlock(&hash_mutex); | ||
1588 | |||
1557 | spin_lock_irq(&i->lock); | 1589 | spin_lock_irq(&i->lock); |
1558 | 1590 | ||
1559 | if (i->head) { | 1591 | if (i->head) { |
@@ -1577,14 +1609,28 @@ static int serial_link_irq_chain(struct uart_8250_port *up) | |||
1577 | 1609 | ||
1578 | static void serial_unlink_irq_chain(struct uart_8250_port *up) | 1610 | static void serial_unlink_irq_chain(struct uart_8250_port *up) |
1579 | { | 1611 | { |
1580 | struct irq_info *i = irq_lists + up->port.irq; | 1612 | struct irq_info *i; |
1613 | struct hlist_node *n; | ||
1614 | struct hlist_head *h; | ||
1581 | 1615 | ||
1616 | mutex_lock(&hash_mutex); | ||
1617 | |||
1618 | h = &irq_lists[up->port.irq % NR_IRQ_HASH]; | ||
1619 | |||
1620 | hlist_for_each(n, h) { | ||
1621 | i = hlist_entry(n, struct irq_info, node); | ||
1622 | if (i->irq == up->port.irq) | ||
1623 | break; | ||
1624 | } | ||
1625 | |||
1626 | BUG_ON(n == NULL); | ||
1582 | BUG_ON(i->head == NULL); | 1627 | BUG_ON(i->head == NULL); |
1583 | 1628 | ||
1584 | if (list_empty(i->head)) | 1629 | if (list_empty(i->head)) |
1585 | free_irq(up->port.irq, i); | 1630 | free_irq(up->port.irq, i); |
1586 | 1631 | ||
1587 | serial_do_unlink(i, up); | 1632 | serial_do_unlink(i, up); |
1633 | mutex_unlock(&hash_mutex); | ||
1588 | } | 1634 | } |
1589 | 1635 | ||
1590 | /* Base timer interval for polling */ | 1636 | /* Base timer interval for polling */ |
@@ -2960,7 +3006,7 @@ EXPORT_SYMBOL(serial8250_unregister_port); | |||
2960 | 3006 | ||
2961 | static int __init serial8250_init(void) | 3007 | static int __init serial8250_init(void) |
2962 | { | 3008 | { |
2963 | int ret, i; | 3009 | int ret; |
2964 | 3010 | ||
2965 | if (nr_uarts > UART_NR) | 3011 | if (nr_uarts > UART_NR) |
2966 | nr_uarts = UART_NR; | 3012 | nr_uarts = UART_NR; |
@@ -2969,9 +3015,6 @@ static int __init serial8250_init(void) | |||
2969 | "%d ports, IRQ sharing %sabled\n", nr_uarts, | 3015 | "%d ports, IRQ sharing %sabled\n", nr_uarts, |
2970 | share_irqs ? "en" : "dis"); | 3016 | share_irqs ? "en" : "dis"); |
2971 | 3017 | ||
2972 | for (i = 0; i < NR_IRQS; i++) | ||
2973 | spin_lock_init(&irq_lists[i].lock); | ||
2974 | |||
2975 | #ifdef CONFIG_SPARC | 3018 | #ifdef CONFIG_SPARC |
2976 | ret = sunserial_register_minors(&serial8250_reg, UART_NR); | 3019 | ret = sunserial_register_minors(&serial8250_reg, UART_NR); |
2977 | #else | 3020 | #else |
@@ -2999,15 +3042,15 @@ static int __init serial8250_init(void) | |||
2999 | goto out; | 3042 | goto out; |
3000 | 3043 | ||
3001 | platform_device_del(serial8250_isa_devs); | 3044 | platform_device_del(serial8250_isa_devs); |
3002 | put_dev: | 3045 | put_dev: |
3003 | platform_device_put(serial8250_isa_devs); | 3046 | platform_device_put(serial8250_isa_devs); |
3004 | unreg_uart_drv: | 3047 | unreg_uart_drv: |
3005 | #ifdef CONFIG_SPARC | 3048 | #ifdef CONFIG_SPARC |
3006 | sunserial_unregister_minors(&serial8250_reg, UART_NR); | 3049 | sunserial_unregister_minors(&serial8250_reg, UART_NR); |
3007 | #else | 3050 | #else |
3008 | uart_unregister_driver(&serial8250_reg); | 3051 | uart_unregister_driver(&serial8250_reg); |
3009 | #endif | 3052 | #endif |
3010 | out: | 3053 | out: |
3011 | return ret; | 3054 | return ret; |
3012 | } | 3055 | } |
3013 | 3056 | ||