Commit | Line | Data |
---|---|---|
800f879a AT |
1 | /* |
2 | * Copyright 2010-2017 Intel Corporation. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License, version 2, | |
6 | * as published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | * General Public License for more details. | |
12 | * | |
13 | * Disclaimer: The codes contained in these modules may be specific to | |
14 | * the Intel Software Development Platform codenamed Knights Ferry, | |
15 | * and the Intel product codenamed Knights Corner, and are not backward | |
16 | * compatible with other Intel products. Additionally, Intel will NOT | |
17 | * support the codes or instruction set in future products. | |
18 | * | |
19 | * Intel offers no warranty of any kind regarding the code. This code is | |
20 | * licensed on an "AS IS" basis and Intel is not obligated to provide | |
21 | * any support, assistance, installation, training, or other services | |
22 | * of any kind. Intel is also not obligated to provide any updates, | |
23 | * enhancements or extensions. Intel specifically disclaims any warranty | |
24 | * of merchantability, non-infringement, fitness for any particular | |
25 | * purpose, and any other warranty. | |
26 | * | |
27 | * Further, Intel disclaims all liability of any kind, including but | |
28 | * not limited to liability for infringement of any proprietary rights, | |
29 | * relating to the use of the code, even if Intel is notified of the | |
30 | * possibility of such liability. Except as expressly stated in an Intel | |
31 | * license agreement provided with this code and agreed upon with Intel, | |
32 | * no license, express or implied, by estoppel or otherwise, to any | |
33 | * intellectual property rights is granted herein. | |
34 | */ | |
35 | ||
36 | #include "mic/micscif.h" | |
37 | #ifndef _MIC_SCIF_ | |
38 | #include "mic_common.h" | |
39 | #endif | |
40 | #include "scif.h" | |
41 | #include <linux/proc_fs.h> | |
42 | #include <linux/debugfs.h> | |
43 | ||
44 | #include <linux/module.h> | |
45 | ||
46 | static char *window_type[] = { | |
47 | "NONE", | |
48 | "SELF", | |
49 | "PEER"}; | |
50 | ||
51 | static char *scifdev_state[] = { | |
52 | "SCIFDEV_NOTPRESENT", | |
53 | "SCIFDEV_INIT", | |
54 | "SCIFDEV_RUNNING", | |
55 | "SCIFDEV_SLEEPING", | |
56 | "SCIFDEV_STOPPING", | |
57 | "SCIFDEV_STOPPED"}; | |
58 | ||
59 | static struct proc_dir_entry *scif_proc; | |
60 | static struct dentry *mic_debug = NULL; | |
61 | ||
62 | #define DEBUG_LEN 10 | |
63 | ||
64 | static int | |
65 | scif_ep_show(struct seq_file *m, void *data) | |
66 | { | |
67 | struct endpt *ep; | |
68 | struct list_head *pos; | |
69 | unsigned long sflags; | |
70 | ||
71 | seq_printf(m, "EP Address State Port Peer Remote Ep Address\n"); | |
72 | seq_printf(m, "=================================================================\n"); | |
73 | spin_lock_irqsave(&ms_info.mi_eplock, sflags); | |
74 | list_for_each(pos, &ms_info.mi_listen) { | |
75 | ep = list_entry(pos, struct endpt, list); | |
76 | seq_printf(m, "%p %s %6d\n", | |
77 | ep, scif_ep_states[ep->state], ep->port.port); | |
78 | } | |
79 | spin_unlock_irqrestore(&ms_info.mi_eplock, sflags); | |
80 | ||
81 | spin_lock_irqsave(&ms_info.mi_connlock, sflags); | |
82 | list_for_each(pos, &ms_info.mi_connected) { | |
83 | ep = list_entry(pos, struct endpt, list); | |
84 | seq_printf(m, "%p %s %6d %2d:%-6d %p\n", | |
85 | ep, scif_ep_states[ep->state], ep->port.port, ep->peer.node, | |
86 | ep->peer.port, (void *)ep->remote_ep); | |
87 | } | |
88 | list_for_each(pos, &ms_info.mi_disconnected) { | |
89 | ep = list_entry(pos, struct endpt, list); | |
90 | seq_printf(m, "%p %s %6d %2d:%-6d %p\n", | |
91 | ep, scif_ep_states[ep->state], ep->port.port, ep->peer.node, | |
92 | ep->peer.port, (void *)ep->remote_ep); | |
93 | } | |
94 | spin_unlock_irqrestore(&ms_info.mi_connlock, sflags); | |
95 | ||
96 | seq_printf(m, "EP Address State Port Peer Remote Ep Address reg_list " | |
97 | "remote_reg_list mmn_list tw_refcount tcw_refcount mi_rma mi_rma_tc " | |
98 | "task_list mic_mmu_notif_cleanup\n"); | |
99 | seq_printf(m, "=================================================================\n"); | |
100 | spin_lock_irqsave(&ms_info.mi_eplock, sflags); | |
101 | list_for_each(pos, &ms_info.mi_zombie) { | |
102 | ep = list_entry(pos, struct endpt, list); | |
103 | seq_printf(m, "%p %s %6d %2d:%-6d %p %d %d %d %d %d %d %d %d %d\n", | |
104 | ep, scif_ep_states[ep->state], ep->port.port, ep->peer.node, | |
105 | ep->peer.port, (void *)ep->remote_ep, | |
106 | list_empty(&ep->rma_info.reg_list), | |
107 | list_empty(&ep->rma_info.remote_reg_list), | |
108 | list_empty(&ep->rma_info.mmn_list), | |
109 | atomic_read(&ep->rma_info.tw_refcount), | |
110 | atomic_read(&ep->rma_info.tcw_refcount), | |
111 | list_empty(&ms_info.mi_rma), | |
112 | list_empty(&ms_info.mi_rma_tc), | |
113 | list_empty(&ep->rma_info.task_list), | |
114 | #ifdef CONFIG_MMU_NOTIFIER | |
115 | list_empty(&ms_info.mi_mmu_notif_cleanup) | |
116 | #else | |
117 | -1 | |
118 | #endif | |
119 | ); | |
120 | } | |
121 | spin_unlock_irqrestore(&ms_info.mi_eplock, sflags); | |
122 | ||
123 | return 0; | |
124 | } | |
125 | ||
126 | static int | |
127 | scif_ep_open(struct inode *inode, struct file *file) | |
128 | { | |
129 | return single_open(file, scif_ep_show, NULL); | |
130 | } | |
131 | ||
132 | struct file_operations scif_ep_fops = { | |
133 | .open = scif_ep_open, | |
134 | .read = seq_read, | |
135 | .llseek = seq_lseek, | |
136 | .release = single_release, | |
137 | }; | |
138 | ||
139 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) | |
140 | ||
141 | static int | |
142 | scif_rma_window_show(struct seq_file *m, void *data) | |
143 | { | |
144 | struct endpt *ep; | |
145 | struct list_head *pos, *item, *tmp; | |
146 | unsigned long sflags; | |
147 | struct reg_range_t *window; | |
148 | ||
149 | seq_printf(m, "SCIF Connected EP RMA Window Info\n"); | |
150 | seq_printf(m, "=================================================================\n"); | |
151 | seq_printf(m, "%-16s\t%-16s %-16s %-16s %-8s %-8s %-8s\n", | |
152 | "Endpoint", "Type", "Offset", "NumPages", "Prot", "Ref_Count", "Unreg State"); | |
153 | spin_lock_irqsave(&ms_info.mi_connlock, sflags); | |
154 | list_for_each(pos, &ms_info.mi_connected) { | |
155 | ep = list_entry(pos, struct endpt, list); | |
156 | if (mutex_trylock(&ep->rma_info.rma_lock)) { | |
157 | list_for_each_safe(item, tmp, &ep->rma_info.reg_list) { | |
158 | window = list_entry(item, struct reg_range_t, list_member); | |
159 | seq_printf(m, | |
160 | "%-16p\t%-16s 0x%-16llx %-16lld %-8d %-8d %-8d\n", | |
161 | ep, window_type[window->type], window->offset, | |
162 | window->nr_pages, window->prot, window->ref_count, | |
163 | window->unreg_state); | |
164 | } | |
165 | list_for_each_safe(item, tmp, &ep->rma_info.remote_reg_list) { | |
166 | window = list_entry(item, struct reg_range_t, list_member); | |
167 | seq_printf(m, | |
168 | "%-16p\t%-16s 0x%-16llx %-16lld %-8d %-8d %-8d\n", | |
169 | ep, window_type[window->type], window->offset, | |
170 | window->nr_pages, window->prot, window->ref_count, | |
171 | window->unreg_state); | |
172 | } | |
173 | mutex_unlock(&ep->rma_info.rma_lock); | |
174 | } else | |
175 | seq_printf(m, | |
176 | "Try Again, some other thread has the RMA lock for ep %p\n", | |
177 | ep); | |
178 | } | |
179 | spin_unlock_irqrestore(&ms_info.mi_connlock, sflags); | |
180 | ||
181 | seq_printf(m, "=================================================================\n"); | |
182 | seq_printf(m, "SCIF Zombie EP RMA Window Info\n"); | |
183 | spin_lock_irqsave(&ms_info.mi_eplock, sflags); | |
184 | list_for_each(pos, &ms_info.mi_zombie) { | |
185 | ep = list_entry(pos, struct endpt, list); | |
186 | if (mutex_trylock(&ep->rma_info.rma_lock)) { | |
187 | list_for_each_safe(item, tmp, &ep->rma_info.reg_list) { | |
188 | window = list_entry(item, struct reg_range_t, list_member); | |
189 | seq_printf(m, | |
190 | "%-16p\t%-16s 0x%-16llx %-16lld %-8d %-8d %-8d\n", | |
191 | ep, window_type[window->type], window->offset, | |
192 | window->nr_pages, window->prot, window->ref_count, | |
193 | window->unreg_state); | |
194 | } | |
195 | list_for_each_safe(item, tmp, &ep->rma_info.remote_reg_list) { | |
196 | window = list_entry(item, struct reg_range_t, list_member); | |
197 | seq_printf(m, | |
198 | "%-16p\t%-16s 0x%-16llx %-16lld %-8d %-8d %-8d\n", | |
199 | ep, window_type[window->type], window->offset, | |
200 | window->nr_pages, window->prot, window->ref_count, | |
201 | window->unreg_state); | |
202 | } | |
203 | mutex_unlock(&ep->rma_info.rma_lock); | |
204 | } else | |
205 | seq_printf(m, | |
206 | "Try Again, some other thread has the RMA lock for ep %p\n", | |
207 | ep); | |
208 | } | |
209 | spin_unlock_irqrestore(&ms_info.mi_eplock, sflags); | |
210 | seq_printf(m, "=================================================================\n"); | |
211 | seq_printf(m, "%-16s\t%-16s %-16s %-16s %-8s %-8s %-8s\n", | |
212 | "Endpoint", "Type", "Offset", "NumPages", "Prot", "Ref_Count", "Unreg State"); | |
213 | spin_lock(&ms_info.mi_rmalock); | |
214 | list_for_each_safe(item, tmp, &ms_info.mi_rma) { | |
215 | window = list_entry(item, | |
216 | struct reg_range_t, list_member); | |
217 | ep = (struct endpt *)window->ep; | |
218 | seq_printf(m, "%-16p\t%-16s 0x%-16llx %-16lld %-8d %-8d %-8d\n", | |
219 | ep, window_type[window->type], window->offset, | |
220 | window->nr_pages, window->prot, window->ref_count, | |
221 | window->unreg_state); | |
222 | } | |
223 | spin_unlock(&ms_info.mi_rmalock); | |
224 | ||
225 | return 0; | |
226 | } | |
227 | ||
228 | static int | |
229 | scif_rma_window_open(struct inode *inode, struct file *file) | |
230 | { | |
231 | return single_open(file, scif_rma_window_show, NULL); | |
232 | } | |
233 | ||
234 | struct file_operations scif_rma_window_fops = { | |
235 | .open = scif_rma_window_open, | |
236 | .read = seq_read, | |
237 | .llseek = seq_lseek, | |
238 | .release = single_release, | |
239 | }; | |
240 | ||
241 | static int | |
242 | scif_rma_xfer_show(struct seq_file *m, void *data) | |
243 | { | |
244 | struct endpt *ep; | |
245 | struct list_head *pos; | |
246 | unsigned long sflags; | |
247 | ||
248 | seq_printf(m, "SCIF RMA Debug\n"); | |
249 | seq_printf(m, "=================================================================\n"); | |
250 | seq_printf(m, "%-16s\t %-16s %-16s %-16s\n", | |
251 | "Endpoint", "Fence Ref Count", "Temp Window Ref Count", "DMA CHANNEL"); | |
252 | spin_lock_irqsave(&ms_info.mi_connlock, sflags); | |
253 | list_for_each(pos, &ms_info.mi_connected) { | |
254 | ep = list_entry(pos, struct endpt, list); | |
255 | seq_printf(m, "%-16p\t%-16d %-16d %-16d\n", | |
256 | ep, ep->rma_info.fence_refcount, | |
257 | atomic_read(&ep->rma_info.tw_refcount), | |
258 | ep->rma_info.dma_chan ? get_chan_num(ep->rma_info.dma_chan): -1); | |
259 | } | |
260 | spin_unlock_irqrestore(&ms_info.mi_connlock, sflags); | |
261 | return 0; | |
262 | } | |
263 | ||
264 | static int | |
265 | scif_rma_xfer_open(struct inode *inode, struct file *file) | |
266 | { | |
267 | return single_open(file, scif_rma_xfer_show, NULL); | |
268 | } | |
269 | ||
270 | struct file_operations scif_rma_xfer_fops = { | |
271 | .open = scif_rma_xfer_open, | |
272 | .read = seq_read, | |
273 | .llseek = seq_lseek, | |
274 | .release = single_release, | |
275 | }; | |
276 | ||
277 | static int | |
278 | scif_dev_show(struct seq_file *m, void *data) | |
279 | { | |
280 | int node; | |
281 | ||
282 | seq_printf(m, "Total Nodes %d Self Node Id %d Maxid %d\n", | |
283 | ms_info.mi_total, ms_info.mi_nodeid, ms_info.mi_maxid); | |
284 | ||
285 | seq_printf(m, "%-16s\t%-16s %-16s\t%-16s\t%-8s\t%-8s\t%-8s\n", | |
286 | "node_id", "state", "scif_ref_cnt", "scif_map_ref_cnt", | |
287 | "wait_status", "conn count", "numa_node"); | |
288 | ||
289 | for (node = 0; node <= ms_info.mi_maxid; node++) | |
290 | seq_printf(m, "%-16d\t%-16s\t0x%-16lx\t%-16d\t%-16lld\t%-16d\t%-16d\n", | |
291 | scif_dev[node].sd_node, scifdev_state[scif_dev[node].sd_state], | |
292 | atomic_long_read(&scif_dev[node].scif_ref_cnt), | |
293 | scif_dev[node].scif_map_ref_cnt, | |
294 | scif_dev[node].sd_wait_status, | |
295 | scif_dev[node].num_active_conn, | |
296 | scif_dev[node].sd_numa_node); | |
297 | ||
298 | return 0; | |
299 | } | |
300 | ||
301 | static int | |
302 | scif_dev_open(struct inode *inode, struct file *file) | |
303 | { | |
304 | return single_open(file, scif_dev_show, NULL); | |
305 | } | |
306 | ||
307 | struct file_operations scif_dev_fops = { | |
308 | .open = scif_dev_open, | |
309 | .read = seq_read, | |
310 | .llseek = seq_lseek, | |
311 | .release = single_release, | |
312 | }; | |
313 | ||
314 | static int | |
315 | scif_debug_show(struct seq_file *m, void *data) | |
316 | { | |
317 | seq_printf(m, "Num gtt_entries %d\n", ms_info.nr_gtt_entries); | |
318 | /* | |
319 | * Tracking the number of zombies for debug. | |
320 | * Need to make sure they are not being left behind forever. | |
321 | */ | |
322 | seq_printf(m, "Num Zombie Endpoints %d\n", ms_info.mi_nr_zombies); | |
323 | seq_printf(m, "Watchdog timeout %d\n", ms_info.mi_watchdog_to); | |
324 | seq_printf(m, "Watchdog enabled %d\n", ms_info.mi_watchdog_enabled); | |
325 | seq_printf(m, "Watchdog auto reboot %d\n", ms_info.mi_watchdog_auto_reboot); | |
326 | seq_printf(m, "Huge Pages Enabled %d Detected 2mb %lld 4k %lld\n", | |
327 | mic_huge_page_enable, ms_info.nr_2mb_pages, ms_info.nr_4k_pages); | |
328 | #ifdef RMA_DEBUG | |
329 | seq_printf(m, "rma_alloc_cnt %ld rma_pin_cnt %ld mmu_notif %ld rma_unaligned_cpu_cnt %ld\n", | |
330 | atomic_long_read(&ms_info.rma_alloc_cnt), | |
331 | atomic_long_read(&ms_info.rma_pin_cnt), | |
332 | atomic_long_read(&ms_info.mmu_notif_cnt), | |
333 | atomic_long_read(&ms_info.rma_unaligned_cpu_cnt)); | |
334 | #endif | |
335 | seq_printf(m, "List empty? mi_uaccept %d mi_listen %d mi_zombie %d " | |
336 | "mi_connected %d mi_disconnected %d\n", | |
337 | list_empty(&ms_info.mi_uaccept), | |
338 | list_empty(&ms_info.mi_listen), | |
339 | list_empty(&ms_info.mi_zombie), | |
340 | list_empty(&ms_info.mi_connected), | |
341 | list_empty(&ms_info.mi_disconnected)); | |
342 | ||
343 | return 0; | |
344 | } | |
345 | ||
346 | static int | |
347 | scif_debug_open(struct inode *inode, struct file *file) | |
348 | { | |
349 | return single_open(file, scif_debug_show, NULL); | |
350 | } | |
351 | ||
352 | struct file_operations scif_debug_fops = { | |
353 | .open = scif_debug_open, | |
354 | .read = seq_read, | |
355 | .llseek = seq_lseek, | |
356 | .release = single_release, | |
357 | }; | |
358 | ||
359 | static int | |
360 | scif_suspend_show(struct seq_file *m, void *data) | |
361 | { | |
362 | int node; | |
363 | uint64_t ret; | |
364 | seq_printf(m, "Removing Nodes mask 0x7\n"); | |
365 | ||
366 | for (node = 1; node < ms_info.mi_total; node++) { | |
367 | ret = micscif_disconnect_node(node, 0 , 1); | |
368 | seq_printf(m, "Node %d requested disconnect. ret = %lld\n", | |
369 | node, ret); | |
370 | } | |
371 | ||
372 | return 0; | |
373 | } | |
374 | ||
375 | static int | |
376 | scif_suspend_open(struct inode *inode, struct file *file) | |
377 | { | |
378 | return single_open(file, scif_suspend_show, NULL); | |
379 | } | |
380 | ||
381 | struct file_operations scif_suspend_fops = { | |
382 | .open = scif_suspend_open, | |
383 | .read = seq_read, | |
384 | .llseek = seq_lseek, | |
385 | .release = single_release, | |
386 | }; | |
387 | ||
388 | static int | |
389 | scif_cache_limit_show(struct seq_file *m, void *data) | |
390 | { | |
391 | seq_printf(m, "reg_cache_limit = 0x%lx\n", ms_info.mi_rma_tc_limit); | |
392 | return 0; | |
393 | } | |
394 | ||
395 | static int | |
396 | scif_cache_limit_open(struct inode *inode, struct file *file) | |
397 | { | |
398 | return single_open(file, scif_cache_limit_show, NULL); | |
399 | } | |
400 | ||
401 | struct file_operations scif_cache_limit_fops = { | |
402 | .open = scif_cache_limit_open, | |
403 | .read = seq_read, | |
404 | .llseek = seq_lseek, | |
405 | .release = single_release, | |
406 | }; | |
407 | ||
408 | #else // LINUX VERSION 3.10 | |
409 | ||
410 | static int | |
411 | scif_rma_window_read(char *buf, char **start, off_t offset, int len, int *eof, void *data) | |
412 | { | |
413 | struct endpt *ep; | |
414 | struct list_head *pos, *item, *tmp; | |
415 | unsigned long sflags; | |
416 | int l = 0; | |
417 | struct reg_range_t *window; | |
418 | ||
419 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
420 | "SCIF Connected EP RMA Window Info\n"); | |
421 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
422 | "=================================================================\n"); | |
423 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
424 | "%-16s\t%-16s %-16s %-16s %-8s %-8s %-8s\n", | |
425 | "Endpoint", "Type", "Offset", "NumPages", "Prot", "Ref_Count", "Unreg State"); | |
426 | spin_lock_irqsave(&ms_info.mi_connlock, sflags); | |
427 | list_for_each(pos, &ms_info.mi_connected) { | |
428 | ep = list_entry(pos, struct endpt, list); | |
429 | if (mutex_trylock(&ep->rma_info.rma_lock)) { | |
430 | list_for_each_safe(item, tmp, &ep->rma_info.reg_list) { | |
431 | window = list_entry(item, struct reg_range_t, list_member); | |
432 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
433 | "%-16p\t%-16s 0x%-16llx %-16lld %-8d %-8d %-8d\n", | |
434 | ep, window_type[window->type], window->offset, | |
435 | window->nr_pages, window->prot, window->ref_count, | |
436 | window->unreg_state); | |
437 | } | |
438 | list_for_each_safe(item, tmp, &ep->rma_info.remote_reg_list) { | |
439 | window = list_entry(item, struct reg_range_t, list_member); | |
440 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
441 | "%-16p\t%-16s 0x%-16llx %-16lld %-8d %-8d %-8d\n", | |
442 | ep, window_type[window->type], window->offset, | |
443 | window->nr_pages, window->prot, window->ref_count, | |
444 | window->unreg_state); | |
445 | } | |
446 | mutex_unlock(&ep->rma_info.rma_lock); | |
447 | } else | |
448 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
449 | "Try Again, some other thread has the RMA lock for ep %p\n", | |
450 | ep); | |
451 | } | |
452 | spin_unlock_irqrestore(&ms_info.mi_connlock, sflags); | |
453 | ||
454 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
455 | "=================================================================\n"); | |
456 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
457 | "SCIF Zombie EP RMA Window Info\n"); | |
458 | spin_lock_irqsave(&ms_info.mi_eplock, sflags); | |
459 | list_for_each(pos, &ms_info.mi_zombie) { | |
460 | ep = list_entry(pos, struct endpt, list); | |
461 | if (mutex_trylock(&ep->rma_info.rma_lock)) { | |
462 | list_for_each_safe(item, tmp, &ep->rma_info.reg_list) { | |
463 | window = list_entry(item, struct reg_range_t, list_member); | |
464 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
465 | "%-16p\t%-16s 0x%-16llx %-16lld %-8d %-8d %-8d\n", | |
466 | ep, window_type[window->type], window->offset, | |
467 | window->nr_pages, window->prot, window->ref_count, | |
468 | window->unreg_state); | |
469 | } | |
470 | list_for_each_safe(item, tmp, &ep->rma_info.remote_reg_list) { | |
471 | window = list_entry(item, struct reg_range_t, list_member); | |
472 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
473 | "%-16p\t%-16s 0x%-16llx %-16lld %-8d %-8d %-8d\n", | |
474 | ep, window_type[window->type], window->offset, | |
475 | window->nr_pages, window->prot, window->ref_count, | |
476 | window->unreg_state); | |
477 | } | |
478 | mutex_unlock(&ep->rma_info.rma_lock); | |
479 | } else | |
480 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
481 | "Try Again, some other thread has the RMA lock for ep %p\n", | |
482 | ep); | |
483 | } | |
484 | spin_unlock_irqrestore(&ms_info.mi_eplock, sflags); | |
485 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
486 | "=================================================================\n"); | |
487 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
488 | "%-16s\t%-16s %-16s %-16s %-8s %-8s %-8s\n", | |
489 | "Endpoint", "Type", "Offset", "NumPages", "Prot", "Ref_Count", "Unreg State"); | |
490 | spin_lock(&ms_info.mi_rmalock); | |
491 | list_for_each_safe(item, tmp, &ms_info.mi_rma) { | |
492 | window = list_entry(item, | |
493 | struct reg_range_t, list_member); | |
494 | ep = (struct endpt *)window->ep; | |
495 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
496 | "%-16p\t%-16s 0x%-16llx %-16lld %-8d %-8d %-8d\n", | |
497 | ep, window_type[window->type], window->offset, | |
498 | window->nr_pages, window->prot, window->ref_count, | |
499 | window->unreg_state); | |
500 | } | |
501 | spin_unlock(&ms_info.mi_rmalock); | |
502 | ||
503 | *eof = 1; | |
504 | return l; | |
505 | } | |
506 | ||
507 | static int | |
508 | scif_rma_xfer_read(char *buf, char **start, off_t offset, int len, int *eof, void *data) | |
509 | { | |
510 | struct endpt *ep; | |
511 | struct list_head *pos; | |
512 | unsigned long sflags; | |
513 | int l = 0; | |
514 | ||
515 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , "SCIF RMA Debug\n"); | |
516 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
517 | "=================================================================\n"); | |
518 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , "%-16s\t %-16s %-16s %-16s\n", | |
519 | "Endpoint", "Fence Ref Count", "Temp Window Ref Count", "DMA CHANNEL"); | |
520 | spin_lock_irqsave(&ms_info.mi_connlock, sflags); | |
521 | list_for_each(pos, &ms_info.mi_connected) { | |
522 | ep = list_entry(pos, struct endpt, list); | |
523 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , "%-16p\t%-16d %-16d %-16d\n", | |
524 | ep, ep->rma_info.fence_refcount, | |
525 | atomic_read(&ep->rma_info.tw_refcount), | |
526 | ep->rma_info.dma_chan ? get_chan_num(ep->rma_info.dma_chan): -1); | |
527 | } | |
528 | spin_unlock_irqrestore(&ms_info.mi_connlock, sflags); | |
529 | ||
530 | *eof = 1; | |
531 | return l; | |
532 | } | |
533 | ||
534 | /* Place Holder for generic SCIF debug information */ | |
535 | static int | |
536 | scif_debug_read(char *buf, char **start, off_t offset, int len, int *eof, void *data) | |
537 | { | |
538 | int l = 0; | |
539 | ||
540 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
541 | "Num gtt_entries %d\n", ms_info.nr_gtt_entries); | |
542 | /* | |
543 | * Tracking the number of zombies for debug. | |
544 | * Need to make sure they are not being left behind forever. | |
545 | */ | |
546 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
547 | "Num Zombie Endpoints %d\n", ms_info.mi_nr_zombies); | |
548 | ||
549 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
550 | "Watchdog timeout %d\n", ms_info.mi_watchdog_to); | |
551 | ||
552 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
553 | "Watchdog enabled %d\n", ms_info.mi_watchdog_enabled); | |
554 | ||
555 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
556 | "Watchdog auto reboot %d\n", ms_info.mi_watchdog_auto_reboot); | |
557 | ||
558 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
559 | "Huge Pages Enabled %d Detected 2mb %lld 4k %lld\n", | |
560 | mic_huge_page_enable, ms_info.nr_2mb_pages, ms_info.nr_4k_pages); | |
561 | #ifdef RMA_DEBUG | |
562 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
563 | "mm ref cnt %ld rma_alloc_cnt %ld rma_pin_cnt %ld mmu_notif %ld rma_unaligned_cpu_cnt %ld\n", | |
564 | atomic_long_read(&ms_info.rma_mm_cnt), | |
565 | atomic_long_read(&ms_info.rma_alloc_cnt), | |
566 | atomic_long_read(&ms_info.rma_pin_cnt), | |
567 | atomic_long_read(&ms_info.mmu_notif_cnt), | |
568 | atomic_long_read(&ms_info.rma_unaligned_cpu_cnt)); | |
569 | #endif | |
570 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
571 | "List empty? mi_uaccept %d mi_listen %d mi_zombie %d " | |
572 | "mi_connected %d mi_disconnected %d\n", | |
573 | list_empty(&ms_info.mi_uaccept), | |
574 | list_empty(&ms_info.mi_listen), | |
575 | list_empty(&ms_info.mi_zombie), | |
576 | list_empty(&ms_info.mi_connected), | |
577 | list_empty(&ms_info.mi_disconnected)); | |
578 | ||
579 | *eof = 1; | |
580 | return l; | |
581 | } | |
582 | ||
583 | static int | |
584 | scif_dev_info(char *buf, char **start, off_t offset, int len, int *eof, void *data) | |
585 | { | |
586 | int l = 0; | |
587 | int node; | |
588 | ||
589 | #ifdef _MIC_SCIF_ | |
590 | micscif_get_node_info(); | |
591 | ||
592 | mutex_lock(&ms_info.mi_conflock); | |
593 | #endif | |
594 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
595 | "Total Nodes %d Self Node Id %d Maxid %d\n", | |
596 | ms_info.mi_total, ms_info.mi_nodeid, ms_info.mi_maxid); | |
597 | ||
598 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
599 | "%-16s\t%-16s %-16s\t%-16s\t%-8s\t%-8s\t%-8s\n", | |
600 | "node_id", "state", "scif_ref_cnt", "scif_map_ref_cnt", | |
601 | "wait_status", "conn count", "numa_node"); | |
602 | ||
603 | for (node = 0; node <= ms_info.mi_maxid; node++) | |
604 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
605 | "%-16d\t%-16s\t0x%-16lx\t%-16d\t%-16lld\t%-16d\t%-16d\n", | |
606 | scif_dev[node].sd_node, scifdev_state[scif_dev[node].sd_state], | |
607 | atomic_long_read(&scif_dev[node].scif_ref_cnt), | |
608 | scif_dev[node].scif_map_ref_cnt, | |
609 | scif_dev[node].sd_wait_status, | |
610 | scif_dev[node].num_active_conn, | |
611 | scif_dev[node].sd_numa_node); | |
612 | #ifdef _MIC_SCIF_ | |
613 | mutex_unlock(&ms_info.mi_conflock); | |
614 | #endif | |
615 | ||
616 | *eof = 1; | |
617 | return l; | |
618 | } | |
619 | ||
620 | static int | |
621 | scif_suspend(char *buf, char **start, off_t offset, int len, int *eof, void *data) | |
622 | { | |
623 | int l = 0; | |
624 | ||
625 | #ifdef _MIC_SCIF_ | |
626 | micscif_suspend_handler(NULL, 0, NULL); | |
627 | #else | |
628 | { | |
629 | int node; | |
630 | uint64_t ret; | |
631 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
632 | "Removing Nodes mask 0x7\n"); | |
633 | for (node = 1; node < ms_info.mi_total; node++) { | |
634 | ret = micscif_disconnect_node(node, 0 , 1); | |
635 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
636 | "Node %d requested disconnect. ret = %lld\n", | |
637 | node, ret); | |
638 | } | |
639 | } | |
640 | #endif | |
641 | ||
642 | *eof = 1; | |
643 | return l; | |
644 | } | |
645 | ||
646 | #ifdef _MIC_SCIF_ | |
647 | static int | |
648 | scif_crash(char *buf, char **start, off_t offset, int len, int *eof, void *data) | |
649 | { | |
650 | int l = 0; | |
651 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
652 | "%s %d Crash the Card to test Lost Nodes\n", __func__, __LINE__); | |
653 | panic("Test Lost Node! Crash the card intentionally\n"); | |
654 | *eof = 1; | |
655 | return l; | |
656 | } | |
657 | ||
658 | static int | |
659 | scif_bugon(char *buf, char **start, off_t offset, int len, int *eof, void *data) | |
660 | { | |
661 | int l = 0; | |
662 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
663 | "%s %d Bug on the Card to test Lost Nodes\n", __func__, __LINE__); | |
664 | BUG_ON(1); | |
665 | *eof = 1; | |
666 | return l; | |
667 | } | |
668 | #endif | |
669 | ||
670 | static int | |
671 | scif_fail_suspend(char *buf, char **start, off_t offset, int len, int *eof, void *data) | |
672 | { | |
673 | int l = 0; | |
674 | ||
675 | #ifdef _MIC_SCIF_ | |
676 | micscif_fail_suspend_handler(NULL, 0, NULL); | |
677 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
678 | "Failing Suspend\n"); | |
679 | #endif | |
680 | ||
681 | *eof = 1; | |
682 | return l; | |
683 | } | |
684 | ||
685 | static int | |
686 | scif_resume(char *buf, char **start, off_t offset, int len, int *eof, void *data) | |
687 | { | |
688 | int l = 0; | |
689 | ||
690 | #ifdef _MIC_SCIF_ | |
691 | micscif_resume_handler(NULL, 0, NULL); | |
692 | l += snprintf(buf + l, len - l > 0 ? len - l : 0, | |
693 | "Resuming/Waking up node\n"); | |
694 | #endif | |
695 | ||
696 | *eof = 1; | |
697 | return l; | |
698 | } | |
699 | ||
700 | static int | |
701 | scif_get_reg_cache_limit(char *buf, char **start, off_t offset, int len, int *eof, void *data) | |
702 | { | |
703 | int l = 0; | |
704 | ||
705 | l += snprintf(buf + l, len - l > 0 ? len - l : 0 , | |
706 | "reg_cache_limit = 0x%lx\n", ms_info.mi_rma_tc_limit); | |
707 | *eof = 1; | |
708 | return l; | |
709 | } | |
710 | ||
711 | static int | |
712 | scif_set_reg_cache_limit(struct file *file, const char __user *buffer, | |
713 | unsigned long len, void *unused) | |
714 | { | |
715 | unsigned long data = 0; | |
716 | char *p; | |
717 | if (!(p = kzalloc(len, GFP_KERNEL))) | |
718 | return -ENOMEM; | |
719 | if (copy_from_user(p, buffer, len)) | |
720 | return -EFAULT; | |
721 | data = simple_strtoul(p, NULL, 0); | |
722 | ms_info.mi_rma_tc_limit = data; | |
723 | return len; | |
724 | } | |
725 | #endif | |
726 | ||
727 | #ifdef _MIC_SCIF_ | |
728 | static int smpt_seq_show(struct seq_file *s, void *pos) | |
729 | { | |
730 | volatile uint8_t *mm_sbox = scif_dev[SCIF_HOST_NODE].mm_sbox; | |
731 | uint32_t smpt_reg_offset = SBOX_SMPT00; | |
732 | uint32_t smpt_reg_val; | |
733 | int i; | |
734 | ||
735 | seq_printf(s, | |
736 | "=================================================================\n"); | |
737 | seq_printf(s,"%-11s| %-15s %-14s %-5s \n", | |
738 | "SMPT entry", "SMPT reg value", "DMA addr", "SNOOP"); | |
739 | seq_printf(s, | |
740 | "=================================================================\n"); | |
741 | ||
742 | for (i = 0; i < NUM_SMPT_ENTRIES_IN_USE; i++) { | |
743 | smpt_reg_val = readl(mm_sbox + smpt_reg_offset); | |
744 | seq_printf(s,"%-11d| %-#15x %-#14llx %-5s \n", | |
745 | i, smpt_reg_val, ((uint64_t)smpt_reg_val >> 2ULL) << MIC_SYSTEM_PAGE_SHIFT, | |
746 | (smpt_reg_val & 0x1) ? "OFF" : "ON"); | |
747 | smpt_reg_offset += 4; | |
748 | } | |
749 | ||
750 | seq_printf(s, | |
751 | "=================================================================\n"); | |
752 | return 0; | |
753 | } | |
754 | ||
755 | #else | |
756 | static int smpt_seq_show(struct seq_file *s, void *pos) | |
757 | { | |
758 | uint64_t bid = (uint64_t)s->private; | |
759 | mic_ctx_t *mic_ctx; | |
760 | int i; | |
761 | unsigned long flags; | |
762 | ||
763 | mic_ctx = get_per_dev_ctx(bid); | |
764 | seq_printf(s, | |
765 | "=================================================================\n"); | |
766 | seq_printf(s,"Board %-2d |%-10s| %-14s %-10s \n", | |
767 | (int)bid + 1, "SMPT entry", "DMA addr", "Reference Count"); | |
768 | seq_printf(s, | |
769 | "=================================================================\n"); | |
770 | ||
771 | if (mic_ctx && mic_ctx->mic_smpt) { | |
772 | spin_lock_irqsave(&mic_ctx->smpt_lock, flags); | |
773 | for (i = 0; i < NUM_SMPT_ENTRIES_IN_USE; i++) { | |
774 | seq_printf(s,"%9s|%-10d| %-#14llx %-10lld \n", | |
775 | " ", i, mic_ctx->mic_smpt[i].dma_addr, mic_ctx->mic_smpt[i].ref_count); | |
776 | } | |
777 | spin_unlock_irqrestore(&mic_ctx->smpt_lock, flags); | |
778 | } | |
779 | ||
780 | seq_printf(s, | |
781 | "================================================================X\n"); | |
782 | return 0; | |
783 | } | |
784 | #endif | |
785 | ||
786 | static int smpt_debug_open(struct inode *inode, struct file *file) | |
787 | { | |
788 | return single_open(file, smpt_seq_show, inode->i_private); | |
789 | } | |
790 | ||
791 | static int smpt_debug_release(struct inode *inode, struct file *file) | |
792 | { | |
793 | return single_release(inode, file); | |
794 | } | |
795 | ||
796 | static struct file_operations smpt_file_ops = { | |
797 | .owner = THIS_MODULE, | |
798 | .open = smpt_debug_open, | |
799 | .read = seq_read, | |
800 | .llseek = seq_lseek, | |
801 | .release = smpt_debug_release | |
802 | }; | |
803 | ||
804 | #ifndef _MIC_SCIF_ | |
805 | static int log_buf_seq_show(struct seq_file *s, void *pos) | |
806 | { | |
807 | uint64_t bid = (uint64_t)s->private; | |
808 | mic_ctx_t *mic_ctx; | |
809 | void *log_buf_len_va, *log_buf_va; | |
810 | struct micscif_dev *dev; | |
811 | ||
812 | mic_ctx = get_per_dev_ctx(bid); | |
813 | if (!mic_ctx || !mic_ctx->log_buf_addr || !mic_ctx->log_buf_len) | |
814 | goto done; | |
815 | ||
816 | if (mic_ctx->bi_family == FAMILY_ABR) { | |
817 | seq_printf(s, "log buffer display not supported for KNF\n"); | |
818 | goto done; | |
819 | } | |
820 | ||
821 | dev = &scif_dev[mic_get_scifnode_id(mic_ctx)]; | |
822 | log_buf_len_va = virt_to_phys(mic_ctx->log_buf_len) + mic_ctx->aper.va; | |
823 | log_buf_va = virt_to_phys(mic_ctx->log_buf_addr) + mic_ctx->aper.va; | |
824 | ||
825 | mutex_lock(&mic_ctx->state_lock); | |
826 | switch (mic_ctx->state) { | |
827 | case MIC_BOOT: | |
828 | case MIC_BOOTFAIL: | |
829 | case MIC_ONLINE: | |
830 | case MIC_SHUTDOWN: | |
831 | case MIC_LOST: | |
832 | micscif_inc_node_refcnt(dev, 1); | |
833 | seq_write(s, log_buf_va, *(int*)log_buf_len_va); | |
834 | micscif_dec_node_refcnt(dev, 1); | |
835 | break; | |
836 | case MIC_NORESPONSE: | |
837 | case MIC_READY: | |
838 | /* Cannot access GDDR while reset is ongoing */ | |
839 | case MIC_RESET: | |
840 | case MIC_RESETFAIL: | |
841 | case MIC_INVALID: | |
842 | default: | |
843 | break; | |
844 | } | |
845 | mutex_unlock(&mic_ctx->state_lock); | |
846 | done: | |
847 | return 0; | |
848 | } | |
849 | ||
850 | static int log_buf_open(struct inode *inode, struct file *file) | |
851 | { | |
852 | return single_open(file, log_buf_seq_show, inode->i_private); | |
853 | } | |
854 | ||
855 | static int log_buf_release(struct inode *inode, struct file *file) | |
856 | { | |
857 | return single_release(inode, file); | |
858 | } | |
859 | ||
860 | static struct file_operations log_buf_ops = { | |
861 | .owner = THIS_MODULE, | |
862 | .open = log_buf_open, | |
863 | .read = seq_read, | |
864 | .llseek = seq_lseek, | |
865 | .release = log_buf_release | |
866 | }; | |
867 | #endif | |
868 | ||
869 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) | |
870 | void | |
871 | scif_proc_init(void) | |
872 | { | |
873 | if ((scif_proc = proc_mkdir("scif", NULL)) != NULL) { | |
874 | proc_create_data("ep", 0444, scif_proc, &scif_ep_fops, NULL); | |
875 | proc_create_data("rma_window", 0444, scif_proc, &scif_rma_window_fops, NULL); | |
876 | proc_create_data("rma_xfer", 0444, scif_proc, &scif_rma_xfer_fops, NULL); | |
877 | proc_create_data("scif_dev", 0444, scif_proc, &scif_dev_fops, NULL); | |
878 | proc_create_data("debug", 0444, scif_proc, &scif_debug_fops, NULL); | |
879 | proc_create_data("suspend", 0444, scif_proc, &scif_suspend_fops, NULL); | |
880 | proc_create("reg_cache_limit", S_IFREG | S_IRUGO | S_IWUGO, scif_proc, | |
881 | &scif_cache_limit_fops); | |
882 | } | |
883 | } | |
884 | #else | |
885 | void | |
886 | scif_proc_init(void) | |
887 | { | |
888 | struct proc_dir_entry *reg_cache_limit_entry; | |
889 | struct proc_dir_entry *ep_entry; | |
890 | ||
891 | if ((scif_proc = create_proc_entry("scif", S_IFDIR | S_IRUGO, NULL)) != NULL) { | |
892 | create_proc_read_entry("rma_window", 0444, scif_proc, scif_rma_window_read, NULL); | |
893 | create_proc_read_entry("rma_xfer", 0444, scif_proc, scif_rma_xfer_read, NULL); | |
894 | create_proc_read_entry("scif_dev", 0444, scif_proc, scif_dev_info, NULL); | |
895 | create_proc_read_entry("debug", 0444, scif_proc, scif_debug_read, NULL); | |
896 | create_proc_read_entry("suspend", 0444, scif_proc, scif_suspend, NULL); | |
897 | create_proc_read_entry("fail_suspend", 0444, scif_proc, scif_fail_suspend, NULL); | |
898 | create_proc_read_entry("resume", 0444, scif_proc, scif_resume, NULL); | |
899 | #ifdef _MIC_SCIF_ | |
900 | create_proc_read_entry("crash", 0444, scif_proc, scif_crash, NULL); | |
901 | create_proc_read_entry("bugon", 0444, scif_proc, scif_bugon, NULL); | |
902 | #endif | |
903 | if ((reg_cache_limit_entry = create_proc_entry("reg_cache_limit", S_IFREG | S_IRUGO | S_IWUGO, scif_proc))) { | |
904 | reg_cache_limit_entry->write_proc = scif_set_reg_cache_limit; | |
905 | reg_cache_limit_entry->read_proc = scif_get_reg_cache_limit; | |
906 | reg_cache_limit_entry->data = NULL; | |
907 | } | |
908 | if ((ep_entry = create_proc_entry("ep", S_IFREG | S_IRUGO | S_IWUGO, scif_proc))) { | |
909 | ep_entry->proc_fops = &scif_ep_fops; | |
910 | } | |
911 | ||
912 | ||
913 | } | |
914 | } | |
915 | #endif // LINUX VERSION | |
916 | ||
917 | #ifdef _MIC_SCIF_ | |
918 | void | |
919 | mic_debug_init(void) | |
920 | { | |
921 | if ((mic_debug = debugfs_create_dir("mic_debug", NULL))) { | |
922 | debugfs_create_file("smpt", 0444, mic_debug, NULL, &smpt_file_ops); | |
923 | debugfs_create_u8("enable_msg_logging", 0666, mic_debug, &(ms_info.en_msg_log)); | |
924 | } | |
925 | } | |
926 | #else | |
927 | void | |
928 | mic_debug_init(mic_ctx_t *mic_ctx) | |
929 | { | |
930 | char name[DEBUG_LEN]; | |
931 | uint64_t id = mic_ctx->bi_id; | |
932 | struct dentry *child; | |
933 | ||
934 | if (!mic_debug) | |
935 | mic_debug = debugfs_create_dir("mic_debug", NULL); | |
936 | ||
937 | if (mic_debug) { | |
938 | snprintf(name, DEBUG_LEN, "mic%d", (int)id); | |
939 | if ((child = debugfs_create_dir(name, mic_debug))) { | |
940 | debugfs_create_file("smpt", 0444, child, (void*)id, &smpt_file_ops); | |
941 | debugfs_create_file("log_buf", 0444, child, (void*)id, &log_buf_ops); | |
942 | } | |
943 | debugfs_create_u8("enable_msg_logging", 0666, mic_debug, &(ms_info.en_msg_log)); | |
944 | } | |
945 | } | |
946 | #endif | |
947 | ||
948 | void | |
949 | mic_debug_uninit(void) | |
950 | { | |
951 | debugfs_remove_recursive(mic_debug); | |
952 | } | |
953 | ||
954 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) | |
955 | void | |
956 | scif_proc_cleanup(void) | |
957 | { | |
958 | if (scif_proc) | |
959 | remove_proc_subtree("scif", NULL); | |
960 | } | |
961 | #else | |
962 | void | |
963 | scif_proc_cleanup(void) | |
964 | { | |
965 | if (scif_proc) { | |
966 | remove_proc_entry("reg_cache_limit", scif_proc); | |
967 | remove_proc_entry("ep", scif_proc); | |
968 | remove_proc_entry("rma_window", scif_proc); | |
969 | remove_proc_entry("rma_xfer", scif_proc); | |
970 | remove_proc_entry("scif_dev", scif_proc); | |
971 | remove_proc_entry("debug", scif_proc); | |
972 | remove_proc_entry("suspend", scif_proc); | |
973 | remove_proc_entry("fail_suspend", scif_proc); | |
974 | remove_proc_entry("resume", scif_proc); | |
975 | #ifdef _MIC_SCIF_ | |
976 | remove_proc_entry("crash", scif_proc); | |
977 | remove_proc_entry("bugon", scif_proc); | |
978 | #endif | |
979 | remove_proc_entry("scif", NULL); | |
980 | scif_proc = NULL; | |
981 | } | |
982 | } | |
983 | #endif | |
984 | ||
985 | #ifdef _MIC_SCIF_ | |
986 | extern int micscif_max_msg_id; | |
987 | ||
988 | /* | |
989 | * Test entry point for error injection | |
990 | */ | |
991 | int | |
992 | micscif_error_inject(int scenario) | |
993 | { | |
994 | switch (scenario) { | |
995 | case 1: | |
996 | micscif_max_msg_id = 0; | |
997 | break; | |
998 | default: | |
999 | pr_debug("Illegal error injection scenario %d\n", scenario); | |
1000 | return -EINVAL; | |
1001 | } | |
1002 | return 0; | |
1003 | } | |
1004 | EXPORT_SYMBOL(micscif_error_inject); | |
1005 | #endif // _MIC_SCIF_ |