diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-08-25 14:46:23 +1000 | 
|---|---|---|
| committer | Paul Mackerras <paulus@samba.org> | 2006-08-30 14:31:03 +1000 | 
| commit | 006b64de607f895de2ba1e21d3179cddf059128f (patch) | |
| tree | c4eb38d1a3fcb42336475ae261c6624d179308ed /arch/powerpc/kernel/prom_parse.c | |
| parent | 7233593b7844c2db930594ee9c0c872a6900bfcc (diff) | |
| download | olio-linux-3.10-006b64de607f895de2ba1e21d3179cddf059128f.tar.xz olio-linux-3.10-006b64de607f895de2ba1e21d3179cddf059128f.zip  | |
[POWERPC] Make OF irq map code detect more error cases
Device-tree bugs on js20 with some versions of SLOF were causing the
interrupt for IDE to not be parsed correctly and fail to boot. This
patch adds a bit more sanity checking to the parser to detect some of
those errors and fail instead of returning bogus information.  The
powerpc PCI code can then trigger a fallback that works on those
machines.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/prom_parse.c')
| -rw-r--r-- | arch/powerpc/kernel/prom_parse.c | 17 | 
1 files changed, 13 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 11052c212ad..a10825a5dfe 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -639,14 +639,17 @@ void of_irq_map_init(unsigned int flags)  } -int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr, -		   struct of_irq *out_irq) +int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 ointsize, +		   u32 *addr, struct of_irq *out_irq)  {  	struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;  	u32 *tmp, *imap, *imask;  	u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;  	int imaplen, match, i; +	DBG("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n", +	    parent->full_name, intspec[0], intspec[1], ointsize); +  	ipar = of_node_get(parent);  	/* First get the #interrupt-cells property of the current cursor @@ -670,6 +673,9 @@ int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr,  	DBG("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize); +	if (ointsize != intsize) +		return -EINVAL; +  	/* Look for this #address-cells. We have to implement the old linux  	 * trick of looking for the parent here as some device-trees rely on it  	 */ @@ -875,12 +881,15 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq  	}  	intsize = *tmp; +	DBG(" intsize=%d intlen=%d\n", intsize, intlen); +  	/* Check index */  	if ((index + 1) * intsize > intlen)  		return -EINVAL;  	/* Get new specifier and map it */ -	res = of_irq_map_raw(p, intspec + index * intsize, addr, out_irq); +	res = of_irq_map_raw(p, intspec + index * intsize, intsize, +			     addr, out_irq);  	of_node_put(p);  	return res;  } @@ -965,7 +974,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)  	laddr[0] = (pdev->bus->number << 16)  		| (pdev->devfn << 8);  	laddr[1]  = laddr[2] = 0; -	return of_irq_map_raw(ppnode, &lspec, laddr, out_irq); +	return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);  }  EXPORT_SYMBOL_GPL(of_irq_map_pci);  #endif /* CONFIG_PCI */  |