Commit 8ef34aa5 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'fixes-for-v4.6-rc2' of...

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().
parents f55532a0 7e8ac87a
...@@ -67,23 +67,9 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) ...@@ -67,23 +67,9 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
static int dwc3_core_soft_reset(struct dwc3 *dwc) static int dwc3_core_soft_reset(struct dwc3 *dwc)
{ {
u32 reg; u32 reg;
int retries = 1000;
int ret; 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->usb2_phy);
usb_phy_init(dwc->usb3_phy); usb_phy_init(dwc->usb3_phy);
ret = phy_init(dwc->usb2_generic_phy); ret = phy_init(dwc->usb2_generic_phy);
...@@ -95,26 +81,28 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) ...@@ -95,26 +81,28 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb2_generic_phy);
return ret; return ret;
} }
mdelay(100);
/* Clear USB3 PHY reset */ /*
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); * We're resetting only the device side because, if we're in host mode,
reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; * XHCI driver will reset the host block. If dwc3 was configured for
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); * 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_DCTL);
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_DCTL_CSFTRST;
reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_DCTL, reg);
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), 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 */ udelay(1);
reg = dwc3_readl(dwc->regs, DWC3_GCTL); } while (--retries);
reg &= ~DWC3_GCTL_CORESOFTRESET;
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
return 0; return -ETIMEDOUT;
} }
/** /**
......
...@@ -568,7 +568,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, ...@@ -568,7 +568,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
if (!usb_endpoint_xfer_isoc(desc)) if (!usb_endpoint_xfer_isoc(desc))
return 0; goto out;
/* Link TRB for ISOC. The HWO bit is never reset */ /* Link TRB for ISOC. The HWO bit is never reset */
trb_st_hw = &dep->trb_pool[0]; trb_st_hw = &dep->trb_pool[0];
...@@ -582,9 +582,10 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, ...@@ -582,9 +582,10 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
trb_link->ctrl |= DWC3_TRB_CTRL_HWO; trb_link->ctrl |= DWC3_TRB_CTRL_HWO;
} }
out:
switch (usb_endpoint_type(desc)) { switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_CONTROL: case USB_ENDPOINT_XFER_CONTROL:
strlcat(dep->name, "-control", sizeof(dep->name)); /* don't change name */
break; break;
case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_ISOC:
strlcat(dep->name, "-isoc", sizeof(dep->name)); strlcat(dep->name, "-isoc", sizeof(dep->name));
...@@ -2487,7 +2488,11 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc) ...@@ -2487,7 +2488,11 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)
* implemented. * implemented.
*/ */
if (dwc->gadget_driver && dwc->gadget_driver->resume) {
spin_unlock(&dwc->lock);
dwc->gadget_driver->resume(&dwc->gadget); dwc->gadget_driver->resume(&dwc->gadget);
spin_lock(&dwc->lock);
}
} }
static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
......
...@@ -656,7 +656,8 @@ static int bos_desc(struct usb_composite_dev *cdev) ...@@ -656,7 +656,8 @@ static int bos_desc(struct usb_composite_dev *cdev)
ssp_cap->bmAttributes = cpu_to_le32(1); ssp_cap->bmAttributes = cpu_to_le32(1);
/* Min RX/TX Lane Count = 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]: * bmSublinkSpeedAttr[0]:
...@@ -666,7 +667,7 @@ static int bos_desc(struct usb_composite_dev *cdev) ...@@ -666,7 +667,7 @@ static int bos_desc(struct usb_composite_dev *cdev)
* LSM = 10 (10 Gbps) * LSM = 10 (10 Gbps)
*/ */
ssp_cap->bmSublinkSpeedAttr[0] = ssp_cap->bmSublinkSpeedAttr[0] =
(3 << 4) | (1 << 14) | (0xa << 16); cpu_to_le32((3 << 4) | (1 << 14) | (0xa << 16));
/* /*
* bmSublinkSpeedAttr[1] = * bmSublinkSpeedAttr[1] =
* ST = Symmetric, TX * ST = Symmetric, TX
...@@ -675,7 +676,8 @@ static int bos_desc(struct usb_composite_dev *cdev) ...@@ -675,7 +676,8 @@ static int bos_desc(struct usb_composite_dev *cdev)
* LSM = 10 (10 Gbps) * LSM = 10 (10 Gbps)
*/ */
ssp_cap->bmSublinkSpeedAttr[1] = 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); return le16_to_cpu(bos->wTotalLength);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/kfifo.h> #include <linux/kfifo.h>
#include <linux/spinlock.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/initval.h> #include <sound/initval.h>
...@@ -89,6 +90,7 @@ struct f_midi { ...@@ -89,6 +90,7 @@ struct f_midi {
unsigned int buflen, qlen; unsigned int buflen, qlen;
/* This fifo is used as a buffer ring for pre-allocated IN usb_requests */ /* This fifo is used as a buffer ring for pre-allocated IN usb_requests */
DECLARE_KFIFO_PTR(in_req_fifo, struct usb_request *); DECLARE_KFIFO_PTR(in_req_fifo, struct usb_request *);
spinlock_t transmit_lock;
unsigned int in_last_port; unsigned int in_last_port;
struct gmidi_in_port in_ports_array[/* in_ports */]; struct gmidi_in_port in_ports_array[/* in_ports */];
...@@ -597,17 +599,22 @@ static void f_midi_transmit(struct f_midi *midi) ...@@ -597,17 +599,22 @@ static void f_midi_transmit(struct f_midi *midi)
{ {
struct usb_ep *ep = midi->in_ep; struct usb_ep *ep = midi->in_ep;
int ret; int ret;
unsigned long flags;
/* We only care about USB requests if IN endpoint is enabled */ /* We only care about USB requests if IN endpoint is enabled */
if (!ep || !ep->enabled) if (!ep || !ep->enabled)
goto drop_out; goto drop_out;
spin_lock_irqsave(&midi->transmit_lock, flags);
do { do {
ret = f_midi_do_transmit(midi, ep); ret = f_midi_do_transmit(midi, ep);
if (ret < 0) if (ret < 0)
goto drop_out; goto drop_out;
} while (ret); } while (ret);
spin_unlock_irqrestore(&midi->transmit_lock, flags);
return; return;
drop_out: drop_out:
...@@ -1201,6 +1208,8 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) ...@@ -1201,6 +1208,8 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
if (status) if (status)
goto setup_fail; goto setup_fail;
spin_lock_init(&midi->transmit_lock);
++opts->refcnt; ++opts->refcnt;
mutex_unlock(&opts->lock); mutex_unlock(&opts->lock);
......
...@@ -1045,20 +1045,6 @@ static void reset_all_endpoints(struct usba_udc *udc) ...@@ -1045,20 +1045,6 @@ static void reset_all_endpoints(struct usba_udc *udc)
list_del_init(&req->queue); list_del_init(&req->queue);
request_complete(ep, req, -ECONNRESET); 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) static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex)
......
...@@ -65,9 +65,7 @@ struct phy_8x16 { ...@@ -65,9 +65,7 @@ struct phy_8x16 {
void __iomem *regs; void __iomem *regs;
struct clk *core_clk; struct clk *core_clk;
struct clk *iface_clk; struct clk *iface_clk;
struct regulator *v3p3; struct regulator_bulk_data regulator[3];
struct regulator *v1p8;
struct regulator *vdd;
struct reset_control *phy_reset; struct reset_control *phy_reset;
...@@ -78,51 +76,6 @@ struct phy_8x16 { ...@@ -78,51 +76,6 @@ struct phy_8x16 {
struct notifier_block reboot_notify; 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, static int phy_8x16_notify_connect(struct usb_phy *phy,
enum usb_device_speed speed) enum usb_device_speed speed)
{ {
...@@ -261,7 +214,6 @@ static void phy_8x16_shutdown(struct usb_phy *phy) ...@@ -261,7 +214,6 @@ static void phy_8x16_shutdown(struct usb_phy *phy)
static int phy_8x16_read_devicetree(struct phy_8x16 *qphy) static int phy_8x16_read_devicetree(struct phy_8x16 *qphy)
{ {
struct regulator_bulk_data regs[3];
struct device *dev = qphy->phy.dev; struct device *dev = qphy->phy.dev;
int ret; int ret;
...@@ -273,18 +225,15 @@ static int phy_8x16_read_devicetree(struct phy_8x16 *qphy) ...@@ -273,18 +225,15 @@ static int phy_8x16_read_devicetree(struct phy_8x16 *qphy)
if (IS_ERR(qphy->iface_clk)) if (IS_ERR(qphy->iface_clk))
return PTR_ERR(qphy->iface_clk); return PTR_ERR(qphy->iface_clk);
regs[0].supply = "v3p3"; qphy->regulator[0].supply = "v3p3";
regs[1].supply = "v1p8"; qphy->regulator[1].supply = "v1p8";
regs[2].supply = "vddcx"; 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) if (ret)
return 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"); qphy->phy_reset = devm_reset_control_get(dev, "phy");
if (IS_ERR(qphy->phy_reset)) if (IS_ERR(qphy->phy_reset))
return PTR_ERR(qphy->phy_reset); return PTR_ERR(qphy->phy_reset);
...@@ -364,8 +313,9 @@ static int phy_8x16_probe(struct platform_device *pdev) ...@@ -364,8 +313,9 @@ static int phy_8x16_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto off_core; goto off_core;
ret = phy_8x16_regulators_enable(qphy); ret = regulator_bulk_enable(ARRAY_SIZE(qphy->regulator),
if (0 && ret) qphy->regulator);
if (WARN_ON(ret))
goto off_clks; goto off_clks;
qphy->vbus_notify.notifier_call = phy_8x16_vbus_notify; qphy->vbus_notify.notifier_call = phy_8x16_vbus_notify;
...@@ -387,7 +337,7 @@ static int phy_8x16_probe(struct platform_device *pdev) ...@@ -387,7 +337,7 @@ static int phy_8x16_probe(struct platform_device *pdev)
extcon_unregister_notifier(qphy->vbus_edev, EXTCON_USB, extcon_unregister_notifier(qphy->vbus_edev, EXTCON_USB,
&qphy->vbus_notify); &qphy->vbus_notify);
off_power: off_power:
phy_8x16_regulators_disable(qphy); regulator_bulk_disable(ARRAY_SIZE(qphy->regulator), qphy->regulator);
off_clks: off_clks:
clk_disable_unprepare(qphy->iface_clk); clk_disable_unprepare(qphy->iface_clk);
off_core: off_core:
...@@ -413,7 +363,7 @@ static int phy_8x16_remove(struct platform_device *pdev) ...@@ -413,7 +363,7 @@ static int phy_8x16_remove(struct platform_device *pdev)
clk_disable_unprepare(qphy->iface_clk); clk_disable_unprepare(qphy->iface_clk);
clk_disable_unprepare(qphy->core_clk); clk_disable_unprepare(qphy->core_clk);
phy_8x16_regulators_disable(qphy); regulator_bulk_disable(ARRAY_SIZE(qphy->regulator), qphy->regulator);
return 0; return 0;
} }
......
...@@ -899,7 +899,7 @@ struct usb_ssp_cap_descriptor { ...@@ -899,7 +899,7 @@ struct usb_ssp_cap_descriptor {
__le32 bmAttributes; __le32 bmAttributes;
#define USB_SSP_SUBLINK_SPEED_ATTRIBS (0x1f << 0) /* sublink speed entries */ #define USB_SSP_SUBLINK_SPEED_ATTRIBS (0x1f << 0) /* sublink speed entries */
#define USB_SSP_SUBLINK_SPEED_IDS (0xf << 5) /* speed ID 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_SUBLINK_SPEED_ATTRIBUTE_ID (0xf)
#define USB_SSP_MIN_RX_LANE_COUNT (0xf << 8) #define USB_SSP_MIN_RX_LANE_COUNT (0xf << 8)
#define USB_SSP_MIN_TX_LANE_COUNT (0xf << 12) #define USB_SSP_MIN_TX_LANE_COUNT (0xf << 12)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment