File Index
Files and directories
Sign in
FILE

cio_inject.c

File preview with syntax highlighting.

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