| From 9087c082f82a40910c9f57c54279080789125941 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Felix=20H=C3=A4dicke?= <felixhaedicke@web.de> |
| Date: Thu, 29 Dec 2016 23:02:11 +0100 |
| Subject: [PATCH] usb: gadget: udc: core: fix return code of |
| usb_gadget_probe_driver() |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| commit 7b01738112608ce47083178ae2b9ebadf02d32cc upstream. |
| |
| This fixes a regression which was introduced by commit f1bddbb, by |
| reverting a small fragment of commit 855ed04. |
| |
| If the following conditions were met, usb_gadget_probe_driver() returned |
| 0, although the call was unsuccessful: |
| 1. A particular UDC was specified by thge gadget driver (using member |
| "udc_name" of struct usb_gadget_driver). |
| 2. The UDC with this name is available. |
| 3. Another gadget driver is already bound to this gadget. |
| 4. The gadget driver has the "match_existing_only" flag set. |
| In this case, the return code variable "ret" is set to 0, the return |
| code of a strcmp() call (to check for the second condition). |
| |
| This also fixes an oops which could occur in the following scenario: |
| 1. Two usb gadget instances were configured using configfs. |
| 2. The first gadget configuration was bound to a UDC (using the configfs |
| attribute "UDC"). |
| 3. It was tried to bind the second gadget configuration to the same UDC |
| in the same way. This operation was then wrongly reported as being |
| successful. |
| 4. The second gadget configuration's "UDC" attribute is cleared, to |
| unbind the (not really bound) second gadget configuration from the UDC. |
| |
| <BUG: unable to handle kernel NULL pointer dereference |
| at (null) |
| IP: [<ffffffff94f5e5e9>] __list_del_entry+0x29/0xc0 |
| PGD 41b4c5067 |
| PUD 41a598067 |
| PMD 0 |
| |
| Oops: 0000 [#1] SMP |
| Modules linked in: cdc_acm usb_f_fs usb_f_serial |
| usb_f_acm u_serial libcomposite configfs dummy_hcd bnep intel_rapl |
| x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm |
| snd_hda_codec_hdmi irqbypass crct10dif_pclmul crc32_pclmul |
| ghash_clmulni_intel aesni_intel aes_x86_64 lrw gf128mul glue_helper |
| ablk_helper cryptd snd_hda_codec_realtek snd_hda_codec_generic serio_raw |
| uvcvideo videobuf2_vmalloc btusb snd_usb_audio snd_hda_intel |
| videobuf2_memops btrtl snd_hda_codec snd_hda_core snd_usbmidi_lib btbcm |
| videobuf2_v4l2 btintel snd_hwdep videobuf2_core snd_seq_midi bluetooth |
| snd_seq_midi_event videodev xpad efi_pstore snd_pcm_oss rfkill joydev |
| media crc16 ff_memless snd_mixer_oss snd_rawmidi nls_ascii snd_pcm |
| snd_seq snd_seq_device nls_cp437 mei_me snd_timer vfat sg udc_core |
| lpc_ich fat |
| efivars mfd_core mei snd soundcore battery nuvoton_cir rc_core evdev |
| intel_smartconnect ie31200_edac edac_core shpchp tpm_tis tpm_tis_core |
| tpm parport_pc ppdev lp parport efivarfs autofs4 btrfs xor raid6_pq |
| hid_logitech_hidpp hid_logitech_dj hid_generic usbhid hid uas |
| usb_storage sr_mod cdrom sd_mod ahci libahci nouveau i915 crc32c_intel |
| i2c_algo_bit psmouse ttm xhci_pci libata scsi_mod ehci_pci |
| drm_kms_helper xhci_hcd ehci_hcd r8169 mii usbcore drm nvme nvme_core |
| fjes button [last unloaded: net2280] |
| CPU: 5 PID: 829 Comm: bash Not tainted 4.9.0-rc7 #1 |
| Hardware name: To Be Filled By O.E.M. To Be Filled By O.E.M./Z77 |
| Extreme3, BIOS P1.50 07/11/2013 |
| task: ffff880419ce4040 task.stack: ffffc90002ed4000 |
| RIP: 0010:[<ffffffff94f5e5e9>] [<ffffffff94f5e5e9>] |
| __list_del_entry+0x29/0xc0 |
| RSP: 0018:ffffc90002ed7d68 EFLAGS: 00010207 |
| RAX: 0000000000000000 RBX: ffff88041787ec30 RCX: dead000000000200 |
| RDX: 0000000000000000 RSI: ffff880417482002 RDI: ffff88041787ec30 |
| RBP: ffffc90002ed7d68 R08: 0000000000000000 R09: 0000000000000010 |
| R10: 0000000000000000 R11: ffff880419ce4040 R12: ffff88041787eb68 |
| R13: ffff88041787eaa8 R14: ffff88041560a2c0 R15: 0000000000000001 |
| FS: 00007fe4e49b8700(0000) GS:ffff88042f340000(0000) |
| knlGS:0000000000000000 |
| CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 |
| CR2: 0000000000000000 CR3: 000000041b4c4000 CR4: 00000000001406e0 |
| Stack: |
| ffffc90002ed7d80 ffffffff94f5e68d ffffffffc0ae5ef0 ffffc90002ed7da0 |
| ffffffffc0ae22aa ffff88041787e800 ffff88041787e800 ffffc90002ed7dc0 |
| ffffffffc0d7a727 ffffffff952273fa ffff88041aba5760 ffffc90002ed7df8 |
| Call Trace: |
| [<ffffffff94f5e68d>] list_del+0xd/0x30 |
| [<ffffffffc0ae22aa>] usb_gadget_unregister_driver+0xaa/0xc0 [udc_core] |
| [<ffffffffc0d7a727>] unregister_gadget+0x27/0x60 [libcomposite] |
| [<ffffffff952273fa>] ? mutex_lock+0x1a/0x30 |
| [<ffffffffc0d7a9b8>] gadget_dev_desc_UDC_store+0x88/0xe0 [libcomposite] |
| [<ffffffffc0af8aa0>] configfs_write_file+0xa0/0x100 [configfs] |
| [<ffffffff94e10d27>] __vfs_write+0x37/0x160 |
| [<ffffffff94e31430>] ? __fd_install+0x30/0xd0 |
| [<ffffffff95229dae>] ? _raw_spin_unlock+0xe/0x10 |
| [<ffffffff94e11458>] vfs_write+0xb8/0x1b0 |
| [<ffffffff94e128f8>] SyS_write+0x58/0xc0 |
| [<ffffffff94e31594>] ? __close_fd+0x94/0xc0 |
| [<ffffffff9522a0fb>] entry_SYSCALL_64_fastpath+0x1e/0xad |
| Code: 66 90 55 48 8b 07 48 b9 00 01 00 00 00 00 ad de 48 8b 57 08 48 89 |
| e5 48 39 c8 74 29 48 b9 00 02 00 00 00 00 ad de 48 39 ca 74 3a <4c> 8b |
| 02 4c 39 c7 75 52 4c 8b 40 08 4c 39 c7 75 66 48 89 50 08 |
| RIP [<ffffffff94f5e5e9>] __list_del_entry+0x29/0xc0 |
| RSP <ffffc90002ed7d68> |
| CR2: 0000000000000000 |
| ---[ end trace 99fc090ab3ff6cbc ]--- |
| |
| Fixes: f1bddbb ("usb: gadget: Fix binding to UDC via configfs |
| interface") |
| Signed-off-by: Felix Hädicke <felixhaedicke@web.de> |
| Tested-by: Krzysztof Opasiak <k.opasiak@samsung.com> |
| Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c |
| index 40c04bb25f2f..b4c47a58ee18 100644 |
| --- a/drivers/usb/gadget/udc/core.c |
| +++ b/drivers/usb/gadget/udc/core.c |
| @@ -1319,7 +1319,11 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver) |
| if (!ret) |
| break; |
| } |
| - if (!ret && !udc->driver) |
| + if (ret) |
| + ret = -ENODEV; |
| + else if (udc->driver) |
| + ret = -EBUSY; |
| + else |
| goto found; |
| } else { |
| list_for_each_entry(udc, &udc_list, list) { |
| -- |
| 2.10.1 |
| |