mirror of
https://github.com/ukui/kernel.git
synced 2026-03-09 10:07:04 -07:00
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:
@@ -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 */
|
||||
|
||||
+36
-12
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+23
-16
@@ -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
|
||||
|
||||
+38
-15
@@ -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;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user