Skip to content

Commit

Permalink
Merge tag 'usb-5.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  ...
  • Loading branch information
torvalds committed Aug 8, 2021
2 parents 85a9050 + 43ad944 commit 6a65554
Show file tree
Hide file tree
Showing 19 changed files with 173 additions and 75 deletions.
15 changes: 1 addition & 14 deletions drivers/thunderbolt/switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -1875,18 +1875,6 @@ static struct attribute *switch_attrs[] = {
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,
struct attribute *attr, int n)
{
Expand All @@ -1895,8 +1883,7 @@ static umode_t switch_attr_is_visible(struct kobject *kobj,

if (attr == &dev_attr_authorized.attr) {
if (sw->tb->security_level == TB_SECURITY_NOPCIE ||
sw->tb->security_level == TB_SECURITY_DPONLY ||
!has_port(sw, TB_TYPE_PCIE_UP))
sw->tb->security_level == TB_SECURITY_DPONLY)
return 0;
} else if (attr == &dev_attr_device.attr) {
if (!sw->device)
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/cdns3/cdns3-ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,7 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
request->actual = 0;
priv_dev->status_completion_no_call = true;
priv_dev->pending_status_request = request;
usb_gadget_set_state(&priv_dev->gadget, USB_STATE_CONFIGURED);
spin_unlock_irqrestore(&priv_dev->lock, flags);

/*
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/cdns3/cdnsp-gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -1882,7 +1882,7 @@ static int __cdnsp_gadget_init(struct cdns *cdns)
pdev->gadget.name = "cdnsp-gadget";
pdev->gadget.speed = USB_SPEED_UNKNOWN;
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->setup_buf = kzalloc(CDNSP_EP0_SETUP_SIZE, GFP_KERNEL);
Expand Down
4 changes: 2 additions & 2 deletions drivers/usb/cdns3/cdnsp-gadget.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,8 @@ struct cdnsp_intr_reg {
#define IMAN_IE BIT(1)
#define IMAN_IP BIT(0)
/* bits 2:31 need to be preserved */
#define IMAN_IE_SET(p) (((p) & IMAN_IE) | 0x2)
#define IMAN_IE_CLEAR(p) (((p) & IMAN_IE) & ~(0x2))
#define IMAN_IE_SET(p) ((p) | IMAN_IE)
#define IMAN_IE_CLEAR(p) ((p) & ~IMAN_IE)

/* IMOD - Interrupter Moderation Register - irq_control bitmasks. */
/*
Expand Down
18 changes: 8 additions & 10 deletions drivers/usb/cdns3/cdnsp-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 (need_zero_pkt && zero_len_trb) {
zero_len_trb = true;
} else {
field &= ~TRB_CHAIN;
field |= TRB_IOC;
more_trbs_coming = false;
need_zero_pkt = false;
preq->td.last_trb = ring->enqueue;
}
if (need_zero_pkt)
zero_len_trb = !zero_len_trb;

field &= ~TRB_CHAIN;
field |= TRB_IOC;
more_trbs_coming = false;
preq->td.last_trb = ring->enqueue;
}

/* Only set interrupt on short packet for OUT endpoints. */
Expand All @@ -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) |
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),
upper_32_bits(send_addr),
length_field,
Expand Down
9 changes: 1 addition & 8 deletions drivers/usb/class/usbtmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2324,17 +2324,10 @@ static void usbtmc_interrupt(struct urb *urb)
dev_err(dev, "overflow with length %d, actual length is %d\n",
data->iin_wMaxPacketSize, urb->actual_length);
fallthrough;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
case -EILSEQ:
case -ETIME:
case -EPIPE:
default:
/* urb terminated, clean up */
dev_dbg(dev, "urb terminated, status: %d\n", status);
return;
default:
dev_err(dev, "unknown status received: %d\n", status);
}
exit:
rv = usb_submit_urb(urb, GFP_ATOMIC);
Expand Down
6 changes: 5 additions & 1 deletion drivers/usb/common/usb-otg-fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,11 @@ static void otg_start_hnp_polling(struct otg_fsm *fsm)
if (!fsm->host_req_flag)
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,
msecs_to_jiffies(T_HOST_REQ_POLL));
}
Expand Down
29 changes: 27 additions & 2 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -1741,9 +1741,13 @@ static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep)
{
struct dwc3_request *req;
struct dwc3_request *tmp;
struct list_head local;
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);
switch (req->status) {
case DWC3_REQUEST_STATUS_DISCONNECTED:
Expand All @@ -1761,6 +1765,9 @@ static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep)
break;
}
}

if (!list_empty(&dep->cancelled_list))
goto restart;
}

static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
Expand Down Expand Up @@ -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
* successful resume, the DWC3 runtime PM resume routine will handle
Expand Down Expand Up @@ -2958,15 +2976,22 @@ static void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep,
{
struct dwc3_request *req;
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;

ret = dwc3_gadget_ep_cleanup_completed_request(dep, event,
req, status);
if (ret)
break;
}

if (!list_empty(&dep->started_list))
goto restart;
}

static bool dwc3_gadget_ep_should_continue(struct dwc3_ep *dep)
Expand Down
44 changes: 38 additions & 6 deletions drivers/usb/gadget/function/f_hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct f_hidg {
unsigned char bInterfaceSubClass;
unsigned char bInterfaceProtocol;
unsigned char protocol;
unsigned char idle;
unsigned short report_desc_length;
char *report_desc;
unsigned short report_length;
Expand Down Expand Up @@ -338,6 +339,11 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,

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)
try_again:
/* write queue */
Expand All @@ -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);

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) {
ERROR(hidg->func.config->cdev,
"copy_from_user error\n");
Expand Down Expand Up @@ -387,14 +399,17 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,

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);
if (status < 0) {
ERROR(hidg->func.config->cdev,
"usb_ep_queue error on int endpoint %zd\n", status);
if (status < 0)
goto release_write_pending;
} else {
else
status = count;
}

return status;
release_write_pending:
Expand Down Expand Up @@ -523,6 +538,14 @@ static int hidg_setup(struct usb_function *f,
goto respond;
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
| HID_REQ_SET_REPORT):
VDBG(cdev, "set_report | wLength=%d\n", ctrl->wLength);
Expand All @@ -546,6 +569,14 @@ static int hidg_setup(struct usb_function *f,
goto stall;
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
| USB_REQ_GET_DESCRIPTOR):
switch (value >> 8) {
Expand Down Expand Up @@ -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.bInterfaceProtocol = hidg->bInterfaceProtocol;
hidg->protocol = HID_REPORT_PROTOCOL;
hidg->idle = 1;
hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_ss_in_comp_desc.wBytesPerInterval =
cpu_to_le16(hidg->report_length);
Expand Down
14 changes: 10 additions & 4 deletions drivers/usb/gadget/udc/max3420_udc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1255,12 +1255,14 @@ static int max3420_probe(struct spi_device *spi)
err = devm_request_irq(&spi->dev, irq, max3420_irq_handler, 0,
"max3420", udc);
if (err < 0)
return err;
goto del_gadget;

udc->thread_task = kthread_create(max3420_thread, udc,
"max3420-thread");
if (IS_ERR(udc->thread_task))
return PTR_ERR(udc->thread_task);
if (IS_ERR(udc->thread_task)) {
err = PTR_ERR(udc->thread_task);
goto del_gadget;
}

irq = of_irq_get_byname(spi->dev.of_node, "vbus");
if (irq <= 0) { /* no vbus irq implies self-powered design */
Expand All @@ -1280,10 +1282,14 @@ static int max3420_probe(struct spi_device *spi)
err = devm_request_irq(&spi->dev, irq,
max3420_vbus_handler, 0, "vbus", udc);
if (err < 0)
return err;
goto del_gadget;
}

return 0;

del_gadget:
usb_del_gadget_udc(&udc->gadget);
return err;
}

static int max3420_remove(struct spi_device *spi)
Expand Down
9 changes: 5 additions & 4 deletions drivers/usb/host/ohci-at91.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,6 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
if (ohci_at91->wakeup)
enable_irq_wake(hcd->irq);

ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1);

ret = ohci_suspend(hcd, ohci_at91->wakeup);
if (ret) {
if (ohci_at91->wakeup)
Expand All @@ -632,7 +630,10 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
/* flush the writes */
(void) ohci_readl (ohci, &ohci->regs->control);
msleep(1);
ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1);
at91_stop_clock(ohci_at91);
} else {
ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1);
}

return ret;
Expand All @@ -644,15 +645,15 @@ ohci_hcd_at91_drv_resume(struct device *dev)
struct usb_hcd *hcd = dev_get_drvdata(dev);
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)
disable_irq_wake(hcd->irq);
else
at91_start_clock(ohci_at91);

ohci_resume(hcd, false);

ohci_at91_port_suspend(ohci_at91->sfr_regmap, 0);

return 0;
}

Expand Down
Loading

0 comments on commit 6a65554

Please sign in to comment.