1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright IBM Corp. 2021
6 * Author(s): Vineeth Vijayan <vneethv@linux.ibm.com>
9 #define KMSG_COMPONENT "cio"
10 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
12 #include <linux/slab.h>
13 #include <linux/spinlock.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
;
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
)
40 copy
= kmemdup(crw
, sizeof(*crw
), GFP_KERNEL
);
44 spin_lock_irqsave(&crw_inject_lock
, flags
);
45 if (crw_inject_data
) {
49 crw_inject_data
= copy
;
51 spin_unlock_irqrestore(&crw_inject_lock
, flags
);
54 crw_handle_channel_report();
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
)
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
;
79 spin_unlock_irqrestore(&crw_inject_lock
, flags
);
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
;
93 if (!static_branch_likely(&cio_inject_enabled
)) {
94 pr_warn("CIO inject is not enabled - ignoring CRW inject\n");
98 buffer
= memdup_user_nul(buf
, lbuf
);
102 rc
= sscanf(buffer
, "%x %x %x %x %x %x %x", &slct
, &oflw
, &chn
, &rsc
, &anc
,
107 pr_warn("crw_inject: Invalid format (need <solicited> <overflow> <chaining> <rsc> <ancillary> <erc> <rsid>)\n");
111 memset(&crw
, 0, sizeof(crw
));
120 rc
= crw_inject(&crw
);
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;
134 rc
= kstrtoul_from_user(buf
, lbuf
, 10, &en
);
140 static_branch_disable(&cio_inject_enabled
);
143 static_branch_enable(&cio_inject_enabled
);
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
,
166 debugfs_create_file("crw_inject", 0200, cio_debugfs_dir
,
171 device_initcall(cio_inject_init
);