Skip to content

Commit 7724325

Browse files
mchehabtorvalds
authored andcommitted
dvb-usb: move data_mutex to struct dvb_usb_device
The data_mutex is initialized too late, as it is needed for each device driver's power control, causing an OOPS: dvb-usb: found a 'TerraTec/qanu USB2.0 Highspeed DVB-T Receiver' in warm state. BUG: unable to handle kernel NULL pointer dereference at (null) IP: [<ffffffff846617af>] __mutex_lock_slowpath+0x6f/0x100 PGD 0 Oops: 0002 [#1] SMP Modules linked in: dvb_usb_cinergyT2(+) dvb_usb CPU: 0 PID: 2029 Comm: modprobe Not tainted 4.9.0-rc4-dvbmod #24 Hardware name: FUJITSU LIFEBOOK A544/FJNBB35 , BIOS Version 1.17 05/09/2014 task: ffff88020e943840 task.stack: ffff8801f36ec000 RIP: 0010:[<ffffffff846617af>] [<ffffffff846617af>] __mutex_lock_slowpath+0x6f/0x100 RSP: 0018:ffff8801f36efb10 EFLAGS: 00010282 RAX: 0000000000000000 RBX: ffff88021509bdc8 RCX: 00000000c0000100 RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffff88021509bdcc RBP: ffff8801f36efb58 R08: ffff88021f216320 R09: 0000000000100000 R10: ffff88021f216320 R11: 00000023fee6c5a1 R12: ffff88020e943840 R13: ffff88021509bdcc R14: 00000000ffffffff R15: ffff88021509bdd0 FS: 00007f21adb86740(0000) GS:ffff88021f200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 0000000215bce000 CR4: 00000000001406f0 Call Trace: mutex_lock+0x16/0x25 cinergyt2_power_ctrl+0x1f/0x60 [dvb_usb_cinergyT2] dvb_usb_device_init+0x21e/0x5d0 [dvb_usb] cinergyt2_usb_probe+0x21/0x50 [dvb_usb_cinergyT2] usb_probe_interface+0xf3/0x2a0 driver_probe_device+0x208/0x2b0 __driver_attach+0x87/0x90 driver_probe_device+0x2b0/0x2b0 bus_for_each_dev+0x52/0x80 bus_add_driver+0x1a3/0x220 driver_register+0x56/0xd0 usb_register_driver+0x77/0x130 do_one_initcall+0x46/0x180 free_vmap_area_noflush+0x38/0x70 kmem_cache_alloc+0x84/0xc0 do_init_module+0x50/0x1be load_module+0x1d8b/0x2100 find_symbol_in_section+0xa0/0xa0 SyS_finit_module+0x89/0x90 entry_SYSCALL_64_fastpath+0x13/0x94 Code: e8 a7 1d 00 00 8b 03 83 f8 01 0f 84 97 00 00 00 48 8b 43 10 4c 8d 7b 08 48 89 63 10 4c 89 3c 24 41 be ff ff ff ff 48 89 44 24 08 <48> 89 20 4c 89 64 24 10 eb 1a 49 c7 44 24 08 02 00 00 00 c6 43 RIP [<ffffffff846617af>] __mutex_lock_slowpath+0x6f/0x100 RSP <ffff8801f36efb10> CR2: 0000000000000000 So, move it to the struct dvb_usb_device and initialize it before calling the driver's callbacks. Reported-by: Jörg Otte <[email protected]> Tested-by: Jörg Otte <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 86e4ee7 commit 7724325

File tree

7 files changed

+61
-95
lines changed

7 files changed

+61
-95
lines changed

drivers/media/usb/dvb-usb/af9005.c

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ struct af9005_device_state {
5353
u8 sequence;
5454
int led_state;
5555
unsigned char data[256];
56-
struct mutex data_mutex;
5756
};
5857

5958
static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
@@ -72,7 +71,7 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
7271
return -EINVAL;
7372
}
7473

75-
mutex_lock(&st->data_mutex);
74+
mutex_lock(&d->data_mutex);
7675
st->data[0] = 14; /* rest of buffer length low */
7776
st->data[1] = 0; /* rest of buffer length high */
7877

@@ -140,7 +139,7 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
140139
values[i] = st->data[8 + i];
141140

142141
ret:
143-
mutex_unlock(&st->data_mutex);
142+
mutex_unlock(&d->data_mutex);
144143
return ret;
145144

146145
}
@@ -481,7 +480,7 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,
481480
}
482481
packet_len = wlen + 5;
483482

484-
mutex_lock(&st->data_mutex);
483+
mutex_lock(&d->data_mutex);
485484

486485
st->data[0] = (u8) (packet_len & 0xff);
487486
st->data[1] = (u8) ((packet_len & 0xff00) >> 8);
@@ -512,7 +511,7 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,
512511
rbuf[i] = st->data[i + 7];
513512
}
514513

515-
mutex_unlock(&st->data_mutex);
514+
mutex_unlock(&d->data_mutex);
516515
return ret;
517516
}
518517

@@ -523,7 +522,7 @@ int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values,
523522
u8 seq;
524523
int ret, i;
525524

526-
mutex_lock(&st->data_mutex);
525+
mutex_lock(&d->data_mutex);
527526

528527
memset(st->data, 0, sizeof(st->data));
529528

@@ -559,7 +558,7 @@ int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values,
559558
for (i = 0; i < len; i++)
560559
values[i] = st->data[6 + i];
561560
}
562-
mutex_unlock(&st->data_mutex);
561+
mutex_unlock(&d->data_mutex);
563562

564563
return ret;
565564
}
@@ -847,7 +846,7 @@ static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state)
847846
return 0;
848847
}
849848

850-
mutex_lock(&st->data_mutex);
849+
mutex_lock(&d->data_mutex);
851850

852851
/* deb_info("rc_query\n"); */
853852
st->data[0] = 3; /* rest of packet length low */
@@ -890,7 +889,7 @@ static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state)
890889
}
891890

892891
ret:
893-
mutex_unlock(&st->data_mutex);
892+
mutex_unlock(&d->data_mutex);
894893
return ret;
895894
}
896895

@@ -1004,20 +1003,8 @@ static struct dvb_usb_device_properties af9005_properties;
10041003
static int af9005_usb_probe(struct usb_interface *intf,
10051004
const struct usb_device_id *id)
10061005
{
1007-
struct dvb_usb_device *d;
1008-
struct af9005_device_state *st;
1009-
int ret;
1010-
1011-
ret = dvb_usb_device_init(intf, &af9005_properties,
1012-
THIS_MODULE, &d, adapter_nr);
1013-
1014-
if (ret < 0)
1015-
return ret;
1016-
1017-
st = d->priv;
1018-
mutex_init(&st->data_mutex);
1019-
1020-
return 0;
1006+
return dvb_usb_device_init(intf, &af9005_properties,
1007+
THIS_MODULE, NULL, adapter_nr);
10211008
}
10221009

10231010
enum af9005_usb_table_entry {

drivers/media/usb/dvb-usb/cinergyT2-core.c

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
4242
struct cinergyt2_state {
4343
u8 rc_counter;
4444
unsigned char data[64];
45-
struct mutex data_mutex;
4645
};
4746

4847
/* We are missing a release hook with usb_device data */
@@ -56,12 +55,12 @@ static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)
5655
struct cinergyt2_state *st = d->priv;
5756
int ret;
5857

59-
mutex_lock(&st->data_mutex);
58+
mutex_lock(&d->data_mutex);
6059
st->data[0] = CINERGYT2_EP1_CONTROL_STREAM_TRANSFER;
6160
st->data[1] = enable ? 1 : 0;
6261

6362
ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 64, 0);
64-
mutex_unlock(&st->data_mutex);
63+
mutex_unlock(&d->data_mutex);
6564

6665
return ret;
6766
}
@@ -71,12 +70,12 @@ static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable)
7170
struct cinergyt2_state *st = d->priv;
7271
int ret;
7372

74-
mutex_lock(&st->data_mutex);
73+
mutex_lock(&d->data_mutex);
7574
st->data[0] = CINERGYT2_EP1_SLEEP_MODE;
7675
st->data[1] = enable ? 0 : 1;
7776

7877
ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 3, 0);
79-
mutex_unlock(&st->data_mutex);
78+
mutex_unlock(&d->data_mutex);
8079

8180
return ret;
8281
}
@@ -89,15 +88,15 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
8988

9089
adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
9190

92-
mutex_lock(&st->data_mutex);
91+
mutex_lock(&d->data_mutex);
9392
st->data[0] = CINERGYT2_EP1_GET_FIRMWARE_VERSION;
9493

9594
ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0);
9695
if (ret < 0) {
9796
deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep "
9897
"state info\n");
9998
}
100-
mutex_unlock(&st->data_mutex);
99+
mutex_unlock(&d->data_mutex);
101100

102101
/* Copy this pointer as we are gonna need it in the release phase */
103102
cinergyt2_usb_device = adap->dev;
@@ -166,7 +165,7 @@ static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
166165

167166
*state = REMOTE_NO_KEY_PRESSED;
168167

169-
mutex_lock(&st->data_mutex);
168+
mutex_lock(&d->data_mutex);
170169
st->data[0] = CINERGYT2_EP1_GET_RC_EVENTS;
171170

172171
ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0);
@@ -202,29 +201,17 @@ static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
202201
}
203202

204203
ret:
205-
mutex_unlock(&st->data_mutex);
204+
mutex_unlock(&d->data_mutex);
206205
return ret;
207206
}
208207

209208
static int cinergyt2_usb_probe(struct usb_interface *intf,
210209
const struct usb_device_id *id)
211210
{
212-
struct dvb_usb_device *d;
213-
struct cinergyt2_state *st;
214-
int ret;
215-
216-
ret = dvb_usb_device_init(intf, &cinergyt2_properties,
217-
THIS_MODULE, &d, adapter_nr);
218-
if (ret < 0)
219-
return ret;
220-
221-
st = d->priv;
222-
mutex_init(&st->data_mutex);
223-
224-
return 0;
211+
return dvb_usb_device_init(intf, &cinergyt2_properties,
212+
THIS_MODULE, NULL, adapter_nr);
225213
}
226214

227-
228215
static struct usb_device_id cinergyt2_usb_table[] = {
229216
{ USB_DEVICE(USB_VID_TERRATEC, 0x0038) },
230217
{ 0 }

drivers/media/usb/dvb-usb/cxusb.c

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
6868

6969
wo = (rbuf == NULL || rlen == 0); /* write-only */
7070

71-
mutex_lock(&st->data_mutex);
71+
mutex_lock(&d->data_mutex);
7272
st->data[0] = cmd;
7373
memcpy(&st->data[1], wbuf, wlen);
7474
if (wo)
@@ -77,7 +77,7 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
7777
ret = dvb_usb_generic_rw(d, st->data, 1 + wlen,
7878
rbuf, rlen, 0);
7979

80-
mutex_unlock(&st->data_mutex);
80+
mutex_unlock(&d->data_mutex);
8181
return ret;
8282
}
8383

@@ -1461,43 +1461,36 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties;
14611461
static int cxusb_probe(struct usb_interface *intf,
14621462
const struct usb_device_id *id)
14631463
{
1464-
struct dvb_usb_device *d;
1465-
struct cxusb_state *st;
1466-
14671464
if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties,
1468-
THIS_MODULE, &d, adapter_nr) ||
1465+
THIS_MODULE, NULL, adapter_nr) ||
14691466
0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties,
1470-
THIS_MODULE, &d, adapter_nr) ||
1467+
THIS_MODULE, NULL, adapter_nr) ||
14711468
0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties,
1472-
THIS_MODULE, &d, adapter_nr) ||
1469+
THIS_MODULE, NULL, adapter_nr) ||
14731470
0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties,
1474-
THIS_MODULE, &d, adapter_nr) ||
1471+
THIS_MODULE, NULL, adapter_nr) ||
14751472
0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties,
1476-
THIS_MODULE, &d, adapter_nr) ||
1473+
THIS_MODULE, NULL, adapter_nr) ||
14771474
0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties,
1478-
THIS_MODULE, &d, adapter_nr) ||
1475+
THIS_MODULE, NULL, adapter_nr) ||
14791476
0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties,
1480-
THIS_MODULE, &d, adapter_nr) ||
1477+
THIS_MODULE, NULL, adapter_nr) ||
14811478
0 == dvb_usb_device_init(intf,
14821479
&cxusb_bluebird_nano2_needsfirmware_properties,
1483-
THIS_MODULE, &d, adapter_nr) ||
1480+
THIS_MODULE, NULL, adapter_nr) ||
14841481
0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties,
1485-
THIS_MODULE, &d, adapter_nr) ||
1482+
THIS_MODULE, NULL, adapter_nr) ||
14861483
0 == dvb_usb_device_init(intf,
14871484
&cxusb_bluebird_dualdig4_rev2_properties,
1488-
THIS_MODULE, &d, adapter_nr) ||
1485+
THIS_MODULE, NULL, adapter_nr) ||
14891486
0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties,
1490-
THIS_MODULE, &d, adapter_nr) ||
1487+
THIS_MODULE, NULL, adapter_nr) ||
14911488
0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties,
1492-
THIS_MODULE, &d, adapter_nr) ||
1489+
THIS_MODULE, NULL, adapter_nr) ||
14931490
0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties,
1494-
THIS_MODULE, &d, adapter_nr) ||
1495-
0) {
1496-
st = d->priv;
1497-
mutex_init(&st->data_mutex);
1498-
1491+
THIS_MODULE, NULL, adapter_nr) ||
1492+
0)
14991493
return 0;
1500-
}
15011494

15021495
return -EINVAL;
15031496
}

drivers/media/usb/dvb-usb/cxusb.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ struct cxusb_state {
3737
struct i2c_client *i2c_client_tuner;
3838

3939
unsigned char data[MAX_XFER_SIZE];
40-
struct mutex data_mutex;
4140
};
4241

4342
#endif

0 commit comments

Comments
 (0)