Commit 2c248f92 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull USB fixes from Greg KH:
 "Here are some small USB fixes that have been in linux-next this past
  week for 5.3-rc7

  They fix the usual xhci, syzbot reports, and other small issues that
  have come up last week.

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

* tag 'usb-5.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  USB: cdc-wdm: fix race between write and disconnect due to flag abuse
  usb: host: xhci: rcar: Fix typo in compatible string matching
  usb: host: xhci-tegra: Set DMA mask correctly
  USB: storage: ums-realtek: Whitelist auto-delink support
  USB: storage: ums-realtek: Update module parameter description for auto_delink_en
  usb: host: ohci: fix a race condition between shutdown and irq
  usb: hcd: use managed device resources
  typec: tcpm: fix a typo in the comparison of pdo_max_voltage
  usb-storage: Add new JMS567 revision to unusual_devs
  usb: chipidea: udc: don't do hardware access if gadget has stopped
  usbtmc: more sanity checking for packet size
  usb: udc: lpc32xx: silence fall-through warning
parents 345464fb 1426bd2c
...@@ -709,12 +709,6 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) ...@@ -709,12 +709,6 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&ci->lock, flags);
ci->gadget.speed = USB_SPEED_UNKNOWN;
ci->remote_wakeup = 0;
ci->suspended = 0;
spin_unlock_irqrestore(&ci->lock, flags);
/* flush all endpoints */ /* flush all endpoints */
gadget_for_each_ep(ep, gadget) { gadget_for_each_ep(ep, gadget) {
usb_ep_fifo_flush(ep); usb_ep_fifo_flush(ep);
...@@ -732,6 +726,12 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) ...@@ -732,6 +726,12 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
ci->status = NULL; ci->status = NULL;
} }
spin_lock_irqsave(&ci->lock, flags);
ci->gadget.speed = USB_SPEED_UNKNOWN;
ci->remote_wakeup = 0;
ci->suspended = 0;
spin_unlock_irqrestore(&ci->lock, flags);
return 0; return 0;
} }
...@@ -1303,6 +1303,10 @@ static int ep_disable(struct usb_ep *ep) ...@@ -1303,6 +1303,10 @@ static int ep_disable(struct usb_ep *ep)
return -EBUSY; return -EBUSY;
spin_lock_irqsave(hwep->lock, flags); spin_lock_irqsave(hwep->lock, flags);
if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
spin_unlock_irqrestore(hwep->lock, flags);
return 0;
}
/* only internal SW should disable ctrl endpts */ /* only internal SW should disable ctrl endpts */
...@@ -1392,6 +1396,10 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, ...@@ -1392,6 +1396,10 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
return -EINVAL; return -EINVAL;
spin_lock_irqsave(hwep->lock, flags); spin_lock_irqsave(hwep->lock, flags);
if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
spin_unlock_irqrestore(hwep->lock, flags);
return 0;
}
retval = _ep_queue(ep, req, gfp_flags); retval = _ep_queue(ep, req, gfp_flags);
spin_unlock_irqrestore(hwep->lock, flags); spin_unlock_irqrestore(hwep->lock, flags);
return retval; return retval;
...@@ -1415,7 +1423,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) ...@@ -1415,7 +1423,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
return -EINVAL; return -EINVAL;
spin_lock_irqsave(hwep->lock, flags); spin_lock_irqsave(hwep->lock, flags);
if (hwep->ci->gadget.speed != USB_SPEED_UNKNOWN)
hw_ep_flush(hwep->ci, hwep->num, hwep->dir); hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) {
...@@ -1487,6 +1495,10 @@ static void ep_fifo_flush(struct usb_ep *ep) ...@@ -1487,6 +1495,10 @@ static void ep_fifo_flush(struct usb_ep *ep)
} }
spin_lock_irqsave(hwep->lock, flags); spin_lock_irqsave(hwep->lock, flags);
if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
spin_unlock_irqrestore(hwep->lock, flags);
return;
}
hw_ep_flush(hwep->ci, hwep->num, hwep->dir); hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
...@@ -1559,6 +1571,10 @@ static int ci_udc_wakeup(struct usb_gadget *_gadget) ...@@ -1559,6 +1571,10 @@ static int ci_udc_wakeup(struct usb_gadget *_gadget)
int ret = 0; int ret = 0;
spin_lock_irqsave(&ci->lock, flags); spin_lock_irqsave(&ci->lock, flags);
if (ci->gadget.speed == USB_SPEED_UNKNOWN) {
spin_unlock_irqrestore(&ci->lock, flags);
return 0;
}
if (!ci->remote_wakeup) { if (!ci->remote_wakeup) {
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
goto out; goto out;
......
...@@ -587,10 +587,20 @@ static int wdm_flush(struct file *file, fl_owner_t id) ...@@ -587,10 +587,20 @@ static int wdm_flush(struct file *file, fl_owner_t id)
{ {
struct wdm_device *desc = file->private_data; struct wdm_device *desc = file->private_data;
wait_event(desc->wait, !test_bit(WDM_IN_USE, &desc->flags)); wait_event(desc->wait,
/*
* needs both flags. We cannot do with one
* because resetting it would cause a race
* with write() yet we need to signal
* a disconnect
*/
!test_bit(WDM_IN_USE, &desc->flags) ||
test_bit(WDM_DISCONNECTING, &desc->flags));
/* cannot dereference desc->intf if WDM_DISCONNECTING */ /* cannot dereference desc->intf if WDM_DISCONNECTING */
if (desc->werr < 0 && !test_bit(WDM_DISCONNECTING, &desc->flags)) if (test_bit(WDM_DISCONNECTING, &desc->flags))
return -ENODEV;
if (desc->werr < 0)
dev_err(&desc->intf->dev, "Error in flush path: %d\n", dev_err(&desc->intf->dev, "Error in flush path: %d\n",
desc->werr); desc->werr);
...@@ -974,8 +984,6 @@ static void wdm_disconnect(struct usb_interface *intf) ...@@ -974,8 +984,6 @@ static void wdm_disconnect(struct usb_interface *intf)
spin_lock_irqsave(&desc->iuspin, flags); spin_lock_irqsave(&desc->iuspin, flags);
set_bit(WDM_DISCONNECTING, &desc->flags); set_bit(WDM_DISCONNECTING, &desc->flags);
set_bit(WDM_READ, &desc->flags); set_bit(WDM_READ, &desc->flags);
/* to terminate pending flushes */
clear_bit(WDM_IN_USE, &desc->flags);
spin_unlock_irqrestore(&desc->iuspin, flags); spin_unlock_irqrestore(&desc->iuspin, flags);
wake_up_all(&desc->wait); wake_up_all(&desc->wait);
mutex_lock(&desc->rlock); mutex_lock(&desc->rlock);
......
...@@ -2362,8 +2362,11 @@ static int usbtmc_probe(struct usb_interface *intf, ...@@ -2362,8 +2362,11 @@ static int usbtmc_probe(struct usb_interface *intf,
goto err_put; goto err_put;
} }
retcode = -EINVAL;
data->bulk_in = bulk_in->bEndpointAddress; data->bulk_in = bulk_in->bEndpointAddress;
data->wMaxPacketSize = usb_endpoint_maxp(bulk_in); data->wMaxPacketSize = usb_endpoint_maxp(bulk_in);
if (!data->wMaxPacketSize)
goto err_put;
dev_dbg(&intf->dev, "Found bulk in endpoint at %u\n", data->bulk_in); dev_dbg(&intf->dev, "Found bulk in endpoint at %u\n", data->bulk_in);
data->bulk_out = bulk_out->bEndpointAddress; data->bulk_out = bulk_out->bEndpointAddress;
......
...@@ -216,17 +216,18 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -216,17 +216,18 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
/* EHCI, OHCI */ /* EHCI, OHCI */
hcd->rsrc_start = pci_resource_start(dev, 0); hcd->rsrc_start = pci_resource_start(dev, 0);
hcd->rsrc_len = pci_resource_len(dev, 0); hcd->rsrc_len = pci_resource_len(dev, 0);
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, if (!devm_request_mem_region(&dev->dev, hcd->rsrc_start,
driver->description)) { hcd->rsrc_len, driver->description)) {
dev_dbg(&dev->dev, "controller already in use\n"); dev_dbg(&dev->dev, "controller already in use\n");
retval = -EBUSY; retval = -EBUSY;
goto put_hcd; goto put_hcd;
} }
hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); hcd->regs = devm_ioremap_nocache(&dev->dev, hcd->rsrc_start,
hcd->rsrc_len);
if (hcd->regs == NULL) { if (hcd->regs == NULL) {
dev_dbg(&dev->dev, "error mapping memory\n"); dev_dbg(&dev->dev, "error mapping memory\n");
retval = -EFAULT; retval = -EFAULT;
goto release_mem_region; goto put_hcd;
} }
} else { } else {
...@@ -240,8 +241,8 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -240,8 +241,8 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
hcd->rsrc_start = pci_resource_start(dev, region); hcd->rsrc_start = pci_resource_start(dev, region);
hcd->rsrc_len = pci_resource_len(dev, region); hcd->rsrc_len = pci_resource_len(dev, region);
if (request_region(hcd->rsrc_start, hcd->rsrc_len, if (devm_request_region(&dev->dev, hcd->rsrc_start,
driver->description)) hcd->rsrc_len, driver->description))
break; break;
} }
if (region == PCI_ROM_RESOURCE) { if (region == PCI_ROM_RESOURCE) {
...@@ -275,20 +276,13 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -275,20 +276,13 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
} }
if (retval != 0) if (retval != 0)
goto unmap_registers; goto put_hcd;
device_wakeup_enable(hcd->self.controller); device_wakeup_enable(hcd->self.controller);
if (pci_dev_run_wake(dev)) if (pci_dev_run_wake(dev))
pm_runtime_put_noidle(&dev->dev); pm_runtime_put_noidle(&dev->dev);
return retval; return retval;
unmap_registers:
if (driver->flags & HCD_MEMORY) {
iounmap(hcd->regs);
release_mem_region:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
} else
release_region(hcd->rsrc_start, hcd->rsrc_len);
put_hcd: put_hcd:
usb_put_hcd(hcd); usb_put_hcd(hcd);
disable_pci: disable_pci:
...@@ -347,14 +341,6 @@ void usb_hcd_pci_remove(struct pci_dev *dev) ...@@ -347,14 +341,6 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
dev_set_drvdata(&dev->dev, NULL); dev_set_drvdata(&dev->dev, NULL);
up_read(&companions_rwsem); up_read(&companions_rwsem);
} }
if (hcd->driver->flags & HCD_MEMORY) {
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
} else {
release_region(hcd->rsrc_start, hcd->rsrc_len);
}
usb_put_hcd(hcd); usb_put_hcd(hcd);
pci_disable_device(dev); pci_disable_device(dev);
} }
......
...@@ -2265,7 +2265,7 @@ static void udc_handle_ep0_setup(struct lpc32xx_udc *udc) ...@@ -2265,7 +2265,7 @@ static void udc_handle_ep0_setup(struct lpc32xx_udc *udc)
default: default:
break; break;
} }
break;
case USB_REQ_SET_ADDRESS: case USB_REQ_SET_ADDRESS:
if (reqtype == (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) { if (reqtype == (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) {
......
...@@ -419,8 +419,7 @@ static void ohci_usb_reset (struct ohci_hcd *ohci) ...@@ -419,8 +419,7 @@ static void ohci_usb_reset (struct ohci_hcd *ohci)
* other cases where the next software may expect clean state from the * other cases where the next software may expect clean state from the
* "firmware". this is bus-neutral, unlike shutdown() methods. * "firmware". this is bus-neutral, unlike shutdown() methods.
*/ */
static void static void _ohci_shutdown(struct usb_hcd *hcd)
ohci_shutdown (struct usb_hcd *hcd)
{ {
struct ohci_hcd *ohci; struct ohci_hcd *ohci;
...@@ -436,6 +435,16 @@ ohci_shutdown (struct usb_hcd *hcd) ...@@ -436,6 +435,16 @@ ohci_shutdown (struct usb_hcd *hcd)
ohci->rh_state = OHCI_RH_HALTED; ohci->rh_state = OHCI_RH_HALTED;
} }
static void ohci_shutdown(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
unsigned long flags;
spin_lock_irqsave(&ohci->lock, flags);
_ohci_shutdown(hcd);
spin_unlock_irqrestore(&ohci->lock, flags);
}
/*-------------------------------------------------------------------------* /*-------------------------------------------------------------------------*
* HC functions * HC functions
*-------------------------------------------------------------------------*/ *-------------------------------------------------------------------------*/
...@@ -760,7 +769,7 @@ static void io_watchdog_func(struct timer_list *t) ...@@ -760,7 +769,7 @@ static void io_watchdog_func(struct timer_list *t)
died: died:
usb_hc_died(ohci_to_hcd(ohci)); usb_hc_died(ohci_to_hcd(ohci));
ohci_dump(ohci); ohci_dump(ohci);
ohci_shutdown(ohci_to_hcd(ohci)); _ohci_shutdown(ohci_to_hcd(ohci));
goto done; goto done;
} else { } else {
/* No write back because the done queue was empty */ /* No write back because the done queue was empty */
......
...@@ -104,7 +104,7 @@ static int xhci_rcar_is_gen2(struct device *dev) ...@@ -104,7 +104,7 @@ static int xhci_rcar_is_gen2(struct device *dev)
return of_device_is_compatible(node, "renesas,xhci-r8a7790") || return of_device_is_compatible(node, "renesas,xhci-r8a7790") ||
of_device_is_compatible(node, "renesas,xhci-r8a7791") || of_device_is_compatible(node, "renesas,xhci-r8a7791") ||
of_device_is_compatible(node, "renesas,xhci-r8a7793") || of_device_is_compatible(node, "renesas,xhci-r8a7793") ||
of_device_is_compatible(node, "renensas,rcar-gen2-xhci"); of_device_is_compatible(node, "renesas,rcar-gen2-xhci");
} }
static int xhci_rcar_is_gen3(struct device *dev) static int xhci_rcar_is_gen3(struct device *dev)
......
...@@ -1194,6 +1194,16 @@ static int tegra_xusb_probe(struct platform_device *pdev) ...@@ -1194,6 +1194,16 @@ static int tegra_xusb_probe(struct platform_device *pdev)
tegra_xusb_config(tegra, regs); tegra_xusb_config(tegra, regs);
/*
* The XUSB Falcon microcontroller can only address 40 bits, so set
* the DMA mask accordingly.
*/
err = dma_set_mask_and_coherent(tegra->dev, DMA_BIT_MASK(40));
if (err < 0) {
dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
goto put_rpm;
}
err = tegra_xusb_load_firmware(tegra); err = tegra_xusb_load_firmware(tegra);
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, "failed to load firmware: %d\n", err); dev_err(&pdev->dev, "failed to load firmware: %d\n", err);
......
...@@ -38,7 +38,7 @@ MODULE_LICENSE("GPL"); ...@@ -38,7 +38,7 @@ MODULE_LICENSE("GPL");
static int auto_delink_en = 1; static int auto_delink_en = 1;
module_param(auto_delink_en, int, S_IRUGO | S_IWUSR); module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(auto_delink_en, "enable auto delink"); MODULE_PARM_DESC(auto_delink_en, "auto delink mode (0=firmware, 1=software [default])");
#ifdef CONFIG_REALTEK_AUTOPM #ifdef CONFIG_REALTEK_AUTOPM
static int ss_en = 1; static int ss_en = 1;
...@@ -996,6 +996,8 @@ static int init_realtek_cr(struct us_data *us) ...@@ -996,6 +996,8 @@ static int init_realtek_cr(struct us_data *us)
goto INIT_FAIL; goto INIT_FAIL;
} }
if (CHECK_PID(chip, 0x0138) || CHECK_PID(chip, 0x0158) ||
CHECK_PID(chip, 0x0159)) {
if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) || if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) ||
CHECK_FW_VER(chip, 0x5901)) CHECK_FW_VER(chip, 0x5901))
SET_AUTO_DELINK(chip); SET_AUTO_DELINK(chip);
...@@ -1003,6 +1005,7 @@ static int init_realtek_cr(struct us_data *us) ...@@ -1003,6 +1005,7 @@ static int init_realtek_cr(struct us_data *us)
if (SUPPORT_AUTO_DELINK(chip)) if (SUPPORT_AUTO_DELINK(chip))
SET_AUTO_DELINK(chip); SET_AUTO_DELINK(chip);
} }
}
#ifdef CONFIG_REALTEK_AUTOPM #ifdef CONFIG_REALTEK_AUTOPM
if (ss_en) if (ss_en)
realtek_cr_autosuspend_setup(us); realtek_cr_autosuspend_setup(us);
......
...@@ -2100,7 +2100,7 @@ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201, ...@@ -2100,7 +2100,7 @@ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201,
US_FL_IGNORE_RESIDUE ), US_FL_IGNORE_RESIDUE ),
/* Reported by Michael Büsch <m@bues.ch> */ /* Reported by Michael Büsch <m@bues.ch> */
UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0116, UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0117,
"JMicron", "JMicron",
"USB to ATA/ATAPI Bridge", "USB to ATA/ATAPI Bridge",
USB_SC_DEVICE, USB_PR_DEVICE, NULL, USB_SC_DEVICE, USB_PR_DEVICE, NULL,
......
...@@ -1446,7 +1446,7 @@ static enum pdo_err tcpm_caps_err(struct tcpm_port *port, const u32 *pdo, ...@@ -1446,7 +1446,7 @@ static enum pdo_err tcpm_caps_err(struct tcpm_port *port, const u32 *pdo,
else if ((pdo_min_voltage(pdo[i]) == else if ((pdo_min_voltage(pdo[i]) ==
pdo_min_voltage(pdo[i - 1])) && pdo_min_voltage(pdo[i - 1])) &&
(pdo_max_voltage(pdo[i]) == (pdo_max_voltage(pdo[i]) ==
pdo_min_voltage(pdo[i - 1]))) pdo_max_voltage(pdo[i - 1])))
return PDO_ERR_DUPE_PDO; return PDO_ERR_DUPE_PDO;
break; break;
/* /*
......
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