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

Commit def4e6f7 authored by Mathias Nyman's avatar Mathias Nyman Committed by Greg Kroah-Hartman
Browse files

xhci: refactor and cleanup endpoint initialization.



xhci_endpoint_init() and helper functions were a bit messy.
Adding the higher bandwidth SuperSpeedPlus Isoc support on
top of it would make it even harder to read.

No functional changes.

Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent faee822c
Loading
Loading
Loading
Loading
+67 −94
Original line number Original line Diff line number Diff line
@@ -1326,7 +1326,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
	default:
	default:
		BUG();
		BUG();
	}
	}
	return EP_INTERVAL(interval);
	return interval;
}
}


/* The "Mult" field in the endpoint context is only set for SuperSpeed isoc eps.
/* The "Mult" field in the endpoint context is only set for SuperSpeed isoc eps.
@@ -1343,33 +1343,36 @@ static u32 xhci_get_endpoint_mult(struct usb_device *udev,
	return ep->ss_ep_comp.bmAttributes;
	return ep->ss_ep_comp.bmAttributes;
}
}


static u32 xhci_get_endpoint_max_burst(struct usb_device *udev,
				       struct usb_host_endpoint *ep)
{
	/* Super speed and Plus have max burst in ep companion desc */
	if (udev->speed >= USB_SPEED_SUPER)
		return ep->ss_ep_comp.bMaxBurst;

	if (udev->speed == USB_SPEED_HIGH &&
	    (usb_endpoint_xfer_isoc(&ep->desc) ||
	     usb_endpoint_xfer_int(&ep->desc)))
		return (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11;

	return 0;
}

static u32 xhci_get_endpoint_type(struct usb_host_endpoint *ep)
static u32 xhci_get_endpoint_type(struct usb_host_endpoint *ep)
{
{
	int in;
	int in;
	u32 type;


	in = usb_endpoint_dir_in(&ep->desc);
	in = usb_endpoint_dir_in(&ep->desc);
	if (usb_endpoint_xfer_control(&ep->desc)) {

		type = EP_TYPE(CTRL_EP);
	if (usb_endpoint_xfer_control(&ep->desc))
	} else if (usb_endpoint_xfer_bulk(&ep->desc)) {
		return CTRL_EP;
		if (in)
	if (usb_endpoint_xfer_bulk(&ep->desc))
			type = EP_TYPE(BULK_IN_EP);
		return in ? BULK_IN_EP : BULK_OUT_EP;
		else
	if (usb_endpoint_xfer_isoc(&ep->desc))
			type = EP_TYPE(BULK_OUT_EP);
		return in ? ISOC_IN_EP : ISOC_OUT_EP;
	} else if (usb_endpoint_xfer_isoc(&ep->desc)) {
	if (usb_endpoint_xfer_int(&ep->desc))
		if (in)
		return in ? INT_IN_EP : INT_OUT_EP;
			type = EP_TYPE(ISOC_IN_EP);
	return 0;
		else
			type = EP_TYPE(ISOC_OUT_EP);
	} else if (usb_endpoint_xfer_int(&ep->desc)) {
		if (in)
			type = EP_TYPE(INT_IN_EP);
		else
			type = EP_TYPE(INT_OUT_EP);
	} else {
		type = 0;
	}
	return type;
}
}


/* Return the maximum endpoint service interval time (ESIT) payload.
/* Return the maximum endpoint service interval time (ESIT) payload.
@@ -1409,10 +1412,14 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
	struct xhci_ep_ctx *ep_ctx;
	struct xhci_ep_ctx *ep_ctx;
	struct xhci_ring *ep_ring;
	struct xhci_ring *ep_ring;
	unsigned int max_packet;
	unsigned int max_packet;
	unsigned int max_burst;
	enum xhci_ring_type ring_type;
	enum xhci_ring_type type;
	u32 max_esit_payload;
	u32 max_esit_payload;
	u32 endpoint_type;
	u32 endpoint_type;
	unsigned int max_burst;
	unsigned int interval;
	unsigned int mult;
	unsigned int avg_trb_len;
	unsigned int err_count = 0;


	ep_index = xhci_get_endpoint_index(&ep->desc);
	ep_index = xhci_get_endpoint_index(&ep->desc);
	ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
	ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
@@ -1420,12 +1427,11 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
	endpoint_type = xhci_get_endpoint_type(ep);
	endpoint_type = xhci_get_endpoint_type(ep);
	if (!endpoint_type)
	if (!endpoint_type)
		return -EINVAL;
		return -EINVAL;
	ep_ctx->ep_info2 = cpu_to_le32(endpoint_type);


	type = usb_endpoint_type(&ep->desc);
	ring_type = usb_endpoint_type(&ep->desc);
	/* Set up the endpoint ring */
	/* Set up the endpoint ring */
	virt_dev->eps[ep_index].new_ring =
	virt_dev->eps[ep_index].new_ring =
		xhci_ring_alloc(xhci, 2, 1, type, mem_flags);
		xhci_ring_alloc(xhci, 2, 1, ring_type, mem_flags);
	if (!virt_dev->eps[ep_index].new_ring) {
	if (!virt_dev->eps[ep_index].new_ring) {
		/* Attempt to use the ring cache */
		/* Attempt to use the ring cache */
		if (virt_dev->num_rings_cached == 0)
		if (virt_dev->num_rings_cached == 0)
@@ -1435,81 +1441,48 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
			virt_dev->ring_cache[virt_dev->num_rings_cached];
			virt_dev->ring_cache[virt_dev->num_rings_cached];
		virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL;
		virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL;
		xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring,
		xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring,
					1, type);
					1, ring_type);
	}
	}
	virt_dev->eps[ep_index].skip = false;
	virt_dev->eps[ep_index].skip = false;
	ep_ring = virt_dev->eps[ep_index].new_ring;
	ep_ring = virt_dev->eps[ep_index].new_ring;
	ep_ctx->deq = cpu_to_le64(ep_ring->first_seg->dma | ep_ring->cycle_state);


	ep_ctx->ep_info = cpu_to_le32(xhci_get_endpoint_interval(udev, ep)
	/*
				      | EP_MULT(xhci_get_endpoint_mult(udev, ep)));
	 * Get values to fill the endpoint context, mostly from ep descriptor.
	 * The average TRB buffer lengt for bulk endpoints is unclear as we
	 * have no clue on scatter gather list entry size. For Isoc and Int,
	 * set it to max available. See xHCI 1.1 spec 4.14.1.1 for details.
	 */
	max_esit_payload = xhci_get_max_esit_payload(udev, ep);
	interval = xhci_get_endpoint_interval(udev, ep);
	mult = xhci_get_endpoint_mult(udev, ep);
	max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc));
	max_burst = xhci_get_endpoint_max_burst(udev, ep);
	avg_trb_len = max_esit_payload;


	/* FIXME dig Mult and streams info out of ep companion desc */
	/* FIXME dig Mult and streams info out of ep companion desc */


	/* Allow 3 retries for everything but isoc;
	/* Allow 3 retries for everything but isoc, set CErr = 3 */
	 * CErr shall be set to 0 for Isoch endpoints.
	 */
	if (!usb_endpoint_xfer_isoc(&ep->desc))
	if (!usb_endpoint_xfer_isoc(&ep->desc))
		ep_ctx->ep_info2 |= cpu_to_le32(ERROR_COUNT(3));
		err_count = 3;
	else
		ep_ctx->ep_info2 |= cpu_to_le32(ERROR_COUNT(0));

	/* Set the max packet size and max burst */
	max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc));
	max_burst = 0;
	switch (udev->speed) {
	case USB_SPEED_SUPER_PLUS:
	case USB_SPEED_SUPER:
		/* dig out max burst from ep companion desc */
		max_burst = ep->ss_ep_comp.bMaxBurst;
		break;
	case USB_SPEED_HIGH:
	/* Some devices get this wrong */
	/* Some devices get this wrong */
		if (usb_endpoint_xfer_bulk(&ep->desc))
	if (usb_endpoint_xfer_bulk(&ep->desc) && udev->speed == USB_SPEED_HIGH)
		max_packet = 512;
		max_packet = 512;
		/* bits 11:12 specify the number of additional transaction
	/* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */
		 * opportunities per microframe (USB 2.0, section 9.6.6)
		 */
		if (usb_endpoint_xfer_isoc(&ep->desc) ||
				usb_endpoint_xfer_int(&ep->desc)) {
			max_burst = (usb_endpoint_maxp(&ep->desc)
				     & 0x1800) >> 11;
		}
		break;
	case USB_SPEED_FULL:
	case USB_SPEED_LOW:
		break;
	default:
		BUG();
	}
	ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet) |
			MAX_BURST(max_burst));
	max_esit_payload = xhci_get_max_esit_payload(udev, ep);
	ep_ctx->tx_info = cpu_to_le32(MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload));

	/*
	 * XXX no idea how to calculate the average TRB buffer length for bulk
	 * endpoints, as the driver gives us no clue how big each scatter gather
	 * list entry (or buffer) is going to be.
	 *
	 * For isochronous and interrupt endpoints, we set it to the max
	 * available, until we have new API in the USB core to allow drivers to
	 * declare how much bandwidth they actually need.
	 *
	 * Normally, it would be calculated by taking the total of the buffer
	 * lengths in the TD and then dividing by the number of TRBs in a TD,
	 * including link TRBs, No-op TRBs, and Event data TRBs.  Since we don't
	 * use Event Data TRBs, and we don't chain in a link TRB on short
	 * transfers, we're basically dividing by 1.
	 *
	 * xHCI 1.0 and 1.1 specification indicates that the Average TRB Length
	 * should be set to 8 for control endpoints.
	 */
	if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
	if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
		ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(8));
		avg_trb_len = 8;
	else

		ep_ctx->tx_info |=
	/* Fill the endpoint context */
			 cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(max_esit_payload));
	ep_ctx->ep_info = cpu_to_le32(EP_INTERVAL(interval) |
				      EP_MULT(mult));
	ep_ctx->ep_info2 = cpu_to_le32(EP_TYPE(endpoint_type) |
				       MAX_PACKET(max_packet) |
				       MAX_BURST(max_burst) |
				       ERROR_COUNT(err_count));
	ep_ctx->deq = cpu_to_le64(ep_ring->first_seg->dma |
				  ep_ring->cycle_state);

	ep_ctx->tx_info = cpu_to_le32(EP_MAX_ESIT_PAYLOAD_LO(max_esit_payload) |
				      EP_AVG_TRB_LENGTH(avg_trb_len));


	/* FIXME Debug endpoint context */
	/* FIXME Debug endpoint context */
	return 0;
	return 0;
+2 −2
Original line number Original line Diff line number Diff line
@@ -749,8 +749,8 @@ struct xhci_ep_ctx {
#define GET_MAX_PACKET(p)	((p) & 0x7ff)
#define GET_MAX_PACKET(p)	((p) & 0x7ff)


/* tx_info bitmasks */
/* tx_info bitmasks */
#define AVG_TRB_LENGTH_FOR_EP(p)	((p) & 0xffff)
#define EP_AVG_TRB_LENGTH(p)		((p) & 0xffff)
#define MAX_ESIT_PAYLOAD_FOR_EP(p)	(((p) & 0xffff) << 16)
#define EP_MAX_ESIT_PAYLOAD_LO(p)	(((p) & 0xffff) << 16)
#define CTX_TO_MAX_ESIT_PAYLOAD(p)	(((p) >> 16) & 0xffff)
#define CTX_TO_MAX_ESIT_PAYLOAD(p)	(((p) >> 16) & 0xffff)


/* deq bitmasks */
/* deq bitmasks */