Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");