| // SPDX-License-Identifier: GPL-2.0 | 
 | #include <linux/ftrace.h> | 
 | #include <linux/tracepoint.h> | 
 | #include <linux/kernel.h> | 
 | #include <linux/module.h> | 
 | #include <linux/init.h> | 
 | #include <linux/rv.h> | 
 | #include <rv/instrumentation.h> | 
 | #include <rv/da_monitor.h> | 
 |  | 
 | #define MODULE_NAME "wwnr" | 
 |  | 
 | #include <trace/events/rv.h> | 
 | #include <trace/events/sched.h> | 
 |  | 
 | #include "wwnr.h" | 
 |  | 
 | static struct rv_monitor rv_wwnr; | 
 | DECLARE_DA_MON_PER_TASK(wwnr, unsigned char); | 
 |  | 
 | static void handle_switch(void *data, bool preempt, struct task_struct *p, | 
 | 			  struct task_struct *n, unsigned int prev_state) | 
 | { | 
 | 	/* start monitoring only after the first suspension */ | 
 | 	if (prev_state == TASK_INTERRUPTIBLE) | 
 | 		da_handle_start_event_wwnr(p, switch_out_wwnr); | 
 | 	else | 
 | 		da_handle_event_wwnr(p, switch_out_wwnr); | 
 |  | 
 | 	da_handle_event_wwnr(n, switch_in_wwnr); | 
 | } | 
 |  | 
 | static void handle_wakeup(void *data, struct task_struct *p) | 
 | { | 
 | 	da_handle_event_wwnr(p, wakeup_wwnr); | 
 | } | 
 |  | 
 | static int enable_wwnr(void) | 
 | { | 
 | 	int retval; | 
 |  | 
 | 	retval = da_monitor_init_wwnr(); | 
 | 	if (retval) | 
 | 		return retval; | 
 |  | 
 | 	rv_attach_trace_probe("wwnr", sched_switch, handle_switch); | 
 | 	rv_attach_trace_probe("wwnr", sched_wakeup, handle_wakeup); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static void disable_wwnr(void) | 
 | { | 
 | 	rv_wwnr.enabled = 0; | 
 |  | 
 | 	rv_detach_trace_probe("wwnr", sched_switch, handle_switch); | 
 | 	rv_detach_trace_probe("wwnr", sched_wakeup, handle_wakeup); | 
 |  | 
 | 	da_monitor_destroy_wwnr(); | 
 | } | 
 |  | 
 | static struct rv_monitor rv_wwnr = { | 
 | 	.name = "wwnr", | 
 | 	.description = "wakeup while not running per-task testing model.", | 
 | 	.enable = enable_wwnr, | 
 | 	.disable = disable_wwnr, | 
 | 	.reset = da_monitor_reset_all_wwnr, | 
 | 	.enabled = 0, | 
 | }; | 
 |  | 
 | static int __init register_wwnr(void) | 
 | { | 
 | 	rv_register_monitor(&rv_wwnr); | 
 | 	return 0; | 
 | } | 
 |  | 
 | static void __exit unregister_wwnr(void) | 
 | { | 
 | 	rv_unregister_monitor(&rv_wwnr); | 
 | } | 
 |  | 
 | module_init(register_wwnr); | 
 | module_exit(unregister_wwnr); | 
 |  | 
 | MODULE_LICENSE("GPL"); | 
 | MODULE_AUTHOR("Daniel Bristot de Oliveira <bristot@kernel.org>"); | 
 | MODULE_DESCRIPTION("wwnr: wakeup while not running monitor"); |