Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *    SCLP control program identification sysfs interface
0004  *
0005  *    Copyright IBM Corp. 2001, 2007
0006  *    Author(s): Martin Peschke <mpeschke@de.ibm.com>
0007  *       Michael Ernst <mernst@de.ibm.com>
0008  */
0009 
0010 #define KMSG_COMPONENT "sclp_cpi"
0011 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0012 
0013 #include <linux/kernel.h>
0014 #include <linux/init.h>
0015 #include <linux/stat.h>
0016 #include <linux/device.h>
0017 #include <linux/string.h>
0018 #include <linux/ctype.h>
0019 #include <linux/kmod.h>
0020 #include <linux/timer.h>
0021 #include <linux/err.h>
0022 #include <linux/slab.h>
0023 #include <linux/completion.h>
0024 #include <linux/export.h>
0025 #include <asm/ebcdic.h>
0026 #include <asm/sclp.h>
0027 
0028 #include "sclp.h"
0029 #include "sclp_rw.h"
0030 #include "sclp_cpi_sys.h"
0031 
0032 #define CPI_LENGTH_NAME 8
0033 #define CPI_LENGTH_LEVEL 16
0034 
0035 static DEFINE_MUTEX(sclp_cpi_mutex);
0036 
0037 struct cpi_evbuf {
0038     struct evbuf_header header;
0039     u8  id_format;
0040     u8  reserved0;
0041     u8  system_type[CPI_LENGTH_NAME];
0042     u64 reserved1;
0043     u8  system_name[CPI_LENGTH_NAME];
0044     u64 reserved2;
0045     u64 system_level;
0046     u64 reserved3;
0047     u8  sysplex_name[CPI_LENGTH_NAME];
0048     u8  reserved4[16];
0049 } __attribute__((packed));
0050 
0051 struct cpi_sccb {
0052     struct sccb_header header;
0053     struct cpi_evbuf cpi_evbuf;
0054 } __attribute__((packed));
0055 
0056 static struct sclp_register sclp_cpi_event = {
0057     .send_mask = EVTYP_CTLPROGIDENT_MASK,
0058 };
0059 
0060 static char system_name[CPI_LENGTH_NAME + 1];
0061 static char sysplex_name[CPI_LENGTH_NAME + 1];
0062 static char system_type[CPI_LENGTH_NAME + 1];
0063 static u64 system_level;
0064 
0065 static void set_data(char *field, char *data)
0066 {
0067     memset(field, ' ', CPI_LENGTH_NAME);
0068     memcpy(field, data, strlen(data));
0069     sclp_ascebc_str(field, CPI_LENGTH_NAME);
0070 }
0071 
0072 static void cpi_callback(struct sclp_req *req, void *data)
0073 {
0074     struct completion *completion = data;
0075 
0076     complete(completion);
0077 }
0078 
0079 static struct sclp_req *cpi_prepare_req(void)
0080 {
0081     struct sclp_req *req;
0082     struct cpi_sccb *sccb;
0083     struct cpi_evbuf *evb;
0084 
0085     req = kzalloc(sizeof(struct sclp_req), GFP_KERNEL);
0086     if (!req)
0087         return ERR_PTR(-ENOMEM);
0088     sccb = (struct cpi_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
0089     if (!sccb) {
0090         kfree(req);
0091         return ERR_PTR(-ENOMEM);
0092     }
0093 
0094     /* setup SCCB for Control-Program Identification */
0095     sccb->header.length = sizeof(struct cpi_sccb);
0096     sccb->cpi_evbuf.header.length = sizeof(struct cpi_evbuf);
0097     sccb->cpi_evbuf.header.type = EVTYP_CTLPROGIDENT;
0098     evb = &sccb->cpi_evbuf;
0099 
0100     /* set system type */
0101     set_data(evb->system_type, system_type);
0102 
0103     /* set system name */
0104     set_data(evb->system_name, system_name);
0105 
0106     /* set system level */
0107     evb->system_level = system_level;
0108 
0109     /* set sysplex name */
0110     set_data(evb->sysplex_name, sysplex_name);
0111 
0112     /* prepare request data structure presented to SCLP driver */
0113     req->command = SCLP_CMDW_WRITE_EVENT_DATA;
0114     req->sccb = sccb;
0115     req->status = SCLP_REQ_FILLED;
0116     req->callback = cpi_callback;
0117     return req;
0118 }
0119 
0120 static void cpi_free_req(struct sclp_req *req)
0121 {
0122     free_page((unsigned long) req->sccb);
0123     kfree(req);
0124 }
0125 
0126 static int cpi_req(void)
0127 {
0128     struct completion completion;
0129     struct sclp_req *req;
0130     int rc;
0131     int response;
0132 
0133     rc = sclp_register(&sclp_cpi_event);
0134     if (rc)
0135         goto out;
0136     if (!(sclp_cpi_event.sclp_receive_mask & EVTYP_CTLPROGIDENT_MASK)) {
0137         rc = -EOPNOTSUPP;
0138         goto out_unregister;
0139     }
0140 
0141     req = cpi_prepare_req();
0142     if (IS_ERR(req)) {
0143         rc = PTR_ERR(req);
0144         goto out_unregister;
0145     }
0146 
0147     init_completion(&completion);
0148     req->callback_data = &completion;
0149 
0150     /* Add request to sclp queue */
0151     rc = sclp_add_request(req);
0152     if (rc)
0153         goto out_free_req;
0154 
0155     wait_for_completion(&completion);
0156 
0157     if (req->status != SCLP_REQ_DONE) {
0158         pr_warn("request failed (status=0x%02x)\n", req->status);
0159         rc = -EIO;
0160         goto out_free_req;
0161     }
0162 
0163     response = ((struct cpi_sccb *) req->sccb)->header.response_code;
0164     if (response != 0x0020) {
0165         pr_warn("request failed with response code 0x%x\n", response);
0166         rc = -EIO;
0167     }
0168 
0169 out_free_req:
0170     cpi_free_req(req);
0171 
0172 out_unregister:
0173     sclp_unregister(&sclp_cpi_event);
0174 
0175 out:
0176     return rc;
0177 }
0178 
0179 static int check_string(const char *attr, const char *str)
0180 {
0181     size_t len;
0182     size_t i;
0183 
0184     len = strlen(str);
0185 
0186     if ((len > 0) && (str[len - 1] == '\n'))
0187         len--;
0188 
0189     if (len > CPI_LENGTH_NAME)
0190         return -EINVAL;
0191 
0192     for (i = 0; i < len ; i++) {
0193         if (isalpha(str[i]) || isdigit(str[i]) ||
0194             strchr("$@# ", str[i]))
0195             continue;
0196         return -EINVAL;
0197     }
0198 
0199     return 0;
0200 }
0201 
0202 static void set_string(char *attr, const char *value)
0203 {
0204     size_t len;
0205     size_t i;
0206 
0207     len = strlen(value);
0208 
0209     if ((len > 0) && (value[len - 1] == '\n'))
0210         len--;
0211 
0212     for (i = 0; i < CPI_LENGTH_NAME; i++) {
0213         if (i < len)
0214             attr[i] = toupper(value[i]);
0215         else
0216             attr[i] = ' ';
0217     }
0218 }
0219 
0220 static ssize_t system_name_show(struct kobject *kobj,
0221                 struct kobj_attribute *attr, char *page)
0222 {
0223     int rc;
0224 
0225     mutex_lock(&sclp_cpi_mutex);
0226     rc = snprintf(page, PAGE_SIZE, "%s\n", system_name);
0227     mutex_unlock(&sclp_cpi_mutex);
0228     return rc;
0229 }
0230 
0231 static ssize_t system_name_store(struct kobject *kobj,
0232                  struct kobj_attribute *attr,
0233                  const char *buf,
0234     size_t len)
0235 {
0236     int rc;
0237 
0238     rc = check_string("system_name", buf);
0239     if (rc)
0240         return rc;
0241 
0242     mutex_lock(&sclp_cpi_mutex);
0243     set_string(system_name, buf);
0244     mutex_unlock(&sclp_cpi_mutex);
0245 
0246     return len;
0247 }
0248 
0249 static struct kobj_attribute system_name_attr =
0250     __ATTR(system_name, 0644, system_name_show, system_name_store);
0251 
0252 static ssize_t sysplex_name_show(struct kobject *kobj,
0253                  struct kobj_attribute *attr, char *page)
0254 {
0255     int rc;
0256 
0257     mutex_lock(&sclp_cpi_mutex);
0258     rc = snprintf(page, PAGE_SIZE, "%s\n", sysplex_name);
0259     mutex_unlock(&sclp_cpi_mutex);
0260     return rc;
0261 }
0262 
0263 static ssize_t sysplex_name_store(struct kobject *kobj,
0264                   struct kobj_attribute *attr,
0265                   const char *buf,
0266     size_t len)
0267 {
0268     int rc;
0269 
0270     rc = check_string("sysplex_name", buf);
0271     if (rc)
0272         return rc;
0273 
0274     mutex_lock(&sclp_cpi_mutex);
0275     set_string(sysplex_name, buf);
0276     mutex_unlock(&sclp_cpi_mutex);
0277 
0278     return len;
0279 }
0280 
0281 static struct kobj_attribute sysplex_name_attr =
0282     __ATTR(sysplex_name, 0644, sysplex_name_show, sysplex_name_store);
0283 
0284 static ssize_t system_type_show(struct kobject *kobj,
0285                 struct kobj_attribute *attr, char *page)
0286 {
0287     int rc;
0288 
0289     mutex_lock(&sclp_cpi_mutex);
0290     rc = snprintf(page, PAGE_SIZE, "%s\n", system_type);
0291     mutex_unlock(&sclp_cpi_mutex);
0292     return rc;
0293 }
0294 
0295 static ssize_t system_type_store(struct kobject *kobj,
0296                  struct kobj_attribute *attr,
0297                  const char *buf,
0298     size_t len)
0299 {
0300     int rc;
0301 
0302     rc = check_string("system_type", buf);
0303     if (rc)
0304         return rc;
0305 
0306     mutex_lock(&sclp_cpi_mutex);
0307     set_string(system_type, buf);
0308     mutex_unlock(&sclp_cpi_mutex);
0309 
0310     return len;
0311 }
0312 
0313 static struct kobj_attribute system_type_attr =
0314     __ATTR(system_type, 0644, system_type_show, system_type_store);
0315 
0316 static ssize_t system_level_show(struct kobject *kobj,
0317                  struct kobj_attribute *attr, char *page)
0318 {
0319     unsigned long long level;
0320 
0321     mutex_lock(&sclp_cpi_mutex);
0322     level = system_level;
0323     mutex_unlock(&sclp_cpi_mutex);
0324     return snprintf(page, PAGE_SIZE, "%#018llx\n", level);
0325 }
0326 
0327 static ssize_t system_level_store(struct kobject *kobj,
0328                   struct kobj_attribute *attr,
0329                   const char *buf,
0330     size_t len)
0331 {
0332     unsigned long long level;
0333     char *endp;
0334 
0335     level = simple_strtoull(buf, &endp, 16);
0336 
0337     if (endp == buf)
0338         return -EINVAL;
0339     if (*endp == '\n')
0340         endp++;
0341     if (*endp)
0342         return -EINVAL;
0343 
0344     mutex_lock(&sclp_cpi_mutex);
0345     system_level = level;
0346     mutex_unlock(&sclp_cpi_mutex);
0347     return len;
0348 }
0349 
0350 static struct kobj_attribute system_level_attr =
0351     __ATTR(system_level, 0644, system_level_show, system_level_store);
0352 
0353 static ssize_t set_store(struct kobject *kobj,
0354              struct kobj_attribute *attr,
0355              const char *buf, size_t len)
0356 {
0357     int rc;
0358 
0359     mutex_lock(&sclp_cpi_mutex);
0360     rc = cpi_req();
0361     mutex_unlock(&sclp_cpi_mutex);
0362     if (rc)
0363         return rc;
0364 
0365     return len;
0366 }
0367 
0368 static struct kobj_attribute set_attr = __ATTR(set, 0200, NULL, set_store);
0369 
0370 static struct attribute *cpi_attrs[] = {
0371     &system_name_attr.attr,
0372     &sysplex_name_attr.attr,
0373     &system_type_attr.attr,
0374     &system_level_attr.attr,
0375     &set_attr.attr,
0376     NULL,
0377 };
0378 
0379 static struct attribute_group cpi_attr_group = {
0380     .attrs = cpi_attrs,
0381 };
0382 
0383 static struct kset *cpi_kset;
0384 
0385 int sclp_cpi_set_data(const char *system, const char *sysplex, const char *type,
0386               const u64 level)
0387 {
0388     int rc;
0389 
0390     rc = check_string("system_name", system);
0391     if (rc)
0392         return rc;
0393     rc = check_string("sysplex_name", sysplex);
0394     if (rc)
0395         return rc;
0396     rc = check_string("system_type", type);
0397     if (rc)
0398         return rc;
0399 
0400     mutex_lock(&sclp_cpi_mutex);
0401     set_string(system_name, system);
0402     set_string(sysplex_name, sysplex);
0403     set_string(system_type, type);
0404     system_level = level;
0405 
0406     rc = cpi_req();
0407     mutex_unlock(&sclp_cpi_mutex);
0408 
0409     return rc;
0410 }
0411 EXPORT_SYMBOL(sclp_cpi_set_data);
0412 
0413 static int __init cpi_init(void)
0414 {
0415     int rc;
0416 
0417     cpi_kset = kset_create_and_add("cpi", NULL, firmware_kobj);
0418     if (!cpi_kset)
0419         return -ENOMEM;
0420 
0421     rc = sysfs_create_group(&cpi_kset->kobj, &cpi_attr_group);
0422     if (rc)
0423         kset_unregister(cpi_kset);
0424 
0425     return rc;
0426 }
0427 
0428 __initcall(cpi_init);