cregit-Linux how code gets into the kernel

Release 4.14 arch/powerpc/sysdev/scom.c

/*
 * Copyright 2010 Benjamin Herrenschmidt, IBM Corp
 *                <benh@kernel.crashing.org>
 *     and        David Gibson, IBM Corporation.
 *
 *   This program is free software;  you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program;  if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/export.h>
#include <asm/debugfs.h>
#include <asm/prom.h>
#include <asm/scom.h>
#include <linux/uaccess.h>


const struct scom_controller *scom_controller;

EXPORT_SYMBOL_GPL(scom_controller);


struct device_node *scom_find_parent(struct device_node *node) { struct device_node *par, *tmp; const u32 *p; for (par = of_node_get(node); par;) { if (of_get_property(par, "scom-controller", NULL)) break; p = of_get_property(par, "scom-parent", NULL); tmp = par; if (p == NULL) par = of_get_parent(par); else par = of_find_node_by_phandle(*p); of_node_put(tmp); } return par; }

Contributors

PersonTokensPropCommitsCommitProp
Benjamin Herrenschmidt96100.00%1100.00%
Total96100.00%1100.00%

EXPORT_SYMBOL_GPL(scom_find_parent);
scom_map_t scom_map_device(struct device_node *dev, int index) { struct device_node *parent; unsigned int cells, size; const __be32 *prop, *sprop; u64 reg, cnt; scom_map_t ret; parent = scom_find_parent(dev); if (parent == NULL) return 0; /* * We support "scom-reg" properties for adding scom registers * to a random device-tree node with an explicit scom-parent * * We also support the simple "reg" property if the device is * a direct child of a scom controller. * * In case both exist, "scom-reg" takes precedence. */ prop = of_get_property(dev, "scom-reg", &size); sprop = of_get_property(parent, "#scom-cells", NULL); if (!prop && parent == dev->parent) { prop = of_get_property(dev, "reg", &size); sprop = of_get_property(parent, "#address-cells", NULL); } if (!prop) return NULL; cells = sprop ? be32_to_cpup(sprop) : 1; size >>= 2; if (index >= (size / (2*cells))) return 0; reg = of_read_number(&prop[index * cells * 2], cells); cnt = of_read_number(&prop[index * cells * 2 + cells], cells); ret = scom_map(parent, reg, cnt); of_node_put(parent); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Benjamin Herrenschmidt211100.00%2100.00%
Total211100.00%2100.00%

EXPORT_SYMBOL_GPL(scom_map_device); #ifdef CONFIG_SCOM_DEBUGFS struct scom_debug_entry { struct device_node *dn; struct debugfs_blob_wrapper path; char name[16]; };
static ssize_t scom_debug_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos) { struct scom_debug_entry *ent = filp->private_data; u64 __user *ubuf64 = (u64 __user *)ubuf; loff_t off = *ppos; ssize_t done = 0; u64 reg, reg_cnt, val; scom_map_t map; int rc; if (off < 0 || (off & 7) || (count & 7)) return -EINVAL; reg = off >> 3; reg_cnt = count >> 3; map = scom_map(ent->dn, reg, reg_cnt); if (!scom_map_ok(map)) return -ENXIO; for (reg = 0; reg < reg_cnt; reg++) { rc = scom_read(map, reg, &val); if (!rc) rc = put_user(val, ubuf64); if (rc) { if (!done) done = rc; break; } ubuf64++; *ppos += 8; done += 8; } scom_unmap(map); return done; }

Contributors

PersonTokensPropCommitsCommitProp
Benjamin Herrenschmidt204100.00%2100.00%
Total204100.00%2100.00%


static ssize_t scom_debug_write(struct file* filp, const char __user *ubuf, size_t count, loff_t *ppos) { struct scom_debug_entry *ent = filp->private_data; u64 __user *ubuf64 = (u64 __user *)ubuf; loff_t off = *ppos; ssize_t done = 0; u64 reg, reg_cnt, val; scom_map_t map; int rc; if (off < 0 || (off & 7) || (count & 7)) return -EINVAL; reg = off >> 3; reg_cnt = count >> 3; map = scom_map(ent->dn, reg, reg_cnt); if (!scom_map_ok(map)) return -ENXIO; for (reg = 0; reg < reg_cnt; reg++) { rc = get_user(val, ubuf64); if (!rc) rc = scom_write(map, reg, val); if (rc) { if (!done) done = rc; break; } ubuf64++; done += 8; } scom_unmap(map); return done; }

Contributors

PersonTokensPropCommitsCommitProp
Benjamin Herrenschmidt199100.00%2100.00%
Total199100.00%2100.00%

static const struct file_operations scom_debug_fops = { .read = scom_debug_read, .write = scom_debug_write, .open = simple_open, .llseek = default_llseek, };
static int scom_debug_init_one(struct dentry *root, struct device_node *dn, int i) { struct scom_debug_entry *ent; struct dentry *dir; ent = kzalloc(sizeof(*ent), GFP_KERNEL); if (!ent) return -ENOMEM; ent->dn = of_node_get(dn); snprintf(ent->name, 16, "%08x", i); ent->path.data = (void*)kasprintf(GFP_KERNEL, "%pOF", dn); ent->path.size = strlen((char *)ent->path.data); dir = debugfs_create_dir(ent->name, root); if (!dir) { of_node_put(dn); kfree(ent->path.data); kfree(ent); return -1; } debugfs_create_blob("devspec", 0400, dir, &ent->path); debugfs_create_file("access", 0600, dir, ent, &scom_debug_fops); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Benjamin Herrenschmidt15584.70%250.00%
Rob Herring2413.11%125.00%
Grant C. Likely42.19%125.00%
Total183100.00%4100.00%


static int scom_debug_init(void) { struct device_node *dn; struct dentry *root; int i, rc; root = debugfs_create_dir("scom", powerpc_debugfs_root); if (!root) return -1; i = rc = 0; for_each_node_with_property(dn, "scom-controller") { int id = of_get_ibm_chip_id(dn); if (id == -1) id = i; rc |= scom_debug_init_one(root, dn, id); i++; } return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Benjamin Herrenschmidt91100.00%2100.00%
Total91100.00%2100.00%

device_initcall(scom_debug_init); #endif /* CONFIG_SCOM_DEBUGFS */

Overall Contributors

PersonTokensPropCommitsCommitProp
Benjamin Herrenschmidt105196.78%440.00%
Rob Herring242.21%110.00%
Paul Gortmaker50.46%220.00%
Grant C. Likely40.37%110.00%
Linus Torvalds10.09%110.00%
Michael Ellerman10.09%110.00%
Total1086100.00%10100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.