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 ...
Unified · Split
| @@ -742,7 +742,6 @@ static int ci_hdrc_remove(struct platform_device *pdev) · 741 unmodified lines | ||
| 742 | 742 | ci_role_destroy(ci); |
| 743 | 743 | ci_hdrc_enter_lpm(ci, true); |
| 744 | 744 | usb_phy_shutdown(ci->transceiver); |
| 745 | − kfree(ci->hw_bank.regmap); | |
| 746 | 745 | |
| 747 | 746 | return 0; |
| 748 | 747 | } |
| @@ -619,7 +619,7 @@ struct dwc2_hsotg { · 618 unmodified lines | ||
| 619 | 619 | unsigned port_suspend_change:1; |
| 620 | 620 | unsigned port_over_current_change:1; |
| 621 | 621 | unsigned port_l1_change:1; |
| 622 | − unsigned reserved:26; | |
| 622 | + unsigned reserved:25; | |
| 623 | 623 | } b; |
| 624 | 624 | } flags; |
| 625 | 625 | |
| @@ -2561,8 +2561,10 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, · 2560 unmodified lines | ||
| 2561 | 2561 | hs_ep->fifo_size = val; |
| 2562 | 2562 | break; |
| 2563 | 2563 | } |
| 2564 | − if (i == 8) | |
| 2565 | − return -ENOMEM; | |
| 2564 | + if (i == 8) { | |
| 2565 | + ret = -ENOMEM; | |
| 2566 | + goto error; | |
| 2567 | + } | |
| 2566 | 2568 | } |
| 2567 | 2569 | |
| 2568 | 2570 | /* for non control endpoints, set PID to D0 */ |
| @@ -2579,6 +2581,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, · 10 unmodified lines | ||
| 2579 | 2581 | /* enable the endpoint interrupt */ |
| 2580 | 2582 | s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1); |
| 2581 | 2583 | |
| 2584 | +error: | |
| 2582 | 2585 | spin_unlock_irqrestore(&hsotg->lock, flags); |
| 2583 | 2586 | return ret; |
| 2584 | 2587 | } |
| @@ -2934,9 +2937,7 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, · 349 unmodified lines | ||
| 2934 | 2937 | |
| 2935 | 2938 | spin_lock_irqsave(&hsotg->lock, flags); |
| 2936 | 2939 | |
| 2937 | − if (!driver) | |
| 2938 | − hsotg->driver = NULL; | |
| 2939 | − | |
| 2940 | + hsotg->driver = NULL; | |
| 2940 | 2941 | hsotg->gadget.speed = USB_SPEED_UNKNOWN; |
| 2941 | 2942 | |
| 2942 | 2943 | spin_unlock_irqrestore(&hsotg->lock, flags); |
| @@ -3567,6 +3568,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev) · 624 unmodified lines | ||
| 3567 | 3568 | s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum); |
| 3568 | 3569 | |
| 3569 | 3570 | /* disable power and clock */ |
| 3571 | + s3c_hsotg_phy_disable(hsotg); | |
| 3570 | 3572 | |
| 3571 | 3573 | ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), |
| 3572 | 3574 | hsotg->supplies); |
| @@ -3575,8 +3577,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 3575 | 3577 | goto err_ep_mem; |
| 3576 | 3578 | } |
| 3577 | 3579 | |
| 3578 | − s3c_hsotg_phy_disable(hsotg); | |
| 3579 | − | |
| 3580 | 3580 | ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget); |
| 3581 | 3581 | if (ret) |
| 3582 | 3582 | goto err_ep_mem; |
| @@ -597,7 +597,7 @@ static int dwc3_omap_prepare(struct device *dev) · 596 unmodified lines | ||
| 597 | 597 | { |
| 598 | 598 | struct dwc3_omap *omap = dev_get_drvdata(dev); |
| 599 | 599 | |
| 600 | − dwc3_omap_write_irqmisc_set(omap, 0x00); | |
| 600 | + dwc3_omap_disable_irqs(omap); | |
| 601 | 601 | |
| 602 | 602 | return 0; |
| 603 | 603 | } |
| @@ -605,19 +605,8 @@ static int dwc3_omap_prepare(struct device *dev) · 1 unmodified line | ||
| 605 | 605 | static void dwc3_omap_complete(struct device *dev) |
| 606 | 606 | { |
| 607 | 607 | struct dwc3_omap *omap = dev_get_drvdata(dev); |
| 608 | − u32 reg; | |
| 609 | 608 | |
| 610 | − reg = (USBOTGSS_IRQMISC_OEVT | | |
| 611 | − USBOTGSS_IRQMISC_DRVVBUS_RISE | | |
| 612 | − USBOTGSS_IRQMISC_CHRGVBUS_RISE | | |
| 613 | − USBOTGSS_IRQMISC_DISCHRGVBUS_RISE | | |
| 614 | − USBOTGSS_IRQMISC_IDPULLUP_RISE | | |
| 615 | − USBOTGSS_IRQMISC_DRVVBUS_FALL | | |
| 616 | − USBOTGSS_IRQMISC_CHRGVBUS_FALL | | |
| 617 | − USBOTGSS_IRQMISC_DISCHRGVBUS_FALL | | |
| 618 | − USBOTGSS_IRQMISC_IDPULLUP_FALL); | |
| 619 | − | |
| 620 | − dwc3_omap_write_irqmisc_set(omap, reg); | |
| 609 | + dwc3_omap_enable_irqs(omap); | |
| 621 | 610 | } |
| 622 | 611 | |
| 623 | 612 | static int dwc3_omap_suspend(struct device *dev) |
| @@ -30,6 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd |
| 31 | 31 | #define PCI_DEVICE_ID_INTEL_BYT 0x0f37 |
| 32 | 32 | #define PCI_DEVICE_ID_INTEL_MRFLD 0x119e |
| 33 | +#define PCI_DEVICE_ID_INTEL_BSW 0x22B7 | |
| 33 | 34 | |
| 34 | 35 | struct dwc3_pci { |
| 35 | 36 | struct device *dev; |
| @@ -181,6 +182,7 @@ static const struct pci_device_id dwc3_pci_id_table[] = { · 145 unmodified lines | ||
| 181 | 182 | PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, |
| 182 | 183 | PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3), |
| 183 | 184 | }, |
| 185 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), }, | |
| 184 | 186 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), }, |
| 185 | 187 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), }, |
| 186 | 188 | { } /* Terminating Entry */ |
| @@ -256,7 +256,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) · 255 unmodified lines | ||
| 256 | 256 | |
| 257 | 257 | /* stall is always issued on EP0 */ |
| 258 | 258 | dep = dwc->eps[0]; |
| 259 | − __dwc3_gadget_ep_set_halt(dep, 1); | |
| 259 | + __dwc3_gadget_ep_set_halt(dep, 1, false); | |
| 260 | 260 | dep->flags = DWC3_EP_ENABLED; |
| 261 | 261 | dwc->delayed_status = false; |
| 262 | 262 | |
| @@ -271,7 +271,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) · 8 unmodified lines | ||
| 271 | 271 | dwc3_ep0_out_start(dwc); |
| 272 | 272 | } |
| 273 | 273 | |
| 274 | −int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value) | |
| 274 | +int __dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value) | |
| 275 | 275 | { |
| 276 | 276 | struct dwc3_ep *dep = to_dwc3_ep(ep); |
| 277 | 277 | struct dwc3 *dwc = dep->dwc; |
| @@ -281,6 +281,20 @@ int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value) · 3 unmodified lines | ||
| 281 | 281 | return 0; |
| 282 | 282 | } |
| 283 | 283 | |
| 284 | +int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value) | |
| 285 | +{ | |
| 286 | + struct dwc3_ep *dep = to_dwc3_ep(ep); | |
| 287 | + struct dwc3 *dwc = dep->dwc; | |
| 288 | + unsigned long flags; | |
| 289 | + int ret; | |
| 290 | + | |
| 291 | + spin_lock_irqsave(&dwc->lock, flags); | |
| 292 | + ret = __dwc3_gadget_ep0_set_halt(ep, value); | |
| 293 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 294 | + | |
| 295 | + return ret; | |
| 296 | +} | |
| 297 | + | |
| 284 | 298 | void dwc3_ep0_out_start(struct dwc3 *dwc) |
| 285 | 299 | { |
| 286 | 300 | int ret; |
| @@ -466,7 +480,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, · 179 unmodified lines | ||
| 466 | 480 | return -EINVAL; |
| 467 | 481 | if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) |
| 468 | 482 | break; |
| 469 | − ret = __dwc3_gadget_ep_set_halt(dep, set); | |
| 483 | + ret = __dwc3_gadget_ep_set_halt(dep, set, true); | |
| 470 | 484 | if (ret) |
| 471 | 485 | return -EINVAL; |
| 472 | 486 | break; |
| @@ -775,9 +789,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, · 302 unmodified lines | ||
| 775 | 789 | |
| 776 | 790 | dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; |
| 777 | 791 | |
| 778 | − r = next_request(&ep0->request_list); | |
| 779 | − ur = &r->request; | |
| 780 | − | |
| 781 | 792 | trb = dwc->ep0_trb; |
| 782 | 793 | |
| 783 | 794 | status = DWC3_TRB_SIZE_TRBSTS(trb->size); |
| @@ -790,6 +801,12 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, · 6 unmodified lines | ||
| 790 | 801 | return; |
| 791 | 802 | } |
| 792 | 803 | |
| 804 | + r = next_request(&ep0->request_list); | |
| 805 | + if (!r) | |
| 806 | + return; | |
| 807 | + | |
| 808 | + ur = &r->request; | |
| 809 | + | |
| 793 | 810 | length = trb->size & DWC3_TRB_SIZE_MASK; |
| 794 | 811 | |
| 795 | 812 | if (dwc->ep0_bounced) { |
| @@ -811,12 +828,19 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, · 15 unmodified lines | ||
| 811 | 828 | |
| 812 | 829 | dwc3_ep0_stall_and_restart(dwc); |
| 813 | 830 | } else { |
| 814 | − /* | |
| 815 | − * handle the case where we have to send a zero packet. This | |
| 816 | − * seems to be case when req.length > maxpacket. Could it be? | |
| 817 | − */ | |
| 818 | − if (r) | |
| 819 | − dwc3_gadget_giveback(ep0, r, 0); | |
| 831 | + dwc3_gadget_giveback(ep0, r, 0); | |
| 832 | + | |
| 833 | + if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) && | |
| 834 | + ur->length && ur->zero) { | |
| 835 | + int ret; | |
| 836 | + | |
| 837 | + dwc->ep0_next_event = DWC3_EP0_COMPLETE; | |
| 838 | + | |
| 839 | + ret = dwc3_ep0_start_trans(dwc, epnum, | |
| 840 | + dwc->ctrl_req_addr, 0, | |
| 841 | + DWC3_TRBCTL_CONTROL_DATA); | |
| 842 | + WARN_ON(ret < 0); | |
| 843 | + } | |
| 820 | 844 | } |
| 821 | 845 | } |
| 822 | 846 | |
| @@ -525,12 +525,11 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, · 524 unmodified lines | ||
| 525 | 525 | if (!usb_endpoint_xfer_isoc(desc)) |
| 526 | 526 | return 0; |
| 527 | 527 | |
| 528 | − memset(&trb_link, 0, sizeof(trb_link)); | |
| 529 | − | |
| 530 | 528 | /* Link TRB for ISOC. The HWO bit is never reset */ |
| 531 | 529 | trb_st_hw = &dep->trb_pool[0]; |
| 532 | 530 | |
| 533 | 531 | trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1]; |
| 532 | + memset(trb_link, 0, sizeof(*trb_link)); | |
| 534 | 533 | |
| 535 | 534 | trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); |
| 536 | 535 | 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) · 44 unmodified lines | ||
| 581 | 580 | |
| 582 | 581 | /* make sure HW endpoint isn't stalled */ |
| 583 | 582 | if (dep->flags & DWC3_EP_STALL) |
| 584 | − __dwc3_gadget_ep_set_halt(dep, 0); | |
| 583 | + __dwc3_gadget_ep_set_halt(dep, 0, false); | |
| 585 | 584 | |
| 586 | 585 | reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); |
| 587 | 586 | reg &= ~DWC3_DALEPENA_EP(dep->number); |
| @@ -1202,15 +1201,28 @@ out0: · 614 unmodified lines | ||
| 1202 | 1201 | return ret; |
| 1203 | 1202 | } |
| 1204 | 1203 | |
| 1205 | −int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) | |
| 1204 | +int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) | |
| 1206 | 1205 | { |
| 1207 | 1206 | struct dwc3_gadget_ep_cmd_params params; |
| 1208 | 1207 | struct dwc3 *dwc = dep->dwc; |
| 1209 | 1208 | int ret; |
| 1210 | 1209 | |
| 1210 | + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { | |
| 1211 | + dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name); | |
| 1212 | + return -EINVAL; | |
| 1213 | + } | |
| 1214 | + | |
| 1211 | 1215 | memset(¶ms, 0x00, sizeof(params)); |
| 1212 | 1216 | |
| 1213 | 1217 | if (value) { |
| 1218 | + if (!protocol && ((dep->direction && dep->flags & DWC3_EP_BUSY) || | |
| 1219 | + (!list_empty(&dep->req_queued) || | |
| 1220 | + !list_empty(&dep->request_list)))) { | |
| 1221 | + dev_dbg(dwc->dev, "%s: pending request, cannot halt\n", | |
| 1222 | + dep->name); | |
| 1223 | + return -EAGAIN; | |
| 1224 | + } | |
| 1225 | + | |
| 1214 | 1226 | ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, |
| 1215 | 1227 | DWC3_DEPCMD_SETSTALL, ¶ms); |
| 1216 | 1228 | if (ret) |
| @@ -1241,15 +1253,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value) · 24 unmodified lines | ||
| 1241 | 1253 | int ret; |
| 1242 | 1254 | |
| 1243 | 1255 | spin_lock_irqsave(&dwc->lock, flags); |
| 1244 | − | |
| 1245 | − if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { | |
| 1246 | − dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name); | |
| 1247 | − ret = -EINVAL; | |
| 1248 | − goto out; | |
| 1249 | − } | |
| 1250 | − | |
| 1251 | − ret = __dwc3_gadget_ep_set_halt(dep, value); | |
| 1252 | −out: | |
| 1256 | + ret = __dwc3_gadget_ep_set_halt(dep, value, false); | |
| 1253 | 1257 | spin_unlock_irqrestore(&dwc->lock, flags); |
| 1254 | 1258 | |
| 1255 | 1259 | return ret; |
| @@ -1260,15 +1264,18 @@ static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep) · 4 unmodified lines | ||
| 1260 | 1264 | struct dwc3_ep *dep = to_dwc3_ep(ep); |
| 1261 | 1265 | struct dwc3 *dwc = dep->dwc; |
| 1262 | 1266 | unsigned long flags; |
| 1267 | + int ret; | |
| 1263 | 1268 | |
| 1264 | 1269 | spin_lock_irqsave(&dwc->lock, flags); |
| 1265 | 1270 | dep->flags |= DWC3_EP_WEDGE; |
| 1266 | − spin_unlock_irqrestore(&dwc->lock, flags); | |
| 1267 | 1271 | |
| 1268 | 1272 | if (dep->number == 0 || dep->number == 1) |
| 1269 | − return dwc3_gadget_ep0_set_halt(ep, 1); | |
| 1273 | + ret = __dwc3_gadget_ep0_set_halt(ep, 1); | |
| 1270 | 1274 | else |
| 1271 | − return dwc3_gadget_ep_set_halt(ep, 1); | |
| 1275 | + ret = __dwc3_gadget_ep_set_halt(dep, 1, false); | |
| 1276 | + spin_unlock_irqrestore(&dwc->lock, flags); | |
| 1277 | + | |
| 1278 | + return ret; | |
| 1272 | 1279 | } |
| 1273 | 1280 | |
| 1274 | 1281 | /* -------------------------------------------------------------------------- */ |
| @@ -82,10 +82,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, · 81 unmodified lines | ||
| 82 | 82 | void dwc3_ep0_interrupt(struct dwc3 *dwc, |
| 83 | 83 | const struct dwc3_event_depevt *event); |
| 84 | 84 | void dwc3_ep0_out_start(struct dwc3 *dwc); |
| 85 | +int __dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value); | |
| 85 | 86 | int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value); |
| 86 | 87 | int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, |
| 87 | 88 | gfp_t gfp_flags); |
| 88 | −int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value); | |
| 89 | +int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol); | |
| 89 | 90 | |
| 90 | 91 | /** |
| 91 | 92 | * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW |
| @@ -73,15 +73,23 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl, · 72 unmodified lines | ||
| 73 | 73 | TP_PROTO(struct usb_ctrlrequest *ctrl), |
| 74 | 74 | TP_ARGS(ctrl), |
| 75 | 75 | TP_STRUCT__entry( |
| 76 | − __field(struct usb_ctrlrequest *, ctrl) | |
| 76 | + __field(__u8, bRequestType) | |
| 77 | + __field(__u8, bRequest) | |
| 78 | + __field(__le16, wValue) | |
| 79 | + __field(__le16, wIndex) | |
| 80 | + __field(__le16, wLength) | |
| 77 | 81 | ), |
| 78 | 82 | TP_fast_assign( |
| 79 | − __entry->ctrl = ctrl; | |
| 83 | + __entry->bRequestType = ctrl->bRequestType; | |
| 84 | + __entry->bRequest = ctrl->bRequest; | |
| 85 | + __entry->wValue = ctrl->wValue; | |
| 86 | + __entry->wIndex = ctrl->wIndex; | |
| 87 | + __entry->wLength = ctrl->wLength; | |
| 80 | 88 | ), |
| 81 | 89 | TP_printk("bRequestType %02x bRequest %02x wValue %04x wIndex %04x wLength %d", |
| 82 | − __entry->ctrl->bRequestType, __entry->ctrl->bRequest, | |
| 83 | − le16_to_cpu(__entry->ctrl->wValue), le16_to_cpu(__entry->ctrl->wIndex), | |
| 84 | − le16_to_cpu(__entry->ctrl->wLength) | |
| 90 | + __entry->bRequestType, __entry->bRequest, | |
| 91 | + le16_to_cpu(__entry->wValue), le16_to_cpu(__entry->wIndex), | |
| 92 | + le16_to_cpu(__entry->wLength) | |
| 85 | 93 | ) |
| 86 | 94 | ); |
| 87 | 95 | |
| @@ -94,15 +102,22 @@ DECLARE_EVENT_CLASS(dwc3_log_request, · 6 unmodified lines | ||
| 94 | 102 | TP_PROTO(struct dwc3_request *req), |
| 95 | 103 | TP_ARGS(req), |
| 96 | 104 | TP_STRUCT__entry( |
| 105 | + __dynamic_array(char, name, DWC3_MSG_MAX) | |
| 97 | 106 | __field(struct dwc3_request *, req) |
| 107 | + __field(unsigned, actual) | |
| 108 | + __field(unsigned, length) | |
| 109 | + __field(int, status) | |
| 98 | 110 | ), |
| 99 | 111 | TP_fast_assign( |
| 112 | + snprintf(__get_str(name), DWC3_MSG_MAX, "%s", req->dep->name); | |
| 100 | 113 | __entry->req = req; |
| 114 | + __entry->actual = req->request.actual; | |
| 115 | + __entry->length = req->request.length; | |
| 116 | + __entry->status = req->request.status; | |
| 101 | 117 | ), |
| 102 | 118 | TP_printk("%s: req %p length %u/%u ==> %d", |
| 103 | − __entry->req->dep->name, __entry->req, | |
| 104 | − __entry->req->request.actual, __entry->req->request.length, | |
| 105 | − __entry->req->request.status | |
| 119 | + __get_str(name), __entry->req, __entry->actual, __entry->length, | |
| 120 | + __entry->status | |
| 106 | 121 | ) |
| 107 | 122 | ); |
| 108 | 123 | |
| @@ -158,17 +173,17 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd, · 49 unmodified lines | ||
| 158 | 173 | struct dwc3_gadget_ep_cmd_params *params), |
| 159 | 174 | TP_ARGS(dep, cmd, params), |
| 160 | 175 | TP_STRUCT__entry( |
| 161 | − __field(struct dwc3_ep *, dep) | |
| 176 | + __dynamic_array(char, name, DWC3_MSG_MAX) | |
| 162 | 177 | __field(unsigned int, cmd) |
| 163 | 178 | __field(struct dwc3_gadget_ep_cmd_params *, params) |
| 164 | 179 | ), |
| 165 | 180 | TP_fast_assign( |
| 166 | − __entry->dep = dep; | |
| 181 | + snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name); | |
| 167 | 182 | __entry->cmd = cmd; |
| 168 | 183 | __entry->params = params; |
| 169 | 184 | ), |
| 170 | 185 | TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x\n", |
| 171 | − __entry->dep->name, dwc3_gadget_ep_cmd_string(__entry->cmd), | |
| 186 | + __get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd), | |
| 172 | 187 | __entry->cmd, __entry->params->param0, |
| 173 | 188 | __entry->params->param1, __entry->params->param2 |
| 174 | 189 | ) |
| @@ -184,16 +199,24 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, · 9 unmodified lines | ||
| 184 | 199 | TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb), |
| 185 | 200 | TP_ARGS(dep, trb), |
| 186 | 201 | TP_STRUCT__entry( |
| 187 | − __field(struct dwc3_ep *, dep) | |
| 202 | + __dynamic_array(char, name, DWC3_MSG_MAX) | |
| 188 | 203 | __field(struct dwc3_trb *, trb) |
| 204 | + __field(u32, bpl) | |
| 205 | + __field(u32, bph) | |
| 206 | + __field(u32, size) | |
| 207 | + __field(u32, ctrl) | |
| 189 | 208 | ), |
| 190 | 209 | TP_fast_assign( |
| 191 | − __entry->dep = dep; | |
| 210 | + snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name); | |
| 192 | 211 | __entry->trb = trb; |
| 212 | + __entry->bpl = trb->bpl; | |
| 213 | + __entry->bph = trb->bph; | |
| 214 | + __entry->size = trb->size; | |
| 215 | + __entry->ctrl = trb->ctrl; | |
| 193 | 216 | ), |
| 194 | 217 | TP_printk("%s: trb %p bph %08x bpl %08x size %08x ctrl %08x\n", |
| 195 | − __entry->dep->name, __entry->trb, __entry->trb->bph, | |
| 196 | − __entry->trb->bpl, __entry->trb->size, __entry->trb->ctrl | |
| 218 | + __get_str(name), __entry->trb, __entry->bph, __entry->bpl, | |
| 219 | + __entry->size, __entry->ctrl | |
| 197 | 220 | ) |
| 198 | 221 | ); |
| 199 | 222 | |
| @@ -560,7 +560,7 @@ static int bos_desc(struct usb_composite_dev *cdev) · 559 unmodified lines | ||
| 560 | 560 | usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE; |
| 561 | 561 | usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY; |
| 562 | 562 | usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT; |
| 563 | − usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT); | |
| 563 | + usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT | USB_BESL_SUPPORT); | |
| 564 | 564 | |
| 565 | 565 | /* |
| 566 | 566 | * 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) · 432 unmodified lines | ||
| 433 | 433 | dev_vdbg(&cdev->gadget->dev, |
| 434 | 434 | "reset acm control interface %d\n", intf); |
| 435 | 435 | usb_ep_disable(acm->notify); |
| 436 | − } else { | |
| 437 | − dev_vdbg(&cdev->gadget->dev, | |
| 438 | − "init acm ctrl interface %d\n", intf); | |
| 436 | + } | |
| 437 | + | |
| 438 | + if (!acm->notify->desc) | |
| 439 | 439 | if (config_ep_by_speed(cdev->gadget, f, acm->notify)) |
| 440 | 440 | return -EINVAL; |
| 441 | − } | |
| 441 | + | |
| 442 | 442 | usb_ep_enable(acm->notify); |
| 443 | 443 | acm->notify->driver_data = acm; |
| 444 | 444 | |
| @@ -325,7 +325,6 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f) · 324 unmodified lines | ||
| 325 | 325 | return 0; |
| 326 | 326 | |
| 327 | 327 | fail: |
| 328 | − usb_free_all_descriptors(f); | |
| 329 | 328 | if (eem->port.out_ep) |
| 330 | 329 | eem->port.out_ep->driver_data = NULL; |
| 331 | 330 | if (eem->port.in_ep) |
| @@ -647,15 +647,26 @@ static void ffs_user_copy_worker(struct work_struct *work) · 646 unmodified lines | ||
| 647 | 647 | if (io_data->read && ret > 0) { |
| 648 | 648 | int i; |
| 649 | 649 | size_t pos = 0; |
| 650 | + | |
| 651 | + /* | |
| 652 | + * Since req->length may be bigger than io_data->len (after | |
| 653 | + * being rounded up to maxpacketsize), we may end up with more | |
| 654 | + * data then user space has space for. | |
| 655 | + */ | |
| 656 | + ret = min_t(int, ret, io_data->len); | |
| 657 | + | |
| 650 | 658 | use_mm(io_data->mm); |
| 651 | 659 | for (i = 0; i < io_data->nr_segs; i++) { |
| 660 | + size_t len = min_t(size_t, ret - pos, | |
| 661 | + io_data->iovec[i].iov_len); | |
| 662 | + if (!len) | |
| 663 | + break; | |
| 652 | 664 | if (unlikely(copy_to_user(io_data->iovec[i].iov_base, |
| 653 | − &io_data->buf[pos], | |
| 654 | − io_data->iovec[i].iov_len))) { | |
| 665 | + &io_data->buf[pos], len))) { | |
| 655 | 666 | ret = -EFAULT; |
| 656 | 667 | break; |
| 657 | 668 | } |
| 658 | − pos += io_data->iovec[i].iov_len; | |
| 669 | + pos += len; | |
| 659 | 670 | } |
| 660 | 671 | unuse_mm(io_data->mm); |
| 661 | 672 | } |
| @@ -687,7 +698,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) · 25 unmodified lines | ||
| 687 | 698 | struct ffs_epfile *epfile = file->private_data; |
| 688 | 699 | struct ffs_ep *ep; |
| 689 | 700 | char *data = NULL; |
| 690 | − ssize_t ret, data_len; | |
| 701 | + ssize_t ret, data_len = -EINVAL; | |
| 691 | 702 | int halt; |
| 692 | 703 | |
| 693 | 704 | /* Are we still active? */ |
| @@ -787,13 +798,30 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) · 93 unmodified lines | ||
| 787 | 798 | /* Fire the request */ |
| 788 | 799 | struct usb_request *req; |
| 789 | 800 | |
| 801 | + /* | |
| 802 | + * Sanity Check: even though data_len can't be used | |
| 803 | + * uninitialized at the time I write this comment, some | |
| 804 | + * compilers complain about this situation. | |
| 805 | + * In order to keep the code clean from warnings, data_len is | |
| 806 | + * being initialized to -EINVAL during its declaration, which | |
| 807 | + * means we can't rely on compiler anymore to warn no future | |
| 808 | + * changes won't result in data_len being used uninitialized. | |
| 809 | + * For such reason, we're adding this redundant sanity check | |
| 810 | + * here. | |
| 811 | + */ | |
| 812 | + if (unlikely(data_len == -EINVAL)) { | |
| 813 | + WARN(1, "%s: data_len == -EINVAL\n", __func__); | |
| 814 | + ret = -EINVAL; | |
| 815 | + goto error_lock; | |
| 816 | + } | |
| 817 | + | |
| 790 | 818 | if (io_data->aio) { |
| 791 | 819 | req = usb_ep_alloc_request(ep->ep, GFP_KERNEL); |
| 792 | 820 | if (unlikely(!req)) |
| 793 | 821 | goto error_lock; |
| 794 | 822 | |
| 795 | 823 | req->buf = data; |
| 796 | − req->length = io_data->len; | |
| 824 | + req->length = data_len; | |
| 797 | 825 | |
| 798 | 826 | io_data->buf = data; |
| 799 | 827 | io_data->ep = ep->ep; |
| @@ -815,7 +843,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) · 15 unmodified lines | ||
| 815 | 843 | |
| 816 | 844 | req = ep->req; |
| 817 | 845 | req->buf = data; |
| 818 | − req->length = io_data->len; | |
| 846 | + req->length = data_len; | |
| 819 | 847 | |
| 820 | 848 | req->context = &done; |
| 821 | 849 | req->complete = ffs_epfile_io_complete; |
| @@ -2663,8 +2691,6 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, · 1841 unmodified lines | ||
| 2663 | 2691 | func->conf = c; |
| 2664 | 2692 | func->gadget = c->cdev->gadget; |
| 2665 | 2693 | |
| 2666 | − ffs_data_get(func->ffs); | |
| 2667 | − | |
| 2668 | 2694 | /* |
| 2669 | 2695 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() |
| 2670 | 2696 | * 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) · 620 unmodified lines | ||
| 621 | 621 | dev = MKDEV(major, hidg->minor); |
| 622 | 622 | status = cdev_add(&hidg->cdev, dev, 1); |
| 623 | 623 | if (status) |
| 624 | − goto fail; | |
| 624 | + goto fail_free_descs; | |
| 625 | 625 | |
| 626 | 626 | device_create(hidg_class, NULL, dev, NULL, "%s%d", "hidg", hidg->minor); |
| 627 | 627 | |
| 628 | 628 | return 0; |
| 629 | 629 | |
| 630 | +fail_free_descs: | |
| 631 | + usb_free_all_descriptors(f); | |
| 630 | 632 | fail: |
| 631 | 633 | ERROR(f->config->cdev, "hidg_bind FAILED\n"); |
| 632 | 634 | if (hidg->req != NULL) { |
| @@ -635,7 +637,6 @@ fail: · 2 unmodified lines | ||
| 635 | 637 | usb_ep_free_request(hidg->in_ep, hidg->req); |
| 636 | 638 | } |
| 637 | 639 | |
| 638 | − usb_free_all_descriptors(f); | |
| 639 | 640 | return status; |
| 640 | 641 | } |
| 641 | 642 | |
| @@ -253,22 +253,13 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req) · 252 unmodified lines | ||
| 253 | 253 | |
| 254 | 254 | case 0: /* normal completion? */ |
| 255 | 255 | if (ep == loop->out_ep) { |
| 256 | − /* loop this OUT packet back IN to the host */ | |
| 257 | 256 | req->zero = (req->actual < req->length); |
| 258 | 257 | req->length = req->actual; |
| 259 | − status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC); | |
| 260 | − if (status == 0) | |
| 261 | − return; | |
| 262 | − | |
| 263 | − /* "should never get here" */ | |
| 264 | − ERROR(cdev, "can't loop %s to %s: %d\n", | |
| 265 | − ep->name, loop->in_ep->name, | |
| 266 | − status); | |
| 267 | 258 | } |
| 268 | 259 | |
| 269 | 260 | /* queue the buffer for some later OUT packet */ |
| 270 | 261 | req->length = buflen; |
| 271 | − status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC); | |
| 262 | + status = usb_ep_queue(ep, req, GFP_ATOMIC); | |
| 272 | 263 | if (status == 0) |
| 273 | 264 | return; |
| 274 | 265 | |
| @@ -308,60 +299,66 @@ static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len) · 33 unmodified lines | ||
| 308 | 299 | return alloc_ep_req(ep, len, buflen); |
| 309 | 300 | } |
| 310 | 301 | |
| 311 | −static int | |
| 312 | −enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop) | |
| 302 | +static int enable_endpoint(struct usb_composite_dev *cdev, struct f_loopback *loop, | |
| 303 | + struct usb_ep *ep) | |
| 313 | 304 | { |
| 314 | − int result = 0; | |
| 315 | − struct usb_ep *ep; | |
| 316 | 305 | struct usb_request *req; |
| 317 | 306 | unsigned i; |
| 307 | + int result; | |
| 318 | 308 | |
| 319 | − /* one endpoint writes data back IN to the host */ | |
| 320 | − ep = loop->in_ep; | |
| 309 | + /* | |
| 310 | + * one endpoint writes data back IN to the host while another endpoint | |
| 311 | + * just reads OUT packets | |
| 312 | + */ | |
| 321 | 313 | result = config_ep_by_speed(cdev->gadget, &(loop->function), ep); |
| 322 | 314 | if (result) |
| 323 | − return result; | |
| 315 | + goto fail0; | |
| 324 | 316 | result = usb_ep_enable(ep); |
| 325 | 317 | if (result < 0) |
| 326 | − return result; | |
| 327 | − ep->driver_data = loop; | |
| 328 | − | |
| 329 | − /* one endpoint just reads OUT packets */ | |
| 330 | − ep = loop->out_ep; | |
| 331 | − result = config_ep_by_speed(cdev->gadget, &(loop->function), ep); | |
| 332 | − if (result) | |
| 333 | 318 | goto fail0; |
| 334 | − | |
| 335 | − result = usb_ep_enable(ep); | |
| 336 | − if (result < 0) { | |
| 337 | −fail0: | |
| 338 | − ep = loop->in_ep; | |
| 339 | − usb_ep_disable(ep); | |
| 340 | − ep->driver_data = NULL; | |
| 341 | − return result; | |
| 342 | − } | |
| 343 | 319 | ep->driver_data = loop; |
| 344 | 320 | |
| 345 | − /* allocate a bunch of read buffers and queue them all at once. | |
| 321 | + /* | |
| 322 | + * allocate a bunch of read buffers and queue them all at once. | |
| 346 | 323 | * we buffer at most 'qlen' transfers; fewer if any need more |
| 347 | 324 | * than 'buflen' bytes each. |
| 348 | 325 | */ |
| 349 | 326 | for (i = 0; i < qlen && result == 0; i++) { |
| 350 | 327 | req = lb_alloc_ep_req(ep, 0); |
| 351 | − if (req) { | |
| 352 | − req->complete = loopback_complete; | |
| 353 | − result = usb_ep_queue(ep, req, GFP_ATOMIC); | |
| 354 | − if (result) | |
| 355 | − ERROR(cdev, "%s queue req --> %d\n", | |
| 356 | − ep->name, result); | |
| 357 | − } else { | |
| 358 | − usb_ep_disable(ep); | |
| 359 | − ep->driver_data = NULL; | |
| 360 | − result = -ENOMEM; | |
| 361 | − goto fail0; | |
| 328 | + if (!req) | |
| 329 | + goto fail1; | |
| 330 | + | |
| 331 | + req->complete = loopback_complete; | |
| 332 | + result = usb_ep_queue(ep, req, GFP_ATOMIC); | |
| 333 | + if (result) { | |
| 334 | + ERROR(cdev, "%s queue req --> %d\n", | |
| 335 | + ep->name, result); | |
| 336 | + goto fail1; | |
| 362 | 337 | } |
| 363 | 338 | } |
| 364 | 339 | |
| 340 | + return 0; | |
| 341 | + | |
| 342 | +fail1: | |
| 343 | + usb_ep_disable(ep); | |
| 344 | + | |
| 345 | +fail0: | |
| 346 | + return result; | |
| 347 | +} | |
| 348 | + | |
| 349 | +static int | |
| 350 | +enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop) | |
| 351 | +{ | |
| 352 | + int result = 0; | |
| 353 | + | |
| 354 | + result = enable_endpoint(cdev, loop, loop->in_ep); | |
| 355 | + if (result) | |
| 356 | + return result; | |
| 357 | + | |
| 358 | + result = enable_endpoint(cdev, loop, loop->out_ep); | |
| 359 | + if (result) | |
| 360 | + return result; | |
| 361 | + | |
| 365 | 362 | DBG(cdev, "%s enabled\n", loop->function.name); |
| 366 | 363 | return result; |
| 367 | 364 | } |
| @@ -1461,7 +1461,6 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) · 1460 unmodified lines | ||
| 1461 | 1461 | return 0; |
| 1462 | 1462 | |
| 1463 | 1463 | fail: |
| 1464 | − usb_free_all_descriptors(f); | |
| 1465 | 1464 | if (ncm->notify_req) { |
| 1466 | 1465 | kfree(ncm->notify_req->buf); |
| 1467 | 1466 | usb_ep_free_request(ncm->notify, ncm->notify_req); |
| @@ -35,6 +35,7 @@ struct f_obex { · 34 unmodified lines | ||
| 35 | 35 | struct gserial port; |
| 36 | 36 | u8 ctrl_id; |
| 37 | 37 | u8 data_id; |
| 38 | + u8 cur_alt; | |
| 38 | 39 | u8 port_num; |
| 39 | 40 | u8 can_activate; |
| 40 | 41 | }; |
| @@ -235,6 +236,8 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt) · 194 unmodified lines | ||
| 235 | 236 | } else |
| 236 | 237 | goto fail; |
| 237 | 238 | |
| 239 | + obex->cur_alt = alt; | |
| 240 | + | |
| 238 | 241 | return 0; |
| 239 | 242 | |
| 240 | 243 | fail: |
| @@ -245,10 +248,7 @@ static int obex_get_alt(struct usb_function *f, unsigned intf) · 4 unmodified lines | ||
| 245 | 248 | { |
| 246 | 249 | struct f_obex *obex = func_to_obex(f); |
| 247 | 250 | |
| 248 | − if (intf == obex->ctrl_id) | |
| 249 | − return 0; | |
| 250 | − | |
| 251 | − return obex->port.in->driver_data ? 1 : 0; | |
| 251 | + return obex->cur_alt; | |
| 252 | 252 | } |
| 253 | 253 | |
| 254 | 254 | static void obex_disable(struct usb_function *f) |
| @@ -397,7 +397,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f) · 142 unmodified lines | ||
| 397 | 397 | return 0; |
| 398 | 398 | |
| 399 | 399 | fail: |
| 400 | − usb_free_all_descriptors(f); | |
| 401 | 400 | /* we might as well release our claims on endpoints */ |
| 402 | 401 | if (obex->port.out) |
| 403 | 402 | obex->port.out->driver_data = NULL; |
| @@ -570,8 +570,8 @@ static int pn_bind(struct usb_configuration *c, struct usb_function *f) · 569 unmodified lines | ||
| 570 | 570 | err_req: |
| 571 | 571 | for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++) |
| 572 | 572 | usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); |
| 573 | −err: | |
| 574 | 573 | usb_free_all_descriptors(f); |
| 574 | +err: | |
| 575 | 575 | if (fp->out_ep) |
| 576 | 576 | fp->out_ep->driver_data = NULL; |
| 577 | 577 | if (fp->in_ep) |
| @@ -802,8 +802,10 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) · 801 unmodified lines | ||
| 802 | 802 | |
| 803 | 803 | if (rndis->manufacturer && rndis->vendorID && |
| 804 | 804 | rndis_set_param_vendor(rndis->config, rndis->vendorID, |
| 805 | − rndis->manufacturer)) | |
| 806 | − goto fail; | |
| 805 | + rndis->manufacturer)) { | |
| 806 | + status = -EINVAL; | |
| 807 | + goto fail_free_descs; | |
| 808 | + } | |
| 807 | 809 | |
| 808 | 810 | /* NOTE: all that is done without knowing or caring about |
| 809 | 811 | * the network link ... which is unavailable to this code |
| @@ -817,10 +819,11 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) · 7 unmodified lines | ||
| 817 | 819 | rndis->notify->name); |
| 818 | 820 | return 0; |
| 819 | 821 | |
| 822 | +fail_free_descs: | |
| 823 | + usb_free_all_descriptors(f); | |
| 820 | 824 | fail: |
| 821 | 825 | kfree(f->os_desc_table); |
| 822 | 826 | f->os_desc_n = 0; |
| 823 | − usb_free_all_descriptors(f); | |
| 824 | 827 | |
| 825 | 828 | if (rndis->notify_req) { |
| 826 | 829 | kfree(rndis->notify_req->buf); |
| @@ -380,7 +380,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) · 379 unmodified lines | ||
| 380 | 380 | return 0; |
| 381 | 381 | |
| 382 | 382 | fail: |
| 383 | − usb_free_all_descriptors(f); | |
| 384 | 383 | /* we might as well release our claims on endpoints */ |
| 385 | 384 | if (geth->port.out_ep) |
| 386 | 385 | geth->port.out_ep->driver_data = NULL; |
| @@ -512,6 +512,11 @@ static int snd_uac2_remove(struct platform_device *pdev) · 511 unmodified lines | ||
| 512 | 512 | return 0; |
| 513 | 513 | } |
| 514 | 514 | |
| 515 | +static void snd_uac2_release(struct device *dev) | |
| 516 | +{ | |
| 517 | + dev_dbg(dev, "releasing '%s'\n", dev_name(dev)); | |
| 518 | +} | |
| 519 | + | |
| 515 | 520 | static int alsa_uac2_init(struct audio_dev *agdev) |
| 516 | 521 | { |
| 517 | 522 | struct snd_uac2_chip *uac2 = &agdev->uac2; |
| @@ -523,6 +528,7 @@ static int alsa_uac2_init(struct audio_dev *agdev) · 5 unmodified lines | ||
| 523 | 528 | |
| 524 | 529 | uac2->pdev.id = 0; |
| 525 | 530 | uac2->pdev.name = uac2_name; |
| 531 | + uac2->pdev.dev.release = snd_uac2_release; | |
| 526 | 532 | |
| 527 | 533 | /* Register snd_uac2 driver */ |
| 528 | 534 | err = platform_driver_register(&uac2->pdrv); |
| @@ -772,6 +778,7 @@ struct usb_endpoint_descriptor fs_epout_desc = { · 243 unmodified lines | ||
| 772 | 778 | |
| 773 | 779 | .bEndpointAddress = USB_DIR_OUT, |
| 774 | 780 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, |
| 781 | + .wMaxPacketSize = cpu_to_le16(1023), | |
| 775 | 782 | .bInterval = 1, |
| 776 | 783 | }; |
| 777 | 784 | |
| @@ -780,6 +787,7 @@ struct usb_endpoint_descriptor hs_epout_desc = { · 2 unmodified lines | ||
| 780 | 787 | .bDescriptorType = USB_DT_ENDPOINT, |
| 781 | 788 | |
| 782 | 789 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, |
| 790 | + .wMaxPacketSize = cpu_to_le16(1024), | |
| 783 | 791 | .bInterval = 4, |
| 784 | 792 | }; |
| 785 | 793 | |
| @@ -847,6 +855,7 @@ struct usb_endpoint_descriptor fs_epin_desc = { · 61 unmodified lines | ||
| 847 | 855 | |
| 848 | 856 | .bEndpointAddress = USB_DIR_IN, |
| 849 | 857 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, |
| 858 | + .wMaxPacketSize = cpu_to_le16(1023), | |
| 850 | 859 | .bInterval = 1, |
| 851 | 860 | }; |
| 852 | 861 | |
| @@ -855,6 +864,7 @@ struct usb_endpoint_descriptor hs_epin_desc = { · 2 unmodified lines | ||
| 855 | 864 | .bDescriptorType = USB_DT_ENDPOINT, |
| 856 | 865 | |
| 857 | 866 | .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, |
| 867 | + .wMaxPacketSize = cpu_to_le16(1024), | |
| 858 | 868 | .bInterval = 4, |
| 859 | 869 | }; |
| 860 | 870 | |
| @@ -947,6 +957,9 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) · 86 unmodified lines | ||
| 947 | 957 | struct snd_uac2_chip *uac2 = prm->uac2; |
| 948 | 958 | int i; |
| 949 | 959 | |
| 960 | + if (!prm->ep_enabled) | |
| 961 | + return; | |
| 962 | + | |
| 950 | 963 | prm->ep_enabled = false; |
| 951 | 964 | |
| 952 | 965 | for (i = 0; i < USB_XFERS; i++) { |
| @@ -1071,7 +1084,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) · 118 unmodified lines | ||
| 1071 | 1084 | prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); |
| 1072 | 1085 | if (!prm->rbuf) { |
| 1073 | 1086 | prm->max_psize = 0; |
| 1074 | − goto err; | |
| 1087 | + goto err_free_descs; | |
| 1075 | 1088 | } |
| 1076 | 1089 | |
| 1077 | 1090 | prm = &agdev->uac2.p_prm; |
| @@ -1079,17 +1092,19 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) · 1 unmodified line | ||
| 1079 | 1092 | prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); |
| 1080 | 1093 | if (!prm->rbuf) { |
| 1081 | 1094 | prm->max_psize = 0; |
| 1082 | − goto err; | |
| 1095 | + goto err_free_descs; | |
| 1083 | 1096 | } |
| 1084 | 1097 | |
| 1085 | 1098 | ret = alsa_uac2_init(agdev); |
| 1086 | 1099 | if (ret) |
| 1087 | − goto err; | |
| 1100 | + goto err_free_descs; | |
| 1088 | 1101 | return 0; |
| 1102 | + | |
| 1103 | +err_free_descs: | |
| 1104 | + usb_free_all_descriptors(fn); | |
| 1089 | 1105 | err: |
| 1090 | 1106 | kfree(agdev->uac2.p_prm.rbuf); |
| 1091 | 1107 | kfree(agdev->uac2.c_prm.rbuf); |
| 1092 | − usb_free_all_descriptors(fn); | |
| 1093 | 1108 | if (agdev->in_ep) |
| 1094 | 1109 | agdev->in_ep->driver_data = NULL; |
| 1095 | 1110 | if (agdev->out_ep) |
| @@ -279,27 +279,41 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface) · 278 unmodified lines | ||
| 279 | 279 | else if (interface != uvc->streaming_intf) |
| 280 | 280 | return -EINVAL; |
| 281 | 281 | else |
| 282 | − return uvc->state == UVC_STATE_STREAMING ? 1 : 0; | |
| 282 | + return uvc->video.ep->driver_data ? 1 : 0; | |
| 283 | 283 | } |
| 284 | 284 | |
| 285 | 285 | static int |
| 286 | 286 | uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) |
| 287 | 287 | { |
| 288 | 288 | struct uvc_device *uvc = to_uvc(f); |
| 289 | + struct usb_composite_dev *cdev = f->config->cdev; | |
| 289 | 290 | struct v4l2_event v4l2_event; |
| 290 | 291 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; |
| 291 | 292 | int ret; |
| 292 | 293 | |
| 293 | − INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt); | |
| 294 | + INFO(cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt); | |
| 294 | 295 | |
| 295 | 296 | if (interface == uvc->control_intf) { |
| 296 | 297 | if (alt) |
| 297 | 298 | return -EINVAL; |
| 298 | 299 | |
| 300 | + if (uvc->control_ep->driver_data) { | |
| 301 | + INFO(cdev, "reset UVC Control\n"); | |
| 302 | + usb_ep_disable(uvc->control_ep); | |
| 303 | + uvc->control_ep->driver_data = NULL; | |
| 304 | + } | |
| 305 | + | |
| 306 | + if (!uvc->control_ep->desc) | |
| 307 | + if (config_ep_by_speed(cdev->gadget, f, uvc->control_ep)) | |
| 308 | + return -EINVAL; | |
| 309 | + | |
| 310 | + usb_ep_enable(uvc->control_ep); | |
| 311 | + uvc->control_ep->driver_data = uvc; | |
| 312 | + | |
| 299 | 313 | if (uvc->state == UVC_STATE_DISCONNECTED) { |
| 300 | 314 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
| 301 | 315 | v4l2_event.type = UVC_EVENT_CONNECT; |
| 302 | − uvc_event->speed = f->config->cdev->gadget->speed; | |
| 316 | + uvc_event->speed = cdev->gadget->speed; | |
| 303 | 317 | v4l2_event_queue(uvc->vdev, &v4l2_event); |
| 304 | 318 | |
| 305 | 319 | uvc->state = UVC_STATE_CONNECTED; |
| @@ -321,8 +335,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) · 15 unmodified lines | ||
| 321 | 335 | if (uvc->state != UVC_STATE_STREAMING) |
| 322 | 336 | return 0; |
| 323 | 337 | |
| 324 | − if (uvc->video.ep) | |
| 338 | + if (uvc->video.ep) { | |
| 325 | 339 | usb_ep_disable(uvc->video.ep); |
| 340 | + uvc->video.ep->driver_data = NULL; | |
| 341 | + } | |
| 326 | 342 | |
| 327 | 343 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
| 328 | 344 | v4l2_event.type = UVC_EVENT_STREAMOFF; |
| @@ -335,14 +351,22 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) · 6 unmodified lines | ||
| 335 | 351 | if (uvc->state != UVC_STATE_CONNECTED) |
| 336 | 352 | return 0; |
| 337 | 353 | |
| 338 | − if (uvc->video.ep) { | |
| 339 | − ret = config_ep_by_speed(f->config->cdev->gadget, | |
| 340 | − &(uvc->func), uvc->video.ep); | |
| 341 | − if (ret) | |
| 342 | − return ret; | |
| 343 | − usb_ep_enable(uvc->video.ep); | |
| 354 | + if (!uvc->video.ep) | |
| 355 | + return -EINVAL; | |
| 356 | + | |
| 357 | + if (uvc->video.ep->driver_data) { | |
| 358 | + INFO(cdev, "reset UVC\n"); | |
| 359 | + usb_ep_disable(uvc->video.ep); | |
| 360 | + uvc->video.ep->driver_data = NULL; | |
| 344 | 361 | } |
| 345 | 362 | |
| 363 | + ret = config_ep_by_speed(f->config->cdev->gadget, | |
| 364 | + &(uvc->func), uvc->video.ep); | |
| 365 | + if (ret) | |
| 366 | + return ret; | |
| 367 | + usb_ep_enable(uvc->video.ep); | |
| 368 | + uvc->video.ep->driver_data = uvc; | |
| 369 | + | |
| 346 | 370 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
| 347 | 371 | v4l2_event.type = UVC_EVENT_STREAMON; |
| 348 | 372 | v4l2_event_queue(uvc->vdev, &v4l2_event); |
| @@ -366,6 +390,16 @@ uvc_function_disable(struct usb_function *f) · 17 unmodified lines | ||
| 366 | 390 | v4l2_event_queue(uvc->vdev, &v4l2_event); |
| 367 | 391 | |
| 368 | 392 | uvc->state = UVC_STATE_DISCONNECTED; |
| 393 | + | |
| 394 | + if (uvc->video.ep->driver_data) { | |
| 395 | + usb_ep_disable(uvc->video.ep); | |
| 396 | + uvc->video.ep->driver_data = NULL; | |
| 397 | + } | |
| 398 | + | |
| 399 | + if (uvc->control_ep->driver_data) { | |
| 400 | + usb_ep_disable(uvc->control_ep); | |
| 401 | + uvc->control_ep->driver_data = NULL; | |
| 402 | + } | |
| 369 | 403 | } |
| 370 | 404 | |
| 371 | 405 | /* -------------------------------------------------------------------------- |
| @@ -352,7 +352,8 @@ int uvcg_video_enable(struct uvc_video *video, int enable) · 351 unmodified lines | ||
| 352 | 352 | |
| 353 | 353 | if (!enable) { |
| 354 | 354 | for (i = 0; i < UVC_NUM_REQUESTS; ++i) |
| 355 | − usb_ep_dequeue(video->ep, video->req[i]); | |
| 355 | + if (video->req[i]) | |
| 356 | + usb_ep_dequeue(video->ep, video->req[i]); | |
| 356 | 357 | |
| 357 | 358 | uvc_video_free_requests(video); |
| 358 | 359 | uvcg_queue_enable(&video->queue, 0); |
| @@ -357,6 +357,7 @@ config USB_EG20T · 356 unmodified lines | ||
| 357 | 357 | |
| 358 | 358 | config USB_GADGET_XILINX |
| 359 | 359 | tristate "Xilinx USB Driver" |
| 360 | + depends on HAS_DMA | |
| 360 | 361 | depends on OF || COMPILE_TEST |
| 361 | 362 | help |
| 362 | 363 | USB peripheral controller driver for Xilinx USB2 device. |
| @@ -507,6 +507,11 @@ static ssize_t usb_udc_softconn_store(struct device *dev, · 506 unmodified lines | ||
| 507 | 507 | { |
| 508 | 508 | struct usb_udc *udc = container_of(dev, struct usb_udc, dev); |
| 509 | 509 | |
| 510 | + if (!udc->driver) { | |
| 511 | + dev_err(dev, "soft-connect without a gadget driver\n"); | |
| 512 | + return -EOPNOTSUPP; | |
| 513 | + } | |
| 514 | + | |
| 510 | 515 | if (sysfs_streq(buf, "connect")) { |
| 511 | 516 | usb_gadget_udc_start(udc->gadget, udc->driver); |
| 512 | 517 | usb_gadget_connect(udc->gadget); |
| @@ -209,7 +209,8 @@ static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer) · 208 unmodified lines | ||
| 209 | 209 | } |
| 210 | 210 | } |
| 211 | 211 | |
| 212 | − if (!list_empty(&controller->early_tx_list)) { | |
| 212 | + if (!list_empty(&controller->early_tx_list) && | |
| 213 | + !hrtimer_is_queued(&controller->early_tx)) { | |
| 213 | 214 | ret = HRTIMER_RESTART; |
| 214 | 215 | hrtimer_forward_now(&controller->early_tx, |
| 215 | 216 | ktime_set(0, 20 * NSEC_PER_USEC)); |
| @@ -868,9 +868,15 @@ static int dsps_suspend(struct device *dev) · 867 unmodified lines | ||
| 868 | 868 | struct dsps_glue *glue = dev_get_drvdata(dev); |
| 869 | 869 | const struct dsps_musb_wrapper *wrp = glue->wrp; |
| 870 | 870 | struct musb *musb = platform_get_drvdata(glue->musb); |
| 871 | − void __iomem *mbase = musb->ctrl_base; | |
| 871 | + void __iomem *mbase; | |
| 872 | 872 | |
| 873 | 873 | del_timer_sync(&glue->timer); |
| 874 | + | |
| 875 | + if (!musb) | |
| 876 | + /* This can happen if the musb device is in -EPROBE_DEFER */ | |
| 877 | + return 0; | |
| 878 | + | |
| 879 | + mbase = musb->ctrl_base; | |
| 874 | 880 | glue->context.control = dsps_readl(mbase, wrp->control); |
| 875 | 881 | glue->context.epintr = dsps_readl(mbase, wrp->epintr_set); |
| 876 | 882 | glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set); |
| @@ -887,8 +893,12 @@ static int dsps_resume(struct device *dev) · 10 unmodified lines | ||
| 887 | 893 | struct dsps_glue *glue = dev_get_drvdata(dev); |
| 888 | 894 | const struct dsps_musb_wrapper *wrp = glue->wrp; |
| 889 | 895 | struct musb *musb = platform_get_drvdata(glue->musb); |
| 890 | − void __iomem *mbase = musb->ctrl_base; | |
| 896 | + void __iomem *mbase; | |
| 897 | + | |
| 898 | + if (!musb) | |
| 899 | + return 0; | |
| 891 | 900 | |
| 901 | + mbase = musb->ctrl_base; | |
| 892 | 902 | dsps_writel(mbase, wrp->control, glue->context.control); |
| 893 | 903 | dsps_writel(mbase, wrp->epintr_set, glue->context.epintr); |
| 894 | 904 | dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr); |
| @@ -896,7 +906,9 @@ static int dsps_resume(struct device *dev) · 1 unmodified line | ||
| 896 | 906 | dsps_writel(mbase, wrp->mode, glue->context.mode); |
| 897 | 907 | dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode); |
| 898 | 908 | dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode); |
| 899 | − setup_timer(&glue->timer, otg_timer, (unsigned long) musb); | |
| 909 | + if (musb->xceiv->state == OTG_STATE_B_IDLE && | |
| 910 | + musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) | |
| 911 | + mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); | |
| 900 | 912 | |
| 901 | 913 | return 0; |
| 902 | 914 | } |
| @@ -155,6 +155,7 @@ static const struct usb_device_id id_table[] = { · 154 unmodified lines | ||
| 155 | 155 | { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ |
| 156 | 156 | { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ |
| 157 | 157 | { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ |
| 158 | + { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */ | |
| 158 | 159 | { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ |
| 159 | 160 | { USB_DEVICE(0x1D6F, 0x0010) }, /* Seluxit ApS RF Dongle */ |
| 160 | 161 | { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */ |
| @@ -140,6 +140,7 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = { · 139 unmodified lines | ||
| 140 | 140 | * /sys/bus/usb-serial/drivers/ftdi_sio/new_id and send a patch or report. |
| 141 | 141 | */ |
| 142 | 142 | static const struct usb_device_id id_table_combined[] = { |
| 143 | + { USB_DEVICE(FTDI_VID, FTDI_BRICK_PID) }, | |
| 143 | 144 | { USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) }, |
| 144 | 145 | { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) }, |
| 145 | 146 | { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) }, |
| @@ -661,6 +662,8 @@ static const struct usb_device_id id_table_combined[] = { · 515 unmodified lines | ||
| 661 | 662 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, |
| 662 | 663 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, |
| 663 | 664 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, |
| 665 | + { USB_DEVICE(XSENS_VID, XSENS_AWINDA_DONGLE_PID) }, | |
| 666 | + { USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) }, | |
| 664 | 667 | { USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) }, |
| 665 | 668 | { USB_DEVICE(XSENS_VID, XSENS_MTW_PID) }, |
| 666 | 669 | { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) }, |
| @@ -30,6 +30,12 @@ · 29 unmodified lines | ||
| 30 | 30 | |
| 31 | 31 | /*** third-party PIDs (using FTDI_VID) ***/ |
| 32 | 32 | |
| 33 | +/* | |
| 34 | + * Certain versions of the official Windows FTDI driver reprogrammed | |
| 35 | + * counterfeit FTDI devices to PID 0. Support these devices anyway. | |
| 36 | + */ | |
| 37 | +#define FTDI_BRICK_PID 0x0000 | |
| 38 | + | |
| 33 | 39 | #define FTDI_LUMEL_PD12_PID 0x6002 |
| 34 | 40 | |
| 35 | 41 | /* |
| @@ -143,8 +149,12 @@ · 107 unmodified lines | ||
| 143 | 149 | * Xsens Technologies BV products (http://www.xsens.com). |
| 144 | 150 | */ |
| 145 | 151 | #define XSENS_VID 0x2639 |
| 146 | −#define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */ | |
| 152 | +#define XSENS_AWINDA_STATION_PID 0x0101 | |
| 153 | +#define XSENS_AWINDA_DONGLE_PID 0x0102 | |
| 147 | 154 | #define XSENS_MTW_PID 0x0200 /* Xsens MTw */ |
| 155 | +#define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */ | |
| 156 | + | |
| 157 | +/* Xsens devices using FTDI VID */ | |
| 148 | 158 | #define XSENS_CONVERTER_0_PID 0xD388 /* Xsens USB converter */ |
| 149 | 159 | #define XSENS_CONVERTER_1_PID 0xD389 /* Xsens Wireless Receiver */ |
| 150 | 160 | #define XSENS_CONVERTER_2_PID 0xD38A |
| @@ -414,8 +414,6 @@ static int kobil_tiocmset(struct tty_struct *tty, · 413 unmodified lines | ||
| 414 | 414 | int result; |
| 415 | 415 | int dtr = 0; |
| 416 | 416 | int rts = 0; |
| 417 | − unsigned char *transfer_buffer; | |
| 418 | − int transfer_buffer_length = 8; | |
| 419 | 417 | |
| 420 | 418 | /* FIXME: locking ? */ |
| 421 | 419 | priv = usb_get_serial_port_data(port); |
| @@ -425,11 +423,6 @@ static int kobil_tiocmset(struct tty_struct *tty, · 3 unmodified lines | ||
| 425 | 423 | return -EINVAL; |
| 426 | 424 | } |
| 427 | 425 | |
| 428 | − /* allocate memory for transfer buffer */ | |
| 429 | − transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); | |
| 430 | − if (!transfer_buffer) | |
| 431 | − return -ENOMEM; | |
| 432 | − | |
| 433 | 426 | if (set & TIOCM_RTS) |
| 434 | 427 | rts = 1; |
| 435 | 428 | if (set & TIOCM_DTR) |
| @@ -469,7 +462,6 @@ static int kobil_tiocmset(struct tty_struct *tty, · 33 unmodified lines | ||
| 469 | 462 | KOBIL_TIMEOUT); |
| 470 | 463 | } |
| 471 | 464 | dev_dbg(dev, "%s - Send set_status_line URB returns: %i\n", __func__, result); |
| 472 | − kfree(transfer_buffer); | |
| 473 | 465 | return (result < 0) ? result : 0; |
| 474 | 466 | } |
| 475 | 467 | |
| @@ -530,8 +522,6 @@ static int kobil_ioctl(struct tty_struct *tty, · 54 unmodified lines | ||
| 530 | 522 | { |
| 531 | 523 | struct usb_serial_port *port = tty->driver_data; |
| 532 | 524 | struct kobil_private *priv = usb_get_serial_port_data(port); |
| 533 | − unsigned char *transfer_buffer; | |
| 534 | − int transfer_buffer_length = 8; | |
| 535 | 525 | int result; |
| 536 | 526 | |
| 537 | 527 | if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || |
| @@ -541,10 +531,6 @@ static int kobil_ioctl(struct tty_struct *tty, · 3 unmodified lines | ||
| 541 | 531 | |
| 542 | 532 | switch (cmd) { |
| 543 | 533 | case TCFLSH: |
| 544 | − transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL); | |
| 545 | − if (!transfer_buffer) | |
| 546 | − return -ENOBUFS; | |
| 547 | − | |
| 548 | 534 | result = usb_control_msg(port->serial->dev, |
| 549 | 535 | usb_sndctrlpipe(port->serial->dev, 0), |
| 550 | 536 | SUSBCRequest_Misc, |
| @@ -559,7 +545,6 @@ static int kobil_ioctl(struct tty_struct *tty, · 8 unmodified lines | ||
| 559 | 545 | dev_dbg(&port->dev, |
| 560 | 546 | "%s - Send reset_all_queues (FLUSH) URB returns: %i\n", |
| 561 | 547 | __func__, result); |
| 562 | − kfree(transfer_buffer); | |
| 563 | 548 | return (result < 0) ? -EIO: 0; |
| 564 | 549 | default: |
| 565 | 550 | return -ENOIOCTLCMD; |
| @@ -269,6 +269,7 @@ static void option_instat_callback(struct urb *urb); · 268 unmodified lines | ||
| 269 | 269 | #define TELIT_PRODUCT_DE910_DUAL 0x1010 |
| 270 | 270 | #define TELIT_PRODUCT_UE910_V2 0x1012 |
| 271 | 271 | #define TELIT_PRODUCT_LE920 0x1200 |
| 272 | +#define TELIT_PRODUCT_LE910 0x1201 | |
| 272 | 273 | |
| 273 | 274 | /* ZTE PRODUCTS */ |
| 274 | 275 | #define ZTE_VENDOR_ID 0x19d2 |
| @@ -362,6 +363,7 @@ static void option_instat_callback(struct urb *urb); · 87 unmodified lines | ||
| 362 | 363 | |
| 363 | 364 | /* Haier products */ |
| 364 | 365 | #define HAIER_VENDOR_ID 0x201e |
| 366 | +#define HAIER_PRODUCT_CE81B 0x10f8 | |
| 365 | 367 | #define HAIER_PRODUCT_CE100 0x2009 |
| 366 | 368 | |
| 367 | 369 | /* Cinterion (formerly Siemens) products */ |
| @@ -589,6 +591,11 @@ static const struct option_blacklist_info zte_1255_blacklist = { · 221 unmodified lines | ||
| 589 | 591 | .reserved = BIT(3) | BIT(4), |
| 590 | 592 | }; |
| 591 | 593 | |
| 594 | +static const struct option_blacklist_info telit_le910_blacklist = { | |
| 595 | + .sendsetup = BIT(0), | |
| 596 | + .reserved = BIT(1) | BIT(2), | |
| 597 | +}; | |
| 598 | + | |
| 592 | 599 | static const struct option_blacklist_info telit_le920_blacklist = { |
| 593 | 600 | .sendsetup = BIT(0), |
| 594 | 601 | .reserved = BIT(1) | BIT(5), |
| @@ -1138,6 +1145,8 @@ static const struct usb_device_id option_ids[] = { · 543 unmodified lines | ||
| 1138 | 1145 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, |
| 1139 | 1146 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, |
| 1140 | 1147 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) }, |
| 1148 | + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), | |
| 1149 | + .driver_info = (kernel_ulong_t)&telit_le910_blacklist }, | |
| 1141 | 1150 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), |
| 1142 | 1151 | .driver_info = (kernel_ulong_t)&telit_le920_blacklist }, |
| 1143 | 1152 | { 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[] = { · 477 unmodified lines | ||
| 1621 | 1630 | { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) }, |
| 1622 | 1631 | { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) }, |
| 1623 | 1632 | { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, |
| 1633 | + { USB_DEVICE_AND_INTERFACE_INFO(HAIER_VENDOR_ID, HAIER_PRODUCT_CE81B, 0xff, 0xff, 0xff) }, | |
| 1624 | 1634 | /* Pirelli */ |
| 1625 | 1635 | { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) }, |
| 1626 | 1636 | { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) }, |