cregit-Linux how code gets into the kernel

Release 4.14 arch/powerpc/platforms/powernv/opal-sensor-groups.c

/*
 * PowerNV OPAL Sensor-groups interface
 *
 * Copyright 2017 IBM Corp.
 *
 * 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.
 */


#define pr_fmt(fmt)     "opal-sensor-groups: " fmt

#include <linux/of.h>
#include <linux/kobject.h>
#include <linux/slab.h>

#include <asm/opal.h>


DEFINE_MUTEX(sg_mutex);


static struct kobject *sg_kobj;


struct sg_attr {
	
u32 handle;
	
struct kobj_attribute attr;
};


static struct sensor_group {
	
char name[20];
	
struct attribute_group sg;
	
struct sg_attr *sgattrs;

} *sgs;


static ssize_t sg_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { struct sg_attr *sattr = container_of(attr, struct sg_attr, attr); struct opal_msg msg; u32 data; int ret, token; ret = kstrtoint(buf, 0, &data); if (ret) return ret; if (data != 1) return -EINVAL; token = opal_async_get_token_interruptible(); if (token < 0) { pr_devel("Failed to get token\n"); return token; } ret = mutex_lock_interruptible(&sg_mutex); if (ret) goto out_token; ret = opal_sensor_group_clear(sattr->handle, token); switch (ret) { case OPAL_ASYNC_COMPLETION: ret = opal_async_wait_response(token, &msg); if (ret) { pr_devel("Failed to wait for the async response\n"); ret = -EIO; goto out; } ret = opal_error_code(opal_get_async_rc(msg)); if (!ret) ret = count; break; case OPAL_SUCCESS: ret = count; break; default: ret = opal_error_code(ret); } out: mutex_unlock(&sg_mutex); out_token: opal_async_release_token(token); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Shilpasri G Bhat219100.00%1100.00%
Total219100.00%1100.00%

static struct sg_ops_info { int opal_no; const char *attr_name; ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count); } ops_info[] = { { OPAL_SENSOR_GROUP_CLEAR, "clear", sg_store }, };
static void add_attr(int handle, struct sg_attr *attr, int index) { attr->handle = handle; sysfs_attr_init(&attr->attr.attr); attr->attr.attr.name = ops_info[index].attr_name; attr->attr.attr.mode = 0220; attr->attr.store = ops_info[index].store; }

Contributors

PersonTokensPropCommitsCommitProp
Shilpasri G Bhat71100.00%1100.00%
Total71100.00%1100.00%


static int add_attr_group(const __be32 *ops, int len, struct sensor_group *sg, u32 handle) { int i, j; int count = 0; for (i = 0; i < len; i++) for (j = 0; j < ARRAY_SIZE(ops_info); j++) if (be32_to_cpu(ops[i]) == ops_info[j].opal_no) { add_attr(handle, &sg->sgattrs[count], j); sg->sg.attrs[count] = &sg->sgattrs[count].attr.attr; count++; } return sysfs_create_group(sg_kobj, &sg->sg); }

Contributors

PersonTokensPropCommitsCommitProp
Shilpasri G Bhat130100.00%1100.00%
Total130100.00%1100.00%


static int get_nr_attrs(const __be32 *ops, int len) { int i, j; int nr_attrs = 0; for (i = 0; i < len; i++) for (j = 0; j < ARRAY_SIZE(ops_info); j++) if (be32_to_cpu(ops[i]) == ops_info[j].opal_no) nr_attrs++; return nr_attrs; }

Contributors

PersonTokensPropCommitsCommitProp
Shilpasri G Bhat76100.00%1100.00%
Total76100.00%1100.00%


void __init opal_sensor_groups_init(void) { struct device_node *sg, *node; int i = 0; sg = of_find_compatible_node(NULL, NULL, "ibm,opal-sensor-group"); if (!sg) { pr_devel("Sensor groups node not found\n"); return; } sgs = kcalloc(of_get_child_count(sg), sizeof(*sgs), GFP_KERNEL); if (!sgs) return; sg_kobj = kobject_create_and_add("sensor_groups", opal_kobj); if (!sg_kobj) { pr_warn("Failed to create sensor group kobject\n"); goto out_sgs; } for_each_child_of_node(sg, node) { const __be32 *ops; u32 sgid, len, nr_attrs, chipid; ops = of_get_property(node, "ops", &len); if (!ops) continue; nr_attrs = get_nr_attrs(ops, len); if (!nr_attrs) continue; sgs[i].sgattrs = kcalloc(nr_attrs, sizeof(struct sg_attr), GFP_KERNEL); if (!sgs[i].sgattrs) goto out_sgs_sgattrs; sgs[i].sg.attrs = kcalloc(nr_attrs + 1, sizeof(struct attribute *), GFP_KERNEL); if (!sgs[i].sg.attrs) { kfree(sgs[i].sgattrs); goto out_sgs_sgattrs; } if (of_property_read_u32(node, "sensor-group-id", &sgid)) { pr_warn("sensor-group-id property not found\n"); goto out_sgs_sgattrs; } if (!of_property_read_u32(node, "ibm,chip-id", &chipid)) sprintf(sgs[i].name, "%s%d", node->name, chipid); else sprintf(sgs[i].name, "%s", node->name); sgs[i].sg.name = sgs[i].name; if (add_attr_group(ops, len, &sgs[i], sgid)) { pr_warn("Failed to create sensor attribute group %s\n", sgs[i].sg.name); goto out_sgs_sgattrs; } i++; } return; out_sgs_sgattrs: while (--i >= 0) { kfree(sgs[i].sgattrs); kfree(sgs[i].sg.attrs); } kobject_put(sg_kobj); out_sgs: kfree(sgs); }

Contributors

PersonTokensPropCommitsCommitProp
Shilpasri G Bhat404100.00%1100.00%
Total404100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Shilpasri G Bhat1017100.00%1100.00%
Total1017100.00%1100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.