---
 include/linux/sched.h       |    2 +
 include/linux/workqueue.h   |    3 +-
 kernel/trace/latency_hist.c |   16 +++++++++---
 kernel/workqueue.c          |   55 ++++++++++++++++++++++++++++++++------------
 4 files changed, 57 insertions(+), 19 deletions(-)

Index: linux-5.15.71-rt51-r3s4/include/linux/sched.h
===================================================================
@ linux-5.15.71-rt51-r3s4/include/linux/sched.h:71 @ struct signal_struct;
 struct task_delay_info;
 struct task_group;
 
+#define MAXFULLTASKNAME 64
+
 /*
  * Task state bitmask. NOTE! These bits are also
  * encoded in fs/proc/array.c: get_task_state().
Index: linux-5.15.71-rt51-r3s4/include/linux/workqueue.h
===================================================================
--- linux-5.15.71-rt51-r3s4.orig/include/linux/workqueue.h
+++ linux-5.15.71-rt51-r3s4/include/linux/workqueue.h
@ linux-5.15.71-rt51-r3s4/include/linux/sched.h:94 @ enum {
 	WORK_BUSY_RUNNING	= 1 << 1,
 
 	/* maximum string length for set_worker_desc() */
-	WORKER_DESC_LEN		= 24,
+	WORKER_DESC_LEN		= 48,
 };
 
 struct work_struct {
@ linux-5.15.71-rt51-r3s4/include/linux/sched.h:474 @ extern __printf(1, 2) void set_worker_de
 extern void print_worker_info(const char *log_lvl, struct task_struct *task);
 extern void show_workqueue_state(void);
 extern void wq_worker_comm(char *buf, size_t size, struct task_struct *task);
+extern void wq_worker_comm_nolock(char *buf, size_t size, struct task_struct *task);
 
 /**
  * queue_work - queue work on a workqueue
Index: linux-5.15.71-rt51-r3s4/kernel/trace/latency_hist.c
===================================================================
--- linux-5.15.71-rt51-r3s4.orig/kernel/trace/latency_hist.c
+++ linux-5.15.71-rt51-r3s4/kernel/trace/latency_hist.c
@ linux-5.15.71-rt51-r3s4/include/linux/sched.h:116 @ static struct enable_data preemptirqsoff
 	defined(CONFIG_MISSED_TIMER_OFFSETS_HIST)
 struct maxlatproc_data {
 	char comm[FIELD_SIZEOF(struct task_struct, comm)];
-	char current_comm[FIELD_SIZEOF(struct task_struct, comm)];
+	char current_comm[MAXFULLTASKNAME];
 	int pid;
 	int current_pid;
 	int prio;
@ linux-5.15.71-rt51-r3s4/include/linux/sched.h:202 @ static struct enable_data timerwakeupswi
 static DEFINE_PER_CPU(struct maxlatproc_data, timerwakeupswitch_maxlatproc);
 #endif
 
+static void fulltaskname(struct task_struct *p, char *tcomm, int size)
+{
+	if (p->flags & PF_WQ_WORKER)
+		wq_worker_comm_nolock(tcomm, size, p);
+	else
+		strscpy_pad(tcomm, p->comm, size);
+}
+
 void notrace latency_hist(int latency_type, int cpu, long latency,
 			  unsigned long timer_offset, long wakeup_latency,
 			  u64 stop, struct task_struct *p, int nr)
@ linux-5.15.71-rt51-r3s4/include/linux/sched.h:309 @ void notrace latency_hist(int latency_ty
 		    latency_type == TIMERWAKEUPSWITCH_LATENCY) {
 			if (latency_type == SWITCHTIME ||
 			    latency_type == TIMERWAKEUPSWITCH_LATENCY) {
-				strncpy(mp->current_comm, p->comm,
+				fulltaskname(p, mp->current_comm,
 				    sizeof(mp->current_comm));
 				strncpy(mp->comm, current->comm,
 				    sizeof(mp->comm));
@ linux-5.15.71-rt51-r3s4/include/linux/sched.h:319 @ void notrace latency_hist(int latency_ty
 				mp->prio = current->prio;
 			} else {
 				strncpy(mp->comm, p->comm, sizeof(mp->comm));
-				strncpy(mp->current_comm, current->comm,
+				fulltaskname(current, mp->current_comm,
 				    sizeof(mp->current_comm));
 				mp->pid = task_pid_nr(p);
 				mp->current_pid = task_pid_nr(current);
@ linux-5.15.71-rt51-r3s4/include/linux/sched.h:604 @ show_maxlatproc(struct file *file, char
 {
 	int r;
 	struct maxlatproc_data *mp = file->private_data;
-	int strmaxlen = (TASK_COMM_LEN * 2) + 32 + (8 * 8);
+	int strmaxlen = 256;
 	unsigned long long t;
 	unsigned long usecs, secs;
 	char *buf;
Index: linux-5.15.71-rt51-r3s4/kernel/workqueue.c
===================================================================
--- linux-5.15.71-rt51-r3s4.orig/kernel/workqueue.c
+++ linux-5.15.71-rt51-r3s4/kernel/workqueue.c
@ linux-5.15.71-rt51-r3s4/include/linux/sched.h:109 @ enum {
 	RESCUER_NICE_LEVEL	= MIN_NICE,
 	HIGHPRI_NICE_LEVEL	= MIN_NICE,
 
-	WQ_NAME_LEN		= 24,
+	WQ_NAME_LEN		= 48,
 };
 
 /*
@ linux-5.15.71-rt51-r3s4/include/linux/sched.h:4901 @ void show_workqueue_state(void)
 	rcu_read_unlock();
 }
 
+static void wq_worker_print(char *buf, size_t size, int off, struct worker *worker)
+{
+	/*
+	 * ->desc tracks information (wq name or
+	 * set_worker_desc()) for the latest execution.  If
+	 * current, prepend '+' and show function, otherwise '-'.
+	 */
+	if (worker->desc[0] != '\0') {
+		if (worker->current_work)
+			scnprintf(buf + off, size - off,
+				  "+%s@%ps", worker->desc,
+				  worker->current_func);
+		else
+			scnprintf(buf + off, size - off, "-%s",
+				  worker->desc);
+	}
+}
+
 /* used to show worker information through /proc/PID/{comm,stat,status} */
 void wq_worker_comm(char *buf, size_t size, struct task_struct *task)
 {
@ linux-5.15.71-rt51-r3s4/include/linux/sched.h:4929 @ void wq_worker_comm(char *buf, size_t si
 	if (off < 0)
 		return;
 
+#ifndef CONFIG_PREEMPT_RT
 	/* stabilize PF_WQ_WORKER and worker pool association */
 	mutex_lock(&wq_pool_attach_mutex);
 
@ linux-5.15.71-rt51-r3s4/include/linux/sched.h:4939 @ void wq_worker_comm(char *buf, size_t si
 
 		if (pool) {
 			raw_spin_lock_irq(&pool->lock);
-			/*
-			 * ->desc tracks information (wq name or
-			 * set_worker_desc()) for the latest execution.  If
-			 * current, prepend '+', otherwise '-'.
-			 */
-			if (worker->desc[0] != '\0') {
-				if (worker->current_work)
-					scnprintf(buf + off, size - off, "+%s",
-						  worker->desc);
-				else
-					scnprintf(buf + off, size - off, "-%s",
-						  worker->desc);
-			}
+			wq_worker_print(buf, size, off, worker);
 			raw_spin_unlock_irq(&pool->lock);
 		}
 	}
 
 	mutex_unlock(&wq_pool_attach_mutex);
+#endif
+}
+
+/* used to get worker information for latency histograms */
+void wq_worker_comm_nolock(char *buf, size_t size, struct task_struct *task)
+{
+	int off;
+
+	/* always show the actual comm */
+	off = strscpy(buf, task->comm, size);
+	if (off < 0)
+		return;
+
+	if (task->flags & PF_WQ_WORKER) {
+		struct worker *worker = kthread_data(task);
+		struct worker_pool *pool = worker->pool;
+
+		if (pool)
+			wq_worker_print(buf, size, off, worker);
+	}
 }
 
 #ifdef CONFIG_SMP