Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3548a69e authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: host: xhci: Add helper function to return controller id"

parents 24d46399 0e596c5f
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -2292,6 +2292,16 @@ usb_hcd_get_xfer_ring_dma_addr(struct usb_device *udev,
	return hcd->driver->get_xfer_ring_dma_addr(hcd, udev, ep);
}

int usb_hcd_get_controller_id(struct usb_device *udev)
{
	struct usb_hcd	*hcd = bus_to_hcd(udev->bus);

	if (!HCD_RH_RUNNING(hcd))
		return -EINVAL;

	return hcd->driver->get_core_id(hcd);
}

#ifdef	CONFIG_PM

int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
+9 −0
Original line number Diff line number Diff line
@@ -876,6 +876,15 @@ dma_addr_t usb_get_xfer_ring_dma_addr(struct usb_device *dev,
}
EXPORT_SYMBOL(usb_get_xfer_ring_dma_addr);

int usb_get_controller_id(struct usb_device *dev)
{
	if (dev->state == USB_STATE_NOTATTACHED)
		return -EINVAL;

	return usb_hcd_get_controller_id(dev);
}
EXPORT_SYMBOL(usb_get_controller_id);

/*-------------------------------------------------------------------*/
/*
 * __usb_get_extra_descriptor() finds a descriptor of specific type in the
+79 −27
Original line number Diff line number Diff line
@@ -1831,27 +1831,17 @@ void xhci_free_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
	erst->entries = NULL;
}

int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num)
void xhci_handle_sec_intr_events(struct xhci_hcd *xhci, int intr_num)
{
	int size;
	u32 iman_reg;
	union xhci_trb *erdp_trb, *current_trb;
	struct xhci_segment	*seg;
	u64 erdp_reg;
	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
	struct device	*dev = xhci_to_hcd(xhci)->self.sysdev;
	u32 iman_reg;
	dma_addr_t deq;
	unsigned long segment_offset;

	if (intr_num > xhci->max_interrupters) {
		xhci_err(xhci, "invalid secondary interrupter num %d\n",
			intr_num);
		return -EINVAL;
	}
	/* disable irq, ack pending interrupt and ack all pending events */

	size =
	sizeof(struct xhci_erst_entry)*(xhci->sec_erst[intr_num].num_entries);
	if (xhci->sec_erst[intr_num].entries) {
		/*
		 * disable irq, ack pending interrupt and clear EHB for xHC to
		 * generate interrupt again when new event ring is setup
		 */
	iman_reg =
		readl_relaxed(&xhci->sec_ir_set[intr_num]->irq_pending);
	iman_reg &= ~IMAN_IE;
@@ -1862,14 +1852,76 @@ int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num)
	if (iman_reg & IMAN_IP)
		writel_relaxed(iman_reg,
			&xhci->sec_ir_set[intr_num]->irq_pending);
		/* make sure IP gets cleared before clearing EHB */
		mb();

		erdp_reg = xhci_read_64(xhci,
				&xhci->sec_ir_set[intr_num]->erst_dequeue);
		xhci_write_64(xhci, erdp_reg | ERST_EHB,
	/* last acked event trb is in erdp reg  */
	erdp_reg =
		xhci_read_64(xhci, &xhci->sec_ir_set[intr_num]->erst_dequeue);
	deq = (dma_addr_t)(erdp_reg & ~ERST_PTR_MASK);
	if (!deq) {
		pr_debug("%s: event ring handling not required\n", __func__);
		return;
	}

	seg = xhci->sec_event_ring[intr_num]->first_seg;
	segment_offset = deq - seg->dma;

	/* find out virtual address of the last acked event trb */
	erdp_trb = current_trb = &seg->trbs[0] +
				(segment_offset/sizeof(*current_trb));

	/* read cycle state of the last acked trb to find out CCS */
	xhci->sec_event_ring[intr_num]->cycle_state =
				(current_trb->event_cmd.flags & TRB_CYCLE);

	while (1) {
		/* last trb of the event ring: toggle cycle state */
		if (current_trb == &seg->trbs[TRBS_PER_SEGMENT - 1]) {
			xhci->sec_event_ring[intr_num]->cycle_state ^= 1;
			current_trb = &seg->trbs[0];
		} else {
			current_trb++;
		}

		/* cycle state transition */
		if ((le32_to_cpu(current_trb->event_cmd.flags) & TRB_CYCLE) !=
		    xhci->sec_event_ring[intr_num]->cycle_state)
			break;
	}

	if (erdp_trb != current_trb) {
		deq =
		xhci_trb_virt_to_dma(xhci->sec_event_ring[intr_num]->deq_seg,
					current_trb);
		if (deq == 0)
			xhci_warn(xhci,
				"WARN invalid SW event ring dequeue ptr.\n");
		/* Update HC event ring dequeue pointer */
		erdp_reg &= ERST_PTR_MASK;
		erdp_reg |= ((u64) deq & (u64) ~ERST_PTR_MASK);
	}

	/* Clear the event handler busy flag (RW1C); event ring is empty. */
	erdp_reg |= ERST_EHB;
	xhci_write_64(xhci, erdp_reg,
			&xhci->sec_ir_set[intr_num]->erst_dequeue);
}

int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num)
{
	int size;
	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
	struct device	*dev = xhci_to_hcd(xhci)->self.sysdev;

	if (intr_num >= xhci->max_interrupters) {
		xhci_err(xhci, "invalid secondary interrupter num %d\n",
			intr_num);
		return -EINVAL;
	}

	size =
	sizeof(struct xhci_erst_entry)*(xhci->sec_erst[intr_num].num_entries);
	if (xhci->sec_erst[intr_num].entries) {
		xhci_handle_sec_intr_events(xhci, intr_num);
		dma_free_coherent(dev, size, xhci->sec_erst[intr_num].entries,
				xhci->sec_erst[intr_num].erst_dma_addr);
		xhci->sec_erst[intr_num].entries = NULL;
@@ -1891,7 +1943,7 @@ void xhci_event_ring_cleanup(struct xhci_hcd *xhci)
	unsigned int i;

	/* sec event ring clean up */
	for (i = 1; i <= xhci->max_interrupters; i++)
	for (i = 1; i < xhci->max_interrupters; i++)
		xhci_sec_event_ring_cleanup(xhci_to_hcd(xhci), i);

	kfree(xhci->sec_ir_set);
@@ -2483,7 +2535,7 @@ int xhci_sec_event_ring_setup(struct usb_hcd *hcd, unsigned int intr_num)

	if ((xhci->xhc_state & XHCI_STATE_HALTED) || !xhci->sec_ir_set
		|| !xhci->sec_event_ring || !xhci->sec_erst ||
		intr_num > xhci->max_interrupters) {
		intr_num >= xhci->max_interrupters) {
		xhci_err(xhci,
		"%s:state %x ir_set %pK evt_ring %pK erst %pK intr# %d\n",
		__func__, xhci->xhc_state, xhci->sec_ir_set,
+10 −2
Original line number Diff line number Diff line
@@ -5112,8 +5112,8 @@ dma_addr_t xhci_get_sec_event_ring_dma_addr(struct usb_hcd *hcd,
{
	struct xhci_hcd *xhci = hcd_to_xhci(hcd);

	if (intr_num > xhci->max_interrupters) {
		xhci_err(xhci, "intr num %d > max intrs %d\n", intr_num,
	if (intr_num >= xhci->max_interrupters) {
		xhci_err(xhci, "intr num %d >= max intrs %d\n", intr_num,
			xhci->max_interrupters);
		return 0;
	}
@@ -5162,6 +5162,13 @@ dma_addr_t xhci_get_xfer_ring_dma_addr(struct usb_hcd *hcd,
	return 0;
}

int xhci_get_core_id(struct usb_hcd *hcd)
{
	struct xhci_hcd *xhci = hcd_to_xhci(hcd);

	return xhci->core_id;
}

static const struct hc_driver xhci_hc_driver = {
	.description =		"xhci-hcd",
	.product_desc =		"xHCI Host Controller",
@@ -5227,6 +5234,7 @@ static const struct hc_driver xhci_hc_driver = {
	.get_sec_event_ring_dma_addr =	xhci_get_sec_event_ring_dma_addr,
	.get_xfer_ring_dma_addr =	xhci_get_xfer_ring_dma_addr,
	.get_dcba_dma_addr =		xhci_get_dcba_dma_addr,
	.get_core_id =			xhci_get_core_id,
};

void xhci_init_driver(struct hc_driver *drv,
+1 −0
Original line number Diff line number Diff line
@@ -2121,6 +2121,7 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);
struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd);

void xhci_hc_died(struct xhci_hcd *xhci);
int xhci_get_core_id(struct usb_hcd *hcd);

#ifdef CONFIG_PM
int xhci_bus_suspend(struct usb_hcd *hcd);
Loading