Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / drivers / s390 / cio / cio_inject.c
bloba2e771ebae8ebd55e1cb841f76b44a69ebb2bea7
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * CIO inject interface
5 * Copyright IBM Corp. 2021
6 * Author(s): Vineeth Vijayan <vneethv@linux.ibm.com>
7 */
9 #define KMSG_COMPONENT "cio"
10 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
12 #include <linux/slab.h>
13 #include <linux/spinlock.h>
14 #include <linux/mm.h>
15 #include <linux/debugfs.h>
16 #include <asm/chpid.h>
18 #include "cio_inject.h"
19 #include "cio_debug.h"
21 static DEFINE_SPINLOCK(crw_inject_lock);
22 DEFINE_STATIC_KEY_FALSE(cio_inject_enabled);
23 static struct crw *crw_inject_data;
25 /**
26 * crw_inject : Initiate the artificial CRW inject
27 * @crw: The data which needs to be injected as new CRW.
29 * The CRW handler is called, which will use the provided artificial
30 * data instead of the CRW from the underlying hardware.
32 * Return: 0 on success
34 static int crw_inject(struct crw *crw)
36 int rc = 0;
37 struct crw *copy;
38 unsigned long flags;
40 copy = kmemdup(crw, sizeof(*crw), GFP_KERNEL);
41 if (!copy)
42 return -ENOMEM;
44 spin_lock_irqsave(&crw_inject_lock, flags);
45 if (crw_inject_data) {
46 kfree(copy);
47 rc = -EBUSY;
48 } else {
49 crw_inject_data = copy;
51 spin_unlock_irqrestore(&crw_inject_lock, flags);
53 if (!rc)
54 crw_handle_channel_report();
56 return rc;
59 /**
60 * stcrw_get_injected: Copy the artificial CRW data to CRW struct.
61 * @crw: The target CRW pointer.
63 * Retrieve an injected CRW data. Return 0 on success, 1 if no
64 * injected-CRW is available. The function reproduces the return
65 * code of the actual STCRW function.
67 int stcrw_get_injected(struct crw *crw)
69 int rc = 1;
70 unsigned long flags;
72 spin_lock_irqsave(&crw_inject_lock, flags);
73 if (crw_inject_data) {
74 memcpy(crw, crw_inject_data, sizeof(*crw));
75 kfree(crw_inject_data);
76 crw_inject_data = NULL;
77 rc = 0;
79 spin_unlock_irqrestore(&crw_inject_lock, flags);
81 return rc;
84 /* The debugfs write handler for crw_inject nodes operation */
85 static ssize_t crw_inject_write(struct file *file, const char __user *buf,
86 size_t lbuf, loff_t *ppos)
88 u32 slct, oflw, chn, rsc, anc, erc, rsid;
89 struct crw crw;
90 char *buffer;
91 int rc;
93 if (!static_branch_likely(&cio_inject_enabled)) {
94 pr_warn("CIO inject is not enabled - ignoring CRW inject\n");
95 return -EINVAL;
98 buffer = memdup_user_nul(buf, lbuf);
99 if (IS_ERR(buffer))
100 return -ENOMEM;
102 rc = sscanf(buffer, "%x %x %x %x %x %x %x", &slct, &oflw, &chn, &rsc, &anc,
103 &erc, &rsid);
105 kvfree(buffer);
106 if (rc != 7) {
107 pr_warn("crw_inject: Invalid format (need <solicited> <overflow> <chaining> <rsc> <ancillary> <erc> <rsid>)\n");
108 return -EINVAL;
111 memset(&crw, 0, sizeof(crw));
112 crw.slct = slct;
113 crw.oflw = oflw;
114 crw.chn = chn;
115 crw.rsc = rsc;
116 crw.anc = anc;
117 crw.erc = erc;
118 crw.rsid = rsid;
120 rc = crw_inject(&crw);
121 if (rc)
122 return rc;
124 return lbuf;
127 /* Debugfs write handler for inject_enable node*/
128 static ssize_t enable_inject_write(struct file *file, const char __user *buf,
129 size_t lbuf, loff_t *ppos)
131 unsigned long en = 0;
132 int rc;
134 rc = kstrtoul_from_user(buf, lbuf, 10, &en);
135 if (rc)
136 return rc;
138 switch (en) {
139 case 0:
140 static_branch_disable(&cio_inject_enabled);
141 break;
142 case 1:
143 static_branch_enable(&cio_inject_enabled);
144 break;
147 return lbuf;
150 static const struct file_operations crw_fops = {
151 .owner = THIS_MODULE,
152 .write = crw_inject_write,
155 static const struct file_operations cio_en_fops = {
156 .owner = THIS_MODULE,
157 .write = enable_inject_write,
160 static int __init cio_inject_init(void)
162 /* enable_inject node enables the static branching */
163 debugfs_create_file("enable_inject", 0200, cio_debugfs_dir,
164 NULL, &cio_en_fops);
166 debugfs_create_file("crw_inject", 0200, cio_debugfs_dir,
167 NULL, &crw_fops);
168 return 0;
171 device_initcall(cio_inject_init);