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