Commit ce20d7bf authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-5.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb into master

Pull USB fixes from Greg KH:
 "Here are a few small USB fixes, and one thunderbolt fix, for 5.8-rc6.

  Nothing huge in here, just the normal collection of gadget, dwc2/3,
  serial, and other minor USB driver fixes and id additions. Full
  details are in the shortlog.

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

* tag 'usb-5.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  USB: serial: iuu_phoenix: fix memory corruption
  USB: c67x00: fix use after free in c67x00_giveback_urb
  usb: gadget: function: fix missing spinlock in f_uac1_legacy
  usb: gadget: udc: atmel: fix uninitialized read in debug printk
  usb: gadget: udc: atmel: remove outdated comment in usba_ep_disable()
  usb: dwc2: Fix shutdown callback in platform
  usb: cdns3: trace: fix some endian issues
  usb: cdns3: ep0: fix some endian issues
  usb: gadget: udc: gr_udc: fix memleak on error handling path in gr_ep_init()
  usb: gadget: fix langid kernel-doc warning in usbstring.c
  usb: dwc3: pci: add support for the Intel Jasper Lake
  usb: dwc3: pci: add support for the Intel Tiger Lake PCH -H variant
  usb: chipidea: core: add wakeup support for extcon
  USB: serial: option: add Quectel EG95 LTE modem
  thunderbolt: Fix path indices used in USB3 tunnel discovery
  USB: serial: ch341: add new Product ID for CH340
  USB: serial: option: add GosunCn GM500 series
  USB: serial: cypress_m8: enable Simply Automated UPB PIM
parents 8c18fc63 c7300cdf
...@@ -913,21 +913,21 @@ struct tb_tunnel *tb_tunnel_discover_usb3(struct tb *tb, struct tb_port *down) ...@@ -913,21 +913,21 @@ struct tb_tunnel *tb_tunnel_discover_usb3(struct tb *tb, struct tb_port *down)
* case. * case.
*/ */
path = tb_path_discover(down, TB_USB3_HOPID, NULL, -1, path = tb_path_discover(down, TB_USB3_HOPID, NULL, -1,
&tunnel->dst_port, "USB3 Up"); &tunnel->dst_port, "USB3 Down");
if (!path) { if (!path) {
/* Just disable the downstream port */ /* Just disable the downstream port */
tb_usb3_port_enable(down, false); tb_usb3_port_enable(down, false);
goto err_free; goto err_free;
} }
tunnel->paths[TB_USB3_PATH_UP] = path; tunnel->paths[TB_USB3_PATH_DOWN] = path;
tb_usb3_init_path(tunnel->paths[TB_USB3_PATH_UP]); tb_usb3_init_path(tunnel->paths[TB_USB3_PATH_DOWN]);
path = tb_path_discover(tunnel->dst_port, -1, down, TB_USB3_HOPID, NULL, path = tb_path_discover(tunnel->dst_port, -1, down, TB_USB3_HOPID, NULL,
"USB3 Down"); "USB3 Up");
if (!path) if (!path)
goto err_deactivate; goto err_deactivate;
tunnel->paths[TB_USB3_PATH_DOWN] = path; tunnel->paths[TB_USB3_PATH_UP] = path;
tb_usb3_init_path(tunnel->paths[TB_USB3_PATH_DOWN]); tb_usb3_init_path(tunnel->paths[TB_USB3_PATH_UP]);
/* Validate that the tunnel is complete */ /* Validate that the tunnel is complete */
if (!tb_port_is_usb3_up(tunnel->dst_port)) { if (!tb_port_is_usb3_up(tunnel->dst_port)) {
......
...@@ -486,7 +486,7 @@ c67x00_giveback_urb(struct c67x00_hcd *c67x00, struct urb *urb, int status) ...@@ -486,7 +486,7 @@ c67x00_giveback_urb(struct c67x00_hcd *c67x00, struct urb *urb, int status)
c67x00_release_urb(c67x00, urb); c67x00_release_urb(c67x00, urb);
usb_hcd_unlink_urb_from_ep(c67x00_hcd_to_hcd(c67x00), urb); usb_hcd_unlink_urb_from_ep(c67x00_hcd_to_hcd(c67x00), urb);
spin_unlock(&c67x00->lock); spin_unlock(&c67x00->lock);
usb_hcd_giveback_urb(c67x00_hcd_to_hcd(c67x00), urb, urbp->status); usb_hcd_giveback_urb(c67x00_hcd_to_hcd(c67x00), urb, status);
spin_lock(&c67x00->lock); spin_lock(&c67x00->lock);
} }
......
...@@ -37,18 +37,18 @@ static void cdns3_ep0_run_transfer(struct cdns3_device *priv_dev, ...@@ -37,18 +37,18 @@ static void cdns3_ep0_run_transfer(struct cdns3_device *priv_dev,
struct cdns3_usb_regs __iomem *regs = priv_dev->regs; struct cdns3_usb_regs __iomem *regs = priv_dev->regs;
struct cdns3_endpoint *priv_ep = priv_dev->eps[0]; struct cdns3_endpoint *priv_ep = priv_dev->eps[0];
priv_ep->trb_pool[0].buffer = TRB_BUFFER(dma_addr); priv_ep->trb_pool[0].buffer = cpu_to_le32(TRB_BUFFER(dma_addr));
priv_ep->trb_pool[0].length = TRB_LEN(length); priv_ep->trb_pool[0].length = cpu_to_le32(TRB_LEN(length));
if (zlp) { if (zlp) {
priv_ep->trb_pool[0].control = TRB_CYCLE | TRB_TYPE(TRB_NORMAL); priv_ep->trb_pool[0].control = cpu_to_le32(TRB_CYCLE | TRB_TYPE(TRB_NORMAL));
priv_ep->trb_pool[1].buffer = TRB_BUFFER(dma_addr); priv_ep->trb_pool[1].buffer = cpu_to_le32(TRB_BUFFER(dma_addr));
priv_ep->trb_pool[1].length = TRB_LEN(0); priv_ep->trb_pool[1].length = cpu_to_le32(TRB_LEN(0));
priv_ep->trb_pool[1].control = TRB_CYCLE | TRB_IOC | priv_ep->trb_pool[1].control = cpu_to_le32(TRB_CYCLE | TRB_IOC |
TRB_TYPE(TRB_NORMAL); TRB_TYPE(TRB_NORMAL));
} else { } else {
priv_ep->trb_pool[0].control = TRB_CYCLE | TRB_IOC | priv_ep->trb_pool[0].control = cpu_to_le32(TRB_CYCLE | TRB_IOC |
TRB_TYPE(TRB_NORMAL); TRB_TYPE(TRB_NORMAL));
priv_ep->trb_pool[1].control = 0; priv_ep->trb_pool[1].control = 0;
} }
...@@ -264,11 +264,11 @@ static int cdns3_req_ep0_get_status(struct cdns3_device *priv_dev, ...@@ -264,11 +264,11 @@ static int cdns3_req_ep0_get_status(struct cdns3_device *priv_dev,
case USB_RECIP_INTERFACE: case USB_RECIP_INTERFACE:
return cdns3_ep0_delegate_req(priv_dev, ctrl); return cdns3_ep0_delegate_req(priv_dev, ctrl);
case USB_RECIP_ENDPOINT: case USB_RECIP_ENDPOINT:
index = cdns3_ep_addr_to_index(ctrl->wIndex); index = cdns3_ep_addr_to_index(le16_to_cpu(ctrl->wIndex));
priv_ep = priv_dev->eps[index]; priv_ep = priv_dev->eps[index];
/* check if endpoint is stalled or stall is pending */ /* check if endpoint is stalled or stall is pending */
cdns3_select_ep(priv_dev, ctrl->wIndex); cdns3_select_ep(priv_dev, le16_to_cpu(ctrl->wIndex));
if (EP_STS_STALL(readl(&priv_dev->regs->ep_sts)) || if (EP_STS_STALL(readl(&priv_dev->regs->ep_sts)) ||
(priv_ep->flags & EP_STALL_PENDING)) (priv_ep->flags & EP_STALL_PENDING))
usb_status = BIT(USB_ENDPOINT_HALT); usb_status = BIT(USB_ENDPOINT_HALT);
...@@ -381,10 +381,10 @@ static int cdns3_ep0_feature_handle_endpoint(struct cdns3_device *priv_dev, ...@@ -381,10 +381,10 @@ static int cdns3_ep0_feature_handle_endpoint(struct cdns3_device *priv_dev,
if (!(ctrl->wIndex & ~USB_DIR_IN)) if (!(ctrl->wIndex & ~USB_DIR_IN))
return 0; return 0;
index = cdns3_ep_addr_to_index(ctrl->wIndex); index = cdns3_ep_addr_to_index(le16_to_cpu(ctrl->wIndex));
priv_ep = priv_dev->eps[index]; priv_ep = priv_dev->eps[index];
cdns3_select_ep(priv_dev, ctrl->wIndex); cdns3_select_ep(priv_dev, le16_to_cpu(ctrl->wIndex));
if (set) if (set)
__cdns3_gadget_ep_set_halt(priv_ep); __cdns3_gadget_ep_set_halt(priv_ep);
...@@ -445,7 +445,7 @@ static int cdns3_req_ep0_set_sel(struct cdns3_device *priv_dev, ...@@ -445,7 +445,7 @@ static int cdns3_req_ep0_set_sel(struct cdns3_device *priv_dev,
if (priv_dev->gadget.state < USB_STATE_ADDRESS) if (priv_dev->gadget.state < USB_STATE_ADDRESS)
return -EINVAL; return -EINVAL;
if (ctrl_req->wLength != 6) { if (le16_to_cpu(ctrl_req->wLength) != 6) {
dev_err(priv_dev->dev, "Set SEL should be 6 bytes, got %d\n", dev_err(priv_dev->dev, "Set SEL should be 6 bytes, got %d\n",
ctrl_req->wLength); ctrl_req->wLength);
return -EINVAL; return -EINVAL;
...@@ -469,7 +469,7 @@ static int cdns3_req_ep0_set_isoch_delay(struct cdns3_device *priv_dev, ...@@ -469,7 +469,7 @@ static int cdns3_req_ep0_set_isoch_delay(struct cdns3_device *priv_dev,
if (ctrl_req->wIndex || ctrl_req->wLength) if (ctrl_req->wIndex || ctrl_req->wLength)
return -EINVAL; return -EINVAL;
priv_dev->isoch_delay = ctrl_req->wValue; priv_dev->isoch_delay = le16_to_cpu(ctrl_req->wValue);
return 0; return 0;
} }
......
...@@ -404,9 +404,9 @@ DECLARE_EVENT_CLASS(cdns3_log_trb, ...@@ -404,9 +404,9 @@ DECLARE_EVENT_CLASS(cdns3_log_trb,
TP_fast_assign( TP_fast_assign(
__assign_str(name, priv_ep->name); __assign_str(name, priv_ep->name);
__entry->trb = trb; __entry->trb = trb;
__entry->buffer = trb->buffer; __entry->buffer = le32_to_cpu(trb->buffer);
__entry->length = trb->length; __entry->length = le32_to_cpu(trb->length);
__entry->control = trb->control; __entry->control = le32_to_cpu(trb->control);
__entry->type = usb_endpoint_type(priv_ep->endpoint.desc); __entry->type = usb_endpoint_type(priv_ep->endpoint.desc);
__entry->last_stream_id = priv_ep->last_stream_id; __entry->last_stream_id = priv_ep->last_stream_id;
), ),
......
...@@ -1243,6 +1243,29 @@ static void ci_controller_suspend(struct ci_hdrc *ci) ...@@ -1243,6 +1243,29 @@ static void ci_controller_suspend(struct ci_hdrc *ci)
enable_irq(ci->irq); enable_irq(ci->irq);
} }
/*
* Handle the wakeup interrupt triggered by extcon connector
* We need to call ci_irq again for extcon since the first
* interrupt (wakeup int) only let the controller be out of
* low power mode, but not handle any interrupts.
*/
static void ci_extcon_wakeup_int(struct ci_hdrc *ci)
{
struct ci_hdrc_cable *cable_id, *cable_vbus;
u32 otgsc = hw_read_otgsc(ci, ~0);
cable_id = &ci->platdata->id_extcon;
cable_vbus = &ci->platdata->vbus_extcon;
if (!IS_ERR(cable_id->edev) && ci->is_otg &&
(otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS))
ci_irq(ci->irq, ci);
if (!IS_ERR(cable_vbus->edev) && ci->is_otg &&
(otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS))
ci_irq(ci->irq, ci);
}
static int ci_controller_resume(struct device *dev) static int ci_controller_resume(struct device *dev)
{ {
struct ci_hdrc *ci = dev_get_drvdata(dev); struct ci_hdrc *ci = dev_get_drvdata(dev);
...@@ -1275,6 +1298,7 @@ static int ci_controller_resume(struct device *dev) ...@@ -1275,6 +1298,7 @@ static int ci_controller_resume(struct device *dev)
enable_irq(ci->irq); enable_irq(ci->irq);
if (ci_otg_is_fsm_mode(ci)) if (ci_otg_is_fsm_mode(ci))
ci_otg_fsm_wakeup_by_srp(ci); ci_otg_fsm_wakeup_by_srp(ci);
ci_extcon_wakeup_int(ci);
} }
return 0; return 0;
......
...@@ -342,7 +342,8 @@ static void dwc2_driver_shutdown(struct platform_device *dev) ...@@ -342,7 +342,8 @@ static void dwc2_driver_shutdown(struct platform_device *dev)
{ {
struct dwc2_hsotg *hsotg = platform_get_drvdata(dev); struct dwc2_hsotg *hsotg = platform_get_drvdata(dev);
disable_irq(hsotg->irq); dwc2_disable_global_interrupts(hsotg);
synchronize_irq(hsotg->irq);
} }
/** /**
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#define PCI_DEVICE_ID_INTEL_ICLLP 0x34ee #define PCI_DEVICE_ID_INTEL_ICLLP 0x34ee
#define PCI_DEVICE_ID_INTEL_EHLLP 0x4b7e #define PCI_DEVICE_ID_INTEL_EHLLP 0x4b7e
#define PCI_DEVICE_ID_INTEL_TGPLP 0xa0ee #define PCI_DEVICE_ID_INTEL_TGPLP 0xa0ee
#define PCI_DEVICE_ID_INTEL_TGPH 0x43ee
#define PCI_DEVICE_ID_INTEL_JSP 0x4dee
#define PCI_INTEL_BXT_DSM_GUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511" #define PCI_INTEL_BXT_DSM_GUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
#define PCI_INTEL_BXT_FUNC_PMU_PWR 4 #define PCI_INTEL_BXT_FUNC_PMU_PWR 4
...@@ -358,6 +360,12 @@ static const struct pci_device_id dwc3_pci_id_table[] = { ...@@ -358,6 +360,12 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGPLP), { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGPLP),
(kernel_ulong_t) &dwc3_pci_intel_properties, }, (kernel_ulong_t) &dwc3_pci_intel_properties, },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGPH),
(kernel_ulong_t) &dwc3_pci_intel_properties, },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_JSP),
(kernel_ulong_t) &dwc3_pci_intel_properties, },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_NL_USB), { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_NL_USB),
(kernel_ulong_t) &dwc3_pci_amd_properties, }, (kernel_ulong_t) &dwc3_pci_amd_properties, },
{ } /* Terminating Entry */ { } /* Terminating Entry */
......
...@@ -336,7 +336,9 @@ static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -336,7 +336,9 @@ static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
/* Copy buffer is full, add it to the play_queue */ /* Copy buffer is full, add it to the play_queue */
if (audio_buf_size - copy_buf->actual < req->actual) { if (audio_buf_size - copy_buf->actual < req->actual) {
spin_lock_irq(&audio->lock);
list_add_tail(&copy_buf->list, &audio->play_queue); list_add_tail(&copy_buf->list, &audio->play_queue);
spin_unlock_irq(&audio->lock);
schedule_work(&audio->playback_work); schedule_work(&audio->playback_work);
copy_buf = f_audio_buffer_alloc(audio_buf_size); copy_buf = f_audio_buffer_alloc(audio_buf_size);
if (IS_ERR(copy_buf)) if (IS_ERR(copy_buf))
......
...@@ -676,13 +676,7 @@ static int usba_ep_disable(struct usb_ep *_ep) ...@@ -676,13 +676,7 @@ static int usba_ep_disable(struct usb_ep *_ep)
if (!ep->ep.desc) { if (!ep->ep.desc) {
spin_unlock_irqrestore(&udc->lock, flags); spin_unlock_irqrestore(&udc->lock, flags);
/* REVISIT because this driver disables endpoints in DBG(DBG_ERR, "ep_disable: %s not enabled\n", ep->ep.name);
* reset_all_endpoints() before calling disconnect(),
* most gadget drivers would trigger this non-error ...
*/
if (udc->gadget.speed != USB_SPEED_UNKNOWN)
DBG(DBG_ERR, "ep_disable: %s not enabled\n",
ep->ep.name);
return -EINVAL; return -EINVAL;
} }
ep->ep.desc = NULL; ep->ep.desc = NULL;
...@@ -871,7 +865,7 @@ static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) ...@@ -871,7 +865,7 @@ static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
u32 status; u32 status;
DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n", DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n",
ep->ep.name, req); ep->ep.name, _req);
spin_lock_irqsave(&udc->lock, flags); spin_lock_irqsave(&udc->lock, flags);
......
...@@ -1980,9 +1980,12 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit) ...@@ -1980,9 +1980,12 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
if (num == 0) { if (num == 0) {
_req = gr_alloc_request(&ep->ep, GFP_ATOMIC); _req = gr_alloc_request(&ep->ep, GFP_ATOMIC);
if (!_req)
return -ENOMEM;
buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_ATOMIC); buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_ATOMIC);
if (!_req || !buf) { if (!buf) {
/* possible _req freed by gr_probe via gr_remove */ gr_free_request(&ep->ep, _req);
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -68,7 +68,7 @@ EXPORT_SYMBOL_GPL(usb_gadget_get_string); ...@@ -68,7 +68,7 @@ EXPORT_SYMBOL_GPL(usb_gadget_get_string);
/** /**
* usb_validate_langid - validate usb language identifiers * usb_validate_langid - validate usb language identifiers
* @lang: usb language identifier * @langid: usb language identifier
* *
* Returns true for valid language identifier, otherwise false. * Returns true for valid language identifier, otherwise false.
*/ */
......
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
static const struct usb_device_id id_table[] = { static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x4348, 0x5523) }, { USB_DEVICE(0x4348, 0x5523) },
{ USB_DEVICE(0x1a86, 0x7522) },
{ USB_DEVICE(0x1a86, 0x7523) }, { USB_DEVICE(0x1a86, 0x7523) },
{ USB_DEVICE(0x1a86, 0x5523) }, { USB_DEVICE(0x1a86, 0x5523) },
{ }, { },
......
...@@ -59,6 +59,7 @@ static const struct usb_device_id id_table_earthmate[] = { ...@@ -59,6 +59,7 @@ static const struct usb_device_id id_table_earthmate[] = {
static const struct usb_device_id id_table_cyphidcomrs232[] = { static const struct usb_device_id id_table_cyphidcomrs232[] = {
{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) }, { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
{ USB_DEVICE(VENDOR_ID_SAI, PRODUCT_ID_CYPHIDCOM) },
{ USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) }, { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
{ USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) }, { USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) },
{ } /* Terminating entry */ { } /* Terminating entry */
...@@ -73,6 +74,7 @@ static const struct usb_device_id id_table_combined[] = { ...@@ -73,6 +74,7 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) }, { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) }, { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) }, { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
{ USB_DEVICE(VENDOR_ID_SAI, PRODUCT_ID_CYPHIDCOM) },
{ USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) }, { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
{ USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) }, { USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) },
{ USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) }, { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
#define VENDOR_ID_CYPRESS 0x04b4 #define VENDOR_ID_CYPRESS 0x04b4
#define PRODUCT_ID_CYPHIDCOM 0x5500 #define PRODUCT_ID_CYPHIDCOM 0x5500
/* Simply Automated HID->COM UPB PIM (using Cypress PID 0x5500) */
#define VENDOR_ID_SAI 0x17dd
/* FRWD Dongle - a GPS sports watch */ /* FRWD Dongle - a GPS sports watch */
#define VENDOR_ID_FRWD 0x6737 #define VENDOR_ID_FRWD 0x6737
#define PRODUCT_ID_CYPHIDCOM_FRWD 0x0001 #define PRODUCT_ID_CYPHIDCOM_FRWD 0x0001
......
...@@ -697,14 +697,16 @@ static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -697,14 +697,16 @@ static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port,
struct iuu_private *priv = usb_get_serial_port_data(port); struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long flags; unsigned long flags;
if (count > 256)
return -ENOMEM;
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
count = min(count, 256 - priv->writelen);
if (count == 0)
goto out;
/* fill the buffer */ /* fill the buffer */
memcpy(priv->writebuf + priv->writelen, buf, count); memcpy(priv->writebuf + priv->writelen, buf, count);
priv->writelen += count; priv->writelen += count;
out:
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
return count; return count;
......
...@@ -245,6 +245,7 @@ static void option_instat_callback(struct urb *urb); ...@@ -245,6 +245,7 @@ static void option_instat_callback(struct urb *urb);
/* These Quectel products use Quectel's vendor ID */ /* These Quectel products use Quectel's vendor ID */
#define QUECTEL_PRODUCT_EC21 0x0121 #define QUECTEL_PRODUCT_EC21 0x0121
#define QUECTEL_PRODUCT_EC25 0x0125 #define QUECTEL_PRODUCT_EC25 0x0125
#define QUECTEL_PRODUCT_EG95 0x0195
#define QUECTEL_PRODUCT_BG96 0x0296 #define QUECTEL_PRODUCT_BG96 0x0296
#define QUECTEL_PRODUCT_EP06 0x0306 #define QUECTEL_PRODUCT_EP06 0x0306
#define QUECTEL_PRODUCT_EM12 0x0512 #define QUECTEL_PRODUCT_EM12 0x0512
...@@ -1097,6 +1098,8 @@ static const struct usb_device_id option_ids[] = { ...@@ -1097,6 +1098,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(4) }, .driver_info = RSVD(4) },
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25), { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25),
.driver_info = RSVD(4) }, .driver_info = RSVD(4) },
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95),
.driver_info = RSVD(4) },
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
.driver_info = RSVD(4) }, .driver_info = RSVD(4) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff), { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
...@@ -2028,6 +2031,9 @@ static const struct usb_device_id option_ids[] = { ...@@ -2028,6 +2031,9 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(4) | RSVD(5) }, .driver_info = RSVD(4) | RSVD(5) },
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */
.driver_info = RSVD(6) }, .driver_info = RSVD(6) },
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, option_ids); MODULE_DEVICE_TABLE(usb, option_ids);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment