From 7b01738112608ce47083178ae2b9ebadf02d32cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20H=C3=A4dicke?= 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 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. ] __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:[] [] __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: [] list_del+0xd/0x30 [] usb_gadget_unregister_driver+0xaa/0xc0 [udc_core] [] unregister_gadget+0x27/0x60 [libcomposite] [] ? mutex_lock+0x1a/0x30 [] gadget_dev_desc_UDC_store+0x88/0xe0 [libcomposite] [] configfs_write_file+0xa0/0x100 [configfs] [] __vfs_write+0x37/0x160 [] ? __fd_install+0x30/0xd0 [] ? _raw_spin_unlock+0xe/0x10 [] vfs_write+0xb8/0x1b0 [] SyS_write+0x58/0xc0 [] ? __close_fd+0x94/0xc0 [] 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 [] __list_del_entry+0x29/0xc0 RSP CR2: 0000000000000000 ---[ end trace 99fc090ab3ff6cbc ]--- Fixes: f1bddbb ("usb: gadget: Fix binding to UDC via configfs interface") Signed-off-by: Felix Hädicke Tested-by: Krzysztof Opasiak Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 9483489080f66..0402177f93cdd 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -1317,7 +1317,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) {