diff options
-rw-r--r-- | include/litmus/litmus_softirq.h | 17 | ||||
-rw-r--r-- | include/litmus/nvidia_info.h | 10 | ||||
-rw-r--r-- | include/litmus/sched_trace.h | 7 | ||||
-rw-r--r-- | kernel/softirq.c | 31 | ||||
-rw-r--r-- | kernel/workqueue.c | 87 | ||||
-rw-r--r-- | litmus/Kconfig | 37 | ||||
-rw-r--r-- | litmus/litmus.c | 2 | ||||
-rw-r--r-- | litmus/litmus_softirq.c | 10 | ||||
-rw-r--r-- | litmus/nvidia_info.c | 306 | ||||
-rw-r--r-- | litmus/sched_cedf.c | 4 | ||||
-rw-r--r-- | litmus/sched_task_trace.c | 4 |
11 files changed, 388 insertions, 127 deletions
diff --git a/include/litmus/litmus_softirq.h b/include/litmus/litmus_softirq.h index cfef08187464..e9590835dc19 100644 --- a/include/litmus/litmus_softirq.h +++ b/include/litmus/litmus_softirq.h | |||
@@ -153,14 +153,27 @@ static inline int _litmus_tasklet_hi_schedule_first( | |||
153 | ////////////// | 153 | ////////////// |
154 | 154 | ||
155 | extern int __litmus_schedule_work( | 155 | extern int __litmus_schedule_work( |
156 | struct work_struct* w, | 156 | struct work_struct *w, |
157 | struct task_struct *klmirqd_thread); | 157 | struct task_struct *klmirqd_thread); |
158 | 158 | ||
159 | static inline int litmus_schedule_work( | 159 | static inline int litmus_schedule_work( |
160 | struct work_struct* w, | 160 | struct work_struct *w, |
161 | struct task_struct *klmirqd_thread) | ||
162 | { | ||
163 | int ret = 0; | ||
164 | if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(w))) { | ||
165 | ret = __litmus_schedule_work(w, klmirqd_thread); | ||
166 | } | ||
167 | return(ret); | ||
168 | } | ||
169 | |||
170 | static inline int _litmus_schedule_work( | ||
171 | struct work_struct *w, | ||
161 | struct task_struct *klmirqd_thread) | 172 | struct task_struct *klmirqd_thread) |
162 | { | 173 | { |
163 | return(__litmus_schedule_work(w, klmirqd_thread)); | 174 | return(__litmus_schedule_work(w, klmirqd_thread)); |
164 | } | 175 | } |
165 | 176 | ||
177 | |||
178 | |||
166 | #endif | 179 | #endif |
diff --git a/include/litmus/nvidia_info.h b/include/litmus/nvidia_info.h index 0ebe9c10c6a2..7db4a32af734 100644 --- a/include/litmus/nvidia_info.h +++ b/include/litmus/nvidia_info.h | |||
@@ -28,7 +28,15 @@ u32 get_work_nv_device_num(const struct work_struct *t); | |||
28 | struct task_struct* get_nv_max_device_owner(u32 target_device_id); | 28 | struct task_struct* get_nv_max_device_owner(u32 target_device_id); |
29 | 29 | ||
30 | #ifdef CONFIG_LITMUS_SOFTIRQD | 30 | #ifdef CONFIG_LITMUS_SOFTIRQD |
31 | struct task_struct* get_nv_klmirqd_thread(u32 target_device_id); | 31 | struct task_struct* get_and_lock_nvklmirqd_thread(u32 target_device_id, unsigned long* flags); |
32 | void unlock_nvklmirqd_thread(u32 target_device_id, unsigned long* flags); | ||
33 | struct task_struct* get_nvklmirqd_thread(u32 target_device_id); | ||
34 | |||
35 | #if defined(CONFIG_LITMUS_NVIDIA_WORKQ_ON) || defined(CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED) | ||
36 | struct task_struct* get_and_lock_nvklmworkqd_thread(u32 target_device_id, unsigned long* flags); | ||
37 | void unlock_nvklmworkqd_thread(u32 target_device_id, unsigned long* flags); | ||
38 | struct task_struct* get_nvklmworkqd_thread(u32 target_device_id); | ||
39 | #endif | ||
32 | #endif | 40 | #endif |
33 | 41 | ||
34 | /* call when the GPU-holding task, t, blocks */ | 42 | /* call when the GPU-holding task, t, blocks */ |
diff --git a/include/litmus/sched_trace.h b/include/litmus/sched_trace.h index 2598cdf6088e..0d22c275dd72 100644 --- a/include/litmus/sched_trace.h +++ b/include/litmus/sched_trace.h | |||
@@ -103,7 +103,8 @@ struct st_tasklet_end_data { | |||
103 | 103 | ||
104 | struct st_work_release_data { | 104 | struct st_work_release_data { |
105 | u64 when; | 105 | u64 when; |
106 | u64 __unused; | 106 | u32 device; |
107 | u32 __unused; | ||
107 | } __attribute__((packed)); | 108 | } __attribute__((packed)); |
108 | 109 | ||
109 | struct st_work_begin_data { | 110 | struct st_work_begin_data { |
@@ -408,8 +409,8 @@ feather_callback void do_sched_trace_migration(unsigned long id, | |||
408 | SCHED_TRACE2(SCHED_TRACE_BASE_ID + 13, do_sched_trace_tasklet_end, t, flushed) | 409 | SCHED_TRACE2(SCHED_TRACE_BASE_ID + 13, do_sched_trace_tasklet_end, t, flushed) |
409 | 410 | ||
410 | 411 | ||
411 | #define sched_trace_work_release(t) \ | 412 | #define sched_trace_work_release(t, d) \ |
412 | SCHED_TRACE(SCHED_TRACE_BASE_ID + 14, do_sched_trace_work_release, t) | 413 | SCHED_TRACE2(SCHED_TRACE_BASE_ID + 14, do_sched_trace_work_release, t, d) |
413 | 414 | ||
414 | #define sched_trace_work_begin(t, e) \ | 415 | #define sched_trace_work_begin(t, e) \ |
415 | SCHED_TRACE2(SCHED_TRACE_BASE_ID + 15, do_sched_trace_work_begin, t, e) | 416 | SCHED_TRACE2(SCHED_TRACE_BASE_ID + 15, do_sched_trace_work_begin, t, e) |
diff --git a/kernel/softirq.c b/kernel/softirq.c index 3ad0e7d9e782..ef70dbe92a97 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -455,23 +455,30 @@ typedef int (*klmirqd_tasklet_sched_t)( | |||
455 | static int __klmirqd_nv_tasklet_schedule(struct tasklet_struct *t, | 455 | static int __klmirqd_nv_tasklet_schedule(struct tasklet_struct *t, |
456 | klmirqd_tasklet_sched_t klmirqd_func) | 456 | klmirqd_tasklet_sched_t klmirqd_func) |
457 | { | 457 | { |
458 | u32 nvidia_device = get_tasklet_nv_device_num(t); | 458 | /* TODO: MOVE THIS TO nvidia_info.c */ |
459 | struct task_struct* klmirqd_th = get_nv_klmirqd_thread(nvidia_device); | 459 | unsigned long flags; |
460 | u32 nvidia_device; | ||
461 | struct task_struct* klmirqd_th; | ||
460 | 462 | ||
461 | BUG_ON(!klmirqd_func); | 463 | BUG_ON(!klmirqd_func); |
462 | 464 | ||
463 | TRACE("Handling NVIDIA tasklet for device %u (klmirqd: %s/%d) at %llu\n", | 465 | nvidia_device = get_tasklet_nv_device_num(t); |
464 | nvidia_device, | 466 | klmirqd_th = get_and_lock_nvklmirqd_thread(nvidia_device, &flags); |
465 | (klmirqd_th) ? klmirqd_th->comm : "nil", | ||
466 | (klmirqd_th) ? klmirqd_th->pid : 0, | ||
467 | litmus_clock()); | ||
468 | 467 | ||
469 | sched_trace_tasklet_release(NULL, nvidia_device); | 468 | if (likely(klmirqd_th)) { |
469 | TRACE("Handling NVIDIA tasklet for device %u (klmirqd: %s/%d) at %llu\n", | ||
470 | nvidia_device, | ||
471 | klmirqd_th->comm, | ||
472 | klmirqd_th->pid, | ||
473 | litmus_clock()); | ||
470 | 474 | ||
471 | if (klmirqd_th && likely(klmirqd_func(t, klmirqd_th))) | 475 | sched_trace_tasklet_release(NULL, nvidia_device); |
472 | return 1; | 476 | if(likely(klmirqd_func(t, klmirqd_th))) { |
473 | else | 477 | unlock_nvklmirqd_thread(nvidia_device, &flags); |
474 | return 0; | 478 | return 1; /* success */ |
479 | } | ||
480 | } | ||
481 | return 0; | ||
475 | } | 482 | } |
476 | #endif | 483 | #endif |
477 | 484 | ||
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 6b59d59ce3cf..9eb58729e1bb 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -44,10 +44,11 @@ | |||
44 | 44 | ||
45 | #include "workqueue_sched.h" | 45 | #include "workqueue_sched.h" |
46 | 46 | ||
47 | #ifdef CONFIG_LITMUS_NVIDIA | 47 | #if defined(CONFIG_LITMUS_NVIDIA_WORKQ_ON) || defined(CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED) |
48 | #include <litmus/litmus.h> | 48 | #include <litmus/litmus.h> |
49 | #include <litmus/sched_trace.h> | ||
50 | #include <litmus/nvidia_info.h> | 49 | #include <litmus/nvidia_info.h> |
50 | #include <litmus/sched_trace.h> | ||
51 | #include <litmus/trace.h> | ||
51 | #endif | 52 | #endif |
52 | 53 | ||
53 | 54 | ||
@@ -2679,6 +2680,32 @@ bool cancel_delayed_work_sync(struct delayed_work *dwork) | |||
2679 | } | 2680 | } |
2680 | EXPORT_SYMBOL(cancel_delayed_work_sync); | 2681 | EXPORT_SYMBOL(cancel_delayed_work_sync); |
2681 | 2682 | ||
2683 | |||
2684 | #if defined(CONFIG_LITMUS_NVIDIA_WORKQ_ON) || defined(CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED) | ||
2685 | static int __klmirqd_nv_work_schedule(struct work_struct *work) | ||
2686 | { | ||
2687 | /* TODO: MOVE THIS TO nvidia_info.c */ | ||
2688 | unsigned long flags; | ||
2689 | u32 nvidia_device = get_work_nv_device_num(work); | ||
2690 | struct task_struct* klmirqd_th = get_and_lock_nvklmworkqd_thread(nvidia_device, &flags); | ||
2691 | |||
2692 | if (likely(klmirqd_th)) { | ||
2693 | TRACE("Handling NVIDIA workq for device %u (klmirqd: %s/%d) at %llu\n", | ||
2694 | nvidia_device, | ||
2695 | klmirqd_th->comm, | ||
2696 | klmirqd_th->pid, | ||
2697 | litmus_clock()); | ||
2698 | |||
2699 | sched_trace_work_release(NULL, nvidia_device); | ||
2700 | if (likely(litmus_schedule_work(work, klmirqd_th))) { | ||
2701 | unlock_nvklmworkqd_thread(nvidia_device, &flags); | ||
2702 | return 1; /* success */ | ||
2703 | } | ||
2704 | } | ||
2705 | return 0; | ||
2706 | } | ||
2707 | #endif | ||
2708 | |||
2682 | /** | 2709 | /** |
2683 | * schedule_work - put work task in global workqueue | 2710 | * schedule_work - put work task in global workqueue |
2684 | * @work: job to be done | 2711 | * @work: job to be done |
@@ -2692,60 +2719,14 @@ EXPORT_SYMBOL(cancel_delayed_work_sync); | |||
2692 | */ | 2719 | */ |
2693 | int schedule_work(struct work_struct *work) | 2720 | int schedule_work(struct work_struct *work) |
2694 | { | 2721 | { |
2695 | #if 0 | 2722 | #if defined(CONFIG_LITMUS_NVIDIA_WORKQ_ON) || defined(CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED) |
2696 | #if defined(CONFIG_LITMUS_NVIDIA) && defined(CONFIG_LITMUS_SOFTIRQD) | 2723 | if(is_nvidia_func(work->func)) { |
2697 | if(is_nvidia_func(work->func)) | 2724 | if (__klmirqd_nv_work_schedule(work)) { |
2698 | { | 2725 | return 1; |
2699 | u32 nvidiaDevice = get_work_nv_device_num(work); | ||
2700 | |||
2701 | //1) Ask Litmus which task owns GPU <nvidiaDevice>. (API to be defined.) | ||
2702 | unsigned long flags; | ||
2703 | struct task_struct* device_owner; | ||
2704 | |||
2705 | lock_nv_registry(nvidiaDevice, &flags); | ||
2706 | |||
2707 | device_owner = get_nv_max_device_owner(nvidiaDevice); | ||
2708 | |||
2709 | //2) If there is an owner, set work->owner to the owner's task struct. | ||
2710 | if(device_owner==NULL) | ||
2711 | { | ||
2712 | work->owner = NULL; | ||
2713 | //TRACE("%s: the owner task of NVIDIA Device %u is NULL\n",__FUNCTION__,nvidiaDevice); | ||
2714 | } | 2726 | } |
2715 | else | ||
2716 | { | ||
2717 | if( is_realtime(device_owner)) | ||
2718 | { | ||
2719 | TRACE("%s: Handling NVIDIA work for device\t%u\tat\t%llu\n", | ||
2720 | __FUNCTION__, nvidiaDevice,litmus_clock()); | ||
2721 | TRACE("%s: the owner task %d of NVIDIA Device %u is RT-task\n", | ||
2722 | __FUNCTION__, | ||
2723 | device_owner->pid, | ||
2724 | nvidiaDevice); | ||
2725 | |||
2726 | //3) Call litmus_schedule_work() and return (don't execute the rest | ||
2727 | // of schedule_schedule()). | ||
2728 | work->owner = device_owner; | ||
2729 | sched_trace_work_release(work->owner); | ||
2730 | if(likely(litmus_schedule_work(work, nvidiaDevice))) | ||
2731 | { | ||
2732 | unlock_nv_registry(nvidiaDevice, &flags); | ||
2733 | return 1; | ||
2734 | } | ||
2735 | else | ||
2736 | { | ||
2737 | work->owner = NULL; /* fall through to normal work scheduling */ | ||
2738 | } | ||
2739 | } | ||
2740 | else | ||
2741 | { | ||
2742 | work->owner = NULL; | ||
2743 | } | ||
2744 | } | ||
2745 | unlock_nv_registry(nvidiaDevice, &flags); | ||
2746 | } | 2727 | } |
2747 | #endif | 2728 | #endif |
2748 | #endif | 2729 | |
2749 | return(__schedule_work(work)); | 2730 | return(__schedule_work(work)); |
2750 | } | 2731 | } |
2751 | EXPORT_SYMBOL(schedule_work); | 2732 | EXPORT_SYMBOL(schedule_work); |
diff --git a/litmus/Kconfig b/litmus/Kconfig index bf802b760e1f..fad4220ae49f 100644 --- a/litmus/Kconfig +++ b/litmus/Kconfig | |||
@@ -400,7 +400,7 @@ config LITMUS_SOFTIRQD_NONE | |||
400 | Don't schedule tasklets in Litmus. Default. | 400 | Don't schedule tasklets in Litmus. Default. |
401 | 401 | ||
402 | config LITMUS_SOFTIRQD | 402 | config LITMUS_SOFTIRQD |
403 | bool "Spawn klmirqd interrupt handling threads." | 403 | bool "Enable klmirqd interrupt (and workqueue) handling threads." |
404 | help | 404 | help |
405 | Create klmirqd interrupt handling threads. Work must be | 405 | Create klmirqd interrupt handling threads. Work must be |
406 | specifically dispatched to these workers. (Softirqs for | 406 | specifically dispatched to these workers. (Softirqs for |
@@ -423,11 +423,10 @@ endchoice | |||
423 | 423 | ||
424 | 424 | ||
425 | config LITMUS_NVIDIA | 425 | config LITMUS_NVIDIA |
426 | bool "Litmus handling of NVIDIA interrupts." | 426 | bool "Litmus handling of NVIDIA driver." |
427 | default n | 427 | default n |
428 | help | 428 | help |
429 | Direct tasklets from NVIDIA devices to Litmus's klmirqd | 429 | Enable Litmus control of NVIDIA driver tasklet/workqueues. |
430 | or PAI interrupt handling routines. | ||
431 | 430 | ||
432 | If unsure, say No. | 431 | If unsure, say No. |
433 | 432 | ||
@@ -444,6 +443,36 @@ config LITMUS_NVIDIA_NONSPLIT_INTERRUPTS | |||
444 | 443 | ||
445 | If unsure, say No. | 444 | If unsure, say No. |
446 | 445 | ||
446 | choice | ||
447 | prompt "Litmus handling of NVIDIA workqueues." | ||
448 | depends on LITMUS_NVIDIA | ||
449 | default LITMUS_NVIDIA_WORKQ_OFF | ||
450 | help | ||
451 | Select method for handling NVIDIA workqueues. | ||
452 | |||
453 | config LITMUS_NVIDIA_WORKQ_OFF | ||
454 | bool "Use Linux's default work queues." | ||
455 | help | ||
456 | Let Linux process all NVIDIA work queue items. | ||
457 | |||
458 | config LITMUS_NVIDIA_WORKQ_ON | ||
459 | bool "Schedule work with interrupt thread." | ||
460 | depends on LITMUS_SOFTIRQD | ||
461 | help | ||
462 | Direct work queue items from NVIDIA devices Litmus's | ||
463 | klmirqd handling routines. Use the same thread | ||
464 | as interrupt handling. | ||
465 | |||
466 | config LITMUS_NVIDIA_WORKQ_ON_DEDICATED | ||
467 | bool "Sechedule work in dedicated threads." | ||
468 | depends on LITMUS_SOFTIRQD | ||
469 | help | ||
470 | Direct work queue items from NVIDIA devices to Litmus's | ||
471 | klmirqd handling routines. Use dedicated thread for | ||
472 | work (seperate thread from interrupt handling). | ||
473 | |||
474 | endchoice | ||
475 | |||
447 | config LITMUS_AFFINITY_AWARE_GPU_ASSINGMENT | 476 | config LITMUS_AFFINITY_AWARE_GPU_ASSINGMENT |
448 | bool "Enable affinity-aware heuristics to improve GPU assignment." | 477 | bool "Enable affinity-aware heuristics to improve GPU assignment." |
449 | depends on LITMUS_NVIDIA && LITMUS_AFFINITY_LOCKING | 478 | depends on LITMUS_NVIDIA && LITMUS_AFFINITY_LOCKING |
diff --git a/litmus/litmus.c b/litmus/litmus.c index f0d01c34110c..740b5e57ecc1 100644 --- a/litmus/litmus.c +++ b/litmus/litmus.c | |||
@@ -736,7 +736,7 @@ static int litmus_shutdown_nb(struct notifier_block *unused1, | |||
736 | if (litmus != &linux_sched_plugin) { | 736 | if (litmus != &linux_sched_plugin) { |
737 | int ret = switch_sched_plugin(&linux_sched_plugin); | 737 | int ret = switch_sched_plugin(&linux_sched_plugin); |
738 | if (ret) { | 738 | if (ret) { |
739 | printk("Auto-shutdown of active Litmus plugin failed.\n"); | 739 | printk(KERN_EMERG "Auto-shutdown of active Litmus plugin failed.\n"); |
740 | } | 740 | } |
741 | } | 741 | } |
742 | return NOTIFY_DONE; | 742 | return NOTIFY_DONE; |
diff --git a/litmus/litmus_softirq.c b/litmus/litmus_softirq.c index a5d61afe7952..aa83b363be7c 100644 --- a/litmus/litmus_softirq.c +++ b/litmus/litmus_softirq.c | |||
@@ -883,9 +883,6 @@ void flush_pending(struct task_struct* tsk) | |||
883 | 883 | ||
884 | work_flushed |= LIT_TASKLET_HI; | 884 | work_flushed |= LIT_TASKLET_HI; |
885 | 885 | ||
886 | // t->owner = NULL; | ||
887 | |||
888 | // WTF? | ||
889 | if(!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) | 886 | if(!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) |
890 | { | 887 | { |
891 | atomic_dec(&which->num_hi_pending); | 888 | atomic_dec(&which->num_hi_pending); |
@@ -923,9 +920,6 @@ void flush_pending(struct task_struct* tsk) | |||
923 | 920 | ||
924 | work_flushed |= LIT_TASKLET_LOW; | 921 | work_flushed |= LIT_TASKLET_LOW; |
925 | 922 | ||
926 | // t->owner = NULL; | ||
927 | // sched_trace_tasklet_end(owner, 1ul); | ||
928 | |||
929 | if(!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) | 923 | if(!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) |
930 | { | 924 | { |
931 | atomic_dec(&which->num_low_pending); | 925 | atomic_dec(&which->num_low_pending); |
@@ -956,14 +950,10 @@ void flush_pending(struct task_struct* tsk) | |||
956 | atomic_dec(&which->num_work_pending); | 950 | atomic_dec(&which->num_work_pending); |
957 | 951 | ||
958 | work->owner = NULL; | 952 | work->owner = NULL; |
959 | // sched_trace_work_end(owner, current, 1ul); | ||
960 | __schedule_work(work); | 953 | __schedule_work(work); |
961 | } | 954 | } |
962 | } | 955 | } |
963 | 956 | ||
964 | //__dump_state(which, "flush_pending: after (before reeval prio)"); | ||
965 | |||
966 | |||
967 | mb(); /* commit changes to pending flags */ | 957 | mb(); /* commit changes to pending flags */ |
968 | 958 | ||
969 | raw_spin_unlock_irqrestore(&which->lock, flags); | 959 | raw_spin_unlock_irqrestore(&which->lock, flags); |
diff --git a/litmus/nvidia_info.c b/litmus/nvidia_info.c index 29031f741fcf..7f1dc18624e1 100644 --- a/litmus/nvidia_info.c +++ b/litmus/nvidia_info.c | |||
@@ -141,7 +141,7 @@ typedef struct litmus_nv_linux_state_s { | |||
141 | } litmus_nv_linux_state_t; | 141 | } litmus_nv_linux_state_t; |
142 | 142 | ||
143 | 143 | ||
144 | 144 | #ifdef CONFIG_SCHED_DEBUG_TRACE | |
145 | static void __attribute__((unused)) | 145 | static void __attribute__((unused)) |
146 | dump_nvidia_info(const struct tasklet_struct *t) | 146 | dump_nvidia_info(const struct tasklet_struct *t) |
147 | { | 147 | { |
@@ -192,7 +192,6 @@ dump_nvidia_info(const struct tasklet_struct *t) | |||
192 | int ns_offset_raw = (void*)(&(linuxstate->device_num)) - (void*)(&(linuxstate->nv_state)); | 192 | int ns_offset_raw = (void*)(&(linuxstate->device_num)) - (void*)(&(linuxstate->nv_state)); |
193 | int ns_offset_desired = (void*)(&(linuxstate->device_num)) - (void*)(nvstate); | 193 | int ns_offset_desired = (void*)(&(linuxstate->device_num)) - (void*)(nvstate); |
194 | 194 | ||
195 | |||
196 | TRACE("LINUX NV State:\n" | 195 | TRACE("LINUX NV State:\n" |
197 | "\tlinux nv state ptr: %p\n" | 196 | "\tlinux nv state ptr: %p\n" |
198 | "\taddress of tasklet: %p\n" | 197 | "\taddress of tasklet: %p\n" |
@@ -226,14 +225,39 @@ dump_nvidia_info(const struct tasklet_struct *t) | |||
226 | TRACE("INVALID LINUXNVSTATE?????\n"); | 225 | TRACE("INVALID LINUXNVSTATE?????\n"); |
227 | } | 226 | } |
228 | } | 227 | } |
229 | 228 | #endif | |
230 | 229 | ||
231 | 230 | ||
232 | static struct module* nvidia_mod = NULL; | 231 | static struct module* nvidia_mod = NULL; |
233 | 232 | ||
234 | static int init_nv_device_reg(void); | 233 | static int init_nv_device_reg(void); |
235 | static int shutdown_nv_device_reg(void); | 234 | static int shutdown_nv_device_reg(void); |
235 | void shutdown_nvidia_info(void); | ||
236 | 236 | ||
237 | static int nvidia_going_module_notify(struct notifier_block *self, | ||
238 | unsigned long val, void *data) | ||
239 | { | ||
240 | struct module *mod = data; | ||
241 | |||
242 | if (nvidia_mod && (mod == nvidia_mod)) { | ||
243 | switch (val) { | ||
244 | case MODULE_STATE_GOING: | ||
245 | /* just set our mod reference to null to avoid crash */ | ||
246 | nvidia_mod = NULL; | ||
247 | mb(); | ||
248 | break; | ||
249 | default: | ||
250 | break; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static struct notifier_block nvidia_going = { | ||
258 | .notifier_call = nvidia_going_module_notify, | ||
259 | .priority = 1, | ||
260 | }; | ||
237 | 261 | ||
238 | int init_nvidia_info(void) | 262 | int init_nvidia_info(void) |
239 | { | 263 | { |
@@ -246,6 +270,9 @@ int init_nvidia_info(void) | |||
246 | (void*)(nvidia_mod->module_core), | 270 | (void*)(nvidia_mod->module_core), |
247 | (void*)(nvidia_mod->module_core) + nvidia_mod->core_size); | 271 | (void*)(nvidia_mod->module_core) + nvidia_mod->core_size); |
248 | init_nv_device_reg(); | 272 | init_nv_device_reg(); |
273 | |||
274 | register_module_notifier(&nvidia_going); | ||
275 | |||
249 | return(0); | 276 | return(0); |
250 | } | 277 | } |
251 | else | 278 | else |
@@ -262,6 +289,7 @@ void shutdown_nvidia_info(void) | |||
262 | nvidia_mod = NULL; | 289 | nvidia_mod = NULL; |
263 | mb(); | 290 | mb(); |
264 | 291 | ||
292 | unregister_module_notifier(&nvidia_going); | ||
265 | shutdown_nv_device_reg(); | 293 | shutdown_nv_device_reg(); |
266 | } | 294 | } |
267 | 295 | ||
@@ -314,9 +342,15 @@ typedef struct { | |||
314 | struct binheap owners; | 342 | struct binheap owners; |
315 | 343 | ||
316 | #ifdef CONFIG_LITMUS_SOFTIRQD | 344 | #ifdef CONFIG_LITMUS_SOFTIRQD |
317 | klmirqd_callback_t callback; | 345 | klmirqd_callback_t interrupt_callback; |
318 | struct task_struct* thread; | 346 | struct task_struct* interrupt_thread; |
319 | int ready:1; /* todo: make threads check for the ready flag */ | 347 | int interrupt_ready:1; /* todo: make threads check for the ready flag */ |
348 | |||
349 | #ifdef CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED | ||
350 | klmirqd_callback_t workq_callback; | ||
351 | struct task_struct* workq_thread; | ||
352 | int workq_ready:1; | ||
353 | #endif | ||
320 | #endif | 354 | #endif |
321 | 355 | ||
322 | #ifdef CONFIG_LITMUS_NV_KLMIRQD_DEBUG | 356 | #ifdef CONFIG_LITMUS_NV_KLMIRQD_DEBUG |
@@ -330,22 +364,40 @@ static nv_device_registry_t NV_DEVICE_REG[NV_DEVICE_NUM]; | |||
330 | 364 | ||
331 | 365 | ||
332 | #ifdef CONFIG_LITMUS_SOFTIRQD | 366 | #ifdef CONFIG_LITMUS_SOFTIRQD |
333 | static int nvidia_klmirqd_cb(void *arg) | 367 | static int nvidia_launch_interrupt_cb(void *arg) |
368 | { | ||
369 | unsigned long flags; | ||
370 | int reg_device_id = (int)(long long)(arg); | ||
371 | nv_device_registry_t *reg = &NV_DEVICE_REG[reg_device_id]; | ||
372 | |||
373 | TRACE("nvklmirqd callback for GPU %d\n", reg_device_id); | ||
374 | |||
375 | raw_spin_lock_irqsave(®->lock, flags); | ||
376 | reg->interrupt_thread = current; | ||
377 | reg->interrupt_ready = 1; | ||
378 | raw_spin_unlock_irqrestore(®->lock, flags); | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | #ifdef CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED | ||
384 | static int nvidia_launch_workq_cb(void *arg) | ||
334 | { | 385 | { |
335 | unsigned long flags; | 386 | unsigned long flags; |
336 | int reg_device_id = (int)(long long)(arg); | 387 | int reg_device_id = (int)(long long)(arg); |
337 | nv_device_registry_t *reg = &NV_DEVICE_REG[reg_device_id]; | 388 | nv_device_registry_t *reg = &NV_DEVICE_REG[reg_device_id]; |
338 | 389 | ||
339 | TRACE("nv klmirqd callback for GPU %d\n", reg_device_id); | 390 | TRACE("nvklmworkerd callback for GPU %d\n", reg_device_id); |
340 | 391 | ||
341 | raw_spin_lock_irqsave(®->lock, flags); | 392 | raw_spin_lock_irqsave(®->lock, flags); |
342 | reg->thread = current; | 393 | reg->workq_thread = current; |
343 | reg->ready = 1; | 394 | reg->workq_ready = 1; |
344 | raw_spin_unlock_irqrestore(®->lock, flags); | 395 | raw_spin_unlock_irqrestore(®->lock, flags); |
345 | 396 | ||
346 | return 0; | 397 | return 0; |
347 | } | 398 | } |
348 | #endif | 399 | #endif |
400 | #endif | ||
349 | 401 | ||
350 | #ifdef CONFIG_LITMUS_NV_KLMIRQD_DEBUG | 402 | #ifdef CONFIG_LITMUS_NV_KLMIRQD_DEBUG |
351 | struct nv_klmirqd_dbg_timer_struct | 403 | struct nv_klmirqd_dbg_timer_struct |
@@ -391,9 +443,9 @@ static enum hrtimer_restart nvklmirqd_timer_func(struct hrtimer *timer) | |||
391 | 443 | ||
392 | reg = &NV_DEVICE_REG[gpu]; | 444 | reg = &NV_DEVICE_REG[gpu]; |
393 | 445 | ||
394 | if (reg->thread && reg->ready) { | 446 | if (reg->interrupt_thread && reg->interrupt_ready) { |
395 | TRACE("Adding a tasklet for GPU %d\n", gpu); | 447 | TRACE("Adding a tasklet for GPU %d\n", gpu); |
396 | litmus_tasklet_schedule(®->nv_klmirqd_dbg_tasklet, reg->thread); | 448 | litmus_tasklet_schedule(®->nv_klmirqd_dbg_tasklet, reg->interrupt_thread); |
397 | } | 449 | } |
398 | else { | 450 | else { |
399 | TRACE("nv klmirqd is not ready!\n"); | 451 | TRACE("nv klmirqd is not ready!\n"); |
@@ -448,15 +500,25 @@ static int init_nv_device_reg(void) | |||
448 | { | 500 | { |
449 | int default_cpu = litmus->map_gpu_to_cpu(i); | 501 | int default_cpu = litmus->map_gpu_to_cpu(i); |
450 | 502 | ||
503 | /* spawn the interrupt thread */ | ||
451 | snprintf(name, MAX_KLMIRQD_NAME_LEN, "nvklmirqd%d", i); | 504 | snprintf(name, MAX_KLMIRQD_NAME_LEN, "nvklmirqd%d", i); |
452 | 505 | NV_DEVICE_REG[i].interrupt_callback.func = nvidia_launch_interrupt_cb; | |
453 | NV_DEVICE_REG[i].callback.func = nvidia_klmirqd_cb; | 506 | NV_DEVICE_REG[i].interrupt_callback.arg = (void*)(long long)(i); |
454 | NV_DEVICE_REG[i].callback.arg = (void*)(long long)(i); | ||
455 | mb(); | 507 | mb(); |
508 | if(launch_klmirqd_thread(name, default_cpu, &NV_DEVICE_REG[i].interrupt_callback) != 0) { | ||
509 | TRACE("Failed to create nvklmirqd thread for GPU %d\n", i); | ||
510 | } | ||
456 | 511 | ||
457 | if(launch_klmirqd_thread(name, default_cpu, &NV_DEVICE_REG[i].callback) != 0) { | 512 | #ifdef CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED |
458 | TRACE("Failed to create klmirqd thread for GPU %d\n", i); | 513 | /* spawn the workqueue thread */ |
514 | snprintf(name, MAX_KLMIRQD_NAME_LEN, "nvklmworker%d", i); | ||
515 | NV_DEVICE_REG[i].workq_callback.func = nvidia_launch_workq_cb; | ||
516 | NV_DEVICE_REG[i].workq_callback.arg = (void*)(long long)(i); | ||
517 | mb(); | ||
518 | if(launch_klmirqd_thread(name, default_cpu, &NV_DEVICE_REG[i].workq_callback) != 0) { | ||
519 | TRACE("Failed to create nvklmworkqd thread for GPU %d\n", i); | ||
459 | } | 520 | } |
521 | #endif | ||
460 | } | 522 | } |
461 | #endif | 523 | #endif |
462 | } | 524 | } |
@@ -479,6 +541,7 @@ static int shutdown_nv_device_reg(void) | |||
479 | 541 | ||
480 | #ifdef CONFIG_LITMUS_SOFTIRQD | 542 | #ifdef CONFIG_LITMUS_SOFTIRQD |
481 | { | 543 | { |
544 | unsigned long flags; | ||
482 | int i; | 545 | int i; |
483 | nv_device_registry_t *reg; | 546 | nv_device_registry_t *reg; |
484 | 547 | ||
@@ -488,12 +551,36 @@ static int shutdown_nv_device_reg(void) | |||
488 | 551 | ||
489 | reg = &NV_DEVICE_REG[i]; | 552 | reg = &NV_DEVICE_REG[i]; |
490 | 553 | ||
491 | if (reg->thread && reg->ready) { | 554 | if ((reg->interrupt_thread && reg->interrupt_ready) |
492 | kill_klmirqd_thread(reg->thread); | 555 | #ifdef CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED |
493 | 556 | || (reg->workq_thread && reg->workq_ready) | |
494 | /* assume that all goes according to plan... */ | 557 | #endif |
495 | reg->thread = NULL; | 558 | ) |
496 | reg->ready = 0; | 559 | { |
560 | raw_spin_lock_irqsave(®->lock, flags); | ||
561 | |||
562 | if (reg->interrupt_thread && reg->interrupt_ready) { | ||
563 | struct task_struct* th = reg->interrupt_thread; | ||
564 | reg->interrupt_thread = NULL; | ||
565 | mb(); | ||
566 | reg->interrupt_ready = 0; | ||
567 | mb(); | ||
568 | |||
569 | kill_klmirqd_thread(th); | ||
570 | } | ||
571 | |||
572 | #ifdef CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED | ||
573 | if (reg->workq_thread && reg->workq_ready) { | ||
574 | struct task_struct* th = reg->workq_thread; | ||
575 | reg->workq_thread = NULL; | ||
576 | mb(); | ||
577 | reg->workq_ready = 0; | ||
578 | mb(); | ||
579 | |||
580 | kill_klmirqd_thread(th); | ||
581 | } | ||
582 | #endif | ||
583 | raw_spin_unlock_irqrestore(®->lock, flags); | ||
497 | } | 584 | } |
498 | 585 | ||
499 | while (!binheap_empty(®->owners)) { | 586 | while (!binheap_empty(®->owners)) { |
@@ -528,29 +615,118 @@ struct task_struct* get_nv_max_device_owner(u32 target_device_id) | |||
528 | return(owner); | 615 | return(owner); |
529 | } | 616 | } |
530 | 617 | ||
618 | |||
531 | #ifdef CONFIG_LITMUS_SOFTIRQD | 619 | #ifdef CONFIG_LITMUS_SOFTIRQD |
532 | struct task_struct* get_nv_klmirqd_thread(u32 target_device_id) | 620 | |
621 | typedef enum { | ||
622 | INTERRUPT_TH, | ||
623 | WORKQ_TH | ||
624 | } nvklmtype_t; | ||
625 | |||
626 | static struct task_struct* __get_klm_thread(nv_device_registry_t* reg, nvklmtype_t type) | ||
533 | { | 627 | { |
534 | struct task_struct *klmirqd = NULL; | 628 | struct task_struct *klmirqd = NULL; |
535 | nv_device_registry_t *reg; | 629 | |
630 | switch(type) | ||
631 | { | ||
632 | case INTERRUPT_TH: | ||
633 | #ifdef CONFIG_LITMUS_NVIDIA_WORKQ_ON | ||
634 | case WORKQ_TH: | ||
635 | #endif | ||
636 | if(likely(reg->interrupt_ready)) | ||
637 | klmirqd = reg->interrupt_thread; | ||
638 | break; | ||
639 | #ifdef CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED | ||
640 | case WORKQ_TH: | ||
641 | if(likely(reg->workq_ready)) | ||
642 | klmirqd = reg->workq_thread; | ||
643 | break; | ||
644 | #endif | ||
645 | } | ||
536 | 646 | ||
537 | BUG_ON(target_device_id >= NV_DEVICE_NUM); | 647 | return klmirqd; |
648 | } | ||
538 | 649 | ||
539 | reg = &NV_DEVICE_REG[target_device_id]; | 650 | static struct task_struct* __get_and_lock_klm_thread(nv_device_registry_t* reg, unsigned long* flags, nvklmtype_t type) |
651 | { | ||
652 | struct task_struct *klmirqd; | ||
653 | |||
654 | raw_spin_lock_irqsave(®->lock, *flags); | ||
655 | klmirqd = __get_klm_thread(reg, type); | ||
540 | 656 | ||
541 | if(likely(reg->ready)) { | 657 | if (!klmirqd) { |
542 | klmirqd = reg->thread; | 658 | /* unlock if thread does not exist or is not ready */ |
659 | raw_spin_unlock_irqrestore(®->lock, *flags); | ||
543 | } | 660 | } |
544 | 661 | ||
545 | return klmirqd; | 662 | return klmirqd; |
546 | } | 663 | } |
547 | #endif | ||
548 | 664 | ||
665 | static void __unlock_klm_thread(nv_device_registry_t* reg, unsigned long* flags, nvklmtype_t type) | ||
666 | { | ||
667 | /* workq and interrupts share a lock per GPU */ | ||
668 | raw_spin_unlock_irqrestore(®->lock, *flags); | ||
669 | } | ||
670 | |||
671 | struct task_struct* get_and_lock_nvklmirqd_thread(u32 target_device_id, unsigned long* flags) | ||
672 | { | ||
673 | nv_device_registry_t *reg; | ||
674 | BUG_ON(target_device_id >= NV_DEVICE_NUM); | ||
675 | reg = &NV_DEVICE_REG[target_device_id]; | ||
676 | return __get_and_lock_klm_thread(reg, flags, INTERRUPT_TH); | ||
677 | } | ||
678 | |||
679 | void unlock_nvklmirqd_thread(u32 target_device_id, unsigned long* flags) | ||
680 | { | ||
681 | nv_device_registry_t *reg; | ||
682 | BUG_ON(target_device_id >= NV_DEVICE_NUM); | ||
683 | reg = &NV_DEVICE_REG[target_device_id]; | ||
684 | __unlock_klm_thread(reg, flags, INTERRUPT_TH); | ||
685 | } | ||
549 | 686 | ||
687 | struct task_struct* get_nvklmirqd_thread(u32 target_device_id) | ||
688 | { | ||
689 | /* should this function be allowed? who will use klmirqd thread without thread safety? */ | ||
690 | unsigned long flags; | ||
691 | struct task_struct *klmirqd; | ||
692 | klmirqd = get_and_lock_nvklmirqd_thread(target_device_id, &flags); | ||
693 | if(klmirqd) | ||
694 | unlock_nvklmirqd_thread(target_device_id, &flags); | ||
695 | return klmirqd; | ||
696 | } | ||
550 | 697 | ||
698 | #if defined(CONFIG_LITMUS_NVIDIA_WORKQ_ON) || defined(CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED) | ||
699 | |||
700 | struct task_struct* get_and_lock_nvklmworkqd_thread(u32 target_device_id, unsigned long* flags) | ||
701 | { | ||
702 | nv_device_registry_t *reg; | ||
703 | BUG_ON(target_device_id >= NV_DEVICE_NUM); | ||
704 | reg = &NV_DEVICE_REG[target_device_id]; | ||
705 | return __get_and_lock_klm_thread(reg, flags, WORKQ_TH); | ||
706 | } | ||
707 | |||
708 | void unlock_nvklmworkqd_thread(u32 target_device_id, unsigned long* flags) | ||
709 | { | ||
710 | nv_device_registry_t *reg; | ||
711 | BUG_ON(target_device_id >= NV_DEVICE_NUM); | ||
712 | reg = &NV_DEVICE_REG[target_device_id]; | ||
713 | __unlock_klm_thread(reg, flags, WORKQ_TH); | ||
714 | } | ||
715 | |||
716 | |||
717 | struct task_struct* get_nvklmworkqd_thread(u32 target_device_id) | ||
718 | { | ||
719 | /* should this function be allowed? who will use klmirqd thread without thread safety? */ | ||
720 | unsigned long flags; | ||
721 | struct task_struct *klmirqd; | ||
722 | klmirqd = get_and_lock_nvklmworkqd_thread(target_device_id, &flags); | ||
723 | if(klmirqd) | ||
724 | unlock_nvklmworkqd_thread(target_device_id, &flags); | ||
725 | return klmirqd; | ||
726 | } | ||
727 | #endif // end WORKQs | ||
551 | 728 | ||
552 | 729 | ||
553 | #ifdef CONFIG_LITMUS_SOFTIRQD | ||
554 | static int gpu_klmirqd_increase_priority(struct task_struct *klmirqd, struct task_struct *hp) | 730 | static int gpu_klmirqd_increase_priority(struct task_struct *klmirqd, struct task_struct *hp) |
555 | { | 731 | { |
556 | int retval = 0; | 732 | int retval = 0; |
@@ -582,7 +758,7 @@ static int gpu_klmirqd_decrease_priority(struct task_struct *klmirqd, struct tas | |||
582 | 758 | ||
583 | return retval; | 759 | return retval; |
584 | } | 760 | } |
585 | #endif | 761 | #endif // end CONFIG_LITMUS_SOFTIRQD |
586 | 762 | ||
587 | 763 | ||
588 | 764 | ||
@@ -624,13 +800,27 @@ long enable_gpu_owner(struct task_struct *t) | |||
624 | struct task_struct, rt_param); | 800 | struct task_struct, rt_param); |
625 | 801 | ||
626 | if (hp == t) { | 802 | if (hp == t) { |
803 | int interrupt_success; | ||
804 | |||
627 | /* we're the new hp */ | 805 | /* we're the new hp */ |
628 | TRACE_CUR("%s/%d (eff_prio = %s/%d) is new hp on GPU %d.\n", | 806 | TRACE_CUR("%s/%d (eff_prio = %s/%d) is new hp on GPU %d.\n", |
629 | t->comm, t->pid, | 807 | t->comm, t->pid, |
630 | effective_priority(t)->comm, effective_priority(t)->pid, | 808 | effective_priority(t)->comm, effective_priority(t)->pid, |
631 | gpu); | 809 | gpu); |
632 | 810 | ||
633 | retval = gpu_klmirqd_increase_priority(reg->thread, effective_priority(t)); | 811 | interrupt_success = gpu_klmirqd_increase_priority(reg->interrupt_thread, effective_priority(t)); |
812 | |||
813 | #ifdef CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED | ||
814 | { | ||
815 | int workq_success = gpu_klmirqd_increase_priority(reg->workq_thread, effective_priority(t)); | ||
816 | if(interrupt_success != 1 || workq_success != 1) | ||
817 | retval = (interrupt_success != 1) ? interrupt_success : workq_success; | ||
818 | else | ||
819 | retval = 1; | ||
820 | } | ||
821 | #else | ||
822 | retval = interrupt_success; | ||
823 | #endif | ||
634 | } | 824 | } |
635 | #endif | 825 | #endif |
636 | 826 | ||
@@ -682,6 +872,9 @@ long disable_gpu_owner(struct task_struct *t) | |||
682 | } | 872 | } |
683 | 873 | ||
684 | if (hp == t && new_hp != t) { | 874 | if (hp == t && new_hp != t) { |
875 | int interrupt_success; | ||
876 | #ifdef CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED | ||
877 | #endif | ||
685 | struct task_struct *to_inh = (new_hp) ? effective_priority(new_hp) : NULL; | 878 | struct task_struct *to_inh = (new_hp) ? effective_priority(new_hp) : NULL; |
686 | 879 | ||
687 | TRACE_CUR("%s/%d is no longer hp on GPU %d; new hp = %s/%d (eff_prio = %s/%d).\n", | 880 | TRACE_CUR("%s/%d is no longer hp on GPU %d; new hp = %s/%d (eff_prio = %s/%d).\n", |
@@ -692,7 +885,19 @@ long disable_gpu_owner(struct task_struct *t) | |||
692 | (to_inh) ? to_inh->comm : "null", | 885 | (to_inh) ? to_inh->comm : "null", |
693 | (to_inh) ? to_inh->pid : 0); | 886 | (to_inh) ? to_inh->pid : 0); |
694 | 887 | ||
695 | retval = gpu_klmirqd_decrease_priority(reg->thread, to_inh); | 888 | interrupt_success = gpu_klmirqd_decrease_priority(reg->interrupt_thread, to_inh); |
889 | |||
890 | #ifdef CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED | ||
891 | { | ||
892 | int workq_success = gpu_klmirqd_decrease_priority(reg->workq_thread, to_inh); | ||
893 | if(interrupt_success != 1 || workq_success != 1) | ||
894 | retval = (interrupt_success != 1) ? interrupt_success : workq_success; | ||
895 | else | ||
896 | retval = 1; | ||
897 | } | ||
898 | #else | ||
899 | retval = interrupt_success; | ||
900 | #endif | ||
696 | } | 901 | } |
697 | #else | 902 | #else |
698 | binheap_delete(&tsk_rt(t)->gpu_owner_node, ®->owners); | 903 | binheap_delete(&tsk_rt(t)->gpu_owner_node, ®->owners); |
@@ -758,13 +963,28 @@ int gpu_owner_increase_priority(struct task_struct *t) | |||
758 | 963 | ||
759 | /* check if the eff. prio. of hp has changed */ | 964 | /* check if the eff. prio. of hp has changed */ |
760 | if (increase_klmirqd || (effective_priority(hp) != hp_eff)) { | 965 | if (increase_klmirqd || (effective_priority(hp) != hp_eff)) { |
966 | int interrupt_success; | ||
967 | |||
761 | hp_eff = effective_priority(hp); | 968 | hp_eff = effective_priority(hp); |
762 | TRACE_CUR("%s/%d (eff_prio = %s/%d) is new hp on GPU %d.\n", | 969 | TRACE_CUR("%s/%d (eff_prio = %s/%d) is new hp on GPU %d.\n", |
763 | t->comm, t->pid, | 970 | t->comm, t->pid, |
764 | hp_eff->comm, hp_eff->pid, | 971 | hp_eff->comm, hp_eff->pid, |
765 | gpu); | 972 | gpu); |
766 | 973 | ||
767 | retval = gpu_klmirqd_increase_priority(reg->thread, hp_eff); | 974 | interrupt_success = gpu_klmirqd_increase_priority(reg->interrupt_thread, hp_eff); |
975 | |||
976 | #ifdef CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED | ||
977 | { | ||
978 | int workq_success = gpu_klmirqd_increase_priority(reg->workq_thread, hp_eff); | ||
979 | if(interrupt_success != 1 || workq_success != 1) | ||
980 | retval = (interrupt_success != 1) ? interrupt_success : workq_success; | ||
981 | else | ||
982 | retval = 1; | ||
983 | } | ||
984 | #else | ||
985 | retval = interrupt_success; | ||
986 | #endif | ||
987 | |||
768 | } | 988 | } |
769 | #endif | 989 | #endif |
770 | 990 | ||
@@ -810,9 +1030,23 @@ int gpu_owner_decrease_priority(struct task_struct *t) | |||
810 | struct task_struct, rt_param); | 1030 | struct task_struct, rt_param); |
811 | /* if the new_hp is still t, or if the effective priority has changed */ | 1031 | /* if the new_hp is still t, or if the effective priority has changed */ |
812 | if ((new_hp == t) || (effective_priority(new_hp) != hp_eff)) { | 1032 | if ((new_hp == t) || (effective_priority(new_hp) != hp_eff)) { |
1033 | int interrupt_success; | ||
1034 | |||
813 | hp_eff = effective_priority(new_hp); | 1035 | hp_eff = effective_priority(new_hp); |
814 | TRACE_CUR("%s/%d is no longer hp on GPU %d.\n", t->comm, t->pid, gpu); | 1036 | TRACE_CUR("%s/%d is no longer hp on GPU %d.\n", t->comm, t->pid, gpu); |
815 | retval = gpu_klmirqd_decrease_priority(reg->thread, hp_eff); | 1037 | interrupt_success = gpu_klmirqd_decrease_priority(reg->interrupt_thread, hp_eff); |
1038 | |||
1039 | #ifdef CONFIG_LITMUS_NVIDIA_WORKQ_ON_DEDICATED | ||
1040 | { | ||
1041 | int workq_success = gpu_klmirqd_decrease_priority(reg->workq_thread, hp_eff); | ||
1042 | if(interrupt_success != 1 || workq_success != 1) | ||
1043 | retval = (interrupt_success != 1) ? interrupt_success : workq_success; | ||
1044 | else | ||
1045 | retval = 1; | ||
1046 | } | ||
1047 | #else | ||
1048 | retval = interrupt_success; | ||
1049 | #endif | ||
816 | } | 1050 | } |
817 | } | 1051 | } |
818 | #endif | 1052 | #endif |
diff --git a/litmus/sched_cedf.c b/litmus/sched_cedf.c index df931de13e16..e2737bafa9b8 100644 --- a/litmus/sched_cedf.c +++ b/litmus/sched_cedf.c | |||
@@ -1701,10 +1701,6 @@ static void cleanup_cedf(void) | |||
1701 | { | 1701 | { |
1702 | int i; | 1702 | int i; |
1703 | 1703 | ||
1704 | #ifdef CONFIG_LITMUS_NVIDIA | ||
1705 | shutdown_nvidia_info(); | ||
1706 | #endif | ||
1707 | |||
1708 | if (clusters_allocated) { | 1704 | if (clusters_allocated) { |
1709 | for (i = 0; i < num_clusters; i++) { | 1705 | for (i = 0; i < num_clusters; i++) { |
1710 | kfree(cedf[i].cpus); | 1706 | kfree(cedf[i].cpus); |
diff --git a/litmus/sched_task_trace.c b/litmus/sched_task_trace.c index 2583ee2bb437..d1df0127cfa4 100644 --- a/litmus/sched_task_trace.c +++ b/litmus/sched_task_trace.c | |||
@@ -349,13 +349,15 @@ EXPORT_SYMBOL(do_sched_trace_tasklet_end); | |||
349 | 349 | ||
350 | 350 | ||
351 | feather_callback void do_sched_trace_work_release(unsigned long id, | 351 | feather_callback void do_sched_trace_work_release(unsigned long id, |
352 | unsigned long _owner) | 352 | unsigned long _owner, |
353 | unsigned long _device) | ||
353 | { | 354 | { |
354 | struct task_struct *t = (struct task_struct*) _owner; | 355 | struct task_struct *t = (struct task_struct*) _owner; |
355 | struct st_event_record *rec = get_record(ST_WORK_RELEASE, t); | 356 | struct st_event_record *rec = get_record(ST_WORK_RELEASE, t); |
356 | 357 | ||
357 | if (rec) { | 358 | if (rec) { |
358 | rec->data.work_release.when = now(); | 359 | rec->data.work_release.when = now(); |
360 | rec->data.work_release.device = _device; | ||
359 | put_record(rec); | 361 | put_record(rec); |
360 | } | 362 | } |
361 | } | 363 | } |