1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2c05ffc4fSMichael Ernst /* 3c05ffc4fSMichael Ernst * SCLP control program identification sysfs interface 4c05ffc4fSMichael Ernst * 5c05ffc4fSMichael Ernst * Copyright IBM Corp. 2001, 2007 6c05ffc4fSMichael Ernst * Author(s): Martin Peschke <mpeschke@de.ibm.com> 7c05ffc4fSMichael Ernst * Michael Ernst <mernst@de.ibm.com> 8c05ffc4fSMichael Ernst */ 9c05ffc4fSMichael Ernst 10b3ff088bSMartin Schwidefsky #define KMSG_COMPONENT "sclp_cpi" 11b3ff088bSMartin Schwidefsky #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 12b3ff088bSMartin Schwidefsky 13c05ffc4fSMichael Ernst #include <linux/kernel.h> 14c05ffc4fSMichael Ernst #include <linux/init.h> 15c05ffc4fSMichael Ernst #include <linux/stat.h> 16c05ffc4fSMichael Ernst #include <linux/device.h> 17c05ffc4fSMichael Ernst #include <linux/string.h> 18c05ffc4fSMichael Ernst #include <linux/ctype.h> 19c05ffc4fSMichael Ernst #include <linux/kmod.h> 20c05ffc4fSMichael Ernst #include <linux/timer.h> 21c05ffc4fSMichael Ernst #include <linux/err.h> 22c05ffc4fSMichael Ernst #include <linux/slab.h> 23c05ffc4fSMichael Ernst #include <linux/completion.h> 243a4c5d59SHeiko Carstens #include <linux/export.h> 25c05ffc4fSMichael Ernst #include <asm/ebcdic.h> 26c05ffc4fSMichael Ernst #include <asm/sclp.h> 27b3ff088bSMartin Schwidefsky 28c05ffc4fSMichael Ernst #include "sclp.h" 29c05ffc4fSMichael Ernst #include "sclp_rw.h" 30c05ffc4fSMichael Ernst #include "sclp_cpi_sys.h" 31c05ffc4fSMichael Ernst 32c05ffc4fSMichael Ernst #define CPI_LENGTH_NAME 8 33c05ffc4fSMichael Ernst #define CPI_LENGTH_LEVEL 16 34c05ffc4fSMichael Ernst 35b1c02d91SMichael Ernst static DEFINE_MUTEX(sclp_cpi_mutex); 36b1c02d91SMichael Ernst 37c05ffc4fSMichael Ernst struct cpi_evbuf { 38c05ffc4fSMichael Ernst struct evbuf_header header; 39c05ffc4fSMichael Ernst u8 id_format; 40c05ffc4fSMichael Ernst u8 reserved0; 41c05ffc4fSMichael Ernst u8 system_type[CPI_LENGTH_NAME]; 42c05ffc4fSMichael Ernst u64 reserved1; 43c05ffc4fSMichael Ernst u8 system_name[CPI_LENGTH_NAME]; 44c05ffc4fSMichael Ernst u64 reserved2; 45c05ffc4fSMichael Ernst u64 system_level; 46c05ffc4fSMichael Ernst u64 reserved3; 47c05ffc4fSMichael Ernst u8 sysplex_name[CPI_LENGTH_NAME]; 48c05ffc4fSMichael Ernst u8 reserved4[16]; 49c05ffc4fSMichael Ernst } __attribute__((packed)); 50c05ffc4fSMichael Ernst 51c05ffc4fSMichael Ernst struct cpi_sccb { 52c05ffc4fSMichael Ernst struct sccb_header header; 53c05ffc4fSMichael Ernst struct cpi_evbuf cpi_evbuf; 54c05ffc4fSMichael Ernst } __attribute__((packed)); 55c05ffc4fSMichael Ernst 56c05ffc4fSMichael Ernst static struct sclp_register sclp_cpi_event = { 57c05ffc4fSMichael Ernst .send_mask = EVTYP_CTLPROGIDENT_MASK, 58c05ffc4fSMichael Ernst }; 59c05ffc4fSMichael Ernst 60c05ffc4fSMichael Ernst static char system_name[CPI_LENGTH_NAME + 1]; 61c05ffc4fSMichael Ernst static char sysplex_name[CPI_LENGTH_NAME + 1]; 62c05ffc4fSMichael Ernst static char system_type[CPI_LENGTH_NAME + 1]; 63c05ffc4fSMichael Ernst static u64 system_level; 64c05ffc4fSMichael Ernst 65c05ffc4fSMichael Ernst static void set_data(char *field, char *data) 66c05ffc4fSMichael Ernst { 67c05ffc4fSMichael Ernst memset(field, ' ', CPI_LENGTH_NAME); 68c05ffc4fSMichael Ernst memcpy(field, data, strlen(data)); 69c05ffc4fSMichael Ernst sclp_ascebc_str(field, CPI_LENGTH_NAME); 70c05ffc4fSMichael Ernst } 71c05ffc4fSMichael Ernst 72c05ffc4fSMichael Ernst static void cpi_callback(struct sclp_req *req, void *data) 73c05ffc4fSMichael Ernst { 74c05ffc4fSMichael Ernst struct completion *completion = data; 75c05ffc4fSMichael Ernst 76c05ffc4fSMichael Ernst complete(completion); 77c05ffc4fSMichael Ernst } 78c05ffc4fSMichael Ernst 79c05ffc4fSMichael Ernst static struct sclp_req *cpi_prepare_req(void) 80c05ffc4fSMichael Ernst { 81c05ffc4fSMichael Ernst struct sclp_req *req; 82c05ffc4fSMichael Ernst struct cpi_sccb *sccb; 83c05ffc4fSMichael Ernst struct cpi_evbuf *evb; 84c05ffc4fSMichael Ernst 85c05ffc4fSMichael Ernst req = kzalloc(sizeof(struct sclp_req), GFP_KERNEL); 86c05ffc4fSMichael Ernst if (!req) 87c05ffc4fSMichael Ernst return ERR_PTR(-ENOMEM); 88c05ffc4fSMichael Ernst sccb = (struct cpi_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 89c05ffc4fSMichael Ernst if (!sccb) { 90c05ffc4fSMichael Ernst kfree(req); 91c05ffc4fSMichael Ernst return ERR_PTR(-ENOMEM); 92c05ffc4fSMichael Ernst } 93c05ffc4fSMichael Ernst 94c05ffc4fSMichael Ernst /* setup SCCB for Control-Program Identification */ 95c05ffc4fSMichael Ernst sccb->header.length = sizeof(struct cpi_sccb); 96c05ffc4fSMichael Ernst sccb->cpi_evbuf.header.length = sizeof(struct cpi_evbuf); 973fa7ee88SSebastian Ott sccb->cpi_evbuf.header.type = EVTYP_CTLPROGIDENT; 98c05ffc4fSMichael Ernst evb = &sccb->cpi_evbuf; 99c05ffc4fSMichael Ernst 100c05ffc4fSMichael Ernst /* set system type */ 101c05ffc4fSMichael Ernst set_data(evb->system_type, system_type); 102c05ffc4fSMichael Ernst 103c05ffc4fSMichael Ernst /* set system name */ 104c05ffc4fSMichael Ernst set_data(evb->system_name, system_name); 105c05ffc4fSMichael Ernst 10688393161SThomas Weber /* set system level */ 107c05ffc4fSMichael Ernst evb->system_level = system_level; 108c05ffc4fSMichael Ernst 109c05ffc4fSMichael Ernst /* set sysplex name */ 110c05ffc4fSMichael Ernst set_data(evb->sysplex_name, sysplex_name); 111c05ffc4fSMichael Ernst 112c05ffc4fSMichael Ernst /* prepare request data structure presented to SCLP driver */ 113c05ffc4fSMichael Ernst req->command = SCLP_CMDW_WRITE_EVENT_DATA; 114c05ffc4fSMichael Ernst req->sccb = sccb; 115c05ffc4fSMichael Ernst req->status = SCLP_REQ_FILLED; 116c05ffc4fSMichael Ernst req->callback = cpi_callback; 117c05ffc4fSMichael Ernst return req; 118c05ffc4fSMichael Ernst } 119c05ffc4fSMichael Ernst 120c05ffc4fSMichael Ernst static void cpi_free_req(struct sclp_req *req) 121c05ffc4fSMichael Ernst { 122c05ffc4fSMichael Ernst free_page((unsigned long) req->sccb); 123c05ffc4fSMichael Ernst kfree(req); 124c05ffc4fSMichael Ernst } 125c05ffc4fSMichael Ernst 126c05ffc4fSMichael Ernst static int cpi_req(void) 127c05ffc4fSMichael Ernst { 128c05ffc4fSMichael Ernst struct completion completion; 129c05ffc4fSMichael Ernst struct sclp_req *req; 130c05ffc4fSMichael Ernst int rc; 131c05ffc4fSMichael Ernst int response; 132c05ffc4fSMichael Ernst 133c05ffc4fSMichael Ernst rc = sclp_register(&sclp_cpi_event); 134a12c53f4SMartin Schwidefsky if (rc) 135c05ffc4fSMichael Ernst goto out; 136d082d3ceSPeter Oberparleiter if (!(sclp_cpi_event.sclp_receive_mask & EVTYP_CTLPROGIDENT_MASK)) { 137c05ffc4fSMichael Ernst rc = -EOPNOTSUPP; 138c05ffc4fSMichael Ernst goto out_unregister; 139c05ffc4fSMichael Ernst } 140c05ffc4fSMichael Ernst 141c05ffc4fSMichael Ernst req = cpi_prepare_req(); 142c05ffc4fSMichael Ernst if (IS_ERR(req)) { 143c05ffc4fSMichael Ernst rc = PTR_ERR(req); 144c05ffc4fSMichael Ernst goto out_unregister; 145c05ffc4fSMichael Ernst } 146c05ffc4fSMichael Ernst 147c05ffc4fSMichael Ernst init_completion(&completion); 148c05ffc4fSMichael Ernst req->callback_data = &completion; 149c05ffc4fSMichael Ernst 150c05ffc4fSMichael Ernst /* Add request to sclp queue */ 151c05ffc4fSMichael Ernst rc = sclp_add_request(req); 152a12c53f4SMartin Schwidefsky if (rc) 153c05ffc4fSMichael Ernst goto out_free_req; 154c05ffc4fSMichael Ernst 155c05ffc4fSMichael Ernst wait_for_completion(&completion); 156c05ffc4fSMichael Ernst 157c05ffc4fSMichael Ernst if (req->status != SCLP_REQ_DONE) { 158baebc70aSJoe Perches pr_warn("request failed (status=0x%02x)\n", req->status); 159c05ffc4fSMichael Ernst rc = -EIO; 160c05ffc4fSMichael Ernst goto out_free_req; 161c05ffc4fSMichael Ernst } 162c05ffc4fSMichael Ernst 163c05ffc4fSMichael Ernst response = ((struct cpi_sccb *) req->sccb)->header.response_code; 164c05ffc4fSMichael Ernst if (response != 0x0020) { 165baebc70aSJoe Perches pr_warn("request failed with response code 0x%x\n", response); 166c05ffc4fSMichael Ernst rc = -EIO; 167c05ffc4fSMichael Ernst } 168c05ffc4fSMichael Ernst 169c05ffc4fSMichael Ernst out_free_req: 170c05ffc4fSMichael Ernst cpi_free_req(req); 171c05ffc4fSMichael Ernst 172c05ffc4fSMichael Ernst out_unregister: 173c05ffc4fSMichael Ernst sclp_unregister(&sclp_cpi_event); 174c05ffc4fSMichael Ernst 175c05ffc4fSMichael Ernst out: 176c05ffc4fSMichael Ernst return rc; 177c05ffc4fSMichael Ernst } 178c05ffc4fSMichael Ernst 179c05ffc4fSMichael Ernst static int check_string(const char *attr, const char *str) 180c05ffc4fSMichael Ernst { 181c05ffc4fSMichael Ernst size_t len; 182c05ffc4fSMichael Ernst size_t i; 183c05ffc4fSMichael Ernst 184c05ffc4fSMichael Ernst len = strlen(str); 185c05ffc4fSMichael Ernst 186c05ffc4fSMichael Ernst if ((len > 0) && (str[len - 1] == '\n')) 187c05ffc4fSMichael Ernst len--; 188c05ffc4fSMichael Ernst 189c05ffc4fSMichael Ernst if (len > CPI_LENGTH_NAME) 190c05ffc4fSMichael Ernst return -EINVAL; 191c05ffc4fSMichael Ernst 192c05ffc4fSMichael Ernst for (i = 0; i < len ; i++) { 193c05ffc4fSMichael Ernst if (isalpha(str[i]) || isdigit(str[i]) || 194c05ffc4fSMichael Ernst strchr("$@# ", str[i])) 195c05ffc4fSMichael Ernst continue; 196c05ffc4fSMichael Ernst return -EINVAL; 197c05ffc4fSMichael Ernst } 198c05ffc4fSMichael Ernst 199c05ffc4fSMichael Ernst return 0; 200c05ffc4fSMichael Ernst } 201c05ffc4fSMichael Ernst 202c05ffc4fSMichael Ernst static void set_string(char *attr, const char *value) 203c05ffc4fSMichael Ernst { 204c05ffc4fSMichael Ernst size_t len; 205c05ffc4fSMichael Ernst size_t i; 206c05ffc4fSMichael Ernst 207c05ffc4fSMichael Ernst len = strlen(value); 208c05ffc4fSMichael Ernst 209c05ffc4fSMichael Ernst if ((len > 0) && (value[len - 1] == '\n')) 210c05ffc4fSMichael Ernst len--; 211c05ffc4fSMichael Ernst 212c05ffc4fSMichael Ernst for (i = 0; i < CPI_LENGTH_NAME; i++) { 213c05ffc4fSMichael Ernst if (i < len) 214c05ffc4fSMichael Ernst attr[i] = toupper(value[i]); 215c05ffc4fSMichael Ernst else 216c05ffc4fSMichael Ernst attr[i] = ' '; 217c05ffc4fSMichael Ernst } 218c05ffc4fSMichael Ernst } 219c05ffc4fSMichael Ernst 220c05ffc4fSMichael Ernst static ssize_t system_name_show(struct kobject *kobj, 221c05ffc4fSMichael Ernst struct kobj_attribute *attr, char *page) 222c05ffc4fSMichael Ernst { 223b1c02d91SMichael Ernst int rc; 224b1c02d91SMichael Ernst 225b1c02d91SMichael Ernst mutex_lock(&sclp_cpi_mutex); 226b1c02d91SMichael Ernst rc = snprintf(page, PAGE_SIZE, "%s\n", system_name); 227b1c02d91SMichael Ernst mutex_unlock(&sclp_cpi_mutex); 228b1c02d91SMichael Ernst return rc; 229c05ffc4fSMichael Ernst } 230c05ffc4fSMichael Ernst 231c05ffc4fSMichael Ernst static ssize_t system_name_store(struct kobject *kobj, 232c05ffc4fSMichael Ernst struct kobj_attribute *attr, 233c05ffc4fSMichael Ernst const char *buf, 234c05ffc4fSMichael Ernst size_t len) 235c05ffc4fSMichael Ernst { 236c05ffc4fSMichael Ernst int rc; 237c05ffc4fSMichael Ernst 238c05ffc4fSMichael Ernst rc = check_string("system_name", buf); 239c05ffc4fSMichael Ernst if (rc) 240c05ffc4fSMichael Ernst return rc; 241c05ffc4fSMichael Ernst 242b1c02d91SMichael Ernst mutex_lock(&sclp_cpi_mutex); 243c05ffc4fSMichael Ernst set_string(system_name, buf); 244b1c02d91SMichael Ernst mutex_unlock(&sclp_cpi_mutex); 245c05ffc4fSMichael Ernst 246c05ffc4fSMichael Ernst return len; 247c05ffc4fSMichael Ernst } 248c05ffc4fSMichael Ernst 249c05ffc4fSMichael Ernst static struct kobj_attribute system_name_attr = 250c05ffc4fSMichael Ernst __ATTR(system_name, 0644, system_name_show, system_name_store); 251c05ffc4fSMichael Ernst 252c05ffc4fSMichael Ernst static ssize_t sysplex_name_show(struct kobject *kobj, 253c05ffc4fSMichael Ernst struct kobj_attribute *attr, char *page) 254c05ffc4fSMichael Ernst { 255b1c02d91SMichael Ernst int rc; 256b1c02d91SMichael Ernst 257b1c02d91SMichael Ernst mutex_lock(&sclp_cpi_mutex); 258b1c02d91SMichael Ernst rc = snprintf(page, PAGE_SIZE, "%s\n", sysplex_name); 259b1c02d91SMichael Ernst mutex_unlock(&sclp_cpi_mutex); 260b1c02d91SMichael Ernst return rc; 261c05ffc4fSMichael Ernst } 262c05ffc4fSMichael Ernst 263c05ffc4fSMichael Ernst static ssize_t sysplex_name_store(struct kobject *kobj, 264c05ffc4fSMichael Ernst struct kobj_attribute *attr, 265c05ffc4fSMichael Ernst const char *buf, 266c05ffc4fSMichael Ernst size_t len) 267c05ffc4fSMichael Ernst { 268c05ffc4fSMichael Ernst int rc; 269c05ffc4fSMichael Ernst 270c05ffc4fSMichael Ernst rc = check_string("sysplex_name", buf); 271c05ffc4fSMichael Ernst if (rc) 272c05ffc4fSMichael Ernst return rc; 273c05ffc4fSMichael Ernst 274b1c02d91SMichael Ernst mutex_lock(&sclp_cpi_mutex); 275c05ffc4fSMichael Ernst set_string(sysplex_name, buf); 276b1c02d91SMichael Ernst mutex_unlock(&sclp_cpi_mutex); 277c05ffc4fSMichael Ernst 278c05ffc4fSMichael Ernst return len; 279c05ffc4fSMichael Ernst } 280c05ffc4fSMichael Ernst 281c05ffc4fSMichael Ernst static struct kobj_attribute sysplex_name_attr = 282c05ffc4fSMichael Ernst __ATTR(sysplex_name, 0644, sysplex_name_show, sysplex_name_store); 283c05ffc4fSMichael Ernst 284c05ffc4fSMichael Ernst static ssize_t system_type_show(struct kobject *kobj, 285c05ffc4fSMichael Ernst struct kobj_attribute *attr, char *page) 286c05ffc4fSMichael Ernst { 287b1c02d91SMichael Ernst int rc; 288b1c02d91SMichael Ernst 289b1c02d91SMichael Ernst mutex_lock(&sclp_cpi_mutex); 290b1c02d91SMichael Ernst rc = snprintf(page, PAGE_SIZE, "%s\n", system_type); 291b1c02d91SMichael Ernst mutex_unlock(&sclp_cpi_mutex); 292b1c02d91SMichael Ernst return rc; 293c05ffc4fSMichael Ernst } 294c05ffc4fSMichael Ernst 295c05ffc4fSMichael Ernst static ssize_t system_type_store(struct kobject *kobj, 296c05ffc4fSMichael Ernst struct kobj_attribute *attr, 297c05ffc4fSMichael Ernst const char *buf, 298c05ffc4fSMichael Ernst size_t len) 299c05ffc4fSMichael Ernst { 300c05ffc4fSMichael Ernst int rc; 301c05ffc4fSMichael Ernst 302c05ffc4fSMichael Ernst rc = check_string("system_type", buf); 303c05ffc4fSMichael Ernst if (rc) 304c05ffc4fSMichael Ernst return rc; 305c05ffc4fSMichael Ernst 306b1c02d91SMichael Ernst mutex_lock(&sclp_cpi_mutex); 307c05ffc4fSMichael Ernst set_string(system_type, buf); 308b1c02d91SMichael Ernst mutex_unlock(&sclp_cpi_mutex); 309c05ffc4fSMichael Ernst 310c05ffc4fSMichael Ernst return len; 311c05ffc4fSMichael Ernst } 312c05ffc4fSMichael Ernst 313c05ffc4fSMichael Ernst static struct kobj_attribute system_type_attr = 314c05ffc4fSMichael Ernst __ATTR(system_type, 0644, system_type_show, system_type_store); 315c05ffc4fSMichael Ernst 316c05ffc4fSMichael Ernst static ssize_t system_level_show(struct kobject *kobj, 317c05ffc4fSMichael Ernst struct kobj_attribute *attr, char *page) 318c05ffc4fSMichael Ernst { 319b1c02d91SMichael Ernst unsigned long long level; 320c05ffc4fSMichael Ernst 321b1c02d91SMichael Ernst mutex_lock(&sclp_cpi_mutex); 322b1c02d91SMichael Ernst level = system_level; 323b1c02d91SMichael Ernst mutex_unlock(&sclp_cpi_mutex); 324c05ffc4fSMichael Ernst return snprintf(page, PAGE_SIZE, "%#018llx\n", level); 325c05ffc4fSMichael Ernst } 326c05ffc4fSMichael Ernst 327c05ffc4fSMichael Ernst static ssize_t system_level_store(struct kobject *kobj, 328c05ffc4fSMichael Ernst struct kobj_attribute *attr, 329c05ffc4fSMichael Ernst const char *buf, 330c05ffc4fSMichael Ernst size_t len) 331c05ffc4fSMichael Ernst { 332c05ffc4fSMichael Ernst unsigned long long level; 333c05ffc4fSMichael Ernst char *endp; 334c05ffc4fSMichael Ernst 335c05ffc4fSMichael Ernst level = simple_strtoull(buf, &endp, 16); 336c05ffc4fSMichael Ernst 337c05ffc4fSMichael Ernst if (endp == buf) 338c05ffc4fSMichael Ernst return -EINVAL; 339c05ffc4fSMichael Ernst if (*endp == '\n') 340c05ffc4fSMichael Ernst endp++; 341c05ffc4fSMichael Ernst if (*endp) 342c05ffc4fSMichael Ernst return -EINVAL; 343c05ffc4fSMichael Ernst 344b1c02d91SMichael Ernst mutex_lock(&sclp_cpi_mutex); 345c05ffc4fSMichael Ernst system_level = level; 346b1c02d91SMichael Ernst mutex_unlock(&sclp_cpi_mutex); 347c05ffc4fSMichael Ernst return len; 348c05ffc4fSMichael Ernst } 349c05ffc4fSMichael Ernst 350c05ffc4fSMichael Ernst static struct kobj_attribute system_level_attr = 351c05ffc4fSMichael Ernst __ATTR(system_level, 0644, system_level_show, system_level_store); 352c05ffc4fSMichael Ernst 353c05ffc4fSMichael Ernst static ssize_t set_store(struct kobject *kobj, 354c05ffc4fSMichael Ernst struct kobj_attribute *attr, 355c05ffc4fSMichael Ernst const char *buf, size_t len) 356c05ffc4fSMichael Ernst { 357c05ffc4fSMichael Ernst int rc; 358c05ffc4fSMichael Ernst 359b1c02d91SMichael Ernst mutex_lock(&sclp_cpi_mutex); 360c05ffc4fSMichael Ernst rc = cpi_req(); 361b1c02d91SMichael Ernst mutex_unlock(&sclp_cpi_mutex); 362c05ffc4fSMichael Ernst if (rc) 363c05ffc4fSMichael Ernst return rc; 364c05ffc4fSMichael Ernst 365c05ffc4fSMichael Ernst return len; 366c05ffc4fSMichael Ernst } 367c05ffc4fSMichael Ernst 368c05ffc4fSMichael Ernst static struct kobj_attribute set_attr = __ATTR(set, 0200, NULL, set_store); 369c05ffc4fSMichael Ernst 370c05ffc4fSMichael Ernst static struct attribute *cpi_attrs[] = { 371c05ffc4fSMichael Ernst &system_name_attr.attr, 372c05ffc4fSMichael Ernst &sysplex_name_attr.attr, 373c05ffc4fSMichael Ernst &system_type_attr.attr, 374c05ffc4fSMichael Ernst &system_level_attr.attr, 375c05ffc4fSMichael Ernst &set_attr.attr, 376c05ffc4fSMichael Ernst NULL, 377c05ffc4fSMichael Ernst }; 378c05ffc4fSMichael Ernst 379c05ffc4fSMichael Ernst static struct attribute_group cpi_attr_group = { 380c05ffc4fSMichael Ernst .attrs = cpi_attrs, 381c05ffc4fSMichael Ernst }; 382c05ffc4fSMichael Ernst 383c05ffc4fSMichael Ernst static struct kset *cpi_kset; 384c05ffc4fSMichael Ernst 385c05ffc4fSMichael Ernst int sclp_cpi_set_data(const char *system, const char *sysplex, const char *type, 386c05ffc4fSMichael Ernst const u64 level) 387c05ffc4fSMichael Ernst { 388c05ffc4fSMichael Ernst int rc; 389c05ffc4fSMichael Ernst 390c05ffc4fSMichael Ernst rc = check_string("system_name", system); 391c05ffc4fSMichael Ernst if (rc) 392c05ffc4fSMichael Ernst return rc; 393c05ffc4fSMichael Ernst rc = check_string("sysplex_name", sysplex); 394c05ffc4fSMichael Ernst if (rc) 395c05ffc4fSMichael Ernst return rc; 396c05ffc4fSMichael Ernst rc = check_string("system_type", type); 397c05ffc4fSMichael Ernst if (rc) 398c05ffc4fSMichael Ernst return rc; 399c05ffc4fSMichael Ernst 400b1c02d91SMichael Ernst mutex_lock(&sclp_cpi_mutex); 401c05ffc4fSMichael Ernst set_string(system_name, system); 402c05ffc4fSMichael Ernst set_string(sysplex_name, sysplex); 403c05ffc4fSMichael Ernst set_string(system_type, type); 404c05ffc4fSMichael Ernst system_level = level; 405c05ffc4fSMichael Ernst 406b1c02d91SMichael Ernst rc = cpi_req(); 407b1c02d91SMichael Ernst mutex_unlock(&sclp_cpi_mutex); 408b1c02d91SMichael Ernst 409b1c02d91SMichael Ernst return rc; 410c05ffc4fSMichael Ernst } 411c05ffc4fSMichael Ernst EXPORT_SYMBOL(sclp_cpi_set_data); 412c05ffc4fSMichael Ernst 413c05ffc4fSMichael Ernst static int __init cpi_init(void) 414c05ffc4fSMichael Ernst { 415c05ffc4fSMichael Ernst int rc; 416c05ffc4fSMichael Ernst 417c05ffc4fSMichael Ernst cpi_kset = kset_create_and_add("cpi", NULL, firmware_kobj); 418c05ffc4fSMichael Ernst if (!cpi_kset) 419c05ffc4fSMichael Ernst return -ENOMEM; 420c05ffc4fSMichael Ernst 421c05ffc4fSMichael Ernst rc = sysfs_create_group(&cpi_kset->kobj, &cpi_attr_group); 422c05ffc4fSMichael Ernst if (rc) 423c05ffc4fSMichael Ernst kset_unregister(cpi_kset); 424c05ffc4fSMichael Ernst 425c05ffc4fSMichael Ernst return rc; 426c05ffc4fSMichael Ernst } 427c05ffc4fSMichael Ernst 428c05ffc4fSMichael Ernst __initcall(cpi_init); 429