Commit c24eb8d6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-5.19-rc4' 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 and new device ids for 5.19-rc4
  for a few small reported issues. They include:

   - new usb-serial driver ids

   - MAINTAINERS file update to properly catch the USB dts files

   - dt-bindings fixes for reported build warnings

   - xhci driver fixes for reported problems

   - typec Kconfig dependancy fix

   - raw_gadget fuzzing fixes found by syzbot

   - chipidea driver bugfix

   - usb gadget uvc bugfix

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

* tag 'usb-5.19-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: chipidea: udc: check request status before setting device address
  USB: gadget: Fix double-free bug in raw_gadget driver
  xhci-pci: Allow host runtime PM as default for Intel Meteor Lake xHCI
  xhci-pci: Allow host runtime PM as default for Intel Raptor Lake xHCI
  xhci: turn off port power in shutdown
  xhci: Keep interrupt disabled in initialization until host is running.
  USB: serial: option: add Quectel RM500K module support
  USB: serial: option: add Quectel EM05-G modem
  USB: serial: pl2303: add support for more HXN (G) types
  usb: typec: wcove: Drop wrong dependency to INTEL_SOC_PMIC
  usb: gadget: uvc: fix list double add in uvcg_video_pump
  dt-bindings: usb: ehci: Increase the number of PHYs
  dt-bindings: usb: ohci: Increase the number of PHYs
  usb: gadget: Fix non-unique driver names in raw-gadget driver
  MAINTAINERS: add include/dt-bindings/usb to USB SUBSYSTEM
  USB: serial: option: add Telit LE910Cx 0x1250 composition
parents cb84318b b24346a2
......@@ -136,7 +136,8 @@ properties:
Phandle of a companion.
phys:
maxItems: 1
minItems: 1
maxItems: 3
phy-names:
const: usb
......
......@@ -103,7 +103,8 @@ properties:
Overrides the detected port count
phys:
maxItems: 1
minItems: 1
maxItems: 3
phy-names:
const: usb
......
......@@ -20749,6 +20749,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
F: Documentation/devicetree/bindings/usb/
F: Documentation/usb/
F: drivers/usb/
F: include/dt-bindings/usb/
F: include/linux/usb.h
F: include/linux/usb/
......
......@@ -1048,6 +1048,9 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
struct ci_hdrc *ci = req->context;
unsigned long flags;
if (req->status < 0)
return;
if (ci->setaddr) {
hw_usb_set_address(ci, ci->address);
ci->setaddr = false;
......
......@@ -424,6 +424,9 @@ static void uvcg_video_pump(struct work_struct *work)
uvcg_queue_cancel(queue, 0);
break;
}
/* Endpoint now owns the request */
req = NULL;
video->req_int_count++;
}
......
......@@ -11,6 +11,7 @@
#include <linux/ctype.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/idr.h>
#include <linux/kref.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
......@@ -36,6 +37,9 @@ MODULE_LICENSE("GPL");
/*----------------------------------------------------------------------*/
static DEFINE_IDA(driver_id_numbers);
#define DRIVER_DRIVER_NAME_LENGTH_MAX 32
#define RAW_EVENT_QUEUE_SIZE 16
struct raw_event_queue {
......@@ -161,6 +165,9 @@ struct raw_dev {
/* Reference to misc device: */
struct device *dev;
/* Make driver names unique */
int driver_id_number;
/* Protected by lock: */
enum dev_state state;
bool gadget_registered;
......@@ -189,6 +196,7 @@ static struct raw_dev *dev_new(void)
spin_lock_init(&dev->lock);
init_completion(&dev->ep0_done);
raw_event_queue_init(&dev->queue);
dev->driver_id_number = -1;
return dev;
}
......@@ -199,6 +207,9 @@ static void dev_free(struct kref *kref)
kfree(dev->udc_name);
kfree(dev->driver.udc_name);
kfree(dev->driver.driver.name);
if (dev->driver_id_number >= 0)
ida_free(&driver_id_numbers, dev->driver_id_number);
if (dev->req) {
if (dev->ep0_urb_queued)
usb_ep_dequeue(dev->gadget->ep0, dev->req);
......@@ -419,9 +430,11 @@ static int raw_release(struct inode *inode, struct file *fd)
static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
{
int ret = 0;
int driver_id_number;
struct usb_raw_init arg;
char *udc_driver_name;
char *udc_device_name;
char *driver_driver_name;
unsigned long flags;
if (copy_from_user(&arg, (void __user *)value, sizeof(arg)))
......@@ -440,36 +453,43 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
return -EINVAL;
}
driver_id_number = ida_alloc(&driver_id_numbers, GFP_KERNEL);
if (driver_id_number < 0)
return driver_id_number;
driver_driver_name = kmalloc(DRIVER_DRIVER_NAME_LENGTH_MAX, GFP_KERNEL);
if (!driver_driver_name) {
ret = -ENOMEM;
goto out_free_driver_id_number;
}
snprintf(driver_driver_name, DRIVER_DRIVER_NAME_LENGTH_MAX,
DRIVER_NAME ".%d", driver_id_number);
udc_driver_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL);
if (!udc_driver_name)
return -ENOMEM;
if (!udc_driver_name) {
ret = -ENOMEM;
goto out_free_driver_driver_name;
}
ret = strscpy(udc_driver_name, &arg.driver_name[0],
UDC_NAME_LENGTH_MAX);
if (ret < 0) {
kfree(udc_driver_name);
return ret;
}
if (ret < 0)
goto out_free_udc_driver_name;
ret = 0;
udc_device_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL);
if (!udc_device_name) {
kfree(udc_driver_name);
return -ENOMEM;
ret = -ENOMEM;
goto out_free_udc_driver_name;
}
ret = strscpy(udc_device_name, &arg.device_name[0],
UDC_NAME_LENGTH_MAX);
if (ret < 0) {
kfree(udc_driver_name);
kfree(udc_device_name);
return ret;
}
if (ret < 0)
goto out_free_udc_device_name;
ret = 0;
spin_lock_irqsave(&dev->lock, flags);
if (dev->state != STATE_DEV_OPENED) {
dev_dbg(dev->dev, "fail, device is not opened\n");
kfree(udc_driver_name);
kfree(udc_device_name);
ret = -EINVAL;
goto out_unlock;
}
......@@ -484,14 +504,25 @@ static int raw_ioctl_init(struct raw_dev *dev, unsigned long value)
dev->driver.suspend = gadget_suspend;
dev->driver.resume = gadget_resume;
dev->driver.reset = gadget_reset;
dev->driver.driver.name = DRIVER_NAME;
dev->driver.driver.name = driver_driver_name;
dev->driver.udc_name = udc_device_name;
dev->driver.match_existing_only = 1;
dev->driver_id_number = driver_id_number;
dev->state = STATE_DEV_INITIALIZED;
spin_unlock_irqrestore(&dev->lock, flags);
return ret;
out_unlock:
spin_unlock_irqrestore(&dev->lock, flags);
out_free_udc_device_name:
kfree(udc_device_name);
out_free_udc_driver_name:
kfree(udc_driver_name);
out_free_driver_driver_name:
kfree(driver_driver_name);
out_free_driver_id_number:
ida_free(&driver_id_numbers, driver_id_number);
return ret;
}
......
......@@ -652,7 +652,7 @@ struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd)
* It will release and re-aquire the lock while calling ACPI
* method.
*/
static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
u16 index, bool on, unsigned long *flags)
__must_hold(&xhci->lock)
{
......
......@@ -61,6 +61,8 @@
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI 0x464e
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed
#define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI 0xa71e
#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_XHCI 0x7ec0
#define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639
#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9
......@@ -269,7 +271,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI))
pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_METEOR_LAKE_XHCI))
xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
......
......@@ -611,15 +611,37 @@ static int xhci_init(struct usb_hcd *hcd)
static int xhci_run_finished(struct xhci_hcd *xhci)
{
unsigned long flags;
u32 temp;
/*
* Enable interrupts before starting the host (xhci 4.2 and 5.5.2).
* Protect the short window before host is running with a lock
*/
spin_lock_irqsave(&xhci->lock, flags);
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Enable interrupts");
temp = readl(&xhci->op_regs->command);
temp |= (CMD_EIE);
writel(temp, &xhci->op_regs->command);
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Enable primary interrupter");
temp = readl(&xhci->ir_set->irq_pending);
writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending);
if (xhci_start(xhci)) {
xhci_halt(xhci);
spin_unlock_irqrestore(&xhci->lock, flags);
return -ENODEV;
}
xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
if (xhci->quirks & XHCI_NEC_HOST)
xhci_ring_cmd_db(xhci);
spin_unlock_irqrestore(&xhci->lock, flags);
return 0;
}
......@@ -668,19 +690,6 @@ int xhci_run(struct usb_hcd *hcd)
temp |= (xhci->imod_interval / 250) & ER_IRQ_INTERVAL_MASK;
writel(temp, &xhci->ir_set->irq_control);
/* Set the HCD state before we enable the irqs */
temp = readl(&xhci->op_regs->command);
temp |= (CMD_EIE);
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"// Enable interrupts, cmd = 0x%x.", temp);
writel(temp, &xhci->op_regs->command);
temp = readl(&xhci->ir_set->irq_pending);
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"// Enabling event ring interrupter %p by writing 0x%x to irq_pending",
xhci->ir_set, (unsigned int) ER_IRQ_ENABLE(temp));
writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending);
if (xhci->quirks & XHCI_NEC_HOST) {
struct xhci_command *command;
......@@ -782,6 +791,8 @@ static void xhci_stop(struct usb_hcd *hcd)
void xhci_shutdown(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
unsigned long flags;
int i;
if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev));
......@@ -797,12 +808,21 @@ void xhci_shutdown(struct usb_hcd *hcd)
del_timer_sync(&xhci->shared_hcd->rh_timer);
}
spin_lock_irq(&xhci->lock);
spin_lock_irqsave(&xhci->lock, flags);
xhci_halt(xhci);
/* Power off USB2 ports*/
for (i = 0; i < xhci->usb2_rhub.num_ports; i++)
xhci_set_port_power(xhci, xhci->main_hcd, i, false, &flags);
/* Power off USB3 ports*/
for (i = 0; i < xhci->usb3_rhub.num_ports; i++)
xhci_set_port_power(xhci, xhci->shared_hcd, i, false, &flags);
/* Workaround for spurious wakeups at shutdown with HSW */
if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
spin_unlock_irq(&xhci->lock);
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_cleanup_msix(xhci);
......
......@@ -2196,6 +2196,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);
struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd);
void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, u16 index,
bool on, unsigned long *flags);
void xhci_hc_died(struct xhci_hcd *xhci);
......
......@@ -252,10 +252,12 @@ static void option_instat_callback(struct urb *urb);
#define QUECTEL_PRODUCT_EG95 0x0195
#define QUECTEL_PRODUCT_BG96 0x0296
#define QUECTEL_PRODUCT_EP06 0x0306
#define QUECTEL_PRODUCT_EM05G 0x030a
#define QUECTEL_PRODUCT_EM12 0x0512
#define QUECTEL_PRODUCT_RM500Q 0x0800
#define QUECTEL_PRODUCT_EC200S_CN 0x6002
#define QUECTEL_PRODUCT_EC200T 0x6026
#define QUECTEL_PRODUCT_RM500K 0x7001
#define CMOTECH_VENDOR_ID 0x16d8
#define CMOTECH_PRODUCT_6001 0x6001
......@@ -1134,6 +1136,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
.driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
{ USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G, 0xff),
.driver_info = RSVD(6) | ZLP },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0xff, 0xff),
.driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0, 0) },
......@@ -1147,6 +1151,7 @@ static const struct usb_device_id option_ids[] = {
.driver_info = ZLP },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
......@@ -1279,6 +1284,7 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1231, 0xff), /* Telit LE910Cx (RNDIS) */
.driver_info = NCTRL(2) | RSVD(3) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x1250, 0xff, 0x00, 0x00) }, /* Telit LE910Cx (rmnet) */
{ USB_DEVICE(TELIT_VENDOR_ID, 0x1260),
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
{ USB_DEVICE(TELIT_VENDOR_ID, 0x1261),
......
......@@ -436,22 +436,27 @@ static int pl2303_detect_type(struct usb_serial *serial)
break;
case 0x200:
switch (bcdDevice) {
case 0x100:
case 0x100: /* GC */
case 0x105:
return TYPE_HXN;
case 0x300: /* GT / TA */
if (pl2303_supports_hx_status(serial))
return TYPE_TA;
fallthrough;
case 0x305:
case 0x400: /* GL */
case 0x405:
return TYPE_HXN;
case 0x500: /* GE / TB */
if (pl2303_supports_hx_status(serial))
return TYPE_TB;
fallthrough;
case 0x505:
case 0x600: /* GS */
case 0x605:
/*
* 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;
case 0x500:
return TYPE_TB;
case 0x700: /* GR */
case 0x705:
return TYPE_HXN;
}
break;
}
......
......@@ -56,7 +56,6 @@ config TYPEC_WCOVE
tristate "Intel WhiskeyCove PMIC USB Type-C PHY driver"
depends on ACPI
depends on MFD_INTEL_PMC_BXT
depends on INTEL_SOC_PMIC
depends on BXT_WC_PMIC_OPREGION
help
This driver adds support for USB Type-C on Intel Broxton platforms
......
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