Skip to content

Commit

Permalink
Merge tag 'usb-4.5-rc6' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are a few USB fixes for 4.5-rc6

  They fix a reported bug for some USB 3 devices by reverting the recent
  patch, a MAINTAINERS change for some drivers, some new device ids, and
  of course, the usual bunch of USB gadget driver fixes.

  All have been in linux-next for a while with no reported issues"

* tag 'usb-4.5-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  MAINTAINERS: drop OMAP USB and MUSB maintainership
  usb: musb: fix DMA for host mode
  usb: phy: msm: Trigger USB state detection work in DRD mode
  usb: gadget: net2280: fix endpoint max packet for super speed connections
  usb: gadget: gadgetfs: unregister gadget only if it got successfully registered
  usb: gadget: remove driver from pending list on probe error
  Revert "usb: hub: do not clear BOS field during reset device"
  usb: chipidea: fix return value check in ci_hdrc_pci_probe()
  usb: chipidea: error on overflow for port_test_write
  USB: option: add "4G LTE usb-modem U901"
  USB: cp210x: add IDs for GE B650V3 and B850V3 boards
  USB: option: add support for SIM7100E
  usb: musb: Fix DMA desired mode for Mentor DMA engine
  usb: gadget: fsl_qe_udc: fix IS_ERR_VALUE usage
  usb: dwc2: USB_DWC2 should depend on HAS_DMA
  usb: dwc2: host: fix the data toggle error in full speed descriptor dma
  usb: dwc2: host: fix logical omissions in dwc2_process_non_isoc_desc
  usb: dwc3: Fix assignment of EP transfer resources
  usb: dwc2: Add extra delay when forcing dr_mode
  • Loading branch information
torvalds committed Feb 28, 2016
2 parents 12b9fa6 + 428b315 commit 62718e3
Show file tree
Hide file tree
Showing 19 changed files with 127 additions and 75 deletions.
7 changes: 2 additions & 5 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -3451,7 +3451,6 @@ F: drivers/usb/dwc2/
DESIGNWARE USB3 DRD IP DRIVER
M: Felipe Balbi <[email protected]>
L: [email protected]
L: [email protected]
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
F: drivers/usb/dwc3/
Expand Down Expand Up @@ -7361,7 +7360,7 @@ F: drivers/tty/isicom.c
F: include/linux/isicom.h

MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
M: Felipe Balbi <[email protected]>
M: Bin Liu <[email protected]>
L: [email protected]
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
Expand Down Expand Up @@ -7930,11 +7929,9 @@ F: drivers/media/platform/omap3isp/
F: drivers/staging/media/omap4iss/

OMAP USB SUPPORT
M: Felipe Balbi <[email protected]>
L: [email protected]
L: [email protected]
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
S: Orphan
F: drivers/usb/*/*omap*
F: arch/arm/*omap*/usb*

Expand Down
4 changes: 2 additions & 2 deletions drivers/usb/chipidea/ci_hdrc_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,

/* register a nop PHY */
ci->phy = usb_phy_generic_register();
if (!ci->phy)
return -ENOMEM;
if (IS_ERR(ci->phy))
return PTR_ERR(ci->phy);

memset(res, 0, sizeof(res));
res[0].start = pci_resource_start(pdev, 0);
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/chipidea/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
if (sscanf(buf, "%u", &mode) != 1)
return -EINVAL;

if (mode > 255)
return -EBADRQC;

pm_runtime_get_sync(ci->dev);
spin_lock_irqsave(&ci->lock, flags);
ret = hw_port_test_set(ci, mode);
Expand Down
8 changes: 3 additions & 5 deletions drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -5401,6 +5401,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
}

bos = udev->bos;
udev->bos = NULL;

for (i = 0; i < SET_CONFIG_TRIES; ++i) {

Expand Down Expand Up @@ -5493,11 +5494,8 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
usb_set_usb2_hardware_lpm(udev, 1);
usb_unlocked_enable_lpm(udev);
usb_enable_ltm(udev);
/* release the new BOS descriptor allocated by hub_port_init() */
if (udev->bos != bos) {
usb_release_bos_descriptor(udev);
udev->bos = bos;
}
usb_release_bos_descriptor(udev);
udev->bos = bos;
return 0;

re_enumerate:
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/dwc2/Kconfig
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
config USB_DWC2
tristate "DesignWare USB2 DRD Core Support"
depends on HAS_DMA
depends on USB || USB_GADGET
help
Say Y here if your system has a Dual Role Hi-Speed USB
Expand Down
6 changes: 6 additions & 0 deletions drivers/usb/dwc2/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,12 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
__func__, hsotg->dr_mode);
break;
}

/*
* NOTE: This is required for some rockchip soc based
* platforms.
*/
msleep(50);
}

/*
Expand Down
23 changes: 11 additions & 12 deletions drivers/usb/dwc2/hcd_ddma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1174,14 +1174,11 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg,
failed = dwc2_update_non_isoc_urb_state_ddma(hsotg, chan, qtd, dma_desc,
halt_status, n_bytes,
xfer_done);
if (*xfer_done && urb->status != -EINPROGRESS)
failed = 1;

if (failed) {
if (failed || (*xfer_done && urb->status != -EINPROGRESS)) {
dwc2_host_complete(hsotg, qtd, urb->status);
dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x status=%08x\n",
failed, *xfer_done, urb->status);
dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x\n",
failed, *xfer_done);
return failed;
}

Expand Down Expand Up @@ -1236,29 +1233,31 @@ static void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,

list_for_each_safe(qtd_item, qtd_tmp, &qh->qtd_list) {
int i;
int qtd_desc_count;

qtd = list_entry(qtd_item, struct dwc2_qtd, qtd_list_entry);
xfer_done = 0;
qtd_desc_count = qtd->n_desc;

for (i = 0; i < qtd->n_desc; i++) {
for (i = 0; i < qtd_desc_count; i++) {
if (dwc2_process_non_isoc_desc(hsotg, chan, chnum, qtd,
desc_num, halt_status,
&xfer_done)) {
qtd = NULL;
break;
}
&xfer_done))
goto stop_scan;

desc_num++;
}
}

stop_scan:
if (qh->ep_type != USB_ENDPOINT_XFER_CONTROL) {
/*
* Resetting the data toggle for bulk and interrupt endpoints
* in case of stall. See handle_hc_stall_intr().
*/
if (halt_status == DWC2_HC_XFER_STALL)
qh->data_toggle = DWC2_HC_PID_DATA0;
else if (qtd)
else
dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
}

Expand Down
8 changes: 8 additions & 0 deletions drivers/usb/dwc2/hcd_intr.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,11 +525,19 @@ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
u32 pid = (hctsiz & TSIZ_SC_MC_PID_MASK) >> TSIZ_SC_MC_PID_SHIFT;

if (chan->ep_type != USB_ENDPOINT_XFER_CONTROL) {
if (WARN(!chan || !chan->qh,
"chan->qh must be specified for non-control eps\n"))
return;

if (pid == TSIZ_SC_MC_PID_DATA0)
chan->qh->data_toggle = DWC2_HC_PID_DATA0;
else
chan->qh->data_toggle = DWC2_HC_PID_DATA1;
} else {
if (WARN(!qtd,
"qtd must be specified for control eps\n"))
return;

if (pid == TSIZ_SC_MC_PID_DATA0)
qtd->data_toggle = DWC2_HC_PID_DATA0;
else
Expand Down
1 change: 0 additions & 1 deletion drivers/usb/dwc3/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,6 @@ struct dwc3 {
unsigned pullups_connected:1;
unsigned resize_fifos:1;
unsigned setup_packet_pending:1;
unsigned start_config_issued:1;
unsigned three_stage_setup:1;
unsigned usb3_lpm_capable:1;

Expand Down
5 changes: 0 additions & 5 deletions drivers/usb/dwc3/ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,6 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
int ret;
u32 reg;

dwc->start_config_issued = false;
cfg = le16_to_cpu(ctrl->wValue);

switch (state) {
Expand Down Expand Up @@ -737,10 +736,6 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY");
ret = dwc3_ep0_set_isoch_delay(dwc, ctrl);
break;
case USB_REQ_SET_INTERFACE:
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_INTERFACE");
dwc->start_config_issued = false;
/* Fall through */
default:
dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver");
ret = dwc3_ep0_delegate_req(dwc, ctrl);
Expand Down
70 changes: 52 additions & 18 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,24 +385,66 @@ static void dwc3_free_trb_pool(struct dwc3_ep *dep)
dep->trb_pool_dma = 0;
}

static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep);

/**
* dwc3_gadget_start_config - Configure EP resources
* @dwc: pointer to our controller context structure
* @dep: endpoint that is being enabled
*
* The assignment of transfer resources cannot perfectly follow the
* data book due to the fact that the controller driver does not have
* all knowledge of the configuration in advance. It is given this
* information piecemeal by the composite gadget framework after every
* SET_CONFIGURATION and SET_INTERFACE. Trying to follow the databook
* programming model in this scenario can cause errors. For two
* reasons:
*
* 1) The databook says to do DEPSTARTCFG for every SET_CONFIGURATION
* and SET_INTERFACE (8.1.5). This is incorrect in the scenario of
* multiple interfaces.
*
* 2) The databook does not mention doing more DEPXFERCFG for new
* endpoint on alt setting (8.1.6).
*
* The following simplified method is used instead:
*
* All hardware endpoints can be assigned a transfer resource and this
* setting will stay persistent until either a core reset or
* hibernation. So whenever we do a DEPSTARTCFG(0) we can go ahead and
* do DEPXFERCFG for every hardware endpoint as well. We are
* guaranteed that there are as many transfer resources as endpoints.
*
* This function is called for each endpoint when it is being enabled
* but is triggered only when called for EP0-out, which always happens
* first, and which should only happen in one of the above conditions.
*/
static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep)
{
struct dwc3_gadget_ep_cmd_params params;
u32 cmd;
int i;
int ret;

if (dep->number)
return 0;

memset(&params, 0x00, sizeof(params));
cmd = DWC3_DEPCMD_DEPSTARTCFG;

if (dep->number != 1) {
cmd = DWC3_DEPCMD_DEPSTARTCFG;
/* XferRscIdx == 0 for ep0 and 2 for the remaining */
if (dep->number > 1) {
if (dwc->start_config_issued)
return 0;
dwc->start_config_issued = true;
cmd |= DWC3_DEPCMD_PARAM(2);
}
ret = dwc3_send_gadget_ep_cmd(dwc, 0, cmd, &params);
if (ret)
return ret;

return dwc3_send_gadget_ep_cmd(dwc, 0, cmd, &params);
for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) {
struct dwc3_ep *dep = dwc->eps[i];

if (!dep)
continue;

ret = dwc3_gadget_set_xfer_resource(dwc, dep);
if (ret)
return ret;
}

return 0;
Expand Down Expand Up @@ -516,10 +558,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
struct dwc3_trb *trb_st_hw;
struct dwc3_trb *trb_link;

ret = dwc3_gadget_set_xfer_resource(dwc, dep);
if (ret)
return ret;

dep->endpoint.desc = desc;
dep->comp_desc = comp_desc;
dep->type = usb_endpoint_type(desc);
Expand Down Expand Up @@ -1636,8 +1674,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
}
dwc3_writel(dwc->regs, DWC3_DCFG, reg);

dwc->start_config_issued = false;

/* Start with SuperSpeed Default */
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);

Expand Down Expand Up @@ -2237,7 +2273,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_DCTL, reg);

dwc3_disconnect_gadget(dwc);
dwc->start_config_issued = false;

dwc->gadget.speed = USB_SPEED_UNKNOWN;
dwc->setup_packet_pending = false;
Expand Down Expand Up @@ -2288,7 +2323,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)

dwc3_stop_active_transfers(dwc);
dwc3_clear_stall_all_ep(dwc);
dwc->start_config_issued = false;

/* Reset device address to zero */
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
Expand Down
7 changes: 5 additions & 2 deletions drivers/usb/gadget/legacy/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ struct dev_data {
setup_can_stall : 1,
setup_out_ready : 1,
setup_out_error : 1,
setup_abort : 1;
setup_abort : 1,
gadget_registered : 1;
unsigned setup_wLength;

/* the rest is basically write-once */
Expand Down Expand Up @@ -1179,7 +1180,8 @@ dev_release (struct inode *inode, struct file *fd)

/* closing ep0 === shutdown all */

usb_gadget_unregister_driver (&gadgetfs_driver);
if (dev->gadget_registered)
usb_gadget_unregister_driver (&gadgetfs_driver);

/* at this point "good" hardware has disconnected the
* device from USB; the host won't see it any more.
Expand Down Expand Up @@ -1847,6 +1849,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
* kick in after the ep0 descriptor is closed.
*/
value = len;
dev->gadget_registered = true;
}
return value;

Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/gadget/udc/fsl_qe_udc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2340,7 +2340,7 @@ static struct qe_udc *qe_udc_config(struct platform_device *ofdev)
{
struct qe_udc *udc;
struct device_node *np = ofdev->dev.of_node;
unsigned int tmp_addr = 0;
unsigned long tmp_addr = 0;
struct usb_device_para __iomem *usbpram;
unsigned int i;
u64 size;
Expand Down
15 changes: 13 additions & 2 deletions drivers/usb/gadget/udc/net2280.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,20 @@ static inline void set_max_speed(struct net2280_ep *ep, u32 max)
static const u32 ep_enhanced[9] = { 0x10, 0x60, 0x30, 0x80,
0x50, 0x20, 0x70, 0x40, 0x90 };

if (ep->dev->enhanced_mode)
if (ep->dev->enhanced_mode) {
reg = ep_enhanced[ep->num];
else{
switch (ep->dev->gadget.speed) {
case USB_SPEED_SUPER:
reg += 2;
break;
case USB_SPEED_FULL:
reg += 1;
break;
case USB_SPEED_HIGH:
default:
break;
}
} else {
reg = (ep->num + 1) * 0x10;
if (ep->dev->gadget.speed != USB_SPEED_HIGH)
reg += 1;
Expand Down
3 changes: 2 additions & 1 deletion drivers/usb/gadget/udc/udc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,9 +413,10 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
if (!driver->udc_name || strcmp(driver->udc_name,
dev_name(&udc->dev)) == 0) {
ret = udc_bind_to_driver(udc, driver);
if (ret != -EPROBE_DEFER)
list_del(&driver->pending);
if (ret)
goto err4;
list_del(&driver->pending);
break;
}
}
Expand Down
Loading

0 comments on commit 62718e3

Please sign in to comment.