Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *   CIO inject interface
0004  *
0005  *    Copyright IBM Corp. 2021
0006  *    Author(s): Vineeth Vijayan <vneethv@linux.ibm.com>
0007  */
0008 
0009 #define KMSG_COMPONENT "cio"
0010 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0011 
0012 #include <linux/slab.h>
0013 #include <linux/spinlock.h>
0014 #include <linux/mm.h>
0015 #include <linux/debugfs.h>
0016 #include <asm/chpid.h>
0017 
0018 #include "cio_inject.h"
0019 #include "cio_debug.h"
0020 
0021 static DEFINE_SPINLOCK(crw_inject_lock);
0022 DEFINE_STATIC_KEY_FALSE(cio_inject_enabled);
0023 static struct crw *crw_inject_data;
0024 
0025 /**
0026  * crw_inject : Initiate the artificial CRW inject
0027  * @crw: The data which needs to be injected as new CRW.
0028  *
0029  * The CRW handler is called, which will use the provided artificial
0030  * data instead of the CRW from the underlying hardware.
0031  *
0032  * Return: 0 on success
0033  */
0034 static int crw_inject(struct crw *crw)
0035 {
0036     int rc = 0;
0037     struct crw *copy;
0038     unsigned long flags;
0039 
0040     copy = kmemdup(crw, sizeof(*crw), GFP_KERNEL);
0041     if (!copy)
0042         return -ENOMEM;
0043 
0044     spin_lock_irqsave(&crw_inject_lock, flags);
0045     if (crw_inject_data) {
0046         kfree(copy);
0047         rc = -EBUSY;
0048     } else {
0049         crw_inject_data = copy;
0050     }
0051     spin_unlock_irqrestore(&crw_inject_lock, flags);
0052 
0053     if (!rc)
0054         crw_handle_channel_report();
0055 
0056     return rc;
0057 }
0058 
0059 /**
0060  * stcrw_get_injected: Copy the artificial CRW data to CRW struct.
0061  * @crw: The target CRW pointer.
0062  *
0063  * Retrieve an injected CRW data. Return 0 on success, 1 if no
0064  * injected-CRW is available. The function reproduces the return
0065  * code of the actual STCRW function.
0066  */
0067 int stcrw_get_injected(struct crw *crw)
0068 {
0069     int rc = 1;
0070     unsigned long flags;
0071 
0072     spin_lock_irqsave(&crw_inject_lock, flags);
0073     if (crw_inject_data) {
0074         memcpy(crw, crw_inject_data, sizeof(*crw));
0075         kfree(crw_inject_data);
0076         crw_inject_data = NULL;
0077         rc = 0;
0078     }
0079     spin_unlock_irqrestore(&crw_inject_lock, flags);
0080 
0081     return rc;
0082 }
0083 
0084 /* The debugfs write handler for crw_inject nodes operation */
0085 static ssize_t crw_inject_write(struct file *file, const char __user *buf,
0086                 size_t lbuf, loff_t *ppos)
0087 {
0088     u32 slct, oflw, chn, rsc, anc, erc, rsid;
0089     struct crw crw;
0090     char *buffer;
0091     int rc;
0092 
0093     if (!static_branch_likely(&cio_inject_enabled)) {
0094         pr_warn("CIO inject is not enabled - ignoring CRW inject\n");
0095         return -EINVAL;
0096     }
0097 
0098     buffer = vmemdup_user(buf, lbuf);
0099     if (IS_ERR(buffer))
0100         return -ENOMEM;
0101 
0102     rc = sscanf(buffer, "%x %x %x %x %x %x %x", &slct, &oflw, &chn, &rsc, &anc,
0103             &erc, &rsid);
0104 
0105     kvfree(buffer);
0106     if (rc != 7) {
0107         pr_warn("crw_inject: Invalid format (need <solicited> <overflow> <chaining> <rsc> <ancillary> <erc> <rsid>)\n");
0108         return -EINVAL;
0109     }
0110 
0111     memset(&crw, 0, sizeof(crw));
0112     crw.slct = slct;
0113     crw.oflw = oflw;
0114     crw.chn = chn;
0115     crw.rsc = rsc;
0116     crw.anc = anc;
0117     crw.erc = erc;
0118     crw.rsid = rsid;
0119 
0120     rc = crw_inject(&crw);
0121     if (rc)
0122         return rc;
0123 
0124     return lbuf;
0125 }
0126 
0127 /* Debugfs write handler for inject_enable node*/
0128 static ssize_t enable_inject_write(struct file *file, const char __user *buf,
0129                    size_t lbuf, loff_t *ppos)
0130 {
0131     unsigned long en = 0;
0132     int rc;
0133 
0134     rc = kstrtoul_from_user(buf, lbuf, 10, &en);
0135     if (rc)
0136         return rc;
0137 
0138     switch (en) {
0139     case 0:
0140         static_branch_disable(&cio_inject_enabled);
0141         break;
0142     case 1:
0143         static_branch_enable(&cio_inject_enabled);
0144         break;
0145     }
0146 
0147     return lbuf;
0148 }
0149 
0150 static const struct file_operations crw_fops = {
0151     .owner = THIS_MODULE,
0152     .write = crw_inject_write,
0153 };
0154 
0155 static const struct file_operations cio_en_fops = {
0156     .owner = THIS_MODULE,
0157     .write = enable_inject_write,
0158 };
0159 
0160 static int __init cio_inject_init(void)
0161 {
0162     /* enable_inject node enables the static branching */
0163     debugfs_create_file("enable_inject", 0200, cio_debugfs_dir,
0164                 NULL, &cio_en_fops);
0165 
0166     debugfs_create_file("crw_inject", 0200, cio_debugfs_dir,
0167                 NULL, &crw_fops);
0168     return 0;
0169 }
0170 
0171 device_initcall(cio_inject_init);