[PATCH] ppc64: Fix result code handling in prom_init

prom_init(), the trampoline code that "talks" to Open Firmware during
early boot, has various issues with managing OF result codes. Some of my
recent fixups in fact made the problem worse on some platforms.

This patch reworks it all. Tested on g5, Maple, POWER3 and POWER5.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Benjamin Herrenschmidt and committed by
Linus Torvalds
1e86d1c6 e0d6d714

+61 -41
+61 -41
arch/ppc64/kernel/prom_init.c
··· 211 211 */ 212 212 #define ADDR(x) (u32) ((unsigned long)(x) - offset) 213 213 214 + /* 215 + * Error results ... some OF calls will return "-1" on error, some 216 + * will return 0, some will return either. To simplify, here are 217 + * macros to use with any ihandle or phandle return value to check if 218 + * it is valid 219 + */ 220 + 221 + #define PROM_ERROR (-1u) 222 + #define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR) 223 + #define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR) 224 + 225 + 214 226 /* This is the one and *ONLY* place where we actually call open 215 227 * firmware from, since we need to make sure we're running in 32b 216 228 * mode when we do. We switch back to 64b mode upon return. 217 229 */ 218 - 219 - #define PROM_ERROR (-1) 220 230 221 231 static int __init call_prom(const char *service, int nargs, int nret, ...) 222 232 { ··· 597 587 { 598 588 unsigned long offset = reloc_offset(); 599 589 ihandle elfloader; 600 - int ret; 601 590 602 591 elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); 603 592 if (elfloader == 0) { 604 593 prom_printf("couldn't open /packages/elf-loader\n"); 605 594 return; 606 595 } 607 - ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"), 596 + call_prom("call-method", 3, 1, ADDR("process-elf-header"), 608 597 elfloader, ADDR(&fake_elf)); 609 598 call_prom("close", 1, 0, elfloader); 610 599 } ··· 655 646 base = _ALIGN_UP(base + 0x100000, align)) { 656 647 prom_debug(" trying: 0x%x\n\r", base); 657 648 addr = (unsigned long)prom_claim(base, size, 0); 658 - if ((int)addr != PROM_ERROR) 649 + if (addr != PROM_ERROR) 659 650 break; 660 651 addr = 0; 661 652 if (align == 0) ··· 717 708 for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { 718 709 prom_debug(" trying: 0x%x\n\r", base); 719 710 addr = (unsigned long)prom_claim(base, size, 0); 720 - if ((int)addr != PROM_ERROR) 711 + if (addr != PROM_ERROR) 721 712 break; 722 713 addr = 0; 723 714 } ··· 911 902 { 912 903 unsigned long offset = reloc_offset(); 913 904 struct prom_t *_prom = PTRRELOC(&prom); 914 - phandle prom_rtas, rtas_node; 905 + phandle rtas_node; 906 + ihandle rtas_inst; 915 907 u32 base, entry = 0; 916 908 u32 size = 0; 917 909 918 910 prom_debug("prom_instantiate_rtas: start...\n"); 919 911 920 - prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); 921 - prom_debug("prom_rtas: %x\n", prom_rtas); 922 - if (prom_rtas == (phandle) -1) 912 + rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas")); 913 + prom_debug("rtas_node: %x\n", rtas_node); 914 + if (!PHANDLE_VALID(rtas_node)) 923 915 return; 924 916 925 - prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size)); 917 + prom_getprop(rtas_node, "rtas-size", &size, sizeof(size)); 926 918 if (size == 0) 927 919 return; 928 920 ··· 932 922 prom_printf("RTAS allocation failed !\n"); 933 923 return; 934 924 } 935 - prom_printf("instantiating rtas at 0x%x", base); 936 925 937 - rtas_node = call_prom("open", 1, 1, ADDR("/rtas")); 938 - prom_printf("..."); 926 + rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); 927 + if (!IHANDLE_VALID(rtas_inst)) { 928 + prom_printf("opening rtas package failed"); 929 + return; 930 + } 931 + 932 + prom_printf("instantiating rtas at 0x%x ...", base); 939 933 940 934 if (call_prom("call-method", 3, 2, 941 935 ADDR("instantiate-rtas"), 942 - rtas_node, base) != PROM_ERROR) { 936 + rtas_inst, base) != PROM_ERROR) { 943 937 entry = (long)_prom->args.rets[1]; 944 938 } 945 939 if (entry == 0) { ··· 954 940 955 941 reserve_mem(base, size); 956 942 957 - prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base)); 958 - prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry)); 943 + prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); 944 + prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); 959 945 960 946 prom_debug("rtas base = 0x%x\n", base); 961 947 prom_debug("rtas entry = 0x%x\n", entry); ··· 1076 1062 1077 1063 prom_printf("opening PHB %s", path); 1078 1064 phb_node = call_prom("open", 1, 1, path); 1079 - if ( (long)phb_node <= 0) 1065 + if (phb_node == 0) 1080 1066 prom_printf("... failed\n"); 1081 1067 else 1082 1068 prom_printf("... done\n"); ··· 1293 1279 1294 1280 /* get a handle for the stdout device */ 1295 1281 _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); 1296 - if ((long)_prom->chosen <= 0) 1282 + if (!PHANDLE_VALID(_prom->chosen)) 1297 1283 prom_panic("cannot find chosen"); /* msg won't be printed :( */ 1298 1284 1299 1285 /* get device tree root */ 1300 1286 _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); 1301 - if ((long)_prom->root <= 0) 1287 + if (!PHANDLE_VALID(_prom->root)) 1302 1288 prom_panic("cannot find device tree root"); /* msg won't be printed :( */ 1303 1289 } 1304 1290 ··· 1370 1356 } 1371 1357 /* Default to pSeries. We need to know if we are running LPAR */ 1372 1358 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); 1373 - if (rtas != (phandle) -1) { 1374 - unsigned long x; 1375 - x = prom_getproplen(rtas, "ibm,hypertas-functions"); 1359 + if (!PHANDLE_VALID(rtas)) { 1360 + int x = prom_getproplen(rtas, "ibm,hypertas-functions"); 1376 1361 if (x != PROM_ERROR) { 1377 1362 prom_printf("Hypertas detected, assuming LPAR !\n"); 1378 1363 return PLATFORM_PSERIES_LPAR; ··· 1439 1426 * leave some room at the end of the path for appending extra 1440 1427 * arguments 1441 1428 */ 1442 - if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0) 1429 + if (call_prom("package-to-path", 3, 1, node, path, 1430 + PROM_SCRATCH_SIZE-10) == PROM_ERROR) 1443 1431 continue; 1444 1432 prom_printf("found display : %s, opening ... ", path); 1445 1433 1446 1434 ih = call_prom("open", 1, 1, path); 1447 - if (ih == (ihandle)0 || ih == (ihandle)-1) { 1435 + if (ih == 0) { 1448 1436 prom_printf("failed\n"); 1449 1437 continue; 1450 1438 } ··· 1528 1514 return 0; 1529 1515 } 1530 1516 1517 + /* 1518 + * The Open Firmware 1275 specification states properties must be 31 bytes or 1519 + * less, however not all firmwares obey this. Make it 64 bytes to be safe. 1520 + */ 1521 + #define MAX_PROPERTY_NAME 64 1522 + 1531 1523 static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, 1532 1524 unsigned long *mem_end) 1533 1525 { ··· 1547 1527 /* get and store all property names */ 1548 1528 prev_name = RELOC(""); 1549 1529 for (;;) { 1550 - 1551 - /* 32 is max len of name including nul. */ 1552 - namep = make_room(mem_start, mem_end, 32, 1); 1553 - if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) { 1530 + int rc; 1531 + 1532 + /* 64 is max len of name including nul. */ 1533 + namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); 1534 + rc = call_prom("nextprop", 3, 1, node, prev_name, namep); 1535 + if (rc != 1) { 1554 1536 /* No more nodes: unwind alloc */ 1555 1537 *mem_start = (unsigned long)namep; 1556 1538 break; ··· 1576 1554 child = call_prom("peer", 1, 1, child); 1577 1555 } 1578 1556 } 1579 - 1580 - /* 1581 - * The Open Firmware 1275 specification states properties must be 31 bytes or 1582 - * less, however not all firmwares obey this. Make it 64 bytes to be safe. 1583 - */ 1584 - #define MAX_PROPERTY_NAME 64 1585 1557 1586 1558 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, 1587 1559 unsigned long *mem_end) ··· 1623 1607 prev_name = RELOC(""); 1624 1608 sstart = (char *)RELOC(dt_string_start); 1625 1609 for (;;) { 1626 - if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0) 1610 + int rc; 1611 + 1612 + rc = call_prom("nextprop", 3, 1, node, prev_name, pname); 1613 + if (rc != 1) 1627 1614 break; 1628 1615 1629 1616 /* find string offset */ ··· 1642 1623 l = call_prom("getproplen", 2, 1, node, pname); 1643 1624 1644 1625 /* sanity checks */ 1645 - if (l < 0) 1626 + if (l == PROM_ERROR) 1646 1627 continue; 1647 1628 if (l > MAX_PROPERTY_LENGTH) { 1648 1629 prom_printf("WARNING: ignoring large property "); ··· 1790 1771 1791 1772 /* Some G5s have a missing interrupt definition, fix it up here */ 1792 1773 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); 1793 - if ((long)u3 <= 0) 1774 + if (!PHANDLE_VALID(u3)) 1794 1775 return; 1795 1776 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); 1796 - if ((long)i2c <= 0) 1777 + if (!PHANDLE_VALID(i2c)) 1797 1778 return; 1798 1779 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); 1799 - if ((long)mpic <= 0) 1780 + if (!PHANDLE_VALID(mpic)) 1800 1781 return; 1801 1782 1802 1783 /* check if proper rev of u3 */ 1803 - if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0) 1784 + if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) 1785 + == PROM_ERROR) 1804 1786 return; 1805 1787 if (u3_rev != 0x35) 1806 1788 return;