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

[PATCH] ppc64: SMU partition recovery

This patch adds the ability to the SMU driver to recover missing
calibration partitions from the SMU chip itself. It also adds some
dynamic mecanism to /proc/device-tree so that new properties are visible
to userland.

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
183d0202 4350147a

+382 -58
+18 -3
arch/powerpc/kernel/prom.c
··· 1974 1974 /* 1975 1975 * Add a property to a node 1976 1976 */ 1977 - void prom_add_property(struct device_node* np, struct property* prop) 1977 + int prom_add_property(struct device_node* np, struct property* prop) 1978 1978 { 1979 - struct property **next = &np->properties; 1979 + struct property **next; 1980 1980 1981 1981 prop->next = NULL; 1982 - while (*next) 1982 + write_lock(&devtree_lock); 1983 + next = &np->properties; 1984 + while (*next) { 1985 + if (strcmp(prop->name, (*next)->name) == 0) { 1986 + /* duplicate ! don't insert it */ 1987 + write_unlock(&devtree_lock); 1988 + return -1; 1989 + } 1983 1990 next = &(*next)->next; 1991 + } 1984 1992 *next = prop; 1993 + write_unlock(&devtree_lock); 1994 + 1995 + /* try to add to proc as well if it was initialized */ 1996 + if (np->pde) 1997 + proc_device_tree_add_prop(np->pde, prop); 1998 + 1999 + return 0; 1985 2000 } 1986 2001 1987 2002 /* I quickly hacked that one, check against spec ! */
+3 -1
arch/ppc/syslib/prom.c
··· 1165 1165 /* 1166 1166 * Add a property to a node 1167 1167 */ 1168 - void 1168 + int 1169 1169 prom_add_property(struct device_node* np, struct property* prop) 1170 1170 { 1171 1171 struct property **next = &np->properties; ··· 1174 1174 while (*next) 1175 1175 next = &(*next)->next; 1176 1176 *next = prop; 1177 + 1178 + return 0; 1177 1179 } 1178 1180 1179 1181 /* I quickly hacked that one, check against spec ! */
+20 -4
arch/ppc64/kernel/prom.c
··· 31 31 #include <linux/initrd.h> 32 32 #include <linux/bitops.h> 33 33 #include <linux/module.h> 34 + #include <linux/module.h> 34 35 35 36 #include <asm/prom.h> 36 37 #include <asm/rtas.h> ··· 1866 1865 EXPORT_SYMBOL(get_property); 1867 1866 1868 1867 /* 1869 - * Add a property to a node 1868 + * Add a property to a node. 1870 1869 */ 1871 - void 1870 + int 1872 1871 prom_add_property(struct device_node* np, struct property* prop) 1873 1872 { 1874 - struct property **next = &np->properties; 1873 + struct property **next; 1875 1874 1876 1875 prop->next = NULL; 1877 - while (*next) 1876 + write_lock(&devtree_lock); 1877 + next = &np->properties; 1878 + while (*next) { 1879 + if (strcmp(prop->name, (*next)->name) == 0) { 1880 + /* duplicate ! don't insert it */ 1881 + write_unlock(&devtree_lock); 1882 + return -1; 1883 + } 1878 1884 next = &(*next)->next; 1885 + } 1879 1886 *next = prop; 1887 + write_unlock(&devtree_lock); 1888 + 1889 + /* try to add to proc as well if it was initialized */ 1890 + if (np->pde) 1891 + proc_device_tree_add_prop(np->pde, prop); 1892 + 1893 + return 0; 1880 1894 } 1881 1895 1882 1896 #if 0
+156 -8
drivers/macintosh/smu.c
··· 47 47 #include <asm/uaccess.h> 48 48 #include <asm/of_device.h> 49 49 50 - #define VERSION "0.6" 50 + #define VERSION "0.7" 51 51 #define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp." 52 52 53 53 #undef DEBUG_SMU 54 54 55 55 #ifdef DEBUG_SMU 56 - #define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0) 56 + #define DPRINTK(fmt, args...) do { udbg_printf(KERN_DEBUG fmt , ##args); } while (0) 57 57 #else 58 58 #define DPRINTK(fmt, args...) do { } while (0) 59 59 #endif ··· 92 92 * for now, just hard code that 93 93 */ 94 94 static struct smu_device *smu; 95 - 95 + static DECLARE_MUTEX(smu_part_access); 96 96 97 97 /* 98 98 * SMU driver low level stuff ··· 113 113 114 114 DPRINTK("SMU: starting cmd %x, %d bytes data\n", cmd->cmd, 115 115 cmd->data_len); 116 - DPRINTK("SMU: data buffer: %02x %02x %02x %02x ...\n", 116 + DPRINTK("SMU: data buffer: %02x %02x %02x %02x %02x %02x %02x %02x\n", 117 117 ((u8 *)cmd->data_buf)[0], ((u8 *)cmd->data_buf)[1], 118 - ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3]); 118 + ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3], 119 + ((u8 *)cmd->data_buf)[4], ((u8 *)cmd->data_buf)[5], 120 + ((u8 *)cmd->data_buf)[6], ((u8 *)cmd->data_buf)[7]); 119 121 120 122 /* Fill the SMU command buffer */ 121 123 smu->cmd_buf->cmd = cmd->cmd; ··· 442 440 EXPORT_SYMBOL(smu_present); 443 441 444 442 445 - int smu_init (void) 443 + int __init smu_init (void) 446 444 { 447 445 struct device_node *np; 448 446 u32 *data; ··· 847 845 return 0; 848 846 } 849 847 850 - struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) 848 + /* 849 + * Handling of "partitions" 850 + */ 851 + 852 + static int smu_read_datablock(u8 *dest, unsigned int addr, unsigned int len) 853 + { 854 + DECLARE_COMPLETION(comp); 855 + unsigned int chunk; 856 + struct smu_cmd cmd; 857 + int rc; 858 + u8 params[8]; 859 + 860 + /* We currently use a chunk size of 0xe. We could check the 861 + * SMU firmware version and use bigger sizes though 862 + */ 863 + chunk = 0xe; 864 + 865 + while (len) { 866 + unsigned int clen = min(len, chunk); 867 + 868 + cmd.cmd = SMU_CMD_MISC_ee_COMMAND; 869 + cmd.data_len = 7; 870 + cmd.data_buf = params; 871 + cmd.reply_len = chunk; 872 + cmd.reply_buf = dest; 873 + cmd.done = smu_done_complete; 874 + cmd.misc = &comp; 875 + params[0] = SMU_CMD_MISC_ee_GET_DATABLOCK_REC; 876 + params[1] = 0x4; 877 + *((u32 *)&params[2]) = addr; 878 + params[6] = clen; 879 + 880 + rc = smu_queue_cmd(&cmd); 881 + if (rc) 882 + return rc; 883 + wait_for_completion(&comp); 884 + if (cmd.status != 0) 885 + return rc; 886 + if (cmd.reply_len != clen) { 887 + printk(KERN_DEBUG "SMU: short read in " 888 + "smu_read_datablock, got: %d, want: %d\n", 889 + cmd.reply_len, clen); 890 + return -EIO; 891 + } 892 + len -= clen; 893 + addr += clen; 894 + dest += clen; 895 + } 896 + return 0; 897 + } 898 + 899 + static struct smu_sdbp_header *smu_create_sdb_partition(int id) 900 + { 901 + DECLARE_COMPLETION(comp); 902 + struct smu_simple_cmd cmd; 903 + unsigned int addr, len, tlen; 904 + struct smu_sdbp_header *hdr; 905 + struct property *prop; 906 + 907 + /* First query the partition info */ 908 + smu_queue_simple(&cmd, SMU_CMD_PARTITION_COMMAND, 2, 909 + smu_done_complete, &comp, 910 + SMU_CMD_PARTITION_LATEST, id); 911 + wait_for_completion(&comp); 912 + 913 + /* Partition doesn't exist (or other error) */ 914 + if (cmd.cmd.status != 0 || cmd.cmd.reply_len != 6) 915 + return NULL; 916 + 917 + /* Fetch address and length from reply */ 918 + addr = *((u16 *)cmd.buffer); 919 + len = cmd.buffer[3] << 2; 920 + /* Calucluate total length to allocate, including the 17 bytes 921 + * for "sdb-partition-XX" that we append at the end of the buffer 922 + */ 923 + tlen = sizeof(struct property) + len + 18; 924 + 925 + prop = kcalloc(tlen, 1, GFP_KERNEL); 926 + if (prop == NULL) 927 + return NULL; 928 + hdr = (struct smu_sdbp_header *)(prop + 1); 929 + prop->name = ((char *)prop) + tlen - 18; 930 + sprintf(prop->name, "sdb-partition-%02x", id); 931 + prop->length = len; 932 + prop->value = (unsigned char *)hdr; 933 + prop->next = NULL; 934 + 935 + /* Read the datablock */ 936 + if (smu_read_datablock((u8 *)hdr, addr, len)) { 937 + printk(KERN_DEBUG "SMU: datablock read failed while reading " 938 + "partition %02x !\n", id); 939 + goto failure; 940 + } 941 + 942 + /* Got it, check a few things and create the property */ 943 + if (hdr->id != id) { 944 + printk(KERN_DEBUG "SMU: Reading partition %02x and got " 945 + "%02x !\n", id, hdr->id); 946 + goto failure; 947 + } 948 + if (prom_add_property(smu->of_node, prop)) { 949 + printk(KERN_DEBUG "SMU: Failed creating sdb-partition-%02x " 950 + "property !\n", id); 951 + goto failure; 952 + } 953 + 954 + return hdr; 955 + failure: 956 + kfree(prop); 957 + return NULL; 958 + } 959 + 960 + /* Note: Only allowed to return error code in pointers (using ERR_PTR) 961 + * when interruptible is 1 962 + */ 963 + struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, 964 + int interruptible) 851 965 { 852 966 char pname[32]; 967 + struct smu_sdbp_header *part; 853 968 854 969 if (!smu) 855 970 return NULL; 856 971 857 972 sprintf(pname, "sdb-partition-%02x", id); 858 - return (struct smu_sdbp_header *)get_property(smu->of_node, 973 + 974 + if (interruptible) { 975 + int rc; 976 + rc = down_interruptible(&smu_part_access); 977 + if (rc) 978 + return ERR_PTR(rc); 979 + } else 980 + down(&smu_part_access); 981 + 982 + part = (struct smu_sdbp_header *)get_property(smu->of_node, 859 983 pname, size); 984 + if (part == NULL) { 985 + part = smu_create_sdb_partition(id); 986 + if (part != NULL && size) 987 + *size = part->len << 2; 988 + } 989 + up(&smu_part_access); 990 + return part; 991 + } 992 + 993 + struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) 994 + { 995 + return __smu_get_sdb_partition(id, size, 0); 860 996 } 861 997 EXPORT_SYMBOL(smu_get_sdb_partition); 862 998 ··· 1069 929 return -EFAULT; 1070 930 else if (hdr.cmdtype == SMU_CMDTYPE_WANTS_EVENTS) { 1071 931 pp->mode = smu_file_events; 932 + return 0; 933 + } else if (hdr.cmdtype == SMU_CMDTYPE_GET_PARTITION) { 934 + struct smu_sdbp_header *part; 935 + part = __smu_get_sdb_partition(hdr.cmd, NULL, 1); 936 + if (part == NULL) 937 + return -EINVAL; 938 + else if (IS_ERR(part)) 939 + return PTR_ERR(part); 1072 940 return 0; 1073 941 } else if (hdr.cmdtype != SMU_CMDTYPE_SMU) 1074 942 return -EINVAL;
+35 -22
fs/proc/proc_devtree.c
··· 49 49 */ 50 50 51 51 /* 52 + * Add a property to a node 53 + */ 54 + static struct proc_dir_entry * 55 + __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp) 56 + { 57 + struct proc_dir_entry *ent; 58 + 59 + /* 60 + * Unfortunately proc_register puts each new entry 61 + * at the beginning of the list. So we rearrange them. 62 + */ 63 + ent = create_proc_read_entry(pp->name, 64 + strncmp(pp->name, "security-", 9) 65 + ? S_IRUGO : S_IRUSR, de, 66 + property_read_proc, pp); 67 + if (ent == NULL) 68 + return NULL; 69 + 70 + if (!strncmp(pp->name, "security-", 9)) 71 + ent->size = 0; /* don't leak number of password chars */ 72 + else 73 + ent->size = pp->length; 74 + 75 + return ent; 76 + } 77 + 78 + 79 + void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop) 80 + { 81 + __proc_device_tree_add_prop(pde, prop); 82 + } 83 + 84 + /* 52 85 * Process a node, adding entries for its children and its properties. 53 86 */ 54 87 void proc_device_tree_add_node(struct device_node *np, ··· 90 57 struct property *pp; 91 58 struct proc_dir_entry *ent; 92 59 struct device_node *child; 93 - struct proc_dir_entry *list = NULL, **lastp; 94 60 const char *p; 95 61 96 62 set_node_proc_entry(np, de); 97 - lastp = &list; 98 63 for (child = NULL; (child = of_get_next_child(np, child));) { 99 64 p = strrchr(child->full_name, '/'); 100 65 if (!p) ··· 102 71 ent = proc_mkdir(p, de); 103 72 if (ent == 0) 104 73 break; 105 - *lastp = ent; 106 - ent->next = NULL; 107 - lastp = &ent->next; 108 74 proc_device_tree_add_node(child, ent); 109 75 } 110 76 of_node_put(child); ··· 112 84 * properties are quite unimportant for us though, thus we 113 85 * simply "skip" them here, but we do have to check. 114 86 */ 115 - for (ent = list; ent != NULL; ent = ent->next) 87 + for (ent = de->subdir; ent != NULL; ent = ent->next) 116 88 if (!strcmp(ent->name, pp->name)) 117 89 break; 118 90 if (ent != NULL) { ··· 122 94 continue; 123 95 } 124 96 125 - /* 126 - * Unfortunately proc_register puts each new entry 127 - * at the beginning of the list. So we rearrange them. 128 - */ 129 - ent = create_proc_read_entry(pp->name, 130 - strncmp(pp->name, "security-", 9) 131 - ? S_IRUGO : S_IRUSR, de, 132 - property_read_proc, pp); 97 + ent = __proc_device_tree_add_prop(de, pp); 133 98 if (ent == 0) 134 99 break; 135 - if (!strncmp(pp->name, "security-", 9)) 136 - ent->size = 0; /* don't leak number of password chars */ 137 - else 138 - ent->size = pp->length; 139 - ent->next = NULL; 140 - *lastp = ent; 141 - lastp = &ent->next; 142 100 } 143 - de->subdir = list; 144 101 } 145 102 146 103 /*
+1 -1
include/asm-powerpc/prom.h
··· 203 203 extern int prom_n_size_cells(struct device_node* np); 204 204 extern int prom_n_intr_cells(struct device_node* np); 205 205 extern void prom_get_irq_senses(unsigned char *senses, int off, int max); 206 - extern void prom_add_property(struct device_node* np, struct property* prop); 206 + extern int prom_add_property(struct device_node* np, struct property* prop); 207 207 208 208 #ifdef CONFIG_PPC32 209 209 /*
+143 -10
include/asm-powerpc/smu.h
··· 20 20 /* 21 21 * Partition info commands 22 22 * 23 - * I do not know what those are for at this point 23 + * These commands are used to retreive the sdb-partition-XX datas from 24 + * the SMU. The lenght is always 2. First byte is the subcommand code 25 + * and second byte is the partition ID. 26 + * 27 + * The reply is 6 bytes: 28 + * 29 + * - 0..1 : partition address 30 + * - 2 : a byte containing the partition ID 31 + * - 3 : length (maybe other bits are rest of header ?) 32 + * 33 + * The data must then be obtained with calls to another command: 34 + * SMU_CMD_MISC_ee_GET_DATABLOCK_REC (described below). 24 35 */ 25 36 #define SMU_CMD_PARTITION_COMMAND 0x3e 37 + #define SMU_CMD_PARTITION_LATEST 0x01 38 + #define SMU_CMD_PARTITION_BASE 0x02 39 + #define SMU_CMD_PARTITION_UPDATE 0x03 26 40 27 41 28 42 /* 29 43 * Fan control 30 44 * 31 - * This is a "mux" for fan control commands, first byte is the 32 - * "sub" command. 45 + * This is a "mux" for fan control commands. The command seem to 46 + * act differently based on the number of arguments. With 1 byte 47 + * of argument, this seem to be queries for fans status, setpoint, 48 + * etc..., while with 0xe arguments, we will set the fans speeds. 49 + * 50 + * Queries (1 byte arg): 51 + * --------------------- 52 + * 53 + * arg=0x01: read RPM fans status 54 + * arg=0x02: read RPM fans setpoint 55 + * arg=0x11: read PWM fans status 56 + * arg=0x12: read PWM fans setpoint 57 + * 58 + * the "status" queries return the current speed while the "setpoint" ones 59 + * return the programmed/target speed. It _seems_ that the result is a bit 60 + * mask in the first byte of active/available fans, followed by 6 words (16 61 + * bits) containing the requested speed. 62 + * 63 + * Setpoint (14 bytes arg): 64 + * ------------------------ 65 + * 66 + * first arg byte is 0 for RPM fans and 0x10 for PWM. Second arg byte is the 67 + * mask of fans affected by the command. Followed by 6 words containing the 68 + * setpoint value for selected fans in the mask (or 0 if mask value is 0) 33 69 */ 34 70 #define SMU_CMD_FAN_COMMAND 0x4a 35 71 ··· 192 156 #define SMU_CMD_POWER_SHUTDOWN "SHUTDOWN" 193 157 #define SMU_CMD_POWER_VOLTAGE_SLEW "VSLEW" 194 158 159 + /* 160 + * Read ADC sensors 161 + * 162 + * This command takes one byte of parameter: the sensor ID (or "reg" 163 + * value in the device-tree) and returns a 16 bits value 164 + */ 165 + #define SMU_CMD_READ_ADC 0xd8 166 + 195 167 /* Misc commands 196 168 * 197 169 * This command seem to be a grab bag of various things ··· 220 176 * Misc commands 221 177 * 222 178 * This command seem to be a grab bag of various things 179 + * 180 + * SMU_CMD_MISC_ee_GET_DATABLOCK_REC is used, among others, to 181 + * transfer blocks of data from the SMU. So far, I've decrypted it's 182 + * usage to retreive partition data. In order to do that, you have to 183 + * break your transfer in "chunks" since that command cannot transfer 184 + * more than a chunk at a time. The chunk size used by OF is 0xe bytes, 185 + * but it seems that the darwin driver will let you do 0x1e bytes if 186 + * your "PMU" version is >= 0x30. You can get the "PMU" version apparently 187 + * either in the last 16 bits of property "smu-version-pmu" or as the 16 188 + * bytes at offset 1 of "smu-version-info" 189 + * 190 + * For each chunk, the command takes 7 bytes of arguments: 191 + * byte 0: subcommand code (0x02) 192 + * byte 1: 0x04 (always, I don't know what it means, maybe the address 193 + * space to use or some other nicety. It's hard coded in OF) 194 + * byte 2..5: SMU address of the chunk (big endian 32 bits) 195 + * byte 6: size to transfer (up to max chunk size) 196 + * 197 + * The data is returned directly 223 198 */ 224 199 #define SMU_CMD_MISC_ee_COMMAND 0xee 225 200 #define SMU_CMD_MISC_ee_GET_DATABLOCK_REC 0x02 ··· 416 353 __u8 flags; 417 354 }; 418 355 419 - /* 420 - * 32 bits integers are usually encoded with 2x16 bits swapped, 421 - * this demangles them 356 + 357 + /* 358 + * demangle 16 and 32 bits integer in some SMU partitions 359 + * (currently, afaik, this concerns only the FVT partition 360 + * (0x12) 422 361 */ 423 - #define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) 362 + #define SMU_U16_MIX(x) le16_to_cpu(x); 363 + #define SMU_U32_MIX(x) ((((x) & 0xff00ff00u) >> 8)|(((x) & 0x00ff00ffu) << 8)) 364 + 424 365 425 366 /* This is the definition of the SMU sdb-partition-0x12 table (called 426 367 * CPU F/V/T operating points in Darwin). The definition for all those 427 368 * SMU tables should be moved to some separate file 428 369 */ 429 - #define SMU_SDB_FVT_ID 0x12 370 + #define SMU_SDB_FVT_ID 0x12 430 371 431 372 struct smu_sdbp_fvt { 432 373 __u32 sysclk; /* Base SysClk frequency in Hz for 433 - * this operating point 374 + * this operating point. Value need to 375 + * be unmixed with SMU_U32_MIX() 434 376 */ 435 377 __u8 pad; 436 378 __u8 maxtemp; /* Max temp. supported by this ··· 444 376 445 377 __u16 volts[3]; /* CPU core voltage for the 3 446 378 * PowerTune modes, a mode with 447 - * 0V = not supported. 379 + * 0V = not supported. Value need 380 + * to be unmixed with SMU_U16_MIX() 448 381 */ 449 382 }; 383 + 384 + /* This partition contains voltage & current sensor calibration 385 + * informations 386 + */ 387 + #define SMU_SDB_CPUVCP_ID 0x21 388 + 389 + struct smu_sdbp_cpuvcp { 390 + __u16 volt_scale; /* u4.12 fixed point */ 391 + __s16 volt_offset; /* s4.12 fixed point */ 392 + __u16 curr_scale; /* u4.12 fixed point */ 393 + __s16 curr_offset; /* s4.12 fixed point */ 394 + __s32 power_quads[3]; /* s4.28 fixed point */ 395 + }; 396 + 397 + /* This partition contains CPU thermal diode calibration 398 + */ 399 + #define SMU_SDB_CPUDIODE_ID 0x18 400 + 401 + struct smu_sdbp_cpudiode { 402 + __u16 m_value; /* u1.15 fixed point */ 403 + __s16 b_value; /* s10.6 fixed point */ 404 + 405 + }; 406 + 407 + /* This partition contains Slots power calibration 408 + */ 409 + #define SMU_SDB_SLOTSPOW_ID 0x78 410 + 411 + struct smu_sdbp_slotspow { 412 + __u16 pow_scale; /* u4.12 fixed point */ 413 + __s16 pow_offset; /* s4.12 fixed point */ 414 + }; 415 + 416 + /* This partition contains machine specific version information about 417 + * the sensor/control layout 418 + */ 419 + #define SMU_SDB_SENSORTREE_ID 0x25 420 + 421 + struct smu_sdbp_sensortree { 422 + u8 model_id; 423 + u8 unknown[3]; 424 + }; 425 + 426 + /* This partition contains CPU thermal control PID informations. So far 427 + * only single CPU machines have been seen with an SMU, so we assume this 428 + * carries only informations for those 429 + */ 430 + #define SMU_SDB_CPUPIDDATA_ID 0x17 431 + 432 + struct smu_sdbp_cpupiddata { 433 + u8 unknown1; 434 + u8 target_temp_delta; 435 + u8 unknown2; 436 + u8 history_len; 437 + s16 power_adj; 438 + u16 max_power; 439 + s32 gp,gr,gd; 440 + }; 441 + 442 + 443 + /* Other partitions without known structures */ 444 + #define SMU_SDB_DEBUG_SWITCHES_ID 0x05 450 445 451 446 #ifdef __KERNEL__ 452 447 /* ··· 554 423 __u32 cmdtype; 555 424 #define SMU_CMDTYPE_SMU 0 /* SMU command */ 556 425 #define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */ 426 + #define SMU_CMDTYPE_GET_PARTITION 2 /* retreive an sdb partition */ 557 427 558 428 __u8 cmd; /* SMU command byte */ 429 + __u8 pad[3]; /* padding */ 559 430 __u32 data_len; /* Lenght of data following */ 560 431 }; 561 432
+1 -1
include/asm-ppc/prom.h
··· 93 93 extern int machine_is_compatible(const char *compat); 94 94 extern unsigned char *get_property(struct device_node *node, const char *name, 95 95 int *lenp); 96 - extern void prom_add_property(struct device_node* np, struct property* prop); 96 + extern int prom_add_property(struct device_node* np, struct property* prop); 97 97 extern void prom_get_irq_senses(unsigned char *, int, int); 98 98 extern int prom_n_addr_cells(struct device_node* np); 99 99 extern int prom_n_size_cells(struct device_node* np);
+1 -1
include/asm-ppc64/prom.h
··· 213 213 extern int prom_n_size_cells(struct device_node* np); 214 214 extern int prom_n_intr_cells(struct device_node* np); 215 215 extern void prom_get_irq_senses(unsigned char *senses, int off, int max); 216 - extern void prom_add_property(struct device_node* np, struct property* prop); 216 + extern int prom_add_property(struct device_node* np, struct property* prop); 217 217 218 218 #endif /* _PPC64_PROM_H */
+4 -7
include/linux/proc_fs.h
··· 139 139 /* 140 140 * proc_devtree.c 141 141 */ 142 - struct device_node; 143 - extern void proc_device_tree_init(void); 144 142 #ifdef CONFIG_PROC_DEVICETREE 143 + struct device_node; 144 + struct property; 145 + extern void proc_device_tree_init(void); 145 146 extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); 146 - #else /* !CONFIG_PROC_DEVICETREE */ 147 - static inline void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *pde) 148 - { 149 - return; 150 - } 147 + extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); 151 148 #endif /* CONFIG_PROC_DEVICETREE */ 152 149 153 150 extern struct proc_dir_entry *proc_symlink(const char *,