1 /* 2 * pSeries_reconfig.c - support for dynamic reconfiguration (including PCI 3 * Hotplug and Dynamic Logical Partitioning on RPA platforms). 4 * 5 * Copyright (C) 2005 Nathan Lynch 6 * Copyright (C) 2005 IBM Corporation 7 * 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License version 11 * 2 as published by the Free Software Foundation. 12 */ 13 14 #include <linux/kernel.h> 15 #include <linux/kref.h> 16 #include <linux/notifier.h> 17 #include <linux/proc_fs.h> 18 #include <linux/slab.h> 19 20 #include <asm/prom.h> 21 #include <asm/machdep.h> 22 #include <asm/uaccess.h> 23 #include <asm/pSeries_reconfig.h> 24 #include <asm/mmu.h> 25 26 27 28 /* 29 * Routines for "runtime" addition and removal of device tree nodes. 30 */ 31 #ifdef CONFIG_PROC_DEVICETREE 32 /* 33 * Add a node to /proc/device-tree. 34 */ 35 static void add_node_proc_entries(struct device_node *np) 36 { 37 struct proc_dir_entry *ent; 38 39 ent = proc_mkdir(strrchr(np->full_name, '/') + 1, np->parent->pde); 40 if (ent) 41 proc_device_tree_add_node(np, ent); 42 } 43 44 static void remove_node_proc_entries(struct device_node *np) 45 { 46 struct property *pp = np->properties; 47 struct device_node *parent = np->parent; 48 49 while (pp) { 50 remove_proc_entry(pp->name, np->pde); 51 pp = pp->next; 52 } 53 if (np->pde) 54 remove_proc_entry(np->pde->name, parent->pde); 55 } 56 #else /* !CONFIG_PROC_DEVICETREE */ 57 static void add_node_proc_entries(struct device_node *np) 58 { 59 return; 60 } 61 62 static void remove_node_proc_entries(struct device_node *np) 63 { 64 return; 65 } 66 #endif /* CONFIG_PROC_DEVICETREE */ 67 68 /** 69 * derive_parent - basically like dirname(1) 70 * @path: the full_name of a node to be added to the tree 71 * 72 * Returns the node which should be the parent of the node 73 * described by path. E.g., for path = "/foo/bar", returns 74 * the node with full_name = "/foo". 75 */ 76 static struct device_node *derive_parent(const char *path) 77 { 78 struct device_node *parent = NULL; 79 char *parent_path = "/"; 80 size_t parent_path_len = strrchr(path, '/') - path + 1; 81 82 /* reject if path is "/" */ 83 if (!strcmp(path, "/")) 84 return ERR_PTR(-EINVAL); 85 86 if (strrchr(path, '/') != path) { 87 parent_path = kmalloc(parent_path_len, GFP_KERNEL); 88 if (!parent_path) 89 return ERR_PTR(-ENOMEM); 90 strlcpy(parent_path, path, parent_path_len); 91 } 92 parent = of_find_node_by_path(parent_path); 93 if (!parent) 94 return ERR_PTR(-EINVAL); 95 if (strcmp(parent_path, "/")) 96 kfree(parent_path); 97 return parent; 98 } 99 100 BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); 101 102 int pSeries_reconfig_notifier_register(struct notifier_block *nb) 103 { 104 return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb); 105 } 106 107 void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) 108 { 109 blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb); 110 } 111 112 static int pSeries_reconfig_add_node(const char *path, struct property *proplist) 113 { 114 struct device_node *np; 115 int err = -ENOMEM; 116 117 np = kzalloc(sizeof(*np), GFP_KERNEL); 118 if (!np) 119 goto out_err; 120 121 np->full_name = kstrdup(path, GFP_KERNEL); 122 if (!np->full_name) 123 goto out_err; 124 125 np->properties = proplist; 126 of_node_set_flag(np, OF_DYNAMIC); 127 kref_init(&np->kref); 128 129 np->parent = derive_parent(path); 130 if (IS_ERR(np->parent)) { 131 err = PTR_ERR(np->parent); 132 goto out_err; 133 } 134 135 err = blocking_notifier_call_chain(&pSeries_reconfig_chain, 136 PSERIES_RECONFIG_ADD, np); 137 if (err == NOTIFY_BAD) { 138 printk(KERN_ERR "Failed to add device node %s\n", path); 139 err = -ENOMEM; /* For now, safe to assume kmalloc failure */ 140 goto out_err; 141 } 142 143 of_attach_node(np); 144 145 add_node_proc_entries(np); 146 147 of_node_put(np->parent); 148 149 return 0; 150 151 out_err: 152 if (np) { 153 of_node_put(np->parent); 154 kfree(np->full_name); 155 kfree(np); 156 } 157 return err; 158 } 159 160 static int pSeries_reconfig_remove_node(struct device_node *np) 161 { 162 struct device_node *parent, *child; 163 164 parent = of_get_parent(np); 165 if (!parent) 166 return -EINVAL; 167 168 if ((child = of_get_next_child(np, NULL))) { 169 of_node_put(child); 170 of_node_put(parent); 171 return -EBUSY; 172 } 173 174 remove_node_proc_entries(np); 175 176 blocking_notifier_call_chain(&pSeries_reconfig_chain, 177 PSERIES_RECONFIG_REMOVE, np); 178 of_detach_node(np); 179 180 of_node_put(parent); 181 of_node_put(np); /* Must decrement the refcount */ 182 return 0; 183 } 184 185 /* 186 * /proc/powerpc/ofdt - yucky binary interface for adding and removing 187 * OF device nodes. Should be deprecated as soon as we get an 188 * in-kernel wrapper for the RTAS ibm,configure-connector call. 189 */ 190 191 static void release_prop_list(const struct property *prop) 192 { 193 struct property *next; 194 for (; prop; prop = next) { 195 next = prop->next; 196 kfree(prop->name); 197 kfree(prop->value); 198 kfree(prop); 199 } 200 201 } 202 203 /** 204 * parse_next_property - process the next property from raw input buffer 205 * @buf: input buffer, must be nul-terminated 206 * @end: end of the input buffer + 1, for validation 207 * @name: return value; set to property name in buf 208 * @length: return value; set to length of value 209 * @value: return value; set to the property value in buf 210 * 211 * Note that the caller must make copies of the name and value returned, 212 * this function does no allocation or copying of the data. Return value 213 * is set to the next name in buf, or NULL on error. 214 */ 215 static char * parse_next_property(char *buf, char *end, char **name, int *length, 216 unsigned char **value) 217 { 218 char *tmp; 219 220 *name = buf; 221 222 tmp = strchr(buf, ' '); 223 if (!tmp) { 224 printk(KERN_ERR "property parse failed in %s at line %d\n", 225 __func__, __LINE__); 226 return NULL; 227 } 228 *tmp = '\0'; 229 230 if (++tmp >= end) { 231 printk(KERN_ERR "property parse failed in %s at line %d\n", 232 __func__, __LINE__); 233 return NULL; 234 } 235 236 /* now we're on the length */ 237 *length = -1; 238 *length = simple_strtoul(tmp, &tmp, 10); 239 if (*length == -1) { 240 printk(KERN_ERR "property parse failed in %s at line %d\n", 241 __func__, __LINE__); 242 return NULL; 243 } 244 if (*tmp != ' ' || ++tmp >= end) { 245 printk(KERN_ERR "property parse failed in %s at line %d\n", 246 __func__, __LINE__); 247 return NULL; 248 } 249 250 /* now we're on the value */ 251 *value = tmp; 252 tmp += *length; 253 if (tmp > end) { 254 printk(KERN_ERR "property parse failed in %s at line %d\n", 255 __func__, __LINE__); 256 return NULL; 257 } 258 else if (tmp < end && *tmp != ' ' && *tmp != '\0') { 259 printk(KERN_ERR "property parse failed in %s at line %d\n", 260 __func__, __LINE__); 261 return NULL; 262 } 263 tmp++; 264 265 /* and now we should be on the next name, or the end */ 266 return tmp; 267 } 268 269 static struct property *new_property(const char *name, const int length, 270 const unsigned char *value, struct property *last) 271 { 272 struct property *new = kzalloc(sizeof(*new), GFP_KERNEL); 273 274 if (!new) 275 return NULL; 276 277 if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL))) 278 goto cleanup; 279 if (!(new->value = kmalloc(length + 1, GFP_KERNEL))) 280 goto cleanup; 281 282 strcpy(new->name, name); 283 memcpy(new->value, value, length); 284 *(((char *)new->value) + length) = 0; 285 new->length = length; 286 new->next = last; 287 return new; 288 289 cleanup: 290 kfree(new->name); 291 kfree(new->value); 292 kfree(new); 293 return NULL; 294 } 295 296 static int do_add_node(char *buf, size_t bufsize) 297 { 298 char *path, *end, *name; 299 struct device_node *np; 300 struct property *prop = NULL; 301 unsigned char* value; 302 int length, rv = 0; 303 304 end = buf + bufsize; 305 path = buf; 306 buf = strchr(buf, ' '); 307 if (!buf) 308 return -EINVAL; 309 *buf = '\0'; 310 buf++; 311 312 if ((np = of_find_node_by_path(path))) { 313 of_node_put(np); 314 return -EINVAL; 315 } 316 317 /* rv = build_prop_list(tmp, bufsize - (tmp - buf), &proplist); */ 318 while (buf < end && 319 (buf = parse_next_property(buf, end, &name, &length, &value))) { 320 struct property *last = prop; 321 322 prop = new_property(name, length, value, last); 323 if (!prop) { 324 rv = -ENOMEM; 325 prop = last; 326 goto out; 327 } 328 } 329 if (!buf) { 330 rv = -EINVAL; 331 goto out; 332 } 333 334 rv = pSeries_reconfig_add_node(path, prop); 335 336 out: 337 if (rv) 338 release_prop_list(prop); 339 return rv; 340 } 341 342 static int do_remove_node(char *buf) 343 { 344 struct device_node *node; 345 int rv = -ENODEV; 346 347 if ((node = of_find_node_by_path(buf))) 348 rv = pSeries_reconfig_remove_node(node); 349 350 of_node_put(node); 351 return rv; 352 } 353 354 static char *parse_node(char *buf, size_t bufsize, struct device_node **npp) 355 { 356 char *handle_str; 357 phandle handle; 358 *npp = NULL; 359 360 handle_str = buf; 361 362 buf = strchr(buf, ' '); 363 if (!buf) 364 return NULL; 365 *buf = '\0'; 366 buf++; 367 368 handle = simple_strtoul(handle_str, NULL, 0); 369 370 *npp = of_find_node_by_phandle(handle); 371 return buf; 372 } 373 374 static int do_add_property(char *buf, size_t bufsize) 375 { 376 struct property *prop = NULL; 377 struct device_node *np; 378 unsigned char *value; 379 char *name, *end; 380 int length; 381 end = buf + bufsize; 382 buf = parse_node(buf, bufsize, &np); 383 384 if (!np) 385 return -ENODEV; 386 387 if (parse_next_property(buf, end, &name, &length, &value) == NULL) 388 return -EINVAL; 389 390 prop = new_property(name, length, value, NULL); 391 if (!prop) 392 return -ENOMEM; 393 394 prom_add_property(np, prop); 395 396 return 0; 397 } 398 399 static int do_remove_property(char *buf, size_t bufsize) 400 { 401 struct device_node *np; 402 char *tmp; 403 struct property *prop; 404 buf = parse_node(buf, bufsize, &np); 405 406 if (!np) 407 return -ENODEV; 408 409 tmp = strchr(buf,' '); 410 if (tmp) 411 *tmp = '\0'; 412 413 if (strlen(buf) == 0) 414 return -EINVAL; 415 416 prop = of_find_property(np, buf, NULL); 417 418 return prom_remove_property(np, prop); 419 } 420 421 static int do_update_property(char *buf, size_t bufsize) 422 { 423 struct device_node *np; 424 unsigned char *value; 425 char *name, *end, *next_prop; 426 int rc, length; 427 struct property *newprop, *oldprop; 428 buf = parse_node(buf, bufsize, &np); 429 end = buf + bufsize; 430 431 if (!np) 432 return -ENODEV; 433 434 next_prop = parse_next_property(buf, end, &name, &length, &value); 435 if (!next_prop) 436 return -EINVAL; 437 438 newprop = new_property(name, length, value, NULL); 439 if (!newprop) 440 return -ENOMEM; 441 442 if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size")) 443 slb_set_size(*(int *)value); 444 445 oldprop = of_find_property(np, name,NULL); 446 if (!oldprop) { 447 if (strlen(name)) 448 return prom_add_property(np, newprop); 449 return -ENODEV; 450 } 451 452 rc = prom_update_property(np, newprop, oldprop); 453 if (rc) 454 return rc; 455 456 /* For memory under the ibm,dynamic-reconfiguration-memory node 457 * of the device tree, adding and removing memory is just an update 458 * to the ibm,dynamic-memory property instead of adding/removing a 459 * memory node in the device tree. For these cases we still need to 460 * involve the notifier chain. 461 */ 462 if (!strcmp(name, "ibm,dynamic-memory")) { 463 int action; 464 465 next_prop = parse_next_property(next_prop, end, &name, 466 &length, &value); 467 if (!next_prop) 468 return -EINVAL; 469 470 if (!strcmp(name, "add")) 471 action = PSERIES_DRCONF_MEM_ADD; 472 else 473 action = PSERIES_DRCONF_MEM_REMOVE; 474 475 rc = blocking_notifier_call_chain(&pSeries_reconfig_chain, 476 action, value); 477 if (rc == NOTIFY_BAD) { 478 rc = prom_update_property(np, oldprop, newprop); 479 return -ENOMEM; 480 } 481 } 482 483 return 0; 484 } 485 486 /** 487 * ofdt_write - perform operations on the Open Firmware device tree 488 * 489 * @file: not used 490 * @buf: command and arguments 491 * @count: size of the command buffer 492 * @off: not used 493 * 494 * Operations supported at this time are addition and removal of 495 * whole nodes along with their properties. Operations on individual 496 * properties are not implemented (yet). 497 */ 498 static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count, 499 loff_t *off) 500 { 501 int rv = 0; 502 char *kbuf; 503 char *tmp; 504 505 if (!(kbuf = kmalloc(count + 1, GFP_KERNEL))) { 506 rv = -ENOMEM; 507 goto out; 508 } 509 if (copy_from_user(kbuf, buf, count)) { 510 rv = -EFAULT; 511 goto out; 512 } 513 514 kbuf[count] = '\0'; 515 516 tmp = strchr(kbuf, ' '); 517 if (!tmp) { 518 rv = -EINVAL; 519 goto out; 520 } 521 *tmp = '\0'; 522 tmp++; 523 524 if (!strcmp(kbuf, "add_node")) 525 rv = do_add_node(tmp, count - (tmp - kbuf)); 526 else if (!strcmp(kbuf, "remove_node")) 527 rv = do_remove_node(tmp); 528 else if (!strcmp(kbuf, "add_property")) 529 rv = do_add_property(tmp, count - (tmp - kbuf)); 530 else if (!strcmp(kbuf, "remove_property")) 531 rv = do_remove_property(tmp, count - (tmp - kbuf)); 532 else if (!strcmp(kbuf, "update_property")) 533 rv = do_update_property(tmp, count - (tmp - kbuf)); 534 else 535 rv = -EINVAL; 536 out: 537 kfree(kbuf); 538 return rv ? rv : count; 539 } 540 541 static const struct file_operations ofdt_fops = { 542 .write = ofdt_write, 543 .llseek = noop_llseek, 544 }; 545 546 /* create /proc/powerpc/ofdt write-only by root */ 547 static int proc_ppc64_create_ofdt(void) 548 { 549 struct proc_dir_entry *ent; 550 551 if (!machine_is(pseries)) 552 return 0; 553 554 ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops); 555 if (ent) 556 ent->size = 0; 557 558 return 0; 559 } 560 __initcall(proc_ppc64_create_ofdt); 561