Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] powerpc: Workaround for offb on 64 bits platforms

This fixes a problem with offb not parsing addresses properly on 64 bits
machines, and thus crashing at boot. The problem is worked around by
locating the matching PCI device and using the properly relocated PCI
base addresses instead of misparsing the Open Firmware properties.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by

Benjamin Herrenschmidt and committed by
Paul Mackerras
b341e32e 1e28a7dd

+35 -5
+35 -5
drivers/video/offb.c
··· 325 325 int *pp, i; 326 326 unsigned int len; 327 327 int width = 640, height = 480, depth = 8, pitch; 328 - unsigned *up; 329 - unsigned long address; 328 + unsigned int rsize, *up; 329 + unsigned long address = 0; 330 330 331 331 if ((pp = (int *) get_property(dp, "depth", &len)) != NULL 332 332 && len == sizeof(int)) ··· 344 344 pitch = 0x1000; 345 345 } else 346 346 pitch = width; 347 - if ((up = (unsigned *) get_property(dp, "address", &len)) != NULL 348 - && len == sizeof(unsigned)) 347 + 348 + rsize = (unsigned long)pitch * (unsigned long)height * 349 + (unsigned long)(depth / 8); 350 + 351 + /* Try to match device to a PCI device in order to get a properly 352 + * translated address rather then trying to decode the open firmware 353 + * stuff in various incorrect ways 354 + */ 355 + #ifdef CONFIG_PCI 356 + /* First try to locate the PCI device if any */ 357 + { 358 + struct pci_dev *pdev = NULL; 359 + 360 + for_each_pci_dev(pdev) { 361 + if (dp == pci_device_to_OF_node(pdev)) 362 + break; 363 + } 364 + if (pdev) { 365 + for (i = 0; i < 6 && address == 0; i++) { 366 + if ((pci_resource_flags(pdev, i) & 367 + IORESOURCE_MEM) && 368 + (pci_resource_len(pdev, i) >= rsize)) 369 + address = pci_resource_start(pdev, i); 370 + } 371 + pci_dev_put(pdev); 372 + } 373 + } 374 + #endif /* CONFIG_PCI */ 375 + 376 + if (address == 0 && 377 + (up = (unsigned *) get_property(dp, "address", &len)) != NULL && 378 + len == sizeof(unsigned)) 349 379 address = (u_long) * up; 350 - else { 380 + if (address == 0) { 351 381 for (i = 0; i < dp->n_addrs; ++i) 352 382 if (dp->addrs[i].size >= 353 383 pitch * height * depth / 8)