usb: fixes for v4.6-rc2

A couple fixes for the new SuperSpeedPlus that went
 in during this merge window. Also two minor fixes
 for dwc3 (one for setting endpoint naming correctly
 and another to improve time spent in our reset
 sequence) and an old bug fix on Atmel UDC which was
 disabling endpoints when it shouldn't.
 
 There's also a build breakage fix to the qcom phy
 driver and a fix to the f_midi gadget to avoid a
 race condition with f_midi_transmit().
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJW+64KAAoJEIaOsuA1yqRE4GIP/jjyMQct/zUKhmYwc4HHh0e5
 cBN30H8hv6d7vz24ilxw6xOCfwOgr2YQKFh7i6hSORhP1yKc7orlx8M8QXqhvGbB
 nCWvCSpNyNQTQUM3D42Ty71mVNBumQvDdSUDtBoEit/t8VxzoYvIz/7TZquKCAoG
 R+nSb4grFWurFi61EgszOFm3/w37S0XDUfHkjIwuJWkUGTn2x1UpPef7ALzilDeg
 WNKCC7ZMJa4pXBWcpjof6OE3slKB0/5Qqb5j5mHcL+BQ2uvQdN5LW3rxSfJiFDBQ
 DNxuHhwScXk1oWrs6bwAPbbSdyNJo+1KfIpMqIQAgCsVh4O+ANLU5g5JQwHDdEUy
 lPRzRTOQT1Cowmh/yV8VA47UX7sx9kz3qU1uGJRbVKzgW/k9TzkOU7RlN2UU5R/Y
 VbDripDMnZqf8oraDMWClbpLX48hrb456tEjqigE4baiqEc5qY8nj+FfO2QVjluS
 fOMPFiQbLFwD5w7CXT+i9HzgR/hHVS1CoYc7mHP52+YRF9GUd3LZYmAL+UND864D
 aS+6NzgVMvSAvJDYPzhtLo7dzkEnjs6l8rl2yHlkiMg0i/V2G5vq1r1f6SgnVyZR
 UrSollFuIuI2G/PdemM0aHmJZ+MerbiNxq0Rf14cJqJPuRRbXtcuZGyb3m/3vdMJ
 2In8/60pWpw6fYj2iSeH
 =cLYy
 -----END PGP SIGNATURE-----

Merge tag 'fixes-for-v4.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus

Felipe writes:

usb: fixes for v4.6-rc2

A couple fixes for the new SuperSpeedPlus that went
in during this merge window. Also two minor fixes
for dwc3 (one for setting endpoint naming correctly
and another to improve time spent in our reset
sequence) and an old bug fix on Atmel UDC which was
disabling endpoints when it shouldn't.

There's also a build breakage fix to the qcom phy
driver and a fix to the f_midi gadget to avoid a
race condition with f_midi_transmit().
This commit is contained in:
Greg Kroah-Hartman 2016-03-30 21:49:30 -07:00
commit 8ef34aa5a1
7 changed files with 52 additions and 112 deletions

View File

@ -67,23 +67,9 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
static int dwc3_core_soft_reset(struct dwc3 *dwc)
{
u32 reg;
int retries = 1000;
int ret;
/* Before Resetting PHY, put Core in Reset */
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg |= DWC3_GCTL_CORESOFTRESET;
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
/* Assert USB3 PHY reset */
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
/* Assert USB2 PHY reset */
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
usb_phy_init(dwc->usb2_phy);
usb_phy_init(dwc->usb3_phy);
ret = phy_init(dwc->usb2_generic_phy);
@ -95,26 +81,28 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
phy_exit(dwc->usb2_generic_phy);
return ret;
}
mdelay(100);
/* Clear USB3 PHY reset */
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
/*
* We're resetting only the device side because, if we're in host mode,
* 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)
return 0;
/* Clear USB2 PHY reset */
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg |= DWC3_DCTL_CSFTRST;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
mdelay(100);
do {
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
if (!(reg & DWC3_DCTL_CSFTRST))
return 0;
/* After PHYs are stable we can take Core out of reset state */
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg &= ~DWC3_GCTL_CORESOFTRESET;
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
udelay(1);
} while (--retries);
return 0;
return -ETIMEDOUT;
}
/**

View File

@ -568,7 +568,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
if (!usb_endpoint_xfer_isoc(desc))
return 0;
goto out;
/* Link TRB for ISOC. The HWO bit is never reset */
trb_st_hw = &dep->trb_pool[0];
@ -582,9 +582,10 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
trb_link->ctrl |= DWC3_TRB_CTRL_HWO;
}
out:
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_CONTROL:
strlcat(dep->name, "-control", sizeof(dep->name));
/* don't change name */
break;
case USB_ENDPOINT_XFER_ISOC:
strlcat(dep->name, "-isoc", sizeof(dep->name));
@ -2487,7 +2488,11 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)
* implemented.
*/
dwc->gadget_driver->resume(&dwc->gadget);
if (dwc->gadget_driver && dwc->gadget_driver->resume) {
spin_unlock(&dwc->lock);
dwc->gadget_driver->resume(&dwc->gadget);
spin_lock(&dwc->lock);
}
}
static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,

View File

@ -656,7 +656,8 @@ static int bos_desc(struct usb_composite_dev *cdev)
ssp_cap->bmAttributes = cpu_to_le32(1);
/* Min RX/TX Lane Count = 1 */
ssp_cap->wFunctionalitySupport = (1 << 8) | (1 << 12);
ssp_cap->wFunctionalitySupport =
cpu_to_le16((1 << 8) | (1 << 12));
/*
* bmSublinkSpeedAttr[0]:
@ -666,7 +667,7 @@ static int bos_desc(struct usb_composite_dev *cdev)
* LSM = 10 (10 Gbps)
*/
ssp_cap->bmSublinkSpeedAttr[0] =
(3 << 4) | (1 << 14) | (0xa << 16);
cpu_to_le32((3 << 4) | (1 << 14) | (0xa << 16));
/*
* bmSublinkSpeedAttr[1] =
* ST = Symmetric, TX
@ -675,7 +676,8 @@ static int bos_desc(struct usb_composite_dev *cdev)
* LSM = 10 (10 Gbps)
*/
ssp_cap->bmSublinkSpeedAttr[1] =
(3 << 4) | (1 << 14) | (0xa << 16) | (1 << 7);
cpu_to_le32((3 << 4) | (1 << 14) |
(0xa << 16) | (1 << 7));
}
return le16_to_cpu(bos->wTotalLength);

View File

@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/kfifo.h>
#include <linux/spinlock.h>
#include <sound/core.h>
#include <sound/initval.h>
@ -89,6 +90,7 @@ struct f_midi {
unsigned int buflen, qlen;
/* This fifo is used as a buffer ring for pre-allocated IN usb_requests */
DECLARE_KFIFO_PTR(in_req_fifo, struct usb_request *);
spinlock_t transmit_lock;
unsigned int in_last_port;
struct gmidi_in_port in_ports_array[/* in_ports */];
@ -597,17 +599,22 @@ static void f_midi_transmit(struct f_midi *midi)
{
struct usb_ep *ep = midi->in_ep;
int ret;
unsigned long flags;
/* We only care about USB requests if IN endpoint is enabled */
if (!ep || !ep->enabled)
goto drop_out;
spin_lock_irqsave(&midi->transmit_lock, flags);
do {
ret = f_midi_do_transmit(midi, ep);
if (ret < 0)
goto drop_out;
} while (ret);
spin_unlock_irqrestore(&midi->transmit_lock, flags);
return;
drop_out:
@ -1201,6 +1208,8 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
if (status)
goto setup_fail;
spin_lock_init(&midi->transmit_lock);
++opts->refcnt;
mutex_unlock(&opts->lock);

View File

@ -1045,20 +1045,6 @@ static void reset_all_endpoints(struct usba_udc *udc)
list_del_init(&req->queue);
request_complete(ep, req, -ECONNRESET);
}
/* NOTE: normally, the next call to the gadget driver is in
* charge of disabling endpoints... usually disconnect().
* The exception would be entering a high speed test mode.
*
* FIXME remove this code ... and retest thoroughly.
*/
list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
if (ep->ep.desc) {
spin_unlock(&udc->lock);
usba_ep_disable(&ep->ep);
spin_lock(&udc->lock);
}
}
}
static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex)

View File

@ -65,9 +65,7 @@ struct phy_8x16 {
void __iomem *regs;
struct clk *core_clk;
struct clk *iface_clk;
struct regulator *v3p3;
struct regulator *v1p8;
struct regulator *vdd;
struct regulator_bulk_data regulator[3];
struct reset_control *phy_reset;
@ -78,51 +76,6 @@ struct phy_8x16 {
struct notifier_block reboot_notify;
};
static int phy_8x16_regulators_enable(struct phy_8x16 *qphy)
{
int ret;
ret = regulator_set_voltage(qphy->vdd, HSPHY_VDD_MIN, HSPHY_VDD_MAX);
if (ret)
return ret;
ret = regulator_enable(qphy->vdd);
if (ret)
return ret;
ret = regulator_set_voltage(qphy->v3p3, HSPHY_3P3_MIN, HSPHY_3P3_MAX);
if (ret)
goto off_vdd;
ret = regulator_enable(qphy->v3p3);
if (ret)
goto off_vdd;
ret = regulator_set_voltage(qphy->v1p8, HSPHY_1P8_MIN, HSPHY_1P8_MAX);
if (ret)
goto off_3p3;
ret = regulator_enable(qphy->v1p8);
if (ret)
goto off_3p3;
return 0;
off_3p3:
regulator_disable(qphy->v3p3);
off_vdd:
regulator_disable(qphy->vdd);
return ret;
}
static void phy_8x16_regulators_disable(struct phy_8x16 *qphy)
{
regulator_disable(qphy->v1p8);
regulator_disable(qphy->v3p3);
regulator_disable(qphy->vdd);
}
static int phy_8x16_notify_connect(struct usb_phy *phy,
enum usb_device_speed speed)
{
@ -261,7 +214,6 @@ static void phy_8x16_shutdown(struct usb_phy *phy)
static int phy_8x16_read_devicetree(struct phy_8x16 *qphy)
{
struct regulator_bulk_data regs[3];
struct device *dev = qphy->phy.dev;
int ret;
@ -273,18 +225,15 @@ static int phy_8x16_read_devicetree(struct phy_8x16 *qphy)
if (IS_ERR(qphy->iface_clk))
return PTR_ERR(qphy->iface_clk);
regs[0].supply = "v3p3";
regs[1].supply = "v1p8";
regs[2].supply = "vddcx";
qphy->regulator[0].supply = "v3p3";
qphy->regulator[1].supply = "v1p8";
qphy->regulator[2].supply = "vddcx";
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(regs), regs);
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(qphy->regulator),
qphy->regulator);
if (ret)
return ret;
qphy->v3p3 = regs[0].consumer;
qphy->v1p8 = regs[1].consumer;
qphy->vdd = regs[2].consumer;
qphy->phy_reset = devm_reset_control_get(dev, "phy");
if (IS_ERR(qphy->phy_reset))
return PTR_ERR(qphy->phy_reset);
@ -364,8 +313,9 @@ static int phy_8x16_probe(struct platform_device *pdev)
if (ret < 0)
goto off_core;
ret = phy_8x16_regulators_enable(qphy);
if (0 && ret)
ret = regulator_bulk_enable(ARRAY_SIZE(qphy->regulator),
qphy->regulator);
if (WARN_ON(ret))
goto off_clks;
qphy->vbus_notify.notifier_call = phy_8x16_vbus_notify;
@ -387,7 +337,7 @@ static int phy_8x16_probe(struct platform_device *pdev)
extcon_unregister_notifier(qphy->vbus_edev, EXTCON_USB,
&qphy->vbus_notify);
off_power:
phy_8x16_regulators_disable(qphy);
regulator_bulk_disable(ARRAY_SIZE(qphy->regulator), qphy->regulator);
off_clks:
clk_disable_unprepare(qphy->iface_clk);
off_core:
@ -413,7 +363,7 @@ static int phy_8x16_remove(struct platform_device *pdev)
clk_disable_unprepare(qphy->iface_clk);
clk_disable_unprepare(qphy->core_clk);
phy_8x16_regulators_disable(qphy);
regulator_bulk_disable(ARRAY_SIZE(qphy->regulator), qphy->regulator);
return 0;
}

View File

@ -899,7 +899,7 @@ struct usb_ssp_cap_descriptor {
__le32 bmAttributes;
#define USB_SSP_SUBLINK_SPEED_ATTRIBS (0x1f << 0) /* sublink speed entries */
#define USB_SSP_SUBLINK_SPEED_IDS (0xf << 5) /* speed ID entries */
__u16 wFunctionalitySupport;
__le16 wFunctionalitySupport;
#define USB_SSP_MIN_SUBLINK_SPEED_ATTRIBUTE_ID (0xf)
#define USB_SSP_MIN_RX_LANE_COUNT (0xf << 8)
#define USB_SSP_MIN_TX_LANE_COUNT (0xf << 12)