Commit 528a506e authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 4f4274af 9c19db5b
......@@ -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(&params, 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, &params);
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;
/*
* 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)
return result;
goto fail0;
result = usb_ep_enable(ep);
if (result < 0)
return result;
ep->driver_data = loop;
/* one endpoint just reads OUT packets */
ep = loop->out_ep;
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;
}
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;