Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e032dc5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files


Pull USB fixes from Greg Kroah-Hartman:
 "Here are a few fixes and new device ids for the 3.5-rc6 tree.

  The PCI changes resolve a long-standing issue with resuming some EHCI
  controllers.  It has been acked by the PCI maintainer, and he asked
  for it to go through my USB tree instead of his.

  The xhci patches also resolve a number of reported issues.

  Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org&gt;">

* tag 'usb-3.5-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  PCI: EHCI: fix crash during suspend on ASUS computers
  USB: cdc-wdm: fix lockup on error in wdm_read
  USB: metro-usb: fix tty_flip_buffer_push use
  USB: option: Add MEDIATEK product ids
  USB: option: add ZTE MF60
  xhci: Fix hang on back-to-back Set TR Deq Ptr commands.
  usb: Add support for root hub port status CAS
parents 5f351f06 dbf0e4c7
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -748,6 +748,18 @@ static int pci_pm_suspend_noirq(struct device *dev)

	pci_pm_set_unknown_state(pci_dev);

	/*
	 * Some BIOSes from ASUS have a bug: If a USB EHCI host controller's
	 * PCI COMMAND register isn't 0, the BIOS assumes that the controller
	 * hasn't been quiesced and tries to turn it off.  If the controller
	 * is already in D3, this can hang or cause memory corruption.
	 *
	 * Since the value of the COMMAND register doesn't matter once the
	 * device has been suspended, we can safely set it to 0 here.
	 */
	if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
		pci_write_config_word(pci_dev, PCI_COMMAND, 0);

	return 0;
}

+0 −5
Original line number Diff line number Diff line
@@ -1744,11 +1744,6 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
	if (target_state == PCI_POWER_ERROR)
		return -EIO;

	/* Some devices mustn't be in D3 during system sleep */
	if (target_state == PCI_D3hot &&
			(dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP))
		return 0;

	pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev));

	error = pci_set_power_state(dev, target_state);
+0 −26
Original line number Diff line number Diff line
@@ -2929,32 +2929,6 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev)
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);

/*
 * The Intel 6 Series/C200 Series chipset's EHCI controllers on many
 * ASUS motherboards will cause memory corruption or a system crash
 * if they are in D3 while the system is put into S3 sleep.
 */
static void __devinit asus_ehci_no_d3(struct pci_dev *dev)
{
	const char *sys_info;
	static const char good_Asus_board[] = "P8Z68-V";

	if (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP)
		return;
	if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK)
		return;
	sys_info = dmi_get_system_info(DMI_BOARD_NAME);
	if (sys_info && memcmp(sys_info, good_Asus_board,
			sizeof(good_Asus_board) - 1) == 0)
		return;

	dev_info(&dev->dev, "broken D3 during system sleep on ASUS\n");
	dev->dev_flags |= PCI_DEV_FLAGS_NO_D3_DURING_SLEEP;
	device_set_wakeup_capable(&dev->dev, false);
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3);

static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
			  struct pci_fixup *end)
{
+2 −0
Original line number Diff line number Diff line
@@ -500,6 +500,8 @@ static ssize_t wdm_read
			goto retry;
		}
		if (!desc->reslength) { /* zero length read */
			dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
			clear_bit(WDM_READ, &desc->flags);
			spin_unlock_irq(&desc->iuspin);
			goto retry;
		}
+10 −8
Original line number Diff line number Diff line
@@ -2324,12 +2324,16 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
static int hub_port_reset(struct usb_hub *hub, int port1,
			struct usb_device *udev, unsigned int delay, bool warm);

/* Is a USB 3.0 port in the Inactive state? */
static bool hub_port_inactive(struct usb_hub *hub, u16 portstatus)
/* Is a USB 3.0 port in the Inactive or Complinance Mode state?
 * Port worm reset is required to recover
 */
static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus)
{
	return hub_is_superspeed(hub->hdev) &&
		(portstatus & USB_PORT_STAT_LINK_STATE) ==
		USB_SS_PORT_LS_SS_INACTIVE;
		(((portstatus & USB_PORT_STAT_LINK_STATE) ==
		  USB_SS_PORT_LS_SS_INACTIVE) ||
		 ((portstatus & USB_PORT_STAT_LINK_STATE) ==
		  USB_SS_PORT_LS_COMP_MOD)) ;
}

static int hub_port_wait_reset(struct usb_hub *hub, int port1,
@@ -2365,7 +2369,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
			 *
			 * See https://bugzilla.kernel.org/show_bug.cgi?id=41752
			 */
			if (hub_port_inactive(hub, portstatus)) {
			if (hub_port_warm_reset_required(hub, portstatus)) {
				int ret;

				if ((portchange & USB_PORT_STAT_C_CONNECTION))
@@ -4408,9 +4412,7 @@ static void hub_events(void)
			/* Warm reset a USB3 protocol port if it's in
			 * SS.Inactive state.
			 */
			if (hub_is_superspeed(hub->hdev) &&
				(portstatus & USB_PORT_STAT_LINK_STATE)
					== USB_SS_PORT_LS_SS_INACTIVE) {
			if (hub_port_warm_reset_required(hub, portstatus)) {
				dev_dbg(hub_dev, "warm reset port %d\n", i);
				hub_port_reset(hub, i, NULL,
						HUB_BH_RESET_TIME, true);
Loading