提交 46552bf4 编写于 作者: L Linus Torvalds

Merge tag 'usb-4.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here is a number of different USB fixes for 4.11-rc2.

  Seems like there were a lot of unresolved issues that people have been
  finding for this subsystem, and a bunch of good security auditing
  happening as well from Johan Hovold. There's the usual batch of gadget
  driver fixes and xhci issues resolved as well.

 All of these have been in linux-next with no reported issues"

* tag 'usb-4.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (35 commits)
  usb: host: xhci-plat: Fix timeout on removal of hot pluggable xhci controllers
  usb: host: xhci-dbg: HCIVERSION should be a binary number
  usb: xhci: remove dummy extra_priv_size for size of xhci_hcd struct
  usb: xhci-mtk: check hcc_params after adding primary hcd
  USB: serial: digi_acceleport: fix OOB-event processing
  MAINTAINERS: usb251xb: remove reference inexistent file
  doc: dt-bindings: usb251xb: mark reg as required
  usb: usb251xb: dt: add unit suffix to oc-delay and power-on-time
  usb: usb251xb: remove max_{power,current}_{sp,bp} properties
  usb-storage: Add ignore-residue quirk for Initio INIC-3619
  USB: iowarrior: fix NULL-deref in write
  USB: iowarrior: fix NULL-deref at probe
  usb: phy: isp1301: Add OF device ID table
  usb: ohci-at91: Do not drop unhandled USB suspend control requests
  USB: serial: safe_serial: fix information leak in completion handler
  USB: serial: io_ti: fix information leak in completion handler
  USB: serial: omninet: drop open callback
  USB: serial: omninet: fix reference leaks at open
  USB: serial: io_ti: fix NULL-deref in interrupt callback
  usb: dwc3: gadget: make to increment req->remaining in all cases
  ...
...@@ -7,18 +7,18 @@ Required properties : ...@@ -7,18 +7,18 @@ Required properties :
- compatible : Should be "microchip,usb251xb" or one of the specific types: - compatible : Should be "microchip,usb251xb" or one of the specific types:
"microchip,usb2512b", "microchip,usb2512bi", "microchip,usb2513b", "microchip,usb2512b", "microchip,usb2512bi", "microchip,usb2513b",
"microchip,usb2513bi", "microchip,usb2514b", "microchip,usb2514bi" "microchip,usb2513bi", "microchip,usb2514b", "microchip,usb2514bi"
- hub-reset-gpios : Should specify the gpio for hub reset - reset-gpios : Should specify the gpio for hub reset
- reg : I2C address on the selected bus (default is <0x2C>)
Optional properties : Optional properties :
- reg : I2C address on the selected bus (default is <0x2C>)
- skip-config : Skip Hub configuration, but only send the USB-Attach command - skip-config : Skip Hub configuration, but only send the USB-Attach command
- vendor-id : USB Vendor ID of the hub (16 bit, default is 0x0424) - vendor-id : Set USB Vendor ID of the hub (16 bit, default is 0x0424)
- product-id : USB Product ID of the hub (16 bit, default depends on type) - product-id : Set USB Product ID of the hub (16 bit, default depends on type)
- device-id : USB Device ID of the hub (16 bit, default is 0x0bb3) - device-id : Set USB Device ID of the hub (16 bit, default is 0x0bb3)
- language-id : USB Language ID (16 bit, default is 0x0000) - language-id : Set USB Language ID (16 bit, default is 0x0000)
- manufacturer : USB Manufacturer string (max 31 characters long) - manufacturer : Set USB Manufacturer string (max 31 characters long)
- product : USB Product string (max 31 characters long) - product : Set USB Product string (max 31 characters long)
- serial : USB Serial string (max 31 characters long) - serial : Set USB Serial string (max 31 characters long)
- {bus,self}-powered : selects between self- and bus-powered operation (default - {bus,self}-powered : selects between self- and bus-powered operation (default
is self-powered) is self-powered)
- disable-hi-speed : disable USB Hi-Speed support - disable-hi-speed : disable USB Hi-Speed support
...@@ -31,8 +31,10 @@ Optional properties : ...@@ -31,8 +31,10 @@ Optional properties :
(default is individual) (default is individual)
- dynamic-power-switching : enable auto-switching from self- to bus-powered - dynamic-power-switching : enable auto-switching from self- to bus-powered
operation if the local power source is removed or unavailable operation if the local power source is removed or unavailable
- oc-delay-{100us,4ms,8ms,16ms} : set over current timer delay (default is 8ms) - oc-delay-us : Delay time (in microseconds) for filtering the over-current
- compound-device : indicated the hub is part of a compound device sense inputs. Valid values are 100, 4000, 8000 (default) and 16000. If
an invalid value is given, the default is used instead.
- compound-device : indicate the hub is part of a compound device
- port-mapping-mode : enable port mapping mode - port-mapping-mode : enable port mapping mode
- string-support : enable string descriptor support (required for manufacturer, - string-support : enable string descriptor support (required for manufacturer,
product and serial string configuration) product and serial string configuration)
...@@ -40,34 +42,15 @@ Optional properties : ...@@ -40,34 +42,15 @@ Optional properties :
device connected. device connected.
- sp-disabled-ports : Specifies the ports which will be self-power disabled - sp-disabled-ports : Specifies the ports which will be self-power disabled
- bp-disabled-ports : Specifies the ports which will be bus-power disabled - bp-disabled-ports : Specifies the ports which will be bus-power disabled
- max-sp-power : Specifies the maximum current the hub consumes from an - power-on-time-ms : Specifies the time it takes from the time the host
upstream port when operating as self-powered hub including the power initiates the power-on sequence to a port until the port has adequate
consumption of a permanently attached peripheral if the hub is power. The value is given in ms in a 0 - 510 range (default is 100ms).
configured as a compound device. The value is given in mA in a 0 - 500
range (default is 2).
- max-bp-power : Specifies the maximum current the hub consumes from an
upstream port when operating as bus-powered hub including the power
consumption of a permanently attached peripheral if the hub is
configured as a compound device. The value is given in mA in a 0 - 500
range (default is 100).
- max-sp-current : Specifies the maximum current the hub consumes from an
upstream port when operating as self-powered hub EXCLUDING the power
consumption of a permanently attached peripheral if the hub is
configured as a compound device. The value is given in mA in a 0 - 500
range (default is 2).
- max-bp-current : Specifies the maximum current the hub consumes from an
upstream port when operating as bus-powered hub EXCLUDING the power
consumption of a permanently attached peripheral if the hub is
configured as a compound device. The value is given in mA in a 0 - 500
range (default is 100).
- power-on-time : Specifies the time it takes from the time the host initiates
the power-on sequence to a port until the port has adequate power. The
value is given in ms in a 0 - 510 range (default is 100ms).
Examples: Examples:
usb2512b@2c { usb2512b@2c {
compatible = "microchip,usb2512b"; compatible = "microchip,usb2512b";
hub-reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; reg = <0x2c>;
reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
}; };
usb2514b@2c { usb2514b@2c {
......
...@@ -8307,7 +8307,6 @@ M: Richard Leitner <richard.leitner@skidata.com> ...@@ -8307,7 +8307,6 @@ M: Richard Leitner <richard.leitner@skidata.com>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
S: Maintained S: Maintained
F: drivers/usb/misc/usb251xb.c F: drivers/usb/misc/usb251xb.c
F: include/linux/platform_data/usb251xb.h
F: Documentation/devicetree/bindings/usb/usb251xb.txt F: Documentation/devicetree/bindings/usb/usb251xb.txt
MICROSOFT SURFACE PRO 3 BUTTON DRIVER MICROSOFT SURFACE PRO 3 BUTTON DRIVER
......
...@@ -250,6 +250,7 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap, ...@@ -250,6 +250,7 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
val = dwc3_omap_read_utmi_ctrl(omap); val = dwc3_omap_read_utmi_ctrl(omap);
val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG; val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG;
dwc3_omap_write_utmi_ctrl(omap, val); dwc3_omap_write_utmi_ctrl(omap, val);
break;
case OMAP_DWC3_VBUS_OFF: case OMAP_DWC3_VBUS_OFF:
val = dwc3_omap_read_utmi_ctrl(omap); val = dwc3_omap_read_utmi_ctrl(omap);
...@@ -392,7 +393,7 @@ static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap) ...@@ -392,7 +393,7 @@ static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap)
{ {
u32 reg; u32 reg;
struct device_node *node = omap->dev->of_node; struct device_node *node = omap->dev->of_node;
int utmi_mode = 0; u32 utmi_mode = 0;
reg = dwc3_omap_read_utmi_ctrl(omap); reg = dwc3_omap_read_utmi_ctrl(omap);
......
...@@ -1342,6 +1342,68 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, ...@@ -1342,6 +1342,68 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
if (r == req) { if (r == req) {
/* wait until it is processed */ /* wait until it is processed */
dwc3_stop_active_transfer(dwc, dep->number, true); dwc3_stop_active_transfer(dwc, dep->number, true);
/*
* If request was already started, this means we had to
* stop the transfer. With that we also need to ignore
* all TRBs used by the request, however TRBs can only
* be modified after completion of END_TRANSFER
* command. So what we do here is that we wait for
* END_TRANSFER completion and only after that, we jump
* over TRBs by clearing HWO and incrementing dequeue
* pointer.
*
* Note that we have 2 possible types of transfers here:
*
* i) Linear buffer request
* ii) SG-list based request
*
* SG-list based requests will have r->num_pending_sgs
* set to a valid number (> 0). Linear requests,
* normally use a single TRB.
*
* For each of these two cases, if r->unaligned flag is
* set, one extra TRB has been used to align transfer
* size to wMaxPacketSize.
*
* All of these cases need to be taken into
* consideration so we don't mess up our TRB ring
* pointers.
*/
wait_event_lock_irq(dep->wait_end_transfer,
!(dep->flags & DWC3_EP_END_TRANSFER_PENDING),
dwc->lock);
if (!r->trb)
goto out1;
if (r->num_pending_sgs) {
struct dwc3_trb *trb;
int i = 0;
for (i = 0; i < r->num_pending_sgs; i++) {
trb = r->trb + i;
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
dwc3_ep_inc_deq(dep);
}
if (r->unaligned) {
trb = r->trb + r->num_pending_sgs + 1;
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
dwc3_ep_inc_deq(dep);
}
} else {
struct dwc3_trb *trb = r->trb;
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
dwc3_ep_inc_deq(dep);
if (r->unaligned) {
trb = r->trb + 1;
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
dwc3_ep_inc_deq(dep);
}
}
goto out1; goto out1;
} }
dev_err(dwc->dev, "request %p was not queued to %s\n", dev_err(dwc->dev, "request %p was not queued to %s\n",
...@@ -1352,6 +1414,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, ...@@ -1352,6 +1414,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
out1: out1:
/* giveback the request */ /* giveback the request */
dep->queued_requests--;
dwc3_gadget_giveback(dep, req, -ECONNRESET); dwc3_gadget_giveback(dep, req, -ECONNRESET);
out0: out0:
...@@ -2126,12 +2189,12 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, ...@@ -2126,12 +2189,12 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
return 1; return 1;
} }
if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
return 1;
count = trb->size & DWC3_TRB_SIZE_MASK; count = trb->size & DWC3_TRB_SIZE_MASK;
req->remaining += count; req->remaining += count;
if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
return 1;
if (dep->direction) { if (dep->direction) {
if (count) { if (count) {
trb_status = DWC3_TRB_SIZE_TRBSTS(trb->size); trb_status = DWC3_TRB_SIZE_TRBSTS(trb->size);
...@@ -3228,15 +3291,10 @@ void dwc3_gadget_exit(struct dwc3 *dwc) ...@@ -3228,15 +3291,10 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
int dwc3_gadget_suspend(struct dwc3 *dwc) int dwc3_gadget_suspend(struct dwc3 *dwc)
{ {
int ret;
if (!dwc->gadget_driver) if (!dwc->gadget_driver)
return 0; return 0;
ret = dwc3_gadget_run_stop(dwc, false, false); dwc3_gadget_run_stop(dwc, false, false);
if (ret < 0)
return ret;
dwc3_disconnect_gadget(dwc); dwc3_disconnect_gadget(dwc);
__dwc3_gadget_stop(dwc); __dwc3_gadget_stop(dwc);
......
...@@ -28,23 +28,23 @@ struct dwc3; ...@@ -28,23 +28,23 @@ struct dwc3;
#define gadget_to_dwc(g) (container_of(g, struct dwc3, gadget)) #define gadget_to_dwc(g) (container_of(g, struct dwc3, gadget))
/* DEPCFG parameter 1 */ /* DEPCFG parameter 1 */
#define DWC3_DEPCFG_INT_NUM(n) ((n) << 0) #define DWC3_DEPCFG_INT_NUM(n) (((n) & 0x1f) << 0)
#define DWC3_DEPCFG_XFER_COMPLETE_EN (1 << 8) #define DWC3_DEPCFG_XFER_COMPLETE_EN (1 << 8)
#define DWC3_DEPCFG_XFER_IN_PROGRESS_EN (1 << 9) #define DWC3_DEPCFG_XFER_IN_PROGRESS_EN (1 << 9)
#define DWC3_DEPCFG_XFER_NOT_READY_EN (1 << 10) #define DWC3_DEPCFG_XFER_NOT_READY_EN (1 << 10)
#define DWC3_DEPCFG_FIFO_ERROR_EN (1 << 11) #define DWC3_DEPCFG_FIFO_ERROR_EN (1 << 11)
#define DWC3_DEPCFG_STREAM_EVENT_EN (1 << 13) #define DWC3_DEPCFG_STREAM_EVENT_EN (1 << 13)
#define DWC3_DEPCFG_BINTERVAL_M1(n) ((n) << 16) #define DWC3_DEPCFG_BINTERVAL_M1(n) (((n) & 0xff) << 16)
#define DWC3_DEPCFG_STREAM_CAPABLE (1 << 24) #define DWC3_DEPCFG_STREAM_CAPABLE (1 << 24)
#define DWC3_DEPCFG_EP_NUMBER(n) ((n) << 25) #define DWC3_DEPCFG_EP_NUMBER(n) (((n) & 0x1f) << 25)
#define DWC3_DEPCFG_BULK_BASED (1 << 30) #define DWC3_DEPCFG_BULK_BASED (1 << 30)
#define DWC3_DEPCFG_FIFO_BASED (1 << 31) #define DWC3_DEPCFG_FIFO_BASED (1 << 31)
/* DEPCFG parameter 0 */ /* DEPCFG parameter 0 */
#define DWC3_DEPCFG_EP_TYPE(n) ((n) << 1) #define DWC3_DEPCFG_EP_TYPE(n) (((n) & 0x3) << 1)
#define DWC3_DEPCFG_MAX_PACKET_SIZE(n) ((n) << 3) #define DWC3_DEPCFG_MAX_PACKET_SIZE(n) (((n) & 0x7ff) << 3)
#define DWC3_DEPCFG_FIFO_NUMBER(n) ((n) << 17) #define DWC3_DEPCFG_FIFO_NUMBER(n) (((n) & 0x1f) << 17)
#define DWC3_DEPCFG_BURST_SIZE(n) ((n) << 22) #define DWC3_DEPCFG_BURST_SIZE(n) (((n) & 0xf) << 22)
#define DWC3_DEPCFG_DATA_SEQ_NUM(n) ((n) << 26) #define DWC3_DEPCFG_DATA_SEQ_NUM(n) ((n) << 26)
/* This applies for core versions earlier than 1.94a */ /* This applies for core versions earlier than 1.94a */
#define DWC3_DEPCFG_IGN_SEQ_NUM (1 << 31) #define DWC3_DEPCFG_IGN_SEQ_NUM (1 << 31)
......
...@@ -269,6 +269,7 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item, ...@@ -269,6 +269,7 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
ret = unregister_gadget(gi); ret = unregister_gadget(gi);
if (ret) if (ret)
goto err; goto err;
kfree(name);
} else { } else {
if (gi->composite.gadget_driver.udc_name) { if (gi->composite.gadget_driver.udc_name) {
ret = -EBUSY; ret = -EBUSY;
......
...@@ -1834,11 +1834,14 @@ static int ffs_func_eps_enable(struct ffs_function *func) ...@@ -1834,11 +1834,14 @@ static int ffs_func_eps_enable(struct ffs_function *func)
spin_lock_irqsave(&func->ffs->eps_lock, flags); spin_lock_irqsave(&func->ffs->eps_lock, flags);
while(count--) { while(count--) {
struct usb_endpoint_descriptor *ds; struct usb_endpoint_descriptor *ds;
struct usb_ss_ep_comp_descriptor *comp_desc = NULL;
int needs_comp_desc = false;
int desc_idx; int desc_idx;
if (ffs->gadget->speed == USB_SPEED_SUPER) if (ffs->gadget->speed == USB_SPEED_SUPER) {
desc_idx = 2; desc_idx = 2;
else if (ffs->gadget->speed == USB_SPEED_HIGH) needs_comp_desc = true;
} else if (ffs->gadget->speed == USB_SPEED_HIGH)
desc_idx = 1; desc_idx = 1;
else else
desc_idx = 0; desc_idx = 0;
...@@ -1855,6 +1858,14 @@ static int ffs_func_eps_enable(struct ffs_function *func) ...@@ -1855,6 +1858,14 @@ static int ffs_func_eps_enable(struct ffs_function *func)
ep->ep->driver_data = ep; ep->ep->driver_data = ep;
ep->ep->desc = ds; ep->ep->desc = ds;
comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds +
USB_DT_ENDPOINT_SIZE);
ep->ep->maxburst = comp_desc->bMaxBurst + 1;
if (needs_comp_desc)
ep->ep->comp_desc = comp_desc;
ret = usb_ep_enable(ep->ep); ret = usb_ep_enable(ep->ep);
if (likely(!ret)) { if (likely(!ret)) {
epfile->ep = ep; epfile->ep = ep;
...@@ -2253,7 +2264,7 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type, ...@@ -2253,7 +2264,7 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
if (len < sizeof(*d) || if (len < sizeof(*d) ||
d->bFirstInterfaceNumber >= ffs->interfaces_count || d->bFirstInterfaceNumber >= ffs->interfaces_count ||
d->Reserved1) !d->Reserved1)
return -EINVAL; return -EINVAL;
for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i) for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
if (d->Reserved2[i]) if (d->Reserved2[i])
......
...@@ -258,13 +258,6 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) ...@@ -258,13 +258,6 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req)); memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req));
v4l2_event_queue(&uvc->vdev, &v4l2_event); v4l2_event_queue(&uvc->vdev, &v4l2_event);
/* Pass additional setup data to userspace */
if (uvc->event_setup_out && uvc->event_length) {
uvc->control_req->length = uvc->event_length;
return usb_ep_queue(uvc->func.config->cdev->gadget->ep0,
uvc->control_req, GFP_ATOMIC);
}
return 0; return 0;
} }
......
...@@ -1781,8 +1781,10 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) ...@@ -1781,8 +1781,10 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
spin_lock_irq (&dev->lock); spin_lock_irq (&dev->lock);
value = -EINVAL; value = -EINVAL;
if (dev->buf) if (dev->buf) {
kfree(kbuf);
goto fail; goto fail;
}
dev->buf = kbuf; dev->buf = kbuf;
/* full or low speed config */ /* full or low speed config */
......
...@@ -610,7 +610,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ...@@ -610,7 +610,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
{ {
struct usba_ep *ep = to_usba_ep(_ep); struct usba_ep *ep = to_usba_ep(_ep);
struct usba_udc *udc = ep->udc; struct usba_udc *udc = ep->udc;
unsigned long flags, ept_cfg, maxpacket; unsigned long flags, maxpacket;
unsigned int nr_trans; unsigned int nr_trans;
DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc); DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc);
...@@ -630,7 +630,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ...@@ -630,7 +630,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
ep->is_in = 0; ep->is_in = 0;
DBG(DBG_ERR, "%s: EPT_CFG = 0x%lx (maxpacket = %lu)\n", DBG(DBG_ERR, "%s: EPT_CFG = 0x%lx (maxpacket = %lu)\n",
ep->ep.name, ept_cfg, maxpacket); ep->ep.name, ep->ept_cfg, maxpacket);
if (usb_endpoint_dir_in(desc)) { if (usb_endpoint_dir_in(desc)) {
ep->is_in = 1; ep->is_in = 1;
......
...@@ -1031,6 +1031,8 @@ static int dummy_udc_probe(struct platform_device *pdev) ...@@ -1031,6 +1031,8 @@ static int dummy_udc_probe(struct platform_device *pdev)
int rc; int rc;
dum = *((void **)dev_get_platdata(&pdev->dev)); dum = *((void **)dev_get_platdata(&pdev->dev));
/* Clear usb_gadget region for new registration to udc-core */
memzero_explicit(&dum->gadget, sizeof(struct usb_gadget));
dum->gadget.name = gadget_name; dum->gadget.name = gadget_name;
dum->gadget.ops = &dummy_ops; dum->gadget.ops = &dummy_ops;
dum->gadget.max_speed = USB_SPEED_SUPER; dum->gadget.max_speed = USB_SPEED_SUPER;
......
...@@ -1146,15 +1146,15 @@ static int scan_dma_completions(struct net2280_ep *ep) ...@@ -1146,15 +1146,15 @@ static int scan_dma_completions(struct net2280_ep *ep)
*/ */
while (!list_empty(&ep->queue)) { while (!list_empty(&ep->queue)) {
struct net2280_request *req; struct net2280_request *req;
u32 tmp; u32 req_dma_count;
req = list_entry(ep->queue.next, req = list_entry(ep->queue.next,
struct net2280_request, queue); struct net2280_request, queue);
if (!req->valid) if (!req->valid)
break; break;
rmb(); rmb();
tmp = le32_to_cpup(&req->td->dmacount); req_dma_count = le32_to_cpup(&req->td->dmacount);
if ((tmp & BIT(VALID_BIT)) != 0) if ((req_dma_count & BIT(VALID_BIT)) != 0)
break; break;
/* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short" /* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short"
...@@ -1163,40 +1163,41 @@ static int scan_dma_completions(struct net2280_ep *ep) ...@@ -1163,40 +1163,41 @@ static int scan_dma_completions(struct net2280_ep *ep)
*/ */
if (unlikely(req->td->dmadesc == 0)) { if (unlikely(req->td->dmadesc == 0)) {
/* paranoia */ /* paranoia */
tmp = readl(&ep->dma->dmacount); u32 const ep_dmacount = readl(&ep->dma->dmacount);
if (tmp & DMA_BYTE_COUNT_MASK)
if (ep_dmacount & DMA_BYTE_COUNT_MASK)
break; break;
/* single transfer mode */ /* single transfer mode */
dma_done(ep, req, tmp, 0); dma_done(ep, req, req_dma_count, 0);
num_completed++; num_completed++;
break; break;
} else if (!ep->is_in && } else if (!ep->is_in &&
(req->req.length % ep->ep.maxpacket) && (req->req.length % ep->ep.maxpacket) &&
!(ep->dev->quirks & PLX_PCIE)) { !(ep->dev->quirks & PLX_PCIE)) {
tmp = readl(&ep->regs->ep_stat); u32 const ep_stat = readl(&ep->regs->ep_stat);
/* AVOID TROUBLE HERE by not issuing short reads from /* AVOID TROUBLE HERE by not issuing short reads from
* your gadget driver. That helps avoids errata 0121, * your gadget driver. That helps avoids errata 0121,
* 0122, and 0124; not all cases trigger the warning. * 0122, and 0124; not all cases trigger the warning.
*/ */
if ((tmp & BIT(NAK_OUT_PACKETS)) == 0) { if ((ep_stat & BIT(NAK_OUT_PACKETS)) == 0) {
ep_warn(ep->dev, "%s lost packet sync!\n", ep_warn(ep->dev, "%s lost packet sync!\n",
ep->ep.name); ep->ep.name);
req->req.status = -EOVERFLOW; req->req.status = -EOVERFLOW;
} else { } else {
tmp = readl(&ep->regs->ep_avail); u32 const ep_avail = readl(&ep->regs->ep_avail);
if (tmp) { if (ep_avail) {
/* fifo gets flushed later */ /* fifo gets flushed later */
ep->out_overflow = 1; ep->out_overflow = 1;
ep_dbg(ep->dev, ep_dbg(ep->dev,
"%s dma, discard %d len %d\n", "%s dma, discard %d len %d\n",
ep->ep.name, tmp, ep->ep.name, ep_avail,
req->req.length); req->req.length);
req->req.status = -EOVERFLOW; req->req.status = -EOVERFLOW;
} }
} }
} }
dma_done(ep, req, tmp, 0); dma_done(ep, req, req_dma_count, 0);
num_completed++; num_completed++;
} }
......
...@@ -2534,9 +2534,10 @@ static int pxa_udc_remove(struct platform_device *_dev) ...@@ -2534,9 +2534,10 @@ static int pxa_udc_remove(struct platform_device *_dev)
usb_del_gadget_udc(&udc->gadget); usb_del_gadget_udc(&udc->gadget);
pxa_cleanup_debugfs(udc); pxa_cleanup_debugfs(udc);
if (!IS_ERR_OR_NULL(udc->transceiver)) if (!IS_ERR_OR_NULL(udc->transceiver)) {
usb_unregister_notifier(udc->transceiver, &pxa27x_udc_phy); usb_unregister_notifier(udc->transceiver, &pxa27x_udc_phy);
usb_put_phy(udc->transceiver); usb_put_phy(udc->transceiver);
}
udc->transceiver = NULL; udc->transceiver = NULL;
the_controller = NULL; the_controller = NULL;
......
...@@ -350,7 +350,7 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -350,7 +350,7 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case USB_PORT_FEAT_SUSPEND: case USB_PORT_FEAT_SUSPEND:
dev_dbg(hcd->self.controller, "SetPortFeat: SUSPEND\n"); dev_dbg(hcd->self.controller, "SetPortFeat: SUSPEND\n");
if (valid_port(wIndex)) { if (valid_port(wIndex) && ohci_at91->sfr_regmap) {
ohci_at91_port_suspend(ohci_at91->sfr_regmap, ohci_at91_port_suspend(ohci_at91->sfr_regmap,
1); 1);
return 0; return 0;
...@@ -393,7 +393,7 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -393,7 +393,7 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case USB_PORT_FEAT_SUSPEND: case USB_PORT_FEAT_SUSPEND:
dev_dbg(hcd->self.controller, "ClearPortFeature: SUSPEND\n"); dev_dbg(hcd->self.controller, "ClearPortFeature: SUSPEND\n");
if (valid_port(wIndex)) { if (valid_port(wIndex) && ohci_at91->sfr_regmap) {
ohci_at91_port_suspend(ohci_at91->sfr_regmap, ohci_at91_port_suspend(ohci_at91->sfr_regmap,
0); 0);
return 0; return 0;
......
...@@ -109,7 +109,7 @@ static void xhci_print_cap_regs(struct xhci_hcd *xhci) ...@@ -109,7 +109,7 @@ static void xhci_print_cap_regs(struct xhci_hcd *xhci)
xhci_dbg(xhci, "RTSOFF 0x%x:\n", temp & RTSOFF_MASK); xhci_dbg(xhci, "RTSOFF 0x%x:\n", temp & RTSOFF_MASK);
/* xhci 1.1 controllers have the HCCPARAMS2 register */ /* xhci 1.1 controllers have the HCCPARAMS2 register */
if (hci_version > 100) { if (hci_version > 0x100) {
temp = readl(&xhci->cap_regs->hcc_params2); temp = readl(&xhci->cap_regs->hcc_params2);
xhci_dbg(xhci, "HCC PARAMS2 0x%x:\n", (unsigned int) temp); xhci_dbg(xhci, "HCC PARAMS2 0x%x:\n", (unsigned int) temp);
xhci_dbg(xhci, " HC %s Force save context capability", xhci_dbg(xhci, " HC %s Force save context capability",
......
...@@ -382,7 +382,6 @@ static int usb_wakeup_of_property_parse(struct xhci_hcd_mtk *mtk, ...@@ -382,7 +382,6 @@ static int usb_wakeup_of_property_parse(struct xhci_hcd_mtk *mtk,
static int xhci_mtk_setup(struct usb_hcd *hcd); static int xhci_mtk_setup(struct usb_hcd *hcd);
static const struct xhci_driver_overrides xhci_mtk_overrides __initconst = { static const struct xhci_driver_overrides xhci_mtk_overrides __initconst = {
.extra_priv_size = sizeof(struct xhci_hcd),
.reset = xhci_mtk_setup, .reset = xhci_mtk_setup,
}; };
...@@ -678,13 +677,13 @@ static int xhci_mtk_probe(struct platform_device *pdev) ...@@ -678,13 +677,13 @@ static int xhci_mtk_probe(struct platform_device *pdev)
goto power_off_phys; goto power_off_phys;
} }
if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
xhci->shared_hcd->can_do_streams = 1;
ret = usb_add_hcd(hcd, irq, IRQF_SHARED); ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret) if (ret)
goto put_usb3_hcd; goto put_usb3_hcd;
if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
xhci->shared_hcd->can_do_streams = 1;
ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
if (ret) if (ret)
goto dealloc_usb2_hcd; goto dealloc_usb2_hcd;
......
...@@ -286,6 +286,8 @@ static int xhci_plat_remove(struct platform_device *dev) ...@@ -286,6 +286,8 @@ static int xhci_plat_remove(struct platform_device *dev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct clk *clk = xhci->clk; struct clk *clk = xhci->clk;
xhci->xhc_state |= XHCI_STATE_REMOVING;
usb_remove_hcd(xhci->shared_hcd); usb_remove_hcd(xhci->shared_hcd);
usb_phy_shutdown(hcd->usb_phy); usb_phy_shutdown(hcd->usb_phy);
......
...@@ -1308,7 +1308,6 @@ static int tegra_xhci_setup(struct usb_hcd *hcd) ...@@ -1308,7 +1308,6 @@ static int tegra_xhci_setup(struct usb_hcd *hcd)
} }
static const struct xhci_driver_overrides tegra_xhci_overrides __initconst = { static const struct xhci_driver_overrides tegra_xhci_overrides __initconst = {
.extra_priv_size = sizeof(struct xhci_hcd),
.reset = tegra_xhci_setup, .reset = tegra_xhci_setup,
}; };
......
...@@ -781,12 +781,6 @@ static int iowarrior_probe(struct usb_interface *interface, ...@@ -781,12 +781,6 @@ static int iowarrior_probe(struct usb_interface *interface,
iface_desc = interface->cur_altsetting; iface_desc = interface->cur_altsetting;
dev->product_id = le16_to_cpu(udev->descriptor.idProduct); dev->product_id = le16_to_cpu(udev->descriptor.idProduct);
if (iface_desc->desc.bNumEndpoints < 1) {
dev_err(&interface->dev, "Invalid number of endpoints\n");
retval = -EINVAL;
goto error;
}
/* set up the endpoint information */ /* set up the endpoint information */
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc; endpoint = &iface_desc->endpoint[i].desc;
...@@ -797,6 +791,21 @@ static int iowarrior_probe(struct usb_interface *interface, ...@@ -797,6 +791,21 @@ static int iowarrior_probe(struct usb_interface *interface,
/* this one will match for the IOWarrior56 only */ /* this one will match for the IOWarrior56 only */
dev->int_out_endpoint = endpoint; dev->int_out_endpoint = endpoint;
} }
if (!dev->int_in_endpoint) {
dev_err(&interface->dev, "no interrupt-in endpoint found\n");
retval = -ENODEV;
goto error;
}
if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) {
if (!dev->int_out_endpoint) {
dev_err(&interface->dev, "no interrupt-out endpoint found\n");
retval = -ENODEV;
goto error;
}
}
/* we have to check the report_size often, so remember it in the endianness suitable for our machine */ /* we have to check the report_size often, so remember it in the endianness suitable for our machine */
dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint); dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint);
if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) && if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) &&
......
...@@ -375,18 +375,24 @@ static int usb251xb_get_ofdata(struct usb251xb *hub, ...@@ -375,18 +375,24 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
if (of_get_property(np, "dynamic-power-switching", NULL)) if (of_get_property(np, "dynamic-power-switching", NULL))
hub->conf_data2 |= BIT(7); hub->conf_data2 |= BIT(7);
if (of_get_property(np, "oc-delay-100us", NULL)) { if (!of_property_read_u32(np, "oc-delay-us", property_u32)) {
hub->conf_data2 &= ~BIT(5); if (*property_u32 == 100) {
hub->conf_data2 &= ~BIT(4); /* 100 us*/
} else if (of_get_property(np, "oc-delay-4ms", NULL)) { hub->conf_data2 &= ~BIT(5);
hub->conf_data2 &= ~BIT(5); hub->conf_data2 &= ~BIT(4);
hub->conf_data2 |= BIT(4); } else if (*property_u32 == 4000) {
} else if (of_get_property(np, "oc-delay-8ms", NULL)) { /* 4 ms */
hub->conf_data2 |= BIT(5); hub->conf_data2 &= ~BIT(5);
hub->conf_data2 &= ~BIT(4); hub->conf_data2 |= BIT(4);
} else if (of_get_property(np, "oc-delay-16ms", NULL)) { } else if (*property_u32 == 16000) {
hub->conf_data2 |= BIT(5); /* 16 ms */
hub->conf_data2 |= BIT(4); hub->conf_data2 |= BIT(5);
hub->conf_data2 |= BIT(4);
} else {
/* 8 ms (DEFAULT) */
hub->conf_data2 |= BIT(5);
hub->conf_data2 &= ~BIT(4);
}
} }
if (of_get_property(np, "compound-device", NULL)) if (of_get_property(np, "compound-device", NULL))
...@@ -432,30 +438,9 @@ static int usb251xb_get_ofdata(struct usb251xb *hub, ...@@ -432,30 +438,9 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
} }
} }
hub->max_power_sp = USB251XB_DEF_MAX_POWER_SELF;
if (!of_property_read_u32(np, "max-sp-power", property_u32))
hub->max_power_sp = min_t(u8, be32_to_cpu(*property_u32) / 2,
250);
hub->max_power_bp = USB251XB_DEF_MAX_POWER_BUS;
if (!of_property_read_u32(np, "max-bp-power", property_u32))
hub->max_power_bp = min_t(u8, be32_to_cpu(*property_u32) / 2,
250);
hub->max_current_sp = USB251XB_DEF_MAX_CURRENT_SELF;
if (!of_property_read_u32(np, "max-sp-current", property_u32))
hub->max_current_sp = min_t(u8, be32_to_cpu(*property_u32) / 2,
250);
hub->max_current_bp = USB251XB_DEF_MAX_CURRENT_BUS;
if (!of_property_read_u32(np, "max-bp-current", property_u32))
hub->max_current_bp = min_t(u8, be32_to_cpu(*property_u32) / 2,
250);
hub->power_on_time = USB251XB_DEF_POWER_ON_TIME; hub->power_on_time = USB251XB_DEF_POWER_ON_TIME;
if (!of_property_read_u32(np, "power-on-time", property_u32)) if (!of_property_read_u32(np, "power-on-time-ms", property_u32))
hub->power_on_time = min_t(u8, be32_to_cpu(*property_u32) / 2, hub->power_on_time = min_t(u8, *property_u32 / 2, 255);
255);
if (of_property_read_u16_array(np, "language-id", &hub->lang_id, 1)) if (of_property_read_u16_array(np, "language-id", &hub->lang_id, 1))
hub->lang_id = USB251XB_DEF_LANGUAGE_ID; hub->lang_id = USB251XB_DEF_LANGUAGE_ID;
...@@ -492,6 +477,10 @@ static int usb251xb_get_ofdata(struct usb251xb *hub, ...@@ -492,6 +477,10 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
/* The following parameters are currently not exposed to devicetree, but /* The following parameters are currently not exposed to devicetree, but
* may be as soon as needed. * may be as soon as needed.
*/ */
hub->max_power_sp = USB251XB_DEF_MAX_POWER_SELF;
hub->max_power_bp = USB251XB_DEF_MAX_POWER_BUS;
hub->max_current_sp = USB251XB_DEF_MAX_CURRENT_SELF;
hub->max_current_bp = USB251XB_DEF_MAX_CURRENT_BUS;
hub->bat_charge_en = USB251XB_DEF_BATTERY_CHARGING_ENABLE; hub->bat_charge_en = USB251XB_DEF_BATTERY_CHARGING_ENABLE;
hub->boost_up = USB251XB_DEF_BOOST_UP; hub->boost_up = USB251XB_DEF_BOOST_UP;
hub->boost_x = USB251XB_DEF_BOOST_X; hub->boost_x = USB251XB_DEF_BOOST_X;
......
...@@ -33,6 +33,12 @@ static const struct i2c_device_id isp1301_id[] = { ...@@ -33,6 +33,12 @@ static const struct i2c_device_id isp1301_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, isp1301_id); MODULE_DEVICE_TABLE(i2c, isp1301_id);
static const struct of_device_id isp1301_of_match[] = {
{.compatible = "nxp,isp1301" },
{ },
};
MODULE_DEVICE_TABLE(of, isp1301_of_match);
static struct i2c_client *isp1301_i2c_client; static struct i2c_client *isp1301_i2c_client;
static int __isp1301_write(struct isp1301 *isp, u8 reg, u8 value, u8 clear) static int __isp1301_write(struct isp1301 *isp, u8 reg, u8 value, u8 clear)
...@@ -130,6 +136,7 @@ static int isp1301_remove(struct i2c_client *client) ...@@ -130,6 +136,7 @@ static int isp1301_remove(struct i2c_client *client)
static struct i2c_driver isp1301_driver = { static struct i2c_driver isp1301_driver = {
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.of_match_table = of_match_ptr(isp1301_of_match),
}, },
.probe = isp1301_probe, .probe = isp1301_probe,
.remove = isp1301_remove, .remove = isp1301_remove,
......
...@@ -1500,7 +1500,7 @@ static int digi_read_oob_callback(struct urb *urb) ...@@ -1500,7 +1500,7 @@ static int digi_read_oob_callback(struct urb *urb)
return -1; return -1;
/* handle each oob command */ /* handle each oob command */
for (i = 0; i < urb->actual_length - 4; i += 4) { for (i = 0; i < urb->actual_length - 3; i += 4) {
opcode = buf[i]; opcode = buf[i];
line = buf[i + 1]; line = buf[i + 1];
status = buf[i + 2]; status = buf[i + 2];
......
...@@ -1674,6 +1674,12 @@ static void edge_interrupt_callback(struct urb *urb) ...@@ -1674,6 +1674,12 @@ static void edge_interrupt_callback(struct urb *urb)
function = TIUMP_GET_FUNC_FROM_CODE(data[0]); function = TIUMP_GET_FUNC_FROM_CODE(data[0]);
dev_dbg(dev, "%s - port_number %d, function %d, info 0x%x\n", __func__, dev_dbg(dev, "%s - port_number %d, function %d, info 0x%x\n", __func__,
port_number, function, data[1]); port_number, function, data[1]);
if (port_number >= edge_serial->serial->num_ports) {
dev_err(dev, "bad port number %d\n", port_number);
goto exit;
}
port = edge_serial->serial->port[port_number]; port = edge_serial->serial->port[port_number];
edge_port = usb_get_serial_port_data(port); edge_port = usb_get_serial_port_data(port);
if (!edge_port) { if (!edge_port) {
...@@ -1755,7 +1761,7 @@ static void edge_bulk_in_callback(struct urb *urb) ...@@ -1755,7 +1761,7 @@ static void edge_bulk_in_callback(struct urb *urb)
port_number = edge_port->port->port_number; port_number = edge_port->port->port_number;
if (edge_port->lsr_event) { if (urb->actual_length > 0 && edge_port->lsr_event) {
edge_port->lsr_event = 0; edge_port->lsr_event = 0;
dev_dbg(dev, "%s ===== Port %u LSR Status = %02x, Data = %02x ======\n", dev_dbg(dev, "%s ===== Port %u LSR Status = %02x, Data = %02x ======\n",
__func__, port_number, edge_port->lsr_mask, *data); __func__, port_number, edge_port->lsr_mask, *data);
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#define BT_IGNITIONPRO_ID 0x2000 #define BT_IGNITIONPRO_ID 0x2000
/* function prototypes */ /* function prototypes */
static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port);
static void omninet_process_read_urb(struct urb *urb); static void omninet_process_read_urb(struct urb *urb);
static void omninet_write_bulk_callback(struct urb *urb); static void omninet_write_bulk_callback(struct urb *urb);
static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
...@@ -60,7 +59,6 @@ static struct usb_serial_driver zyxel_omninet_device = { ...@@ -60,7 +59,6 @@ static struct usb_serial_driver zyxel_omninet_device = {
.attach = omninet_attach, .attach = omninet_attach,
.port_probe = omninet_port_probe, .port_probe = omninet_port_probe,
.port_remove = omninet_port_remove, .port_remove = omninet_port_remove,
.open = omninet_open,
.write = omninet_write, .write = omninet_write,
.write_room = omninet_write_room, .write_room = omninet_write_room,
.write_bulk_callback = omninet_write_bulk_callback, .write_bulk_callback = omninet_write_bulk_callback,
...@@ -140,17 +138,6 @@ static int omninet_port_remove(struct usb_serial_port *port) ...@@ -140,17 +138,6 @@ static int omninet_port_remove(struct usb_serial_port *port)
return 0; return 0;
} }
static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct usb_serial_port *wport;
wport = serial->port[1];
tty_port_tty_set(&wport->port, tty);
return usb_serial_generic_open(tty, port);
}
#define OMNINET_HEADERLEN 4 #define OMNINET_HEADERLEN 4
#define OMNINET_BULKOUTSIZE 64 #define OMNINET_BULKOUTSIZE 64
#define OMNINET_PAYLOADSIZE (OMNINET_BULKOUTSIZE - OMNINET_HEADERLEN) #define OMNINET_PAYLOADSIZE (OMNINET_BULKOUTSIZE - OMNINET_HEADERLEN)
......
...@@ -200,6 +200,11 @@ static void safe_process_read_urb(struct urb *urb) ...@@ -200,6 +200,11 @@ static void safe_process_read_urb(struct urb *urb)
if (!safe) if (!safe)
goto out; goto out;
if (length < 2) {
dev_err(&port->dev, "malformed packet\n");
return;
}
fcs = fcs_compute10(data, length, CRC10_INITFCS); fcs = fcs_compute10(data, length, CRC10_INITFCS);
if (fcs) { if (fcs) {
dev_err(&port->dev, "%s - bad CRC %x\n", __func__, fcs); dev_err(&port->dev, "%s - bad CRC %x\n", __func__, fcs);
......
...@@ -2071,6 +2071,20 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110, ...@@ -2071,6 +2071,20 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110,
USB_SC_DEVICE, USB_PR_DEVICE, NULL, USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ), US_FL_IGNORE_RESIDUE ),
/*
* Reported by Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
* The INIC-3619 bridge is used in the StarTech SLSODDU33B
* SATA-USB enclosure for slimline optical drives.
*
* The quirk enables MakeMKV to properly exchange keys with
* an installed BD drive.
*/
UNUSUAL_DEV( 0x13fd, 0x3609, 0x0209, 0x0209,
"Initio Corporation",
"INIC-3619",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
/* Reported by Qinglin Ye <yestyle@gmail.com> */ /* Reported by Qinglin Ye <yestyle@gmail.com> */
UNUSUAL_DEV( 0x13fe, 0x3600, 0x0100, 0x0100, UNUSUAL_DEV( 0x13fe, 0x3600, 0x0100, 0x0100,
"Kingston", "Kingston",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册