From df4fedeaa623f6af0b72c0089000b5ea5540ed22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Wed, 1 Dec 2010 11:53:00 +0100 Subject: usb: g_audio: Fix crash at driver removal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: [] 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:[] 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] [] ? gaudio_cleanup+0x87/0xe0 [g_audio] [ 4146.802869] [] ? audio_unbind+0x8/0xc [g_audio] [ 4146.802881] [] ? composite_unbind+0x8d/0xcb [g_audio] [ 4146.802895] [] ? usb_gadget_unregister_driver+0x7b/0xc0 [ioh_udc] [ 4146.802908] [] ? usb_composite_unregister+0x15/0x17 [g_audio] [ 4146.802920] [] ? cleanup+0xd/0xf [g_audio] [ 4146.802932] [] ? sys_delete_module+0x185/0x1dd [ 4146.802944] [] ? do_page_fault+0x248/0x276 [ 4146.802956] [] ? 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: [] 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 Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/u_audio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/u_audio.c b/drivers/usb/gadget/u_audio.c index 7a86d2c..59ffe1e 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) ERROR(card, "No such PCM capture device: %s\n", fn_cap); snd->substream = NULL; snd->card = NULL; + snd->filp = NULL; } else { pcm_file = snd->filp->private_data; snd->substream = pcm_file->substream; @@ -273,17 +274,17 @@ static int gaudio_close_snd_dev(struct gaudio *gau) /* Close control device */ snd = &gau->control; - if (!IS_ERR(snd->filp)) + if (snd->filp) filp_close(snd->filp, current->files); /* Close PCM playback device and setup substream */ snd = &gau->playback; - if (!IS_ERR(snd->filp)) + if (snd->filp) filp_close(snd->filp, current->files); /* Close PCM capture device and setup substream */ snd = &gau->capture; - if (!IS_ERR(snd->filp)) + if (snd->filp) filp_close(snd->filp, current->files); return 0; @@ -304,8 +305,7 @@ int __init gaudio_setup(struct gaudio *card) ret = gaudio_open_snd_dev(card); if (ret) ERROR(card, "we need at least one control device\n"); - - if (!the_card) + else if (!the_card) the_card = card; return ret; -- cgit v1.1