]>
Commit | Line | Data |
---|---|---|
3d4ecfe4 SL |
1 | From 2146583cf6bf5db0d96587d9df4a2160f9502f38 Mon Sep 17 00:00:00 2001 |
2 | From: James Hutchinson <jahutchinson99@googlemail.com> | |
3 | Date: Sun, 13 Jan 2019 16:13:47 -0500 | |
4 | Subject: media: m88ds3103: serialize reset messages in m88ds3103_set_frontend | |
5 | ||
6 | [ Upstream commit 981fbe3da20a6f35f17977453bce7dfc1664d74f ] | |
7 | ||
8 | Ref: https://bugzilla.kernel.org/show_bug.cgi?id=199323 | |
9 | ||
10 | Users are experiencing problems with the DVBSky S960/S960C USB devices | |
11 | since the following commit: | |
12 | ||
13 | 9d659ae: ("locking/mutex: Add lock handoff to avoid starvation") | |
14 | ||
15 | The device malfunctions after running for an indeterminable period of | |
16 | time, and the problem can only be cleared by rebooting the machine. | |
17 | ||
18 | It is possible to encourage the problem to surface by blocking the | |
19 | signal to the LNB. | |
20 | ||
21 | Further debugging revealed the cause of the problem. | |
22 | ||
23 | In the following capture: | |
24 | - thread #1325 is running m88ds3103_set_frontend | |
25 | - thread #42 is running ts2020_stat_work | |
26 | ||
27 | a> [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 07 80 | |
28 | [1325] usb 1-1: dvb_usb_v2_generic_io: <<< 08 | |
29 | [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 68 3f | |
30 | [42] usb 1-1: dvb_usb_v2_generic_io: <<< 08 ff | |
31 | [42] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11 | |
32 | [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 | |
33 | [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 60 3d | |
34 | [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 ff | |
35 | b> [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 07 00 | |
36 | [1325] usb 1-1: dvb_usb_v2_generic_io: <<< 07 | |
37 | [42] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11 | |
38 | [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 | |
39 | [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 60 21 | |
40 | [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 ff | |
41 | [42] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11 | |
42 | [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 | |
43 | [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 60 66 | |
44 | [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 ff | |
45 | [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11 | |
46 | [1325] usb 1-1: dvb_usb_v2_generic_io: <<< 07 | |
47 | [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 60 02 10 0b | |
48 | [1325] usb 1-1: dvb_usb_v2_generic_io: <<< 07 | |
49 | ||
50 | Two i2c messages are sent to perform a reset in m88ds3103_set_frontend: | |
51 | ||
52 | a. 0x07, 0x80 | |
53 | b. 0x07, 0x00 | |
54 | ||
55 | However, as shown in the capture, the regmap mutex is being handed over | |
56 | to another thread (ts2020_stat_work) in between these two messages. | |
57 | ||
58 | >From here, the device responds to every i2c message with an 07 message, | |
59 | and will only return to normal operation following a power cycle. | |
60 | ||
61 | Use regmap_multi_reg_write to group the two reset messages, ensuring | |
62 | both are processed before the regmap mutex is unlocked. | |
63 | ||
64 | Signed-off-by: James Hutchinson <jahutchinson99@googlemail.com> | |
65 | Reviewed-by: Antti Palosaari <crope@iki.fi> | |
66 | Signed-off-by: Sean Young <sean@mess.org> | |
67 | Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | |
68 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
69 | --- | |
70 | drivers/media/dvb-frontends/m88ds3103.c | 9 ++++----- | |
71 | 1 file changed, 4 insertions(+), 5 deletions(-) | |
72 | ||
73 | diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c | |
74 | index 65d157fe76d19..b4bd1af34745d 100644 | |
75 | --- a/drivers/media/dvb-frontends/m88ds3103.c | |
76 | +++ b/drivers/media/dvb-frontends/m88ds3103.c | |
77 | @@ -309,6 +309,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) | |
78 | u16 u16tmp; | |
79 | u32 tuner_frequency_khz, target_mclk; | |
80 | s32 s32tmp; | |
81 | + static const struct reg_sequence reset_buf[] = { | |
82 | + {0x07, 0x80}, {0x07, 0x00} | |
83 | + }; | |
84 | ||
85 | dev_dbg(&client->dev, | |
86 | "delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", | |
87 | @@ -321,11 +324,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) | |
88 | } | |
89 | ||
90 | /* reset */ | |
91 | - ret = regmap_write(dev->regmap, 0x07, 0x80); | |
92 | - if (ret) | |
93 | - goto err; | |
94 | - | |
95 | - ret = regmap_write(dev->regmap, 0x07, 0x00); | |
96 | + ret = regmap_multi_reg_write(dev->regmap, reset_buf, 2); | |
97 | if (ret) | |
98 | goto err; | |
99 | ||
100 | -- | |
101 | 2.20.1 | |
102 |