1. 16 3月, 2018 2 次提交
  2. 12 3月, 2018 1 次提交
    • G
      Revert "usb: core: Add "quirks" parameter for usbcore" · 95713fb8
      Greg Kroah-Hartman 提交于
      This reverts commit b27560e4 as it
      breaks the build for some arches :(
      Reported-by: Nkbuild test robot <fengguang.wu@intel.com>
      Cc: Kai-Heng Feng <kai.heng.feng@canonical.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      
      diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
      index 1d1d53f85ddd..70a7398c20e2 100644
      --- a/Documentation/admin-guide/kernel-parameters.txt
      +++ b/Documentation/admin-guide/kernel-parameters.txt
      @@ -4368,6 +4368,61 @@
      
       	usbcore.nousb	[USB] Disable the USB subsystem
      
      +	usbcore.quirks=
      +			[USB] A list of quirks entries to supplement or
      +			override the built-in usb core quirk list.  List
      +			entries are separated by commas.  Each entry has
      +			the form VID:PID:Flags where VID and PID are Vendor
      +			and Product ID values (4-digit hex numbers) and
      +			Flags is a set of characters, each corresponding
      +			to a common usb core quirk flag as follows:
      +				a = USB_QUIRK_STRING_FETCH_255 (string
      +					descriptors must not be fetched using
      +					a 255-byte read);
      +				b = USB_QUIRK_RESET_RESUME (device can't resume
      +					correctly so reset it instead);
      +				c = USB_QUIRK_NO_SET_INTF (device can't handle
      +					Set-Interface requests);
      +				d = USB_QUIRK_CONFIG_INTF_STRINGS (device can't
      +					handle its Configuration or Interface
      +					strings);
      +				e = USB_QUIRK_RESET (device can't be reset
      +					(e.g morph devices), don't use reset);
      +				f = USB_QUIRK_HONOR_BNUMINTERFACES (device has
      +					more interface descriptions than the
      +					bNumInterfaces count, and can't handle
      +					talking to these interfaces);
      +				g = USB_QUIRK_DELAY_INIT (device needs a pause
      +					during initialization, after we read
      +					the device descriptor);
      +				h = USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL (For
      +					high speed and super speed interrupt
      +					endpoints, the USB 2.0 and USB 3.0 spec
      +					require the interval in microframes (1
      +					microframe = 125 microseconds) to be
      +					calculated as interval = 2 ^
      +					(bInterval-1).
      +					Devices with this quirk report their
      +					bInterval as the result of this
      +					calculation instead of the exponent
      +					variable used in the calculation);
      +				i = USB_QUIRK_DEVICE_QUALIFIER (device can't
      +					handle device_qualifier descriptor
      +					requests);
      +				j = USB_QUIRK_IGNORE_REMOTE_WAKEUP (device
      +					generates spurious wakeup, ignore
      +					remote wakeup capability);
      +				k = USB_QUIRK_NO_LPM (device can't handle Link
      +					Power Management);
      +				l = USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL
      +					(Device reports its bInterval as linear
      +					frames instead of the USB 2.0
      +					calculation);
      +				m = USB_QUIRK_DISCONNECT_SUSPEND (Device needs
      +					to be disconnected before suspend to
      +					prevent spurious wakeup)
      +			Example: quirks=0781:5580:bk,0a5c:5834:gij
      +
       	usbhid.mousepoll=
       			[USBHID] The interval which mice are to be polled at.
      
      diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
      index f4a548471f0f..42faaeead81b 100644
      --- a/drivers/usb/core/quirks.c
      +++ b/drivers/usb/core/quirks.c
      @@ -11,6 +11,143 @@
       #include <linux/usb/hcd.h>
       #include "usb.h"
      
      +struct quirk_entry {
      +	u16 vid;
      +	u16 pid;
      +	u32 flags;
      +};
      +
      +static DEFINE_MUTEX(quirk_mutex);
      +
      +static struct quirk_entry *quirk_list;
      +static unsigned int quirk_count;
      +
      +static char quirks_param[128];
      +
      +static int quirks_param_set(const char *val, const struct kernel_param *kp)
      +{
      +	char *p, *field;
      +	u16 vid, pid;
      +	u32 flags;
      +	size_t i;
      +
      +	mutex_lock(&quirk_mutex);
      +
      +	if (!val || !*val) {
      +		quirk_count = 0;
      +		kfree(quirk_list);
      +		quirk_list = NULL;
      +		goto unlock;
      +	}
      +
      +	for (quirk_count = 1, i = 0; val[i]; i++)
      +		if (val[i] == ',')
      +			quirk_count++;
      +
      +	if (quirk_list) {
      +		kfree(quirk_list);
      +		quirk_list = NULL;
      +	}
      +
      +	quirk_list = kcalloc(quirk_count, sizeof(struct quirk_entry),
      +			     GFP_KERNEL);
      +	if (!quirk_list) {
      +		mutex_unlock(&quirk_mutex);
      +		return -ENOMEM;
      +	}
      +
      +	for (i = 0, p = (char *)val; p && *p;) {
      +		/* Each entry consists of VID:PID:flags */
      +		field = strsep(&p, ":");
      +		if (!field)
      +			break;
      +
      +		if (kstrtou16(field, 16, &vid))
      +			break;
      +
      +		field = strsep(&p, ":");
      +		if (!field)
      +			break;
      +
      +		if (kstrtou16(field, 16, &pid))
      +			break;
      +
      +		field = strsep(&p, ",");
      +		if (!field || !*field)
      +			break;
      +
      +		/* Collect the flags */
      +		for (flags = 0; *field; field++) {
      +			switch (*field) {
      +			case 'a':
      +				flags |= USB_QUIRK_STRING_FETCH_255;
      +				break;
      +			case 'b':
      +				flags |= USB_QUIRK_RESET_RESUME;
      +				break;
      +			case 'c':
      +				flags |= USB_QUIRK_NO_SET_INTF;
      +				break;
      +			case 'd':
      +				flags |= USB_QUIRK_CONFIG_INTF_STRINGS;
      +				break;
      +			case 'e':
      +				flags |= USB_QUIRK_RESET;
      +				break;
      +			case 'f':
      +				flags |= USB_QUIRK_HONOR_BNUMINTERFACES;
      +				break;
      +			case 'g':
      +				flags |= USB_QUIRK_DELAY_INIT;
      +				break;
      +			case 'h':
      +				flags |= USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL;
      +				break;
      +			case 'i':
      +				flags |= USB_QUIRK_DEVICE_QUALIFIER;
      +				break;
      +			case 'j':
      +				flags |= USB_QUIRK_IGNORE_REMOTE_WAKEUP;
      +				break;
      +			case 'k':
      +				flags |= USB_QUIRK_NO_LPM;
      +				break;
      +			case 'l':
      +				flags |= USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL;
      +				break;
      +			case 'm':
      +				flags |= USB_QUIRK_DISCONNECT_SUSPEND;
      +				break;
      +			/* Ignore unrecognized flag characters */
      +			}
      +		}
      +
      +		quirk_list[i++] = (struct quirk_entry)
      +			{ .vid = vid, .pid = pid, .flags = flags };
      +	}
      +
      +	if (i < quirk_count)
      +		quirk_count = i;
      +
      +unlock:
      +	mutex_unlock(&quirk_mutex);
      +
      +	return param_set_copystring(val, kp);
      +}
      +
      +static const struct kernel_param_ops quirks_param_ops = {
      +	.set = quirks_param_set,
      +	.get = param_get_string,
      +};
      +
      +static struct kparam_string quirks_param_string = {
      +	.maxlen = sizeof(quirks_param),
      +	.string = quirks_param,
      +};
      +
      +module_param_cb(quirks, &quirks_param_ops, &quirks_param_string, 0644);
      +MODULE_PARM_DESC(quirks, "Add/modify USB quirks by specifying quirks=vendorID:productID:quirks");
      +
       /* Lists of quirky USB devices, split in device quirks and interface quirks.
        * Device quirks are applied at the very beginning of the enumeration process,
        * right after reading the device descriptor. They can thus only match on device
      @@ -320,8 +457,8 @@ static int usb_amd_resume_quirk(struct usb_device *udev)
       	return 0;
       }
      
      -static u32 __usb_detect_quirks(struct usb_device *udev,
      -			       const struct usb_device_id *id)
      +static u32 usb_detect_static_quirks(struct usb_device *udev,
      +				    const struct usb_device_id *id)
       {
       	u32 quirks = 0;
      
      @@ -339,21 +476,43 @@ static u32 __usb_detect_quirks(struct usb_device *udev,
       	return quirks;
       }
      
      +static u32 usb_detect_dynamic_quirks(struct usb_device *udev)
      +{
      +	u16 vid = le16_to_cpu(udev->descriptor.idVendor);
      +	u16 pid = le16_to_cpu(udev->descriptor.idProduct);
      +	int i, flags = 0;
      +
      +	mutex_lock(&quirk_mutex);
      +
      +	for (i = 0; i < quirk_count; i++) {
      +		if (vid == quirk_list[i].vid && pid == quirk_list[i].pid) {
      +			flags = quirk_list[i].flags;
      +			break;
      +		}
      +	}
      +
      +	mutex_unlock(&quirk_mutex);
      +
      +	return flags;
      +}
      +
       /*
        * Detect any quirks the device has, and do any housekeeping for it if needed.
        */
       void usb_detect_quirks(struct usb_device *udev)
       {
      -	udev->quirks = __usb_detect_quirks(udev, usb_quirk_list);
      +	udev->quirks = usb_detect_static_quirks(udev, usb_quirk_list);
      
       	/*
       	 * Pixart-based mice would trigger remote wakeup issue on AMD
       	 * Yangtze chipset, so set them as RESET_RESUME flag.
       	 */
       	if (usb_amd_resume_quirk(udev))
      -		udev->quirks |= __usb_detect_quirks(udev,
      +		udev->quirks |= usb_detect_static_quirks(udev,
       				usb_amd_resume_quirk_list);
      
      +	udev->quirks ^= usb_detect_dynamic_quirks(udev);
      +
       	if (udev->quirks)
       		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
       			udev->quirks);
      @@ -372,7 +531,7 @@ void usb_detect_interface_quirks(struct usb_device *udev)
       {
       	u32 quirks;
      
      -	quirks = __usb_detect_quirks(udev, usb_interface_quirk_list);
      +	quirks = usb_detect_static_quirks(udev, usb_interface_quirk_list);
       	if (quirks == 0)
       		return;
      
      @@ -380,3 +539,11 @@ void usb_detect_interface_quirks(struct usb_device *udev)
       		quirks);
       	udev->quirks |= quirks;
       }
      +
      +void usb_release_quirk_list(void)
      +{
      +	mutex_lock(&quirk_mutex);
      +	kfree(quirk_list);
      +	quirk_list = NULL;
      +	mutex_unlock(&quirk_mutex);
      +}
      diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
      index 2f5fbc56a9dd..0adb6345ff2e 100644
      --- a/drivers/usb/core/usb.c
      +++ b/drivers/usb/core/usb.c
      @@ -1259,6 +1259,7 @@ static void __exit usb_exit(void)
       	if (usb_disabled())
       		return;
      
      +	usb_release_quirk_list();
       	usb_deregister_device_driver(&usb_generic_driver);
       	usb_major_cleanup();
       	usb_deregister(&usbfs_driver);
      diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
      index 149cc7480971..546a2219454b 100644
      --- a/drivers/usb/core/usb.h
      +++ b/drivers/usb/core/usb.h
      @@ -36,6 +36,7 @@ extern void usb_deauthorize_interface(struct usb_interface *);
       extern void usb_authorize_interface(struct usb_interface *);
       extern void usb_detect_quirks(struct usb_device *udev);
       extern void usb_detect_interface_quirks(struct usb_device *udev);
      +extern void usb_release_quirk_list(void);
       extern int usb_remove_device(struct usb_device *udev);
      
       extern int usb_get_device_descriptor(struct usb_device *dev,
      95713fb8
  3. 10 3月, 2018 28 次提交
  4. 07 3月, 2018 2 次提交
  5. 22 2月, 2018 2 次提交
  6. 20 2月, 2018 2 次提交
  7. 16 2月, 2018 3 次提交
    • D
      usb: cdc_acm: prevent race at write to acm while system resumes · b86b8eb6
      Dominik Bozek 提交于
      ACM driver may accept data to transmit while system is not fully
      resumed. In this case ACM driver buffers data and prepare URBs
      on usb anchor list.
      There is a little chance that two tasks put a char and initiate
      acm_tty_flush_chars(). In such a case, driver will put one URB
      twice on usb anchor list.
      This patch also reset length of data before resue of a buffer.
      This not only prevent sending rubbish, but also lower risc of race.
      
      Without this patch we hit following kernel panic in one of our
      stabilty/stress tests.
      
      [   46.884442] *list_add double add*: new=ffff9b2ab7289330, prev=ffff9b2ab7289330, next=ffff9b2ab81e28e0.
      [   46.884476] Modules linked in: hci_uart btbcm bluetooth rfkill_gpio igb_avb(O) cfg80211 snd_soc_sst_bxt_tdf8532 snd_soc_skl snd_soc_skl_ipc snd_soc_sst_ipc snd_soc_sst_dsp snd_soc_sst_acpi snd_soc_sst_match snd_hda_ext_core snd_hda_core trusty_timer trusty_wall trusty_log trusty_virtio trusty_ipc trusty_mem trusty_irq trusty virtio_ring virtio intel_ipu4_mmu_bxtB0 lib2600_mod_bxtB0 intel_ipu4_isys_mod_bxtB0 lib2600psys_mod_bxtB0 intel_ipu4_psys_mod_bxtB0 intel_ipu4_mod_bxtB0 intel_ipu4_wrapper_bxtB0 intel_ipu4_acpi videobuf2_dma_contig as3638 dw9714 lm3643 crlmodule smiapp smiapp_pll
      [   46.884480] CPU: 1 PID: 33 Comm: kworker/u8:1 Tainted: G     U  W  O    4.9.56-quilt-2e5dc0ac-g618ed69ced6e-dirty #4
      [   46.884489] Workqueue: events_unbound flush_to_ldisc
      [   46.884494]  ffffb98ac012bb08 ffffffffad3e82e5 ffffb98ac012bb58 0000000000000000
      [   46.884497]  ffffb98ac012bb48 ffffffffad0a23d1 00000024ad6374dd ffff9b2ab7289330
      [   46.884500]  ffff9b2ab81e28e0 ffff9b2ab7289330 0000000000000002 0000000000000000
      [   46.884501] Call Trace:
      [   46.884507]  [<ffffffffad3e82e5>] dump_stack+0x67/0x92
      [   46.884511]  [<ffffffffad0a23d1>] __warn+0xd1/0xf0
      [   46.884513]  [<ffffffffad0a244f>] warn_slowpath_fmt+0x5f/0x80
      [   46.884516]  [<ffffffffad407443>] __list_add+0xb3/0xc0
      [   46.884521]  [<ffffffffad71133c>] *usb_anchor_urb*+0x4c/0xa0
      [   46.884524]  [<ffffffffad782c6f>] *acm_tty_flush_chars*+0x8f/0xb0
      [   46.884527]  [<ffffffffad782cd1>] *acm_tty_put_char*+0x41/0x100
      [   46.884530]  [<ffffffffad4ced34>] tty_put_char+0x24/0x40
      [   46.884533]  [<ffffffffad4d3bf5>] do_output_char+0xa5/0x200
      [   46.884535]  [<ffffffffad4d3e98>] __process_echoes+0x148/0x290
      [   46.884538]  [<ffffffffad4d654c>] n_tty_receive_buf_common+0x57c/0xb00
      [   46.884541]  [<ffffffffad4d6ae4>] n_tty_receive_buf2+0x14/0x20
      [   46.884543]  [<ffffffffad4d9662>] tty_ldisc_receive_buf+0x22/0x50
      [   46.884545]  [<ffffffffad4d9c05>] flush_to_ldisc+0xc5/0xe0
      [   46.884549]  [<ffffffffad0bcfe8>] process_one_work+0x148/0x440
      [   46.884551]  [<ffffffffad0bdc19>] worker_thread+0x69/0x4a0
      [   46.884554]  [<ffffffffad0bdbb0>] ? max_active_store+0x80/0x80
      [   46.884556]  [<ffffffffad0c2e10>] kthread+0x110/0x130
      [   46.884559]  [<ffffffffad0c2d00>] ? kthread_park+0x60/0x60
      [   46.884563]  [<ffffffffadad9917>] ret_from_fork+0x27/0x40
      [   46.884566] ---[ end trace 3bd599058b8a9eb3 ]---
      Signed-off-by: NDominik Bozek <dominikx.bozek@intel.com>
      Signed-off-by: NKuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
      Acked-by: NOliver Neukum <oneukum@suse.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      b86b8eb6
    • J
      sparc,leon: Select USB_UHCI_BIG_ENDIAN_{MMIO,DESC} · 5efad9ee
      James Hogan 提交于
      Now that USB_UHCI_BIG_ENDIAN_MMIO and USB_UHCI_BIG_ENDIAN_DESC are moved
      outside of the USB_SUPPORT conditional, simply select them from
      SPARC_LEON rather than by the symbol's defaults in drivers/usb/Kconfig,
      similar to how it is done for USB_EHCI_BIG_ENDIAN_MMIO and
      USB_EHCI_BIG_ENDIAN_DESC.
      Signed-off-by: NJames Hogan <jhogan@kernel.org>
      Cc: "David S. Miller" <davem@davemloft.net>
      Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
      Cc: Corentin Labbe <clabbe.montjoie@gmail.com>
      Cc: sparclinux@vger.kernel.org
      Cc: linux-usb@vger.kernel.org
      Acked-by: NDavid S. Miller <davem@davemloft.net>
      Patchwork: https://patchwork.linux-mips.org/patch/18560/
      5efad9ee
    • J
      usb: Move USB_UHCI_BIG_ENDIAN_* out of USB_SUPPORT · ec897569
      James Hogan 提交于
      Move the Kconfig symbols USB_UHCI_BIG_ENDIAN_MMIO and
      USB_UHCI_BIG_ENDIAN_DESC out of drivers/usb/host/Kconfig, which is
      conditional upon USB && USB_SUPPORT, so that it can be freely selected
      by platform Kconfig symbols in architecture code.
      
      For example once the MIPS_GENERIC platform selects are fixed in commit
      2e6522c5 ("MIPS: Fix typo BIG_ENDIAN to CPU_BIG_ENDIAN"), the MIPS
      32r6_defconfig warns like so:
      
      warning: (MIPS_GENERIC) selects USB_UHCI_BIG_ENDIAN_MMIO which has unmet direct dependencies (USB_SUPPORT && USB)
      warning: (MIPS_GENERIC) selects USB_UHCI_BIG_ENDIAN_DESC which has unmet direct dependencies (USB_SUPPORT && USB)
      
      Fixes: 2e6522c5 ("MIPS: Fix typo BIG_ENDIAN to CPU_BIG_ENDIAN")
      Signed-off-by: NJames Hogan <jhogan@kernel.org>
      Cc: Corentin Labbe <clabbe.montjoie@gmail.com>
      Cc: Ralf Baechle <ralf@linux-mips.org>
      Cc: Paul Burton <paul.burton@mips.com>
      Cc: linux-usb@vger.kernel.org
      Cc: linux-mips@linux-mips.org
      Acked-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      Patchwork: https://patchwork.linux-mips.org/patch/18559/
      ec897569