forked from Minki/linux
USB fixes for 3.18-rc3
Here are a bunch of USB fixes for 3.18-rc3. Mostly usb-serial device ids and gadget fixes for issues that have been reported. Full details are in the shortlog. All of these have been in linux-next for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iEYEABECAAYFAlRVP34ACgkQMUfUDdst+ykxrwCbB2HvQU+YKThwHs2g6Gf+MElI Rk8An2ftMJlvvB4rcqwUYqbMZGV02zxV =0SHY -----END PGP SIGNATURE----- Merge tag 'usb-3.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg KH: "Here are a bunch of USB fixes for 3.18-rc3. Mostly usb-serial device ids and gadget fixes for issues that have been reported. Full details are in the shortlog. All of these have been in linux-next for a while" * tag 'usb-3.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (42 commits) usb: chipidea: Fix oops when removing the ci_hdrc module usb: gadget: function: Fixed the return value on error path usb: dwc2: gadget: disable phy before turning off power regulators usb: gadget: function: Remove redundant usb_free_all_descriptors usb: dwc3: gadget: Properly initialize LINK TRB usb: dwc2: gadget: fix gadget unregistration in udc_stop() function usb: dwc2: Bits in bitfield should add up to 32 usb: dwc2: gadget: sparse warning of context imbalance usb: gadget: udc: core: fix kernel oops with soft-connect usb: musb: musb_dsps: fix NULL pointer in suspend usb: musb: dsps: start OTG timer on resume again usb: gadget: loopback: don't queue requests to bogus endpoints usb: ffs: fix regression when quirk_ep_out_aligned_size flag is set usb: gadget: f_fs: remove redundant ffs_data_get() usb: gadget: udc: USB_GADGET_XILINX should depend on HAS_DMA Revert "usb: dwc3: dwc3-omap: Disable/Enable only wrapper interrupts in prepare/complete" usb: gadget: composite: enable BESL support usb: musb: cppi41: restart hrtimer only if not yet done usb: dwc3: ep0: fix Data Phase for transfer sizes aligned to wMaxPacketSize usb: serial: ftdi_sio: add "bricked" FTDI device PID ...
This commit is contained in:
commit
528a506e4b
@ -742,7 +742,6 @@ static int ci_hdrc_remove(struct platform_device *pdev)
|
||||
ci_role_destroy(ci);
|
||||
ci_hdrc_enter_lpm(ci, true);
|
||||
usb_phy_shutdown(ci->transceiver);
|
||||
kfree(ci->hw_bank.regmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -619,7 +619,7 @@ struct dwc2_hsotg {
|
||||
unsigned port_suspend_change:1;
|
||||
unsigned port_over_current_change:1;
|
||||
unsigned port_l1_change:1;
|
||||
unsigned reserved:26;
|
||||
unsigned reserved:25;
|
||||
} b;
|
||||
} flags;
|
||||
|
||||
|
@ -2561,8 +2561,10 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
|
||||
hs_ep->fifo_size = val;
|
||||
break;
|
||||
}
|
||||
if (i == 8)
|
||||
return -ENOMEM;
|
||||
if (i == 8) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* for non control endpoints, set PID to D0 */
|
||||
@ -2579,6 +2581,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
|
||||
/* enable the endpoint interrupt */
|
||||
s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
|
||||
|
||||
error:
|
||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
@ -2934,9 +2937,7 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
|
||||
|
||||
spin_lock_irqsave(&hsotg->lock, flags);
|
||||
|
||||
if (!driver)
|
||||
hsotg->driver = NULL;
|
||||
|
||||
hsotg->driver = NULL;
|
||||
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
|
||||
|
||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
@ -3567,6 +3568,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
|
||||
s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum);
|
||||
|
||||
/* disable power and clock */
|
||||
s3c_hsotg_phy_disable(hsotg);
|
||||
|
||||
ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
|
||||
hsotg->supplies);
|
||||
@ -3575,8 +3577,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
|
||||
goto err_ep_mem;
|
||||
}
|
||||
|
||||
s3c_hsotg_phy_disable(hsotg);
|
||||
|
||||
ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
|
||||
if (ret)
|
||||
goto err_ep_mem;
|
||||
|
@ -597,7 +597,7 @@ static int dwc3_omap_prepare(struct device *dev)
|
||||
{
|
||||
struct dwc3_omap *omap = dev_get_drvdata(dev);
|
||||
|
||||
dwc3_omap_write_irqmisc_set(omap, 0x00);
|
||||
dwc3_omap_disable_irqs(omap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -605,19 +605,8 @@ static int dwc3_omap_prepare(struct device *dev)
|
||||
static void dwc3_omap_complete(struct device *dev)
|
||||
{
|
||||
struct dwc3_omap *omap = dev_get_drvdata(dev);
|
||||
u32 reg;
|
||||
|
||||
reg = (USBOTGSS_IRQMISC_OEVT |
|
||||
USBOTGSS_IRQMISC_DRVVBUS_RISE |
|
||||
USBOTGSS_IRQMISC_CHRGVBUS_RISE |
|
||||
USBOTGSS_IRQMISC_DISCHRGVBUS_RISE |
|
||||
USBOTGSS_IRQMISC_IDPULLUP_RISE |
|
||||
USBOTGSS_IRQMISC_DRVVBUS_FALL |
|
||||
USBOTGSS_IRQMISC_CHRGVBUS_FALL |
|
||||
USBOTGSS_IRQMISC_DISCHRGVBUS_FALL |
|
||||
USBOTGSS_IRQMISC_IDPULLUP_FALL);
|
||||
|
||||
dwc3_omap_write_irqmisc_set(omap, reg);
|
||||
dwc3_omap_enable_irqs(omap);
|
||||
}
|
||||
|
||||
static int dwc3_omap_suspend(struct device *dev)
|
||||
|
@ -30,6 +30,7 @@
|
||||
#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd
|
||||
#define PCI_DEVICE_ID_INTEL_BYT 0x0f37
|
||||
#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
|
||||
#define PCI_DEVICE_ID_INTEL_BSW 0x22B7
|
||||
|
||||
struct dwc3_pci {
|
||||
struct device *dev;
|
||||
@ -181,6 +182,7 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
|
||||
PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
|
||||
PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
|
||||
},
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
|
||||
{ } /* Terminating Entry */
|
||||
|
@ -256,7 +256,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
|
||||
|
||||
/* stall is always issued on EP0 */
|
||||
dep = dwc->eps[0];
|
||||
__dwc3_gadget_ep_set_halt(dep, 1);
|
||||
__dwc3_gadget_ep_set_halt(dep, 1, false);
|
||||
dep->flags = DWC3_EP_ENABLED;
|
||||
dwc->delayed_status = false;
|
||||
|
||||
@ -271,7 +271,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
|
||||
dwc3_ep0_out_start(dwc);
|
||||
}
|
||||
|
||||
int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value)
|
||||
int __dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value)
|
||||
{
|
||||
struct dwc3_ep *dep = to_dwc3_ep(ep);
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
@ -281,6 +281,20 @@ int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value)
|
||||
{
|
||||
struct dwc3_ep *dep = to_dwc3_ep(ep);
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
ret = __dwc3_gadget_ep0_set_halt(ep, value);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dwc3_ep0_out_start(struct dwc3 *dwc)
|
||||
{
|
||||
int ret;
|
||||
@ -466,7 +480,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
|
||||
return -EINVAL;
|
||||
if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
|
||||
break;
|
||||
ret = __dwc3_gadget_ep_set_halt(dep, set);
|
||||
ret = __dwc3_gadget_ep_set_halt(dep, set, true);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
break;
|
||||
@ -775,9 +789,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
|
||||
|
||||
dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;
|
||||
|
||||
r = next_request(&ep0->request_list);
|
||||
ur = &r->request;
|
||||
|
||||
trb = dwc->ep0_trb;
|
||||
|
||||
status = DWC3_TRB_SIZE_TRBSTS(trb->size);
|
||||
@ -790,6 +801,12 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
|
||||
return;
|
||||
}
|
||||
|
||||
r = next_request(&ep0->request_list);
|
||||
if (!r)
|
||||
return;
|
||||
|
||||
ur = &r->request;
|
||||
|
||||
length = trb->size & DWC3_TRB_SIZE_MASK;
|
||||
|
||||
if (dwc->ep0_bounced) {
|
||||
@ -811,12 +828,19 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
|
||||
|
||||
dwc3_ep0_stall_and_restart(dwc);
|
||||
} else {
|
||||
/*
|
||||
* handle the case where we have to send a zero packet. This
|
||||
* seems to be case when req.length > maxpacket. Could it be?
|
||||
*/
|
||||
if (r)
|
||||
dwc3_gadget_giveback(ep0, r, 0);
|
||||
dwc3_gadget_giveback(ep0, r, 0);
|
||||
|
||||
if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) &&
|
||||
ur->length && ur->zero) {
|
||||
int ret;
|
||||
|
||||
dwc->ep0_next_event = DWC3_EP0_COMPLETE;
|
||||
|
||||
ret = dwc3_ep0_start_trans(dwc, epnum,
|
||||
dwc->ctrl_req_addr, 0,
|
||||
DWC3_TRBCTL_CONTROL_DATA);
|
||||
WARN_ON(ret < 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,12 +525,11 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
|
||||
if (!usb_endpoint_xfer_isoc(desc))
|
||||
return 0;
|
||||
|
||||
memset(&trb_link, 0, sizeof(trb_link));
|
||||
|
||||
/* Link TRB for ISOC. The HWO bit is never reset */
|
||||
trb_st_hw = &dep->trb_pool[0];
|
||||
|
||||
trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1];
|
||||
memset(trb_link, 0, sizeof(*trb_link));
|
||||
|
||||
trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw));
|
||||
trb_link->bph = upper_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw));
|
||||
@ -581,7 +580,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
|
||||
|
||||
/* make sure HW endpoint isn't stalled */
|
||||
if (dep->flags & DWC3_EP_STALL)
|
||||
__dwc3_gadget_ep_set_halt(dep, 0);
|
||||
__dwc3_gadget_ep_set_halt(dep, 0, false);
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
|
||||
reg &= ~DWC3_DALEPENA_EP(dep->number);
|
||||
@ -1202,15 +1201,28 @@ out0:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
|
||||
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
|
||||
{
|
||||
struct dwc3_gadget_ep_cmd_params params;
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
int ret;
|
||||
|
||||
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
|
||||
dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(¶ms, 0x00, sizeof(params));
|
||||
|
||||
if (value) {
|
||||
if (!protocol && ((dep->direction && dep->flags & DWC3_EP_BUSY) ||
|
||||
(!list_empty(&dep->req_queued) ||
|
||||
!list_empty(&dep->request_list)))) {
|
||||
dev_dbg(dwc->dev, "%s: pending request, cannot halt\n",
|
||||
dep->name);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
|
||||
DWC3_DEPCMD_SETSTALL, ¶ms);
|
||||
if (ret)
|
||||
@ -1241,15 +1253,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value)
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
|
||||
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
|
||||
dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = __dwc3_gadget_ep_set_halt(dep, value);
|
||||
out:
|
||||
ret = __dwc3_gadget_ep_set_halt(dep, value, false);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
return ret;
|
||||
@ -1260,15 +1264,18 @@ static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep)
|
||||
struct dwc3_ep *dep = to_dwc3_ep(ep);
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
dep->flags |= DWC3_EP_WEDGE;
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
if (dep->number == 0 || dep->number == 1)
|
||||
return dwc3_gadget_ep0_set_halt(ep, 1);
|
||||
ret = __dwc3_gadget_ep0_set_halt(ep, 1);
|
||||
else
|
||||
return dwc3_gadget_ep_set_halt(ep, 1);
|
||||
ret = __dwc3_gadget_ep_set_halt(dep, 1, false);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -82,10 +82,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
|
||||
void dwc3_ep0_interrupt(struct dwc3 *dwc,
|
||||
const struct dwc3_event_depevt *event);
|
||||
void dwc3_ep0_out_start(struct dwc3 *dwc);
|
||||
int __dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
|
||||
int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
|
||||
int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
|
||||
gfp_t gfp_flags);
|
||||
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value);
|
||||
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
|
||||
|
||||
/**
|
||||
* dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
|
||||
|
@ -73,15 +73,23 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
|
||||
TP_PROTO(struct usb_ctrlrequest *ctrl),
|
||||
TP_ARGS(ctrl),
|
||||
TP_STRUCT__entry(
|
||||
__field(struct usb_ctrlrequest *, ctrl)
|
||||
__field(__u8, bRequestType)
|
||||
__field(__u8, bRequest)
|
||||
__field(__le16, wValue)
|
||||
__field(__le16, wIndex)
|
||||
__field(__le16, wLength)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->ctrl = ctrl;
|
||||
__entry->bRequestType = ctrl->bRequestType;
|
||||
__entry->bRequest = ctrl->bRequest;
|
||||
__entry->wValue = ctrl->wValue;
|
||||
__entry->wIndex = ctrl->wIndex;
|
||||
__entry->wLength = ctrl->wLength;
|
||||
),
|
||||
TP_printk("bRequestType %02x bRequest %02x wValue %04x wIndex %04x wLength %d",
|
||||
__entry->ctrl->bRequestType, __entry->ctrl->bRequest,
|
||||
le16_to_cpu(__entry->ctrl->wValue), le16_to_cpu(__entry->ctrl->wIndex),
|
||||
le16_to_cpu(__entry->ctrl->wLength)
|
||||
__entry->bRequestType, __entry->bRequest,
|
||||
le16_to_cpu(__entry->wValue), le16_to_cpu(__entry->wIndex),
|
||||
le16_to_cpu(__entry->wLength)
|
||||
)
|
||||
);
|
||||
|
||||
@ -94,15 +102,22 @@ DECLARE_EVENT_CLASS(dwc3_log_request,
|
||||
TP_PROTO(struct dwc3_request *req),
|
||||
TP_ARGS(req),
|
||||
TP_STRUCT__entry(
|
||||
__dynamic_array(char, name, DWC3_MSG_MAX)
|
||||
__field(struct dwc3_request *, req)
|
||||
__field(unsigned, actual)
|
||||
__field(unsigned, length)
|
||||
__field(int, status)
|
||||
),
|
||||
TP_fast_assign(
|
||||
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", req->dep->name);
|
||||
__entry->req = req;
|
||||
__entry->actual = req->request.actual;
|
||||
__entry->length = req->request.length;
|
||||
__entry->status = req->request.status;
|
||||
),
|
||||
TP_printk("%s: req %p length %u/%u ==> %d",
|
||||
__entry->req->dep->name, __entry->req,
|
||||
__entry->req->request.actual, __entry->req->request.length,
|
||||
__entry->req->request.status
|
||||
__get_str(name), __entry->req, __entry->actual, __entry->length,
|
||||
__entry->status
|
||||
)
|
||||
);
|
||||
|
||||
@ -158,17 +173,17 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
|
||||
struct dwc3_gadget_ep_cmd_params *params),
|
||||
TP_ARGS(dep, cmd, params),
|
||||
TP_STRUCT__entry(
|
||||
__field(struct dwc3_ep *, dep)
|
||||
__dynamic_array(char, name, DWC3_MSG_MAX)
|
||||
__field(unsigned int, cmd)
|
||||
__field(struct dwc3_gadget_ep_cmd_params *, params)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dep = dep;
|
||||
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
|
||||
__entry->cmd = cmd;
|
||||
__entry->params = params;
|
||||
),
|
||||
TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x\n",
|
||||
__entry->dep->name, dwc3_gadget_ep_cmd_string(__entry->cmd),
|
||||
__get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd),
|
||||
__entry->cmd, __entry->params->param0,
|
||||
__entry->params->param1, __entry->params->param2
|
||||
)
|
||||
@ -184,16 +199,24 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
|
||||
TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb),
|
||||
TP_ARGS(dep, trb),
|
||||
TP_STRUCT__entry(
|
||||
__field(struct dwc3_ep *, dep)
|
||||
__dynamic_array(char, name, DWC3_MSG_MAX)
|
||||
__field(struct dwc3_trb *, trb)
|
||||
__field(u32, bpl)
|
||||
__field(u32, bph)
|
||||
__field(u32, size)
|
||||
__field(u32, ctrl)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dep = dep;
|
||||
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
|
||||
__entry->trb = trb;
|
||||
__entry->bpl = trb->bpl;
|
||||
__entry->bph = trb->bph;
|
||||
__entry->size = trb->size;
|
||||
__entry->ctrl = trb->ctrl;
|
||||
),
|
||||
TP_printk("%s: trb %p bph %08x bpl %08x size %08x ctrl %08x\n",
|
||||
__entry->dep->name, __entry->trb, __entry->trb->bph,
|
||||
__entry->trb->bpl, __entry->trb->size, __entry->trb->ctrl
|
||||
__get_str(name), __entry->trb, __entry->bph, __entry->bpl,
|
||||
__entry->size, __entry->ctrl
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -560,7 +560,7 @@ static int bos_desc(struct usb_composite_dev *cdev)
|
||||
usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE;
|
||||
usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
|
||||
usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
|
||||
usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT);
|
||||
usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT | USB_BESL_SUPPORT);
|
||||
|
||||
/*
|
||||
* The Superspeed USB Capability descriptor shall be implemented by all
|
||||
|
@ -433,12 +433,12 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
||||
dev_vdbg(&cdev->gadget->dev,
|
||||
"reset acm control interface %d\n", intf);
|
||||
usb_ep_disable(acm->notify);
|
||||
} else {
|
||||
dev_vdbg(&cdev->gadget->dev,
|
||||
"init acm ctrl interface %d\n", intf);
|
||||
}
|
||||
|
||||
if (!acm->notify->desc)
|
||||
if (config_ep_by_speed(cdev->gadget, f, acm->notify))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
usb_ep_enable(acm->notify);
|
||||
acm->notify->driver_data = acm;
|
||||
|
||||
|
@ -325,7 +325,6 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
usb_free_all_descriptors(f);
|
||||
if (eem->port.out_ep)
|
||||
eem->port.out_ep->driver_data = NULL;
|
||||
if (eem->port.in_ep)
|
||||
|
@ -647,15 +647,26 @@ static void ffs_user_copy_worker(struct work_struct *work)
|
||||
if (io_data->read && ret > 0) {
|
||||
int i;
|
||||
size_t pos = 0;
|
||||
|
||||
/*
|
||||
* Since req->length may be bigger than io_data->len (after
|
||||
* being rounded up to maxpacketsize), we may end up with more
|
||||
* data then user space has space for.
|
||||
*/
|
||||
ret = min_t(int, ret, io_data->len);
|
||||
|
||||
use_mm(io_data->mm);
|
||||
for (i = 0; i < io_data->nr_segs; i++) {
|
||||
size_t len = min_t(size_t, ret - pos,
|
||||
io_data->iovec[i].iov_len);
|
||||
if (!len)
|
||||
break;
|
||||
if (unlikely(copy_to_user(io_data->iovec[i].iov_base,
|
||||
&io_data->buf[pos],
|
||||
io_data->iovec[i].iov_len))) {
|
||||
&io_data->buf[pos], len))) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
pos += io_data->iovec[i].iov_len;
|
||||
pos += len;
|
||||
}
|
||||
unuse_mm(io_data->mm);
|
||||
}
|
||||
@ -687,7 +698,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
|
||||
struct ffs_epfile *epfile = file->private_data;
|
||||
struct ffs_ep *ep;
|
||||
char *data = NULL;
|
||||
ssize_t ret, data_len;
|
||||
ssize_t ret, data_len = -EINVAL;
|
||||
int halt;
|
||||
|
||||
/* Are we still active? */
|
||||
@ -787,13 +798,30 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
|
||||
/* Fire the request */
|
||||
struct usb_request *req;
|
||||
|
||||
/*
|
||||
* Sanity Check: even though data_len can't be used
|
||||
* uninitialized at the time I write this comment, some
|
||||
* compilers complain about this situation.
|
||||
* In order to keep the code clean from warnings, data_len is
|
||||
* being initialized to -EINVAL during its declaration, which
|
||||
* means we can't rely on compiler anymore to warn no future
|
||||
* changes won't result in data_len being used uninitialized.
|
||||
* For such reason, we're adding this redundant sanity check
|
||||
* here.
|
||||
*/
|
||||
if (unlikely(data_len == -EINVAL)) {
|
||||
WARN(1, "%s: data_len == -EINVAL\n", __func__);
|
||||
ret = -EINVAL;
|
||||
goto error_lock;
|
||||
}
|
||||
|
||||
if (io_data->aio) {
|
||||
req = usb_ep_alloc_request(ep->ep, GFP_KERNEL);
|
||||
if (unlikely(!req))
|
||||
goto error_lock;
|
||||
|
||||
req->buf = data;
|
||||
req->length = io_data->len;
|
||||
req->length = data_len;
|
||||
|
||||
io_data->buf = data;
|
||||
io_data->ep = ep->ep;
|
||||
@ -815,7 +843,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
|
||||
|
||||
req = ep->req;
|
||||
req->buf = data;
|
||||
req->length = io_data->len;
|
||||
req->length = data_len;
|
||||
|
||||
req->context = &done;
|
||||
req->complete = ffs_epfile_io_complete;
|
||||
@ -2663,8 +2691,6 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
|
||||
func->conf = c;
|
||||
func->gadget = c->cdev->gadget;
|
||||
|
||||
ffs_data_get(func->ffs);
|
||||
|
||||
/*
|
||||
* in drivers/usb/gadget/configfs.c:configfs_composite_bind()
|
||||
* configurations are bound in sequence with list_for_each_entry,
|
||||
|
@ -621,12 +621,14 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
dev = MKDEV(major, hidg->minor);
|
||||
status = cdev_add(&hidg->cdev, dev, 1);
|
||||
if (status)
|
||||
goto fail;
|
||||
goto fail_free_descs;
|
||||
|
||||
device_create(hidg_class, NULL, dev, NULL, "%s%d", "hidg", hidg->minor);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_free_descs:
|
||||
usb_free_all_descriptors(f);
|
||||
fail:
|
||||
ERROR(f->config->cdev, "hidg_bind FAILED\n");
|
||||
if (hidg->req != NULL) {
|
||||
@ -635,7 +637,6 @@ fail:
|
||||
usb_ep_free_request(hidg->in_ep, hidg->req);
|
||||
}
|
||||
|
||||
usb_free_all_descriptors(f);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -253,22 +253,13 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
|
||||
case 0: /* normal completion? */
|
||||
if (ep == loop->out_ep) {
|
||||
/* loop this OUT packet back IN to the host */
|
||||
req->zero = (req->actual < req->length);
|
||||
req->length = req->actual;
|
||||
status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC);
|
||||
if (status == 0)
|
||||
return;
|
||||
|
||||
/* "should never get here" */
|
||||
ERROR(cdev, "can't loop %s to %s: %d\n",
|
||||
ep->name, loop->in_ep->name,
|
||||
status);
|
||||
}
|
||||
|
||||
/* queue the buffer for some later OUT packet */
|
||||
req->length = buflen;
|
||||
status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC);
|
||||
status = usb_ep_queue(ep, req, GFP_ATOMIC);
|
||||
if (status == 0)
|
||||
return;
|
||||
|
||||
@ -308,60 +299,66 @@ static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
|
||||
return alloc_ep_req(ep, len, buflen);
|
||||
}
|
||||
|
||||
static int
|
||||
enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
|
||||
static int enable_endpoint(struct usb_composite_dev *cdev, struct f_loopback *loop,
|
||||
struct usb_ep *ep)
|
||||
{
|
||||
int result = 0;
|
||||
struct usb_ep *ep;
|
||||
struct usb_request *req;
|
||||
unsigned i;
|
||||
int result;
|
||||
|
||||
/* one endpoint writes data back IN to the host */
|
||||
ep = loop->in_ep;
|
||||
result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
|
||||
if (result)
|
||||
return result;
|
||||
result = usb_ep_enable(ep);
|
||||
if (result < 0)
|
||||
return result;
|
||||
ep->driver_data = loop;
|
||||
|
||||
/* one endpoint just reads OUT packets */
|
||||
ep = loop->out_ep;
|
||||
/*
|
||||
* one endpoint writes data back IN to the host while another endpoint
|
||||
* just reads OUT packets
|
||||
*/
|
||||
result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
|
||||
if (result)
|
||||
goto fail0;
|
||||
|
||||
result = usb_ep_enable(ep);
|
||||
if (result < 0) {
|
||||
fail0:
|
||||
ep = loop->in_ep;
|
||||
usb_ep_disable(ep);
|
||||
ep->driver_data = NULL;
|
||||
return result;
|
||||
}
|
||||
if (result < 0)
|
||||
goto fail0;
|
||||
ep->driver_data = loop;
|
||||
|
||||
/* allocate a bunch of read buffers and queue them all at once.
|
||||
/*
|
||||
* allocate a bunch of read buffers and queue them all at once.
|
||||
* we buffer at most 'qlen' transfers; fewer if any need more
|
||||
* than 'buflen' bytes each.
|
||||
*/
|
||||
for (i = 0; i < qlen && result == 0; i++) {
|
||||
req = lb_alloc_ep_req(ep, 0);
|
||||
if (req) {
|
||||
req->complete = loopback_complete;
|
||||
result = usb_ep_queue(ep, req, GFP_ATOMIC);
|
||||
if (result)
|
||||
ERROR(cdev, "%s queue req --> %d\n",
|
||||
ep->name, result);
|
||||
} else {
|
||||
usb_ep_disable(ep);
|
||||
ep->driver_data = NULL;
|
||||
result = -ENOMEM;
|
||||
goto fail0;
|
||||
if (!req)
|
||||
goto fail1;
|
||||
|
||||
req->complete = loopback_complete;
|
||||
result = usb_ep_queue(ep, req, GFP_ATOMIC);
|
||||
if (result) {
|
||||
ERROR(cdev, "%s queue req --> %d\n",
|
||||
ep->name, result);
|
||||
goto fail1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail1:
|
||||
usb_ep_disable(ep);
|
||||
|
||||
fail0:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result = enable_endpoint(cdev, loop, loop->in_ep);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = enable_endpoint(cdev, loop, loop->out_ep);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
DBG(cdev, "%s enabled\n", loop->function.name);
|
||||
return result;
|
||||
}
|
||||
|
@ -1461,7 +1461,6 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
usb_free_all_descriptors(f);
|
||||
if (ncm->notify_req) {
|
||||
kfree(ncm->notify_req->buf);
|
||||
usb_ep_free_request(ncm->notify, ncm->notify_req);
|
||||
|
@ -35,6 +35,7 @@ struct f_obex {
|
||||
struct gserial port;
|
||||
u8 ctrl_id;
|
||||
u8 data_id;
|
||||
u8 cur_alt;
|
||||
u8 port_num;
|
||||
u8 can_activate;
|
||||
};
|
||||
@ -235,6 +236,8 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
||||
} else
|
||||
goto fail;
|
||||
|
||||
obex->cur_alt = alt;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@ -245,10 +248,7 @@ static int obex_get_alt(struct usb_function *f, unsigned intf)
|
||||
{
|
||||
struct f_obex *obex = func_to_obex(f);
|
||||
|
||||
if (intf == obex->ctrl_id)
|
||||
return 0;
|
||||
|
||||
return obex->port.in->driver_data ? 1 : 0;
|
||||
return obex->cur_alt;
|
||||
}
|
||||
|
||||
static void obex_disable(struct usb_function *f)
|
||||
@ -397,7 +397,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
usb_free_all_descriptors(f);
|
||||
/* we might as well release our claims on endpoints */
|
||||
if (obex->port.out)
|
||||
obex->port.out->driver_data = NULL;
|
||||
|
@ -570,8 +570,8 @@ static int pn_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
err_req:
|
||||
for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++)
|
||||
usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
|
||||
err:
|
||||
usb_free_all_descriptors(f);
|
||||
err:
|
||||
if (fp->out_ep)
|
||||
fp->out_ep->driver_data = NULL;
|
||||
if (fp->in_ep)
|
||||
|
@ -802,8 +802,10 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
|
||||
if (rndis->manufacturer && rndis->vendorID &&
|
||||
rndis_set_param_vendor(rndis->config, rndis->vendorID,
|
||||
rndis->manufacturer))
|
||||
goto fail;
|
||||
rndis->manufacturer)) {
|
||||
status = -EINVAL;
|
||||
goto fail_free_descs;
|
||||
}
|
||||
|
||||
/* NOTE: all that is done without knowing or caring about
|
||||
* the network link ... which is unavailable to this code
|
||||
@ -817,10 +819,11 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
rndis->notify->name);
|
||||
return 0;
|
||||
|
||||
fail_free_descs:
|
||||
usb_free_all_descriptors(f);
|
||||
fail:
|
||||
kfree(f->os_desc_table);
|
||||
f->os_desc_n = 0;
|
||||
usb_free_all_descriptors(f);
|
||||
|
||||
if (rndis->notify_req) {
|
||||
kfree(rndis->notify_req->buf);
|
||||
|
@ -380,7 +380,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
usb_free_all_descriptors(f);
|
||||
/* we might as well release our claims on endpoints */
|
||||
if (geth->port.out_ep)
|
||||
geth->port.out_ep->driver_data = NULL;
|
||||
|
@ -512,6 +512,11 @@ static int snd_uac2_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_uac2_release(struct device *dev)
|
||||
{
|
||||
dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
|
||||
}
|
||||
|
||||
static int alsa_uac2_init(struct audio_dev *agdev)
|
||||
{
|
||||
struct snd_uac2_chip *uac2 = &agdev->uac2;
|
||||
@ -523,6 +528,7 @@ static int alsa_uac2_init(struct audio_dev *agdev)
|
||||
|
||||
uac2->pdev.id = 0;
|
||||
uac2->pdev.name = uac2_name;
|
||||
uac2->pdev.dev.release = snd_uac2_release;
|
||||
|
||||
/* Register snd_uac2 driver */
|
||||
err = platform_driver_register(&uac2->pdrv);
|
||||
@ -772,6 +778,7 @@ struct usb_endpoint_descriptor fs_epout_desc = {
|
||||
|
||||
.bEndpointAddress = USB_DIR_OUT,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
|
||||
.wMaxPacketSize = cpu_to_le16(1023),
|
||||
.bInterval = 1,
|
||||
};
|
||||
|
||||
@ -780,6 +787,7 @@ struct usb_endpoint_descriptor hs_epout_desc = {
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
|
||||
.wMaxPacketSize = cpu_to_le16(1024),
|
||||
.bInterval = 4,
|
||||
};
|
||||
|
||||
@ -847,6 +855,7 @@ struct usb_endpoint_descriptor fs_epin_desc = {
|
||||
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
|
||||
.wMaxPacketSize = cpu_to_le16(1023),
|
||||
.bInterval = 1,
|
||||
};
|
||||
|
||||
@ -855,6 +864,7 @@ struct usb_endpoint_descriptor hs_epin_desc = {
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
|
||||
.wMaxPacketSize = cpu_to_le16(1024),
|
||||
.bInterval = 4,
|
||||
};
|
||||
|
||||
@ -947,6 +957,9 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
|
||||
struct snd_uac2_chip *uac2 = prm->uac2;
|
||||
int i;
|
||||
|
||||
if (!prm->ep_enabled)
|
||||
return;
|
||||
|
||||
prm->ep_enabled = false;
|
||||
|
||||
for (i = 0; i < USB_XFERS; i++) {
|
||||
@ -1071,7 +1084,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
|
||||
prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
|
||||
if (!prm->rbuf) {
|
||||
prm->max_psize = 0;
|
||||
goto err;
|
||||
goto err_free_descs;
|
||||
}
|
||||
|
||||
prm = &agdev->uac2.p_prm;
|
||||
@ -1079,17 +1092,19 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
|
||||
prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
|
||||
if (!prm->rbuf) {
|
||||
prm->max_psize = 0;
|
||||
goto err;
|
||||
goto err_free_descs;
|
||||
}
|
||||
|
||||
ret = alsa_uac2_init(agdev);
|
||||
if (ret)
|
||||
goto err;
|
||||
goto err_free_descs;
|
||||
return 0;
|
||||
|
||||
err_free_descs:
|
||||
usb_free_all_descriptors(fn);
|
||||
err:
|
||||
kfree(agdev->uac2.p_prm.rbuf);
|
||||
kfree(agdev->uac2.c_prm.rbuf);
|
||||
usb_free_all_descriptors(fn);
|
||||
if (agdev->in_ep)
|
||||
agdev->in_ep->driver_data = NULL;
|
||||
if (agdev->out_ep)
|
||||
|
@ -279,27 +279,41 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface)
|
||||
else if (interface != uvc->streaming_intf)
|
||||
return -EINVAL;
|
||||
else
|
||||
return uvc->state == UVC_STATE_STREAMING ? 1 : 0;
|
||||
return uvc->video.ep->driver_data ? 1 : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
|
||||
{
|
||||
struct uvc_device *uvc = to_uvc(f);
|
||||
struct usb_composite_dev *cdev = f->config->cdev;
|
||||
struct v4l2_event v4l2_event;
|
||||
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
|
||||
int ret;
|
||||
|
||||
INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
|
||||
INFO(cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
|
||||
|
||||
if (interface == uvc->control_intf) {
|
||||
if (alt)
|
||||
return -EINVAL;
|
||||
|
||||
if (uvc->control_ep->driver_data) {
|
||||
INFO(cdev, "reset UVC Control\n");
|
||||
usb_ep_disable(uvc->control_ep);
|
||||
uvc->control_ep->driver_data = NULL;
|
||||
}
|
||||
|
||||
if (!uvc->control_ep->desc)
|
||||
if (config_ep_by_speed(cdev->gadget, f, uvc->control_ep))
|
||||
return -EINVAL;
|
||||
|
||||
usb_ep_enable(uvc->control_ep);
|
||||
uvc->control_ep->driver_data = uvc;
|
||||
|
||||
if (uvc->state == UVC_STATE_DISCONNECTED) {
|
||||
memset(&v4l2_event, 0, sizeof(v4l2_event));
|
||||
v4l2_event.type = UVC_EVENT_CONNECT;
|
||||
uvc_event->speed = f->config->cdev->gadget->speed;
|
||||
uvc_event->speed = cdev->gadget->speed;
|
||||
v4l2_event_queue(uvc->vdev, &v4l2_event);
|
||||
|
||||
uvc->state = UVC_STATE_CONNECTED;
|
||||
@ -321,8 +335,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
|
||||
if (uvc->state != UVC_STATE_STREAMING)
|
||||
return 0;
|
||||
|
||||
if (uvc->video.ep)
|
||||
if (uvc->video.ep) {
|
||||
usb_ep_disable(uvc->video.ep);
|
||||
uvc->video.ep->driver_data = NULL;
|
||||
}
|
||||
|
||||
memset(&v4l2_event, 0, sizeof(v4l2_event));
|
||||
v4l2_event.type = UVC_EVENT_STREAMOFF;
|
||||
@ -335,14 +351,22 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
|
||||
if (uvc->state != UVC_STATE_CONNECTED)
|
||||
return 0;
|
||||
|
||||
if (uvc->video.ep) {
|
||||
ret = config_ep_by_speed(f->config->cdev->gadget,
|
||||
&(uvc->func), uvc->video.ep);
|
||||
if (ret)
|
||||
return ret;
|
||||
usb_ep_enable(uvc->video.ep);
|
||||
if (!uvc->video.ep)
|
||||
return -EINVAL;
|
||||
|
||||
if (uvc->video.ep->driver_data) {
|
||||
INFO(cdev, "reset UVC\n");
|
||||
usb_ep_disable(uvc->video.ep);
|
||||
uvc->video.ep->driver_data = NULL;
|
||||
}
|
||||
|
||||
ret = config_ep_by_speed(f->config->cdev->gadget,
|
||||
&(uvc->func), uvc->video.ep);
|
||||
if (ret)
|
||||
return ret;
|
||||
usb_ep_enable(uvc->video.ep);
|
||||
uvc->video.ep->driver_data = uvc;
|
||||
|
||||
memset(&v4l2_event, 0, sizeof(v4l2_event));
|
||||
v4l2_event.type = UVC_EVENT_STREAMON;
|
||||
v4l2_event_queue(uvc->vdev, &v4l2_event);
|
||||
@ -366,6 +390,16 @@ uvc_function_disable(struct usb_function *f)
|
||||
v4l2_event_queue(uvc->vdev, &v4l2_event);
|
||||
|
||||
uvc->state = UVC_STATE_DISCONNECTED;
|
||||
|
||||
if (uvc->video.ep->driver_data) {
|
||||
usb_ep_disable(uvc->video.ep);
|
||||
uvc->video.ep->driver_data = NULL;
|
||||
}
|
||||
|
||||
if (uvc->control_ep->driver_data) {
|
||||
usb_ep_disable(uvc->control_ep);
|
||||
uvc->control_ep->driver_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
|
@ -352,7 +352,8 @@ int uvcg_video_enable(struct uvc_video *video, int enable)
|
||||
|
||||
if (!enable) {
|
||||
for (i = 0; i < UVC_NUM_REQUESTS; ++i)
|
||||
usb_ep_dequeue(video->ep, video->req[i]);
|
||||
if (video->req[i])
|
||||
usb_ep_dequeue(video->ep, video->req[i]);
|
||||
|
||||
uvc_video_free_requests(video);
|
||||
uvcg_queue_enable(&video->queue, 0);
|
||||
|
@ -357,6 +357,7 @@ config USB_EG20T
|
||||
|
||||
config USB_GADGET_XILINX
|
||||
tristate "Xilinx USB Driver"
|
||||
depends on HAS_DMA
|
||||
depends on OF || COMPILE_TEST
|
||||
help
|
||||
USB peripheral controller driver for Xilinx USB2 device.
|
||||
|
@ -507,6 +507,11 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
|
||||
{
|
||||
struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
|
||||
|
||||
if (!udc->driver) {
|
||||
dev_err(dev, "soft-connect without a gadget driver\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (sysfs_streq(buf, "connect")) {
|
||||
usb_gadget_udc_start(udc->gadget, udc->driver);
|
||||
usb_gadget_connect(udc->gadget);
|
||||
|
@ -209,7 +209,8 @@ static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
|
||||
}
|
||||
}
|
||||
|
||||
if (!list_empty(&controller->early_tx_list)) {
|
||||
if (!list_empty(&controller->early_tx_list) &&
|
||||
!hrtimer_is_queued(&controller->early_tx)) {
|
||||
ret = HRTIMER_RESTART;
|
||||
hrtimer_forward_now(&controller->early_tx,
|
||||
ktime_set(0, 20 * NSEC_PER_USEC));
|
||||
|
@ -868,9 +868,15 @@ static int dsps_suspend(struct device *dev)
|
||||
struct dsps_glue *glue = dev_get_drvdata(dev);
|
||||
const struct dsps_musb_wrapper *wrp = glue->wrp;
|
||||
struct musb *musb = platform_get_drvdata(glue->musb);
|
||||
void __iomem *mbase = musb->ctrl_base;
|
||||
void __iomem *mbase;
|
||||
|
||||
del_timer_sync(&glue->timer);
|
||||
|
||||
if (!musb)
|
||||
/* This can happen if the musb device is in -EPROBE_DEFER */
|
||||
return 0;
|
||||
|
||||
mbase = musb->ctrl_base;
|
||||
glue->context.control = dsps_readl(mbase, wrp->control);
|
||||
glue->context.epintr = dsps_readl(mbase, wrp->epintr_set);
|
||||
glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set);
|
||||
@ -887,8 +893,12 @@ static int dsps_resume(struct device *dev)
|
||||
struct dsps_glue *glue = dev_get_drvdata(dev);
|
||||
const struct dsps_musb_wrapper *wrp = glue->wrp;
|
||||
struct musb *musb = platform_get_drvdata(glue->musb);
|
||||
void __iomem *mbase = musb->ctrl_base;
|
||||
void __iomem *mbase;
|
||||
|
||||
if (!musb)
|
||||
return 0;
|
||||
|
||||
mbase = musb->ctrl_base;
|
||||
dsps_writel(mbase, wrp->control, glue->context.control);
|
||||
dsps_writel(mbase, wrp->epintr_set, glue->context.epintr);
|
||||
dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr);
|
||||
@ -896,7 +906,9 @@ static int dsps_resume(struct device *dev)
|
||||
dsps_writel(mbase, wrp->mode, glue->context.mode);
|
||||
dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode);
|
||||
dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode);
|
||||
setup_timer(&glue->timer, otg_timer, (unsigned long) musb);
|
||||
if (musb->xceiv->state == OTG_STATE_B_IDLE &&
|
||||
musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
|
||||
mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -155,6 +155,7 @@ static const struct usb_device_id id_table[] = {
|
||||
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
|
||||
{ USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
|
||||
{ USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
|
||||
{ USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */
|
||||
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
|
||||
{ USB_DEVICE(0x1D6F, 0x0010) }, /* Seluxit ApS RF Dongle */
|
||||
{ USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
|
||||
|
@ -140,6 +140,7 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = {
|
||||
* /sys/bus/usb-serial/drivers/ftdi_sio/new_id and send a patch or report.
|
||||
*/
|
||||
static const struct usb_device_id id_table_combined[] = {
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_BRICK_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) },
|
||||
@ -661,6 +662,8 @@ static const struct usb_device_id id_table_combined[] = {
|
||||
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
|
||||
{ USB_DEVICE(XSENS_VID, XSENS_AWINDA_DONGLE_PID) },
|
||||
{ USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) },
|
||||
{ USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) },
|
||||
{ USB_DEVICE(XSENS_VID, XSENS_MTW_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
|
||||
|
@ -30,6 +30,12 @@
|
||||
|
||||
/*** third-party PIDs (using FTDI_VID) ***/
|
||||
|
||||
/*
|
||||
* Certain versions of the official Windows FTDI driver reprogrammed
|
||||
* counterfeit FTDI devices to PID 0. Support these devices anyway.
|
||||
*/
|
||||
#define FTDI_BRICK_PID 0x0000
|
||||
|
||||
#define FTDI_LUMEL_PD12_PID 0x6002
|
||||
|
||||
/*
|
||||
@ -143,8 +149,12 @@
|
||||
* Xsens Technologies BV products (http://www.xsens.com).
|
||||
*/
|
||||
#define XSENS_VID 0x2639
|
||||
#define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */
|
||||
#define XSENS_AWINDA_STATION_PID 0x0101
|
||||
#define XSENS_AWINDA_DONGLE_PID 0x0102
|
||||
#define XSENS_MTW_PID 0x0200 /* Xsens MTw */
|
||||
#define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */
|
||||
|
||||
/* Xsens devices using FTDI VID */
|
||||
#define XSENS_CONVERTER_0_PID 0xD388 /* Xsens USB converter */
|
||||
#define XSENS_CONVERTER_1_PID 0xD389 /* Xsens Wireless Receiver */
|
||||
#define XSENS_CONVERTER_2_PID 0xD38A
|
||||
|
@ -414,8 +414,6 @@ static int kobil_tiocmset(struct tty_struct *tty,
|
||||
int result;
|
||||
int dtr = 0;
|
||||
int rts = 0;
|
||||
unsigned char *transfer_buffer;
|
||||
int transfer_buffer_length = 8;
|
||||
|
||||
/* FIXME: locking ? */
|
||||
priv = usb_get_serial_port_data(port);
|
||||
@ -425,11 +423,6 @@ static int kobil_tiocmset(struct tty_struct *tty,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* allocate memory for transfer buffer */
|
||||
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
|
||||
if (!transfer_buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
if (set & TIOCM_RTS)
|
||||
rts = 1;
|
||||
if (set & TIOCM_DTR)
|
||||
@ -469,7 +462,6 @@ static int kobil_tiocmset(struct tty_struct *tty,
|
||||
KOBIL_TIMEOUT);
|
||||
}
|
||||
dev_dbg(dev, "%s - Send set_status_line URB returns: %i\n", __func__, result);
|
||||
kfree(transfer_buffer);
|
||||
return (result < 0) ? result : 0;
|
||||
}
|
||||
|
||||
@ -530,8 +522,6 @@ static int kobil_ioctl(struct tty_struct *tty,
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct kobil_private *priv = usb_get_serial_port_data(port);
|
||||
unsigned char *transfer_buffer;
|
||||
int transfer_buffer_length = 8;
|
||||
int result;
|
||||
|
||||
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
|
||||
@ -541,10 +531,6 @@ static int kobil_ioctl(struct tty_struct *tty,
|
||||
|
||||
switch (cmd) {
|
||||
case TCFLSH:
|
||||
transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
|
||||
if (!transfer_buffer)
|
||||
return -ENOBUFS;
|
||||
|
||||
result = usb_control_msg(port->serial->dev,
|
||||
usb_sndctrlpipe(port->serial->dev, 0),
|
||||
SUSBCRequest_Misc,
|
||||
@ -559,7 +545,6 @@ static int kobil_ioctl(struct tty_struct *tty,
|
||||
dev_dbg(&port->dev,
|
||||
"%s - Send reset_all_queues (FLUSH) URB returns: %i\n",
|
||||
__func__, result);
|
||||
kfree(transfer_buffer);
|
||||
return (result < 0) ? -EIO: 0;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
|
@ -269,6 +269,7 @@ static void option_instat_callback(struct urb *urb);
|
||||
#define TELIT_PRODUCT_DE910_DUAL 0x1010
|
||||
#define TELIT_PRODUCT_UE910_V2 0x1012
|
||||
#define TELIT_PRODUCT_LE920 0x1200
|
||||
#define TELIT_PRODUCT_LE910 0x1201
|
||||
|
||||
/* ZTE PRODUCTS */
|
||||
#define ZTE_VENDOR_ID 0x19d2
|
||||
@ -362,6 +363,7 @@ static void option_instat_callback(struct urb *urb);
|
||||
|
||||
/* Haier products */
|
||||
#define HAIER_VENDOR_ID 0x201e
|
||||
#define HAIER_PRODUCT_CE81B 0x10f8
|
||||
#define HAIER_PRODUCT_CE100 0x2009
|
||||
|
||||
/* Cinterion (formerly Siemens) products */
|
||||
@ -589,6 +591,11 @@ static const struct option_blacklist_info zte_1255_blacklist = {
|
||||
.reserved = BIT(3) | BIT(4),
|
||||
};
|
||||
|
||||
static const struct option_blacklist_info telit_le910_blacklist = {
|
||||
.sendsetup = BIT(0),
|
||||
.reserved = BIT(1) | BIT(2),
|
||||
};
|
||||
|
||||
static const struct option_blacklist_info telit_le920_blacklist = {
|
||||
.sendsetup = BIT(0),
|
||||
.reserved = BIT(1) | BIT(5),
|
||||
@ -1138,6 +1145,8 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
|
||||
.driver_info = (kernel_ulong_t)&telit_le910_blacklist },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
|
||||
.driver_info = (kernel_ulong_t)&telit_le920_blacklist },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
|
||||
@ -1621,6 +1630,7 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
|
||||
{ USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
|
||||
{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(HAIER_VENDOR_ID, HAIER_PRODUCT_CE81B, 0xff, 0xff, 0xff) },
|
||||
/* Pirelli */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) },
|
||||
|
Loading…
Reference in New Issue
Block a user