xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_model_error_generator.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2 /*
3  *
4  * (C) COPYRIGHT 2014-2015, 2018-2023 ARM Limited. All rights reserved.
5  *
6  * This program is free software and is provided to you under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation, and any use by you of this program is subject to the terms
9  * of such GNU license.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you can access it online at
18  * http://www.gnu.org/licenses/gpl-2.0.html.
19  *
20  */
21 
22 #include <mali_kbase.h>
23 #include <linux/random.h>
24 #include "backend/gpu/mali_kbase_model_linux.h"
25 
26 static struct kbase_error_atom *error_track_list;
27 
28 #ifdef CONFIG_MALI_ERROR_INJECT_RANDOM
29 
30 /** Kernel 6.1.0 has dropped prandom_u32(), use get_random_u32() */
31 #if (KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE)
32 #define prandom_u32 get_random_u32
33 #endif
34 
35 /*following error probability are set quite high in order to stress the driver*/
36 static unsigned int error_probability = 50; /* to be set between 0 and 100 */
37 /* probability to have multiple error give that there is an error */
38 static unsigned int multiple_error_probability = 50;
39 
40 /* all the error conditions supported by the model */
41 #define TOTAL_FAULTS 27
42 /* maximum number of levels in the MMU translation table tree */
43 #define MAX_MMU_TABLE_LEVEL 4
44 /* worst case scenario is <1 MMU fault + 1 job fault + 2 GPU faults> */
45 #define MAX_CONCURRENT_FAULTS 3
46 
47 /**
48  * gpu_generate_error - Generate GPU error
49  */
gpu_generate_error(void)50 static void gpu_generate_error(void)
51 {
52 	unsigned int errors_num = 0;
53 
54 	/*is there at least one error? */
55 	if ((prandom_u32() % 100) < error_probability) {
56 		/* pick up a faulty mmu address space */
57 		hw_error_status.faulty_mmu_as = prandom_u32() % NUM_MMU_AS;
58 		/* pick up an mmu table level */
59 		hw_error_status.mmu_table_level =
60 			1 + (prandom_u32() % MAX_MMU_TABLE_LEVEL);
61 		hw_error_status.errors_mask =
62 			(u32)(1 << (prandom_u32() % TOTAL_FAULTS));
63 
64 		/*is there also one or more errors? */
65 		if ((prandom_u32() % 100) < multiple_error_probability) {
66 			errors_num = 1 + (prandom_u32() %
67 					  (MAX_CONCURRENT_FAULTS - 1));
68 			while (errors_num-- > 0) {
69 				u32 temp_mask;
70 
71 				temp_mask = (u32)(
72 					1 << (prandom_u32() % TOTAL_FAULTS));
73 				/* below we check that no bit of the same error
74 				 * type is set again in the error mask
75 				 */
76 				if ((temp_mask & IS_A_JOB_ERROR) &&
77 						(hw_error_status.errors_mask &
78 							IS_A_JOB_ERROR)) {
79 					errors_num++;
80 					continue;
81 				}
82 				if ((temp_mask & IS_A_MMU_ERROR) &&
83 						(hw_error_status.errors_mask &
84 							IS_A_MMU_ERROR)) {
85 					errors_num++;
86 					continue;
87 				}
88 				if ((temp_mask & IS_A_GPU_ERROR) &&
89 						(hw_error_status.errors_mask &
90 							IS_A_GPU_ERROR)) {
91 					errors_num++;
92 					continue;
93 				}
94 				/* this error mask is already set */
95 				if ((hw_error_status.errors_mask | temp_mask) ==
96 						hw_error_status.errors_mask) {
97 					errors_num++;
98 					continue;
99 				}
100 				hw_error_status.errors_mask |= temp_mask;
101 			}
102 		}
103 	}
104 }
105 #endif
106 
job_atom_inject_error(struct kbase_error_params * params)107 int job_atom_inject_error(struct kbase_error_params *params)
108 {
109 	struct kbase_error_atom *new_elem;
110 
111 	KBASE_DEBUG_ASSERT(params);
112 
113 	new_elem = kzalloc(sizeof(*new_elem), GFP_KERNEL);
114 
115 	if (!new_elem) {
116 		model_error_log(KBASE_CORE,
117 			"\njob_atom_inject_error: kzalloc failed for new_elem\n"
118 									);
119 		return -ENOMEM;
120 	}
121 	new_elem->params.jc = params->jc;
122 	new_elem->params.errors_mask = params->errors_mask;
123 	new_elem->params.mmu_table_level = params->mmu_table_level;
124 	new_elem->params.faulty_mmu_as = params->faulty_mmu_as;
125 
126 	/*circular list below */
127 	if (error_track_list == NULL) {	/*no elements */
128 		error_track_list = new_elem;
129 		new_elem->next = error_track_list;
130 	} else {
131 		struct kbase_error_atom *walker = error_track_list;
132 
133 		while (walker->next != error_track_list)
134 			walker = walker->next;
135 
136 		new_elem->next = error_track_list;
137 		walker->next = new_elem;
138 	}
139 	return 0;
140 }
141 
midgard_set_error(int job_slot)142 void midgard_set_error(int job_slot)
143 {
144 #ifdef CONFIG_MALI_ERROR_INJECT_RANDOM
145 	gpu_generate_error();
146 #else
147 	struct kbase_error_atom *walker, *auxiliar;
148 
149 	if (error_track_list != NULL) {
150 		walker = error_track_list->next;
151 		auxiliar = error_track_list;
152 		do {
153 			if (walker->params.jc == hw_error_status.current_jc) {
154 				/* found a faulty atom matching with the
155 				 * current one
156 				 */
157 				hw_error_status.errors_mask =
158 						walker->params.errors_mask;
159 				hw_error_status.mmu_table_level =
160 						walker->params.mmu_table_level;
161 				hw_error_status.faulty_mmu_as =
162 						walker->params.faulty_mmu_as;
163 				hw_error_status.current_job_slot = job_slot;
164 
165 				if (walker->next == walker) {
166 					/* only one element */
167 					kfree(error_track_list);
168 					error_track_list = NULL;
169 				} else {
170 					auxiliar->next = walker->next;
171 					if (walker == error_track_list)
172 						error_track_list = walker->next;
173 
174 					kfree(walker);
175 				}
176 				break;
177 			}
178 			auxiliar = walker;
179 			walker = walker->next;
180 		} while (auxiliar->next != error_track_list);
181 	}
182 #endif				/* CONFIG_MALI_ERROR_INJECT_RANDOM */
183 }
184