aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/8250.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2008-08-19 23:49:40 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-16 10:52:02 -0400
commit25db8ad5c56700e7716fe23426b16c5e3b1674b4 (patch)
treea4f4864f7fb83b091289f4ef73279d8d8b9f34c6 /drivers/serial/8250.c
parent5fef06e8c8c52aa7170dbbb068aa996d83738d38 (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.c67
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
158struct irq_info { 158struct 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
163static struct irq_info irq_lists[NR_IRQS]; 165#define NR_IRQ_HASH 32 /* Can be adjusted later */
166static struct hlist_head irq_lists[NR_IRQ_HASH];
167static 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
1552static int serial_link_irq_chain(struct uart_8250_port *up) 1560static 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
1578static void serial_unlink_irq_chain(struct uart_8250_port *up) 1610static 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
2961static int __init serial8250_init(void) 3007static 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: 3045put_dev:
3003 platform_device_put(serial8250_isa_devs); 3046 platform_device_put(serial8250_isa_devs);
3004 unreg_uart_drv: 3047unreg_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: 3053out:
3011 return ret; 3054 return ret;
3012} 3055}
3013 3056