^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * err_inject.c -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * 1.) Inject errors to a processor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * 2.) Query error injection capabilities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This driver along with user space code can be acting as an error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * injection tool.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * the Free Software Foundation; either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * This program is distributed in the hope that it will be useful, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * NON INFRINGEMENT. See the GNU General Public License for more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * You should have received a copy of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * along with this program; if not, write to the Free Software
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Written by: Fenghua Yu <fenghua.yu@intel.com>, Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Copyright (C) 2006, Intel Corp. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define ERR_INJ_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define ERR_DATA_BUFFER_SIZE 3 // Three 8-byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define define_one_ro(name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static DEVICE_ATTR(name, 0444, show_##name, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define define_one_rw(name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static DEVICE_ATTR(name, 0644, show_##name, store_##name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static u64 call_start[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static u64 phys_addr[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static u64 err_type_info[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static u64 err_struct_info[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) u64 data1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) u64 data2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) u64 data3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) } __attribute__((__aligned__(16))) err_data_buffer[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static s64 status[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static u64 capabilities[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static u64 resources[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define show(name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static ssize_t \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) show_##name(struct device *dev, struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 cpu=dev->id; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return sprintf(buf, "%llx\n", name[cpu]); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define store(name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static ssize_t \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) store_##name(struct device *dev, struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) const char *buf, size_t size) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned int cpu=dev->id; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) name[cpu] = simple_strtoull(buf, NULL, 16); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return size; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) show(call_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* It's user's responsibility to call the PAL procedure on a specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * processor. The cpu number in driver is only used for storing data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) store_call_start(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) const char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) unsigned int cpu=dev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned long call_start = simple_strtoull(buf, NULL, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #ifdef ERR_INJ_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) printk(KERN_DEBUG "pal_mc_err_inject for cpu%d:\n", cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) printk(KERN_DEBUG "err_type_info=%llx,\n", err_type_info[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) printk(KERN_DEBUG "err_struct_info=%llx,\n", err_struct_info[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) printk(KERN_DEBUG "err_data_buffer=%llx, %llx, %llx.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) err_data_buffer[cpu].data1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) err_data_buffer[cpu].data2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) err_data_buffer[cpu].data3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) switch (call_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) case 0: /* Do nothing. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) case 1: /* Call pal_mc_error_inject in physical mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) status[cpu]=ia64_pal_mc_error_inject_phys(err_type_info[cpu],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) err_struct_info[cpu],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) ia64_tpa(&err_data_buffer[cpu]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) &capabilities[cpu],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) &resources[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) case 2: /* Call pal_mc_error_inject in virtual mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) status[cpu]=ia64_pal_mc_error_inject_virt(err_type_info[cpu],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) err_struct_info[cpu],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ia64_tpa(&err_data_buffer[cpu]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) &capabilities[cpu],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) &resources[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) status[cpu] = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #ifdef ERR_INJ_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) printk(KERN_DEBUG "Returns: status=%d,\n", (int)status[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) printk(KERN_DEBUG "capabilities=%llx,\n", capabilities[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) printk(KERN_DEBUG "resources=%llx\n", resources[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) show(err_type_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) store(err_type_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) show_virtual_to_phys(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) unsigned int cpu=dev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return sprintf(buf, "%llx\n", phys_addr[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) store_virtual_to_phys(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) const char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int cpu=dev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) u64 virt_addr=simple_strtoull(buf, NULL, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ret = get_user_pages_fast(virt_addr, 1, FOLL_WRITE, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (ret<=0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #ifdef ERR_INJ_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) printk("Virtual address %llx is not existing.\n", virt_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) phys_addr[cpu] = ia64_tpa(virt_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) show(err_struct_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) store(err_struct_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) show_err_data_buffer(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) unsigned int cpu=dev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return sprintf(buf, "%llx, %llx, %llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) err_data_buffer[cpu].data1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) err_data_buffer[cpu].data2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) err_data_buffer[cpu].data3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) store_err_data_buffer(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) const char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) unsigned int cpu=dev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #ifdef ERR_INJ_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) printk("write err_data_buffer=[%llx,%llx,%llx] on cpu%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) err_data_buffer[cpu].data1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) err_data_buffer[cpu].data2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) err_data_buffer[cpu].data3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ret = sscanf(buf, "%llx, %llx, %llx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) &err_data_buffer[cpu].data1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) &err_data_buffer[cpu].data2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) &err_data_buffer[cpu].data3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (ret!=ERR_DATA_BUFFER_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) show(status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) show(capabilities)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) show(resources)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) define_one_rw(call_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) define_one_rw(err_type_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) define_one_rw(err_struct_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) define_one_rw(err_data_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) define_one_rw(virtual_to_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) define_one_ro(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) define_one_ro(capabilities);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) define_one_ro(resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static struct attribute *default_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) &dev_attr_call_start.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) &dev_attr_virtual_to_phys.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) &dev_attr_err_type_info.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) &dev_attr_err_struct_info.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) &dev_attr_err_data_buffer.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) &dev_attr_status.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) &dev_attr_capabilities.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) &dev_attr_resources.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static struct attribute_group err_inject_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .attrs = default_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .name = "err_inject"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* Add/Remove err_inject interface for CPU device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static int err_inject_add_dev(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct device *sys_dev = get_cpu_device(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return sysfs_create_group(&sys_dev->kobj, &err_inject_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static int err_inject_remove_dev(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct device *sys_dev = get_cpu_device(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static enum cpuhp_state hp_online;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static int __init err_inject_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #ifdef ERR_INJ_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) printk(KERN_INFO "Enter error injection driver.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/err_inj:online",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) err_inject_add_dev, err_inject_remove_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (ret >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) hp_online = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static void __exit err_inject_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) #ifdef ERR_INJ_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) printk(KERN_INFO "Exit error injection driver.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) cpuhp_remove_state(hp_online);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) module_init(err_inject_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) module_exit(err_inject_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) MODULE_AUTHOR("Fenghua Yu <fenghua.yu@intel.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) MODULE_DESCRIPTION("MC error injection kernel sysfs interface");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) MODULE_LICENSE("GPL");