Skip to contentSkip to conversation

3.18: lockdep problems in cpufreq

PATCH New Russell King - ARM Linux 6 participants 36 messages Dec 14, 2014 – Aug 18, 2015 Thermal

lore
Share & tools
lore
#0 lore raw

Here's a nice Christmas present one of my iMX6 machines gave me tonight. I haven't begun to look into it.

======================================================
[ INFO: possible circular locking dependency detected ]
3.18.0+ #1453 Not tainted
-------------------------------------------------------
rc.local/770 is trying to acquire lock:
(cooling_cpufreq_lock){+.+.+.}, at: [<c04abfc4>] cpufreq_thermal_notifier+0x34/0xfc

but task is already holding lock:
((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>] __blocking_notifier_call_chain+0x34/0x68

which lock already depends on the new lock.

the existing dependency chain (in reverse order) is:

-> #1 ((cpufreq_policy_notifier_list).rwsem){++++.+}:

       [<c06bc3b0>] down_write+0x44/0x9c
       [<c0043444>] blocking_notifier_chain_register+0x28/0xd8
       [<c04ad610>] cpufreq_register_notifier+0x68/0x90
       [<c04abe4c>] __cpufreq_cooling_register.part.1+0x120/0x180
       [<c04abf44>] __cpufreq_cooling_register+0x98/0xa4
       [<c04abf8c>] cpufreq_cooling_register+0x18/0x1c
       [<bf0046f8>] imx_thermal_probe+0x1c0/0x470 [imx_thermal]
       [<c037cef8>] platform_drv_probe+0x50/0xac
       [<c037b710>] driver_probe_device+0x114/0x234
       [<c037b8cc>] __driver_attach+0x9c/0xa0
       [<c0379d68>] bus_for_each_dev+0x5c/0x90
       [<c037b204>] driver_attach+0x24/0x28
       [<c037ae7c>] bus_add_driver+0xe0/0x1d8
       [<c037c0cc>] driver_register+0x80/0xfc
       [<c037cd80>] __platform_driver_register+0x50/0x64
       [<bf007018>] 0xbf007018
       [<c0008a5c>] do_one_initcall+0x88/0x1d8
       [<c0095da4>] load_module+0x1768/0x1ef8
       [<c0096614>] SyS_init_module+0xe0/0xf4
       [<c000ec00>] ret_fast_syscall+0x0/0x48

-> #0 (cooling_cpufreq_lock){+.+.+.}:

       [<c00619f8>] lock_acquire+0xb0/0x124
       [<c06ba3b4>] mutex_lock_nested+0x5c/0x3d8
       [<c04abfc4>] cpufreq_thermal_notifier+0x34/0xfc
       [<c0042bf4>] notifier_call_chain+0x4c/0x8c
       [<c0042f20>] __blocking_notifier_call_chain+0x50/0x68
       [<c0042f58>] blocking_notifier_call_chain+0x20/0x28
       [<c04ae62c>] cpufreq_set_policy+0x7c/0x1d0
       [<c04af3cc>] store_scaling_governor+0x74/0x9c
       [<c04ad418>] store+0x90/0xc0
       [<c0175384>] sysfs_kf_write+0x54/0x58
       [<c01746b4>] kernfs_fop_write+0xdc/0x190
       [<c010dcc0>] vfs_write+0xac/0x1b4
       [<c010dfec>] SyS_write+0x44/0x90
       [<c000ec00>] ret_fast_syscall+0x0/0x48

other info that might help us debug this:

 Possible unsafe locking scenario:
       CPU0                    CPU1
       ----                    ----
  lock((cpufreq_policy_notifier_list).rwsem);
                               lock(cooling_cpufreq_lock);
                               lock((cpufreq_policy_notifier_list).rwsem);

lock(cooling_cpufreq_lock);

*** DEADLOCK ***

7 locks held by rc.local/770:

 #0:  (sb_writers#6){.+.+.+}, at: [<c010dda0>] vfs_write+0x18c/0x1b4
 #1:  (&of->mutex){+.+.+.}, at: [<c0174678>] kernfs_fop_write+0xa0/0x190
 #2:  (s_active#52){.+.+.+}, at: [<c0174680>] kernfs_fop_write+0xa8/0x190
 #3:  (cpu_hotplug.lock){++++++}, at: [<c0026a60>] get_online_cpus+0x34/0x90
 #4:  (cpufreq_rwsem){.+.+.+}, at: [<c04ad3e0>] store+0x58/0xc0
 #5:  (&policy->rwsem){+.+.+.}, at: [<c04ad3f8>] store+0x70/0xc0
 #6:  ((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>] __blocking_notifier_call_chain+0x34/0x68
stack backtrace:
CPU: 0 PID: 770 Comm: rc.local Not tainted 3.18.0+ #1453
Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
Backtrace: 
[<c00121c8>] (dump_backtrace) from [<c0012360>] (show_stack+0x18/0x1c)
 r6:c0b85a80 r5:c0b75630 r4:00000000 r3:00000000
[<c0012348>] (show_stack) from [<c06b6c48>] (dump_stack+0x7c/0x98)
[<c06b6bcc>] (dump_stack) from [<c06b42a4>] (print_circular_bug+0x28c/0x2d8)
 r4:c0b85a80 r3:d0071d40
[<c06b4018>] (print_circular_bug) from [<c00613b0>] (__lock_acquire+0x1acc/0x1bb0)
 r10:c0b50660 r8:c09e6d80 r7:d0071d40 r6:c11d0f0c r5:00000007 r4:d0072240
[<c005f8e4>] (__lock_acquire) from [<c00619f8>] (lock_acquire+0xb0/0x124)
 r10:00000000 r9:c04abfc4 r8:00000000 r7:00000000 r6:00000000 r5:c0a06f0c
 r4:00000000
[<c0061948>] (lock_acquire) from [<c06ba3b4>] (mutex_lock_nested+0x5c/0x3d8)
 r10:ec853800 r9:c0a06ed4 r8:d0071d40 r7:c0a06ed4 r6:c11d0f0c r5:00000000
 r4:c04abfc4
[<c06ba358>] (mutex_lock_nested) from [<c04abfc4>] (cpufreq_thermal_notifier+0x34/0xfc)
 r10:ec853800 r9:ec85380c r8:d00d7d3c r7:c0a06ed4 r6:d00d7d3c r5:00000000
 r4:fffffffe
[<c04abf90>] (cpufreq_thermal_notifier) from [<c0042bf4>] (notifier_call_chain+0x4c/0x8c)
 r7:00000000 r6:00000000 r5:00000000 r4:fffffffe
[<c0042ba8>] (notifier_call_chain) from [<c0042f20>] (__blocking_notifier_call_chain+0x50/0x68)
 r8:c0a072a4 r7:00000000 r6:d00d7d3c r5:ffffffff r4:c0a06fc8 r3:ffffffff
[<c0042ed0>] (__blocking_notifier_call_chain) from [<c0042f58>] (blocking_notifier_call_chain+0x20/0x28)
 r7:ec98b540 r6:c13ebc80 r5:ed76e600 r4:d00d7d3c
[<c0042f38>] (blocking_notifier_call_chain) from [<c04ae62c>] (cpufreq_set_policy+0x7c/0x1d0)
[<c04ae5b0>] (cpufreq_set_policy) from [<c04af3cc>] (store_scaling_governor+0x74/0x9c)
 r7:ec98b540 r6:0000000c r5:ec98b540 r4:ed76e600
[<c04af358>] (store_scaling_governor) from [<c04ad418>] (store+0x90/0xc0)
 r6:0000000c r5:ed76e6d4 r4:ed76e600
[<c04ad388>] (store) from [<c0175384>] (sysfs_kf_write+0x54/0x58)
 r8:0000000c r7:d00d7f78 r6:ec98b540 r5:0000000c r4:ec853800 r3:0000000c
[<c0175330>] (sysfs_kf_write) from [<c01746b4>] (kernfs_fop_write+0xdc/0x190)
 r6:ec98b540 r5:00000000 r4:00000000 r3:c0175330
[<c01745d8>] (kernfs_fop_write) from [<c010dcc0>] (vfs_write+0xac/0x1b4)
 r10:0162aa70 r9:d00d6000 r8:0000000c r7:d00d7f78 r6:0162aa70 r5:0000000c
 r4:eccde500
[<c010dc14>] (vfs_write) from [<c010dfec>] (SyS_write+0x44/0x90)
 r10:0162aa70 r8:0000000c r7:eccde500 r6:eccde500 r5:00000000 r4:00000000
[<c010dfa8>] (SyS_write) from [<c000ec00>] (ret_fast_syscall+0x0/0x48)
 r10:00000000 r8:c000edc4 r7:00000004 r6:000216cc r5:0000000c r4:0162aa70
Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
#1 lore raw
Quoted 10 lines · Russell King - ARM Linux

Here's a nice Christmas present one of my iMX6 machines gave me tonight. I haven't begun to look into it.

======================================================
[ INFO: possible circular locking dependency detected ]
3.18.0+ #1453 Not tainted
-------------------------------------------------------
rc.local/770 is trying to acquire lock:
(cooling_cpufreq_lock){+.+.+.}, at: [<c04abfc4>] cpufreq_thermal_notifier+0x34/0xfc

Quoted 4 lines

but task is already holding lock:
((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>] __blocking_notifier_call_chain+0x34/0x68

which lock already depends on the new lock.

Well, that's for Viresh.

Also adding Eduardo as he's been working with Viresh on the cooling stuff recently.

Rafael

#2 lore raw
Quoted 3 lines · Rafael J. Wysocki
Quoted 2 lines · Russell King - ARM Linux

Here's a nice Christmas present one of my iMX6 machines gave me tonight. I haven't begun to look into it.

Is the culprit this one?

Fixes 2dcd851fe4b4 ("thermal: cpu_cooling: Update always cpufreq

policy with thermal constraints")

As this is what it changed:

@@ -316,21 +312,28 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,

 {
        struct cpufreq_policy *policy = data;
        unsigned long max_freq = 0;

+ struct cpufreq_cooling_device *cpufreq_dev;

- if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID)
+ if (event != CPUFREQ_ADJUST)

                return 0;

- if (cpumask_test_cpu(policy->cpu, &notify_device->allowed_cpus))
- max_freq = notify_device->cpufreq_val;
- else
- return 0;
+ mutex_lock(&cooling_cpufreq_lock);
+ list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
+ if (!cpumask_test_cpu(policy->cpu,
+ &cpufreq_dev->allowed_cpus))
+ continue;
+
+ if (!cpufreq_dev->cpufreq_val)
+ cpufreq_dev->cpufreq_val = get_cpu_frequency(
+ cpumask_any(&cpufreq_dev->allowed_cpus),
+ cpufreq_dev->cpufreq_state);

- /* Never exceed user_policy.max */
- if (max_freq > policy->user_policy.max)
- max_freq = policy->user_policy.max;
+ max_freq = cpufreq_dev->cpufreq_val;

- if (policy->max != max_freq)
- cpufreq_verify_within_limits(policy, 0, max_freq);
+ if (policy->max != max_freq)
+ cpufreq_verify_within_limits(policy, 0, max_freq);
+ }
+ mutex_unlock(&cooling_cpufreq_lock);

        return 0;

}

Quoted 7 lines
Quoted 7 lines

======================================================
[ INFO: possible circular locking dependency detected ]
3.18.0+ #1453 Not tainted
-------------------------------------------------------
rc.local/770 is trying to acquire lock:
(cooling_cpufreq_lock){+.+.+.}, at: [<c04abfc4>] cpufreq_thermal_notifier+0x34/0xfc

Quoted 6 lines
Quoted 4 lines

but task is already holding lock:
((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>] __blocking_notifier_call_chain+0x34/0x68

which lock already depends on the new lock.

Well, that's for Viresh.

Maybe not as the rework I have done is queued for this merge window. I was afraid really after reading the "offenders" discussion on IRC :)

Cc'd Yadwinder as well who wrote this patch.

#3 lore raw
Quoted 82 lines

-----Original Message-----
From: Viresh Kumar [mailto:[email protected]]
Sent: Monday, December 15, 2014 9:27 AM
To: Rafael J. Wysocki; [email protected]
Cc: Russell King - ARM Linux; [email protected]; [email protected]; Eduardo Valentin
Subject: Re: 3.18: lockdep problems in cpufreq

Quoted 1 line · Rafael J. Wysocki

On Sunday, December 14, 2014 09:36:55 PM Russell King - ARM Linux

Quoted 1 line · wrote:
Quoted 1 line

Here's a nice Christmas present one of my iMX6 machines gave me

tonight.

Quoted 1 line
Quoted 1 line

I haven't begun to look into it.

Is the culprit this one?

Fixes 2dcd851fe4b4 ("thermal: cpu_cooling: Update always cpufreq

policy with thermal constraints")

As this is what it changed:

(quoted diff) +17 -10
@@ -316,21 +312,28 @@ static int cpufreq_thermal_notifier(struct
 notifier_block *nb,  {
        struct cpufreq_policy *policy = data;
        unsigned long max_freq = 0;
+       struct cpufreq_cooling_device *cpufreq_dev;
 
-       if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID)
+       if (event != CPUFREQ_ADJUST)
                return 0;
 
-       if (cpumask_test_cpu(policy->cpu, &notify_device-
 >allowed_cpus))
-               max_freq = notify_device->cpufreq_val;
-       else
-               return 0;
+       mutex_lock(&cooling_cpufreq_lock);
+       list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
+               if (!cpumask_test_cpu(policy->cpu,
+                                       &cpufreq_dev->allowed_cpus))
+                       continue;
+
+               if (!cpufreq_dev->cpufreq_val)
+                       cpufreq_dev->cpufreq_val = get_cpu_frequency(
+                                       cpumask_any(&cpufreq_dev-
 >allowed_cpus),
+                                       cpufreq_dev->cpufreq_state);
 
-       /* Never exceed user_policy.max */
-       if (max_freq > policy->user_policy.max)
-               max_freq = policy->user_policy.max;
+               max_freq = cpufreq_dev->cpufreq_val;
 
-       if (policy->max != max_freq)
-               cpufreq_verify_within_limits(policy, 0, max_freq);
+               if (policy->max != max_freq)
+                       cpufreq_verify_within_limits(policy, 0,
 max_freq);
+       }
+       mutex_unlock(&cooling_cpufreq_lock);
        return 0;

}

Quoted 2 lines
Quoted 2 lines

======================================================
[ INFO: possible circular locking dependency detected ] 3.18.0+

#1453

Quoted 10 lines
Quoted 10 lines

Not tainted
-------------------------------------------------------
rc.local/770 is trying to acquire lock:
(cooling_cpufreq_lock){+.+.+.}, at: [<c04abfc4>]
cpufreq_thermal_notifier+0x34/0xfc

but task is already holding lock:
((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>]
__blocking_notifier_call_chain+0x34/0x68

Quoted 8 lines
Quoted 3 lines
Quoted 1 line

which lock already depends on the new lock.

Well, that's for Viresh.

Maybe not as the rework I have done is queued for this merge window. I was afraid really after reading the "offenders" discussion on IRC :)

Cc'd Yadwinder as well who wrote this patch.

Thanks :).

Unfortunately, I didn’t get any such warning though I tested patch enabling CONFIG_PROVE_LOCKING before posting. It seems Russell is trying to load imx_thermal as module and parallely Changing cpufreq governor from userspace, which was not my test case.

Anyways, after analyzing log and code,I think problem is not in cpufreq_thermal_notifier which was modified in patch as stated above. Actual problem is in __cpufreq_cooling_register which is unnecessarily calling cpufreq_register_notifier() inside section protected by cooling_cpufreq_lock.
Because cpufreq_policy_notifier_list).rwsem is already held
by store_scaling_governor when __cpufreq_cooling_register is trying to cpufreq_policy_notifier_list while holding cooling_cpufreq_lock.

So I think following can fix the problem:

drivers/thermal/cpu_cooling.c +4 -4
index ad09e51..622ea40 100644
@@ -484,15 +484,15 @@ __cpufreq_cooling_register(struct device_node *np,
        cpufreq_dev->cpufreq_state = 0;
        mutex_lock(&cooling_cpufreq_lock);
 
-       /* Register the notifier for first cpufreq cooling device */
-       if (cpufreq_dev_count == 0)
-               cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
-                                         CPUFREQ_POLICY_NOTIFIER);
        cpufreq_dev_count++;
        list_add(&cpufreq_dev->node, &cpufreq_dev_list);
 
        mutex_unlock(&cooling_cpufreq_lock);
 
+       /* Register the notifier for first cpufreq cooling device */
+       if (cpufreq_dev_count == 0)
+               cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
+                                         CPUFREQ_POLICY_NOTIFIER);
        return cool_dev;
 }
 

Best Regards,
Yadwinder

#4 lore raw
Quoted 5 lines · Yadwinder Singh Brar

Unfortunately, I didn?t get any such warning though I tested patch enabling CONFIG_PROVE_LOCKING before posting. It seems Russell is trying to load imx_thermal as module and parallely Changing cpufreq governor from userspace, which was not my test case.

No. Yes, imx_thermal is a module, which is loaded by udev very early in the userspace boot. Later on, in the rc.local, I poke the governor from userspace.

This is evidenced by the bluetooth modules being loaded after imx_thermal:

Module                  Size  Used by
bnep                   10574  2
rfcomm                 33720  0
bluetooth             293598  10 bnep,rfcomm
nfsd                   90264  0
exportfs                3988  1 nfsd
hid_cypress             1763  0
snd_soc_fsl_spdif       9753  2
imx_pcm_dma             1137  1 snd_soc_fsl_spdif
imx_sdma               12885  2
imx2_wdt                3248  0
imx_thermal             5386  0
snd_soc_imx_spdif       1877  0

and the timestamp on the bluetooth message:

[   25.503739] Bluetooth: Core ver 2.19

vs the timestamp on the lockdep message:

[   29.499195] [ INFO: possible circular locking dependency detected ]

My rc.local does this:

# Configure cpufreq
echo 1 > /sys/devices/system/cpu/cpufreq/ondemand/io_is_busy echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

Quoted 22 lines

Anyways, after analyzing log and code,I think problem is not in cpufreq_thermal_notifier which was modified in patch as stated above. Actual problem is in __cpufreq_cooling_register which is unnecessarily calling cpufreq_register_notifier() inside section protected by cooling_cpufreq_lock.
Because cpufreq_policy_notifier_list).rwsem is already held
by store_scaling_governor when __cpufreq_cooling_register is trying to cpufreq_policy_notifier_list while holding cooling_cpufreq_lock.

So I think following can fix the problem:

drivers/thermal/cpu_cooling.c +0 -3
index ad09e51..622ea40 100644
@@ -484,15 +484,15 @@ __cpufreq_cooling_register(struct device_node *np,
        cpufreq_dev->cpufreq_state = 0;
        mutex_lock(&cooling_cpufreq_lock);
 
-       /* Register the notifier for first cpufreq cooling device */
-       if (cpufreq_dev_count == 0)
-               cpufreq_register_notifier(&thermal_cpufreq_notifier_block,

drivers/thermal/cpu_cooling.c __cpufreq_cooling_register(struct device_node *np, · line 495

Quoted 10 lines
drivers/thermal/cpu_cooling.c +4 -1
-                                         CPUFREQ_POLICY_NOTIFIER);
        cpufreq_dev_count++;
        list_add(&cpufreq_dev->node, &cpufreq_dev_list);
 
        mutex_unlock(&cooling_cpufreq_lock);
 
+       /* Register the notifier for first cpufreq cooling device */
+       if (cpufreq_dev_count == 0)
+               cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
+                                         CPUFREQ_POLICY_NOTIFIER);

No, sorry, this patch is worse.

1. cpufreq_register_notifier() will never be called, even on the first caller to this code: at the point where it's tested for zero, it will be incremented to one by the previous code.

2. What happens if two threads come here?

The first thread succeeds in grabbing cooling_cpufreq_lock. The second thread stalls waiting for cooling_cpufreq_lock to be released.

The first thread increments cpufreq_dev_count, adds to the list, and then releases the lock. At this point, control may be passed to the second thread (since mutex_unlock() will wake it up.) The second thread gets into the critical region, and increments cpufreq_dev_count again.

By the time the first thread runs, cpufreq_dev_count may be two at this point.

Unfortunately, you do need some kind of synchronisation here. If it's not important when cpufreq_register_notifier() gets called, maybe this can work:

	bool register;

	mutex_lock(&cooling_cpufreq_lock);
	register = cpufreq_dev_count++ == 0;
	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
	mutex_unlock(&cooling_cpufreq_lock);

	if (register)
		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
					  CPUFREQ_POLICY_NOTIFIER);

However, I suspect that may well be buggy if we have a cleanup path which unregisters the notifier when cpufreq_dev_count is decremented to zero... which we seem to have in cpufreq_cooling_unregister().

The answer may well be to have finer grained locking here:

- one lock to protect cpufreq_dev_list, which is only ever taken when adding or removing entries from it

- a second lock to protect cpufreq_dev_count and the calls to cpufreq_register_notifier() and cpufreq_unregister_notifier()

and you would /never/ take either of those two locks inside each other. In other words:

	mutex_lock(&cooling_list_lock);
	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
	mutex_unlock(&cooling_list_lock);

	mutex_lock(&cooling_cpufreq_lock);
	if (cpufreq_dev_count++ == 0)
		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
					  CPUFREQ_POLICY_NOTIFIER);
	mutex_unlock(&cooling_cpufreq_lock);

and similar in the cleanup path. The notifier itself would only ever take the cooling_list_lock.

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
#5 lore raw
Quoted 84 lines

-----Original Message-----
From: Russell King - ARM Linux [mailto:[email protected]]
Sent: Monday, December 15, 2014 7:17 PM
To: Yadwinder Singh Brar
Cc: 'Viresh Kumar'; 'Rafael J. Wysocki'; linux-arm- [email protected]; [email protected]; 'Eduardo Valentin'
Subject: Re: 3.18: lockdep problems in cpufreq

Quoted 4 lines · Yadwinder Singh Brar

Unfortunately, I didn’t get any such warning though I tested patch enabling CONFIG_PROVE_LOCKING before posting. It seems Russell is trying to load imx_thermal as module and parallely Changing cpufreq governor from userspace, which was not my test case.

No. Yes, imx_thermal is a module, which is loaded by udev very early in the userspace boot. Later on, in the rc.local, I poke the governor from userspace.

This is evidenced by the bluetooth modules being loaded after imx_thermal:

Module                  Size  Used by
bnep                   10574  2
rfcomm                 33720  0
bluetooth             293598  10 bnep,rfcomm
nfsd                   90264  0
exportfs                3988  1 nfsd
hid_cypress             1763  0
snd_soc_fsl_spdif       9753  2
imx_pcm_dma             1137  1 snd_soc_fsl_spdif
imx_sdma               12885  2
imx2_wdt                3248  0
imx_thermal             5386  0
snd_soc_imx_spdif       1877  0

and the timestamp on the bluetooth message:

[   25.503739] Bluetooth: Core ver 2.19

vs the timestamp on the lockdep message:

[   29.499195] [ INFO: possible circular locking dependency detected ]

My rc.local does this:

# Configure cpufreq
echo 1 > /sys/devices/system/cpu/cpufreq/ondemand/io_is_busy echo performance >
/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

Quoted 3 lines

Anyways, after analyzing log and code,I think problem is not in cpufreq_thermal_notifier which was modified in patch as stated above. Actual problem is in __cpufreq_cooling_register which is

unnecessarily

drivers/thermal/cpu_cooling.c __cpufreq_cooling_register(struct device_node

Quoted 13 lines

calling cpufreq_register_notifier() inside section protected by cooling_cpufreq_lock.
Because cpufreq_policy_notifier_list).rwsem is already held by store_scaling_governor when __cpufreq_cooling_register is trying to cpufreq_policy_notifier_list while holding cooling_cpufreq_lock.

So I think following can fix the problem:

(quoted diff) +0 -0

b/drivers/thermal/cpu_cooling.c index ad09e51..622ea40 100644

drivers/thermal/cpu_cooling.c +0 -0
@@ -484,15 +484,15 @@ __cpufreq_cooling_register(struct device_node

*np,

drivers/thermal/cpu_cooling.c __cpufreq_cooling_register(struct device_node *np,

Quoted 6 lines
drivers/thermal/cpu_cooling.c +0 -3
        cpufreq_dev->cpufreq_state = 0;
        mutex_lock(&cooling_cpufreq_lock);
 
-       /* Register the notifier for first cpufreq cooling device */
-       if (cpufreq_dev_count == 0)
-

cpufreq_register_notifier(&thermal_cpufreq_notifier_block,

Quoted 6 lines
drivers/thermal/cpu_cooling.c +0 -1
-                                         CPUFREQ_POLICY_NOTIFIER);
        cpufreq_dev_count++;
        list_add(&cpufreq_dev->node, &cpufreq_dev_list);
 
        mutex_unlock(&cooling_cpufreq_lock);
 
Quoted 8 lines

drivers/thermal/cpu_cooling.c __cpufreq_cooling_register(struct device_node *np,

Quoted 3 lines
drivers/thermal/cpu_cooling.c +3 -0
+       /* Register the notifier for first cpufreq cooling device */
+       if (cpufreq_dev_count == 0)
+

cpufreq_register_notifier(&thermal_cpufreq_notifier_block,

drivers/thermal/cpu_cooling.c __cpufreq_cooling_register(struct device_node *np, · line 495

Quoted 1 line
drivers/thermal/cpu_cooling.c +1 -0
+                                         CPUFREQ_POLICY_NOTIFIER);

No, sorry, this patch is worse.

Actually it was not patch :P , just moved cpufreq_register_notifier() out of locking, as it is(C&P) to explain my point.

Quoted 19 lines

1. cpufreq_register_notifier() will never be called, even on the first caller to this code: at the point where it's tested for zero, it
will
be incremented to one by the previous code.

2. What happens if two threads come here?

The first thread succeeds in grabbing cooling_cpufreq_lock. The
second
thread stalls waiting for cooling_cpufreq_lock to be released.

The first thread increments cpufreq_dev_count, adds to the list, and
then
releases the lock. At this point, control may be passed to the
second
thread (since mutex_unlock() will wake it up.) The second thread
gets
into the critical region, and increments cpufreq_dev_count again.

Quoted 3 lines

By the time the first thread runs, cpufreq_dev_count may be two at
this
point.

Yes, may be.

Quoted 5 lines

Unfortunately, you do need some kind of synchronisation here. If it's not important when cpufreq_register_notifier() gets called, maybe this can work:

Quoted 8 lines
	bool register;

	mutex_lock(&cooling_cpufreq_lock);
	register = cpufreq_dev_count++ == 0;
	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
	mutex_unlock(&cooling_cpufreq_lock);

	if (register)

register may be 0 in scenario you stated above in second point. So this approach will not work.

Quoted 29 lines
		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
					  CPUFREQ_POLICY_NOTIFIER);

However, I suspect that may well be buggy if we have a cleanup path which unregisters the notifier when cpufreq_dev_count is decremented to zero...
which we seem to have in cpufreq_cooling_unregister().

The answer may well be to have finer grained locking here:

- one lock to protect cpufreq_dev_list, which is only ever taken when adding or removing entries from it

- a second lock to protect cpufreq_dev_count and the calls to cpufreq_register_notifier() and cpufreq_unregister_notifier()

and you would /never/ take either of those two locks inside each other. In other words:

	mutex_lock(&cooling_list_lock);
	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
	mutex_unlock(&cooling_list_lock);

	mutex_lock(&cooling_cpufreq_lock);
	if (cpufreq_dev_count++ == 0)
		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
					  CPUFREQ_POLICY_NOTIFIER);
	mutex_unlock(&cooling_cpufreq_lock);
Quoted 3 lines

and similar in the cleanup path. The notifier itself would only ever take the cooling_list_lock.

I agree with this approach, if its fine for others also, I can implement and post patch.

Thanks,
Yadwinder

Quoted 3 lines

--
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up according to speedtest.net.

#6 lore raw
Quoted 21 lines · Yadwinder Singh Brar
Quoted 21 lines

The answer may well be to have finer grained locking here:

- one lock to protect cpufreq_dev_list, which is only ever taken when adding or removing entries from it

- a second lock to protect cpufreq_dev_count and the calls to cpufreq_register_notifier() and cpufreq_unregister_notifier()

and you would /never/ take either of those two locks inside each other. In other words:

	mutex_lock(&cooling_list_lock);
	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
	mutex_unlock(&cooling_list_lock);

	mutex_lock(&cooling_cpufreq_lock);
	if (cpufreq_dev_count++ == 0)
		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
					  CPUFREQ_POLICY_NOTIFIER);
	mutex_unlock(&cooling_cpufreq_lock);
Quoted 6 lines
Quoted 3 lines

and similar in the cleanup path. The notifier itself would only ever take the cooling_list_lock.

I agree with this approach, if its fine for others also, I can implement and post patch.

Yes, please do.

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
#7 lore raw
Quoted 22 lines · Russell King - ARM Linux
Quoted 21 lines · Yadwinder Singh Brar
Quoted 21 lines

The answer may well be to have finer grained locking here:

- one lock to protect cpufreq_dev_list, which is only ever taken when adding or removing entries from it

- a second lock to protect cpufreq_dev_count and the calls to cpufreq_register_notifier() and cpufreq_unregister_notifier()

and you would /never/ take either of those two locks inside each other. In other words:

	mutex_lock(&cooling_list_lock);
	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
	mutex_unlock(&cooling_list_lock);

	mutex_lock(&cooling_cpufreq_lock);
	if (cpufreq_dev_count++ == 0)
		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
					  CPUFREQ_POLICY_NOTIFIER);
	mutex_unlock(&cooling_cpufreq_lock);
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

and similar in the cleanup path. The notifier itself would only ever take the cooling_list_lock.

I agree with this approach, if its fine for others also, I can implement and post patch.

Yes, please do.

Indeed. We have a regression here to fix.

Rafael

#8 lore raw
Quoted 8 lines · Rafael J. Wysocki
Quoted 5 lines · Russell King - ARM Linux
Quoted 2 lines · Yadwinder Singh Brar

I agree with this approach, if its fine for others also, I can implement and post patch.

Yes, please do.

Indeed. We have a regression here to fix.

Well, here's a patch which I'm running on top of 3.18 at the moment, which is basically what I described in my email, and I'm running with it and it is without any lockdep complaint.

8<===
From: Russell King <[email protected]>
thermal: cpu_cooling: fix lockdep problems in cpu_cooling

A recent change to the cpu_cooling code introduced a AB-BA deadlock scenario between the cpufreq_policy_notifier_list rwsem and the cooling_cpufreq_lock. This is caused by cooling_cpufreq_lock being held before the registration/removal of the notifier block (an operation which takes the rwsem), and the notifier code itself which takes the locks in the reverse order.

Solve this by moving to finer grained locking - use one mutex to protect the cpufreq_dev_list as a whole, and a separate lock to ensure correct ordering of cpufreq notifier registration and removal.

I considered taking the cooling_list_lock within cooling_cpufreq_lock to protect the registration sequence as a whole, but that adds a dependency between these two locks which is best avoided (lest someone tries to take those two new locks in the reverse order.) In any case, it's safer to have an empty cpufreq_dev_list than to have unnecessary dependencies between locks.

Fixes 2dcd851fe4b4 ("thermal: cpu_cooling: Update always cpufreq policy with thermal constraints")

---

 drivers/thermal/cpu_cooling.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/thermal/cpu_cooling.c +12 -4
index ad09e51ffae4..9e42c6f30785 100644
@@ -57,6 +57,7 @@ static DEFINE_MUTEX(cooling_cpufreq_lock);
 
 static unsigned int cpufreq_dev_count;
 
+static DEFINE_MUTEX(cooling_list_lock);
 static LIST_HEAD(cpufreq_dev_list);
 
 /**
@@ -317,7 +318,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 	if (event != CPUFREQ_ADJUST)
 		return 0;
 
-	mutex_lock(&cooling_cpufreq_lock);
+	mutex_lock(&cooling_list_lock);
 	list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
 		if (!cpumask_test_cpu(policy->cpu,
 					&cpufreq_dev->allowed_cpus))
@@ -333,7 +334,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 		if (policy->max != max_freq)
 			cpufreq_verify_within_limits(policy, 0, max_freq);
 	}
-	mutex_unlock(&cooling_cpufreq_lock);
+	mutex_unlock(&cooling_list_lock);
 
 	return 0;
 }
@@ -482,6 +483,11 @@ __cpufreq_cooling_register(struct device_node *np,
 	}
 	cpufreq_dev->cool_dev = cool_dev;
 	cpufreq_dev->cpufreq_state = 0;
+
+	mutex_lock(&cooling_list_lock);
+	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+	mutex_unlock(&cooling_list_lock);
+
 	mutex_lock(&cooling_cpufreq_lock);
 
 	/* Register the notifier for first cpufreq cooling device */
@@ -489,7 +495,6 @@ __cpufreq_cooling_register(struct device_node *np,
 		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
 					  CPUFREQ_POLICY_NOTIFIER);
 	cpufreq_dev_count++;
-	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
 
 	mutex_unlock(&cooling_cpufreq_lock);
 
@@ -553,7 +558,6 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
 	cpufreq_dev = cdev->devdata;
 	mutex_lock(&cooling_cpufreq_lock);
-	list_del(&cpufreq_dev->node);
 	cpufreq_dev_count--;
 
 	/* Unregister the notifier for the last cpufreq cooling device */
@@ -562,6 +566,10 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 					    CPUFREQ_POLICY_NOTIFIER);
 	mutex_unlock(&cooling_cpufreq_lock);
 
+	mutex_lock(&cooling_list_lock);
+	list_del(&cpufreq_dev->node);
+	mutex_unlock(&cooling_list_lock);
+
 	thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
 	release_idr(&cpufreq_idr, cpufreq_dev->id);
 	kfree(cpufreq_dev);
Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
Reviewed-by
#9 lore raw
Quoted 3 lines · Russell King - ARM Linux

Well, here's a patch which I'm running on top of 3.18 at the moment, which is basically what I described in my email, and I'm running with it and it is without any lockdep complaint.

We need two separate patches now, one for 3.18 and other one for 3.19-rc. 3.19 has see lots of changes in this particular file and so we need to change few things here.

Quoted 88 lines

8<===
From: Russell King <[email protected]>
thermal: cpu_cooling: fix lockdep problems in cpu_cooling

A recent change to the cpu_cooling code introduced a AB-BA deadlock scenario between the cpufreq_policy_notifier_list rwsem and the cooling_cpufreq_lock. This is caused by cooling_cpufreq_lock being held before the registration/removal of the notifier block (an operation which takes the rwsem), and the notifier code itself which takes the locks in the reverse order.

Solve this by moving to finer grained locking - use one mutex to protect the cpufreq_dev_list as a whole, and a separate lock to ensure correct ordering of cpufreq notifier registration and removal.

I considered taking the cooling_list_lock within cooling_cpufreq_lock to protect the registration sequence as a whole, but that adds a dependency between these two locks which is best avoided (lest someone tries to take those two new locks in the reverse order.) In any case, it's safer to have an empty cpufreq_dev_list than to have unnecessary dependencies between locks.

Fixes 2dcd851fe4b4 ("thermal: cpu_cooling: Update always cpufreq policy with thermal constraints")

---

 drivers/thermal/cpu_cooling.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/thermal/cpu_cooling.c +8 -4
index ad09e51ffae4..9e42c6f30785 100644
@@ -57,6 +57,7 @@ static DEFINE_MUTEX(cooling_cpufreq_lock);
 
 static unsigned int cpufreq_dev_count;
 
+static DEFINE_MUTEX(cooling_list_lock);
 static LIST_HEAD(cpufreq_dev_list);
 
 /**
@@ -317,7 +318,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
        if (event != CPUFREQ_ADJUST)
                return 0;
 
-       mutex_lock(&cooling_cpufreq_lock);
+       mutex_lock(&cooling_list_lock);
        list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
                if (!cpumask_test_cpu(policy->cpu,
                                        &cpufreq_dev->allowed_cpus))
@@ -333,7 +334,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
                if (policy->max != max_freq)
                        cpufreq_verify_within_limits(policy, 0, max_freq);
        }
-       mutex_unlock(&cooling_cpufreq_lock);
+       mutex_unlock(&cooling_list_lock);
 
        return 0;
 }
@@ -482,6 +483,11 @@ __cpufreq_cooling_register(struct device_node *np,
        }
        cpufreq_dev->cool_dev = cool_dev;
        cpufreq_dev->cpufreq_state = 0;
+
+       mutex_lock(&cooling_list_lock);
+       list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+       mutex_unlock(&cooling_list_lock);
+
        mutex_lock(&cooling_cpufreq_lock);
 
        /* Register the notifier for first cpufreq cooling device */
@@ -489,7 +495,6 @@ __cpufreq_cooling_register(struct device_node *np,
                cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
                                          CPUFREQ_POLICY_NOTIFIER);
        cpufreq_dev_count++;
-       list_add(&cpufreq_dev->node, &cpufreq_dev_list);
 
        mutex_unlock(&cooling_cpufreq_lock);
 
@@ -553,7 +558,6 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
        cpufreq_dev = cdev->devdata;
        mutex_lock(&cooling_cpufreq_lock);
-       list_del(&cpufreq_dev->node);
        cpufreq_dev_count--;
 
        /* Unregister the notifier for the last cpufreq cooling device */

drivers/thermal/cpu_cooling.c void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) · line 575

Quoted 10 lines
drivers/thermal/cpu_cooling.c +4 -0
@@ -562,6 +566,10 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
                                            CPUFREQ_POLICY_NOTIFIER);
        mutex_unlock(&cooling_cpufreq_lock);
 
+       mutex_lock(&cooling_list_lock);
+       list_del(&cpufreq_dev->node);
+       mutex_unlock(&cooling_list_lock);
+
        thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
        release_idr(&cpufreq_idr, cpufreq_dev->id);
        kfree(cpufreq_dev);

For 3.18

#10 lore raw
Quoted 9 lines · Viresh Kumar
Quoted 3 lines · Russell King - ARM Linux

Well, here's a patch which I'm running on top of 3.18 at the moment, which is basically what I described in my email, and I'm running with it and it is without any lockdep complaint.

We need two separate patches now, one for 3.18 and other one for 3.19-rc. 3.19 has see lots of changes in this particular file and so we need to change few things here.

I'm sorry, I don't have the bandwidth to create a patch for 3.19-rc right now.

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
#11 lore raw
In reply to Viresh Kumar
Quoted 9 lines · Viresh Kumar
Quoted 3 lines · Russell King - ARM Linux

Well, here's a patch which I'm running on top of 3.18 at the moment, which is basically what I described in my email, and I'm running with it and it is without any lockdep complaint.

We need two separate patches now, one for 3.18 and other one for 3.19-rc. 3.19 has see lots of changes in this particular file and so we need to change few things here.

What happened with this? I'm still carrying the patch.

Quoted 102 lines
Quoted 88 lines

8<===
From: Russell King <[email protected]>
thermal: cpu_cooling: fix lockdep problems in cpu_cooling

A recent change to the cpu_cooling code introduced a AB-BA deadlock scenario between the cpufreq_policy_notifier_list rwsem and the cooling_cpufreq_lock. This is caused by cooling_cpufreq_lock being held before the registration/removal of the notifier block (an operation which takes the rwsem), and the notifier code itself which takes the locks in the reverse order.

Solve this by moving to finer grained locking - use one mutex to protect the cpufreq_dev_list as a whole, and a separate lock to ensure correct ordering of cpufreq notifier registration and removal.

I considered taking the cooling_list_lock within cooling_cpufreq_lock to protect the registration sequence as a whole, but that adds a dependency between these two locks which is best avoided (lest someone tries to take those two new locks in the reverse order.) In any case, it's safer to have an empty cpufreq_dev_list than to have unnecessary dependencies between locks.

Fixes 2dcd851fe4b4 ("thermal: cpu_cooling: Update always cpufreq policy with thermal constraints")

---

 drivers/thermal/cpu_cooling.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/thermal/cpu_cooling.c +8 -4
index ad09e51ffae4..9e42c6f30785 100644
@@ -57,6 +57,7 @@ static DEFINE_MUTEX(cooling_cpufreq_lock);
 
 static unsigned int cpufreq_dev_count;
 
+static DEFINE_MUTEX(cooling_list_lock);
 static LIST_HEAD(cpufreq_dev_list);
 
 /**
@@ -317,7 +318,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
        if (event != CPUFREQ_ADJUST)
                return 0;
 
-       mutex_lock(&cooling_cpufreq_lock);
+       mutex_lock(&cooling_list_lock);
        list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
                if (!cpumask_test_cpu(policy->cpu,
                                        &cpufreq_dev->allowed_cpus))
@@ -333,7 +334,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
                if (policy->max != max_freq)
                        cpufreq_verify_within_limits(policy, 0, max_freq);
        }
-       mutex_unlock(&cooling_cpufreq_lock);
+       mutex_unlock(&cooling_list_lock);
 
        return 0;
 }
@@ -482,6 +483,11 @@ __cpufreq_cooling_register(struct device_node *np,
        }
        cpufreq_dev->cool_dev = cool_dev;
        cpufreq_dev->cpufreq_state = 0;
+
+       mutex_lock(&cooling_list_lock);
+       list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+       mutex_unlock(&cooling_list_lock);
+
        mutex_lock(&cooling_cpufreq_lock);
 
        /* Register the notifier for first cpufreq cooling device */
@@ -489,7 +495,6 @@ __cpufreq_cooling_register(struct device_node *np,
                cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
                                          CPUFREQ_POLICY_NOTIFIER);
        cpufreq_dev_count++;
-       list_add(&cpufreq_dev->node, &cpufreq_dev_list);
 
        mutex_unlock(&cooling_cpufreq_lock);
 
@@ -553,7 +558,6 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
        cpufreq_dev = cdev->devdata;
        mutex_lock(&cooling_cpufreq_lock);
-       list_del(&cpufreq_dev->node);
        cpufreq_dev_count--;
 
        /* Unregister the notifier for the last cpufreq cooling device */

drivers/thermal/cpu_cooling.c void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) · line 575

Quoted 10 lines
drivers/thermal/cpu_cooling.c +4 -0
@@ -562,6 +566,10 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
                                            CPUFREQ_POLICY_NOTIFIER);
        mutex_unlock(&cooling_cpufreq_lock);
 
+       mutex_lock(&cooling_list_lock);
+       list_del(&cpufreq_dev->node);
+       mutex_unlock(&cooling_list_lock);
+
        thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
        release_idr(&cpufreq_idr, cpufreq_dev->id);
        kfree(cpufreq_dev);

For 3.18

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
#12 lore raw
Quoted 7 lines · Russell King - ARM Linux
Quoted 6 lines · Viresh Kumar
Quoted 3 lines · Russell King - ARM Linux

Well, here's a patch which I'm running on top of 3.18 at the moment, which is basically what I described in my email, and I'm running with it and it is without any lockdep complaint.

Quoted 5 lines
Quoted 3 lines

We need two separate patches now, one for 3.18 and other one for 3.19-rc. 3.19 has see lots of changes in this particular file and so we need to change few things here.

What happened with this? I'm still carrying the patch.

This should go in through the thermal tree. Eduardo?

Quoted 105 lines
Quoted 103 lines
Quoted 89 lines

8<===
From: Russell King <[email protected]>
thermal: cpu_cooling: fix lockdep problems in cpu_cooling

A recent change to the cpu_cooling code introduced a AB-BA deadlock scenario between the cpufreq_policy_notifier_list rwsem and the cooling_cpufreq_lock. This is caused by cooling_cpufreq_lock being held before the registration/removal of the notifier block (an operation which takes the rwsem), and the notifier code itself which takes the locks in the reverse order.

Solve this by moving to finer grained locking - use one mutex to protect the cpufreq_dev_list as a whole, and a separate lock to ensure correct ordering of cpufreq notifier registration and removal.

I considered taking the cooling_list_lock within cooling_cpufreq_lock to protect the registration sequence as a whole, but that adds a dependency between these two locks which is best avoided (lest someone tries to take those two new locks in the reverse order.) In any case, it's safer to have an empty cpufreq_dev_list than to have unnecessary dependencies between locks.

Fixes 2dcd851fe4b4 ("thermal: cpu_cooling: Update always cpufreq policy with thermal constraints")

---

 drivers/thermal/cpu_cooling.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/thermal/cpu_cooling.c +8 -4
index ad09e51ffae4..9e42c6f30785 100644
@@ -57,6 +57,7 @@ static DEFINE_MUTEX(cooling_cpufreq_lock);
 
 static unsigned int cpufreq_dev_count;
 
+static DEFINE_MUTEX(cooling_list_lock);
 static LIST_HEAD(cpufreq_dev_list);
 
 /**
@@ -317,7 +318,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
        if (event != CPUFREQ_ADJUST)
                return 0;
 
-       mutex_lock(&cooling_cpufreq_lock);
+       mutex_lock(&cooling_list_lock);
        list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
                if (!cpumask_test_cpu(policy->cpu,
                                        &cpufreq_dev->allowed_cpus))
@@ -333,7 +334,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
                if (policy->max != max_freq)
                        cpufreq_verify_within_limits(policy, 0, max_freq);
        }
-       mutex_unlock(&cooling_cpufreq_lock);
+       mutex_unlock(&cooling_list_lock);
 
        return 0;
 }
@@ -482,6 +483,11 @@ __cpufreq_cooling_register(struct device_node *np,
        }
        cpufreq_dev->cool_dev = cool_dev;
        cpufreq_dev->cpufreq_state = 0;
+
+       mutex_lock(&cooling_list_lock);
+       list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+       mutex_unlock(&cooling_list_lock);
+
        mutex_lock(&cooling_cpufreq_lock);
 
        /* Register the notifier for first cpufreq cooling device */
@@ -489,7 +495,6 @@ __cpufreq_cooling_register(struct device_node *np,
                cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
                                          CPUFREQ_POLICY_NOTIFIER);
        cpufreq_dev_count++;
-       list_add(&cpufreq_dev->node, &cpufreq_dev_list);
 
        mutex_unlock(&cooling_cpufreq_lock);
 
@@ -553,7 +558,6 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
        cpufreq_dev = cdev->devdata;
        mutex_lock(&cooling_cpufreq_lock);
-       list_del(&cpufreq_dev->node);
        cpufreq_dev_count--;
 
        /* Unregister the notifier for the last cpufreq cooling device */

drivers/thermal/cpu_cooling.c void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) · line 575

Quoted 10 lines
drivers/thermal/cpu_cooling.c +4 -0
@@ -562,6 +566,10 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
                                            CPUFREQ_POLICY_NOTIFIER);
        mutex_unlock(&cooling_cpufreq_lock);
 
+       mutex_lock(&cooling_list_lock);
+       list_del(&cpufreq_dev->node);
+       mutex_unlock(&cooling_list_lock);
+
        thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
        release_idr(&cpufreq_idr, cpufreq_dev->id);
        kfree(cpufreq_dev);

For 3.18

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#13 lore raw
Quoted 8 lines · Rafael J. Wysocki
Quoted 7 lines · Russell King - ARM Linux
Quoted 6 lines · Viresh Kumar
Quoted 3 lines · Russell King - ARM Linux

Well, here's a patch which I'm running on top of 3.18 at the moment, which is basically what I described in my email, and I'm running with it and it is without any lockdep complaint.

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines

We need two separate patches now, one for 3.18 and other one for 3.19-rc. 3.19 has see lots of changes in this particular file and so we need to change few things here.

What happened with this? I'm still carrying the patch.

This should go in through the thermal tree. Eduardo?

Having waited a long time for any kind of response from Eduardo, I've given up. My conclusion is that Eduardo isn't interested in this.

I've re-checked, and the AB-BA deadlock is still there in the latest code. So, I've taken it upon myself to throw this into my for-next branch to force the issue - not something I _want_ to do, but I'm doing this out of frustration. It's clear to me that "playing nice" by email does _not_ work with some people.

I'm rather hoping that Stephen reports a merge conflict with linux-next this evening to highlight this situation. I've added additional commentry to the commit message on the patch giving the reason why I've done this, and the relevant message IDs showing the past history.

I've not decided whether I'm going to ask Linus to take this patch directly or not, that rather depends whether there's any co-operation from Eduardo on this. I'd rather Eduardo took the patch.

The patch I have has had to be updated again for changes to the driver, but I really don't see the point of re-posting it just for it to be ignored yet again.

I'm really disappointed by this dysfunctional state of affairs, and that what should be an urgent fix for an observable problem is still not merged some nine months after it was first identified.

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
#14 lore raw
Quoted 5 lines · Russell King - ARM Linux
Quoted 4 lines · Rafael J. Wysocki
Quoted 3 lines · Russell King - ARM Linux
Quoted 2 lines · Viresh Kumar

On 16 December 2014 at 04:39, Russell King - ARM Linux <[email protected]> wrote:

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 3 lines

Well, here's a patch which I'm running on top of 3.18 at the moment, which is basically what I described in my email, and I'm running with it and it is without any lockdep complaint.

We need two separate patches now, one for 3.18 and other one for 3.19-rc. 3.19 has see lots of changes in this particular file and so we need to change few things here.

Was the patch for latest kernel ever circulated ? Probably that's why Eduardo never got back to it.

Signature · 1 line
viresh
#15 lore raw
Quoted 10 lines · Viresh Kumar
Quoted 9 lines · Russell King - ARM Linux
Quoted 8 lines · Rafael J. Wysocki
Quoted 7 lines · Russell King - ARM Linux
Quoted 6 lines · Viresh Kumar
Quoted 3 lines · Russell King - ARM Linux

Well, here's a patch which I'm running on top of 3.18 at the moment, which is basically what I described in my email, and I'm running with it and it is without any lockdep complaint.

Quoted 6 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

We need two separate patches now, one for 3.18 and other one for 3.19-rc. 3.19 has see lots of changes in this particular file and so we need to change few things here.

Was the patch for latest kernel ever circulated ? Probably that's why Eduardo never got back to it.

Maybe not - I often lose track of which patches are in what state - tracking the state of 250+ patches over many months and in some cases _years_ is not easy.

That's still no reason for Eduardo to _completely_ ignore this thread, especially when Rafael explicitly tried to get comment from Eduardo.

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
#16 lore raw
Quoted 3 lines · Russell King - ARM Linux

Maybe not - I often lose track of which patches are in what state - tracking the state of 250+ patches over many months and in some cases _years_ is not easy.

I agree..

Quoted 2 lines

That's still no reason for Eduardo to _completely_ ignore this thread, especially when Rafael explicitly tried to get comment from Eduardo.

Oh, no. I am not trying to be anybody's advocate here. I was just highlighting the point here, that I remembered.

Even I was quite busy then and couldn't get back to it.

Lets fix this now. I believe you have a patch for this based on latest kernel? Mind pasting that here for quick review?

Signature · 1 line
viresh
#17 lore raw

PATCH 1/1 thermal: cpu_cooling: fix lockdep problems in cpu_cooling

A recent change to the cpu_cooling code introduced a AB-BA deadlock scenario between the cpufreq_policy_notifier_list rwsem and the cooling_cpufreq_lock. This is caused by cooling_cpufreq_lock being held before the registration/removal of the notifier block (an operation which takes the rwsem), and the notifier code itself which takes the locks in the reverse order:

======================================================
[ INFO: possible circular locking dependency detected ]
3.18.0+ #1453 Not tainted
-------------------------------------------------------
rc.local/770 is trying to acquire lock:
(cooling_cpufreq_lock){+.+.+.}, at: [<c04abfc4>] cpufreq_thermal_notifier+0x34/0xfc

but task is already holding lock:
((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>] __blocking_notifier_call_chain+0x34/0x68

which lock already depends on the new lock.

the existing dependency chain (in reverse order) is:

-> #1 ((cpufreq_policy_notifier_list).rwsem){++++.+}:

       [<c06bc3b0>] down_write+0x44/0x9c
       [<c0043444>] blocking_notifier_chain_register+0x28/0xd8
       [<c04ad610>] cpufreq_register_notifier+0x68/0x90
       [<c04abe4c>] __cpufreq_cooling_register.part.1+0x120/0x180
       [<c04abf44>] __cpufreq_cooling_register+0x98/0xa4
       [<c04abf8c>] cpufreq_cooling_register+0x18/0x1c
       [<bf0046f8>] imx_thermal_probe+0x1c0/0x470 [imx_thermal]
       [<c037cef8>] platform_drv_probe+0x50/0xac
       [<c037b710>] driver_probe_device+0x114/0x234
       [<c037b8cc>] __driver_attach+0x9c/0xa0
       [<c0379d68>] bus_for_each_dev+0x5c/0x90
       [<c037b204>] driver_attach+0x24/0x28
       [<c037ae7c>] bus_add_driver+0xe0/0x1d8
       [<c037c0cc>] driver_register+0x80/0xfc
       [<c037cd80>] __platform_driver_register+0x50/0x64
       [<bf007018>] 0xbf007018
       [<c0008a5c>] do_one_initcall+0x88/0x1d8
       [<c0095da4>] load_module+0x1768/0x1ef8
       [<c0096614>] SyS_init_module+0xe0/0xf4
       [<c000ec00>] ret_fast_syscall+0x0/0x48

-> #0 (cooling_cpufreq_lock){+.+.+.}:

       [<c00619f8>] lock_acquire+0xb0/0x124
       [<c06ba3b4>] mutex_lock_nested+0x5c/0x3d8
       [<c04abfc4>] cpufreq_thermal_notifier+0x34/0xfc
       [<c0042bf4>] notifier_call_chain+0x4c/0x8c
       [<c0042f20>] __blocking_notifier_call_chain+0x50/0x68
       [<c0042f58>] blocking_notifier_call_chain+0x20/0x28
       [<c04ae62c>] cpufreq_set_policy+0x7c/0x1d0
       [<c04af3cc>] store_scaling_governor+0x74/0x9c
       [<c04ad418>] store+0x90/0xc0
       [<c0175384>] sysfs_kf_write+0x54/0x58
       [<c01746b4>] kernfs_fop_write+0xdc/0x190
       [<c010dcc0>] vfs_write+0xac/0x1b4
       [<c010dfec>] SyS_write+0x44/0x90
       [<c000ec00>] ret_fast_syscall+0x0/0x48

other info that might help us debug this:

 Possible unsafe locking scenario:
       CPU0                    CPU1
       ----                    ----
  lock((cpufreq_policy_notifier_list).rwsem);
                               lock(cooling_cpufreq_lock);
                               lock((cpufreq_policy_notifier_list).rwsem);

lock(cooling_cpufreq_lock);

*** DEADLOCK ***

7 locks held by rc.local/770:

 #0:  (sb_writers#6){.+.+.+}, at: [<c010dda0>] vfs_write+0x18c/0x1b4
 #1:  (&of->mutex){+.+.+.}, at: [<c0174678>] kernfs_fop_write+0xa0/0x190
 #2:  (s_active#52){.+.+.+}, at: [<c0174680>] kernfs_fop_write+0xa8/0x190
 #3:  (cpu_hotplug.lock){++++++}, at: [<c0026a60>] get_online_cpus+0x34/0x90
 #4:  (cpufreq_rwsem){.+.+.+}, at: [<c04ad3e0>] store+0x58/0xc0
 #5:  (&policy->rwsem){+.+.+.}, at: [<c04ad3f8>] store+0x70/0xc0
 #6:  ((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>] __blocking_notifier_call_chain+0x34/0x68
stack backtrace:
CPU: 0 PID: 770 Comm: rc.local Not tainted 3.18.0+ #1453
Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
Backtrace:
[<c00121c8>] (dump_backtrace) from [<c0012360>] (show_stack+0x18/0x1c)
 r6:c0b85a80 r5:c0b75630 r4:00000000 r3:00000000
[<c0012348>] (show_stack) from [<c06b6c48>] (dump_stack+0x7c/0x98)
[<c06b6bcc>] (dump_stack) from [<c06b42a4>] (print_circular_bug+0x28c/0x2d8)
 r4:c0b85a80 r3:d0071d40
[<c06b4018>] (print_circular_bug) from [<c00613b0>] (__lock_acquire+0x1acc/0x1bb0)
 r10:c0b50660 r8:c09e6d80 r7:d0071d40 r6:c11d0f0c r5:00000007 r4:d0072240
[<c005f8e4>] (__lock_acquire) from [<c00619f8>] (lock_acquire+0xb0/0x124)
 r10:00000000 r9:c04abfc4 r8:00000000 r7:00000000 r6:00000000 r5:c0a06f0c
 r4:00000000
[<c0061948>] (lock_acquire) from [<c06ba3b4>] (mutex_lock_nested+0x5c/0x3d8)
 r10:ec853800 r9:c0a06ed4 r8:d0071d40 r7:c0a06ed4 r6:c11d0f0c r5:00000000
 r4:c04abfc4
[<c06ba358>] (mutex_lock_nested) from [<c04abfc4>] (cpufreq_thermal_notifier+0x34/0xfc)
 r10:ec853800 r9:ec85380c r8:d00d7d3c r7:c0a06ed4 r6:d00d7d3c r5:00000000
 r4:fffffffe
[<c04abf90>] (cpufreq_thermal_notifier) from [<c0042bf4>] (notifier_call_chain+0x4c/0x8c)
 r7:00000000 r6:00000000 r5:00000000 r4:fffffffe
[<c0042ba8>] (notifier_call_chain) from [<c0042f20>] (__blocking_notifier_call_chain+0x50/0x68)
 r8:c0a072a4 r7:00000000 r6:d00d7d3c r5:ffffffff r4:c0a06fc8 r3:ffffffff
[<c0042ed0>] (__blocking_notifier_call_chain) from [<c0042f58>] (blocking_notifier_call_chain+0x20/0x28)
 r7:ec98b540 r6:c13ebc80 r5:ed76e600 r4:d00d7d3c
[<c0042f38>] (blocking_notifier_call_chain) from [<c04ae62c>] (cpufreq_set_policy+0x7c/0x1d0)
[<c04ae5b0>] (cpufreq_set_policy) from [<c04af3cc>] (store_scaling_governor+0x74/0x9c)
 r7:ec98b540 r6:0000000c r5:ec98b540 r4:ed76e600
[<c04af358>] (store_scaling_governor) from [<c04ad418>] (store+0x90/0xc0)
 r6:0000000c r5:ed76e6d4 r4:ed76e600
[<c04ad388>] (store) from [<c0175384>] (sysfs_kf_write+0x54/0x58)
 r8:0000000c r7:d00d7f78 r6:ec98b540 r5:0000000c r4:ec853800 r3:0000000c
[<c0175330>] (sysfs_kf_write) from [<c01746b4>] (kernfs_fop_write+0xdc/0x190)
 r6:ec98b540 r5:00000000 r4:00000000 r3:c0175330
[<c01745d8>] (kernfs_fop_write) from [<c010dcc0>] (vfs_write+0xac/0x1b4)
 r10:0162aa70 r9:d00d6000 r8:0000000c r7:d00d7f78 r6:0162aa70 r5:0000000c
 r4:eccde500
[<c010dc14>] (vfs_write) from [<c010dfec>] (SyS_write+0x44/0x90)
 r10:0162aa70 r8:0000000c r7:eccde500 r6:eccde500 r5:00000000 r4:00000000
[<c010dfa8>] (SyS_write) from [<c000ec00>] (ret_fast_syscall+0x0/0x48)
 r10:00000000 r8:c000edc4 r7:00000004 r6:000216cc r5:0000000c r4:0162aa70

Solve this by moving to finer grained locking - use one mutex to protect the cpufreq_dev_list as a whole, and a separate lock to ensure correct ordering of cpufreq notifier registration and removal.

I considered taking the cooling_list_lock within cooling_cpufreq_lock to protect the registration sequence as a whole, but that adds a dependency between these two locks which is best avoided (lest someone tries to take those two new locks in the reverse order.) In any case, it's safer to have an empty cpufreq_dev_list than to have unnecessary dependencies between locks.

Fixes 2dcd851fe4b4 ("thermal: cpu_cooling: Update always cpufreq policy with

For some reason, despite Rafael saying that this should go in, despite it having been reviewed, Eduardo appears to be ignoring basic fixes to code under his control. Having waited more than a reasonable amount of time, it is now time to take some action against this blockage. Hence, I'm putting this into linux-next in the hope that it'll conflict and elicit a response for this important bug fix.

Relevant message IDs:
20141214213655.GA11285 at n2100.arm.linux.org.uk 7573578.UE8ufgjWuX at vostro.rjw.lan 20141215230922.GL11285 at n2100.arm.linux.org.uk CAKohponhkk9BK6-7ScHeZa4R43iooWQFV8YoPLv6LjO40GNq=A at mail.gmail.com 20150518185645.GA28053 at n2100.arm.linux.org.uk 2574268.XBqpdL2VLI at vostro.rjw.lan

---
 drivers/thermal/cpu_cooling.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)
drivers/thermal/cpu_cooling.c +16 -6
index 6509c61b9648..d1fd02eec58d 100644
@@ -107,6 +107,9 @@ struct cpufreq_cooling_device {
 static DEFINE_IDR(cpufreq_idr);
 static DEFINE_MUTEX(cooling_cpufreq_lock);
 
+static unsigned int cpufreq_dev_count;
+
+static DEFINE_MUTEX(cooling_list_lock);
 static LIST_HEAD(cpufreq_dev_list);
 
 /**
@@ -221,7 +224,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 	switch (event) {
 
 	case CPUFREQ_ADJUST:
-		mutex_lock(&cooling_cpufreq_lock);
+		mutex_lock(&cooling_list_lock);
 		list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
 			if (!cpumask_test_cpu(policy->cpu,
 					      &cpufreq_dev->allowed_cpus))
@@ -233,7 +236,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 				cpufreq_verify_within_limits(policy, 0,
 							     max_freq);
 		}
-		mutex_unlock(&cooling_cpufreq_lock);
+		mutex_unlock(&cooling_list_lock);
 		break;
 	default:
 		return NOTIFY_DONE;
@@ -865,12 +868,15 @@ __cpufreq_cooling_register(struct device_node *np,
 	cpufreq_dev->cool_dev = cool_dev;
 
 	mutex_lock(&cooling_cpufreq_lock);
+	mutex_lock(&cooling_list_lock);
+	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+	mutex_unlock(&cooling_list_lock);
 
 	/* Register the notifier for first cpufreq cooling device */
-	if (list_empty(&cpufreq_dev_list))
+	if (cpufreq_dev_count == 0)
 		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
 					  CPUFREQ_POLICY_NOTIFIER);
-	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+	cpufreq_dev_count++;
 
 	mutex_unlock(&cooling_cpufreq_lock);
 
@@ -1014,14 +1020,18 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
 	cpufreq_dev = cdev->devdata;
 	mutex_lock(&cooling_cpufreq_lock);
-	list_del(&cpufreq_dev->node);
+	cpufreq_dev_count--;
 
 	/* Unregister the notifier for the last cpufreq cooling device */
-	if (list_empty(&cpufreq_dev_list))
+	if (cpufreq_dev_count == 0)
 		cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
 					    CPUFREQ_POLICY_NOTIFIER);
 	mutex_unlock(&cooling_cpufreq_lock);
 
+	mutex_lock(&cooling_list_lock);
+	list_del(&cpufreq_dev->node);
+	mutex_unlock(&cooling_list_lock);
+
 	thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
 	release_idr(&cpufreq_idr, cpufreq_dev->id);
 	kfree(cpufreq_dev->time_in_idle_timestamp);
Signature · 1 line
2.1.0
#18 lore raw

PATCH 1/1 thermal: cpu_cooling: fix lockdep problems in cpu_cooling

drivers/thermal/cpu_cooling.c static int cpufreq_thermal_notifier(struct notifier_block *nb, · line 227

Quoted 8 lines · Russell King
drivers/thermal/cpu_cooling.c +1 -1
 /**
@@ -221,7 +224,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 	switch (event) {
 
 	case CPUFREQ_ADJUST:
-		mutex_lock(&cooling_cpufreq_lock);
+		mutex_lock(&cooling_list_lock);

There is one more place where the list's locking needs update:
cpufreq_cooling_get_level().

Quoted 13 lines
drivers/thermal/cpu_cooling.c +1 -1
 		list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
 			if (!cpumask_test_cpu(policy->cpu,
 					      &cpufreq_dev->allowed_cpus))
@@ -233,7 +236,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 				cpufreq_verify_within_limits(policy, 0,
 							     max_freq);
 		}
-		mutex_unlock(&cooling_cpufreq_lock);
+		mutex_unlock(&cooling_list_lock);
 		break;
 	default:
 		return NOTIFY_DONE;

drivers/thermal/cpu_cooling.c __cpufreq_cooling_register(struct device_node *np, · line 871

Quoted 4 lines
drivers/thermal/cpu_cooling.c +1 -0
@@ -865,12 +868,15 @@ __cpufreq_cooling_register(struct device_node *np,
 	cpufreq_dev->cool_dev = cool_dev;
 
 	mutex_lock(&cooling_cpufreq_lock);
+	mutex_lock(&cooling_list_lock);

Why is the list lock taken from within the existing lock here? and ...

drivers/thermal/cpu_cooling.c __cpufreq_cooling_register(struct device_node *np, · line 879

Quoted 10 lines
drivers/thermal/cpu_cooling.c +4 -2
+	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+	mutex_unlock(&cooling_list_lock);
 
 	/* Register the notifier for first cpufreq cooling device */
-	if (list_empty(&cpufreq_dev_list))
+	if (cpufreq_dev_count == 0)
 		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
 					  CPUFREQ_POLICY_NOTIFIER);
-	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+	cpufreq_dev_count++;

Maybe:

        if (!cpufreq_dev_count++)
                cpufreq_register_notifier();

drivers/thermal/cpu_cooling.c void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) · line 1026

Quoted 13 lines
drivers/thermal/cpu_cooling.c +2 -2
 	mutex_unlock(&cooling_cpufreq_lock);
 
@@ -1014,14 +1020,18 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
 	cpufreq_dev = cdev->devdata;
 	mutex_lock(&cooling_cpufreq_lock);
-	list_del(&cpufreq_dev->node);
+	cpufreq_dev_count--;
 
 	/* Unregister the notifier for the last cpufreq cooling device */
-	if (list_empty(&cpufreq_dev_list))
+	if (cpufreq_dev_count == 0)

Maybe:

        if (!--cpufreq_dev_count)
                cpufreq_register_notifier();

drivers/thermal/cpu_cooling.c void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) · line 1031

Quoted 5 lines
drivers/thermal/cpu_cooling.c +1 -0
 		cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
 					    CPUFREQ_POLICY_NOTIFIER);
 	mutex_unlock(&cooling_cpufreq_lock);
 
+	mutex_lock(&cooling_list_lock);

... The same list lock is not taken from within the earlier critical section?

Quoted 8 lines
drivers/thermal/cpu_cooling.c +3 -0
+	list_del(&cpufreq_dev->node);
+	mutex_unlock(&cooling_list_lock);
+
 	thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
 	release_idr(&cpufreq_idr, cpufreq_dev->id);
 	kfree(cpufreq_dev->time_in_idle_timestamp);
Signature · 1 line
2.1.0
Signature · 1 line
viresh
#19 lore raw

PATCH 1/1 thermal: cpu_cooling: fix lockdep problems in cpu_cooling

Quoted 28 lines · Viresh Kumar

drivers/thermal/cpu_cooling.c static int cpufreq_thermal_notifier(struct notifier_block *nb, · line 227

Quoted 8 lines · Russell King
drivers/thermal/cpu_cooling.c +1 -1
 /**
@@ -221,7 +224,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 	switch (event) {
 
 	case CPUFREQ_ADJUST:
-		mutex_lock(&cooling_cpufreq_lock);
+		mutex_lock(&cooling_list_lock);

There is one more place where the list's locking needs update:
cpufreq_cooling_get_level().

Quoted 15 lines
drivers/thermal/cpu_cooling.c +1 -1
 		list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
 			if (!cpumask_test_cpu(policy->cpu,
 					      &cpufreq_dev->allowed_cpus))
@@ -233,7 +236,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 				cpufreq_verify_within_limits(policy, 0,
 							     max_freq);
 		}
-		mutex_unlock(&cooling_cpufreq_lock);
+		mutex_unlock(&cooling_list_lock);
 		break;
 	default:
 		return NOTIFY_DONE;
@@ -865,12 +868,15 @@ __cpufreq_cooling_register(struct device_node *np,
 	cpufreq_dev->cool_dev = cool_dev;
 
Quoted 4 lines

drivers/thermal/cpu_cooling.c __cpufreq_cooling_register(struct device_node *np, · line 871

Quoted 2 lines
drivers/thermal/cpu_cooling.c +1 -0
 	mutex_lock(&cooling_cpufreq_lock);
+	mutex_lock(&cooling_list_lock);

Why is the list lock taken from within the existing lock here? and ...

To preserve the behaviour of the code, which is to atomically add to the list and register the notifier.

Quoted 12 lines

drivers/thermal/cpu_cooling.c __cpufreq_cooling_register(struct device_node *np, · line 879

Quoted 10 lines
drivers/thermal/cpu_cooling.c +4 -2
+	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+	mutex_unlock(&cooling_list_lock);
 
 	/* Register the notifier for first cpufreq cooling device */
-	if (list_empty(&cpufreq_dev_list))
+	if (cpufreq_dev_count == 0)
 		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
 					  CPUFREQ_POLICY_NOTIFIER);
-	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+	cpufreq_dev_count++;

Maybe:

Quoted 2 lines
        if (!cpufreq_dev_count++)
                cpufreq_register_notifier();

Possibly, had the code previously been like that. See:

commit 2479bb6443d6a793f896219a34bfab0cc410f0b4

Author: Viresh Kumar <[email protected]>
Date:   Thu Dec 4 09:42:04 2014 +0530

which post-dates this patch, and removes this "style" in favour of using the broken list mechanism. Frankly... you don't have a leg to stand on because _you_ knew about this problem, and you saw my patch. So removing something that my patch to fix a serious bug relied upon...

You know what? At this point, I'm just not going to bother. You fix this lockdep problem, I'm obviously useless at kernel stuff.

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
#20 lore raw

PATCH 1/1 thermal: cpu_cooling: fix lockdep problems in cpu_cooling

Quoted 8 lines · Russell King - ARM Linux

Possibly, had the code previously been like that. See:

commit 2479bb6443d6a793f896219a34bfab0cc410f0b4

Author: Viresh Kumar <[email protected]>
Date:   Thu Dec 4 09:42:04 2014 +0530

which post-dates this patch, and removes this "style" in favour of using the broken list mechanism.

Just to make sure I understand it properly, do you want to say that I added 2479bb6 patch after you reported this problem & your patch?

If yes, then I don't see how my patch came after yours. Mine was written on 4/Dec/2014 and committed on 8/Dec/2014 and you first reported the problem on 14/Dec/2014.

Quoted 1 line

Frankly... you don't have a leg to stand on

I can accept that :)

Quoted 2 lines

because _you_ knew about this problem, and you saw my patch. So removing something that my patch to fix a serious bug relied upon...

I don't think I removed that stuff after your patch.

Quoted 2 lines

You know what? At this point, I'm just not going to bother. You fix this lockdep problem, I'm obviously useless at kernel stuff.

Okay, leave it on me. I will re-circulate your patch.

Signature · 1 line
viresh
#21 lore raw

PATCH 1/1 thermal: cpu_cooling: fix lockdep problems in cpu_cooling

In reply to Russell King

Hi Russell,

On Wed, Aug 12, 2015 at 08:41:49AM +0100, Russell King wrote:

<cut>

Quoted 7 lines

For some reason, despite Rafael saying that this should go in, despite it having been reviewed, Eduardo appears to be ignoring basic fixes to code under his control. Having waited more than a reasonable amount of time, it is now time to take some action against this blockage. Hence, I'm putting this into linux-next in the hope that it'll conflict and elicit a response for this important bug fix.

Sorry if I let this one to fall into the cracks for this long.

I am looking at this now and queuing as soon as possible.

Thanks for pushing this fix.

BR,

Eduardo

Quoted 86 lines

Relevant message IDs:
20141214213655.GA11285 at n2100.arm.linux.org.uk 7573578.UE8ufgjWuX at vostro.rjw.lan 20141215230922.GL11285 at n2100.arm.linux.org.uk CAKohponhkk9BK6-7ScHeZa4R43iooWQFV8YoPLv6LjO40GNq=A at mail.gmail.com 20150518185645.GA28053 at n2100.arm.linux.org.uk 2574268.XBqpdL2VLI at vostro.rjw.lan

---
 drivers/thermal/cpu_cooling.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)
drivers/thermal/cpu_cooling.c +16 -6
index 6509c61b9648..d1fd02eec58d 100644
@@ -107,6 +107,9 @@ struct cpufreq_cooling_device {
 static DEFINE_IDR(cpufreq_idr);
 static DEFINE_MUTEX(cooling_cpufreq_lock);
 
+static unsigned int cpufreq_dev_count;
+
+static DEFINE_MUTEX(cooling_list_lock);
 static LIST_HEAD(cpufreq_dev_list);
 
 /**
@@ -221,7 +224,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 	switch (event) {
 
 	case CPUFREQ_ADJUST:
-		mutex_lock(&cooling_cpufreq_lock);
+		mutex_lock(&cooling_list_lock);
 		list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
 			if (!cpumask_test_cpu(policy->cpu,
 					      &cpufreq_dev->allowed_cpus))
@@ -233,7 +236,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 				cpufreq_verify_within_limits(policy, 0,
 							     max_freq);
 		}
-		mutex_unlock(&cooling_cpufreq_lock);
+		mutex_unlock(&cooling_list_lock);
 		break;
 	default:
 		return NOTIFY_DONE;
@@ -865,12 +868,15 @@ __cpufreq_cooling_register(struct device_node *np,
 	cpufreq_dev->cool_dev = cool_dev;
 
 	mutex_lock(&cooling_cpufreq_lock);
+	mutex_lock(&cooling_list_lock);
+	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+	mutex_unlock(&cooling_list_lock);
 
 	/* Register the notifier for first cpufreq cooling device */
-	if (list_empty(&cpufreq_dev_list))
+	if (cpufreq_dev_count == 0)
 		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
 					  CPUFREQ_POLICY_NOTIFIER);
-	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+	cpufreq_dev_count++;
 
 	mutex_unlock(&cooling_cpufreq_lock);
 
@@ -1014,14 +1020,18 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
 	cpufreq_dev = cdev->devdata;
 	mutex_lock(&cooling_cpufreq_lock);
-	list_del(&cpufreq_dev->node);
+	cpufreq_dev_count--;
 
 	/* Unregister the notifier for the last cpufreq cooling device */
-	if (list_empty(&cpufreq_dev_list))
+	if (cpufreq_dev_count == 0)
 		cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
 					    CPUFREQ_POLICY_NOTIFIER);
 	mutex_unlock(&cooling_cpufreq_lock);
 
+	mutex_lock(&cooling_list_lock);
+	list_del(&cpufreq_dev->node);
+	mutex_unlock(&cooling_list_lock);
+
 	thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
 	release_idr(&cpufreq_idr, cpufreq_dev->id);
 	kfree(cpufreq_dev->time_in_idle_timestamp);
Signature · 1 line
2.1.0
#22 lore raw

PATCH 1/1 thermal: cpu_cooling: fix lockdep problems in cpu_cooling

Quoted 3 lines · Eduardo Valentin

Sorry if I let this one to fall into the cracks for this long.

I am looking at this now and queuing as soon as possible.

You applied the wrong one, please drop it. And apply the one I have sent as a separate thread, with my sob on it.

Signature · 1 line
viresh
#23 lore raw

PATCH 1/1 thermal: cpu_cooling: fix lockdep problems in cpu_cooling

Quoted 7 lines · Viresh Kumar
Quoted 3 lines · Eduardo Valentin

Sorry if I let this one to fall into the cracks for this long.

I am looking at this now and queuing as soon as possible.

You applied the wrong one, please drop it. And apply the one I have sent as a separate thread, with my sob on it.

OK. I am updating it to your V2.

Quoted 3 lines
Signature · 2 lines
-- 
viresh

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150814/825916ac/attachment.sig>

#24 lore raw

PATCH 1/1 thermal: cpu_cooling: fix lockdep problems in cpu_cooling

Quoted 10 lines · Eduardo Valentin
Quoted 7 lines · Viresh Kumar
Quoted 3 lines · Eduardo Valentin

Sorry if I let this one to fall into the cracks for this long.

I am looking at this now and queuing as soon as possible.

You applied the wrong one, please drop it. And apply the one I have sent as a separate thread, with my sob on it.

OK. I am updating it to your V2.

Looks fine now.

Signature · 1 line
viresh
#25 lore raw
In reply to Viresh Kumar
Quoted 10 lines · Viresh Kumar
Quoted 3 lines · Russell King - ARM Linux

Maybe not - I often lose track of which patches are in what state - tracking the state of 250+ patches over many months and in some cases _years_ is not easy.

I agree..

Quoted 2 lines

That's still no reason for Eduardo to _completely_ ignore this thread, especially when Rafael explicitly tried to get comment from Eduardo.

Quoted 7 lines

Oh, no. I am not trying to be anybody's advocate here. I was just highlighting the point here, that I remembered.

Even I was quite busy then and couldn't get back to it.

Lets fix this now. I believe you have a patch for this based on latest kernel? Mind pasting that here for quick review?

I don't think it's changed much since the original, but I've posted what's in linux-next as of today, and it doesn't conflict with anything. So there's no excuse about getting it merged.

The problem will be back-porting it to stable kernels, because I think it's had to be updated at least a couple of times. I don't have the old versions anymore, so I'm just going to say "not my problem" - sorry.

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
#26 lore raw
Quoted 3 lines · Russell King - ARM Linux

The problem will be back-porting it to stable kernels, because I think it's had to be updated at least a couple of times. I don't have the old versions anymore, so I'm just going to say "not my problem" - sorry.

Your old 3.18 version :)

8<===
From: Russell King <[email protected]>
thermal: cpu_cooling: fix lockdep problems in cpu_cooling

A recent change to the cpu_cooling code introduced a AB-BA deadlock scenario between the cpufreq_policy_notifier_list rwsem and the cooling_cpufreq_lock. This is caused by cooling_cpufreq_lock being held before the registration/removal of the notifier block (an operation which takes the rwsem), and the notifier code itself which takes the locks in the reverse order.

Solve this by moving to finer grained locking - use one mutex to protect the cpufreq_dev_list as a whole, and a separate lock to ensure correct ordering of cpufreq notifier registration and removal.

I considered taking the cooling_list_lock within cooling_cpufreq_lock to protect the registration sequence as a whole, but that adds a dependency between these two locks which is best avoided (lest someone tries to take those two new locks in the reverse order.) In any case, it's safer to have an empty cpufreq_dev_list than to have unnecessary dependencies between locks.

Fixes 2dcd851fe4b4 ("thermal: cpu_cooling: Update always cpufreq policy with thermal constraints")

---

 drivers/thermal/cpu_cooling.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/thermal/cpu_cooling.c +12 -4
index ad09e51ffae4..9e42c6f30785 100644
@@ -57,6 +57,7 @@ static DEFINE_MUTEX(cooling_cpufreq_lock);
 
 static unsigned int cpufreq_dev_count;
 
+static DEFINE_MUTEX(cooling_list_lock);
 static LIST_HEAD(cpufreq_dev_list);
 
 /**
@@ -317,7 +318,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 	if (event != CPUFREQ_ADJUST)
 		return 0;
 
-	mutex_lock(&cooling_cpufreq_lock);
+	mutex_lock(&cooling_list_lock);
 	list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
 		if (!cpumask_test_cpu(policy->cpu,
 					&cpufreq_dev->allowed_cpus))
@@ -333,7 +334,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 		if (policy->max != max_freq)
 			cpufreq_verify_within_limits(policy, 0, max_freq);
 	}
-	mutex_unlock(&cooling_cpufreq_lock);
+	mutex_unlock(&cooling_list_lock);
 
 	return 0;
 }
@@ -482,6 +483,11 @@ __cpufreq_cooling_register(struct device_node *np,
 	}
 	cpufreq_dev->cool_dev = cool_dev;
 	cpufreq_dev->cpufreq_state = 0;
+
+	mutex_lock(&cooling_list_lock);
+	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+	mutex_unlock(&cooling_list_lock);
+
 	mutex_lock(&cooling_cpufreq_lock);
 
 	/* Register the notifier for first cpufreq cooling device */
@@ -489,7 +495,6 @@ __cpufreq_cooling_register(struct device_node *np,
 		cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
 					  CPUFREQ_POLICY_NOTIFIER);
 	cpufreq_dev_count++;
-	list_add(&cpufreq_dev->node, &cpufreq_dev_list);
 
 	mutex_unlock(&cooling_cpufreq_lock);
 
@@ -553,7 +558,6 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
 	cpufreq_dev = cdev->devdata;
 	mutex_lock(&cooling_cpufreq_lock);
-	list_del(&cpufreq_dev->node);
 	cpufreq_dev_count--;
 
 	/* Unregister the notifier for the last cpufreq cooling device */
@@ -562,6 +566,10 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 					    CPUFREQ_POLICY_NOTIFIER);
 	mutex_unlock(&cooling_cpufreq_lock);
 
+	mutex_lock(&cooling_list_lock);
+	list_del(&cpufreq_dev->node);
+	mutex_unlock(&cooling_list_lock);
+
 	thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
 	release_idr(&cpufreq_idr, cpufreq_dev->id);
 	kfree(cpufreq_dev);
#27 lore raw
Quoted 6 lines · Viresh Kumar
Quoted 3 lines · Russell King - ARM Linux

The problem will be back-porting it to stable kernels, because I think it's had to be updated at least a couple of times. I don't have the old versions anymore, so I'm just going to say "not my problem" - sorry.

Your old 3.18 version :)

And now generate versions for all the stable kernels inbetween. Now your problem. I'm sick of this.

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
#28 lore raw
Quoted 2 lines · Russell King - ARM Linux

And now generate versions for all the stable kernels inbetween. Now your problem. I'm sick of this.

Haha.. There wouldn't be many. 3.19 got large number of changes (from me) and so we required a newer version. But after that should be somewhat stable.

Signature · 1 line
viresh
#29 lore raw
In reply to Russell King - ARM Linux
Quoted 35 lines · Russell King - ARM Linux
Quoted 8 lines · Rafael J. Wysocki
Quoted 7 lines · Russell King - ARM Linux
Quoted 6 lines · Viresh Kumar
Quoted 3 lines · Russell King - ARM Linux

Well, here's a patch which I'm running on top of 3.18 at the moment, which is basically what I described in my email, and I'm running with it and it is without any lockdep complaint.

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines

We need two separate patches now, one for 3.18 and other one for 3.19-rc. 3.19 has see lots of changes in this particular file and so we need to change few things here.

What happened with this? I'm still carrying the patch.

This should go in through the thermal tree. Eduardo?

Having waited a long time for any kind of response from Eduardo, I've given up. My conclusion is that Eduardo isn't interested in this.

I've re-checked, and the AB-BA deadlock is still there in the latest code. So, I've taken it upon myself to throw this into my for-next branch to force the issue - not something I _want_ to do, but I'm doing this out of frustration. It's clear to me that "playing nice" by email does _not_ work with some people.

I'm rather hoping that Stephen reports a merge conflict with linux-next this evening to highlight this situation. I've added additional commentry to the commit message on the patch giving the reason why I've done this, and the relevant message IDs showing the past history.

I've not decided whether I'm going to ask Linus to take this patch directly or not, that rather depends whether there's any co-operation from Eduardo on this. I'd rather Eduardo took the patch.

Quoted 7 lines

The patch I have has had to be updated again for changes to the driver, but I really don't see the point of re-posting it just for it to be ignored yet again.

I'm really disappointed by this dysfunctional state of affairs, and that what should be an urgent fix for an observable problem is still not merged some nine months after it was first identified.

I guess it might help if you sent the updated patch in a new thread.

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#30 lore raw
Quoted 40 lines · Rafael J. Wysocki
Quoted 39 lines · Russell King - ARM Linux
Quoted 8 lines · Rafael J. Wysocki
Quoted 7 lines · Russell King - ARM Linux
Quoted 6 lines · Viresh Kumar
Quoted 3 lines · Russell King - ARM Linux

Well, here's a patch which I'm running on top of 3.18 at the moment, which is basically what I described in my email, and I'm running with it and it is without any lockdep complaint.

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines

We need two separate patches now, one for 3.18 and other one for 3.19-rc. 3.19 has see lots of changes in this particular file and so we need to change few things here.

What happened with this? I'm still carrying the patch.

This should go in through the thermal tree. Eduardo?

Having waited a long time for any kind of response from Eduardo, I've given up. My conclusion is that Eduardo isn't interested in this.

I've re-checked, and the AB-BA deadlock is still there in the latest code. So, I've taken it upon myself to throw this into my for-next branch to force the issue - not something I _want_ to do, but I'm doing this out of frustration. It's clear to me that "playing nice" by email does _not_ work with some people.

I'm rather hoping that Stephen reports a merge conflict with linux-next this evening to highlight this situation. I've added additional commentry to the commit message on the patch giving the reason why I've done this, and the relevant message IDs showing the past history.

I've not decided whether I'm going to ask Linus to take this patch directly or not, that rather depends whether there's any co-operation from Eduardo on this. I'd rather Eduardo took the patch.

The patch I have has had to be updated again for changes to the driver, but I really don't see the point of re-posting it just for it to be ignored yet again.

Quoted 5 lines
Quoted 3 lines

I'm really disappointed by this dysfunctional state of affairs, and that what should be an urgent fix for an observable problem is still not merged some nine months after it was first identified.

I guess it might help if you sent the updated patch in a new thread.

That I doubt. Eduardo has not bothered to reply at _any_ time. I have to question whether there is anyone even reading that email address, or whether it's a redirect to /dev/null. All the evidence I have right now is that this Eduardo is a ficticous character.

I would have at least expected some complaints when I said "I've put it in linux-next" but... absolutely nothing.

So... my only conclusion is that you're all pulling my leg that there _is_ this "Eduardo" maintainer who's supposed to be taking patches for this stuff.

As I've said, I'm not bothering with this anymore, it's just far too much effort to play these stupid games. The deadlock can stay for all I care.

Sorry.

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
#31 lore raw
Quoted 11 lines · Russell King - ARM Linux

That I doubt. Eduardo has not bothered to reply at _any_ time. I have to question whether there is anyone even reading that email address, or whether it's a redirect to /dev/null. All the evidence I have right now is that this Eduardo is a ficticous character.

I would have at least expected some complaints when I said "I've put it in linux-next" but... absolutely nothing.

So... my only conclusion is that you're all pulling my leg that there _is_ this "Eduardo" maintainer who's supposed to be taking patches for this stuff.

Haha, If that's the case then we are all in the same boat. Who is Eduardo ? A bot ? :)

Anyway, AFAIK, he wasn't around for sometime and came back last week only. Even I have expected him to reply to yesterday's discussions.

Quoted 3 lines

As I've said, I'm not bothering with this anymore, it's just far too much effort to play these stupid games. The deadlock can stay for all I care.

And finally I took the charge to carry it now. :)

Signature · 1 line
viresh
#32 lore raw
In reply to Russell King - ARM Linux
Quoted 52 lines · Russell King - ARM Linux
Quoted 40 lines · Rafael J. Wysocki
Quoted 39 lines · Russell King - ARM Linux
Quoted 8 lines · Rafael J. Wysocki
Quoted 7 lines · Russell King - ARM Linux
Quoted 6 lines · Viresh Kumar
Quoted 3 lines · Russell King - ARM Linux

Well, here's a patch which I'm running on top of 3.18 at the moment, which is basically what I described in my email, and I'm running with it and it is without any lockdep complaint.

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines

We need two separate patches now, one for 3.18 and other one for 3.19-rc. 3.19 has see lots of changes in this particular file and so we need to change few things here.

What happened with this? I'm still carrying the patch.

This should go in through the thermal tree. Eduardo?

Having waited a long time for any kind of response from Eduardo, I've given up. My conclusion is that Eduardo isn't interested in this.

I've re-checked, and the AB-BA deadlock is still there in the latest code. So, I've taken it upon myself to throw this into my for-next branch to force the issue - not something I _want_ to do, but I'm doing this out of frustration. It's clear to me that "playing nice" by email does _not_ work with some people.

I'm rather hoping that Stephen reports a merge conflict with linux-next this evening to highlight this situation. I've added additional commentry to the commit message on the patch giving the reason why I've done this, and the relevant message IDs showing the past history.

I've not decided whether I'm going to ask Linus to take this patch directly or not, that rather depends whether there's any co-operation from Eduardo on this. I'd rather Eduardo took the patch.

The patch I have has had to be updated again for changes to the driver, but I really don't see the point of re-posting it just for it to be ignored yet again.

Quoted 5 lines
Quoted 3 lines

I'm really disappointed by this dysfunctional state of affairs, and that what should be an urgent fix for an observable problem is still not merged some nine months after it was first identified.

I guess it might help if you sent the updated patch in a new thread.

That I doubt. Eduardo has not bothered to reply at _any_ time. I have to question whether there is anyone even reading that email address, or whether it's a redirect to /dev/null. All the evidence I have right now is that this Eduardo is a ficticous character.

Quoted 6 lines

I would have at least expected some complaints when I said "I've put it in linux-next" but... absolutely nothing.

So... my only conclusion is that you're all pulling my leg that there _is_ this "Eduardo" maintainer who's supposed to be taking patches for this stuff.

Well, that's the situation as per MAINTAINERS today. You seem to be concerned that it may not reflect the reality, but in that case I can only recommend sending a patch against MAINTAINERS to remove Eduardo from there.

Quoted 2 lines

As I've said, I'm not bothering with this anymore, it's just far too much effort to play these stupid games.

I'm not sure what you mean by "these stupid games" here.

Quoted 1 line

The deadlock can stay for all I care.

Fair enough.

Thanks,
Rafael

#33 lore raw

Hi there,

On Mon, Aug 17, 2015 at 6:32 PM, Rafael J. Wysocki <[email protected]> wrote:

<cut>

Quoted 5 lines

Well, that's the situation as per MAINTAINERS today. You seem to be concerned that it may not reflect the reality, but in that case I can only recommend sending a patch against MAINTAINERS to remove Eduardo from there.

Quoted 8 lines
Quoted 2 lines

As I've said, I'm not bothering with this anymore, it's just far too much effort to play these stupid games.

I'm not sure what you mean by "these stupid games" here.

Quoted 1 line

The deadlock can stay for all I care.

Fair enough.

I applied the patch. And it has generated the conflict in linux-next, as was mentioned in this thread. I already sent the pull request.

Yes, I missed the thread. Apologize for this and for the inconvenience I have caused. The deadlock will be taken care using Russel's patch.

Thanks Viresh for notifying me.

Quoted 4 lines

Thanks,
Rafael

BR,

Signature · 1 line
Eduardo Bezerra Valentin
#34 lore raw
In reply to Yadwinder Singh Brar
Quoted 11 lines · Yadwinder Singh Brar
Quoted 11 lines

Unfortunately, you do need some kind of synchronisation here. If it's not important when cpufreq_register_notifier() gets called, maybe this can work:

      bool register;

      mutex_lock(&cooling_cpufreq_lock);
      register = cpufreq_dev_count++ == 0;
      list_add(&cpufreq_dev->node, &cpufreq_dev_list);
      mutex_unlock(&cooling_cpufreq_lock);
Quoted 4 lines
Quoted 1 line

if (register)

register may be 0 in scenario you stated above in second point. So this approach will not work.

I didn't understood what you meant here. register will be zero only for one of the threads.

#35 lore raw
In reply to Yadwinder Singh Brar
Quoted 2 lines · Yadwinder Singh Brar

Unfortunately, I didn?t get any such warning though I tested patch enabling CONFIG_PROVE_LOCKING before posting. It seems

Even I couldn't reproduce it :)

Quoted 5 lines

Anyways, after analyzing log and code,I think problem is not in cpufreq_thermal_notifier which was modified in patch as stated above. Actual problem is in __cpufreq_cooling_register which is unnecessarily calling cpufreq_register_notifier() inside section protected by cooling_cpufreq_lock.

Agreed, and I was looking to reproduce first before writing some crazy code.

Quoted 3 lines

Because cpufreq_policy_notifier_list).rwsem is already held
by store_scaling_governor when __cpufreq_cooling_register is trying to cpufreq_policy_notifier_list while holding cooling_cpufreq_lock.

Correct.

Quoted 11 lines

So I think following can fix the problem:

drivers/thermal/cpu_cooling.c +0 -1
index ad09e51..622ea40 100644
@@ -484,15 +484,15 @@ __cpufreq_cooling_register(struct device_node *np,
        cpufreq_dev->cpufreq_state = 0;
        mutex_lock(&cooling_cpufreq_lock);
 
-       /* Register the notifier for first cpufreq cooling device */

drivers/thermal/cpu_cooling.c __cpufreq_cooling_register(struct device_node *np, · line 493

Quoted 10 lines
drivers/thermal/cpu_cooling.c +2 -3
-       if (cpufreq_dev_count == 0)
-               cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
-                                         CPUFREQ_POLICY_NOTIFIER);
        cpufreq_dev_count++;
        list_add(&cpufreq_dev->node, &cpufreq_dev_list);
 
        mutex_unlock(&cooling_cpufreq_lock);
 
+       /* Register the notifier for first cpufreq cooling device */
+       if (cpufreq_dev_count == 0)

This will always fail :), over that we need to access cpufreq_dev_count from within the lock.

Quoted 4 lines
drivers/thermal/cpu_cooling.c +2 -0
+               cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
+                                         CPUFREQ_POLICY_NOTIFIER);
        return cool_dev;
 }