summaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/qmi_wwan.c
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2012-06-21 23:11:18 +0000
committerDavid S. Miller <davem@davemloft.net>2012-06-28 16:53:28 -0700
commitd9b8706843a501034d09bea63ca6723a2ed02b11 (patch)
tree62a15bb769efc8636805106886103d131402660e /drivers/net/usb/qmi_wwan.c
parent9acc7bde23ebb19a704395f76490685e1513e422 (diff)
net: qmi_wwan: fix Oops while disconnecting
usbnet_disconnect() will set intfdata to NULL before calling the minidriver unbind function. The cdc_wdm subdriver cannot know that it is disconnecting until the qmi_wwan unbind function has called its disconnect function. This means that we must be able to support the cdc_wdm subdriver operating normally while usbnet_disconnect() is running, and in particular that intfdata may be NULL. The only place this matters is in qmi_wwan_cdc_wdm_manage_power which is called from cdc_wdm. Simply testing for NULL intfdata there is sufficient to allow it to continue working at all times. Fixes this Oops where a cdc-wdm device was closed while the USB device was disconnecting, causing wdm_release to call qmi_wwan_cdc_wdm_manage_power after intfdata was set to NULL by usbnet_disconnect: [41819.087460] BUG: unable to handle kernel NULL pointer dereference at 00000080 [41819.087815] IP: [<f8640458>] qmi_wwan_manage_power+0x68/0x90 [qmi_wwan] [41819.088028] *pdpt = 000000000314f001 *pde = 0000000000000000 [41819.088028] Oops: 0002 [#1] SMP [41819.088028] Modules linked in: qmi_wwan option usb_wwan usbserial usbnet cdc_wdm nls_iso8859_1 nls_cp437 vfat fat usb_storage bnep rfcomm bluetooth parport_pc ppdev binfmt_misc iptable_nat nf_nat nf_conntrack_ipv4 nf_conntrack nf_defrag_ipv4 iptable_mangle iptable_filter ip_tables x_tables dm_crypt uvcvideo snd_hda_codec_realtek snd_hda_intel videobuf2_core snd_hda_codec joydev videodev videobuf2_vmalloc hid_multitouch snd_hwdep arc4 videobuf2_memops snd_pcm snd_seq_midi snd_rawmidi snd_seq_midi_event ath9k mac80211 snd_seq ath9k_common ath9k_hw ath snd_timer snd_seq_device sparse_keymap dm_multipath scsi_dh coretemp mac_hid snd soundcore cfg80211 snd_page_alloc psmouse serio_raw microcode lp parport dm_mirror dm_region_hash dm_log usbhid hid i915 drm_kms_helper drm r8169 i2c_algo_bit wmi video [last unloaded: qmi_wwan] [41819.088028] [41819.088028] Pid: 23292, comm: qmicli Not tainted 3.4.0-5-generic #11-Ubuntu GIGABYTE T1005/T1005 [41819.088028] EIP: 0060:[<f8640458>] EFLAGS: 00010246 CPU: 1 [41819.088028] EIP is at qmi_wwan_manage_power+0x68/0x90 [qmi_wwan] [41819.088028] EAX: 00000000 EBX: 00000000 ECX: 000000c3 EDX: 00000000 [41819.088028] ESI: c3b27658 EDI: 00000000 EBP: c298bea4 ESP: c298be98 [41819.088028] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [41819.088028] CR0: 8005003b CR2: 00000080 CR3: 3605e000 CR4: 000007f0 [41819.088028] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [41819.088028] DR6: ffff0ff0 DR7: 00000400 [41819.088028] Process qmicli (pid: 23292, ti=c298a000 task=f343b280 task.ti=c298a000) [41819.088028] Stack: [41819.088028] 00000000 c3b27658 e2a80d00 c298beb0 f864051a c3b27600 c298bec0 f9027099 [41819.088028] c2fd6000 00000008 c298bef0 c1147f96 00000001 00000000 00000000 f4e54790 [41819.088028] ecf43a00 ecf43a00 c2fd6008 c2fd6000 ebbd7600 ffffffb9 c298bf08 c1144474 [41819.088028] Call Trace: [41819.088028] [<f864051a>] qmi_wwan_cdc_wdm_manage_power+0x1a/0x20 [qmi_wwan] [41819.088028] [<f9027099>] wdm_release+0x69/0x70 [cdc_wdm] [41819.088028] [<c1147f96>] fput+0xe6/0x210 [41819.088028] [<c1144474>] filp_close+0x54/0x80 [41819.088028] [<c1046a65>] put_files_struct+0x75/0xc0 [41819.088028] [<c1046b56>] exit_files+0x46/0x60 [41819.088028] [<c1046f81>] do_exit+0x141/0x780 [41819.088028] [<c107248f>] ? wake_up_state+0xf/0x20 [41819.088028] [<c1053f48>] ? signal_wake_up+0x28/0x40 [41819.088028] [<c1054f3b>] ? zap_other_threads+0x6b/0x80 [41819.088028] [<c1047864>] do_group_exit+0x34/0xa0 [41819.088028] [<c10478e8>] sys_exit_group+0x18/0x20 [41819.088028] [<c15bb7df>] sysenter_do_call+0x12/0x28 [41819.088028] Code: 04 83 e7 01 c1 e7 03 0f b6 42 18 83 e0 f7 09 f8 88 42 18 8b 43 04 e8 48 9a dd c8 89 f0 8b 5d f4 8b 75 f8 8b 7d fc 89 ec 5d c3 90 <f0> ff 88 80 00 00 00 0f 94 c0 84 c0 75 b7 31 f6 8b 5d f4 89 f0 [41819.088028] EIP: [<f8640458>] qmi_wwan_manage_power+0x68/0x90 [qmi_wwan] SS:ESP 0068:c298be98 [41819.088028] CR2: 0000000000000080 [41819.149492] ---[ end trace 0944479ff8257f55 ]--- Reported-by: Marius Bjørnstad Kotsbak <marius.kotsbak@gmail.com> Cc: <stable@vger.kernel.org> # v3.4 Signed-off-by: Bjørn Mork <bjorn@mork.no> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb/qmi_wwan.c')
-rw-r--r--drivers/net/usb/qmi_wwan.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 3767a122586..b01960fcfbc 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -197,6 +197,10 @@ err:
static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on)
{
struct usbnet *dev = usb_get_intfdata(intf);
+
+ /* can be called while disconnecting */
+ if (!dev)
+ return 0;
return qmi_wwan_manage_power(dev, on);
}