Commit de879a8d authored by Linus Torvalds's avatar Linus Torvalds

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

Pull USB fixes from Greg KH:
 "Here are a few small USB driver fixes for 5.12-rc6 to resolve reported
  problems.

  They include:

   - a number of cdc-acm fixes for reported problems. It seems more
     people are using this driver lately...

   - dwc3 driver fixes for reported problems, and fixes for the fixes :)

   - dwc2 driver fixes for reported issues.

   - musb driver fix.

   - new USB quirk additions.

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

* tag 'usb-5.12-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (23 commits)
  usb: dwc2: Prevent core suspend when port connection flag is 0
  usb: dwc2: Fix HPRT0.PrtSusp bit setting for HiKey 960 board.
  usb: musb: Fix suspend with devices connected for a64
  usb: xhci-mtk: fix broken streams issue on 0.96 xHCI
  usb: dwc3: gadget: Clear DEP flags after stop transfers in ep disable
  usbip: vhci_hcd fix shift out-of-bounds in vhci_hub_control()
  USB: quirks: ignore remote wake-up on Fibocom L850-GL LTE modem
  USB: cdc-acm: do not log successful probe on later errors
  USB: cdc-acm: always claim data interface
  USB: cdc-acm: use negation for NULL checks
  USB: cdc-acm: clean up probe error labels
  USB: cdc-acm: drop redundant driver-data reset
  USB: cdc-acm: drop redundant driver-data assignment
  USB: cdc-acm: fix use-after-free after probe failure
  USB: cdc-acm: fix double free on probe failure
  USB: cdc-acm: downgrade message to debug
  USB: cdc-acm: untangle a circular dependency between callback and softint
  cdc-acm: fix BREAK rx code path adding necessary calls
  usb: gadget: udc: amd5536udc_pci fix null-ptr-dereference
  usb: dwc3: pci: Enable dis_uX_susphy_quirk for Intel Merrifield
  ...
parents 57fbdb15 93f67280
...@@ -147,17 +147,29 @@ static inline int acm_set_control(struct acm *acm, int control) ...@@ -147,17 +147,29 @@ static inline int acm_set_control(struct acm *acm, int control)
#define acm_send_break(acm, ms) \ #define acm_send_break(acm, ms) \
acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0) acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0)
static void acm_kill_urbs(struct acm *acm) static void acm_poison_urbs(struct acm *acm)
{ {
int i; int i;
usb_kill_urb(acm->ctrlurb); usb_poison_urb(acm->ctrlurb);
for (i = 0; i < ACM_NW; i++) for (i = 0; i < ACM_NW; i++)
usb_kill_urb(acm->wb[i].urb); usb_poison_urb(acm->wb[i].urb);
for (i = 0; i < acm->rx_buflimit; i++) for (i = 0; i < acm->rx_buflimit; i++)
usb_kill_urb(acm->read_urbs[i]); usb_poison_urb(acm->read_urbs[i]);
}
static void acm_unpoison_urbs(struct acm *acm)
{
int i;
for (i = 0; i < acm->rx_buflimit; i++)
usb_unpoison_urb(acm->read_urbs[i]);
for (i = 0; i < ACM_NW; i++)
usb_unpoison_urb(acm->wb[i].urb);
usb_unpoison_urb(acm->ctrlurb);
} }
/* /*
* Write buffer management. * Write buffer management.
* All of these assume proper locks taken by the caller. * All of these assume proper locks taken by the caller.
...@@ -226,6 +238,7 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb) ...@@ -226,6 +238,7 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb)
rc = usb_submit_urb(wb->urb, GFP_ATOMIC); rc = usb_submit_urb(wb->urb, GFP_ATOMIC);
if (rc < 0) { if (rc < 0) {
if (rc != -EPERM)
dev_err(&acm->data->dev, dev_err(&acm->data->dev,
"%s - usb_submit_urb(write bulk) failed: %d\n", "%s - usb_submit_urb(write bulk) failed: %d\n",
__func__, rc); __func__, rc);
...@@ -313,8 +326,10 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf) ...@@ -313,8 +326,10 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf)
acm->iocount.dsr++; acm->iocount.dsr++;
if (difference & ACM_CTRL_DCD) if (difference & ACM_CTRL_DCD)
acm->iocount.dcd++; acm->iocount.dcd++;
if (newctrl & ACM_CTRL_BRK) if (newctrl & ACM_CTRL_BRK) {
acm->iocount.brk++; acm->iocount.brk++;
tty_insert_flip_char(&acm->port, 0, TTY_BREAK);
}
if (newctrl & ACM_CTRL_RI) if (newctrl & ACM_CTRL_RI)
acm->iocount.rng++; acm->iocount.rng++;
if (newctrl & ACM_CTRL_FRAMING) if (newctrl & ACM_CTRL_FRAMING)
...@@ -480,11 +495,6 @@ static void acm_read_bulk_callback(struct urb *urb) ...@@ -480,11 +495,6 @@ static void acm_read_bulk_callback(struct urb *urb)
dev_vdbg(&acm->data->dev, "got urb %d, len %d, status %d\n", dev_vdbg(&acm->data->dev, "got urb %d, len %d, status %d\n",
rb->index, urb->actual_length, status); rb->index, urb->actual_length, status);
if (!acm->dev) {
dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__);
return;
}
switch (status) { switch (status) {
case 0: case 0:
usb_mark_last_busy(acm->dev); usb_mark_last_busy(acm->dev);
...@@ -649,7 +659,8 @@ static void acm_port_dtr_rts(struct tty_port *port, int raise) ...@@ -649,7 +659,8 @@ static void acm_port_dtr_rts(struct tty_port *port, int raise)
res = acm_set_control(acm, val); res = acm_set_control(acm, val);
if (res && (acm->ctrl_caps & USB_CDC_CAP_LINE)) if (res && (acm->ctrl_caps & USB_CDC_CAP_LINE))
dev_err(&acm->control->dev, "failed to set dtr/rts\n"); /* This is broken in too many devices to spam the logs */
dev_dbg(&acm->control->dev, "failed to set dtr/rts\n");
} }
static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
...@@ -731,6 +742,7 @@ static void acm_port_shutdown(struct tty_port *port) ...@@ -731,6 +742,7 @@ static void acm_port_shutdown(struct tty_port *port)
* Need to grab write_lock to prevent race with resume, but no need to * Need to grab write_lock to prevent race with resume, but no need to
* hold it due to the tty-port initialised flag. * hold it due to the tty-port initialised flag.
*/ */
acm_poison_urbs(acm);
spin_lock_irq(&acm->write_lock); spin_lock_irq(&acm->write_lock);
spin_unlock_irq(&acm->write_lock); spin_unlock_irq(&acm->write_lock);
...@@ -747,7 +759,8 @@ static void acm_port_shutdown(struct tty_port *port) ...@@ -747,7 +759,8 @@ static void acm_port_shutdown(struct tty_port *port)
usb_autopm_put_interface_async(acm->control); usb_autopm_put_interface_async(acm->control);
} }
acm_kill_urbs(acm); acm_unpoison_urbs(acm);
} }
static void acm_tty_cleanup(struct tty_struct *tty) static void acm_tty_cleanup(struct tty_struct *tty)
...@@ -1296,13 +1309,6 @@ static int acm_probe(struct usb_interface *intf, ...@@ -1296,13 +1309,6 @@ static int acm_probe(struct usb_interface *intf,
if (!combined_interfaces && intf != control_interface) if (!combined_interfaces && intf != control_interface)
return -ENODEV; return -ENODEV;
if (!combined_interfaces && usb_interface_claimed(data_interface)) {
/* valid in this context */
dev_dbg(&intf->dev, "The data interface isn't available\n");
return -EBUSY;
}
if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 || if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 ||
control_interface->cur_altsetting->desc.bNumEndpoints == 0) control_interface->cur_altsetting->desc.bNumEndpoints == 0)
return -EINVAL; return -EINVAL;
...@@ -1323,8 +1329,8 @@ static int acm_probe(struct usb_interface *intf, ...@@ -1323,8 +1329,8 @@ static int acm_probe(struct usb_interface *intf,
dev_dbg(&intf->dev, "interfaces are valid\n"); dev_dbg(&intf->dev, "interfaces are valid\n");
acm = kzalloc(sizeof(struct acm), GFP_KERNEL); acm = kzalloc(sizeof(struct acm), GFP_KERNEL);
if (acm == NULL) if (!acm)
goto alloc_fail; return -ENOMEM;
tty_port_init(&acm->port); tty_port_init(&acm->port);
acm->port.ops = &acm_port_ops; acm->port.ops = &acm_port_ops;
...@@ -1341,7 +1347,7 @@ static int acm_probe(struct usb_interface *intf, ...@@ -1341,7 +1347,7 @@ static int acm_probe(struct usb_interface *intf,
minor = acm_alloc_minor(acm); minor = acm_alloc_minor(acm);
if (minor < 0) if (minor < 0)
goto alloc_fail1; goto err_put_port;
acm->minor = minor; acm->minor = minor;
acm->dev = usb_dev; acm->dev = usb_dev;
...@@ -1372,15 +1378,15 @@ static int acm_probe(struct usb_interface *intf, ...@@ -1372,15 +1378,15 @@ static int acm_probe(struct usb_interface *intf,
buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
if (!buf) if (!buf)
goto alloc_fail1; goto err_put_port;
acm->ctrl_buffer = buf; acm->ctrl_buffer = buf;
if (acm_write_buffers_alloc(acm) < 0) if (acm_write_buffers_alloc(acm) < 0)
goto alloc_fail2; goto err_free_ctrl_buffer;
acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->ctrlurb) if (!acm->ctrlurb)
goto alloc_fail3; goto err_free_write_buffers;
for (i = 0; i < num_rx_buf; i++) { for (i = 0; i < num_rx_buf; i++) {
struct acm_rb *rb = &(acm->read_buffers[i]); struct acm_rb *rb = &(acm->read_buffers[i]);
...@@ -1389,13 +1395,13 @@ static int acm_probe(struct usb_interface *intf, ...@@ -1389,13 +1395,13 @@ static int acm_probe(struct usb_interface *intf,
rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL, rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL,
&rb->dma); &rb->dma);
if (!rb->base) if (!rb->base)
goto alloc_fail4; goto err_free_read_urbs;
rb->index = i; rb->index = i;
rb->instance = acm; rb->instance = acm;
urb = usb_alloc_urb(0, GFP_KERNEL); urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) if (!urb)
goto alloc_fail4; goto err_free_read_urbs;
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
urb->transfer_dma = rb->dma; urb->transfer_dma = rb->dma;
...@@ -1416,8 +1422,8 @@ static int acm_probe(struct usb_interface *intf, ...@@ -1416,8 +1422,8 @@ static int acm_probe(struct usb_interface *intf,
struct acm_wb *snd = &(acm->wb[i]); struct acm_wb *snd = &(acm->wb[i]);
snd->urb = usb_alloc_urb(0, GFP_KERNEL); snd->urb = usb_alloc_urb(0, GFP_KERNEL);
if (snd->urb == NULL) if (!snd->urb)
goto alloc_fail5; goto err_free_write_urbs;
if (usb_endpoint_xfer_int(epwrite)) if (usb_endpoint_xfer_int(epwrite))
usb_fill_int_urb(snd->urb, usb_dev, acm->out, usb_fill_int_urb(snd->urb, usb_dev, acm->out,
...@@ -1435,7 +1441,7 @@ static int acm_probe(struct usb_interface *intf, ...@@ -1435,7 +1441,7 @@ static int acm_probe(struct usb_interface *intf,
i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); i = device_create_file(&intf->dev, &dev_attr_bmCapabilities);
if (i < 0) if (i < 0)
goto alloc_fail5; goto err_free_write_urbs;
if (h.usb_cdc_country_functional_desc) { /* export the country data */ if (h.usb_cdc_country_functional_desc) { /* export the country data */
struct usb_cdc_country_functional_desc * cfd = struct usb_cdc_country_functional_desc * cfd =
...@@ -1480,20 +1486,21 @@ static int acm_probe(struct usb_interface *intf, ...@@ -1480,20 +1486,21 @@ static int acm_probe(struct usb_interface *intf,
acm->nb_index = 0; acm->nb_index = 0;
acm->nb_size = 0; acm->nb_size = 0;
dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
acm->line.dwDTERate = cpu_to_le32(9600); acm->line.dwDTERate = cpu_to_le32(9600);
acm->line.bDataBits = 8; acm->line.bDataBits = 8;
acm_set_line(acm, &acm->line); acm_set_line(acm, &acm->line);
usb_driver_claim_interface(&acm_driver, data_interface, acm); if (!acm->combined_interfaces) {
usb_set_intfdata(data_interface, acm); rv = usb_driver_claim_interface(&acm_driver, data_interface, acm);
if (rv)
goto err_remove_files;
}
tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor, tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor,
&control_interface->dev); &control_interface->dev);
if (IS_ERR(tty_dev)) { if (IS_ERR(tty_dev)) {
rv = PTR_ERR(tty_dev); rv = PTR_ERR(tty_dev);
goto alloc_fail6; goto err_release_data_interface;
} }
if (quirks & CLEAR_HALT_CONDITIONS) { if (quirks & CLEAR_HALT_CONDITIONS) {
...@@ -1501,32 +1508,39 @@ static int acm_probe(struct usb_interface *intf, ...@@ -1501,32 +1508,39 @@ static int acm_probe(struct usb_interface *intf,
usb_clear_halt(usb_dev, acm->out); usb_clear_halt(usb_dev, acm->out);
} }
dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
return 0; return 0;
alloc_fail6:
err_release_data_interface:
if (!acm->combined_interfaces) {
/* Clear driver data so that disconnect() returns early. */
usb_set_intfdata(data_interface, NULL);
usb_driver_release_interface(&acm_driver, data_interface);
}
err_remove_files:
if (acm->country_codes) { if (acm->country_codes) {
device_remove_file(&acm->control->dev, device_remove_file(&acm->control->dev,
&dev_attr_wCountryCodes); &dev_attr_wCountryCodes);
device_remove_file(&acm->control->dev, device_remove_file(&acm->control->dev,
&dev_attr_iCountryCodeRelDate); &dev_attr_iCountryCodeRelDate);
kfree(acm->country_codes);
} }
device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);
alloc_fail5: err_free_write_urbs:
usb_set_intfdata(intf, NULL);
for (i = 0; i < ACM_NW; i++) for (i = 0; i < ACM_NW; i++)
usb_free_urb(acm->wb[i].urb); usb_free_urb(acm->wb[i].urb);
alloc_fail4: err_free_read_urbs:
for (i = 0; i < num_rx_buf; i++) for (i = 0; i < num_rx_buf; i++)
usb_free_urb(acm->read_urbs[i]); usb_free_urb(acm->read_urbs[i]);
acm_read_buffers_free(acm); acm_read_buffers_free(acm);
usb_free_urb(acm->ctrlurb); usb_free_urb(acm->ctrlurb);
alloc_fail3: err_free_write_buffers:
acm_write_buffers_free(acm); acm_write_buffers_free(acm);
alloc_fail2: err_free_ctrl_buffer:
usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
alloc_fail1: err_put_port:
tty_port_put(&acm->port); tty_port_put(&acm->port);
alloc_fail:
return rv; return rv;
} }
...@@ -1540,8 +1554,14 @@ static void acm_disconnect(struct usb_interface *intf) ...@@ -1540,8 +1554,14 @@ static void acm_disconnect(struct usb_interface *intf)
if (!acm) if (!acm)
return; return;
mutex_lock(&acm->mutex);
acm->disconnected = true; acm->disconnected = true;
/*
* there is a circular dependency. acm_softint() can resubmit
* the URBs in error handling so we need to block any
* submission right away
*/
acm_poison_urbs(acm);
mutex_lock(&acm->mutex);
if (acm->country_codes) { if (acm->country_codes) {
device_remove_file(&acm->control->dev, device_remove_file(&acm->control->dev,
&dev_attr_wCountryCodes); &dev_attr_wCountryCodes);
...@@ -1560,7 +1580,6 @@ static void acm_disconnect(struct usb_interface *intf) ...@@ -1560,7 +1580,6 @@ static void acm_disconnect(struct usb_interface *intf)
tty_kref_put(tty); tty_kref_put(tty);
} }
acm_kill_urbs(acm);
cancel_delayed_work_sync(&acm->dwork); cancel_delayed_work_sync(&acm->dwork);
tty_unregister_device(acm_tty_driver, acm->minor); tty_unregister_device(acm_tty_driver, acm->minor);
...@@ -1602,7 +1621,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -1602,7 +1621,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
if (cnt) if (cnt)
return 0; return 0;
acm_kill_urbs(acm); acm_poison_urbs(acm);
cancel_delayed_work_sync(&acm->dwork); cancel_delayed_work_sync(&acm->dwork);
acm->urbs_in_error_delay = 0; acm->urbs_in_error_delay = 0;
...@@ -1615,6 +1634,7 @@ static int acm_resume(struct usb_interface *intf) ...@@ -1615,6 +1634,7 @@ static int acm_resume(struct usb_interface *intf)
struct urb *urb; struct urb *urb;
int rv = 0; int rv = 0;
acm_unpoison_urbs(acm);
spin_lock_irq(&acm->write_lock); spin_lock_irq(&acm->write_lock);
if (--acm->susp_count) if (--acm->susp_count)
......
...@@ -498,6 +498,10 @@ static const struct usb_device_id usb_quirk_list[] = { ...@@ -498,6 +498,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* DJI CineSSD */ /* DJI CineSSD */
{ USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM }, { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM },
/* Fibocom L850-GL LTE Modem */
{ USB_DEVICE(0x2cb7, 0x0007), .driver_info =
USB_QUIRK_IGNORE_REMOTE_WAKEUP },
/* INTEL VALUE SSD */ /* INTEL VALUE SSD */
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
......
...@@ -4322,7 +4322,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd) ...@@ -4322,7 +4322,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
if (hsotg->op_state == OTG_STATE_B_PERIPHERAL) if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
goto unlock; goto unlock;
if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL) if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
hsotg->flags.b.port_connect_status == 0)
goto skip_power_saving; goto skip_power_saving;
/* /*
...@@ -5398,7 +5399,7 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg) ...@@ -5398,7 +5399,7 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg)
dwc2_writel(hsotg, hprt0, HPRT0); dwc2_writel(hsotg, hprt0, HPRT0);
/* Wait for the HPRT0.PrtSusp register field to be set */ /* Wait for the HPRT0.PrtSusp register field to be set */
if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 3000)) if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 5000))
dev_warn(hsotg->dev, "Suspend wasn't generated\n"); dev_warn(hsotg->dev, "Suspend wasn't generated\n");
/* /*
......
...@@ -120,6 +120,8 @@ static const struct property_entry dwc3_pci_intel_properties[] = { ...@@ -120,6 +120,8 @@ static const struct property_entry dwc3_pci_intel_properties[] = {
static const struct property_entry dwc3_pci_mrfld_properties[] = { static const struct property_entry dwc3_pci_mrfld_properties[] = {
PROPERTY_ENTRY_STRING("dr_mode", "otg"), PROPERTY_ENTRY_STRING("dr_mode", "otg"),
PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"), PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"),
PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"),
PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
{} {}
}; };
......
...@@ -244,6 +244,9 @@ static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom) ...@@ -244,6 +244,9 @@ static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom)
struct device *dev = qcom->dev; struct device *dev = qcom->dev;
int ret; int ret;
if (has_acpi_companion(dev))
return 0;
qcom->icc_path_ddr = of_icc_get(dev, "usb-ddr"); qcom->icc_path_ddr = of_icc_get(dev, "usb-ddr");
if (IS_ERR(qcom->icc_path_ddr)) { if (IS_ERR(qcom->icc_path_ddr)) {
dev_err(dev, "failed to get usb-ddr path: %ld\n", dev_err(dev, "failed to get usb-ddr path: %ld\n",
......
...@@ -791,10 +791,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) ...@@ -791,10 +791,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
reg &= ~DWC3_DALEPENA_EP(dep->number); reg &= ~DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
dep->stream_capable = false;
dep->type = 0;
dep->flags = 0;
/* Clear out the ep descriptors for non-ep0 */ /* Clear out the ep descriptors for non-ep0 */
if (dep->number > 1) { if (dep->number > 1) {
dep->endpoint.comp_desc = NULL; dep->endpoint.comp_desc = NULL;
...@@ -803,6 +799,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) ...@@ -803,6 +799,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dwc3_remove_requests(dwc, dep); dwc3_remove_requests(dwc, dep);
dep->stream_capable = false;
dep->type = 0;
dep->flags = 0;
return 0; return 0;
} }
...@@ -2083,7 +2083,7 @@ static void __dwc3_gadget_set_speed(struct dwc3 *dwc) ...@@ -2083,7 +2083,7 @@ static void __dwc3_gadget_set_speed(struct dwc3 *dwc)
u32 reg; u32 reg;
speed = dwc->gadget_max_speed; speed = dwc->gadget_max_speed;
if (speed > dwc->maximum_speed) if (speed == USB_SPEED_UNKNOWN || speed > dwc->maximum_speed)
speed = dwc->maximum_speed; speed = dwc->maximum_speed;
if (speed == USB_SPEED_SUPER_PLUS && if (speed == USB_SPEED_SUPER_PLUS &&
...@@ -2523,6 +2523,7 @@ static void dwc3_gadget_set_ssp_rate(struct usb_gadget *g, ...@@ -2523,6 +2523,7 @@ static void dwc3_gadget_set_ssp_rate(struct usb_gadget *g,
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dwc->lock, flags); spin_lock_irqsave(&dwc->lock, flags);
dwc->gadget_max_speed = USB_SPEED_SUPER_PLUS;
dwc->gadget_ssp_rate = rate; dwc->gadget_ssp_rate = rate;
spin_unlock_irqrestore(&dwc->lock, flags); spin_unlock_irqrestore(&dwc->lock, flags);
} }
......
...@@ -153,6 +153,11 @@ static int udc_pci_probe( ...@@ -153,6 +153,11 @@ static int udc_pci_probe(
pci_set_master(pdev); pci_set_master(pdev);
pci_try_set_mwi(pdev); pci_try_set_mwi(pdev);
dev->phys_addr = resource;
dev->irq = pdev->irq;
dev->pdev = pdev;
dev->dev = &pdev->dev;
/* init dma pools */ /* init dma pools */
if (use_dma) { if (use_dma) {
retval = init_dma_pools(dev); retval = init_dma_pools(dev);
...@@ -160,11 +165,6 @@ static int udc_pci_probe( ...@@ -160,11 +165,6 @@ static int udc_pci_probe(
goto err_dma; goto err_dma;
} }
dev->phys_addr = resource;
dev->irq = pdev->irq;
dev->pdev = pdev;
dev->dev = &pdev->dev;
/* general probing */ /* general probing */
if (udc_probe(dev)) { if (udc_probe(dev)) {
retval = -ENODEV; retval = -ENODEV;
......
...@@ -397,6 +397,13 @@ static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci) ...@@ -397,6 +397,13 @@ static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_SPURIOUS_SUCCESS; xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
if (mtk->lpm_support) if (mtk->lpm_support)
xhci->quirks |= XHCI_LPM_SUPPORT; xhci->quirks |= XHCI_LPM_SUPPORT;
/*
* MTK xHCI 0.96: PSA is 1 by default even if doesn't support stream,
* and it's 3 when support it.
*/
if (xhci->hci_version < 0x100 && HCC_MAX_PSA(xhci->hcc_params) == 4)
xhci->quirks |= XHCI_BROKEN_STREAMS;
} }
/* called during probe() after chip reset completes */ /* called during probe() after chip reset completes */
...@@ -548,7 +555,8 @@ static int xhci_mtk_probe(struct platform_device *pdev) ...@@ -548,7 +555,8 @@ static int xhci_mtk_probe(struct platform_device *pdev)
if (ret) if (ret)
goto put_usb3_hcd; goto put_usb3_hcd;
if (HCC_MAX_PSA(xhci->hcc_params) >= 4) if (HCC_MAX_PSA(xhci->hcc_params) >= 4 &&
!(xhci->quirks & XHCI_BROKEN_STREAMS))
xhci->shared_hcd->can_do_streams = 1; 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);
......
...@@ -2004,10 +2004,14 @@ static void musb_pm_runtime_check_session(struct musb *musb) ...@@ -2004,10 +2004,14 @@ static void musb_pm_runtime_check_session(struct musb *musb)
MUSB_DEVCTL_HR; MUSB_DEVCTL_HR;
switch (devctl & ~s) { switch (devctl & ~s) {
case MUSB_QUIRK_B_DISCONNECT_99: case MUSB_QUIRK_B_DISCONNECT_99:
if (musb->quirk_retries && !musb->flush_irq_work) {
musb_dbg(musb, "Poll devctl in case of suspend after disconnect\n"); musb_dbg(musb, "Poll devctl in case of suspend after disconnect\n");
schedule_delayed_work(&musb->irq_work, schedule_delayed_work(&musb->irq_work,
msecs_to_jiffies(1000)); msecs_to_jiffies(1000));
musb->quirk_retries--;
break; break;
}
fallthrough;
case MUSB_QUIRK_B_INVALID_VBUS_91: case MUSB_QUIRK_B_INVALID_VBUS_91:
if (musb->quirk_retries && !musb->flush_irq_work) { if (musb->quirk_retries && !musb->flush_irq_work) {
musb_dbg(musb, musb_dbg(musb,
......
...@@ -594,6 +594,8 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -594,6 +594,8 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
pr_err("invalid port number %d\n", wIndex); pr_err("invalid port number %d\n", wIndex);
goto error; goto error;
} }
if (wValue >= 32)
goto error;
if (hcd->speed == HCD_USB3) { if (hcd->speed == HCD_USB3) {
if ((vhci_hcd->port_status[rhport] & if ((vhci_hcd->port_status[rhport] &
USB_SS_PORT_STAT_POWER) != 0) { USB_SS_PORT_STAT_POWER) != 0) {
......
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