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