diff options
author | Richard Röjfors <richard.rojfors@pelagicore.com> | 2010-12-01 05:53:00 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-03 15:05:35 -0500 |
commit | df4fedeaa623f6af0b72c0089000b5ea5540ed22 (patch) | |
tree | 503ed250e2e7eac02c33c5e81af67716eb6efbf0 /drivers/usb/gadget/u_audio.c | |
parent | 0ae86689d88bebba16c2db899f845446578d53b3 (diff) |
usb: g_audio: Fix crash at driver removal
If g_audio fails to open the sound control device, it crashes at removal:
Insertion:
[ 4143.836536] g_audio gadget: unable to open sound control device file: /dev/snd/controlC0
[ 4143.836543] g_audio gadget: we need at least one control device
[ 4143.836551] g_audio gadget: Linux USB Audio Gadget, version: Dec 18, 2008
[ 4143.836558] g_audio gadget: g_audio ready
Removal:
[ 4146.802643] BUG: unable to handle kernel paging request at 00023018
[ 4146.802655] IP: [<c10af9f5>] filp_close+0xa/0x5b
[ 4146.802674] *pdpt = 0000000015426001 *pde = 0000000000000000
[ 4146.802684] Oops: 0000 [#1] PREEMPT SMP
[ 4146.802692] last sysfs file: /sys/power/state
[ 4146.802701] Modules linked in: g_audio(-) ioh_udc fuse asix usbnet [last unloaded: g_audio]
[ 4146.802719]
[ 4146.802728] Pid: 1394, comm: rmmod Not tainted 2.6.33.5-26.1-ivi #1 To be filled by O.E.M./To be filled by O.E.M.
[ 4146.802738] EIP: 0060:[<c10af9f5>] EFLAGS: 00010206 CPU: 0
[ 4146.802746] EIP is at filp_close+0xa/0x5b
[ 4146.802753] EAX: 00023000 EBX: 00023000 ECX: 00000046 EDX: df842680
[ 4146.802760] ESI: e071cd4c EDI: df842680 EBP: ddbbbef0 ESP: ddbbbee4
[ 4146.802768] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
[ 4146.802776] Process rmmod (pid: 1394, ti=ddbba000 task=dd95a4f0 task.ti=ddbba000)
[ 4146.802782] Stack:
[ 4146.802787] d540c280 e071cd4c df2bc000 ddbbbefc e071b82c df11e440 ddbbbf04 e071c622
[ 4146.802804] <0> ddbbbf28 e071c47f 00000008 e071cd74 df11e464 df2bc01c df2bc000 e071ce68
[ 4146.802822] <0> 00000880 ddbbbf38 e07fd1b8 e071cef0 00000000 ddbbbf40 e071b9f4 ddbbbf48
[ 4146.802842] Call Trace:
[ 4146.802857] [<e071b82c>] ? gaudio_cleanup+0x87/0xe0 [g_audio]
[ 4146.802869] [<e071c622>] ? audio_unbind+0x8/0xc [g_audio]
[ 4146.802881] [<e071c47f>] ? composite_unbind+0x8d/0xcb [g_audio]
[ 4146.802895] [<e07fd1b8>] ? usb_gadget_unregister_driver+0x7b/0xc0 [ioh_udc]
[ 4146.802908] [<e071b9f4>] ? usb_composite_unregister+0x15/0x17 [g_audio]
[ 4146.802920] [<e071c633>] ? cleanup+0xd/0xf [g_audio]
[ 4146.802932] [<c105a938>] ? sys_delete_module+0x185/0x1dd
[ 4146.802944] [<c101c3ea>] ? do_page_fault+0x248/0x276
[ 4146.802956] [<c10027d0>] ? sysenter_do_call+0x12/0x26
[ 4146.802962] Code: 12 5f 3a 00 8b 43 04 8b 40 0c 0f b3 30 3b 73 44 73 03 89 73 44 89 f8 e8 f1 61 3a 00 5b 5e 5f 5d c3 55 89 e5 57 89 d7 56 53 89 c3 <8b> 40 18 85 c0 75 0f 68 32 15 5e c1 31 f6 e8 52 39 3a 00 5a eb
[ 4146.803058] EIP: [<c10af9f5>] filp_close+0xa/0x5b SS:ESP 0068:ddbbbee4
[ 4146.803071] CR2: 0000000000023018
[ 4146.803112] ---[ end trace 0989a7e023da0434 ]---
This patch makes sure not to assign the_card if gaudio_open_snd_dev fails,
since the parent function will deallocate the card.
Also make sure all filp's in gaudio_open_snd_dev is assigned NULL upon error
and gaudio_close_snd_dev only cleanups when the filp's are non-NULL.
Signed-off-by: Richard Röjfors <richard.rojfors@pelagicore.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget/u_audio.c')
-rw-r--r-- | drivers/usb/gadget/u_audio.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/usb/gadget/u_audio.c b/drivers/usb/gadget/u_audio.c index 7a86d2c9109c..59ffe1ecf1c9 100644 --- a/drivers/usb/gadget/u_audio.c +++ b/drivers/usb/gadget/u_audio.c | |||
@@ -255,6 +255,7 @@ static int gaudio_open_snd_dev(struct gaudio *card) | |||
255 | ERROR(card, "No such PCM capture device: %s\n", fn_cap); | 255 | ERROR(card, "No such PCM capture device: %s\n", fn_cap); |
256 | snd->substream = NULL; | 256 | snd->substream = NULL; |
257 | snd->card = NULL; | 257 | snd->card = NULL; |
258 | snd->filp = NULL; | ||
258 | } else { | 259 | } else { |
259 | pcm_file = snd->filp->private_data; | 260 | pcm_file = snd->filp->private_data; |
260 | snd->substream = pcm_file->substream; | 261 | snd->substream = pcm_file->substream; |
@@ -273,17 +274,17 @@ static int gaudio_close_snd_dev(struct gaudio *gau) | |||
273 | 274 | ||
274 | /* Close control device */ | 275 | /* Close control device */ |
275 | snd = &gau->control; | 276 | snd = &gau->control; |
276 | if (!IS_ERR(snd->filp)) | 277 | if (snd->filp) |
277 | filp_close(snd->filp, current->files); | 278 | filp_close(snd->filp, current->files); |
278 | 279 | ||
279 | /* Close PCM playback device and setup substream */ | 280 | /* Close PCM playback device and setup substream */ |
280 | snd = &gau->playback; | 281 | snd = &gau->playback; |
281 | if (!IS_ERR(snd->filp)) | 282 | if (snd->filp) |
282 | filp_close(snd->filp, current->files); | 283 | filp_close(snd->filp, current->files); |
283 | 284 | ||
284 | /* Close PCM capture device and setup substream */ | 285 | /* Close PCM capture device and setup substream */ |
285 | snd = &gau->capture; | 286 | snd = &gau->capture; |
286 | if (!IS_ERR(snd->filp)) | 287 | if (snd->filp) |
287 | filp_close(snd->filp, current->files); | 288 | filp_close(snd->filp, current->files); |
288 | 289 | ||
289 | return 0; | 290 | return 0; |
@@ -304,8 +305,7 @@ int __init gaudio_setup(struct gaudio *card) | |||
304 | ret = gaudio_open_snd_dev(card); | 305 | ret = gaudio_open_snd_dev(card); |
305 | if (ret) | 306 | if (ret) |
306 | ERROR(card, "we need at least one control device\n"); | 307 | ERROR(card, "we need at least one control device\n"); |
307 | 308 | else if (!the_card) | |
308 | if (!the_card) | ||
309 | the_card = card; | 309 | the_card = card; |
310 | 310 | ||
311 | return ret; | 311 | return ret; |