Commit 8e48aec714f1faf581949f23ae0e3d6e2317433b

Authored by David S. Miller
1 parent 3d824a46b7

[OPENPROM]: Rewrite driver to use in-kernel device tree.

Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 336 additions and 257 deletions Side-by-side Diff

drivers/sbus/char/openprom.c
... ... @@ -29,8 +29,6 @@
29 29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 30 */
31 31  
32   -#define PROMLIB_INTERNAL
33   -
34 32 #include <linux/config.h>
35 33 #include <linux/module.h>
36 34 #include <linux/kernel.h>
37 35  
... ... @@ -39,10 +37,10 @@
39 37 #include <linux/slab.h>
40 38 #include <linux/string.h>
41 39 #include <linux/miscdevice.h>
42   -#include <linux/smp_lock.h>
43 40 #include <linux/init.h>
44 41 #include <linux/fs.h>
45 42 #include <asm/oplib.h>
  43 +#include <asm/prom.h>
46 44 #include <asm/system.h>
47 45 #include <asm/uaccess.h>
48 46 #include <asm/openpromio.h>
49 47  
50 48  
... ... @@ -51,15 +49,20 @@
51 49 #include <asm/pbm.h>
52 50 #endif
53 51  
  52 +MODULE_AUTHOR("Thomas K. Dyas (tdyas@noc.rutgers.edu) and Eddie C. Dost (ecd@skynet.be)");
  53 +MODULE_DESCRIPTION("OPENPROM Configuration Driver");
  54 +MODULE_LICENSE("GPL");
  55 +MODULE_VERSION("1.0");
  56 +
54 57 /* Private data kept by the driver for each descriptor. */
55 58 typedef struct openprom_private_data
56 59 {
57   - int current_node; /* Current node for SunOS ioctls. */
58   - int lastnode; /* Last valid node used by BSD ioctls. */
  60 + struct device_node *current_node; /* Current node for SunOS ioctls. */
  61 + struct device_node *lastnode; /* Last valid node used by BSD ioctls. */
59 62 } DATA;
60 63  
61 64 /* ID of the PROM node containing all of the EEPROM options. */
62   -static int options_node = 0;
  65 +static struct device_node *options_node;
63 66  
64 67 /*
65 68 * Copy an openpromio structure into kernel space from user space.
66 69  
... ... @@ -87,9 +90,8 @@
87 90 if (bufsize > OPROMMAXPARAM)
88 91 bufsize = OPROMMAXPARAM;
89 92  
90   - if (!(*opp_p = kmalloc(sizeof(int) + bufsize + 1, GFP_KERNEL)))
  93 + if (!(*opp_p = kzalloc(sizeof(int) + bufsize + 1, GFP_KERNEL)))
91 94 return -ENOMEM;
92   - memset(*opp_p, 0, sizeof(int) + bufsize + 1);
93 95  
94 96 if (copy_from_user(&(*opp_p)->oprom_array,
95 97 &info->oprom_array, bufsize)) {
96 98  
... ... @@ -107,10 +109,9 @@
107 109 if (!info || !opp_p)
108 110 return -EFAULT;
109 111  
110   - if (!(*opp_p = kmalloc(sizeof(int) + OPROMMAXPARAM + 1, GFP_KERNEL)))
  112 + if (!(*opp_p = kzalloc(sizeof(int) + OPROMMAXPARAM + 1, GFP_KERNEL)))
111 113 return -ENOMEM;
112 114  
113   - memset(*opp_p, 0, sizeof(int) + OPROMMAXPARAM + 1);
114 115 (*opp_p)->oprom_size = 0;
115 116  
116 117 n = bufsize = 0;
117 118  
118 119  
119 120  
... ... @@ -140,16 +141,164 @@
140 141 return 0;
141 142 }
142 143  
  144 +static int opromgetprop(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize)
  145 +{
  146 + void *pval;
  147 + int len;
  148 +
  149 + pval = of_get_property(dp, op->oprom_array, &len);
  150 + if (!pval || len <= 0 || len > bufsize)
  151 + return copyout(argp, op, sizeof(int));
  152 +
  153 + memcpy(op->oprom_array, pval, len);
  154 + op->oprom_array[len] = '\0';
  155 + op->oprom_size = len;
  156 +
  157 + return copyout(argp, op, sizeof(int) + bufsize);
  158 +}
  159 +
  160 +static int opromnxtprop(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize)
  161 +{
  162 + struct property *prop;
  163 + int len;
  164 +
  165 + if (op->oprom_array[0] == '\0') {
  166 + prop = dp->properties;
  167 + if (!prop)
  168 + return copyout(argp, op, sizeof(int));
  169 + len = strlen(prop->name);
  170 + } else {
  171 + prop = of_find_property(dp, op->oprom_array, NULL);
  172 +
  173 + if (!prop ||
  174 + !prop->next ||
  175 + (len = strlen(prop->next->name)) + 1 > bufsize)
  176 + return copyout(argp, op, sizeof(int));
  177 +
  178 + prop = prop->next;
  179 + }
  180 +
  181 + memcpy(op->oprom_array, prop->name, len);
  182 + op->oprom_array[len] = '\0';
  183 + op->oprom_size = ++len;
  184 +
  185 + return copyout(argp, op, sizeof(int) + bufsize);
  186 +}
  187 +
  188 +static int opromsetopt(struct device_node *dp, struct openpromio *op, int bufsize)
  189 +{
  190 + char *buf = op->oprom_array + strlen(op->oprom_array) + 1;
  191 + int len = op->oprom_array + bufsize - buf;
  192 +
  193 + return of_set_property(options_node, op->oprom_array, buf, len);
  194 +}
  195 +
  196 +static int opromnext(void __user *argp, unsigned int cmd, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data)
  197 +{
  198 + phandle ph;
  199 +
  200 + BUILD_BUG_ON(sizeof(phandle) != sizeof(int));
  201 +
  202 + if (bufsize < sizeof(phandle))
  203 + return -EINVAL;
  204 +
  205 + ph = *((int *) op->oprom_array);
  206 + if (ph) {
  207 + dp = of_find_node_by_phandle(ph);
  208 + if (!dp)
  209 + return -EINVAL;
  210 +
  211 + switch (cmd) {
  212 + case OPROMNEXT:
  213 + dp = dp->sibling;
  214 + break;
  215 +
  216 + case OPROMCHILD:
  217 + dp = dp->child;
  218 + break;
  219 +
  220 + case OPROMSETCUR:
  221 + default:
  222 + break;
  223 + };
  224 + } else {
  225 + /* Sibling of node zero is the root node. */
  226 + if (cmd != OPROMNEXT)
  227 + return -EINVAL;
  228 +
  229 + dp = of_find_node_by_path("/");
  230 + }
  231 +
  232 + ph = 0;
  233 + if (dp)
  234 + ph = dp->node;
  235 +
  236 + data->current_node = dp;
  237 + *((int *) op->oprom_array) = ph;
  238 + op->oprom_size = sizeof(phandle);
  239 +
  240 + return copyout(argp, op, bufsize + sizeof(int));
  241 +}
  242 +
  243 +static int oprompci2node(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data)
  244 +{
  245 + int err = -EINVAL;
  246 +
  247 + if (bufsize >= 2*sizeof(int)) {
  248 +#ifdef CONFIG_PCI
  249 + struct pci_dev *pdev;
  250 + struct pcidev_cookie *pcp;
  251 + pdev = pci_find_slot (((int *) op->oprom_array)[0],
  252 + ((int *) op->oprom_array)[1]);
  253 +
  254 + pcp = pdev->sysdata;
  255 + if (pcp != NULL) {
  256 + dp = pcp->prom_node;
  257 + data->current_node = dp;
  258 + *((int *)op->oprom_array) = dp->node;
  259 + op->oprom_size = sizeof(int);
  260 + err = copyout(argp, op, bufsize + sizeof(int));
  261 + }
  262 +#endif
  263 + }
  264 +
  265 + return err;
  266 +}
  267 +
  268 +static int oprompath2node(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data)
  269 +{
  270 + dp = of_find_node_by_path(op->oprom_array);
  271 + data->current_node = dp;
  272 + *((int *)op->oprom_array) = dp->node;
  273 + op->oprom_size = sizeof(int);
  274 +
  275 + return copyout(argp, op, bufsize + sizeof(int));
  276 +}
  277 +
  278 +static int opromgetbootargs(void __user *argp, struct openpromio *op, int bufsize)
  279 +{
  280 + char *buf = saved_command_line;
  281 + int len = strlen(buf);
  282 +
  283 + if (len > bufsize)
  284 + return -EINVAL;
  285 +
  286 + strcpy(op->oprom_array, buf);
  287 + op->oprom_size = len;
  288 +
  289 + return copyout(argp, op, bufsize + sizeof(int));
  290 +}
  291 +
143 292 /*
144 293 * SunOS and Solaris /dev/openprom ioctl calls.
145 294 */
146 295 static int openprom_sunos_ioctl(struct inode * inode, struct file * file,
147   - unsigned int cmd, unsigned long arg, int node)
  296 + unsigned int cmd, unsigned long arg,
  297 + struct device_node *dp)
148 298 {
149   - DATA *data = (DATA *) file->private_data;
150   - char buffer[OPROMMAXPARAM+1], *buf;
  299 + DATA *data = file->private_data;
151 300 struct openpromio *opp;
152   - int bufsize, len, error = 0;
  301 + int bufsize, error = 0;
153 302 static int cnt;
154 303 void __user *argp = (void __user *)arg;
155 304  
156 305  
157 306  
158 307  
159 308  
160 309  
161 310  
... ... @@ -164,119 +313,35 @@
164 313 switch (cmd) {
165 314 case OPROMGETOPT:
166 315 case OPROMGETPROP:
167   - len = prom_getproplen(node, opp->oprom_array);
168   -
169   - if (len <= 0 || len > bufsize) {
170   - error = copyout(argp, opp, sizeof(int));
171   - break;
172   - }
173   -
174   - len = prom_getproperty(node, opp->oprom_array, buffer, bufsize);
175   -
176   - memcpy(opp->oprom_array, buffer, len);
177   - opp->oprom_array[len] = '\0';
178   - opp->oprom_size = len;
179   -
180   - error = copyout(argp, opp, sizeof(int) + bufsize);
  316 + error = opromgetprop(argp, dp, opp, bufsize);
181 317 break;
182 318  
183 319 case OPROMNXTOPT:
184 320 case OPROMNXTPROP:
185   - buf = prom_nextprop(node, opp->oprom_array, buffer);
186   -
187   - len = strlen(buf);
188   - if (len == 0 || len + 1 > bufsize) {
189   - error = copyout(argp, opp, sizeof(int));
190   - break;
191   - }
192   -
193   - memcpy(opp->oprom_array, buf, len);
194   - opp->oprom_array[len] = '\0';
195   - opp->oprom_size = ++len;
196   -
197   - error = copyout(argp, opp, sizeof(int) + bufsize);
  321 + error = opromnxtprop(argp, dp, opp, bufsize);
198 322 break;
199 323  
200 324 case OPROMSETOPT:
201 325 case OPROMSETOPT2:
202   - buf = opp->oprom_array + strlen(opp->oprom_array) + 1;
203   - len = opp->oprom_array + bufsize - buf;
204   -
205   - error = prom_setprop(options_node, opp->oprom_array,
206   - buf, len);
207   -
208   - if (error < 0)
209   - error = -EINVAL;
  326 + error = opromsetopt(dp, opp, bufsize);
210 327 break;
211 328  
212 329 case OPROMNEXT:
213 330 case OPROMCHILD:
214 331 case OPROMSETCUR:
215   - if (bufsize < sizeof(int)) {
216   - error = -EINVAL;
217   - break;
218   - }
219   -
220   - node = *((int *) opp->oprom_array);
221   -
222   - switch (cmd) {
223   - case OPROMNEXT: node = __prom_getsibling(node); break;
224   - case OPROMCHILD: node = __prom_getchild(node); break;
225   - case OPROMSETCUR: break;
226   - }
227   -
228   - data->current_node = node;
229   - *((int *)opp->oprom_array) = node;
230   - opp->oprom_size = sizeof(int);
231   -
232   - error = copyout(argp, opp, bufsize + sizeof(int));
  332 + error = opromnext(argp, cmd, dp, opp, bufsize, data);
233 333 break;
234 334  
235 335 case OPROMPCI2NODE:
236   - error = -EINVAL;
237   -
238   - if (bufsize >= 2*sizeof(int)) {
239   -#ifdef CONFIG_PCI
240   - struct pci_dev *pdev;
241   - struct pcidev_cookie *pcp;
242   - pdev = pci_find_slot (((int *) opp->oprom_array)[0],
243   - ((int *) opp->oprom_array)[1]);
244   -
245   - pcp = pdev->sysdata;
246   - if (pcp != NULL) {
247   - node = pcp->prom_node->node;
248   - data->current_node = node;
249   - *((int *)opp->oprom_array) = node;
250   - opp->oprom_size = sizeof(int);
251   - error = copyout(argp, opp, bufsize + sizeof(int));
252   - }
253   -#endif
254   - }
  336 + error = oprompci2node(argp, dp, opp, bufsize, data);
255 337 break;
256 338  
257 339 case OPROMPATH2NODE:
258   - node = prom_finddevice(opp->oprom_array);
259   - data->current_node = node;
260   - *((int *)opp->oprom_array) = node;
261   - opp->oprom_size = sizeof(int);
262   -
263   - error = copyout(argp, opp, bufsize + sizeof(int));
  340 + error = oprompath2node(argp, dp, opp, bufsize, data);
264 341 break;
265 342  
266 343 case OPROMGETBOOTARGS:
267   - buf = saved_command_line;
268   -
269   - len = strlen(buf);
270   -
271   - if (len > bufsize) {
272   - error = -EINVAL;
273   - break;
274   - }
275   -
276   - strcpy(opp->oprom_array, buf);
277   - opp->oprom_size = len;
278   -
279   - error = copyout(argp, opp, bufsize + sizeof(int));
  344 + error = opromgetbootargs(argp, opp, bufsize);
280 345 break;
281 346  
282 347 case OPROMU2P:
283 348  
284 349  
... ... @@ -297,25 +362,14 @@
297 362 return error;
298 363 }
299 364  
300   -
301   -/* Return nonzero if a specific node is in the PROM device tree. */
302   -static int intree(int root, int node)
  365 +static struct device_node *get_node(phandle n, DATA *data)
303 366 {
304   - for (; root != 0; root = prom_getsibling(root))
305   - if (root == node || intree(prom_getchild(root),node))
306   - return 1;
307   - return 0;
308   -}
  367 + struct device_node *dp = of_find_node_by_phandle(n);
309 368  
310   -/* Return nonzero if a specific node is "valid". */
311   -static int goodnode(int n, DATA *data)
312   -{
313   - if (n == data->lastnode || n == prom_root_node || n == options_node)
314   - return 1;
315   - if (n == 0 || n == -1 || !intree(prom_root_node,n))
316   - return 0;
317   - data->lastnode = n;
318   - return 1;
  369 + if (dp)
  370 + data->lastnode = dp;
  371 +
  372 + return dp;
319 373 }
320 374  
321 375 /* Copy in a whole string from userspace into kernelspace. */
... ... @@ -330,7 +384,7 @@
330 384 if (!tmp)
331 385 return -ENOMEM;
332 386  
333   - if(copy_from_user(tmp, user, len)) {
  387 + if (copy_from_user(tmp, user, len)) {
334 388 kfree(tmp);
335 389 return -EFAULT;
336 390 }
337 391  
338 392  
339 393  
340 394  
341 395  
342 396  
343 397  
344 398  
345 399  
346 400  
347 401  
348 402  
349 403  
350 404  
351 405  
352 406  
353 407  
354 408  
355 409  
356 410  
357 411  
358 412  
359 413  
360 414  
361 415  
362 416  
363 417  
364 418  
365 419  
366 420  
367 421  
368 422  
369 423  
370 424  
371 425  
372 426  
373 427  
374 428  
375 429  
376 430  
... ... @@ -345,162 +399,187 @@
345 399 /*
346 400 * NetBSD /dev/openprom ioctl calls.
347 401 */
348   -static int openprom_bsd_ioctl(struct inode * inode, struct file * file,
349   - unsigned int cmd, unsigned long arg)
  402 +static int opiocget(void __user *argp, DATA *data)
350 403 {
351   - DATA *data = (DATA *) file->private_data;
352   - void __user *argp = (void __user *)arg;
353 404 struct opiocdesc op;
354   - int error, node, len;
355   - char *str, *tmp;
356   - char buffer[64];
357   - static int cnt;
  405 + struct device_node *dp;
  406 + char *str;
  407 + void *pval;
  408 + int err, len;
358 409  
359   - switch (cmd) {
360   - case OPIOCGET:
361   - if (copy_from_user(&op, argp, sizeof(op)))
362   - return -EFAULT;
  410 + if (copy_from_user(&op, argp, sizeof(op)))
  411 + return -EFAULT;
363 412  
364   - if (!goodnode(op.op_nodeid,data))
365   - return -EINVAL;
  413 + dp = get_node(op.op_nodeid, data);
366 414  
367   - error = copyin_string(op.op_name, op.op_namelen, &str);
368   - if (error)
369   - return error;
  415 + err = copyin_string(op.op_name, op.op_namelen, &str);
  416 + if (err)
  417 + return err;
370 418  
371   - len = prom_getproplen(op.op_nodeid,str);
372   -
373   - if (len > op.op_buflen) {
374   - kfree(str);
375   - return -ENOMEM;
376   - }
377   -
  419 + pval = of_get_property(dp, str, &len);
  420 + err = 0;
  421 + if (!pval || len > op.op_buflen) {
  422 + err = -EINVAL;
  423 + } else {
378 424 op.op_buflen = len;
  425 + if (copy_to_user(argp, &op, sizeof(op)) ||
  426 + copy_to_user(op.op_buf, pval, len))
  427 + err = -EFAULT;
  428 + }
  429 + kfree(str);
379 430  
380   - if (len <= 0) {
381   - kfree(str);
382   - /* Verified by the above copy_from_user */
383   - if (__copy_to_user(argp, &op,
384   - sizeof(op)))
385   - return -EFAULT;
386   - return 0;
387   - }
  431 + return err;
  432 +}
388 433  
389   - tmp = kmalloc(len + 1, GFP_KERNEL);
390   - if (!tmp) {
391   - kfree(str);
392   - return -ENOMEM;
393   - }
  434 +static int opiocnextprop(void __user *argp, DATA *data)
  435 +{
  436 + struct opiocdesc op;
  437 + struct device_node *dp;
  438 + struct property *prop;
  439 + char *str;
  440 + int err, len;
394 441  
395   - cnt = prom_getproperty(op.op_nodeid, str, tmp, len);
396   - if (cnt <= 0) {
397   - error = -EINVAL;
398   - } else {
399   - tmp[len] = '\0';
  442 + if (copy_from_user(&op, argp, sizeof(op)))
  443 + return -EFAULT;
400 444  
401   - if (__copy_to_user(argp, &op, sizeof(op)) != 0 ||
402   - copy_to_user(op.op_buf, tmp, len) != 0)
403   - error = -EFAULT;
404   - }
  445 + dp = get_node(op.op_nodeid, data);
  446 + if (!dp)
  447 + return -EINVAL;
405 448  
406   - kfree(tmp);
407   - kfree(str);
  449 + err = copyin_string(op.op_name, op.op_namelen, &str);
  450 + if (err)
  451 + return err;
408 452  
409   - return error;
  453 + if (str[0] == '\0') {
  454 + prop = dp->properties;
  455 + } else {
  456 + prop = of_find_property(dp, str, NULL);
  457 + if (prop)
  458 + prop = prop->next;
  459 + }
  460 + kfree(str);
410 461  
411   - case OPIOCNEXTPROP:
412   - if (copy_from_user(&op, argp, sizeof(op)))
413   - return -EFAULT;
  462 + if (!prop)
  463 + len = 0;
  464 + else
  465 + len = prop->length;
414 466  
415   - if (!goodnode(op.op_nodeid,data))
416   - return -EINVAL;
  467 + if (len > op.op_buflen)
  468 + len = op.op_buflen;
417 469  
418   - error = copyin_string(op.op_name, op.op_namelen, &str);
419   - if (error)
420   - return error;
  470 + if (copy_to_user(argp, &op, sizeof(op)))
  471 + return -EFAULT;
421 472  
422   - tmp = prom_nextprop(op.op_nodeid,str,buffer);
  473 + if (len &&
  474 + copy_to_user(op.op_buf, prop->value, len))
  475 + return -EFAULT;
423 476  
424   - if (tmp) {
425   - len = strlen(tmp);
426   - if (len > op.op_buflen)
427   - len = op.op_buflen;
428   - else
429   - op.op_buflen = len;
430   - } else {
431   - len = op.op_buflen = 0;
432   - }
  477 + return 0;
  478 +}
433 479  
434   - if (!access_ok(VERIFY_WRITE, argp, sizeof(op))) {
435   - kfree(str);
436   - return -EFAULT;
437   - }
  480 +static int opiocset(void __user *argp, DATA *data)
  481 +{
  482 + struct opiocdesc op;
  483 + struct device_node *dp;
  484 + char *str, *tmp;
  485 + int err;
438 486  
439   - if (!access_ok(VERIFY_WRITE, op.op_buf, len)) {
440   - kfree(str);
441   - return -EFAULT;
442   - }
  487 + if (copy_from_user(&op, argp, sizeof(op)))
  488 + return -EFAULT;
443 489  
444   - error = __copy_to_user(argp, &op, sizeof(op));
445   - if (!error) error = __copy_to_user(op.op_buf, tmp, len);
  490 + dp = get_node(op.op_nodeid, data);
  491 + if (!dp)
  492 + return -EINVAL;
446 493  
  494 + err = copyin_string(op.op_name, op.op_namelen, &str);
  495 + if (err)
  496 + return err;
  497 +
  498 + err = copyin_string(op.op_buf, op.op_buflen, &tmp);
  499 + if (err) {
447 500 kfree(str);
  501 + return err;
  502 + }
448 503  
449   - return error;
  504 + err = of_set_property(dp, str, tmp, op.op_buflen);
450 505  
451   - case OPIOCSET:
452   - if (copy_from_user(&op, argp, sizeof(op)))
453   - return -EFAULT;
  506 + kfree(str);
  507 + kfree(tmp);
454 508  
455   - if (!goodnode(op.op_nodeid,data))
456   - return -EINVAL;
  509 + return err;
  510 +}
457 511  
458   - error = copyin_string(op.op_name, op.op_namelen, &str);
459   - if (error)
460   - return error;
  512 +static int opiocgetnext(unsigned int cmd, void __user *argp)
  513 +{
  514 + struct device_node *dp;
  515 + phandle nd;
461 516  
462   - error = copyin_string(op.op_buf, op.op_buflen, &tmp);
463   - if (error) {
464   - kfree(str);
465   - return error;
466   - }
  517 + BUILD_BUG_ON(sizeof(phandle) != sizeof(int));
467 518  
468   - len = prom_setprop(op.op_nodeid,str,tmp,op.op_buflen+1);
  519 + if (copy_from_user(&nd, argp, sizeof(phandle)))
  520 + return -EFAULT;
469 521  
470   - if (len != op.op_buflen)
  522 + if (nd == 0) {
  523 + if (cmd != OPIOCGETNEXT)
471 524 return -EINVAL;
  525 + dp = of_find_node_by_path("/");
  526 + } else {
  527 + dp = of_find_node_by_phandle(nd);
  528 + nd = 0;
  529 + if (dp) {
  530 + if (cmd == OPIOCGETNEXT)
  531 + dp = dp->sibling;
  532 + else
  533 + dp = dp->child;
  534 + }
  535 + }
  536 + if (dp)
  537 + nd = dp->node;
  538 + if (copy_to_user(argp, &nd, sizeof(phandle)))
  539 + return -EFAULT;
472 540  
473   - kfree(str);
474   - kfree(tmp);
  541 + return 0;
  542 +}
475 543  
476   - return 0;
  544 +static int openprom_bsd_ioctl(struct inode * inode, struct file * file,
  545 + unsigned int cmd, unsigned long arg)
  546 +{
  547 + DATA *data = (DATA *) file->private_data;
  548 + void __user *argp = (void __user *)arg;
  549 + int err;
477 550  
478   - case OPIOCGETOPTNODE:
479   - if (copy_to_user(argp, &options_node, sizeof(int)))
480   - return -EFAULT;
481   - return 0;
  551 + switch (cmd) {
  552 + case OPIOCGET:
  553 + err = opiocget(argp, data);
  554 + break;
482 555  
483   - case OPIOCGETNEXT:
484   - case OPIOCGETCHILD:
485   - if (copy_from_user(&node, argp, sizeof(int)))
486   - return -EFAULT;
  556 + case OPIOCNEXTPROP:
  557 + err = opiocnextprop(argp, data);
  558 + break;
487 559  
488   - if (cmd == OPIOCGETNEXT)
489   - node = __prom_getsibling(node);
490   - else
491   - node = __prom_getchild(node);
  560 + case OPIOCSET:
  561 + err = opiocset(argp, data);
  562 + break;
492 563  
493   - if (__copy_to_user(argp, &node, sizeof(int)))
  564 + case OPIOCGETOPTNODE:
  565 + BUILD_BUG_ON(sizeof(phandle) != sizeof(int));
  566 +
  567 + if (copy_to_user(argp, &options_node->node, sizeof(phandle)))
494 568 return -EFAULT;
495 569  
496 570 return 0;
497 571  
  572 + case OPIOCGETNEXT:
  573 + case OPIOCGETCHILD:
  574 + err = opiocgetnext(cmd, argp);
  575 + break;
  576 +
498 577 default:
499   - if (cnt++ < 10)
500   - printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd);
501 578 return -EINVAL;
502 579  
503   - }
  580 + };
  581 +
  582 + return err;
504 583 }
505 584  
506 585  
... ... @@ -511,7 +590,6 @@
511 590 unsigned int cmd, unsigned long arg)
512 591 {
513 592 DATA *data = (DATA *) file->private_data;
514   - static int cnt;
515 593  
516 594 switch (cmd) {
517 595 case OPROMGETOPT:
518 596  
... ... @@ -563,10 +641,8 @@
563 641 return openprom_bsd_ioctl(inode,file,cmd,arg);
564 642  
565 643 default:
566   - if (cnt++ < 10)
567   - printk("openprom_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg);
568 644 return -EINVAL;
569   - }
  645 + };
570 646 }
571 647  
572 648 static long openprom_compat_ioctl(struct file *file, unsigned int cmd,
573 649  
... ... @@ -594,9 +670,7 @@
594 670 case OPROMSETCUR:
595 671 case OPROMPCI2NODE:
596 672 case OPROMPATH2NODE:
597   - lock_kernel();
598 673 rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg);
599   - lock_kernel();
600 674 break;
601 675 }
602 676  
603 677  
... ... @@ -607,13 +681,13 @@
607 681 {
608 682 DATA *data;
609 683  
610   - data = (DATA *) kmalloc(sizeof(DATA), GFP_KERNEL);
  684 + data = kmalloc(sizeof(DATA), GFP_KERNEL);
611 685 if (!data)
612 686 return -ENOMEM;
613 687  
614   - data->current_node = prom_root_node;
615   - data->lastnode = prom_root_node;
616   - file->private_data = (void *)data;
  688 + data->current_node = of_find_node_by_path("/");
  689 + data->lastnode = data->current_node;
  690 + file->private_data = (void *) data;
617 691  
618 692 return 0;
619 693 }
620 694  
621 695  
622 696  
623 697  
... ... @@ -634,24 +708,30 @@
634 708 };
635 709  
636 710 static struct miscdevice openprom_dev = {
637   - SUN_OPENPROM_MINOR, "openprom", &openprom_fops
  711 + .minor = SUN_OPENPROM_MINOR,
  712 + .name = "openprom",
  713 + .fops = &openprom_fops,
638 714 };
639 715  
640 716 static int __init openprom_init(void)
641 717 {
642   - int error;
  718 + struct device_node *dp;
  719 + int err;
643 720  
644   - error = misc_register(&openprom_dev);
645   - if (error) {
646   - printk(KERN_ERR "openprom: unable to get misc minor\n");
647   - return error;
  721 + err = misc_register(&openprom_dev);
  722 + if (err)
  723 + return err;
  724 +
  725 + dp = of_find_node_by_path("/");
  726 + dp = dp->child;
  727 + while (dp) {
  728 + if (!strcmp(dp->name, "options"))
  729 + break;
  730 + dp = dp->sibling;
648 731 }
  732 + options_node = dp;
649 733  
650   - options_node = prom_getchild(prom_root_node);
651   - options_node = prom_searchsiblings(options_node,"options");
652   -
653   - if (options_node == 0 || options_node == -1) {
654   - printk(KERN_ERR "openprom: unable to find options node\n");
  734 + if (!options_node) {
655 735 misc_deregister(&openprom_dev);
656 736 return -EIO;
657 737 }
... ... @@ -666,5 +746,4 @@
666 746  
667 747 module_init(openprom_init);
668 748 module_exit(openprom_cleanup);
669   -MODULE_LICENSE("GPL");