aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2010-12-16 08:06:35 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-12-16 16:14:32 -0500
commit35c64e5d13c3d7d8c4ad061ad5e20498b9160c24 (patch)
tree7fe8761e76c9dd07a785dacba0837af93603763d /drivers/serial
parent3f960dbb9dfe29ff283810624c4340c79fde87f5 (diff)
drivers: serial: apbuart: Handle OF failures gracefully
The apbuart driver depends on OF and relies on everything being available. So if it's probed on a platform which has OF support, but no device tree is available it crashes. Triggered by the upcoming x86 OF support in randconfig testing. Further it's inconsistent vs. the probing and exiting from the of_match loop. Make it robust and consistent: - check the availablility of OF nodes before dereferencing - return -ENODEV when the device tree lookup fails - return -ENODEV when no uart port configuration is found - return -ENODEV when invalid uart port configuration is found Remove the enum_done check while at it. Driver init functions are only called once. Remove the pointless vendor and device queries as well. Reported-by: Ingo Molnar <mingo.elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Kristoffer Glembo <kristoffer@gaisler.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/apbuart.c48
1 files changed, 19 insertions, 29 deletions
diff --git a/drivers/serial/apbuart.c b/drivers/serial/apbuart.c
index cc01c650a144..2e84d9c3d419 100644
--- a/drivers/serial/apbuart.c
+++ b/drivers/serial/apbuart.c
@@ -593,54 +593,44 @@ static struct of_platform_driver grlib_apbuart_of_driver = {
593}; 593};
594 594
595 595
596static void grlib_apbuart_configure(void) 596static int grlib_apbuart_configure(void)
597{ 597{
598 static int enum_done;
599 struct device_node *np, *rp; 598 struct device_node *np, *rp;
600 struct uart_port *port = NULL;
601 const u32 *prop; 599 const u32 *prop;
602 int freq_khz; 600 int freq_khz, line = 0;
603 int v = 0, d = 0;
604 unsigned int addr;
605 int irq, line;
606 struct amba_prom_registers *regs;
607
608 if (enum_done)
609 return;
610 601
611 /* Get bus frequency */ 602 /* Get bus frequency */
612 rp = of_find_node_by_path("/"); 603 rp = of_find_node_by_path("/");
604 if (!rp)
605 return -ENODEV;
613 rp = of_get_next_child(rp, NULL); 606 rp = of_get_next_child(rp, NULL);
607 if (!rp)
608 return -ENODEV;
614 prop = of_get_property(rp, "clock-frequency", NULL); 609 prop = of_get_property(rp, "clock-frequency", NULL);
610 if (!prop)
611 return -ENODEV;
615 freq_khz = *prop; 612 freq_khz = *prop;
616 613
617 line = 0;
618 for_each_matching_node(np, apbuart_match) { 614 for_each_matching_node(np, apbuart_match) {
615 const int *irqs = of_get_property(np, "interrupts", NULL);
616 const struct amba_prom_registers *regs;
617 struct uart_port *port;
618 unsigned long addr;
619 619
620 int *vendor = (int *) of_get_property(np, "vendor", NULL); 620 regs = of_get_property(np, "reg", NULL);
621 int *device = (int *) of_get_property(np, "device", NULL);
622 int *irqs = (int *) of_get_property(np, "interrupts", NULL);
623 regs = (struct amba_prom_registers *)
624 of_get_property(np, "reg", NULL);
625
626 if (vendor)
627 v = *vendor;
628 if (device)
629 d = *device;
630 621
631 if (!irqs || !regs) 622 if (!irqs || !regs)
632 return; 623 return -ENODEV;
633 624
634 grlib_apbuart_nodes[line] = np; 625 grlib_apbuart_nodes[line] = np;
635 626
636 addr = regs->phys_addr; 627 addr = regs->phys_addr;
637 irq = *irqs;
638 628
639 port = &grlib_apbuart_ports[line]; 629 port = &grlib_apbuart_ports[line];
640 630
641 port->mapbase = addr; 631 port->mapbase = addr;
642 port->membase = ioremap(addr, sizeof(struct grlib_apbuart_regs_map)); 632 port->membase = ioremap(addr, sizeof(struct grlib_apbuart_regs_map));
643 port->irq = irq; 633 port->irq = *irqs;
644 port->iotype = UPIO_MEM; 634 port->iotype = UPIO_MEM;
645 port->ops = &grlib_apbuart_ops; 635 port->ops = &grlib_apbuart_ops;
646 port->flags = UPF_BOOT_AUTOCONF; 636 port->flags = UPF_BOOT_AUTOCONF;
@@ -652,12 +642,10 @@ static void grlib_apbuart_configure(void)
652 /* We support maximum UART_NR uarts ... */ 642 /* We support maximum UART_NR uarts ... */
653 if (line == UART_NR) 643 if (line == UART_NR)
654 break; 644 break;
655
656 } 645 }
657 646
658 enum_done = 1;
659
660 grlib_apbuart_driver.nr = grlib_apbuart_port_nr = line; 647 grlib_apbuart_driver.nr = grlib_apbuart_port_nr = line;
648 return line ? 0 : -ENODEV;
661} 649}
662 650
663static int __init grlib_apbuart_init(void) 651static int __init grlib_apbuart_init(void)
@@ -665,7 +653,9 @@ static int __init grlib_apbuart_init(void)
665 int ret; 653 int ret;
666 654
667 /* Find all APBUARTS in device the tree and initialize their ports */ 655 /* Find all APBUARTS in device the tree and initialize their ports */
668 grlib_apbuart_configure(); 656 ret = grlib_apbuart_configure();
657 if (ret)
658 return ret;
669 659
670 printk(KERN_INFO "Serial: GRLIB APBUART driver\n"); 660 printk(KERN_INFO "Serial: GRLIB APBUART driver\n");
671 661