3131
3232#define CSD_TYPE (_csd ) ((_csd)->node.u_flags & CSD_FLAG_TYPE_MASK)
3333
34- #ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
35- union cfd_seq_cnt {
36- u64 val ;
37- struct {
38- u64 src :16 ;
39- u64 dst :16 ;
40- #define CFD_SEQ_NOCPU 0xffff
41- u64 type :4 ;
42- #define CFD_SEQ_QUEUE 0
43- #define CFD_SEQ_IPI 1
44- #define CFD_SEQ_NOIPI 2
45- #define CFD_SEQ_PING 3
46- #define CFD_SEQ_PINGED 4
47- #define CFD_SEQ_HANDLE 5
48- #define CFD_SEQ_DEQUEUE 6
49- #define CFD_SEQ_IDLE 7
50- #define CFD_SEQ_GOTIPI 8
51- #define CFD_SEQ_HDLEND 9
52- u64 cnt :28 ;
53- } u ;
54- };
55-
56- static char * seq_type [] = {
57- [CFD_SEQ_QUEUE ] = "queue" ,
58- [CFD_SEQ_IPI ] = "ipi" ,
59- [CFD_SEQ_NOIPI ] = "noipi" ,
60- [CFD_SEQ_PING ] = "ping" ,
61- [CFD_SEQ_PINGED ] = "pinged" ,
62- [CFD_SEQ_HANDLE ] = "handle" ,
63- [CFD_SEQ_DEQUEUE ] = "dequeue (src CPU 0 == empty)" ,
64- [CFD_SEQ_IDLE ] = "idle" ,
65- [CFD_SEQ_GOTIPI ] = "gotipi" ,
66- [CFD_SEQ_HDLEND ] = "hdlend (src CPU 0 == early)" ,
67- };
68-
69- struct cfd_seq_local {
70- u64 ping ;
71- u64 pinged ;
72- u64 handle ;
73- u64 dequeue ;
74- u64 idle ;
75- u64 gotipi ;
76- u64 hdlend ;
77- };
78- #endif
79-
8034struct cfd_percpu {
8135 call_single_data_t csd ;
82- #ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
83- u64 seq_queue ;
84- u64 seq_ipi ;
85- u64 seq_noipi ;
86- #endif
8736};
8837
8938struct call_function_data {
@@ -159,18 +108,21 @@ void __init call_function_init(void)
159108#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
160109
161110static DEFINE_STATIC_KEY_MAYBE (CONFIG_CSD_LOCK_WAIT_DEBUG_DEFAULT , csdlock_debug_enabled ) ;
162- static DEFINE_STATIC_KEY_FALSE (csdlock_debug_extended );
163111
112+ /*
113+ * Parse the csdlock_debug= kernel boot parameter.
114+ *
115+ * If you need to restore the old "ext" value that once provided
116+ * additional debugging information, reapply the following commits:
117+ *
118+ * de7b09ef658d ("locking/csd_lock: Prepare more CSD lock debugging")
119+ * a5aabace5fb8 ("locking/csd_lock: Add more data to CSD lock debugging")
120+ */
164121static int __init csdlock_debug (char * str )
165122{
166123 unsigned int val = 0 ;
167124
168- if (str && !strcmp (str , "ext" )) {
169- val = 1 ;
170- static_branch_enable (& csdlock_debug_extended );
171- } else
172- get_option (& str , & val );
173-
125+ get_option (& str , & val );
174126 if (val )
175127 static_branch_enable (& csdlock_debug_enabled );
176128
@@ -181,36 +133,11 @@ __setup("csdlock_debug=", csdlock_debug);
181133static DEFINE_PER_CPU (call_single_data_t * , cur_csd ) ;
182134static DEFINE_PER_CPU (smp_call_func_t , cur_csd_func ) ;
183135static DEFINE_PER_CPU (void * , cur_csd_info ) ;
184- static DEFINE_PER_CPU (struct cfd_seq_local , cfd_seq_local ) ;
185136
186137static ulong csd_lock_timeout = 5000 ; /* CSD lock timeout in milliseconds. */
187138module_param (csd_lock_timeout , ulong , 0444 );
188139
189140static atomic_t csd_bug_count = ATOMIC_INIT (0 );
190- static u64 cfd_seq ;
191-
192- #define CFD_SEQ (s , d , t , c ) \
193- (union cfd_seq_cnt){ .u.src = s, .u.dst = d, .u.type = t, .u.cnt = c }
194-
195- static u64 cfd_seq_inc (unsigned int src , unsigned int dst , unsigned int type )
196- {
197- union cfd_seq_cnt new , old ;
198-
199- new = CFD_SEQ (src , dst , type , 0 );
200-
201- do {
202- old .val = READ_ONCE (cfd_seq );
203- new .u .cnt = old .u .cnt + 1 ;
204- } while (cmpxchg (& cfd_seq , old .val , new .val ) != old .val );
205-
206- return old .val ;
207- }
208-
209- #define cfd_seq_store (var , src , dst , type ) \
210- do { \
211- if (static_branch_unlikely(&csdlock_debug_extended)) \
212- var = cfd_seq_inc(src, dst, type); \
213- } while (0)
214141
215142/* Record current CSD work for current CPU, NULL to erase. */
216143static void __csd_lock_record (struct __call_single_data * csd )
@@ -244,80 +171,6 @@ static int csd_lock_wait_getcpu(struct __call_single_data *csd)
244171 return -1 ;
245172}
246173
247- static void cfd_seq_data_add (u64 val , unsigned int src , unsigned int dst ,
248- unsigned int type , union cfd_seq_cnt * data ,
249- unsigned int * n_data , unsigned int now )
250- {
251- union cfd_seq_cnt new [2 ];
252- unsigned int i , j , k ;
253-
254- new [0 ].val = val ;
255- new [1 ] = CFD_SEQ (src , dst , type , new [0 ].u .cnt + 1 );
256-
257- for (i = 0 ; i < 2 ; i ++ ) {
258- if (new [i ].u .cnt <= now )
259- new [i ].u .cnt |= 0x80000000U ;
260- for (j = 0 ; j < * n_data ; j ++ ) {
261- if (new [i ].u .cnt == data [j ].u .cnt ) {
262- /* Direct read value trumps generated one. */
263- if (i == 0 )
264- data [j ].val = new [i ].val ;
265- break ;
266- }
267- if (new [i ].u .cnt < data [j ].u .cnt ) {
268- for (k = * n_data ; k > j ; k -- )
269- data [k ].val = data [k - 1 ].val ;
270- data [j ].val = new [i ].val ;
271- (* n_data )++ ;
272- break ;
273- }
274- }
275- if (j == * n_data ) {
276- data [j ].val = new [i ].val ;
277- (* n_data )++ ;
278- }
279- }
280- }
281-
282- static const char * csd_lock_get_type (unsigned int type )
283- {
284- return (type >= ARRAY_SIZE (seq_type )) ? "?" : seq_type [type ];
285- }
286-
287- static void csd_lock_print_extended (struct __call_single_data * csd , int cpu )
288- {
289- struct cfd_seq_local * seq = & per_cpu (cfd_seq_local , cpu );
290- unsigned int srccpu = csd -> node .src ;
291- struct call_function_data * cfd = per_cpu_ptr (& cfd_data , srccpu );
292- struct cfd_percpu * pcpu = per_cpu_ptr (cfd -> pcpu , cpu );
293- unsigned int now ;
294- union cfd_seq_cnt data [2 * ARRAY_SIZE (seq_type )];
295- unsigned int n_data = 0 , i ;
296-
297- data [0 ].val = READ_ONCE (cfd_seq );
298- now = data [0 ].u .cnt ;
299-
300- cfd_seq_data_add (pcpu -> seq_queue , srccpu , cpu , CFD_SEQ_QUEUE , data , & n_data , now );
301- cfd_seq_data_add (pcpu -> seq_ipi , srccpu , cpu , CFD_SEQ_IPI , data , & n_data , now );
302- cfd_seq_data_add (pcpu -> seq_noipi , srccpu , cpu , CFD_SEQ_NOIPI , data , & n_data , now );
303-
304- cfd_seq_data_add (per_cpu (cfd_seq_local .ping , srccpu ), srccpu , CFD_SEQ_NOCPU , CFD_SEQ_PING , data , & n_data , now );
305- cfd_seq_data_add (per_cpu (cfd_seq_local .pinged , srccpu ), srccpu , CFD_SEQ_NOCPU , CFD_SEQ_PINGED , data , & n_data , now );
306-
307- cfd_seq_data_add (seq -> idle , CFD_SEQ_NOCPU , cpu , CFD_SEQ_IDLE , data , & n_data , now );
308- cfd_seq_data_add (seq -> gotipi , CFD_SEQ_NOCPU , cpu , CFD_SEQ_GOTIPI , data , & n_data , now );
309- cfd_seq_data_add (seq -> handle , CFD_SEQ_NOCPU , cpu , CFD_SEQ_HANDLE , data , & n_data , now );
310- cfd_seq_data_add (seq -> dequeue , CFD_SEQ_NOCPU , cpu , CFD_SEQ_DEQUEUE , data , & n_data , now );
311- cfd_seq_data_add (seq -> hdlend , CFD_SEQ_NOCPU , cpu , CFD_SEQ_HDLEND , data , & n_data , now );
312-
313- for (i = 0 ; i < n_data ; i ++ ) {
314- pr_alert ("\tcsd: cnt(%07x): %04x->%04x %s\n" ,
315- data [i ].u .cnt & ~0x80000000U , data [i ].u .src ,
316- data [i ].u .dst , csd_lock_get_type (data [i ].u .type ));
317- }
318- pr_alert ("\tcsd: cnt now: %07x\n" , now );
319- }
320-
321174/*
322175 * Complain if too much time spent waiting. Note that only
323176 * the CSD_TYPE_SYNC/ASYNC types provide the destination CPU,
@@ -368,8 +221,6 @@ static bool csd_lock_wait_toolong(struct __call_single_data *csd, u64 ts0, u64 *
368221 * bug_id , !cpu_cur_csd ? "unresponsive" : "handling this request" );
369222 }
370223 if (cpu >= 0 ) {
371- if (static_branch_unlikely (& csdlock_debug_extended ))
372- csd_lock_print_extended (csd , cpu );
373224 dump_cpu_task (cpu );
374225 if (!cpu_cur_csd ) {
375226 pr_alert ("csd: Re-sending CSD lock (#%d) IPI from CPU#%02d to CPU#%02d\n" , * bug_id , raw_smp_processor_id (), cpu );
@@ -412,27 +263,7 @@ static __always_inline void csd_lock_wait(struct __call_single_data *csd)
412263
413264 smp_cond_load_acquire (& csd -> node .u_flags , !(VAL & CSD_FLAG_LOCK ));
414265}
415-
416- static void __smp_call_single_queue_debug (int cpu , struct llist_node * node )
417- {
418- unsigned int this_cpu = smp_processor_id ();
419- struct cfd_seq_local * seq = this_cpu_ptr (& cfd_seq_local );
420- struct call_function_data * cfd = this_cpu_ptr (& cfd_data );
421- struct cfd_percpu * pcpu = per_cpu_ptr (cfd -> pcpu , cpu );
422-
423- cfd_seq_store (pcpu -> seq_queue , this_cpu , cpu , CFD_SEQ_QUEUE );
424- if (llist_add (node , & per_cpu (call_single_queue , cpu ))) {
425- cfd_seq_store (pcpu -> seq_ipi , this_cpu , cpu , CFD_SEQ_IPI );
426- cfd_seq_store (seq -> ping , this_cpu , cpu , CFD_SEQ_PING );
427- send_call_function_single_ipi (cpu );
428- cfd_seq_store (seq -> pinged , this_cpu , cpu , CFD_SEQ_PINGED );
429- } else {
430- cfd_seq_store (pcpu -> seq_noipi , this_cpu , cpu , CFD_SEQ_NOIPI );
431- }
432- }
433266#else
434- #define cfd_seq_store (var , src , dst , type )
435-
436267static void csd_lock_record (struct __call_single_data * csd )
437268{
438269}
@@ -470,19 +301,6 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(call_single_data_t, csd_data);
470301
471302void __smp_call_single_queue (int cpu , struct llist_node * node )
472303{
473- #ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
474- if (static_branch_unlikely (& csdlock_debug_extended )) {
475- unsigned int type ;
476-
477- type = CSD_TYPE (container_of (node , call_single_data_t ,
478- node .llist ));
479- if (type == CSD_TYPE_SYNC || type == CSD_TYPE_ASYNC ) {
480- __smp_call_single_queue_debug (cpu , node );
481- return ;
482- }
483- }
484- #endif
485-
486304 /*
487305 * The list addition should be visible before sending the IPI
488306 * handler locks the list to pull the entry off it because of
@@ -541,8 +359,6 @@ static int generic_exec_single(int cpu, struct __call_single_data *csd)
541359 */
542360void generic_smp_call_function_single_interrupt (void )
543361{
544- cfd_seq_store (this_cpu_ptr (& cfd_seq_local )-> gotipi , CFD_SEQ_NOCPU ,
545- smp_processor_id (), CFD_SEQ_GOTIPI );
546362 __flush_smp_call_function_queue (true);
547363}
548364
@@ -570,13 +386,7 @@ static void __flush_smp_call_function_queue(bool warn_cpu_offline)
570386 lockdep_assert_irqs_disabled ();
571387
572388 head = this_cpu_ptr (& call_single_queue );
573- cfd_seq_store (this_cpu_ptr (& cfd_seq_local )-> handle , CFD_SEQ_NOCPU ,
574- smp_processor_id (), CFD_SEQ_HANDLE );
575389 entry = llist_del_all (head );
576- cfd_seq_store (this_cpu_ptr (& cfd_seq_local )-> dequeue ,
577- /* Special meaning of source cpu: 0 == queue empty */
578- entry ? CFD_SEQ_NOCPU : 0 ,
579- smp_processor_id (), CFD_SEQ_DEQUEUE );
580390 entry = llist_reverse_order (entry );
581391
582392 /* There shouldn't be any pending callbacks on an offline CPU. */
@@ -635,12 +445,8 @@ static void __flush_smp_call_function_queue(bool warn_cpu_offline)
635445 }
636446 }
637447
638- if (!entry ) {
639- cfd_seq_store (this_cpu_ptr (& cfd_seq_local )-> hdlend ,
640- 0 , smp_processor_id (),
641- CFD_SEQ_HDLEND );
448+ if (!entry )
642449 return ;
643- }
644450
645451 /*
646452 * Second; run all !SYNC callbacks.
@@ -678,9 +484,6 @@ static void __flush_smp_call_function_queue(bool warn_cpu_offline)
678484 */
679485 if (entry )
680486 sched_ttwu_pending (entry );
681-
682- cfd_seq_store (this_cpu_ptr (& cfd_seq_local )-> hdlend , CFD_SEQ_NOCPU ,
683- smp_processor_id (), CFD_SEQ_HDLEND );
684487}
685488
686489
@@ -704,8 +507,6 @@ void flush_smp_call_function_queue(void)
704507 if (llist_empty (this_cpu_ptr (& call_single_queue )))
705508 return ;
706509
707- cfd_seq_store (this_cpu_ptr (& cfd_seq_local )-> idle , CFD_SEQ_NOCPU ,
708- smp_processor_id (), CFD_SEQ_IDLE );
709510 local_irq_save (flags );
710511 /* Get the already pending soft interrupts for RT enabled kernels */
711512 was_pending = local_softirq_pending ();
@@ -929,8 +730,7 @@ static void smp_call_function_many_cond(const struct cpumask *mask,
929730
930731 cpumask_clear (cfd -> cpumask_ipi );
931732 for_each_cpu (cpu , cfd -> cpumask ) {
932- struct cfd_percpu * pcpu = per_cpu_ptr (cfd -> pcpu , cpu );
933- call_single_data_t * csd = & pcpu -> csd ;
733+ call_single_data_t * csd = & per_cpu_ptr (cfd -> pcpu , cpu )-> csd ;
934734
935735 if (cond_func && !cond_func (cpu , info ))
936736 continue ;
@@ -944,20 +744,13 @@ static void smp_call_function_many_cond(const struct cpumask *mask,
944744 csd -> node .src = smp_processor_id ();
945745 csd -> node .dst = cpu ;
946746#endif
947- cfd_seq_store (pcpu -> seq_queue , this_cpu , cpu , CFD_SEQ_QUEUE );
948747 if (llist_add (& csd -> node .llist , & per_cpu (call_single_queue , cpu ))) {
949748 __cpumask_set_cpu (cpu , cfd -> cpumask_ipi );
950749 nr_cpus ++ ;
951750 last_cpu = cpu ;
952-
953- cfd_seq_store (pcpu -> seq_ipi , this_cpu , cpu , CFD_SEQ_IPI );
954- } else {
955- cfd_seq_store (pcpu -> seq_noipi , this_cpu , cpu , CFD_SEQ_NOIPI );
956751 }
957752 }
958753
959- cfd_seq_store (this_cpu_ptr (& cfd_seq_local )-> ping , this_cpu , CFD_SEQ_NOCPU , CFD_SEQ_PING );
960-
961754 /*
962755 * Choose the most efficient way to send an IPI. Note that the
963756 * number of CPUs might be zero due to concurrent changes to the
@@ -967,8 +760,6 @@ static void smp_call_function_many_cond(const struct cpumask *mask,
967760 send_call_function_single_ipi (last_cpu );
968761 else if (likely (nr_cpus > 1 ))
969762 arch_send_call_function_ipi_mask (cfd -> cpumask_ipi );
970-
971- cfd_seq_store (this_cpu_ptr (& cfd_seq_local )-> pinged , this_cpu , CFD_SEQ_NOCPU , CFD_SEQ_PINGED );
972763 }
973764
974765 if (run_local && (!cond_func || cond_func (this_cpu , info ))) {
0 commit comments