diff options
Diffstat (limited to 'drivers/usb')
50 files changed, 549 insertions, 358 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index f699abab1787..148f3ee70286 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -19,6 +19,12 @@ config USB_EHCI_BIG_ENDIAN_MMIO  config USB_EHCI_BIG_ENDIAN_DESC  	bool +config USB_UHCI_BIG_ENDIAN_MMIO +	bool + +config USB_UHCI_BIG_ENDIAN_DESC +	bool +  menuconfig USB_SUPPORT  	bool "USB support"  	depends on HAS_IOMEM diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 06b3b54a0e68..7b366a6c0b49 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -174,6 +174,7 @@ static int acm_wb_alloc(struct acm *acm)  		wb = &acm->wb[wbn];  		if (!wb->use) {  			wb->use = 1; +			wb->len = 0;  			return wbn;  		}  		wbn = (wbn + 1) % ACM_NW; @@ -805,16 +806,18 @@ static int acm_tty_write(struct tty_struct *tty,  static void acm_tty_flush_chars(struct tty_struct *tty)  {  	struct acm *acm = tty->driver_data; -	struct acm_wb *cur = acm->putbuffer; +	struct acm_wb *cur;  	int err;  	unsigned long flags; +	spin_lock_irqsave(&acm->write_lock, flags); + +	cur = acm->putbuffer;  	if (!cur) /* nothing to do */ -		return; +		goto out;  	acm->putbuffer = NULL;  	err = usb_autopm_get_interface_async(acm->control); -	spin_lock_irqsave(&acm->write_lock, flags);  	if (err < 0) {  		cur->use = 0;  		acm->putbuffer = cur; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index c64cf6c4a83d..0c11d40a12bc 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -151,6 +151,10 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,  	ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout); +	/* Linger a bit, prior to the next control message. */ +	if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG) +		msleep(200); +  	kfree(dr);  	return ret; diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 4024926c1d68..54b019e267c5 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -226,8 +226,12 @@ static const struct usb_device_id usb_quirk_list[] = {  	{ USB_DEVICE(0x1a0a, 0x0200), .driver_info =  			USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, +	/* Corsair K70 RGB */ +	{ USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT }, +  	/* Corsair Strafe RGB */ -	{ USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT }, +	{ USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT | +	  USB_QUIRK_DELAY_CTRL_MSG },  	/* Corsair K70 LUX */  	{ USB_DEVICE(0x1b1c, 0x1b36), .driver_info = USB_QUIRK_DELAY_INIT }, diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index e4c3ce0de5de..5bcad1d869b5 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -1917,7 +1917,9 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,  		/* Not specific buffer needed for ep0 ZLP */  		dma_addr_t dma = hs_ep->desc_list_dma; -		dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep); +		if (!index) +			dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep); +  		dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0);  	} else {  		dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) | @@ -2974,9 +2976,13 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,  	if (ints & DXEPINT_STSPHSERCVD) {  		dev_dbg(hsotg->dev, "%s: StsPhseRcvd\n", __func__); -		/* Move to STATUS IN for DDMA */ -		if (using_desc_dma(hsotg)) -			dwc2_hsotg_ep0_zlp(hsotg, true); +		/* Safety check EP0 state when STSPHSERCVD asserted */ +		if (hsotg->ep0_state == DWC2_EP0_DATA_OUT) { +			/* Move to STATUS IN for DDMA */ +			if (using_desc_dma(hsotg)) +				dwc2_hsotg_ep0_zlp(hsotg, true); +		} +  	}  	if (ints & DXEPINT_BACK2BACKSETUP) @@ -3375,12 +3381,6 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,  	dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |  	       DXEPCTL_USBACTEP, hsotg->regs + DIEPCTL0); -	dwc2_hsotg_enqueue_setup(hsotg); - -	dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", -		dwc2_readl(hsotg->regs + DIEPCTL0), -		dwc2_readl(hsotg->regs + DOEPCTL0)); -  	/* clear global NAKs */  	val = DCTL_CGOUTNAK | DCTL_CGNPINNAK;  	if (!is_usb_reset) @@ -3391,6 +3391,12 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,  	mdelay(3);  	hsotg->lx_state = DWC2_L0; + +	dwc2_hsotg_enqueue_setup(hsotg); + +	dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", +		dwc2_readl(hsotg->regs + DIEPCTL0), +		dwc2_readl(hsotg->regs + DOEPCTL0));  }  static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 03fd20f0b496..c4a47496d2fb 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -137,7 +137,7 @@ static void dwc2_set_stm32f4x9_fsotg_params(struct dwc2_hsotg *hsotg)  	p->activate_stm_fs_transceiver = true;  } -static void dwc2_set_stm32f7xx_hsotg_params(struct dwc2_hsotg *hsotg) +static void dwc2_set_stm32f7_hsotg_params(struct dwc2_hsotg *hsotg)  {  	struct dwc2_core_params *p = &hsotg->params; @@ -164,8 +164,8 @@ const struct of_device_id dwc2_of_match_table[] = {  	{ .compatible = "st,stm32f4x9-fsotg",  	  .data = dwc2_set_stm32f4x9_fsotg_params },  	{ .compatible = "st,stm32f4x9-hsotg" }, -	{ .compatible = "st,stm32f7xx-hsotg", -	  .data = dwc2_set_stm32f7xx_hsotg_params }, +	{ .compatible = "st,stm32f7-hsotg", +	  .data = dwc2_set_stm32f7_hsotg_params },  	{},  };  MODULE_DEVICE_TABLE(of, dwc2_of_match_table); diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ade2ab00d37a..e94bf91cc58a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -100,6 +100,8 @@ static void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)  	reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));  	reg |= DWC3_GCTL_PRTCAPDIR(mode);  	dwc3_writel(dwc->regs, DWC3_GCTL, reg); + +	dwc->current_dr_role = mode;  }  static void __dwc3_set_mode(struct work_struct *work) @@ -133,8 +135,6 @@ static void __dwc3_set_mode(struct work_struct *work)  	dwc3_set_prtcap(dwc, dwc->desired_dr_role); -	dwc->current_dr_role = dwc->desired_dr_role; -  	spin_unlock_irqrestore(&dwc->lock, flags);  	switch (dwc->desired_dr_role) { @@ -175,7 +175,7 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode)  	dwc->desired_dr_role = mode;  	spin_unlock_irqrestore(&dwc->lock, flags); -	queue_work(system_power_efficient_wq, &dwc->drd_work); +	queue_work(system_freezable_wq, &dwc->drd_work);  }  u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) @@ -219,7 +219,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)  	 * XHCI driver will reset the host block. If dwc3 was configured for  	 * host-only mode, then we can return early.  	 */ -	if (dwc->dr_mode == USB_DR_MODE_HOST) +	if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST)  		return 0;  	reg = dwc3_readl(dwc->regs, DWC3_DCTL); @@ -234,6 +234,9 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)  		udelay(1);  	} while (--retries); +	phy_exit(dwc->usb3_generic_phy); +	phy_exit(dwc->usb2_generic_phy); +  	return -ETIMEDOUT;  } @@ -483,6 +486,22 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)  	parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);  } +static int dwc3_core_ulpi_init(struct dwc3 *dwc) +{ +	int intf; +	int ret = 0; + +	intf = DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3); + +	if (intf == DWC3_GHWPARAMS3_HSPHY_IFC_ULPI || +	    (intf == DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI && +	     dwc->hsphy_interface && +	     !strncmp(dwc->hsphy_interface, "ulpi", 4))) +		ret = dwc3_ulpi_init(dwc); + +	return ret; +} +  /**   * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core   * @dwc: Pointer to our controller context structure @@ -494,7 +513,6 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)  static int dwc3_phy_setup(struct dwc3 *dwc)  {  	u32 reg; -	int ret;  	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); @@ -565,9 +583,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)  		}  		/* FALLTHROUGH */  	case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: -		ret = dwc3_ulpi_init(dwc); -		if (ret) -			return ret;  		/* FALLTHROUGH */  	default:  		break; @@ -724,6 +739,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)  }  static int dwc3_core_get_phy(struct dwc3 *dwc); +static int dwc3_core_ulpi_init(struct dwc3 *dwc);  /**   * dwc3_core_init - Low-level initialization of DWC3 Core @@ -755,17 +771,27 @@ static int dwc3_core_init(struct dwc3 *dwc)  			dwc->maximum_speed = USB_SPEED_HIGH;  	} -	ret = dwc3_core_get_phy(dwc); +	ret = dwc3_phy_setup(dwc);  	if (ret)  		goto err0; -	ret = dwc3_core_soft_reset(dwc); -	if (ret) -		goto err0; +	if (!dwc->ulpi_ready) { +		ret = dwc3_core_ulpi_init(dwc); +		if (ret) +			goto err0; +		dwc->ulpi_ready = true; +	} -	ret = dwc3_phy_setup(dwc); +	if (!dwc->phys_ready) { +		ret = dwc3_core_get_phy(dwc); +		if (ret) +			goto err0a; +		dwc->phys_ready = true; +	} + +	ret = dwc3_core_soft_reset(dwc);  	if (ret) -		goto err0; +		goto err0a;  	dwc3_core_setup_global_control(dwc);  	dwc3_core_num_eps(dwc); @@ -838,6 +864,9 @@ err1:  	phy_exit(dwc->usb2_generic_phy);  	phy_exit(dwc->usb3_generic_phy); +err0a: +	dwc3_ulpi_exit(dwc); +  err0:  	return ret;  } @@ -916,7 +945,6 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)  	switch (dwc->dr_mode) {  	case USB_DR_MODE_PERIPHERAL: -		dwc->current_dr_role = DWC3_GCTL_PRTCAP_DEVICE;  		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);  		if (dwc->usb2_phy) @@ -932,7 +960,6 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)  		}  		break;  	case USB_DR_MODE_HOST: -		dwc->current_dr_role = DWC3_GCTL_PRTCAP_HOST;  		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);  		if (dwc->usb2_phy) @@ -1234,7 +1261,6 @@ err4:  err3:  	dwc3_free_event_buffers(dwc); -	dwc3_ulpi_exit(dwc);  err2:  	pm_runtime_allow(&pdev->dev); @@ -1284,7 +1310,7 @@ static int dwc3_remove(struct platform_device *pdev)  }  #ifdef CONFIG_PM -static int dwc3_suspend_common(struct dwc3 *dwc) +static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)  {  	unsigned long	flags; @@ -1296,6 +1322,10 @@ static int dwc3_suspend_common(struct dwc3 *dwc)  		dwc3_core_exit(dwc);  		break;  	case DWC3_GCTL_PRTCAP_HOST: +		/* do nothing during host runtime_suspend */ +		if (!PMSG_IS_AUTO(msg)) +			dwc3_core_exit(dwc); +		break;  	default:  		/* do nothing */  		break; @@ -1304,7 +1334,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc)  	return 0;  } -static int dwc3_resume_common(struct dwc3 *dwc) +static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)  {  	unsigned long	flags;  	int		ret; @@ -1320,6 +1350,13 @@ static int dwc3_resume_common(struct dwc3 *dwc)  		spin_unlock_irqrestore(&dwc->lock, flags);  		break;  	case DWC3_GCTL_PRTCAP_HOST: +		/* nothing to do on host runtime_resume */ +		if (!PMSG_IS_AUTO(msg)) { +			ret = dwc3_core_init(dwc); +			if (ret) +				return ret; +		} +		break;  	default:  		/* do nothing */  		break; @@ -1331,12 +1368,11 @@ static int dwc3_resume_common(struct dwc3 *dwc)  static int dwc3_runtime_checks(struct dwc3 *dwc)  {  	switch (dwc->current_dr_role) { -	case USB_DR_MODE_PERIPHERAL: -	case USB_DR_MODE_OTG: +	case DWC3_GCTL_PRTCAP_DEVICE:  		if (dwc->connected)  			return -EBUSY;  		break; -	case USB_DR_MODE_HOST: +	case DWC3_GCTL_PRTCAP_HOST:  	default:  		/* do nothing */  		break; @@ -1353,7 +1389,7 @@ static int dwc3_runtime_suspend(struct device *dev)  	if (dwc3_runtime_checks(dwc))  		return -EBUSY; -	ret = dwc3_suspend_common(dwc); +	ret = dwc3_suspend_common(dwc, PMSG_AUTO_SUSPEND);  	if (ret)  		return ret; @@ -1369,7 +1405,7 @@ static int dwc3_runtime_resume(struct device *dev)  	device_init_wakeup(dev, false); -	ret = dwc3_resume_common(dwc); +	ret = dwc3_resume_common(dwc, PMSG_AUTO_RESUME);  	if (ret)  		return ret; @@ -1416,7 +1452,7 @@ static int dwc3_suspend(struct device *dev)  	struct dwc3	*dwc = dev_get_drvdata(dev);  	int		ret; -	ret = dwc3_suspend_common(dwc); +	ret = dwc3_suspend_common(dwc, PMSG_SUSPEND);  	if (ret)  		return ret; @@ -1432,7 +1468,7 @@ static int dwc3_resume(struct device *dev)  	pinctrl_pm_select_default_state(dev); -	ret = dwc3_resume_common(dwc); +	ret = dwc3_resume_common(dwc, PMSG_RESUME);  	if (ret)  		return ret; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 03c7aaaac926..860d2bc184d1 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -158,13 +158,15 @@  #define DWC3_GDBGFIFOSPACE_TYPE(n)	(((n) << 5) & 0x1e0)  #define DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(n) (((n) >> 16) & 0xffff) -#define DWC3_TXFIFOQ		1 -#define DWC3_RXFIFOQ		3 -#define DWC3_TXREQQ		5 -#define DWC3_RXREQQ		7 -#define DWC3_RXINFOQ		9 -#define DWC3_DESCFETCHQ		13 -#define DWC3_EVENTQ		15 +#define DWC3_TXFIFOQ		0 +#define DWC3_RXFIFOQ		1 +#define DWC3_TXREQQ		2 +#define DWC3_RXREQQ		3 +#define DWC3_RXINFOQ		4 +#define DWC3_PSTATQ		5 +#define DWC3_DESCFETCHQ		6 +#define DWC3_EVENTQ		7 +#define DWC3_AUXEVENTQ		8  /* Global RX Threshold Configuration Register */  #define DWC3_GRXTHRCFG_MAXRXBURSTSIZE(n) (((n) & 0x1f) << 19) @@ -795,7 +797,9 @@ struct dwc3_scratchpad_array {   * @usb3_phy: pointer to USB3 PHY   * @usb2_generic_phy: pointer to USB2 PHY   * @usb3_generic_phy: pointer to USB3 PHY + * @phys_ready: flag to indicate that PHYs are ready   * @ulpi: pointer to ulpi interface + * @ulpi_ready: flag to indicate that ULPI is initialized   * @u2sel: parameter from Set SEL request.   * @u2pel: parameter from Set SEL request.   * @u1sel: parameter from Set SEL request. @@ -893,7 +897,10 @@ struct dwc3 {  	struct phy		*usb2_generic_phy;  	struct phy		*usb3_generic_phy; +	bool			phys_ready; +  	struct ulpi		*ulpi; +	bool			ulpi_ready;  	void __iomem		*regs;  	size_t			regs_size; diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c index 7ae0eefc7cc7..e54c3622eb28 100644 --- a/drivers/usb/dwc3/dwc3-of-simple.c +++ b/drivers/usb/dwc3/dwc3-of-simple.c @@ -143,6 +143,7 @@ static int dwc3_of_simple_remove(struct platform_device *pdev)  		clk_disable_unprepare(simple->clks[i]);  		clk_put(simple->clks[i]);  	} +	simple->num_clocks = 0;  	reset_control_assert(simple->resets);  	reset_control_put(simple->resets); diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index a4719e853b85..ed8b86517675 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -582,9 +582,25 @@ static int dwc3_omap_resume(struct device *dev)  	return 0;  } +static void dwc3_omap_complete(struct device *dev) +{ +	struct dwc3_omap	*omap = dev_get_drvdata(dev); + +	if (extcon_get_state(omap->edev, EXTCON_USB)) +		dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); +	else +		dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF); + +	if (extcon_get_state(omap->edev, EXTCON_USB_HOST)) +		dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); +	else +		dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT); +} +  static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {  	SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume) +	.complete = dwc3_omap_complete,  };  #define DEV_PM_OPS	(&dwc3_omap_dev_pm_ops) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 9c2e4a17918e..18be31d5743a 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -854,7 +854,12 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,  		trb++;  		trb->ctrl &= ~DWC3_TRB_CTRL_HWO;  		trace_dwc3_complete_trb(ep0, trb); -		ep0->trb_enqueue = 0; + +		if (r->direction) +			dwc->eps[1]->trb_enqueue = 0; +		else +			dwc->eps[0]->trb_enqueue = 0; +  		dwc->ep0_bounced = false;  	} diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 616ef49ccb49..2bda4eb1e9ac 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2745,6 +2745,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)  		break;  	} +	dwc->eps[1]->endpoint.maxpacket = dwc->gadget.ep0->maxpacket; +  	/* Enable USB2 LPM Capability */  	if ((dwc->revision > DWC3_REVISION_194A) && diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 8f2cf3baa19c..d2428a9e8900 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1538,7 +1538,6 @@ ffs_fs_kill_sb(struct super_block *sb)  	if (sb->s_fs_info) {  		ffs_release_dev(sb->s_fs_info);  		ffs_data_closed(sb->s_fs_info); -		ffs_data_put(sb->s_fs_info);  	}  } @@ -1855,44 +1854,20 @@ static int ffs_func_eps_enable(struct ffs_function *func)  	spin_lock_irqsave(&func->ffs->eps_lock, flags);  	while(count--) { -		struct usb_endpoint_descriptor *ds; -		struct usb_ss_ep_comp_descriptor *comp_desc = NULL; -		int needs_comp_desc = false; -		int desc_idx; - -		if (ffs->gadget->speed == USB_SPEED_SUPER) { -			desc_idx = 2; -			needs_comp_desc = true; -		} else if (ffs->gadget->speed == USB_SPEED_HIGH) -			desc_idx = 1; -		else -			desc_idx = 0; - -		/* fall-back to lower speed if desc missing for current speed */ -		do { -			ds = ep->descs[desc_idx]; -		} while (!ds && --desc_idx >= 0); - -		if (!ds) { -			ret = -EINVAL; -			break; -		} -  		ep->ep->driver_data = ep; -		ep->ep->desc = ds; -		if (needs_comp_desc) { -			comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds + -					USB_DT_ENDPOINT_SIZE); -			ep->ep->maxburst = comp_desc->bMaxBurst + 1; -			ep->ep->comp_desc = comp_desc; +		ret = config_ep_by_speed(func->gadget, &func->function, ep->ep); +		if (ret) { +			pr_err("%s: config_ep_by_speed(%s) returned %d\n", +					__func__, ep->ep->name, ret); +			break;  		}  		ret = usb_ep_enable(ep->ep);  		if (likely(!ret)) {  			epfile->ep = ep; -			epfile->in = usb_endpoint_dir_in(ds); -			epfile->isoc = usb_endpoint_xfer_isoc(ds); +			epfile->in = usb_endpoint_dir_in(ep->ep->desc); +			epfile->isoc = usb_endpoint_xfer_isoc(ep->ep->desc);  		} else {  			break;  		} @@ -2979,10 +2954,8 @@ static int _ffs_func_bind(struct usb_configuration *c,  	struct ffs_data *ffs = func->ffs;  	const int full = !!func->ffs->fs_descs_count; -	const int high = gadget_is_dualspeed(func->gadget) && -		func->ffs->hs_descs_count; -	const int super = gadget_is_superspeed(func->gadget) && -		func->ffs->ss_descs_count; +	const int high = !!func->ffs->hs_descs_count; +	const int super = !!func->ffs->ss_descs_count;  	int fs_len, hs_len, ss_len, ret, i;  	struct ffs_ep *eps_ptr; diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 11fe788b4308..d2dc1f00180b 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -524,6 +524,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)  		dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);  		return ret;  	} +	iad_desc.bFirstInterface = ret; +  	std_ac_if_desc.bInterfaceNumber = ret;  	uac2->ac_intf = ret;  	uac2->ac_alt = 0; diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 1e9567091d86..0875d38476ee 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -274,7 +274,6 @@ config USB_SNP_UDC_PLAT  	tristate "Synopsys USB 2.0 Device controller"  	depends on USB_GADGET && OF && HAS_DMA  	depends on EXTCON || EXTCON=n -	select USB_GADGET_DUALSPEED  	select USB_SNP_CORE  	default ARCH_BCM_IPROC  	help diff --git a/drivers/usb/gadget/udc/bdc/bdc_pci.c b/drivers/usb/gadget/udc/bdc/bdc_pci.c index 1e940f054cb8..6dbc489513cd 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_pci.c +++ b/drivers/usb/gadget/udc/bdc/bdc_pci.c @@ -77,6 +77,7 @@ static int bdc_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)  	if (ret) {  		dev_err(&pci->dev,  			"couldn't add resources to bdc device\n"); +		platform_device_put(bdc);  		return ret;  	} diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 859d5b11ba4c..1f8b19d9cf97 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -180,8 +180,8 @@ EXPORT_SYMBOL_GPL(usb_ep_alloc_request);  void usb_ep_free_request(struct usb_ep *ep,  				       struct usb_request *req)  { -	ep->ops->free_request(ep, req);  	trace_usb_ep_free_request(ep, req, 0); +	ep->ops->free_request(ep, req);  }  EXPORT_SYMBOL_GPL(usb_ep_free_request); diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index e5b4ee96c4bf..56b517a38865 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -1305,7 +1305,7 @@ static void udc_reset_ep_queue(struct fsl_udc *udc, u8 pipe)  {  	struct fsl_ep *ep = get_ep_by_pipe(udc, pipe); -	if (ep->name) +	if (ep->ep.name)  		nuke(ep, -ESHUTDOWN);  } @@ -1693,7 +1693,7 @@ static void dtd_complete_irq(struct fsl_udc *udc)  		curr_ep = get_ep_by_pipe(udc, i);  		/* If the ep is configured */ -		if (curr_ep->name == NULL) { +		if (!curr_ep->ep.name) {  			WARNING("Invalid EP?");  			continue;  		} diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 6e87af248367..409cde4e6a51 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -2410,7 +2410,7 @@ static int renesas_usb3_remove(struct platform_device *pdev)  	__renesas_usb3_ep_free_request(usb3->ep0_req);  	if (usb3->phy)  		phy_put(usb3->phy); -	pm_runtime_disable(usb3_to_dev(usb3)); +	pm_runtime_disable(&pdev->dev);  	return 0;  } diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 6150bed7cfa8..4fcfb3084b36 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -633,14 +633,6 @@ config USB_UHCI_ASPEED         bool         default y if ARCH_ASPEED -config USB_UHCI_BIG_ENDIAN_MMIO -	bool -	default y if SPARC_LEON - -config USB_UHCI_BIG_ENDIAN_DESC -	bool -	default y if SPARC_LEON -  config USB_FHCI_HCD  	tristate "Freescale QE USB Host Controller support"  	depends on OF_GPIO && QE_GPIO && QUICC_ENGINE diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index facafdf8fb95..d7641cbdee43 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -774,12 +774,12 @@ static struct urb *request_single_step_set_feature_urb(  	atomic_inc(&urb->use_count);  	atomic_inc(&urb->dev->urbnum);  	urb->setup_dma = dma_map_single( -			hcd->self.controller, +			hcd->self.sysdev,  			urb->setup_packet,  			sizeof(struct usb_ctrlrequest),  			DMA_TO_DEVICE);  	urb->transfer_dma = dma_map_single( -			hcd->self.controller, +			hcd->self.sysdev,  			urb->transfer_buffer,  			urb->transfer_buffer_length,  			DMA_FROM_DEVICE); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 88158324dcae..327630405695 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1188,10 +1188,10 @@ static int submit_single_step_set_feature(  	 * 15 secs after the setup  	 */  	if (is_setup) { -		/* SETUP pid */ +		/* SETUP pid, and interrupt after SETUP completion */  		qtd_fill(ehci, qtd, urb->setup_dma,  				sizeof(struct usb_ctrlrequest), -				token | (2 /* "setup" */ << 8), 8); +				QTD_IOC | token | (2 /* "setup" */ << 8), 8);  		submit_async(ehci, urb, &qtd_list, GFP_ATOMIC);  		return 0; /*Return now; we shall come back after 15 seconds*/ @@ -1228,12 +1228,8 @@ static int submit_single_step_set_feature(  	qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);  	list_add_tail(&qtd->qtd_list, head); -	/* dont fill any data in such packets */ -	qtd_fill(ehci, qtd, 0, 0, token, 0); - -	/* by default, enable interrupt on urb completion */ -	if (likely(!(urb->transfer_flags & URB_NO_INTERRUPT))) -		qtd->hw_token |= cpu_to_hc32(ehci, QTD_IOC); +	/* Interrupt after STATUS completion */ +	qtd_fill(ehci, qtd, 0, 0, token | QTD_IOC, 0);  	submit_async(ehci, urb, &qtd_list, GFP_KERNEL); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index ee9676349333..d088c340e4d0 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -74,6 +74,7 @@ static const char	hcd_name [] = "ohci_hcd";  #define	STATECHANGE_DELAY	msecs_to_jiffies(300)  #define	IO_WATCHDOG_DELAY	msecs_to_jiffies(275) +#define	IO_WATCHDOG_OFF		0xffffff00  #include "ohci.h"  #include "pci-quirks.h" @@ -231,7 +232,7 @@ static int ohci_urb_enqueue (  		}  		/* Start up the I/O watchdog timer, if it's not running */ -		if (!timer_pending(&ohci->io_watchdog) && +		if (ohci->prev_frame_no == IO_WATCHDOG_OFF &&  				list_empty(&ohci->eds_in_use) &&  				!(ohci->flags & OHCI_QUIRK_QEMU)) {  			ohci->prev_frame_no = ohci_frame_no(ohci); @@ -446,7 +447,8 @@ static int ohci_init (struct ohci_hcd *ohci)  	struct usb_hcd *hcd = ohci_to_hcd(ohci);  	/* Accept arbitrarily long scatter-gather lists */ -	hcd->self.sg_tablesize = ~0; +	if (!(hcd->driver->flags & HCD_LOCAL_MEM)) +		hcd->self.sg_tablesize = ~0;  	if (distrust_firmware)  		ohci->flags |= OHCI_QUIRK_HUB_POWER; @@ -501,6 +503,7 @@ static int ohci_init (struct ohci_hcd *ohci)  		return 0;  	timer_setup(&ohci->io_watchdog, io_watchdog_func, 0); +	ohci->prev_frame_no = IO_WATCHDOG_OFF;  	ohci->hcca = dma_alloc_coherent (hcd->self.controller,  			sizeof(*ohci->hcca), &ohci->hcca_dma, GFP_KERNEL); @@ -730,7 +733,7 @@ static void io_watchdog_func(struct timer_list *t)  	u32		head;  	struct ed	*ed;  	struct td	*td, *td_start, *td_next; -	unsigned	frame_no; +	unsigned	frame_no, prev_frame_no = IO_WATCHDOG_OFF;  	unsigned long	flags;  	spin_lock_irqsave(&ohci->lock, flags); @@ -835,7 +838,7 @@ static void io_watchdog_func(struct timer_list *t)  			}  		}  		if (!list_empty(&ohci->eds_in_use)) { -			ohci->prev_frame_no = frame_no; +			prev_frame_no = frame_no;  			ohci->prev_wdh_cnt = ohci->wdh_cnt;  			ohci->prev_donehead = ohci_readl(ohci,  					&ohci->regs->donehead); @@ -845,6 +848,7 @@ static void io_watchdog_func(struct timer_list *t)  	}   done: +	ohci->prev_frame_no = prev_frame_no;  	spin_unlock_irqrestore(&ohci->lock, flags);  } @@ -973,6 +977,7 @@ static void ohci_stop (struct usb_hcd *hcd)  	if (quirk_nec(ohci))  		flush_work(&ohci->nec_work);  	del_timer_sync(&ohci->io_watchdog); +	ohci->prev_frame_no = IO_WATCHDOG_OFF;  	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);  	ohci_usb_reset(ohci); diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index fb7aaa3b9d06..634f3c7bf774 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -311,8 +311,10 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)  		rc = ohci_rh_suspend (ohci, 0);  	spin_unlock_irq (&ohci->lock); -	if (rc == 0) +	if (rc == 0) {  		del_timer_sync(&ohci->io_watchdog); +		ohci->prev_frame_no = IO_WATCHDOG_OFF; +	}  	return rc;  } diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index b2ec8c399363..4ccb85a67bb3 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -1019,6 +1019,8 @@ skip_ed:  		 * have modified this list.  normally it's just prepending  		 * entries (which we'd ignore), but paranoia won't hurt.  		 */ +		*last = ed->ed_next; +		ed->ed_next = NULL;  		modified = 0;  		/* unlink urbs as requested, but rescan the list after @@ -1077,21 +1079,22 @@ rescan_this:  			goto rescan_this;  		/* -		 * If no TDs are queued, take ED off the ed_rm_list. +		 * If no TDs are queued, ED is now idle.  		 * Otherwise, if the HC is running, reschedule. -		 * If not, leave it on the list for further dequeues. +		 * If the HC isn't running, add ED back to the +		 * start of the list for later processing.  		 */  		if (list_empty(&ed->td_list)) { -			*last = ed->ed_next; -			ed->ed_next = NULL;  			ed->state = ED_IDLE;  			list_del(&ed->in_use_list);  		} else if (ohci->rh_state == OHCI_RH_RUNNING) { -			*last = ed->ed_next; -			ed->ed_next = NULL;  			ed_schedule(ohci, ed);  		} else { -			last = &ed->ed_next; +			ed->ed_next = ohci->ed_rm_list; +			ohci->ed_rm_list = ed; +			/* Don't loop on the same ED */ +			if (last == &ohci->ed_rm_list) +				last = &ed->ed_next;  		}  		if (modified) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 161536717025..67ad4bb6919a 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -66,6 +66,23 @@  #define	AX_INDXC		0x30  #define	AX_DATAC		0x34 +#define PT_ADDR_INDX		0xE8 +#define PT_READ_INDX		0xE4 +#define PT_SIG_1_ADDR		0xA520 +#define PT_SIG_2_ADDR		0xA521 +#define PT_SIG_3_ADDR		0xA522 +#define PT_SIG_4_ADDR		0xA523 +#define PT_SIG_1_DATA		0x78 +#define PT_SIG_2_DATA		0x56 +#define PT_SIG_3_DATA		0x34 +#define PT_SIG_4_DATA		0x12 +#define PT4_P1_REG		0xB521 +#define PT4_P2_REG		0xB522 +#define PT2_P1_REG		0xD520 +#define PT2_P2_REG		0xD521 +#define PT1_P1_REG		0xD522 +#define PT1_P2_REG		0xD523 +  #define	NB_PCIE_INDX_ADDR	0xe0  #define	NB_PCIE_INDX_DATA	0xe4  #define	PCIE_P_CNTL		0x10040 @@ -513,6 +530,98 @@ void usb_amd_dev_put(void)  EXPORT_SYMBOL_GPL(usb_amd_dev_put);  /* + * Check if port is disabled in BIOS on AMD Promontory host. + * BIOS Disabled ports may wake on connect/disconnect and need + * driver workaround to keep them disabled. + * Returns true if port is marked disabled. + */ +bool usb_amd_pt_check_port(struct device *device, int port) +{ +	unsigned char value, port_shift; +	struct pci_dev *pdev; +	u16 reg; + +	pdev = to_pci_dev(device); +	pci_write_config_word(pdev, PT_ADDR_INDX, PT_SIG_1_ADDR); + +	pci_read_config_byte(pdev, PT_READ_INDX, &value); +	if (value != PT_SIG_1_DATA) +		return false; + +	pci_write_config_word(pdev, PT_ADDR_INDX, PT_SIG_2_ADDR); + +	pci_read_config_byte(pdev, PT_READ_INDX, &value); +	if (value != PT_SIG_2_DATA) +		return false; + +	pci_write_config_word(pdev, PT_ADDR_INDX, PT_SIG_3_ADDR); + +	pci_read_config_byte(pdev, PT_READ_INDX, &value); +	if (value != PT_SIG_3_DATA) +		return false; + +	pci_write_config_word(pdev, PT_ADDR_INDX, PT_SIG_4_ADDR); + +	pci_read_config_byte(pdev, PT_READ_INDX, &value); +	if (value != PT_SIG_4_DATA) +		return false; + +	/* Check disabled port setting, if bit is set port is enabled */ +	switch (pdev->device) { +	case 0x43b9: +	case 0x43ba: +	/* +	 * device is AMD_PROMONTORYA_4(0x43b9) or PROMONTORYA_3(0x43ba) +	 * PT4_P1_REG bits[7..1] represents USB2.0 ports 6 to 0 +	 * PT4_P2_REG bits[6..0] represents ports 13 to 7 +	 */ +		if (port > 6) { +			reg = PT4_P2_REG; +			port_shift = port - 7; +		} else { +			reg = PT4_P1_REG; +			port_shift = port + 1; +		} +		break; +	case 0x43bb: +	/* +	 * device is AMD_PROMONTORYA_2(0x43bb) +	 * PT2_P1_REG bits[7..5] represents USB2.0 ports 2 to 0 +	 * PT2_P2_REG bits[5..0] represents ports 9 to 3 +	 */ +		if (port > 2) { +			reg = PT2_P2_REG; +			port_shift = port - 3; +		} else { +			reg = PT2_P1_REG; +			port_shift = port + 5; +		} +		break; +	case 0x43bc: +	/* +	 * device is AMD_PROMONTORYA_1(0x43bc) +	 * PT1_P1_REG[7..4] represents USB2.0 ports 3 to 0 +	 * PT1_P2_REG[5..0] represents ports 9 to 4 +	 */ +		if (port > 3) { +			reg = PT1_P2_REG; +			port_shift = port - 4; +		} else { +			reg = PT1_P1_REG; +			port_shift = port + 4; +		} +		break; +	default: +		return false; +	} +	pci_write_config_word(pdev, PT_ADDR_INDX, reg); +	pci_read_config_byte(pdev, PT_READ_INDX, &value); + +	return !(value & BIT(port_shift)); +} +EXPORT_SYMBOL_GPL(usb_amd_pt_check_port); + +/*   * Make sure the controller is completely inactive, unable to   * generate interrupts or do DMA.   */ diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index b68dcb5dd0fd..4ca0d9b7e463 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -17,6 +17,7 @@ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);  void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);  void sb800_prefetch(struct device *dev, int on);  bool usb_xhci_needs_pci_reset(struct pci_dev *pdev); +bool usb_amd_pt_check_port(struct device *device, int port);  #else  struct pci_dev;  static inline void usb_amd_quirk_pll_disable(void) {} @@ -25,6 +26,10 @@ static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}  static inline void usb_amd_dev_put(void) {}  static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}  static inline void sb800_prefetch(struct device *dev, int on) {} +static inline bool usb_amd_pt_check_port(struct device *device, int port) +{ +	return false; +}  #endif  /* CONFIG_USB_PCI */  #endif  /*  __LINUX_USB_PCI_QUIRKS_H  */ diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index a1ab8acf39ba..c359bae7b754 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -328,13 +328,14 @@ dbc_ep_do_queue(struct dbc_ep *dep, struct dbc_request *req)  int dbc_ep_queue(struct dbc_ep *dep, struct dbc_request *req,  		 gfp_t gfp_flags)  { +	unsigned long		flags;  	struct xhci_dbc		*dbc = dep->dbc;  	int			ret = -ESHUTDOWN; -	spin_lock(&dbc->lock); +	spin_lock_irqsave(&dbc->lock, flags);  	if (dbc->state == DS_CONFIGURED)  		ret = dbc_ep_do_queue(dep, req); -	spin_unlock(&dbc->lock); +	spin_unlock_irqrestore(&dbc->lock, flags);  	mod_delayed_work(system_wq, &dbc->event_work, 0); @@ -521,15 +522,16 @@ static void xhci_do_dbc_stop(struct xhci_hcd *xhci)  static int xhci_dbc_start(struct xhci_hcd *xhci)  {  	int			ret; +	unsigned long		flags;  	struct xhci_dbc		*dbc = xhci->dbc;  	WARN_ON(!dbc);  	pm_runtime_get_sync(xhci_to_hcd(xhci)->self.controller); -	spin_lock(&dbc->lock); +	spin_lock_irqsave(&dbc->lock, flags);  	ret = xhci_do_dbc_start(xhci); -	spin_unlock(&dbc->lock); +	spin_unlock_irqrestore(&dbc->lock, flags);  	if (ret) {  		pm_runtime_put(xhci_to_hcd(xhci)->self.controller); @@ -541,6 +543,7 @@ static int xhci_dbc_start(struct xhci_hcd *xhci)  static void xhci_dbc_stop(struct xhci_hcd *xhci)  { +	unsigned long		flags;  	struct xhci_dbc		*dbc = xhci->dbc;  	struct dbc_port		*port = &dbc->port; @@ -551,9 +554,9 @@ static void xhci_dbc_stop(struct xhci_hcd *xhci)  	if (port->registered)  		xhci_dbc_tty_unregister_device(xhci); -	spin_lock(&dbc->lock); +	spin_lock_irqsave(&dbc->lock, flags);  	xhci_do_dbc_stop(xhci); -	spin_unlock(&dbc->lock); +	spin_unlock_irqrestore(&dbc->lock, flags);  	pm_runtime_put_sync(xhci_to_hcd(xhci)->self.controller);  } @@ -779,14 +782,15 @@ static void xhci_dbc_handle_events(struct work_struct *work)  	int			ret;  	enum evtreturn		evtr;  	struct xhci_dbc		*dbc; +	unsigned long		flags;  	struct xhci_hcd		*xhci;  	dbc = container_of(to_delayed_work(work), struct xhci_dbc, event_work);  	xhci = dbc->xhci; -	spin_lock(&dbc->lock); +	spin_lock_irqsave(&dbc->lock, flags);  	evtr = xhci_dbc_do_handle_events(dbc); -	spin_unlock(&dbc->lock); +	spin_unlock_irqrestore(&dbc->lock, flags);  	switch (evtr) {  	case EVT_GSER: diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c index 8d47b6fbf973..75f0b92694ba 100644 --- a/drivers/usb/host/xhci-dbgtty.c +++ b/drivers/usb/host/xhci-dbgtty.c @@ -92,21 +92,23 @@ static void dbc_start_rx(struct dbc_port *port)  static void  dbc_read_complete(struct xhci_hcd *xhci, struct dbc_request *req)  { +	unsigned long		flags;  	struct xhci_dbc		*dbc = xhci->dbc;  	struct dbc_port		*port = &dbc->port; -	spin_lock(&port->port_lock); +	spin_lock_irqsave(&port->port_lock, flags);  	list_add_tail(&req->list_pool, &port->read_queue);  	tasklet_schedule(&port->push); -	spin_unlock(&port->port_lock); +	spin_unlock_irqrestore(&port->port_lock, flags);  }  static void dbc_write_complete(struct xhci_hcd *xhci, struct dbc_request *req)  { +	unsigned long		flags;  	struct xhci_dbc		*dbc = xhci->dbc;  	struct dbc_port		*port = &dbc->port; -	spin_lock(&port->port_lock); +	spin_lock_irqsave(&port->port_lock, flags);  	list_add(&req->list_pool, &port->write_pool);  	switch (req->status) {  	case 0: @@ -119,7 +121,7 @@ static void dbc_write_complete(struct xhci_hcd *xhci, struct dbc_request *req)  			  req->status);  		break;  	} -	spin_unlock(&port->port_lock); +	spin_unlock_irqrestore(&port->port_lock, flags);  }  static void xhci_dbc_free_req(struct dbc_ep *dep, struct dbc_request *req) @@ -327,12 +329,13 @@ static void dbc_rx_push(unsigned long _port)  {  	struct dbc_request	*req;  	struct tty_struct	*tty; +	unsigned long		flags;  	bool			do_push = false;  	bool			disconnect = false;  	struct dbc_port		*port = (void *)_port;  	struct list_head	*queue = &port->read_queue; -	spin_lock_irq(&port->port_lock); +	spin_lock_irqsave(&port->port_lock, flags);  	tty = port->port.tty;  	while (!list_empty(queue)) {  		req = list_first_entry(queue, struct dbc_request, list_pool); @@ -392,16 +395,17 @@ static void dbc_rx_push(unsigned long _port)  	if (!disconnect)  		dbc_start_rx(port); -	spin_unlock_irq(&port->port_lock); +	spin_unlock_irqrestore(&port->port_lock, flags);  }  static int dbc_port_activate(struct tty_port *_port, struct tty_struct *tty)  { +	unsigned long	flags;  	struct dbc_port	*port = container_of(_port, struct dbc_port, port); -	spin_lock_irq(&port->port_lock); +	spin_lock_irqsave(&port->port_lock, flags);  	dbc_start_rx(port); -	spin_unlock_irq(&port->port_lock); +	spin_unlock_irqrestore(&port->port_lock, flags);  	return 0;  } diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c index e26e685d8a57..5851052d4668 100644 --- a/drivers/usb/host/xhci-debugfs.c +++ b/drivers/usb/host/xhci-debugfs.c @@ -211,7 +211,7 @@ static void xhci_ring_dump_segment(struct seq_file *s,  static int xhci_ring_trb_show(struct seq_file *s, void *unused)  {  	int			i; -	struct xhci_ring	*ring = s->private; +	struct xhci_ring	*ring = *(struct xhci_ring **)s->private;  	struct xhci_segment	*seg = ring->first_seg;  	for (i = 0; i < ring->num_segs; i++) { @@ -387,7 +387,7 @@ void xhci_debugfs_create_endpoint(struct xhci_hcd *xhci,  	snprintf(epriv->name, sizeof(epriv->name), "ep%02d", ep_index);  	epriv->root = xhci_debugfs_create_ring_dir(xhci, -						   &dev->eps[ep_index].new_ring, +						   &dev->eps[ep_index].ring,  						   epriv->name,  						   spriv->root);  	spriv->eps[ep_index] = epriv; diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 46d5e08f05f1..72ebbc908e19 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1224,17 +1224,17 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  				temp = readl(port_array[wIndex]);  				break;  			} - -			/* Software should not attempt to set -			 * port link state above '3' (U3) and the port -			 * must be enabled. -			 */ -			if ((temp & PORT_PE) == 0 || -				(link_state > USB_SS_PORT_LS_U3)) { -				xhci_warn(xhci, "Cannot set link state.\n"); +			/* Port must be enabled */ +			if (!(temp & PORT_PE)) { +				retval = -ENODEV; +				break; +			} +			/* Can't set port link state above '3' (U3) */ +			if (link_state > USB_SS_PORT_LS_U3) { +				xhci_warn(xhci, "Cannot set port %d link state %d\n", +					 wIndex, link_state);  				goto error;  			} -  			if (link_state == USB_SS_PORT_LS_U3) {  				slot_id = xhci_find_slot_id_by_port(hcd, xhci,  						wIndex + 1); @@ -1522,6 +1522,13 @@ int xhci_bus_suspend(struct usb_hcd *hcd)  				t2 |= PORT_WKOC_E | PORT_WKCONN_E;  				t2 &= ~PORT_WKDISC_E;  			} + +			if ((xhci->quirks & XHCI_U2_DISABLE_WAKE) && +			    (hcd->speed < HCD_USB3)) { +				if (usb_amd_pt_check_port(hcd->self.controller, +							  port_index)) +					t2 &= ~PORT_WAKE_BITS; +			}  		} else  			t2 &= ~PORT_WAKE_BITS; diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 6c79037876db..d9f831b67e57 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -42,6 +42,10 @@  #define PCI_DEVICE_ID_INTEL_APL_XHCI			0x5aa8  #define PCI_DEVICE_ID_INTEL_DNV_XHCI			0x19d0 +#define PCI_DEVICE_ID_AMD_PROMONTORYA_4			0x43b9 +#define PCI_DEVICE_ID_AMD_PROMONTORYA_3			0x43ba +#define PCI_DEVICE_ID_AMD_PROMONTORYA_2			0x43bb +#define PCI_DEVICE_ID_AMD_PROMONTORYA_1			0x43bc  #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI		0x1142  static const char hcd_name[] = "xhci_hcd"; @@ -122,9 +126,19 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)  	if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info())  		xhci->quirks |= XHCI_AMD_PLL_FIX; +	if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x43bb) +		xhci->quirks |= XHCI_SUSPEND_DELAY; +  	if (pdev->vendor == PCI_VENDOR_ID_AMD)  		xhci->quirks |= XHCI_TRUST_TX_LENGTH; +	if ((pdev->vendor == PCI_VENDOR_ID_AMD) && +		((pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4) || +		(pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_3) || +		(pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_2) || +		(pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_1))) +		xhci->quirks |= XHCI_U2_DISABLE_WAKE; +  	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {  		xhci->quirks |= XHCI_LPM_SUPPORT;  		xhci->quirks |= XHCI_INTEL_HOST; diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 6f038306c14d..6652e2d5bd2e 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -360,7 +360,6 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev)  {  	struct usb_hcd	*hcd = dev_get_drvdata(dev);  	struct xhci_hcd	*xhci = hcd_to_xhci(hcd); -	int ret;  	/*  	 * xhci_suspend() needs `do_wakeup` to know whether host is allowed @@ -370,12 +369,7 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev)  	 * reconsider this when xhci_plat_suspend enlarges its scope, e.g.,  	 * also applies to runtime suspend.  	 */ -	ret = xhci_suspend(xhci, device_may_wakeup(dev)); - -	if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk)) -		clk_disable_unprepare(xhci->clk); - -	return ret; +	return xhci_suspend(xhci, device_may_wakeup(dev));  }  static int __maybe_unused xhci_plat_resume(struct device *dev) @@ -384,9 +378,6 @@ static int __maybe_unused xhci_plat_resume(struct device *dev)  	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);  	int ret; -	if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk)) -		clk_prepare_enable(xhci->clk); -  	ret = xhci_priv_resume_quirk(hcd);  	if (ret)  		return ret; diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index f0b559660007..f33ffc2bc4ed 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c @@ -83,6 +83,10 @@ static const struct soc_device_attribute rcar_quirks_match[]  = {  		.soc_id = "r8a7796",  		.data = (void *)RCAR_XHCI_FIRMWARE_V3,  	}, +	{ +		.soc_id = "r8a77965", +		.data = (void *)RCAR_XHCI_FIRMWARE_V3, +	},  	{ /* sentinel */ },  }; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1eeb3396300f..5d37700ae4b0 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -646,8 +646,6 @@ static void xhci_stop(struct usb_hcd *hcd)  		return;  	} -	xhci_debugfs_exit(xhci); -  	xhci_dbc_exit(xhci);  	spin_lock_irq(&xhci->lock); @@ -680,6 +678,7 @@ static void xhci_stop(struct usb_hcd *hcd)  	xhci_dbg_trace(xhci, trace_xhci_dbg_init, "cleaning up memory");  	xhci_mem_cleanup(xhci); +	xhci_debugfs_exit(xhci);  	xhci_dbg_trace(xhci, trace_xhci_dbg_init,  			"xhci_stop completed - status = %x",  			readl(&xhci->op_regs->status)); @@ -878,6 +877,9 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)  	clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);  	del_timer_sync(&xhci->shared_hcd->rh_timer); +	if (xhci->quirks & XHCI_SUSPEND_DELAY) +		usleep_range(1000, 1500); +  	spin_lock_irq(&xhci->lock);  	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);  	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); @@ -1014,6 +1016,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)  		xhci_dbg(xhci, "cleaning up memory\n");  		xhci_mem_cleanup(xhci); +		xhci_debugfs_exit(xhci);  		xhci_dbg(xhci, "xhci_stop completed - status = %x\n",  			    readl(&xhci->op_regs->status)); @@ -3544,12 +3547,10 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)  		virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING;  		del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);  	} - +	xhci_debugfs_remove_slot(xhci, udev->slot_id);  	ret = xhci_disable_slot(xhci, udev->slot_id); -	if (ret) { -		xhci_debugfs_remove_slot(xhci, udev->slot_id); +	if (ret)  		xhci_free_virt_device(xhci, udev->slot_id); -	}  }  int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 96099a245c69..866e141d4972 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -718,11 +718,12 @@ struct xhci_ep_ctx {  /* bits 10:14 are Max Primary Streams */  /* bit 15 is Linear Stream Array */  /* Interval - period between requests to an endpoint - 125u increments. */ -#define EP_INTERVAL(p)		(((p) & 0xff) << 16) -#define EP_INTERVAL_TO_UFRAMES(p)		(1 << (((p) >> 16) & 0xff)) -#define CTX_TO_EP_INTERVAL(p)	(((p) >> 16) & 0xff) -#define EP_MAXPSTREAMS_MASK	(0x1f << 10) -#define EP_MAXPSTREAMS(p)	(((p) << 10) & EP_MAXPSTREAMS_MASK) +#define EP_INTERVAL(p)			(((p) & 0xff) << 16) +#define EP_INTERVAL_TO_UFRAMES(p)	(1 << (((p) >> 16) & 0xff)) +#define CTX_TO_EP_INTERVAL(p)		(((p) >> 16) & 0xff) +#define EP_MAXPSTREAMS_MASK		(0x1f << 10) +#define EP_MAXPSTREAMS(p)		(((p) << 10) & EP_MAXPSTREAMS_MASK) +#define CTX_TO_EP_MAXPSTREAMS(p)	(((p) & EP_MAXPSTREAMS_MASK) >> 10)  /* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */  #define	EP_HAS_LSA		(1 << 15)  /* hosts with LEC=1 use bits 31:24 as ESIT high bits. */ @@ -1822,9 +1823,10 @@ struct xhci_hcd {  /* For controller with a broken Port Disable implementation */  #define XHCI_BROKEN_PORT_PED	(1 << 25)  #define XHCI_LIMIT_ENDPOINT_INTERVAL_7	(1 << 26) -/* Reserved. It was XHCI_U2_DISABLE_WAKE */ +#define XHCI_U2_DISABLE_WAKE	(1 << 27)  #define XHCI_ASMEDIA_MODIFY_FLOWCONTROL	(1 << 28)  #define XHCI_HW_LPM_DISABLE	(1 << 29) +#define XHCI_SUSPEND_DELAY	(1 << 30)  	unsigned int		num_active_eps;  	unsigned int		limit_active_eps; @@ -2549,21 +2551,22 @@ static inline const char *xhci_decode_ep_context(u32 info, u32 info2, u64 deq,  	u8 burst;  	u8 cerr;  	u8 mult; -	u8 lsa; -	u8 hid; + +	bool lsa; +	bool hid;  	esit = CTX_TO_MAX_ESIT_PAYLOAD_HI(info) << 16 |  		CTX_TO_MAX_ESIT_PAYLOAD(tx_info);  	ep_state = info & EP_STATE_MASK; -	max_pstr = info & EP_MAXPSTREAMS_MASK; +	max_pstr = CTX_TO_EP_MAXPSTREAMS(info);  	interval = CTX_TO_EP_INTERVAL(info);  	mult = CTX_TO_EP_MULT(info) + 1; -	lsa = info & EP_HAS_LSA; +	lsa = !!(info & EP_HAS_LSA);  	cerr = (info2 & (3 << 1)) >> 1;  	ep_type = CTX_TO_EP_TYPE(info2); -	hid = info2 & (1 << 7); +	hid = !!(info2 & (1 << 7));  	burst = CTX_TO_MAX_BURST(info2);  	maxp = MAX_PACKET_DECODED(info2); diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 63b9e85dc0e9..236a60f53099 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -42,6 +42,9 @@  #define USB_DEVICE_ID_LD_MICROCASSYTIME		0x1033	/* USB Product ID of Micro-CASSY Time (reserved) */  #define USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE	0x1035	/* USB Product ID of Micro-CASSY Temperature */  #define USB_DEVICE_ID_LD_MICROCASSYPH		0x1038	/* USB Product ID of Micro-CASSY pH */ +#define USB_DEVICE_ID_LD_POWERANALYSERCASSY	0x1040	/* USB Product ID of Power Analyser CASSY */ +#define USB_DEVICE_ID_LD_CONVERTERCONTROLLERCASSY	0x1042	/* USB Product ID of Converter Controller CASSY */ +#define USB_DEVICE_ID_LD_MACHINETESTCASSY	0x1043	/* USB Product ID of Machine Test CASSY */  #define USB_DEVICE_ID_LD_JWM		0x1080	/* USB Product ID of Joule and Wattmeter */  #define USB_DEVICE_ID_LD_DMMP		0x1081	/* USB Product ID of Digital Multimeter P (reserved) */  #define USB_DEVICE_ID_LD_UMIP		0x1090	/* USB Product ID of UMI P */ @@ -84,6 +87,9 @@ static const struct usb_device_id ld_usb_table[] = {  	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTIME) },  	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE) },  	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYPH) }, +	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERANALYSERCASSY) }, +	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CONVERTERCONTROLLERCASSY) }, +	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETESTCASSY) },  	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) },  	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) },  	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) }, diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index f5e1bb5e5217..984f7e12a6a5 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c @@ -85,6 +85,8 @@ struct mon_reader_text {  	wait_queue_head_t wait;  	int printf_size; +	size_t printf_offset; +	size_t printf_togo;  	char *printf_buf;  	struct mutex printf_lock; @@ -376,75 +378,103 @@ err_alloc:  	return rc;  } -/* - * For simplicity, we read one record in one system call and throw out - * what does not fit. This means that the following does not work: - *   dd if=/dbg/usbmon/0t bs=10 - * Also, we do not allow seeks and do not bother advancing the offset. - */ +static ssize_t mon_text_copy_to_user(struct mon_reader_text *rp, +    char __user * const buf, const size_t nbytes) +{ +	const size_t togo = min(nbytes, rp->printf_togo); + +	if (copy_to_user(buf, &rp->printf_buf[rp->printf_offset], togo)) +		return -EFAULT; +	rp->printf_togo -= togo; +	rp->printf_offset += togo; +	return togo; +} + +/* ppos is not advanced since the llseek operation is not permitted. */  static ssize_t mon_text_read_t(struct file *file, char __user *buf, -				size_t nbytes, loff_t *ppos) +    size_t nbytes, loff_t *ppos)  {  	struct mon_reader_text *rp = file->private_data;  	struct mon_event_text *ep;  	struct mon_text_ptr ptr; +	ssize_t ret; -	ep = mon_text_read_wait(rp, file); -	if (IS_ERR(ep)) -		return PTR_ERR(ep);  	mutex_lock(&rp->printf_lock); -	ptr.cnt = 0; -	ptr.pbuf = rp->printf_buf; -	ptr.limit = rp->printf_size; - -	mon_text_read_head_t(rp, &ptr, ep); -	mon_text_read_statset(rp, &ptr, ep); -	ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, -	    " %d", ep->length); -	mon_text_read_data(rp, &ptr, ep); - -	if (copy_to_user(buf, rp->printf_buf, ptr.cnt)) -		ptr.cnt = -EFAULT; + +	if (rp->printf_togo == 0) { + +		ep = mon_text_read_wait(rp, file); +		if (IS_ERR(ep)) { +			mutex_unlock(&rp->printf_lock); +			return PTR_ERR(ep); +		} +		ptr.cnt = 0; +		ptr.pbuf = rp->printf_buf; +		ptr.limit = rp->printf_size; + +		mon_text_read_head_t(rp, &ptr, ep); +		mon_text_read_statset(rp, &ptr, ep); +		ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, +		    " %d", ep->length); +		mon_text_read_data(rp, &ptr, ep); + +		rp->printf_togo = ptr.cnt; +		rp->printf_offset = 0; + +		kmem_cache_free(rp->e_slab, ep); +	} + +	ret = mon_text_copy_to_user(rp, buf, nbytes);  	mutex_unlock(&rp->printf_lock); -	kmem_cache_free(rp->e_slab, ep); -	return ptr.cnt; +	return ret;  } +/* ppos is not advanced since the llseek operation is not permitted. */  static ssize_t mon_text_read_u(struct file *file, char __user *buf, -				size_t nbytes, loff_t *ppos) +    size_t nbytes, loff_t *ppos)  {  	struct mon_reader_text *rp = file->private_data;  	struct mon_event_text *ep;  	struct mon_text_ptr ptr; +	ssize_t ret; -	ep = mon_text_read_wait(rp, file); -	if (IS_ERR(ep)) -		return PTR_ERR(ep);  	mutex_lock(&rp->printf_lock); -	ptr.cnt = 0; -	ptr.pbuf = rp->printf_buf; -	ptr.limit = rp->printf_size; -	mon_text_read_head_u(rp, &ptr, ep); -	if (ep->type == 'E') { -		mon_text_read_statset(rp, &ptr, ep); -	} else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) { -		mon_text_read_isostat(rp, &ptr, ep); -		mon_text_read_isodesc(rp, &ptr, ep); -	} else if (ep->xfertype == USB_ENDPOINT_XFER_INT) { -		mon_text_read_intstat(rp, &ptr, ep); -	} else { -		mon_text_read_statset(rp, &ptr, ep); +	if (rp->printf_togo == 0) { + +		ep = mon_text_read_wait(rp, file); +		if (IS_ERR(ep)) { +			mutex_unlock(&rp->printf_lock); +			return PTR_ERR(ep); +		} +		ptr.cnt = 0; +		ptr.pbuf = rp->printf_buf; +		ptr.limit = rp->printf_size; + +		mon_text_read_head_u(rp, &ptr, ep); +		if (ep->type == 'E') { +			mon_text_read_statset(rp, &ptr, ep); +		} else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) { +			mon_text_read_isostat(rp, &ptr, ep); +			mon_text_read_isodesc(rp, &ptr, ep); +		} else if (ep->xfertype == USB_ENDPOINT_XFER_INT) { +			mon_text_read_intstat(rp, &ptr, ep); +		} else { +			mon_text_read_statset(rp, &ptr, ep); +		} +		ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, +		    " %d", ep->length); +		mon_text_read_data(rp, &ptr, ep); + +		rp->printf_togo = ptr.cnt; +		rp->printf_offset = 0; + +		kmem_cache_free(rp->e_slab, ep);  	} -	ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, -	    " %d", ep->length); -	mon_text_read_data(rp, &ptr, ep); -	if (copy_to_user(buf, rp->printf_buf, ptr.cnt)) -		ptr.cnt = -EFAULT; +	ret = mon_text_copy_to_user(rp, buf, nbytes);  	mutex_unlock(&rp->printf_lock); -	kmem_cache_free(rp->e_slab, ep); -	return ptr.cnt; +	return ret;  }  static struct mon_event_text *mon_text_read_wait(struct mon_reader_text *rp, diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 968bf1e8b0fe..4d723077be2b 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1756,6 +1756,7 @@ vbus_show(struct device *dev, struct device_attribute *attr, char *buf)  	int		vbus;  	u8		devctl; +	pm_runtime_get_sync(dev);  	spin_lock_irqsave(&musb->lock, flags);  	val = musb->a_wait_bcon;  	vbus = musb_platform_get_vbus_status(musb); @@ -1769,6 +1770,7 @@ vbus_show(struct device *dev, struct device_attribute *attr, char *buf)  			vbus = 0;  	}  	spin_unlock_irqrestore(&musb->lock, flags); +	pm_runtime_put_sync(dev);  	return sprintf(buf, "Vbus %s, timeout %lu msec\n",  			vbus ? "on" : "off", val); @@ -2471,11 +2473,11 @@ static int musb_remove(struct platform_device *pdev)  	musb_disable_interrupts(musb);  	musb_writeb(musb->mregs, MUSB_DEVCTL, 0);  	spin_unlock_irqrestore(&musb->lock, flags); +	musb_platform_exit(musb);  	pm_runtime_dont_use_autosuspend(musb->controller);  	pm_runtime_put_sync(musb->controller);  	pm_runtime_disable(musb->controller); -	musb_platform_exit(musb);  	musb_phy_callback = NULL;  	if (musb->dma_controller)  		musb_dma_controller_destroy(musb->dma_controller); @@ -2708,7 +2710,8 @@ static int musb_resume(struct device *dev)  	if ((devctl & mask) != (musb->context.devctl & mask))  		musb->port1_status = 0; -	musb_start(musb); +	musb_enable_interrupts(musb); +	musb_platform_enable(musb);  	spin_lock_irqsave(&musb->lock, flags);  	error = musb_run_resume_work(musb); diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 394b4ac86161..45ed32c2cba9 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -391,13 +391,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb,  		}  	} -	/* -	 * The pipe must be broken if current urb->status is set, so don't -	 * start next urb. -	 * TODO: to minimize the risk of regression, only check urb->status -	 * for RX, until we have a test case to understand the behavior of TX. -	 */ -	if ((!status || !is_in) && qh && qh->is_ready) { +	if (qh != NULL && qh->is_ready) {  		musb_dbg(musb, "... next ep%d %cX urb %p",  		    hw_ep->epnum, is_in ? 'R' : 'T', next_urb(qh));  		musb_start_urb(musb, is_in, qh); diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index da031c45395a..fbec863350f6 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -602,6 +602,9 @@ static enum usb_charger_type mxs_phy_charger_detect(struct usb_phy *phy)  	void __iomem *base = phy->io_priv;  	enum usb_charger_type chgr_type = UNKNOWN_TYPE; +	if (!regmap) +		return UNKNOWN_TYPE; +  	if (mxs_charger_data_contact_detect(mxs_phy))  		return chgr_type; diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 5925d111bd47..39fa2fc1b8b7 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -982,6 +982,10 @@ static int usbhsf_dma_prepare_pop_with_usb_dmac(struct usbhs_pkt *pkt,  	if ((uintptr_t)pkt->buf & (USBHS_USB_DMAC_XFER_SIZE - 1))  		goto usbhsf_pio_prepare_pop; +	/* return at this time if the pipe is running */ +	if (usbhs_pipe_is_running(pipe)) +		return 0; +  	usbhs_pipe_config_change_bfre(pipe, 1);  	ret = usbhsf_fifo_select(pipe, fifo, 0); @@ -1172,6 +1176,7 @@ static int usbhsf_dma_pop_done_with_usb_dmac(struct usbhs_pkt *pkt,  	usbhsf_fifo_clear(pipe, fifo);  	pkt->actual = usbhs_dma_calc_received_size(pkt, chan, rcv_len); +	usbhs_pipe_running(pipe, 0);  	usbhsf_dma_stop(pipe, fifo);  	usbhsf_dma_unmap(pkt);  	usbhsf_fifo_unselect(pipe, pipe->fifo); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5db8ed517e0e..2d8d9150da0c 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -241,6 +241,7 @@ static void option_instat_callback(struct urb *urb);  #define QUECTEL_PRODUCT_EC21			0x0121  #define QUECTEL_PRODUCT_EC25			0x0125  #define QUECTEL_PRODUCT_BG96			0x0296 +#define QUECTEL_PRODUCT_EP06			0x0306  #define CMOTECH_VENDOR_ID			0x16d8  #define CMOTECH_PRODUCT_6001			0x6001 @@ -689,6 +690,10 @@ static const struct option_blacklist_info yuga_clm920_nc5_blacklist = {  	.reserved = BIT(1) | BIT(4),  }; +static const struct option_blacklist_info quectel_ep06_blacklist = { +	.reserved = BIT(4) | BIT(5), +}; +  static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },  	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -1203,6 +1208,8 @@ static const struct usb_device_id option_ids[] = {  	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },  	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),  	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, +	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06), +	  .driver_info = (kernel_ulong_t)&quectel_ep06_blacklist },  	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },  	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },  	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003), diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 3b1b9695177a..6034c39b67d1 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -1076,7 +1076,7 @@ static int uas_post_reset(struct usb_interface *intf)  		return 0;  	err = uas_configure_endpoints(devinfo); -	if (err && err != ENODEV) +	if (err && err != -ENODEV)  		shost_printk(KERN_ERR, shost,  			     "%s: alloc streams error %d after reset",  			     __func__, err); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 264af199aec8..747d3a9596d9 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2118,6 +2118,13 @@ UNUSUAL_DEV(  0x152d, 0x2566, 0x0114, 0x0114,  		USB_SC_DEVICE, USB_PR_DEVICE, NULL,  		US_FL_BROKEN_FUA ), +/* Reported by Teijo Kinnunen <teijo.kinnunen@code-q.fi> */ +UNUSUAL_DEV(  0x152d, 0x2567, 0x0117, 0x0117, +		"JMicron", +		"USB to ATA/ATAPI Bridge", +		USB_SC_DEVICE, USB_PR_DEVICE, NULL, +		US_FL_BROKEN_FUA ), +  /* Reported-by George Cherian <george.cherian@cavium.com> */  UNUSUAL_DEV(0x152d, 0x9561, 0x0000, 0x9999,  		"JMicron", diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 9ce4756adad6..dcd8ef085b30 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -1857,7 +1857,8 @@ static int fusb302_probe(struct i2c_client *client,  	chip->tcpm_port = tcpm_register_port(&client->dev, &chip->tcpc_dev);  	if (IS_ERR(chip->tcpm_port)) {  		ret = PTR_ERR(chip->tcpm_port); -		dev_err(dev, "cannot register tcpm port, ret=%d", ret); +		if (ret != -EPROBE_DEFER) +			dev_err(dev, "cannot register tcpm port, ret=%d", ret);  		goto destroy_workqueue;  	} diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index f4d563ee7690..8b637a4b474b 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -252,9 +252,6 @@ struct tcpm_port {  	unsigned int nr_src_pdo;  	u32 snk_pdo[PDO_MAX_OBJECTS];  	unsigned int nr_snk_pdo; -	unsigned int nr_fixed; /* number of fixed sink PDOs */ -	unsigned int nr_var; /* number of variable sink PDOs */ -	unsigned int nr_batt; /* number of battery sink PDOs */  	u32 snk_vdo[VDO_MAX_OBJECTS];  	unsigned int nr_snk_vdo; @@ -1770,90 +1767,39 @@ static int tcpm_pd_check_request(struct tcpm_port *port)  	return 0;  } -#define min_power(x, y) min(pdo_max_power(x), pdo_max_power(y)) -#define min_current(x, y) min(pdo_max_current(x), pdo_max_current(y)) - -static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo, -			      int *src_pdo) +static int tcpm_pd_select_pdo(struct tcpm_port *port)  { -	unsigned int i, j, max_mw = 0, max_mv = 0, mw = 0, mv = 0, ma = 0; +	unsigned int i, max_mw = 0, max_mv = 0;  	int ret = -EINVAL;  	/* -	 * Select the source PDO providing the most power which has a -	 * matchig sink cap. +	 * Select the source PDO providing the most power while staying within +	 * the board's voltage limits. Prefer PDO providing exp  	 */  	for (i = 0; i < port->nr_source_caps; i++) {  		u32 pdo = port->source_caps[i];  		enum pd_pdo_type type = pdo_type(pdo); +		unsigned int mv, ma, mw; -		if (type == PDO_TYPE_FIXED) { -			for (j = 0; j < port->nr_fixed; j++) { -				if (pdo_fixed_voltage(pdo) == -				    pdo_fixed_voltage(port->snk_pdo[j])) { -					ma = min_current(pdo, port->snk_pdo[j]); -					mv = pdo_fixed_voltage(pdo); -					mw = ma * mv / 1000; -					if (mw > max_mw || -					    (mw == max_mw && mv > max_mv)) { -						ret = 0; -						*src_pdo = i; -						*sink_pdo = j; -						max_mw = mw; -						max_mv = mv; -					} -					/* There could only be one fixed pdo -					 * at a specific voltage level. -					 * So breaking here. -					 */ -					break; -				} -			} -		} else if (type == PDO_TYPE_BATT) { -			for (j = port->nr_fixed; -			     j < port->nr_fixed + -				 port->nr_batt; -			     j++) { -				if (pdo_min_voltage(pdo) >= -				     pdo_min_voltage(port->snk_pdo[j]) && -				     pdo_max_voltage(pdo) <= -				     pdo_max_voltage(port->snk_pdo[j])) { -					mw = min_power(pdo, port->snk_pdo[j]); -					mv = pdo_min_voltage(pdo); -					if (mw > max_mw || -					    (mw == max_mw && mv > max_mv)) { -						ret = 0; -						*src_pdo = i; -						*sink_pdo = j; -						max_mw = mw; -						max_mv = mv; -					} -				} -			} -		} else if (type == PDO_TYPE_VAR) { -			for (j = port->nr_fixed + -				 port->nr_batt; -			     j < port->nr_fixed + -				 port->nr_batt + -				 port->nr_var; -			     j++) { -				if (pdo_min_voltage(pdo) >= -				     pdo_min_voltage(port->snk_pdo[j]) && -				     pdo_max_voltage(pdo) <= -				     pdo_max_voltage(port->snk_pdo[j])) { -					ma = min_current(pdo, port->snk_pdo[j]); -					mv = pdo_min_voltage(pdo); -					mw = ma * mv / 1000; -					if (mw > max_mw || -					    (mw == max_mw && mv > max_mv)) { -						ret = 0; -						*src_pdo = i; -						*sink_pdo = j; -						max_mw = mw; -						max_mv = mv; -					} -				} -			} +		if (type == PDO_TYPE_FIXED) +			mv = pdo_fixed_voltage(pdo); +		else +			mv = pdo_min_voltage(pdo); + +		if (type == PDO_TYPE_BATT) { +			mw = pdo_max_power(pdo); +		} else { +			ma = min(pdo_max_current(pdo), +				 port->max_snk_ma); +			mw = ma * mv / 1000; +		} + +		/* Perfer higher voltages if available */ +		if ((mw > max_mw || (mw == max_mw && mv > max_mv)) && +		    mv <= port->max_snk_mv) { +			ret = i; +			max_mw = mw; +			max_mv = mv;  		}  	} @@ -1865,14 +1811,13 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo)  	unsigned int mv, ma, mw, flags;  	unsigned int max_ma, max_mw;  	enum pd_pdo_type type; -	int src_pdo_index, snk_pdo_index; -	u32 pdo, matching_snk_pdo; +	int index; +	u32 pdo; -	if (tcpm_pd_select_pdo(port, &snk_pdo_index, &src_pdo_index) < 0) +	index = tcpm_pd_select_pdo(port); +	if (index < 0)  		return -EINVAL; - -	pdo = port->source_caps[src_pdo_index]; -	matching_snk_pdo = port->snk_pdo[snk_pdo_index]; +	pdo = port->source_caps[index];  	type = pdo_type(pdo);  	if (type == PDO_TYPE_FIXED) @@ -1880,28 +1825,26 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo)  	else  		mv = pdo_min_voltage(pdo); -	/* Select maximum available current within the sink pdo's limit */ +	/* Select maximum available current within the board's power limit */  	if (type == PDO_TYPE_BATT) { -		mw = min_power(pdo, matching_snk_pdo); -		ma = 1000 * mw / mv; +		mw = pdo_max_power(pdo); +		ma = 1000 * min(mw, port->max_snk_mw) / mv;  	} else { -		ma = min_current(pdo, matching_snk_pdo); -		mw = ma * mv / 1000; +		ma = min(pdo_max_current(pdo), +			 1000 * port->max_snk_mw / mv);  	} +	ma = min(ma, port->max_snk_ma);  	flags = RDO_USB_COMM | RDO_NO_SUSPEND;  	/* Set mismatch bit if offered power is less than operating power */ +	mw = ma * mv / 1000;  	max_ma = ma;  	max_mw = mw;  	if (mw < port->operating_snk_mw) {  		flags |= RDO_CAP_MISMATCH; -		if (type == PDO_TYPE_BATT && -		    (pdo_max_power(matching_snk_pdo) > pdo_max_power(pdo))) -			max_mw = pdo_max_power(matching_snk_pdo); -		else if (pdo_max_current(matching_snk_pdo) > -			 pdo_max_current(pdo)) -			max_ma = pdo_max_current(matching_snk_pdo); +		max_mw = port->operating_snk_mw; +		max_ma = max_mw * 1000 / mv;  	}  	tcpm_log(port, "cc=%d cc1=%d cc2=%d vbus=%d vconn=%s polarity=%d", @@ -1910,16 +1853,16 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo)  		 port->polarity);  	if (type == PDO_TYPE_BATT) { -		*rdo = RDO_BATT(src_pdo_index + 1, mw, max_mw, flags); +		*rdo = RDO_BATT(index + 1, mw, max_mw, flags);  		tcpm_log(port, "Requesting PDO %d: %u mV, %u mW%s", -			 src_pdo_index, mv, mw, +			 index, mv, mw,  			 flags & RDO_CAP_MISMATCH ? " [mismatch]" : "");  	} else { -		*rdo = RDO_FIXED(src_pdo_index + 1, ma, max_ma, flags); +		*rdo = RDO_FIXED(index + 1, ma, max_ma, flags);  		tcpm_log(port, "Requesting PDO %d: %u mV, %u mA%s", -			 src_pdo_index, mv, ma, +			 index, mv, ma,  			 flags & RDO_CAP_MISMATCH ? " [mismatch]" : "");  	} @@ -3650,19 +3593,6 @@ int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo,  }  EXPORT_SYMBOL_GPL(tcpm_update_sink_capabilities); -static int nr_type_pdos(const u32 *pdo, unsigned int nr_pdo, -			enum pd_pdo_type type) -{ -	int count = 0; -	int i; - -	for (i = 0; i < nr_pdo; i++) { -		if (pdo_type(pdo[i]) == type) -			count++; -	} -	return count; -} -  struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)  {  	struct tcpm_port *port; @@ -3708,15 +3638,6 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)  					  tcpc->config->nr_src_pdo);  	port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, tcpc->config->snk_pdo,  					  tcpc->config->nr_snk_pdo); -	port->nr_fixed =  nr_type_pdos(port->snk_pdo, -				       port->nr_snk_pdo, -				       PDO_TYPE_FIXED); -	port->nr_var = nr_type_pdos(port->snk_pdo, -				    port->nr_snk_pdo, -				    PDO_TYPE_VAR); -	port->nr_batt = nr_type_pdos(port->snk_pdo, -				     port->nr_snk_pdo, -				     PDO_TYPE_BATT);  	port->nr_snk_vdo = tcpm_copy_vdos(port->snk_vdo, tcpc->config->snk_vdo,  					  tcpc->config->nr_snk_vdo); diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index 49e552472c3f..dd8ef36ab10e 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -73,6 +73,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a  			goto err;  		sdev->ud.tcp_socket = socket; +		sdev->ud.sockfd = sockfd;  		spin_unlock_irq(&sdev->ud.lock); @@ -172,6 +173,7 @@ static void stub_shutdown_connection(struct usbip_device *ud)  	if (ud->tcp_socket) {  		sockfd_put(ud->tcp_socket);  		ud->tcp_socket = NULL; +		ud->sockfd = -1;  	}  	/* 3. free used data */ @@ -266,6 +268,7 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev)  	sdev->ud.status		= SDEV_ST_AVAILABLE;  	spin_lock_init(&sdev->ud.lock);  	sdev->ud.tcp_socket	= NULL; +	sdev->ud.sockfd		= -1;  	INIT_LIST_HEAD(&sdev->priv_init);  	INIT_LIST_HEAD(&sdev->priv_tx); diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index c3e1008aa491..20e3d4609583 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -984,6 +984,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud)  	if (vdev->ud.tcp_socket) {  		sockfd_put(vdev->ud.tcp_socket);  		vdev->ud.tcp_socket = NULL; +		vdev->ud.sockfd = -1;  	}  	pr_info("release socket\n"); @@ -1030,6 +1031,7 @@ static void vhci_device_reset(struct usbip_device *ud)  	if (ud->tcp_socket) {  		sockfd_put(ud->tcp_socket);  		ud->tcp_socket = NULL; +		ud->sockfd = -1;  	}  	ud->status = VDEV_ST_NULL; diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c index d86f72bbbb91..6dcd3ff655c3 100644 --- a/drivers/usb/usbip/vudc_sysfs.c +++ b/drivers/usb/usbip/vudc_sysfs.c @@ -105,10 +105,14 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a  	if (rv != 0)  		return -EINVAL; +	if (!udc) { +		dev_err(dev, "no device"); +		return -ENODEV; +	}  	spin_lock_irqsave(&udc->lock, flags);  	/* Don't export what we don't have */ -	if (!udc || !udc->driver || !udc->pullup) { -		dev_err(dev, "no device or gadget not bound"); +	if (!udc->driver || !udc->pullup) { +		dev_err(dev, "gadget not bound");  		ret = -ENODEV;  		goto unlock;  	}  | 

