Commit ebf613ae authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull USB fixes from Greg KH:
 "Here are some small USB fixes that resolve a number of tiny issues.
  They include:

   - new USB serial driver ids

   - xhci driver fixes for a bunch of issues

   - musb error path fixes.

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

* tag 'usb-5.15-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: musb: dsps: Fix the probe error path
  xhci: Enable trust tx length quirk for Fresco FL11 USB controller
  xhci: Fix command ring pointer corruption while aborting a command
  USB: xhci: dbc: fix tty registration race
  xhci: add quirk for host controllers that don't update endpoint DCS
  xhci: guard accesses to ep_state in xhci_endpoint_reset()
  USB: serial: qcserial: add EM9191 QDL support
  USB: serial: option: add Quectel EC200S-CN module support
  USB: serial: option: add prod. id for Quectel EG91
  USB: serial: option: add Telit LE910Cx composition 0x1204
parents 12dbbfad cd932c2a
Loading
Loading
Loading
Loading
+13 −15
Original line number Diff line number Diff line
@@ -408,40 +408,38 @@ static int xhci_dbc_tty_register_device(struct xhci_dbc *dbc)
		return -EBUSY;

	xhci_dbc_tty_init_port(dbc, port);
	tty_dev = tty_port_register_device(&port->port,
					   dbc_tty_driver, 0, NULL);
	if (IS_ERR(tty_dev)) {
		ret = PTR_ERR(tty_dev);
		goto register_fail;
	}

	ret = kfifo_alloc(&port->write_fifo, DBC_WRITE_BUF_SIZE, GFP_KERNEL);
	if (ret)
		goto buf_alloc_fail;
		goto err_exit_port;

	ret = xhci_dbc_alloc_requests(dbc, BULK_IN, &port->read_pool,
				      dbc_read_complete);
	if (ret)
		goto request_fail;
		goto err_free_fifo;

	ret = xhci_dbc_alloc_requests(dbc, BULK_OUT, &port->write_pool,
				      dbc_write_complete);
	if (ret)
		goto request_fail;
		goto err_free_requests;

	tty_dev = tty_port_register_device(&port->port,
					   dbc_tty_driver, 0, NULL);
	if (IS_ERR(tty_dev)) {
		ret = PTR_ERR(tty_dev);
		goto err_free_requests;
	}

	port->registered = true;

	return 0;

request_fail:
err_free_requests:
	xhci_dbc_free_requests(&port->read_pool);
	xhci_dbc_free_requests(&port->write_pool);
err_free_fifo:
	kfifo_free(&port->write_fifo);

buf_alloc_fail:
	tty_unregister_device(dbc_tty_driver, 0);

register_fail:
err_exit_port:
	xhci_dbc_tty_exit_port(port);

	dev_err(dbc->dev, "can't register tty port, err %d\n", ret);
+5 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#define PCI_VENDOR_ID_FRESCO_LOGIC	0x1b73
#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK	0x1000
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1009	0x1009
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1100	0x1100
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400	0x1400

#define PCI_VENDOR_ID_ETRON		0x1b6f
@@ -113,6 +114,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
	/* Look for vendor-specific quirks */
	if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
			(pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK ||
			 pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1100 ||
			 pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) {
		if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
				pdev->revision == 0x0) {
@@ -279,8 +281,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
			pdev->device == 0x3432)
		xhci->quirks |= XHCI_BROKEN_STREAMS;

	if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483)
	if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) {
		xhci->quirks |= XHCI_LPM_SUPPORT;
		xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
	}

	if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
		pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI)
+34 −5
Original line number Diff line number Diff line
@@ -366,16 +366,22 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
/* Must be called with xhci->lock held, releases and aquires lock back */
static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
{
	u64 temp_64;
	u32 temp_32;
	int ret;

	xhci_dbg(xhci, "Abort command ring\n");

	reinit_completion(&xhci->cmd_ring_stop_completion);

	temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
	xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
			&xhci->op_regs->cmd_ring);
	/*
	 * The control bits like command stop, abort are located in lower
	 * dword of the command ring control register. Limit the write
	 * to the lower dword to avoid corrupting the command ring pointer
	 * in case if the command ring is stopped by the time upper dword
	 * is written.
	 */
	temp_32 = readl(&xhci->op_regs->cmd_ring);
	writel(temp_32 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring);

	/* Section 4.6.1.2 of xHCI 1.0 spec says software should also time the
	 * completion of the Command Abort operation. If CRR is not negated in 5
@@ -559,8 +565,11 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci,
	struct xhci_ring *ep_ring;
	struct xhci_command *cmd;
	struct xhci_segment *new_seg;
	struct xhci_segment *halted_seg = NULL;
	union xhci_trb *new_deq;
	int new_cycle;
	union xhci_trb *halted_trb;
	int index = 0;
	dma_addr_t addr;
	u64 hw_dequeue;
	bool cycle_found = false;
@@ -598,7 +607,27 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci,
	hw_dequeue = xhci_get_hw_deq(xhci, dev, ep_index, stream_id);
	new_seg = ep_ring->deq_seg;
	new_deq = ep_ring->dequeue;

	/*
	 * Quirk: xHC write-back of the DCS field in the hardware dequeue
	 * pointer is wrong - use the cycle state of the TRB pointed to by
	 * the dequeue pointer.
	 */
	if (xhci->quirks & XHCI_EP_CTX_BROKEN_DCS &&
	    !(ep->ep_state & EP_HAS_STREAMS))
		halted_seg = trb_in_td(xhci, td->start_seg,
				       td->first_trb, td->last_trb,
				       hw_dequeue & ~0xf, false);
	if (halted_seg) {
		index = ((dma_addr_t)(hw_dequeue & ~0xf) - halted_seg->dma) /
			 sizeof(*halted_trb);
		halted_trb = &halted_seg->trbs[index];
		new_cycle = halted_trb->generic.field[3] & 0x1;
		xhci_dbg(xhci, "Endpoint DCS = %d TRB index = %d cycle = %d\n",
			 (u8)(hw_dequeue & 0x1), index, new_cycle);
	} else {
		new_cycle = hw_dequeue & 0x1;
	}

	/*
	 * We want to find the pointer, segment and cycle state of the new trb
+5 −0
Original line number Diff line number Diff line
@@ -3214,10 +3214,13 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
		return;

	/* Bail out if toggle is already being cleared by a endpoint reset */
	spin_lock_irqsave(&xhci->lock, flags);
	if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) {
		ep->ep_state &= ~EP_HARD_CLEAR_TOGGLE;
		spin_unlock_irqrestore(&xhci->lock, flags);
		return;
	}
	spin_unlock_irqrestore(&xhci->lock, flags);
	/* Only interrupt and bulk ep's use data toggle, USB2 spec 5.5.4-> */
	if (usb_endpoint_xfer_control(&host_ep->desc) ||
	    usb_endpoint_xfer_isoc(&host_ep->desc))
@@ -3303,8 +3306,10 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
	xhci_free_command(xhci, cfg_cmd);
cleanup:
	xhci_free_command(xhci, stop_cmd);
	spin_lock_irqsave(&xhci->lock, flags);
	if (ep->ep_state & EP_SOFT_CLEAR_TOGGLE)
		ep->ep_state &= ~EP_SOFT_CLEAR_TOGGLE;
	spin_unlock_irqrestore(&xhci->lock, flags);
}

static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
+1 −0
Original line number Diff line number Diff line
@@ -1899,6 +1899,7 @@ struct xhci_hcd {
#define XHCI_SG_TRB_CACHE_SIZE_QUIRK	BIT_ULL(39)
#define XHCI_NO_SOFT_RETRY	BIT_ULL(40)
#define XHCI_BROKEN_D3COLD	BIT_ULL(41)
#define XHCI_EP_CTX_BROKEN_DCS	BIT_ULL(42)

	unsigned int		num_active_eps;
	unsigned int		limit_active_eps;
Loading