From: Stephen Boyd <hidden> Date: 2016-06-28 01:18:32
We setup the HNP polling worker, but we never stop it. The OTG
state machine can go round and round and keep reinitializing the
worker even while it's actively running. That's bad, and debug
objects catches it. Fix this by canceling the work when we leave
the A_HOST or B_HOST states.
[otg_set_state] Set state: a_wait_bcon
usb 2-1: USB disconnect, device number 2
[otg_statemachine] quit statemachine, changed = 1
[otg_set_state] Set state: a_host
<HNP Polling started>
[otg_statemachine] quit statemachine, changed = 1
usb 2-1: new low-speed USB device number 3 using ci_hdrc
usb 2-1: New USB device found, idVendor=03f0, idProduct=134a
usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 2-1: Product: HP USB Optical Mouse
usb 2-1: Manufacturer: PixArt
input: PixArt HP USB Optical Mouse as /devices/platform/soc/f9a55000.usb/ci_hdrc.0/usb2/2-1/2-1:1.0/0003:03F0:134A.0002/input/input1
hid-generic 0003:03F0:134A.0002: input: USB HID v1.11 Mouse [PixArt HP USB Optical Mouse] on usb-ci_hdrc.0-1/input0
[otg_set_state] Set state: a_wait_bcon
usb 2-1: USB disconnect, device number 3
[otg_statemachine] quit statemachine, changed = 1
[otg_set_state] Set state: a_host
<HNP Polling started>
------------[ cut here ]------------
WARNING: CPU: 2 PID: 95 at lib/debugobjects.c:263 debug_print_object+0x98/0xc0
ODEBUG: init active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x2c
Modules linked in: phy_qcom_usb_hsic phy_qcom_usb_hs ci_hdrc_msm ci_hdrc
CPU: 2 PID: 95 Comm: kworker/u8:1 Not tainted 4.7.0-rc1-00043-g1f22f3b65c44-dirty #442
Hardware name: Qualcomm (Flattened Device Tree)
Workqueue: ci_otg ci_otg_work [ci_hdrc]
[<c031067c>] (unwind_backtrace) from [<c030cbf0>] (show_stack+0x20/0x24)
[<c030cbf0>] (show_stack) from [<c060cec8>] (dump_stack+0x7c/0x9c)
[<c060cec8>] (dump_stack) from [<c031f8a4>] (__warn+0xe4/0x110)
[<c031f8a4>] (__warn) from [<c031f9a0>] (warn_slowpath_fmt+0x48/0x50)
[<c031f9a0>] (warn_slowpath_fmt) from [<c06289c0>] (debug_print_object+0x98/0xc0)
[<c06289c0>] (debug_print_object) from [<c0628bbc>] (__debug_object_init+0xcc/0x3bc)
[<c0628bbc>] (__debug_object_init) from [<c0628ed0>] (debug_object_init+0x24/0x2c)
[<c0628ed0>] (debug_object_init) from [<c037ceb0>] (init_timer_key+0x24/0x120)
[<c037ceb0>] (init_timer_key) from [<c07b3f1c>] (otg_start_hnp_polling+0x7c/0xbc)
[<c07b3f1c>] (otg_start_hnp_polling) from [<c074543c>] (otg_set_state+0x740/0xc20)
[<c074543c>] (otg_set_state) from [<c0745d98>] (otg_statemachine+0x47c/0x4ac)
[<c0745d98>] (otg_statemachine) from [<bf00c808>] (ci_otg_fsm_work+0x48/0x1a0 [ci_hdrc])
[<bf00c808>] (ci_otg_fsm_work [ci_hdrc]) from [<bf007428>] (ci_otg_work+0xd4/0x218 [ci_hdrc])
[<bf007428>] (ci_otg_work [ci_hdrc]) from [<c0338cac>] (process_one_work+0x154/0x4b4)
[<c0338cac>] (process_one_work) from [<c033908c>] (worker_thread+0x38/0x4d0)
[<c033908c>] (worker_thread) from [<c033f0a0>] (kthread+0xe8/0x104)
[<c033f0a0>] (kthread) from [<c0308ed8>] (ret_from_fork+0x14/0x3c)
Cc: Li Jun <redacted>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Fixes: ae57e97a9521 ("usb: common: otg-fsm: add HNP polling support")
Signed-off-by: Stephen Boyd <redacted>
---
drivers/usb/common/usb-otg-fsm.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
@@ -61,6 +61,18 @@ static int otg_set_protocol(struct otg_fsm *fsm, int protocol)return0;}+staticvoidotg_stop_hnp_polling(structotg_fsm*fsm)+{+/*+*Thememoryofhost_req_flagshouldbeallocatedby+*controllerdriver,otherwise,hnppollingisnotstarted.+*/+if(!fsm->host_req_flag)+return;++cancel_delayed_work_sync(&fsm->hnp_polling_work);+}+/* Called when leaving a state. Do state clean up jobs here */staticvoidotg_leave_state(structotg_fsm*fsm,enumusb_otg_stateold_state){
-----Original Message-----
From: Stephen Boyd [mailto:stephen.boyd at linaro.org]
Sent: Tuesday, June 28, 2016 9:18 AM
To: Peter Chen <redacted>; Felipe Balbi <balbi@kernel.org>
Cc: linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
linux-usb at vger.kernel.org; Jun Li [off-list ref]; Greg Kroah-Hartman
[off-list ref]
Subject: [PATCH] usb: otg-fsm: Cancel HNP polling work when not used
We setup the HNP polling worker, but we never stop it. The OTG state
machine can go round and round and keep reinitializing the worker even
while it's actively running. That's bad, and debug objects catches it. Fix
this by canceling the work when we leave the A_HOST or B_HOST states.
Normally we need not stop it because the scheduled delayed work will
be finished before next host entering, in your case there is another
host entering before the previous delayed work timeout, so we reinit
the active worker wrongly. Thanks for the required fix.
Acked-by: Li Jun <redacted>
quoted hunk
[otg_set_state] Set state: a_wait_bcon
usb 2-1: USB disconnect, device number 2 [otg_statemachine] quit
statemachine, changed = 1 [otg_set_state] Set state: a_host <HNP Polling
started> [otg_statemachine] quit statemachine, changed = 1 usb 2-1: new
low-speed USB device number 3 using ci_hdrc usb 2-1: New USB device found,
idVendor=03f0, idProduct=134a usb 2-1: New USB device strings: Mfr=1,
Product=2, SerialNumber=0 usb 2-1: Product: HP USB Optical Mouse usb 2-1:
Manufacturer: PixArt
input: PixArt HP USB Optical Mouse as
/devices/platform/soc/f9a55000.usb/ci_hdrc.0/usb2/2-1/2-
1:1.0/0003:03F0:134A.0002/input/input1
hid-generic 0003:03F0:134A.0002: input: USB HID v1.11 Mouse [PixArt HP USB
Optical Mouse] on usb-ci_hdrc.0-1/input0 [otg_set_state] Set state:
a_wait_bcon usb 2-1: USB disconnect, device number 3 [otg_statemachine]
quit statemachine, changed = 1 [otg_set_state] Set state: a_host <HNP
Polling started> ------------[ cut here ]------------
WARNING: CPU: 2 PID: 95 at lib/debugobjects.c:263
debug_print_object+0x98/0xc0
ODEBUG: init active (active state 0) object type: timer_list hint:
delayed_work_timer_fn+0x0/0x2c Modules linked in: phy_qcom_usb_hsic
phy_qcom_usb_hs ci_hdrc_msm ci_hdrc
CPU: 2 PID: 95 Comm: kworker/u8:1 Not tainted 4.7.0-rc1-00043-
g1f22f3b65c44-dirty #442 Hardware name: Qualcomm (Flattened Device Tree)
Workqueue: ci_otg ci_otg_work [ci_hdrc]
[<c031067c>] (unwind_backtrace) from [<c030cbf0>] (show_stack+0x20/0x24)
[<c030cbf0>] (show_stack) from [<c060cec8>] (dump_stack+0x7c/0x9c)
[<c060cec8>] (dump_stack) from [<c031f8a4>] (__warn+0xe4/0x110)
[<c031f8a4>] (__warn) from [<c031f9a0>] (warn_slowpath_fmt+0x48/0x50)
[<c031f9a0>] (warn_slowpath_fmt) from [<c06289c0>]
(debug_print_object+0x98/0xc0) [<c06289c0>] (debug_print_object) from
[<c0628bbc>] (__debug_object_init+0xcc/0x3bc) [<c0628bbc>]
(__debug_object_init) from [<c0628ed0>] (debug_object_init+0x24/0x2c)
[<c0628ed0>] (debug_object_init) from [<c037ceb0>]
(init_timer_key+0x24/0x120) [<c037ceb0>] (init_timer_key) from [<c07b3f1c>]
(otg_start_hnp_polling+0x7c/0xbc) [<c07b3f1c>] (otg_start_hnp_polling)
from [<c074543c>] (otg_set_state+0x740/0xc20) [<c074543c>] (otg_set_state)
from [<c0745d98>] (otg_statemachine+0x47c/0x4ac) [<c0745d98>]
(otg_statemachine) from [<bf00c808>] (ci_otg_fsm_work+0x48/0x1a0 [ci_hdrc])
[<bf00c808>] (ci_otg_fsm_work [ci_hdrc]) from [<bf007428>]
(ci_otg_work+0xd4/0x218 [ci_hdrc]) [<bf007428>] (ci_otg_work [ci_hdrc])
from [<c0338cac>] (process_one_work+0x154/0x4b4) [<c0338cac>]
(process_one_work) from [<c033908c>] (worker_thread+0x38/0x4d0)
[<c033908c>] (worker_thread) from [<c033f0a0>] (kthread+0xe8/0x104)
[<c033f0a0>] (kthread) from [<c0308ed8>] (ret_from_fork+0x14/0x3c)
Cc: Li Jun <redacted>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Fixes: ae57e97a9521 ("usb: common: otg-fsm: add HNP polling support")
Signed-off-by: Stephen Boyd <redacted>
---
drivers/usb/common/usb-otg-fsm.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
From: Peter Chen <hidden> Date: 2016-06-29 09:50:50
On Mon, Jun 27, 2016 at 06:18:27PM -0700, Stephen Boyd wrote:
quoted hunk
We setup the HNP polling worker, but we never stop it. The OTG
state machine can go round and round and keep reinitializing the
worker even while it's actively running. That's bad, and debug
objects catches it. Fix this by canceling the work when we leave
the A_HOST or B_HOST states.
[otg_set_state] Set state: a_wait_bcon
usb 2-1: USB disconnect, device number 2
[otg_statemachine] quit statemachine, changed = 1
[otg_set_state] Set state: a_host
<HNP Polling started>
[otg_statemachine] quit statemachine, changed = 1
usb 2-1: new low-speed USB device number 3 using ci_hdrc
usb 2-1: New USB device found, idVendor=03f0, idProduct=134a
usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 2-1: Product: HP USB Optical Mouse
usb 2-1: Manufacturer: PixArt
input: PixArt HP USB Optical Mouse as /devices/platform/soc/f9a55000.usb/ci_hdrc.0/usb2/2-1/2-1:1.0/0003:03F0:134A.0002/input/input1
hid-generic 0003:03F0:134A.0002: input: USB HID v1.11 Mouse [PixArt HP USB Optical Mouse] on usb-ci_hdrc.0-1/input0
[otg_set_state] Set state: a_wait_bcon
usb 2-1: USB disconnect, device number 3
[otg_statemachine] quit statemachine, changed = 1
[otg_set_state] Set state: a_host
<HNP Polling started>
------------[ cut here ]------------
WARNING: CPU: 2 PID: 95 at lib/debugobjects.c:263 debug_print_object+0x98/0xc0
ODEBUG: init active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x2c
Modules linked in: phy_qcom_usb_hsic phy_qcom_usb_hs ci_hdrc_msm ci_hdrc
CPU: 2 PID: 95 Comm: kworker/u8:1 Not tainted 4.7.0-rc1-00043-g1f22f3b65c44-dirty #442
Hardware name: Qualcomm (Flattened Device Tree)
Workqueue: ci_otg ci_otg_work [ci_hdrc]
[<c031067c>] (unwind_backtrace) from [<c030cbf0>] (show_stack+0x20/0x24)
[<c030cbf0>] (show_stack) from [<c060cec8>] (dump_stack+0x7c/0x9c)
[<c060cec8>] (dump_stack) from [<c031f8a4>] (__warn+0xe4/0x110)
[<c031f8a4>] (__warn) from [<c031f9a0>] (warn_slowpath_fmt+0x48/0x50)
[<c031f9a0>] (warn_slowpath_fmt) from [<c06289c0>] (debug_print_object+0x98/0xc0)
[<c06289c0>] (debug_print_object) from [<c0628bbc>] (__debug_object_init+0xcc/0x3bc)
[<c0628bbc>] (__debug_object_init) from [<c0628ed0>] (debug_object_init+0x24/0x2c)
[<c0628ed0>] (debug_object_init) from [<c037ceb0>] (init_timer_key+0x24/0x120)
[<c037ceb0>] (init_timer_key) from [<c07b3f1c>] (otg_start_hnp_polling+0x7c/0xbc)
[<c07b3f1c>] (otg_start_hnp_polling) from [<c074543c>] (otg_set_state+0x740/0xc20)
[<c074543c>] (otg_set_state) from [<c0745d98>] (otg_statemachine+0x47c/0x4ac)
[<c0745d98>] (otg_statemachine) from [<bf00c808>] (ci_otg_fsm_work+0x48/0x1a0 [ci_hdrc])
[<bf00c808>] (ci_otg_fsm_work [ci_hdrc]) from [<bf007428>] (ci_otg_work+0xd4/0x218 [ci_hdrc])
[<bf007428>] (ci_otg_work [ci_hdrc]) from [<c0338cac>] (process_one_work+0x154/0x4b4)
[<c0338cac>] (process_one_work) from [<c033908c>] (worker_thread+0x38/0x4d0)
[<c033908c>] (worker_thread) from [<c033f0a0>] (kthread+0xe8/0x104)
[<c033f0a0>] (kthread) from [<c0308ed8>] (ret_from_fork+0x14/0x3c)
Cc: Li Jun <redacted>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Fixes: ae57e97a9521 ("usb: common: otg-fsm: add HNP polling support")
Signed-off-by: Stephen Boyd <redacted>
---
drivers/usb/common/usb-otg-fsm.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
@@ -61,6 +61,18 @@ static int otg_set_protocol(struct otg_fsm *fsm, int protocol)return0;}+staticvoidotg_stop_hnp_polling(structotg_fsm*fsm)+{+/*+*Thememoryofhost_req_flagshouldbeallocatedby+*controllerdriver,otherwise,hnppollingisnotstarted.+*/+if(!fsm->host_req_flag)+return;++cancel_delayed_work_sync(&fsm->hnp_polling_work);+}+/* Called when leaving a state. Do state clean up jobs here */staticvoidotg_leave_state(structotg_fsm*fsm,enumusb_otg_stateold_state){
-----Original Message-----
From: Peter Chen [mailto:hzpeterchen at gmail.com]
Sent: Wednesday, June 29, 2016 5:44 PM
To: Stephen Boyd <redacted>
Cc: Peter Chen <redacted>; Felipe Balbi <balbi@kernel.org>;
linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org; linux-
usb at vger.kernel.org; Jun Li [off-list ref]; Greg Kroah-Hartman
[off-list ref]
Subject: Re: [PATCH] usb: otg-fsm: Cancel HNP polling work when not used
On Mon, Jun 27, 2016 at 06:18:27PM -0700, Stephen Boyd wrote:
quoted
We setup the HNP polling worker, but we never stop it. The OTG state
machine can go round and round and keep reinitializing the worker even
while it's actively running. That's bad, and debug objects catches it.
Fix this by canceling the work when we leave the A_HOST or B_HOST
states.
[otg_set_state] Set state: a_wait_bcon usb 2-1: USB disconnect,
device number 2 [otg_statemachine] quit statemachine, changed = 1
[otg_set_state] Set state: a_host <HNP Polling started>
[otg_statemachine] quit statemachine, changed = 1 usb 2-1: new
low-speed USB device number 3 using ci_hdrc usb 2-1: New USB device
found, idVendor=03f0, idProduct=134a usb 2-1: New USB device strings:
Mfr=1, Product=2, SerialNumber=0 usb 2-1: Product: HP USB Optical
Mouse usb 2-1: Manufacturer: PixArt
input: PixArt HP USB Optical Mouse as
/devices/platform/soc/f9a55000.usb/ci_hdrc.0/usb2/2-1/2-1:1.0/0003:03F
0:134A.0002/input/input1 hid-generic 0003:03F0:134A.0002: input: USB
HID v1.11 Mouse [PixArt HP USB Optical Mouse] on
usb-ci_hdrc.0-1/input0 [otg_set_state] Set state: a_wait_bcon usb
2-1: USB disconnect, device number 3 [otg_statemachine] quit
statemachine, changed = 1 [otg_set_state] Set state: a_host <HNP
Polling started> ------------[ cut here ]------------
WARNING: CPU: 2 PID: 95 at lib/debugobjects.c:263
debug_print_object+0x98/0xc0
ODEBUG: init active (active state 0) object type: timer_list hint:
delayed_work_timer_fn+0x0/0x2c Modules linked in: phy_qcom_usb_hsic
phy_qcom_usb_hs ci_hdrc_msm ci_hdrc
CPU: 2 PID: 95 Comm: kworker/u8:1 Not tainted
4.7.0-rc1-00043-g1f22f3b65c44-dirty #442 Hardware name: Qualcomm
(Flattened Device Tree)
Workqueue: ci_otg ci_otg_work [ci_hdrc] [<c031067c>]
(unwind_backtrace) from [<c030cbf0>] (show_stack+0x20/0x24)
[<c030cbf0>] (show_stack) from [<c060cec8>] (dump_stack+0x7c/0x9c)
[<c060cec8>] (dump_stack) from [<c031f8a4>] (__warn+0xe4/0x110)
[<c031f8a4>] (__warn) from [<c031f9a0>] (warn_slowpath_fmt+0x48/0x50)
[<c031f9a0>] (warn_slowpath_fmt) from [<c06289c0>]
(debug_print_object+0x98/0xc0) [<c06289c0>] (debug_print_object) from
[<c0628bbc>] (__debug_object_init+0xcc/0x3bc) [<c0628bbc>]
(__debug_object_init) from [<c0628ed0>] (debug_object_init+0x24/0x2c)
[<c0628ed0>] (debug_object_init) from [<c037ceb0>]
(init_timer_key+0x24/0x120) [<c037ceb0>] (init_timer_key) from
[<c07b3f1c>] (otg_start_hnp_polling+0x7c/0xbc) [<c07b3f1c>]
(otg_start_hnp_polling) from [<c074543c>] (otg_set_state+0x740/0xc20)
[<c074543c>] (otg_set_state) from [<c0745d98>]
(otg_statemachine+0x47c/0x4ac) [<c0745d98>] (otg_statemachine) from
[<bf00c808>] (ci_otg_fsm_work+0x48/0x1a0 [ci_hdrc]) [<bf00c808>]
(ci_otg_fsm_work [ci_hdrc]) from [<bf007428>] (ci_otg_work+0xd4/0x218
[ci_hdrc]) [<bf007428>] (ci_otg_work [ci_hdrc]) from [<c0338cac>]
(process_one_work+0x154/0x4b4) [<c0338cac>] (process_one_work) from
[<c033908c>] (worker_thread+0x38/0x4d0) [<c033908c>] (worker_thread)
from [<c033f0a0>] (kthread+0xe8/0x104) [<c033f0a0>] (kthread) from
[<c0308ed8>] (ret_from_fork+0x14/0x3c)
Cc: Li Jun <redacted>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Fixes: ae57e97a9521 ("usb: common: otg-fsm: add HNP polling support")
Signed-off-by: Stephen Boyd <redacted>
---
drivers/usb/common/usb-otg-fsm.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/usb/common/usb-otg-fsm.c
b/drivers/usb/common/usb-otg-fsm.c
index 9059b7dc185e..73eec8c12235 100644
fsm->a_wait_bcon_tmout = 0;
break;
case OTG_STATE_A_HOST:
+ otg_stop_hnp_polling(fsm);
otg_del_timer(fsm, A_WAIT_ENUM);
break;
case OTG_STATE_A_SUSPEND:
--
It introduces circular locking after applying it, otg_statemachine calls
otg_leave_state, and otg_leave_state calls otg_statemachine again due to
flush work, see below dump:
How did you trigger this locking issue? I did some simple tests with
this patch but no problems found.
I suggest moving initialization/flush hnp polling work to chipidea driver.
Since the HNP polling is done in common driver completely, so I think
it's not proper to move some of it into controller driver.
Li Jun
From: Peter Chen <hidden> Date: 2016-06-29 11:30:57
On Wed, Jun 29, 2016 at 10:56:42AM +0000, Jun Li wrote:
quoted
quoted
}
+static void otg_stop_hnp_polling(struct otg_fsm *fsm) {
+ /*
+ * The memory of host_req_flag should be allocated by
+ * controller driver, otherwise, hnp polling is not started.
+ */
+ if (!fsm->host_req_flag)
+ return;
+
+ cancel_delayed_work_sync(&fsm->hnp_polling_work);
+}
+
/* Called when leaving a state. Do state clean up jobs here */
static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state
old_state) { @@ -84,6 +96,7 @@ static void otg_leave_state(struct
otg_fsm *fsm, enum usb_otg_state old_state)
fsm->b_ase0_brst_tmout = 0;
break;
case OTG_STATE_B_HOST:
+ otg_stop_hnp_polling(fsm);
break;
case OTG_STATE_A_IDLE:
fsm->adp_prb = 0;
fsm->a_wait_bcon_tmout = 0;
break;
case OTG_STATE_A_HOST:
+ otg_stop_hnp_polling(fsm);
otg_del_timer(fsm, A_WAIT_ENUM);
break;
case OTG_STATE_A_SUSPEND:
--
It introduces circular locking after applying it, otg_statemachine calls
otg_leave_state, and otg_leave_state calls otg_statemachine again due to
flush work, see below dump:
How did you trigger this locking issue? I did some simple tests with
this patch but no problems found.
Just do srp repeat at b side.
counter=0
while [ 1 ]
do
./srp.sh 0
sleep 5
./srp.sh 1
sleep 5
counter=$(( $counter + 1 ))
echo "the counter is $counter"
done
root at imx6qdlsolo:~# cat srp.sh
echo $1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
quoted
I suggest moving initialization/flush hnp polling work to chipidea driver.
Since the HNP polling is done in common driver completely, so I think
it's not proper to move some of it into controller driver.
If we can keep one-shot operation well, like initialization and remove,
I have no idea to keep it like current way.
Peter
From: Stephen Boyd <hidden> Date: 2016-06-30 02:02:32
Quoting Peter Chen (2016-06-29 02:43:47)
On Mon, Jun 27, 2016 at 06:18:27PM -0700, Stephen Boyd wrote:
It introduces circular locking after applying it, otg_statemachine calls
otg_leave_state, and otg_leave_state calls otg_statemachine again due
to flush work, see below dump:
I suggest moving initialization/flush hnp polling work to chipidea driver.
[ 183.086987] ======================================================
[ 183.093183] [ INFO: possible circular locking dependency detected ]
[ 183.099471] 4.7.0-rc4-00012-gf1f333f-dirty #856 Not tainted
[ 183.105059] -------------------------------------------------------
[ 183.111341] kworker/0:2/114 is trying to acquire lock:
[ 183.116492] (&ci->fsm.lock){+.+.+.}, at: [<806118dc>]
otg_statemachine+0x20/0x470
[ 183.124199]
[ 183.124199] but task is already holding lock:
[ 183.130052] ((&(&fsm->hnp_polling_work)->work)){+.+...}, at:
[<80140368>] process_one_work+0x128/0x418
[ 183.139568]
[ 183.139568] which lock already depends on the new lock.
[ 183.139568]
[ 183.147765]
[ 183.147765] the existing dependency chain (in reverse order) is:
[ 183.155265]
-> #1 ((&(&fsm->hnp_polling_work)->work)){+.+...}:
[ 183.161371] [<8013e97c>] flush_work+0x44/0x234
[ 183.166469] [<801411a8>] __cancel_work_timer+0x98/0x1c8
[ 183.172347] [<80141304>] cancel_delayed_work_sync+0x14/0x18
[ 183.178570] [<80610ef8>] otg_set_state+0x290/0xc54
[ 183.184011] [<806119d0>] otg_statemachine+0x114/0x470
[ 183.189712] [<8060a590>] ci_otg_fsm_work+0x40/0x190
[ 183.195239] [<806054d0>] ci_otg_work+0xcc/0x1e4
[ 183.200430] [<801403d4>] process_one_work+0x194/0x418
[ 183.206136] [<8014068c>] worker_thread+0x34/0x4fc
[ 183.211489] [<80146d08>] kthread+0xdc/0xf8
[ 183.216238] [<80108ab0>] ret_from_fork+0x14/0x24
[ 183.221514]
-> #0 (&ci->fsm.lock){+.+.+.}:
[ 183.225880] [<8016ff94>] lock_acquire+0x78/0x98
[ 183.231062] [<80947c18>] mutex_lock_nested+0x54/0x3ec
[ 183.236773] [<806118dc>] otg_statemachine+0x20/0x470
[ 183.242388] [<80611df4>] otg_hnp_polling_work+0xc8/0x1a4
[ 183.248352] [<801403d4>] process_one_work+0x194/0x418
[ 183.254055] [<8014068c>] worker_thread+0x34/0x4fc
[ 183.259409] [<80146d08>] kthread+0xdc/0xf8
[ 183.264154] [<80108ab0>] ret_from_fork+0x14/0x24
[ 183.269424]
[ 183.269424] other info that might help us debug this:
[ 183.269424]
[ 183.277451] Possible unsafe locking scenario:
[ 183.277451]
[ 183.283389] CPU0 CPU1
[ 183.287931] ---- ----
[ 183.292473] lock((&(&fsm->hnp_polling_work)->work));
[ 183.297665] lock(&ci->fsm.lock);
[ 183.303639]
lock((&(&fsm->hnp_polling_work)->work));
[ 183.311347] lock(&ci->fsm.lock);
[ 183.314801]
Hm.. perhaps we should do cancel_delayed_work() then and not require any
sync? That would require some locking in the polling worker, but that
looks racy anyway as it runs in parallel to the state machine so it
probably needs to lock with the FSM. Completely untested patch as I'm
going home from work now.
----8<----
@@ -70,7 +70,11 @@ static void otg_stop_hnp_polling(struct otg_fsm *fsm)if(!fsm->host_req_flag)return;-cancel_delayed_work_sync(&fsm->hnp_polling_work);+/*+*Wedon'tcallcancel_delayed_work_sync()herebecausethe+*workerissynchronizedtothisfunctionviathefsmlock.+*/+cancel_delayed_work(&fsm->hnp_polling_work);}/* Called when leaving a state. Do state clean up jobs here */
@@ -136,23 +140,27 @@ static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)}}+staticint__otg_statemachine(structotg_fsm*fsm);+staticvoidotg_hnp_polling_work(structwork_struct*work){structotg_fsm*fsm=container_of(to_delayed_work(work),structotg_fsm,hnp_polling_work);structusb_device*udev;-enumusb_otg_statestate=fsm->otg->state;+enumusb_otg_statestate;u8flag;intretval;+mutex_lock(&fsm->lock);+state=fsm->otg->state;if(state!=OTG_STATE_A_HOST&&state!=OTG_STATE_B_HOST)-return;+gotounlock;udev=usb_hub_find_child(fsm->otg->host->root_hub,1);if(!udev){dev_err(fsm->otg->host->controller,"no usb dev connected, can't start HNP polling\n");-return;+gotounlock;}*fsm->host_req_flag=0;
@@ -168,7 +176,7 @@ static void otg_hnp_polling_work(struct work_struct *work)USB_CTRL_GET_TIMEOUT);if(retval!=1){dev_err(&udev->dev,"Get one byte OTG status failed\n");-return;+gotounlock;}flag=*fsm->host_req_flag;
@@ -176,10 +184,10 @@ static void otg_hnp_polling_work(struct work_struct *work)/* Continue HNP polling */schedule_delayed_work(&fsm->hnp_polling_work,msecs_to_jiffies(T_HOST_REQ_POLL));-return;+gotounlock;}elseif(flag!=HOST_REQUEST_FLAG){dev_err(&udev->dev,"host request flag %d is invalid\n",flag);-return;+gotounlock;}/* Host request flag is set */
From: Peter Chen <hidden> Date: 2016-06-30 09:19:31
On Wed, Jun 29, 2016 at 07:02:32PM -0700, Stephen Boyd wrote:
Quoting Peter Chen (2016-06-29 02:43:47)
quoted
On Mon, Jun 27, 2016 at 06:18:27PM -0700, Stephen Boyd wrote:
It introduces circular locking after applying it, otg_statemachine calls
otg_leave_state, and otg_leave_state calls otg_statemachine again due
to flush work, see below dump:
I suggest moving initialization/flush hnp polling work to chipidea driver.
[ 183.086987] ======================================================
[ 183.093183] [ INFO: possible circular locking dependency detected ]
[ 183.099471] 4.7.0-rc4-00012-gf1f333f-dirty #856 Not tainted
[ 183.105059] -------------------------------------------------------
[ 183.111341] kworker/0:2/114 is trying to acquire lock:
[ 183.116492] (&ci->fsm.lock){+.+.+.}, at: [<806118dc>]
otg_statemachine+0x20/0x470
[ 183.124199]
[ 183.124199] but task is already holding lock:
[ 183.130052] ((&(&fsm->hnp_polling_work)->work)){+.+...}, at:
[<80140368>] process_one_work+0x128/0x418
[ 183.139568]
[ 183.139568] which lock already depends on the new lock.
[ 183.139568]
[ 183.147765]
[ 183.147765] the existing dependency chain (in reverse order) is:
[ 183.155265]
-> #1 ((&(&fsm->hnp_polling_work)->work)){+.+...}:
[ 183.161371] [<8013e97c>] flush_work+0x44/0x234
[ 183.166469] [<801411a8>] __cancel_work_timer+0x98/0x1c8
[ 183.172347] [<80141304>] cancel_delayed_work_sync+0x14/0x18
[ 183.178570] [<80610ef8>] otg_set_state+0x290/0xc54
[ 183.184011] [<806119d0>] otg_statemachine+0x114/0x470
[ 183.189712] [<8060a590>] ci_otg_fsm_work+0x40/0x190
[ 183.195239] [<806054d0>] ci_otg_work+0xcc/0x1e4
[ 183.200430] [<801403d4>] process_one_work+0x194/0x418
[ 183.206136] [<8014068c>] worker_thread+0x34/0x4fc
[ 183.211489] [<80146d08>] kthread+0xdc/0xf8
[ 183.216238] [<80108ab0>] ret_from_fork+0x14/0x24
[ 183.221514]
-> #0 (&ci->fsm.lock){+.+.+.}:
[ 183.225880] [<8016ff94>] lock_acquire+0x78/0x98
[ 183.231062] [<80947c18>] mutex_lock_nested+0x54/0x3ec
[ 183.236773] [<806118dc>] otg_statemachine+0x20/0x470
[ 183.242388] [<80611df4>] otg_hnp_polling_work+0xc8/0x1a4
[ 183.248352] [<801403d4>] process_one_work+0x194/0x418
[ 183.254055] [<8014068c>] worker_thread+0x34/0x4fc
[ 183.259409] [<80146d08>] kthread+0xdc/0xf8
[ 183.264154] [<80108ab0>] ret_from_fork+0x14/0x24
[ 183.269424]
[ 183.269424] other info that might help us debug this:
[ 183.269424]
[ 183.277451] Possible unsafe locking scenario:
[ 183.277451]
[ 183.283389] CPU0 CPU1
[ 183.287931] ---- ----
[ 183.292473] lock((&(&fsm->hnp_polling_work)->work));
[ 183.297665] lock(&ci->fsm.lock);
[ 183.303639]
lock((&(&fsm->hnp_polling_work)->work));
[ 183.311347] lock(&ci->fsm.lock);
[ 183.314801]
Hm.. perhaps we should do cancel_delayed_work() then and not require any
sync? That would require some locking in the polling worker, but that
looks racy anyway as it runs in parallel to the state machine so it
probably needs to lock with the FSM. Completely untested patch as I'm
going home from work now.
@@ -70,7 +70,11 @@ static void otg_stop_hnp_polling(struct otg_fsm *fsm)if(!fsm->host_req_flag)return;-cancel_delayed_work_sync(&fsm->hnp_polling_work);+/*+*Wedon'tcallcancel_delayed_work_sync()herebecausethe+*workerissynchronizedtothisfunctionviathefsmlock.+*/+cancel_delayed_work(&fsm->hnp_polling_work);}/* Called when leaving a state. Do state clean up jobs here */
@@ -136,23 +140,27 @@ static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)}}+staticint__otg_statemachine(structotg_fsm*fsm);+staticvoidotg_hnp_polling_work(structwork_struct*work){structotg_fsm*fsm=container_of(to_delayed_work(work),structotg_fsm,hnp_polling_work);structusb_device*udev;-enumusb_otg_statestate=fsm->otg->state;+enumusb_otg_statestate;u8flag;intretval;+mutex_lock(&fsm->lock);+state=fsm->otg->state;if(state!=OTG_STATE_A_HOST&&state!=OTG_STATE_B_HOST)-return;+gotounlock;udev=usb_hub_find_child(fsm->otg->host->root_hub,1);if(!udev){dev_err(fsm->otg->host->controller,"no usb dev connected, can't start HNP polling\n");-return;+gotounlock;}*fsm->host_req_flag=0;
@@ -168,7 +176,7 @@ static void otg_hnp_polling_work(struct work_struct *work)USB_CTRL_GET_TIMEOUT);if(retval!=1){dev_err(&udev->dev,"Get one byte OTG status failed\n");-return;+gotounlock;}flag=*fsm->host_req_flag;
@@ -176,10 +184,10 @@ static void otg_hnp_polling_work(struct work_struct *work)/* Continue HNP polling */schedule_delayed_work(&fsm->hnp_polling_work,msecs_to_jiffies(T_HOST_REQ_POLL));-return;+gotounlock;}elseif(flag!=HOST_REQUEST_FLAG){dev_err(&udev->dev,"host request flag %d is invalid\n",flag);-return;+gotounlock;}/* Host request flag is set */