forked from luck/tmp_suning_uos_patched
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:
commit
8ef34aa5a1
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue
Block a user