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