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 20 static DEFINE_SPINLOCK(crw_inject_lock); 21 DEFINE_STATIC_KEY_FALSE(cio_inject_enabled); 22 static 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 */ 33 static 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 */ 66 int 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 */ 84 static 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*/ 127 static 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 149 static const struct file_operations crw_fops = { 150 .owner = THIS_MODULE, 151 .write = crw_inject_write, 152 }; 153 154 static const struct file_operations cio_en_fops = { 155 .owner = THIS_MODULE, 156 .write = enable_inject_write, 157 }; 158 159 static 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 170 device_initcall(cio_inject_init); 171