Fix for rt-patch.sh and realtime patches on Xavier

This changes two things. One is that the rt-patch.sh script itself was not modifying tegra_defconfig. Another was the script needed to also disabled the CPU idle on T19X platform, not just T18X. Lastly, the defconfig will have cpufreq compiled in and so cpufreq_times.c was missing conversions to raw spinlocks on the regular spinlocks in use. Without these changes, my experience was a board flashed with 32.1 and rt-patch.sh apply-patches in use would get stuck on boot in various kernel BUG calls.

diff --git a/kernel/kernel-4.9/drivers/cpufreq/cpufreq_times.c b/kernel/kernel-4.9/drivers/cpufreq/cpufreq_times.c
index 0e8754b6..d4f6504a 100644
--- a/kernel/kernel-4.9/drivers/cpufreq/cpufreq_times.c
+++ b/kernel/kernel-4.9/drivers/cpufreq/cpufreq_times.c
@@ -29,8 +29,8 @@
 
 static DECLARE_HASHTABLE(uid_hash_table, UID_HASH_BITS);
 
-static DEFINE_SPINLOCK(task_time_in_state_lock); /* task->time_in_state */
-static DEFINE_SPINLOCK(uid_lock); /* uid_hash_table */
+static DEFINE_RAW_SPINLOCK(task_time_in_state_lock); /* task->time_in_state */
+static DEFINE_RAW_SPINLOCK(uid_lock); /* uid_hash_table */
 
 struct uid_entry {
 	uid_t uid;
@@ -236,9 +236,9 @@ void cpufreq_task_times_init(struct task_struct *p)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&task_time_in_state_lock, flags);
+	raw_spin_lock_irqsave(&task_time_in_state_lock, flags);
 	p->time_in_state = NULL;
-	spin_unlock_irqrestore(&task_time_in_state_lock, flags);
+	raw_spin_unlock_irqrestore(&task_time_in_state_lock, flags);
 	p->max_state = 0;
 }
 
@@ -253,9 +253,9 @@ void cpufreq_task_times_alloc(struct task_struct *p)
 	if (!temp)
 		return;
 
-	spin_lock_irqsave(&task_time_in_state_lock, flags);
+	raw_spin_lock_irqsave(&task_time_in_state_lock, flags);
 	p->time_in_state = temp;
-	spin_unlock_irqrestore(&task_time_in_state_lock, flags);
+	raw_spin_unlock_irqrestore(&task_time_in_state_lock, flags);
 	p->max_state = max_state;
 }
 
@@ -283,10 +283,10 @@ void cpufreq_task_times_exit(struct task_struct *p)
 	if (!p->time_in_state)
 		return;
 
-	spin_lock_irqsave(&task_time_in_state_lock, flags);
+	raw_spin_lock_irqsave(&task_time_in_state_lock, flags);
 	temp = p->time_in_state;
 	p->time_in_state = NULL;
-	spin_unlock_irqrestore(&task_time_in_state_lock, flags);
+	raw_spin_unlock_irqrestore(&task_time_in_state_lock, flags);
 	kfree(temp);
 }
 
@@ -299,7 +299,7 @@ int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns,
 	struct cpu_freqs *freqs;
 	struct cpu_freqs *last_freqs = NULL;
 
-	spin_lock_irqsave(&task_time_in_state_lock, flags);
+	raw_spin_lock_irqsave(&task_time_in_state_lock, flags);
 	for_each_possible_cpu(cpu) {
 		freqs = all_freqs[cpu];
 		if (!freqs || freqs == last_freqs)
@@ -318,7 +318,7 @@ int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns,
 				   (unsigned long)cputime_to_clock_t(cputime));
 		}
 	}
-	spin_unlock_irqrestore(&task_time_in_state_lock, flags);
+	raw_spin_unlock_irqrestore(&task_time_in_state_lock, flags);
 	return 0;
 }
 
@@ -335,17 +335,17 @@ void cpufreq_acct_update_power(struct task_struct *p, cputime_t cputime)
 
 	state = freqs->offset + READ_ONCE(freqs->last_index);
 
-	spin_lock_irqsave(&task_time_in_state_lock, flags);
+	raw_spin_lock_irqsave(&task_time_in_state_lock, flags);
 	if ((state < p->max_state || !cpufreq_task_times_realloc_locked(p)) &&
 	    p->time_in_state)
 		p->time_in_state[state] += cputime;
-	spin_unlock_irqrestore(&task_time_in_state_lock, flags);
+	raw_spin_unlock_irqrestore(&task_time_in_state_lock, flags);
 
-	spin_lock_irqsave(&uid_lock, flags);
+	raw_spin_lock_irqsave(&uid_lock, flags);
 	uid_entry = find_or_register_uid_locked(uid);
 	if (uid_entry && state < uid_entry->max_state)
 		uid_entry->time_in_state[state] += cputime;
-	spin_unlock_irqrestore(&uid_lock, flags);
+	raw_spin_unlock_irqrestore(&uid_lock, flags);
 }
 
 void cpufreq_times_create_policy(struct cpufreq_policy *policy)
@@ -393,7 +393,7 @@ void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end)
 	struct hlist_node *tmp;
 	unsigned long flags;
 
-	spin_lock_irqsave(&uid_lock, flags);
+	raw_spin_lock_irqsave(&uid_lock, flags);
 
 	for (; uid_start <= uid_end; uid_start++) {
 		hash_for_each_possible_safe(uid_hash_table, uid_entry, tmp,
@@ -405,7 +405,7 @@ void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end)
 		}
 	}
 
-	spin_unlock_irqrestore(&uid_lock, flags);
+	raw_spin_unlock_irqrestore(&uid_lock, flags);
 }
 
 void cpufreq_times_record_transition(struct cpufreq_freqs *freq)
diff --git a/kernel/kernel-4.9/scripts/rt-patch.sh b/kernel/kernel-4.9/scripts/rt-patch.sh
index 6176eee2..daefe1c8 100755
--- a/kernel/kernel-4.9/scripts/rt-patch.sh
+++ b/kernel/kernel-4.9/scripts/rt-patch.sh
@@ -11,7 +11,7 @@
 any_failure=0
 apply_rt_patches()
 {
-	if [ -f ../arch/arm64/configs/.tmp.tegra_gnu_linux_defconfig ]; then
+	if [ -f ../arch/arm64/configs/.tmp.tegra_defconfig ]; then
 		echo "The PREEMPT RT patches are already applied to the kernel!"
 	else
 		file_list=`find ../rt-patches -name \*.patch -type f | sort`
@@ -20,27 +20,28 @@ apply_rt_patches()
 			patch -s -d .. -p1 < $p || any_failure=1
 		done
 		#make temporary copy of the defconfig file
-		cp ../arch/arm64/configs/tegra_gnu_linux_defconfig\
-			../arch/arm64/configs/.tmp.tegra_gnu_linux_defconfig
-		./config --file ../arch/arm64/configs/tegra_gnu_linux_defconfig\
+		cp ../arch/arm64/configs/tegra_defconfig\
+			../arch/arm64/configs/.tmp.tegra_defconfig
+		./config --file ../arch/arm64/configs/tegra_defconfig\
 			--enable PREEMPT_RT_FULL  --disable CPU_IDLE_TEGRA18X\
-			--disable CPU_FREQ_GOV_INTERACTIVE || any_failure=1
+                        --disable CPU_IDLE_TEGRA19X\
+                        --disable CPU_FREQ_GOV_INTERACTIVE || any_failure=1
 		echo "The PREEMPT RT patches have been successfully applied!"
 	fi
 }
 
 revert_rt_patches()
 {
-	if [ -f ../arch/arm64/configs/.tmp.tegra_gnu_linux_defconfig ]; then
+	if [ -f ../arch/arm64/configs/.tmp.tegra_defconfig ]; then
 		file_list=`find ../rt-patches -name \*.patch -type f | sort -r`
 		for p in $file_list; do
 			# set flag in case of failure and continue
 			patch -s -R -d .. -p1 < $p || any_failure=1
 		done
 		#  CPU_FREQ_GOV_INTERACTIVE need to keep disable for Automotive
-		cp ../arch/arm64/configs/.tmp.tegra_gnu_linux_defconfig\
-			../arch/arm64/configs/tegra_gnu_linux_defconfig
-		rm -rf ../arch/arm64/configs/.tmp.tegra_gnu_linux_defconfig
+		cp ../arch/arm64/configs/.tmp.tegra_defconfig\
+			../arch/arm64/configs/tegra_defconfig
+		rm -rf ../arch/arm64/configs/.tmp.tegra_defconfig
 		echo "The PREEMPT RT patches have been successfully reverted!"
 	else
 		echo "The PREEMPT RT patches are not applied to the kernel!"

jrestifo,

Do you mean there is compilation error after apply original script?

No, I mean that if you apply the patches in 4.2, you will end up with a non functioning kernel. The first issue is that the script doesn’t apply the patches to tegra_defconfig, which is what most people would expect. But the second issue is that for me, the patches did compile, but the kernel gets stuck in soft lockup because the defconfig has cpufreq, but cpufreq was using a regular spinlock, when it needed to be a raw spinlock to work with PREEMPT_RT.

Hi jrestifo

I’m having this same problem with the Jetson Nano and 4.2. I’m trying to compile a kernel with PREEMPT_RT patches, the kernel compiles without problem, but as you said, I get in a soft lockup at boot. I tried applying the changes you suggested (in cpufreq_times.c and rt-patch.sh) but in the Nano this solution is not working, I always get in a soft lockup at boot. What do you think can be the problem with the Nano?

Regards

Please try rel-32.2 from latest sdkmanager. This issue should be resolved. Thanks for your patience.

Hi WayneWWW

I just tried with 32.2 and the problem is the same. I am able to compile a kernel with the PREEMPT_RT patches and create an image for the Nano but I am not able to boot using that image.

ajcalderont,

Would you mind filing a new topic and share detailed method of setup and log on Nano forum board?

Hello,

I think PREEMPT_RT patch doesn’t run on NANO, such was the case on TX1 as well. Also, there’s no output on the serial console after it finds the kernel Image and the initrd.img files.

I may be wrong about it and will be very happy if there’s a way to get PREEMPT_RT kernels booted on TX1 and NANO.

P.S. Please let me know the new post that will be opened related to this topic.

which sequence of commands needs to be run for patch to get applied at Jetpack 4.2.1 ?

Hi WayneWWW,

Actually I posted this problem a couple of months ago in the Nano forum:
https://devtalk.nvidia.com/default/topic/1050012/jetson-nano/preempt-rt-patches-for-jetson-nano/post/5365110/#5365110

If you see my last comment, there is the method I followed using L4T 32.2

Best regards

Hi Andrey1984

In the kernel source files there is a script for applying the patches (kernel/kernel-4.9/scripts/rt-patch.sh), so the command you must execute is:

./rt-patch.sh apply-patches

I haven’t tried it on the Xavier, but you can see the whole process I did with the Nano here:
https://devtalk.nvidia.com/default/topic/1050012/jetson-nano/preempt-rt-patches-for-jetson-nano/post/5365110/#5365110

Just use the Xavier sources instead of the Nano sources and in the end you have to look how to flash the result to the Xavier.

Regards