Commit 6a655547 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull USB driver fixes from Greg KH:
 "Here are some small USB driver fixes for 5.14-rc5. They resolve a
  number of small reported issues, including:

   - cdnsp driver fixes

   - usb serial driver fixes and device id updates

   - usb gadget hid fixes

   - usb host driver fixes

   - usb dwc3 driver fixes

   - other usb gadget driver fixes

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

* tag 'usb-5.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (21 commits)
  usb: typec: tcpm: Keep other events when receiving FRS and Sourcing_vbus events
  usb: dwc3: gadget: Avoid runtime resume if disabling pullup
  usb: dwc3: gadget: Use list_replace_init() before traversing lists
  USB: serial: ftdi_sio: add device ID for Auto-M3 OP-COM v2
  USB: serial: pl2303: fix GT type detection
  USB: serial: option: add Telit FD980 composition 0x1056
  USB: serial: pl2303: fix HX type detection
  USB: serial: ch341: fix character loss at high transfer rates
  usb: cdnsp: Fix the IMAN_IE_SET and IMAN_IE_CLEAR macro
  usb: cdnsp: Fixed issue with ZLP
  usb: cdnsp: Fix incorrect supported maximum speed
  usb: cdns3: Fixed incorrect gadget state
  usb: gadget: f_hid: idle uses the highest byte for duration
  Revert "thunderbolt: Hide authorized attribute if router does not support PCIe tunnels"
  usb: otg-fsm: Fix hrtimer list corruption
  usb: host: ohci-at91: suspend/resume ports after/before OHCI accesses
  usb: musb: Fix suspend and resume issues for PHYs on I2C and SPI
  usb: gadget: f_hid: added GET_IDLE and SET_IDLE handlers
  usb: gadget: f_hid: fixed NULL pointer dereference
  usb: gadget: remove leaked entry from udc driver list
  ...
parents 85a90500 43ad944c
...@@ -1875,18 +1875,6 @@ static struct attribute *switch_attrs[] = { ...@@ -1875,18 +1875,6 @@ static struct attribute *switch_attrs[] = {
NULL, NULL,
}; };
static bool has_port(const struct tb_switch *sw, enum tb_port_type type)
{
const struct tb_port *port;
tb_switch_for_each_port(sw, port) {
if (!port->disabled && port->config.type == type)
return true;
}
return false;
}
static umode_t switch_attr_is_visible(struct kobject *kobj, static umode_t switch_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n) struct attribute *attr, int n)
{ {
...@@ -1895,8 +1883,7 @@ static umode_t switch_attr_is_visible(struct kobject *kobj, ...@@ -1895,8 +1883,7 @@ static umode_t switch_attr_is_visible(struct kobject *kobj,
if (attr == &dev_attr_authorized.attr) { if (attr == &dev_attr_authorized.attr) {
if (sw->tb->security_level == TB_SECURITY_NOPCIE || if (sw->tb->security_level == TB_SECURITY_NOPCIE ||
sw->tb->security_level == TB_SECURITY_DPONLY || sw->tb->security_level == TB_SECURITY_DPONLY)
!has_port(sw, TB_TYPE_PCIE_UP))
return 0; return 0;
} else if (attr == &dev_attr_device.attr) { } else if (attr == &dev_attr_device.attr) {
if (!sw->device) if (!sw->device)
......
...@@ -731,6 +731,7 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep, ...@@ -731,6 +731,7 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
request->actual = 0; request->actual = 0;
priv_dev->status_completion_no_call = true; priv_dev->status_completion_no_call = true;
priv_dev->pending_status_request = request; priv_dev->pending_status_request = request;
usb_gadget_set_state(&priv_dev->gadget, USB_STATE_CONFIGURED);
spin_unlock_irqrestore(&priv_dev->lock, flags); spin_unlock_irqrestore(&priv_dev->lock, flags);
/* /*
......
...@@ -1882,7 +1882,7 @@ static int __cdnsp_gadget_init(struct cdns *cdns) ...@@ -1882,7 +1882,7 @@ static int __cdnsp_gadget_init(struct cdns *cdns)
pdev->gadget.name = "cdnsp-gadget"; pdev->gadget.name = "cdnsp-gadget";
pdev->gadget.speed = USB_SPEED_UNKNOWN; pdev->gadget.speed = USB_SPEED_UNKNOWN;
pdev->gadget.sg_supported = 1; pdev->gadget.sg_supported = 1;
pdev->gadget.max_speed = USB_SPEED_SUPER_PLUS; pdev->gadget.max_speed = max_speed;
pdev->gadget.lpm_capable = 1; pdev->gadget.lpm_capable = 1;
pdev->setup_buf = kzalloc(CDNSP_EP0_SETUP_SIZE, GFP_KERNEL); pdev->setup_buf = kzalloc(CDNSP_EP0_SETUP_SIZE, GFP_KERNEL);
......
...@@ -383,8 +383,8 @@ struct cdnsp_intr_reg { ...@@ -383,8 +383,8 @@ struct cdnsp_intr_reg {
#define IMAN_IE BIT(1) #define IMAN_IE BIT(1)
#define IMAN_IP BIT(0) #define IMAN_IP BIT(0)
/* bits 2:31 need to be preserved */ /* bits 2:31 need to be preserved */
#define IMAN_IE_SET(p) (((p) & IMAN_IE) | 0x2) #define IMAN_IE_SET(p) ((p) | IMAN_IE)
#define IMAN_IE_CLEAR(p) (((p) & IMAN_IE) & ~(0x2)) #define IMAN_IE_CLEAR(p) ((p) & ~IMAN_IE)
/* IMOD - Interrupter Moderation Register - irq_control bitmasks. */ /* IMOD - Interrupter Moderation Register - irq_control bitmasks. */
/* /*
......
...@@ -1932,15 +1932,13 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq) ...@@ -1932,15 +1932,13 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
} }
if (enqd_len + trb_buff_len >= full_len) { if (enqd_len + trb_buff_len >= full_len) {
if (need_zero_pkt && zero_len_trb) { if (need_zero_pkt)
zero_len_trb = true; zero_len_trb = !zero_len_trb;
} else {
field &= ~TRB_CHAIN; field &= ~TRB_CHAIN;
field |= TRB_IOC; field |= TRB_IOC;
more_trbs_coming = false; more_trbs_coming = false;
need_zero_pkt = false; preq->td.last_trb = ring->enqueue;
preq->td.last_trb = ring->enqueue;
}
} }
/* Only set interrupt on short packet for OUT endpoints. */ /* Only set interrupt on short packet for OUT endpoints. */
...@@ -1955,7 +1953,7 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq) ...@@ -1955,7 +1953,7 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
length_field = TRB_LEN(trb_buff_len) | TRB_TD_SIZE(remainder) | length_field = TRB_LEN(trb_buff_len) | TRB_TD_SIZE(remainder) |
TRB_INTR_TARGET(0); TRB_INTR_TARGET(0);
cdnsp_queue_trb(pdev, ring, more_trbs_coming | need_zero_pkt, cdnsp_queue_trb(pdev, ring, more_trbs_coming | zero_len_trb,
lower_32_bits(send_addr), lower_32_bits(send_addr),
upper_32_bits(send_addr), upper_32_bits(send_addr),
length_field, length_field,
......
...@@ -2324,17 +2324,10 @@ static void usbtmc_interrupt(struct urb *urb) ...@@ -2324,17 +2324,10 @@ static void usbtmc_interrupt(struct urb *urb)
dev_err(dev, "overflow with length %d, actual length is %d\n", dev_err(dev, "overflow with length %d, actual length is %d\n",
data->iin_wMaxPacketSize, urb->actual_length); data->iin_wMaxPacketSize, urb->actual_length);
fallthrough; fallthrough;
case -ECONNRESET: default:
case -ENOENT:
case -ESHUTDOWN:
case -EILSEQ:
case -ETIME:
case -EPIPE:
/* urb terminated, clean up */ /* urb terminated, clean up */
dev_dbg(dev, "urb terminated, status: %d\n", status); dev_dbg(dev, "urb terminated, status: %d\n", status);
return; return;
default:
dev_err(dev, "unknown status received: %d\n", status);
} }
exit: exit:
rv = usb_submit_urb(urb, GFP_ATOMIC); rv = usb_submit_urb(urb, GFP_ATOMIC);
......
...@@ -193,7 +193,11 @@ static void otg_start_hnp_polling(struct otg_fsm *fsm) ...@@ -193,7 +193,11 @@ static void otg_start_hnp_polling(struct otg_fsm *fsm)
if (!fsm->host_req_flag) if (!fsm->host_req_flag)
return; return;
INIT_DELAYED_WORK(&fsm->hnp_polling_work, otg_hnp_polling_work); if (!fsm->hnp_work_inited) {
INIT_DELAYED_WORK(&fsm->hnp_polling_work, otg_hnp_polling_work);
fsm->hnp_work_inited = true;
}
schedule_delayed_work(&fsm->hnp_polling_work, schedule_delayed_work(&fsm->hnp_polling_work,
msecs_to_jiffies(T_HOST_REQ_POLL)); msecs_to_jiffies(T_HOST_REQ_POLL));
} }
......
...@@ -1741,9 +1741,13 @@ static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep) ...@@ -1741,9 +1741,13 @@ static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep)
{ {
struct dwc3_request *req; struct dwc3_request *req;
struct dwc3_request *tmp; struct dwc3_request *tmp;
struct list_head local;
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
list_for_each_entry_safe(req, tmp, &dep->cancelled_list, list) { restart:
list_replace_init(&dep->cancelled_list, &local);
list_for_each_entry_safe(req, tmp, &local, list) {
dwc3_gadget_ep_skip_trbs(dep, req); dwc3_gadget_ep_skip_trbs(dep, req);
switch (req->status) { switch (req->status) {
case DWC3_REQUEST_STATUS_DISCONNECTED: case DWC3_REQUEST_STATUS_DISCONNECTED:
...@@ -1761,6 +1765,9 @@ static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep) ...@@ -1761,6 +1765,9 @@ static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep)
break; break;
} }
} }
if (!list_empty(&dep->cancelled_list))
goto restart;
} }
static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
...@@ -2249,6 +2256,17 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) ...@@ -2249,6 +2256,17 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
} }
} }
/*
* Avoid issuing a runtime resume if the device is already in the
* suspended state during gadget disconnect. DWC3 gadget was already
* halted/stopped during runtime suspend.
*/
if (!is_on) {
pm_runtime_barrier(dwc->dev);
if (pm_runtime_suspended(dwc->dev))
return 0;
}
/* /*
* Check the return value for successful resume, or error. For a * Check the return value for successful resume, or error. For a
* successful resume, the DWC3 runtime PM resume routine will handle * successful resume, the DWC3 runtime PM resume routine will handle
...@@ -2958,8 +2976,12 @@ static void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep, ...@@ -2958,8 +2976,12 @@ static void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep,
{ {
struct dwc3_request *req; struct dwc3_request *req;
struct dwc3_request *tmp; struct dwc3_request *tmp;
struct list_head local;
list_for_each_entry_safe(req, tmp, &dep->started_list, list) { restart:
list_replace_init(&dep->started_list, &local);
list_for_each_entry_safe(req, tmp, &local, list) {
int ret; int ret;
ret = dwc3_gadget_ep_cleanup_completed_request(dep, event, ret = dwc3_gadget_ep_cleanup_completed_request(dep, event,
...@@ -2967,6 +2989,9 @@ static void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep, ...@@ -2967,6 +2989,9 @@ static void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep,
if (ret) if (ret)
break; break;
} }
if (!list_empty(&dep->started_list))
goto restart;
} }
static bool dwc3_gadget_ep_should_continue(struct dwc3_ep *dep) static bool dwc3_gadget_ep_should_continue(struct dwc3_ep *dep)
......
...@@ -41,6 +41,7 @@ struct f_hidg { ...@@ -41,6 +41,7 @@ struct f_hidg {
unsigned char bInterfaceSubClass; unsigned char bInterfaceSubClass;
unsigned char bInterfaceProtocol; unsigned char bInterfaceProtocol;
unsigned char protocol; unsigned char protocol;
unsigned char idle;
unsigned short report_desc_length; unsigned short report_desc_length;
char *report_desc; char *report_desc;
unsigned short report_length; unsigned short report_length;
...@@ -338,6 +339,11 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, ...@@ -338,6 +339,11 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
spin_lock_irqsave(&hidg->write_spinlock, flags); spin_lock_irqsave(&hidg->write_spinlock, flags);
if (!hidg->req) {
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
return -ESHUTDOWN;
}
#define WRITE_COND (!hidg->write_pending) #define WRITE_COND (!hidg->write_pending)
try_again: try_again:
/* write queue */ /* write queue */
...@@ -358,8 +364,14 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, ...@@ -358,8 +364,14 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
count = min_t(unsigned, count, hidg->report_length); count = min_t(unsigned, count, hidg->report_length);
spin_unlock_irqrestore(&hidg->write_spinlock, flags); spin_unlock_irqrestore(&hidg->write_spinlock, flags);
status = copy_from_user(req->buf, buffer, count);
if (!req) {
ERROR(hidg->func.config->cdev, "hidg->req is NULL\n");
status = -ESHUTDOWN;
goto release_write_pending;
}
status = copy_from_user(req->buf, buffer, count);
if (status != 0) { if (status != 0) {
ERROR(hidg->func.config->cdev, ERROR(hidg->func.config->cdev,
"copy_from_user error\n"); "copy_from_user error\n");
...@@ -387,14 +399,17 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, ...@@ -387,14 +399,17 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
spin_unlock_irqrestore(&hidg->write_spinlock, flags); spin_unlock_irqrestore(&hidg->write_spinlock, flags);
if (!hidg->in_ep->enabled) {
ERROR(hidg->func.config->cdev, "in_ep is disabled\n");
status = -ESHUTDOWN;
goto release_write_pending;
}
status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC); status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
if (status < 0) { if (status < 0)
ERROR(hidg->func.config->cdev,
"usb_ep_queue error on int endpoint %zd\n", status);
goto release_write_pending; goto release_write_pending;
} else { else
status = count; status = count;
}
return status; return status;
release_write_pending: release_write_pending:
...@@ -523,6 +538,14 @@ static int hidg_setup(struct usb_function *f, ...@@ -523,6 +538,14 @@ static int hidg_setup(struct usb_function *f,
goto respond; goto respond;
break; break;
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_GET_IDLE):
VDBG(cdev, "get_idle\n");
length = min_t(unsigned int, length, 1);
((u8 *) req->buf)[0] = hidg->idle;
goto respond;
break;
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_SET_REPORT): | HID_REQ_SET_REPORT):
VDBG(cdev, "set_report | wLength=%d\n", ctrl->wLength); VDBG(cdev, "set_report | wLength=%d\n", ctrl->wLength);
...@@ -546,6 +569,14 @@ static int hidg_setup(struct usb_function *f, ...@@ -546,6 +569,14 @@ static int hidg_setup(struct usb_function *f,
goto stall; goto stall;
break; break;
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
| HID_REQ_SET_IDLE):
VDBG(cdev, "set_idle\n");
length = 0;
hidg->idle = value >> 8;
goto respond;
break;
case ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8 case ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8
| USB_REQ_GET_DESCRIPTOR): | USB_REQ_GET_DESCRIPTOR):
switch (value >> 8) { switch (value >> 8) {
...@@ -773,6 +804,7 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -773,6 +804,7 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass; hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol; hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
hidg->protocol = HID_REPORT_PROTOCOL; hidg->protocol = HID_REPORT_PROTOCOL;
hidg->idle = 1;
hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length); hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_ss_in_comp_desc.wBytesPerInterval = hidg_ss_in_comp_desc.wBytesPerInterval =
cpu_to_le16(hidg->report_length); cpu_to_le16(hidg->report_length);
......
...@@ -1255,12 +1255,14 @@ static int max3420_probe(struct spi_device *spi) ...@@ -1255,12 +1255,14 @@ static int max3420_probe(struct spi_device *spi)
err = devm_request_irq(&spi->dev, irq, max3420_irq_handler, 0, err = devm_request_irq(&spi->dev, irq, max3420_irq_handler, 0,
"max3420", udc); "max3420", udc);
if (err < 0) if (err < 0)
return err; goto del_gadget;
udc->thread_task = kthread_create(max3420_thread, udc, udc->thread_task = kthread_create(max3420_thread, udc,
"max3420-thread"); "max3420-thread");
if (IS_ERR(udc->thread_task)) if (IS_ERR(udc->thread_task)) {
return PTR_ERR(udc->thread_task); err = PTR_ERR(udc->thread_task);
goto del_gadget;
}
irq = of_irq_get_byname(spi->dev.of_node, "vbus"); irq = of_irq_get_byname(spi->dev.of_node, "vbus");
if (irq <= 0) { /* no vbus irq implies self-powered design */ if (irq <= 0) { /* no vbus irq implies self-powered design */
...@@ -1280,10 +1282,14 @@ static int max3420_probe(struct spi_device *spi) ...@@ -1280,10 +1282,14 @@ static int max3420_probe(struct spi_device *spi)
err = devm_request_irq(&spi->dev, irq, err = devm_request_irq(&spi->dev, irq,
max3420_vbus_handler, 0, "vbus", udc); max3420_vbus_handler, 0, "vbus", udc);
if (err < 0) if (err < 0)
return err; goto del_gadget;
} }
return 0; return 0;
del_gadget:
usb_del_gadget_udc(&udc->gadget);
return err;
} }
static int max3420_remove(struct spi_device *spi) static int max3420_remove(struct spi_device *spi)
......
...@@ -611,8 +611,6 @@ ohci_hcd_at91_drv_suspend(struct device *dev) ...@@ -611,8 +611,6 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
if (ohci_at91->wakeup) if (ohci_at91->wakeup)
enable_irq_wake(hcd->irq); enable_irq_wake(hcd->irq);
ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1);
ret = ohci_suspend(hcd, ohci_at91->wakeup); ret = ohci_suspend(hcd, ohci_at91->wakeup);
if (ret) { if (ret) {
if (ohci_at91->wakeup) if (ohci_at91->wakeup)
...@@ -632,7 +630,10 @@ ohci_hcd_at91_drv_suspend(struct device *dev) ...@@ -632,7 +630,10 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
/* flush the writes */ /* flush the writes */
(void) ohci_readl (ohci, &ohci->regs->control); (void) ohci_readl (ohci, &ohci->regs->control);
msleep(1); msleep(1);
ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1);
at91_stop_clock(ohci_at91); at91_stop_clock(ohci_at91);
} else {
ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1);
} }
return ret; return ret;
...@@ -644,6 +645,8 @@ ohci_hcd_at91_drv_resume(struct device *dev) ...@@ -644,6 +645,8 @@ ohci_hcd_at91_drv_resume(struct device *dev)
struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_hcd *hcd = dev_get_drvdata(dev);
struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd); struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd);
ohci_at91_port_suspend(ohci_at91->sfr_regmap, 0);
if (ohci_at91->wakeup) if (ohci_at91->wakeup)
disable_irq_wake(hcd->irq); disable_irq_wake(hcd->irq);
else else
...@@ -651,8 +654,6 @@ ohci_hcd_at91_drv_resume(struct device *dev) ...@@ -651,8 +654,6 @@ ohci_hcd_at91_drv_resume(struct device *dev)
ohci_resume(hcd, false); ohci_resume(hcd, false);
ohci_at91_port_suspend(ohci_at91->sfr_regmap, 0);
return 0; return 0;
} }
......
...@@ -35,6 +35,7 @@ struct omap2430_glue { ...@@ -35,6 +35,7 @@ struct omap2430_glue {
struct device *control_otghs; struct device *control_otghs;
unsigned int is_runtime_suspended:1; unsigned int is_runtime_suspended:1;
unsigned int needs_resume:1; unsigned int needs_resume:1;
unsigned int phy_suspended:1;
}; };
#define glue_to_musb(g) platform_get_drvdata(g->musb) #define glue_to_musb(g) platform_get_drvdata(g->musb)
...@@ -458,8 +459,10 @@ static int omap2430_runtime_suspend(struct device *dev) ...@@ -458,8 +459,10 @@ static int omap2430_runtime_suspend(struct device *dev)
omap2430_low_level_exit(musb); omap2430_low_level_exit(musb);
phy_power_off(musb->phy); if (!glue->phy_suspended) {
phy_exit(musb->phy); phy_power_off(musb->phy);
phy_exit(musb->phy);
}
glue->is_runtime_suspended = 1; glue->is_runtime_suspended = 1;
...@@ -474,8 +477,10 @@ static int omap2430_runtime_resume(struct device *dev) ...@@ -474,8 +477,10 @@ static int omap2430_runtime_resume(struct device *dev)
if (!musb) if (!musb)
return 0; return 0;
phy_init(musb->phy); if (!glue->phy_suspended) {
phy_power_on(musb->phy); phy_init(musb->phy);
phy_power_on(musb->phy);
}
omap2430_low_level_init(musb); omap2430_low_level_init(musb);
musb_writel(musb->mregs, OTG_INTERFSEL, musb_writel(musb->mregs, OTG_INTERFSEL,
...@@ -489,7 +494,21 @@ static int omap2430_runtime_resume(struct device *dev) ...@@ -489,7 +494,21 @@ static int omap2430_runtime_resume(struct device *dev)
return 0; return 0;
} }
/* I2C and SPI PHYs need to be suspended before the glue layer */
static int omap2430_suspend(struct device *dev) static int omap2430_suspend(struct device *dev)
{
struct omap2430_glue *glue = dev_get_drvdata(dev);
struct musb *musb = glue_to_musb(glue);
phy_power_off(musb->phy);
phy_exit(musb->phy);
glue->phy_suspended = 1;
return 0;
}
/* Glue layer needs to be suspended after musb_suspend() */
static int omap2430_suspend_late(struct device *dev)
{ {
struct omap2430_glue *glue = dev_get_drvdata(dev); struct omap2430_glue *glue = dev_get_drvdata(dev);
...@@ -501,7 +520,7 @@ static int omap2430_suspend(struct device *dev) ...@@ -501,7 +520,7 @@ static int omap2430_suspend(struct device *dev)
return omap2430_runtime_suspend(dev); return omap2430_runtime_suspend(dev);
} }
static int omap2430_resume(struct device *dev) static int omap2430_resume_early(struct device *dev)
{ {
struct omap2430_glue *glue = dev_get_drvdata(dev); struct omap2430_glue *glue = dev_get_drvdata(dev);
...@@ -513,10 +532,24 @@ static int omap2430_resume(struct device *dev) ...@@ -513,10 +532,24 @@ static int omap2430_resume(struct device *dev)
return omap2430_runtime_resume(dev); return omap2430_runtime_resume(dev);
} }
static int omap2430_resume(struct device *dev)
{
struct omap2430_glue *glue = dev_get_drvdata(dev);
struct musb *musb = glue_to_musb(glue);
phy_init(musb->phy);
phy_power_on(musb->phy);
glue->phy_suspended = 0;
return 0;
}
static const struct dev_pm_ops omap2430_pm_ops = { static const struct dev_pm_ops omap2430_pm_ops = {
.runtime_suspend = omap2430_runtime_suspend, .runtime_suspend = omap2430_runtime_suspend,
.runtime_resume = omap2430_runtime_resume, .runtime_resume = omap2430_runtime_resume,
.suspend = omap2430_suspend, .suspend = omap2430_suspend,
.suspend_late = omap2430_suspend_late,
.resume_early = omap2430_resume_early,
.resume = omap2430_resume, .resume = omap2430_resume,
}; };
......
...@@ -851,6 +851,7 @@ static struct usb_serial_driver ch341_device = { ...@@ -851,6 +851,7 @@ static struct usb_serial_driver ch341_device = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "ch341-uart", .name = "ch341-uart",
}, },
.bulk_in_size = 512,
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.open = ch341_open, .open = ch341_open,
......
...@@ -219,6 +219,7 @@ static const struct usb_device_id id_table_combined[] = { ...@@ -219,6 +219,7 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) }, { USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) },
{ USB_DEVICE(FTDI_VID, FTDI_VARDAAN_PID) }, { USB_DEVICE(FTDI_VID, FTDI_VARDAAN_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_AUTO_M3_OP_COM_V2_PID) },
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
......
...@@ -159,6 +159,9 @@ ...@@ -159,6 +159,9 @@
/* Vardaan Enterprises Serial Interface VEUSB422R3 */ /* Vardaan Enterprises Serial Interface VEUSB422R3 */
#define FTDI_VARDAAN_PID 0xF070 #define FTDI_VARDAAN_PID 0xF070
/* Auto-M3 Ltd. - OP-COM USB V2 - OBD interface Adapter */
#define FTDI_AUTO_M3_OP_COM_V2_PID 0x4f50
/* /*
* Xsens Technologies BV products (http://www.xsens.com). * Xsens Technologies BV products (http://www.xsens.com).
*/ */
......
...@@ -1203,6 +1203,8 @@ static const struct usb_device_id option_ids[] = { ...@@ -1203,6 +1203,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(2) | RSVD(3) }, .driver_info = NCTRL(2) | RSVD(3) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1055, 0xff), /* Telit FN980 (PCIe) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1055, 0xff), /* Telit FN980 (PCIe) */
.driver_info = NCTRL(0) | RSVD(1) }, .driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1056, 0xff), /* Telit FD980 */
.driver_info = NCTRL(2) | RSVD(3) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
......
...@@ -418,24 +418,34 @@ static int pl2303_detect_type(struct usb_serial *serial) ...@@ -418,24 +418,34 @@ static int pl2303_detect_type(struct usb_serial *serial)
bcdDevice = le16_to_cpu(desc->bcdDevice); bcdDevice = le16_to_cpu(desc->bcdDevice);
bcdUSB = le16_to_cpu(desc->bcdUSB); bcdUSB = le16_to_cpu(desc->bcdUSB);
switch (bcdDevice) { switch (bcdUSB) {
case 0x100: case 0x110:
/* switch (bcdDevice) {
* Assume it's an HXN-type if the device doesn't support the old read case 0x300:
* request value. return TYPE_HX;
*/ case 0x400:
if (bcdUSB == 0x200 && !pl2303_supports_hx_status(serial)) return TYPE_HXD;
return TYPE_HXN; default:
return TYPE_HX;
}
break; break;
case 0x300: case 0x200:
if (bcdUSB == 0x200) switch (bcdDevice) {
case 0x100:
case 0x305:
/*
* Assume it's an HXN-type if the device doesn't
* support the old read request value.
*/
if (!pl2303_supports_hx_status(serial))
return TYPE_HXN;
break;
case 0x300:
return TYPE_TA; return TYPE_TA;
case 0x500:
return TYPE_HX; return TYPE_TB;
case 0x400: }
return TYPE_HXD; break;
case 0x500:
return TYPE_TB;
} }
dev_err(&serial->interface->dev, dev_err(&serial->interface->dev,
......
...@@ -5369,7 +5369,7 @@ EXPORT_SYMBOL_GPL(tcpm_pd_hard_reset); ...@@ -5369,7 +5369,7 @@ EXPORT_SYMBOL_GPL(tcpm_pd_hard_reset);
void tcpm_sink_frs(struct tcpm_port *port) void tcpm_sink_frs(struct tcpm_port *port)
{ {
spin_lock(&port->pd_event_lock); spin_lock(&port->pd_event_lock);
port->pd_events = TCPM_FRS_EVENT; port->pd_events |= TCPM_FRS_EVENT;
spin_unlock(&port->pd_event_lock); spin_unlock(&port->pd_event_lock);
kthread_queue_work(port->wq, &port->event_work); kthread_queue_work(port->wq, &port->event_work);
} }
...@@ -5378,7 +5378,7 @@ EXPORT_SYMBOL_GPL(tcpm_sink_frs); ...@@ -5378,7 +5378,7 @@ EXPORT_SYMBOL_GPL(tcpm_sink_frs);
void tcpm_sourcing_vbus(struct tcpm_port *port) void tcpm_sourcing_vbus(struct tcpm_port *port)
{ {
spin_lock(&port->pd_event_lock); spin_lock(&port->pd_event_lock);
port->pd_events = TCPM_SOURCING_VBUS; port->pd_events |= TCPM_SOURCING_VBUS;
spin_unlock(&port->pd_event_lock); spin_unlock(&port->pd_event_lock);
kthread_queue_work(port->wq, &port->event_work); kthread_queue_work(port->wq, &port->event_work);
} }
......
...@@ -196,6 +196,7 @@ struct otg_fsm { ...@@ -196,6 +196,7 @@ struct otg_fsm {
struct mutex lock; struct mutex lock;
u8 *host_req_flag; u8 *host_req_flag;
struct delayed_work hnp_polling_work; struct delayed_work hnp_polling_work;
bool hnp_work_inited;
bool state_changed; bool state_changed;
}; };
......
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