cregit-Linux how code gets into the kernel

Release 4.14 arch/powerpc/platforms/pseries/reconfig.c

/*
 * pSeries_reconfig.c - support for dynamic reconfiguration (including PCI
 * Hotplug and Dynamic Logical Partitioning on RPA platforms).
 *
 * Copyright (C) 2005 Nathan Lynch
 * Copyright (C) 2005 IBM Corporation
 *
 *
 *      This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License version
 *      2 as published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/of.h>

#include <asm/prom.h>
#include <asm/machdep.h>
#include <linux/uaccess.h>
#include <asm/mmu.h>

#include "of_helpers.h"


static int pSeries_reconfig_add_node(const char *path, struct property *proplist) { struct device_node *np; int err = -ENOMEM; np = kzalloc(sizeof(*np), GFP_KERNEL); if (!np) goto out_err; np->full_name = kstrdup(path, GFP_KERNEL); if (!np->full_name) goto out_err; np->properties = proplist; of_node_set_flag(np, OF_DYNAMIC); of_node_init(np); np->parent = pseries_of_derive_parent(path); if (IS_ERR(np->parent)) { err = PTR_ERR(np->parent); goto out_err; } err = of_attach_node(np); if (err) { printk(KERN_ERR "Failed to add device node %s\n", path); goto out_err; } of_node_put(np->parent); return 0; out_err: if (np) { of_node_put(np->parent); kfree(np->full_name); kfree(np); } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras17193.44%114.29%
Tyrel Datwyler52.73%114.29%
Michael Ellerman31.64%114.29%
Pekka J Enberg10.55%114.29%
Julia Lawall10.55%114.29%
Andy Shevchenko10.55%114.29%
Nathan Fontenot10.55%114.29%
Total183100.00%7100.00%


static int pSeries_reconfig_remove_node(struct device_node *np) { struct device_node *parent, *child; parent = of_get_parent(np); if (!parent) return -EINVAL; if ((child = of_get_next_child(np, NULL))) { of_node_put(child); of_node_put(parent); return -EBUSY; } of_detach_node(np); of_node_put(parent); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras7293.51%150.00%
Julia Lawall56.49%150.00%
Total77100.00%2100.00%

/* * /proc/powerpc/ofdt - yucky binary interface for adding and removing * OF device nodes. Should be deprecated as soon as we get an * in-kernel wrapper for the RTAS ibm,configure-connector call. */
static void release_prop_list(const struct property *prop) { struct property *next; for (; prop; prop = next) { next = prop->next; kfree(prop->name); kfree(prop->value); kfree(prop); } }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras53100.00%1100.00%
Total53100.00%1100.00%

/** * parse_next_property - process the next property from raw input buffer * @buf: input buffer, must be nul-terminated * @end: end of the input buffer + 1, for validation * @name: return value; set to property name in buf * @length: return value; set to length of value * @value: return value; set to the property value in buf * * Note that the caller must make copies of the name and value returned, * this function does no allocation or copying of the data. Return value * is set to the next name in buf, or NULL on error. */
static char * parse_next_property(char *buf, char *end, char **name, int *length, unsigned char **value) { char *tmp; *name = buf; tmp = strchr(buf, ' '); if (!tmp) { printk(KERN_ERR "property parse failed in %s at line %d\n", __func__, __LINE__); return NULL; } *tmp = '\0'; if (++tmp >= end) { printk(KERN_ERR "property parse failed in %s at line %d\n", __func__, __LINE__); return NULL; } /* now we're on the length */ *length = -1; *length = simple_strtoul(tmp, &tmp, 10); if (*length == -1) { printk(KERN_ERR "property parse failed in %s at line %d\n", __func__, __LINE__); return NULL; } if (*tmp != ' ' || ++tmp >= end) { printk(KERN_ERR "property parse failed in %s at line %d\n", __func__, __LINE__); return NULL; } /* now we're on the value */ *value = tmp; tmp += *length; if (tmp > end) { printk(KERN_ERR "property parse failed in %s at line %d\n", __func__, __LINE__); return NULL; } else if (tmp < end && *tmp != ' ' && *tmp != '\0') { printk(KERN_ERR "property parse failed in %s at line %d\n", __func__, __LINE__); return NULL; } tmp++; /* and now we should be on the next name, or the end */ return tmp; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras23097.46%150.00%
Harvey Harrison62.54%150.00%
Total236100.00%2100.00%


static struct property *new_property(const char *name, const int length, const unsigned char *value, struct property *last) { struct property *new = kzalloc(sizeof(*new), GFP_KERNEL); if (!new) return NULL; if (!(new->name = kstrdup(name, GFP_KERNEL))) goto cleanup; if (!(new->value = kmalloc(length + 1, GFP_KERNEL))) goto cleanup; memcpy(new->value, value, length); *(((char *)new->value) + length) = 0; new->length = length; new->next = last; return new; cleanup: kfree(new->name); kfree(new->value); kfree(new); return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras15798.74%133.33%
Yan Burman10.63%133.33%
Grant C. Likely10.63%133.33%
Total159100.00%3100.00%


static int do_add_node(char *buf, size_t bufsize) { char *path, *end, *name; struct device_node *np; struct property *prop = NULL; unsigned char* value; int length, rv = 0; end = buf + bufsize; path = buf; buf = strchr(buf, ' '); if (!buf) return -EINVAL; *buf = '\0'; buf++; if ((np = of_find_node_by_path(path))) { of_node_put(np); return -EINVAL; } /* rv = build_prop_list(tmp, bufsize - (tmp - buf), &proplist); */ while (buf < end && (buf = parse_next_property(buf, end, &name, &length, &value))) { struct property *last = prop; prop = new_property(name, length, value, last); if (!prop) { rv = -ENOMEM; prop = last; goto out; } } if (!buf) { rv = -EINVAL; goto out; } rv = pSeries_reconfig_add_node(path, prop); out: if (rv) release_prop_list(prop); return rv; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras211100.00%1100.00%
Total211100.00%1100.00%


static int do_remove_node(char *buf) { struct device_node *node; int rv = -ENODEV; if ((node = of_find_node_by_path(buf))) rv = pSeries_reconfig_remove_node(node); of_node_put(node); return rv; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras47100.00%1100.00%
Total47100.00%1100.00%


static char *parse_node(char *buf, size_t bufsize, struct device_node **npp) { char *handle_str; phandle handle; *npp = NULL; handle_str = buf; buf = strchr(buf, ' '); if (!buf) return NULL; *buf = '\0'; buf++; handle = simple_strtoul(handle_str, NULL, 0); *npp = of_find_node_by_phandle(handle); return buf; }

Contributors

PersonTokensPropCommitsCommitProp
Dave C Boutcher8298.80%150.00%
Nathan Fontenot11.20%150.00%
Total83100.00%2100.00%


static int do_add_property(char *buf, size_t bufsize) { struct property *prop = NULL; struct device_node *np; unsigned char *value; char *name, *end; int length; end = buf + bufsize; buf = parse_node(buf, bufsize, &np); if (!np) return -ENODEV; if (parse_next_property(buf, end, &name, &length, &value) == NULL) return -EINVAL; prop = new_property(name, length, value, NULL); if (!prop) return -ENOMEM; of_add_property(np, prop); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Dave C Boutcher12299.19%150.00%
Nathan Fontenot10.81%150.00%
Total123100.00%2100.00%


static int do_remove_property(char *buf, size_t bufsize) { struct device_node *np; char *tmp; buf = parse_node(buf, bufsize, &np); if (!np) return -ENODEV; tmp = strchr(buf,' '); if (tmp) *tmp = '\0'; if (strlen(buf) == 0) return -EINVAL; return of_remove_property(np, of_find_property(np, buf, NULL)); }

Contributors

PersonTokensPropCommitsCommitProp
Dave C Boutcher8494.38%150.00%
Suraj Jitindar Singh55.62%150.00%
Total89100.00%2100.00%


static int do_update_property(char *buf, size_t bufsize) { struct device_node *np; unsigned char *value; char *name, *end, *next_prop; int length; struct property *newprop; buf = parse_node(buf, bufsize, &np); end = buf + bufsize; if (!np) return -ENODEV; next_prop = parse_next_property(buf, end, &name, &length, &value); if (!next_prop) return -EINVAL; if (!strlen(name)) return -ENODEV; newprop = new_property(name, length, value, NULL); if (!newprop) return -ENOMEM; if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size")) slb_set_size(*(int *)value); return of_update_property(np, newprop); }

Contributors

PersonTokensPropCommitsCommitProp
Dave C Boutcher10865.45%116.67%
Brian King2816.97%116.67%
Nathan Fontenot1710.30%350.00%
Dong Aisheng127.27%116.67%
Total165100.00%6100.00%

/** * ofdt_write - perform operations on the Open Firmware device tree * * @file: not used * @buf: command and arguments * @count: size of the command buffer * @off: not used * * Operations supported at this time are addition and removal of * whole nodes along with their properties. Operations on individual * properties are not implemented (yet). */
static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count, loff_t *off) { int rv; char *kbuf; char *tmp; kbuf = memdup_user_nul(buf, count); if (IS_ERR(kbuf)) return PTR_ERR(kbuf); tmp = strchr(kbuf, ' '); if (!tmp) { rv = -EINVAL; goto out; } *tmp = '\0'; tmp++; if (!strcmp(kbuf, "add_node")) rv = do_add_node(tmp, count - (tmp - kbuf)); else if (!strcmp(kbuf, "remove_node")) rv = do_remove_node(tmp); else if (!strcmp(kbuf, "add_property")) rv = do_add_property(tmp, count - (tmp - kbuf)); else if (!strcmp(kbuf, "remove_property")) rv = do_remove_property(tmp, count - (tmp - kbuf)); else if (!strcmp(kbuf, "update_property")) rv = do_update_property(tmp, count - (tmp - kbuf)); else rv = -EINVAL; out: kfree(kbuf); return rv ? rv : count; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras14362.17%133.33%
Dave C Boutcher7833.91%133.33%
Geliang Tang93.91%133.33%
Total230100.00%3100.00%

static const struct file_operations ofdt_fops = { .write = ofdt_write, .llseek = noop_llseek, }; /* create /proc/powerpc/ofdt write-only by root */
static int proc_ppc64_create_ofdt(void) { struct proc_dir_entry *ent; ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops); if (ent) proc_set_size(ent, 0); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras3278.05%125.00%
David Howells49.76%125.00%
Denis V. Lunev49.76%125.00%
Benjamin Herrenschmidt12.44%125.00%
Total41100.00%4100.00%

machine_device_initcall(pseries, proc_ppc64_create_ofdt);

Overall Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras114965.40%13.45%
Dave C Boutcher47426.98%13.45%
Brian King311.76%13.45%
Nathan Fontenot231.31%517.24%
Dong Aisheng120.68%13.45%
Geliang Tang90.51%13.45%
Julia Lawall60.34%26.90%
Harvey Harrison60.34%13.45%
Arnd Bergmann60.34%13.45%
Michael Ellerman60.34%26.90%
Tyrel Datwyler50.28%13.45%
Suraj Jitindar Singh50.28%13.45%
Benjamin Herrenschmidt50.28%26.90%
Denis V. Lunev40.23%13.45%
David Howells40.23%13.45%
Andy Shevchenko40.23%13.45%
Tejun Heo30.17%13.45%
Linus Torvalds10.06%13.45%
Pekka J Enberg10.06%13.45%
Yan Burman10.06%13.45%
Grant C. Likely10.06%13.45%
Arjan van de Ven10.06%13.45%
Total1757100.00%29100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.