cregit-Linux how code gets into the kernel

Release 4.7 drivers/s390/char/sclp_cpi_sys.c

/*
 *    SCLP control program identification sysfs interface
 *
 *    Copyright IBM Corp. 2001, 2007
 *    Author(s): Martin Peschke <mpeschke@de.ibm.com>
 *               Michael Ernst <mernst@de.ibm.com>
 */


#define KMSG_COMPONENT "sclp_cpi"

#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/stat.h>
#include <linux/device.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/kmod.h>
#include <linux/timer.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/export.h>
#include <asm/ebcdic.h>
#include <asm/sclp.h>

#include "sclp.h"
#include "sclp_rw.h"
#include "sclp_cpi_sys.h"


#define CPI_LENGTH_NAME 8

#define CPI_LENGTH_LEVEL 16

static DEFINE_MUTEX(sclp_cpi_mutex);


struct cpi_evbuf {
	
struct evbuf_header header;
	
u8	id_format;
	
u8	reserved0;
	
u8	system_type[CPI_LENGTH_NAME];
	
u64	reserved1;
	
u8	system_name[CPI_LENGTH_NAME];
	
u64	reserved2;
	
u64	system_level;
	
u64	reserved3;
	
u8	sysplex_name[CPI_LENGTH_NAME];
	
u8	reserved4[16];
} __attribute__((packed));


struct cpi_sccb {
	
struct sccb_header header;
	
struct cpi_evbuf cpi_evbuf;
} __attribute__((packed));


static struct sclp_register sclp_cpi_event = {
	.send_mask = EVTYP_CTLPROGIDENT_MASK,
};


static char system_name[CPI_LENGTH_NAME + 1];

static char sysplex_name[CPI_LENGTH_NAME + 1];

static char system_type[CPI_LENGTH_NAME + 1];

static u64 system_level;


static void set_data(char *field, char *data) { memset(field, ' ', CPI_LENGTH_NAME); memcpy(field, data, strlen(data)); sclp_ascebc_str(field, CPI_LENGTH_NAME); }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst42100.00%1100.00%
Total42100.00%1100.00%


static void cpi_callback(struct sclp_req *req, void *data) { struct completion *completion = data; complete(completion); }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst27100.00%1100.00%
Total27100.00%1100.00%


static struct sclp_req *cpi_prepare_req(void) { struct sclp_req *req; struct cpi_sccb *sccb; struct cpi_evbuf *evb; req = kzalloc(sizeof(struct sclp_req), GFP_KERNEL); if (!req) return ERR_PTR(-ENOMEM); sccb = (struct cpi_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); if (!sccb) { kfree(req); return ERR_PTR(-ENOMEM); } /* setup SCCB for Control-Program Identification */ sccb->header.length = sizeof(struct cpi_sccb); sccb->cpi_evbuf.header.length = sizeof(struct cpi_evbuf); sccb->cpi_evbuf.header.type = EVTYP_CTLPROGIDENT; evb = &sccb->cpi_evbuf; /* set system type */ set_data(evb->system_type, system_type); /* set system name */ set_data(evb->system_name, system_name); /* set system level */ evb->system_level = system_level; /* set sysplex name */ set_data(evb->sysplex_name, sysplex_name); /* prepare request data structure presented to SCLP driver */ req->command = SCLP_CMDW_WRITE_EVENT_DATA; req->sccb = sccb; req->status = SCLP_REQ_FILLED; req->callback = cpi_callback; return req; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst19098.96%133.33%
sebastian ottsebastian ott10.52%133.33%
thomas weberthomas weber10.52%133.33%
Total192100.00%3100.00%


static void cpi_free_req(struct sclp_req *req) { free_page((unsigned long) req->sccb); kfree(req); }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst27100.00%1100.00%
Total27100.00%1100.00%


static int cpi_req(void) { struct completion completion; struct sclp_req *req; int rc; int response; rc = sclp_register(&sclp_cpi_event); if (rc) goto out; if (!(sclp_cpi_event.sclp_receive_mask & EVTYP_CTLPROGIDENT_MASK)) { rc = -EOPNOTSUPP; goto out_unregister; } req = cpi_prepare_req(); if (IS_ERR(req)) { rc = PTR_ERR(req); goto out_unregister; } init_completion(&completion); req->callback_data = &completion; /* Add request to sclp queue */ rc = sclp_add_request(req); if (rc) goto out_free_req; wait_for_completion(&completion); if (req->status != SCLP_REQ_DONE) { pr_warn("request failed (status=0x%02x)\n", req->status); rc = -EIO; goto out_free_req; } response = ((struct cpi_sccb *) req->sccb)->header.response_code; if (response != 0x0020) { pr_warn("request failed with response code 0x%x\n", response); rc = -EIO; } out_free_req: cpi_free_req(req); out_unregister: sclp_unregister(&sclp_cpi_event); out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst19697.51%125.00%
joe perchesjoe perches21.00%125.00%
martin schwidefskymartin schwidefsky21.00%125.00%
peter oberparleiterpeter oberparleiter10.50%125.00%
Total201100.00%4100.00%


static int check_string(const char *attr, const char *str) { size_t len; size_t i; len = strlen(str); if ((len > 0) && (str[len - 1] == '\n')) len--; if (len > CPI_LENGTH_NAME) return -EINVAL; for (i = 0; i < len ; i++) { if (isalpha(str[i]) || isdigit(str[i]) || strchr("$@# ", str[i])) continue; return -EINVAL; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst112100.00%1100.00%
Total112100.00%1100.00%


static void set_string(char *attr, const char *value) { size_t len; size_t i; len = strlen(value); if ((len > 0) && (value[len - 1] == '\n')) len--; for (i = 0; i < CPI_LENGTH_NAME; i++) { if (i < len) attr[i] = toupper(value[i]); else attr[i] = ' '; } }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst92100.00%1100.00%
Total92100.00%1100.00%


static ssize_t system_name_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { int rc; mutex_lock(&sclp_cpi_mutex); rc = snprintf(page, PAGE_SIZE, "%s\n", system_name); mutex_unlock(&sclp_cpi_mutex); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst51100.00%2100.00%
Total51100.00%2100.00%


static ssize_t system_name_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len) { int rc; rc = check_string("system_name", buf); if (rc) return rc; mutex_lock(&sclp_cpi_mutex); set_string(system_name, buf); mutex_unlock(&sclp_cpi_mutex); return len; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst65100.00%2100.00%
Total65100.00%2100.00%

static struct kobj_attribute system_name_attr = __ATTR(system_name, 0644, system_name_show, system_name_store);
static ssize_t sysplex_name_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { int rc; mutex_lock(&sclp_cpi_mutex); rc = snprintf(page, PAGE_SIZE, "%s\n", sysplex_name); mutex_unlock(&sclp_cpi_mutex); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst51100.00%2100.00%
Total51100.00%2100.00%


static ssize_t sysplex_name_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len) { int rc; rc = check_string("sysplex_name", buf); if (rc) return rc; mutex_lock(&sclp_cpi_mutex); set_string(sysplex_name, buf); mutex_unlock(&sclp_cpi_mutex); return len; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst65100.00%2100.00%
Total65100.00%2100.00%

static struct kobj_attribute sysplex_name_attr = __ATTR(sysplex_name, 0644, sysplex_name_show, sysplex_name_store);
static ssize_t system_type_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { int rc; mutex_lock(&sclp_cpi_mutex); rc = snprintf(page, PAGE_SIZE, "%s\n", system_type); mutex_unlock(&sclp_cpi_mutex); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst51100.00%2100.00%
Total51100.00%2100.00%


static ssize_t system_type_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len) { int rc; rc = check_string("system_type", buf); if (rc) return rc; mutex_lock(&sclp_cpi_mutex); set_string(system_type, buf); mutex_unlock(&sclp_cpi_mutex); return len; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst65100.00%2100.00%
Total65100.00%2100.00%

static struct kobj_attribute system_type_attr = __ATTR(system_type, 0644, system_type_show, system_type_store);
static ssize_t system_level_show(struct kobject *kobj, struct kobj_attribute *attr, char *page) { unsigned long long level; mutex_lock(&sclp_cpi_mutex); level = system_level; mutex_unlock(&sclp_cpi_mutex); return snprintf(page, PAGE_SIZE, "%#018llx\n", level); }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst53100.00%2100.00%
Total53100.00%2100.00%


static ssize_t system_level_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len) { unsigned long long level; char *endp; level = simple_strtoull(buf, &endp, 16); if (endp == buf) return -EINVAL; if (*endp == '\n') endp++; if (*endp) return -EINVAL; mutex_lock(&sclp_cpi_mutex); system_level = level; mutex_unlock(&sclp_cpi_mutex); return len; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst93100.00%2100.00%
Total93100.00%2100.00%

static struct kobj_attribute system_level_attr = __ATTR(system_level, 0644, system_level_show, system_level_store);
static ssize_t set_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len) { int rc; mutex_lock(&sclp_cpi_mutex); rc = cpi_req(); mutex_unlock(&sclp_cpi_mutex); if (rc) return rc; return len; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst54100.00%2100.00%
Total54100.00%2100.00%

static struct kobj_attribute set_attr = __ATTR(set, 0200, NULL, set_store); static struct attribute *cpi_attrs[] = { &system_name_attr.attr, &sysplex_name_attr.attr, &system_type_attr.attr, &system_level_attr.attr, &set_attr.attr, NULL, }; static struct attribute_group cpi_attr_group = { .attrs = cpi_attrs, }; static struct kset *cpi_kset;
int sclp_cpi_set_data(const char *system, const char *sysplex, const char *type, const u64 level) { int rc; rc = check_string("system_name", system); if (rc) return rc; rc = check_string("sysplex_name", sysplex); if (rc) return rc; rc = check_string("system_type", type); if (rc) return rc; mutex_lock(&sclp_cpi_mutex); set_string(system_name, system); set_string(sysplex_name, sysplex); set_string(system_type, type); system_level = level; rc = cpi_req(); mutex_unlock(&sclp_cpi_mutex); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst120100.00%2100.00%
Total120100.00%2100.00%

EXPORT_SYMBOL(sclp_cpi_set_data);
static int __init cpi_init(void) { int rc; cpi_kset = kset_create_and_add("cpi", NULL, firmware_kobj); if (!cpi_kset) return -ENOMEM; rc = sysfs_create_group(&cpi_kset->kobj, &cpi_attr_group); if (rc) kset_unregister(cpi_kset); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst57100.00%1100.00%
Total57100.00%1100.00%

__initcall(cpi_init);

Overall Contributors

PersonTokensPropCommitsCommitProp
michael ernstmichael ernst173698.75%222.22%
martin schwidefskymartin schwidefsky130.74%111.11%
heiko carstensheiko carstens40.23%222.22%
joe perchesjoe perches20.11%111.11%
peter oberparleiterpeter oberparleiter10.06%111.11%
thomas weberthomas weber10.06%111.11%
sebastian ottsebastian ott10.06%111.11%
Total1758100.00%9100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}